diff --git a/projects/NXP/README.md b/projects/NXP/README.md new file mode 100644 index 0000000000..e5f726113a --- /dev/null +++ b/projects/NXP/README.md @@ -0,0 +1,15 @@ +# NXP + +This project is for NXP SoC devices + +## Devices + +**iMX6** +* [Cubox-i](devices/iMX6) +* [Udoo](devices/iMX6) +* [Wandboard](devices/iMX6) + +**iMX8** +* [Coral Edge TPU Development Board](devices/iMX8) +* [i.MX8MQ EVK](devices/iMX8) +* [TechNexion PICO-PI-8M](devices/iMX8) diff --git a/projects/NXP/devices/iMX8/linux/linux.aarch64.conf b/projects/NXP/devices/iMX8/linux/linux.aarch64.conf index 6a6b42fd76..c1a79d71c0 100644 --- a/projects/NXP/devices/iMX8/linux/linux.aarch64.conf +++ b/projects/NXP/devices/iMX8/linux/linux.aarch64.conf @@ -1,23 +1,27 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 6.6.66 Kernel Configuration +# Linux/arm64 6.15.4 Kernel Configuration # -CONFIG_CC_VERSION_TEXT="aarch64-libreelec-linux-gnu-gcc-13.2.0 (GCC) 13.2.0" +CONFIG_CC_VERSION_TEXT="aarch64-libreelec-linux-gnu-gcc-15.1.0 (GCC) 15.1.0" CONFIG_CC_IS_GCC=y -CONFIG_GCC_VERSION=130200 +CONFIG_GCC_VERSION=150100 CONFIG_CLANG_VERSION=0 CONFIG_AS_IS_GNU=y -CONFIG_AS_VERSION=24100 +CONFIG_AS_VERSION=24400 CONFIG_LD_IS_BFD=y -CONFIG_LD_VERSION=24100 +CONFIG_LD_VERSION=24400 CONFIG_LLD_VERSION=0 +CONFIG_RUSTC_VERSION=0 +CONFIG_RUSTC_LLVM_VERSION=0 CONFIG_CC_CAN_LINK=y -CONFIG_CC_CAN_LINK_STATIC=y CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y -CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y +CONFIG_TOOLS_SUPPORT_RELR=y CONFIG_CC_HAS_ASM_INLINE=y CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y +CONFIG_CC_HAS_COUNTED_BY=y +CONFIG_CC_HAS_MULTIDIMENSIONAL_NONSTRING=y +CONFIG_LD_CAN_USE_KEEP_IN_OVERLAY=y CONFIG_PAHOLE_VERSION=0 CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_TABLE_SORT=y @@ -63,6 +67,7 @@ CONFIG_IRQ_MSI_IOMMU=y CONFIG_IRQ_FORCED_THREADING=y CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_IRQ_DEBUGFS is not set +CONFIG_GENERIC_IRQ_KEXEC_CLEAR_VM_FORWARD=y # end of IRQ subsystem CONFIG_GENERIC_TIME_VSYSCALL=y @@ -103,6 +108,7 @@ CONFIG_PREEMPT_VOLUNTARY_BUILD=y # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set +# CONFIG_PREEMPT_RT is not set # CONFIG_PREEMPT_DYNAMIC is not set # @@ -125,6 +131,7 @@ CONFIG_TREE_RCU=y # CONFIG_RCU_EXPERT is not set CONFIG_TREE_SRCU=y CONFIG_TASKS_RCU_GENERIC=y +CONFIG_NEED_TASKS_RCU=y CONFIG_TASKS_TRACE_RCU=y CONFIG_RCU_STALL_COMMON=y CONFIG_RCU_NEED_SEGCBLIST=y @@ -149,24 +156,29 @@ CONFIG_CC_HAS_INT128=y CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" CONFIG_GCC10_NO_ARRAY_BOUNDS=y CONFIG_CC_NO_ARRAY_BOUNDS=y +CONFIG_GCC_NO_STRINGOP_OVERFLOW=y +CONFIG_CC_NO_STRINGOP_OVERFLOW=y CONFIG_ARCH_SUPPORTS_INT128=y +CONFIG_SLAB_OBJ_EXT=y CONFIG_CGROUPS=y CONFIG_PAGE_COUNTER=y # CONFIG_CGROUP_FAVOR_DYNMODS is not set CONFIG_MEMCG=y -CONFIG_MEMCG_KMEM=y +# CONFIG_MEMCG_V1 is not set CONFIG_BLK_CGROUP=y CONFIG_CGROUP_WRITEBACK=y CONFIG_CGROUP_SCHED=y +CONFIG_GROUP_SCHED_WEIGHT=y CONFIG_FAIR_GROUP_SCHED=y CONFIG_CFS_BANDWIDTH=y # CONFIG_RT_GROUP_SCHED is not set CONFIG_SCHED_MM_CID=y CONFIG_CGROUP_PIDS=y # CONFIG_CGROUP_RDMA is not set +# CONFIG_CGROUP_DMEM is not set CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y -CONFIG_PROC_PID_CPUSET=y +# CONFIG_CPUSETS_V1 is not set CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_PERF=y @@ -205,17 +217,17 @@ CONFIG_LD_ORPHAN_WARN_LEVEL="warn" CONFIG_SYSCTL=y CONFIG_HAVE_UID16=y CONFIG_SYSCTL_EXCEPTION_TRACE=y +# CONFIG_SYSFS_SYSCALL is not set CONFIG_EXPERT=y -# CONFIG_UID16 is not set +CONFIG_UID16=y CONFIG_MULTIUSER=y # CONFIG_SGETMASK_SYSCALL is not set -# CONFIG_SYSFS_SYSCALL is not set CONFIG_FHANDLE=y CONFIG_POSIX_TIMERS=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y +# CONFIG_BASE_SMALL is not set CONFIG_FUTEX=y CONFIG_FUTEX_PI=y CONFIG_EPOLL=y @@ -227,17 +239,17 @@ CONFIG_AIO=y CONFIG_IO_URING=y CONFIG_ADVISE_SYSCALLS=y CONFIG_MEMBARRIER=y +CONFIG_KCMP=y +CONFIG_RSEQ=y +# CONFIG_DEBUG_RSEQ is not set +CONFIG_CACHESTAT_SYSCALL=y +# CONFIG_PC104 is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_SELFTEST is not set # CONFIG_KALLSYMS_ALL is not set -CONFIG_KALLSYMS_BASE_RELATIVE=y CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y -CONFIG_KCMP=y -CONFIG_RSEQ=y -CONFIG_CACHESTAT_SYSCALL=y -# CONFIG_DEBUG_RSEQ is not set +CONFIG_ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS=y CONFIG_HAVE_PERF_EVENTS=y -# CONFIG_PC104 is not set # # Kernel Performance Events And Counters @@ -254,22 +266,20 @@ CONFIG_PROFILING=y # # CONFIG_KEXEC is not set # CONFIG_KEXEC_FILE is not set -# CONFIG_CRASH_DUMP is not set # end of Kexec and crash features # end of General setup CONFIG_ARM64=y +CONFIG_RUSTC_SUPPORTS_ARM64=y CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y CONFIG_64BIT=y CONFIG_MMU=y -CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_CONT_PTE_SHIFT=4 CONFIG_ARM64_CONT_PMD_SHIFT=4 CONFIG_ARCH_MMAP_RND_BITS_MIN=18 CONFIG_ARCH_MMAP_RND_BITS_MAX=33 CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 -CONFIG_NO_IOPORT_MAP=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 CONFIG_LOCKDEP_SUPPORT=y @@ -290,12 +300,14 @@ CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y # Platform selection # # CONFIG_ARCH_ACTIONS is not set +# CONFIG_ARCH_AIROHA is not set # CONFIG_ARCH_SUNXI is not set # CONFIG_ARCH_ALPINE is not set # CONFIG_ARCH_APPLE is not set # CONFIG_ARCH_BCM is not set # CONFIG_ARCH_BERLIN is not set # CONFIG_ARCH_BITMAIN is not set +# CONFIG_ARCH_BLAIZE is not set # CONFIG_ARCH_EXYNOS is not set # CONFIG_ARCH_SPARX5 is not set # CONFIG_ARCH_K3 is not set @@ -311,6 +323,7 @@ CONFIG_ARCH_MXC=y # CONFIG_ARCH_S32 is not set # CONFIG_ARCH_MA35 is not set # CONFIG_ARCH_NPCM is not set +# CONFIG_ARCH_PENSANDO is not set # CONFIG_ARCH_QCOM is not set # CONFIG_ARCH_REALTEK is not set # CONFIG_ARCH_RENESAS is not set @@ -344,15 +357,14 @@ CONFIG_ARM64_ERRATUM_827319=y CONFIG_ARM64_ERRATUM_824069=y CONFIG_ARM64_ERRATUM_819472=y # CONFIG_ARM64_ERRATUM_832075 is not set -# CONFIG_ARM64_ERRATUM_1742098 is not set +CONFIG_ARM64_ERRATUM_1742098=y CONFIG_ARM64_ERRATUM_845719=y CONFIG_ARM64_ERRATUM_843419=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y # CONFIG_ARM64_ERRATUM_1024718 is not set # CONFIG_ARM64_ERRATUM_1418040 is not set -CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y # CONFIG_ARM64_ERRATUM_1165522 is not set -CONFIG_ARM64_ERRATUM_1319367=y +# CONFIG_ARM64_ERRATUM_1319367 is not set # CONFIG_ARM64_ERRATUM_1530923 is not set # CONFIG_ARM64_ERRATUM_2441007 is not set # CONFIG_ARM64_ERRATUM_1286807 is not set @@ -368,7 +380,7 @@ CONFIG_ARM64_ERRATUM_1319367=y # CONFIG_ARM64_ERRATUM_2645198 is not set # CONFIG_ARM64_ERRATUM_2966298 is not set # CONFIG_ARM64_ERRATUM_3117295 is not set -# CONFIG_ARM64_ERRATUM_3194386 is not set +CONFIG_ARM64_ERRATUM_3194386=y # CONFIG_CAVIUM_ERRATUM_22375 is not set # CONFIG_CAVIUM_ERRATUM_23154 is not set # CONFIG_CAVIUM_ERRATUM_27456 is not set @@ -376,11 +388,13 @@ CONFIG_ARM64_ERRATUM_1319367=y # CONFIG_CAVIUM_TX2_ERRATUM_219 is not set # CONFIG_FUJITSU_ERRATUM_010001 is not set # CONFIG_HISILICON_ERRATUM_161600802 is not set +# CONFIG_HISILICON_ERRATUM_162100801 is not set # CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set # CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set # CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set # CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set # CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set +# CONFIG_ROCKCHIP_ERRATUM_3568002 is not set # CONFIG_ROCKCHIP_ERRATUM_3588001 is not set # CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set # end of ARM errata workarounds via the alternatives framework @@ -390,6 +404,7 @@ CONFIG_ARM64_4K_PAGES=y # CONFIG_ARM64_64K_PAGES is not set # CONFIG_ARM64_VA_BITS_39 is not set CONFIG_ARM64_VA_BITS_48=y +# CONFIG_ARM64_VA_BITS_52 is not set CONFIG_ARM64_VA_BITS=48 CONFIG_ARM64_PA_BITS_48=y CONFIG_ARM64_PA_BITS=48 @@ -418,6 +433,7 @@ CONFIG_ARCH_SUPPORTS_KEXEC_SIG=y CONFIG_ARCH_SUPPORTS_KEXEC_IMAGE_VERIFY_SIG=y CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y CONFIG_ARCH_SUPPORTS_CRASH_DUMP=y +CONFIG_ARCH_DEFAULT_CRASH_DUMP=y # CONFIG_XEN is not set CONFIG_ARCH_FORCE_MAX_ORDER=10 CONFIG_UNMAP_KERNEL_AT_EL0=y @@ -479,6 +495,7 @@ CONFIG_AS_HAS_ARMV8_5=y CONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI=y # CONFIG_ARM64_E0PD is not set CONFIG_ARM64_AS_HAS_MTE=y +# CONFIG_ARM64_MTE is not set # end of ARMv8.5 architectural features # @@ -486,12 +503,28 @@ CONFIG_ARM64_AS_HAS_MTE=y # # end of ARMv8.7 architectural features +CONFIG_AS_HAS_MOPS=y + +# +# ARMv8.9 architectural features +# +# CONFIG_ARM64_POE is not set +CONFIG_ARCH_PKEY_BITS=3 +# end of ARMv8.9 architectural features + +# +# v9.4 architectural features +# +CONFIG_ARM64_GCS=y +# end of v9.4 architectural features + CONFIG_ARM64_SVE=y # CONFIG_ARM64_PSEUDO_NMI is not set CONFIG_RELOCATABLE=y # CONFIG_RANDOMIZE_BASE is not set CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y CONFIG_STACKPROTECTOR_PER_TASK=y +CONFIG_ARM64_CONTPTE=y # end of Kernel Features # @@ -499,6 +532,7 @@ CONFIG_STACKPROTECTOR_PER_TASK=y # CONFIG_CMDLINE="" # CONFIG_EFI is not set +# CONFIG_COMPRESSED_INSTALL is not set # end of Boot options # @@ -569,18 +603,19 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y # CPU frequency scaling drivers # CONFIG_CPUFREQ_DT=y +# CONFIG_CPUFREQ_VIRT is not set CONFIG_CPUFREQ_DT_PLATDEV=y CONFIG_ARM_IMX_CPUFREQ_DT=y # end of CPU Frequency scaling # end of CPU Power Management -CONFIG_HAVE_KVM=y # CONFIG_VIRTUALIZATION is not set CONFIG_CPU_MITIGATIONS=y # # General architecture-dependent options # +CONFIG_HOTPLUG_SMT=y CONFIG_HOTPLUG_CORE_SYNC=y CONFIG_HOTPLUG_CORE_SYNC_DEAD=y # CONFIG_KPROBES is not set @@ -590,7 +625,6 @@ CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y -CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y CONFIG_HAVE_NMI=y CONFIG_TRACE_IRQFLAGS_SUPPORT=y @@ -608,6 +642,7 @@ CONFIG_ARCH_WANTS_NO_INSTR=y CONFIG_HAVE_ASM_MODVERSIONS=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_RSEQ=y +CONFIG_HAVE_RUST=y CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y CONFIG_HAVE_HW_BREAKPOINT=y CONFIG_HAVE_PERF_REGS=y @@ -650,6 +685,7 @@ CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y CONFIG_ARCH_WANT_PMD_MKWRITE=y CONFIG_HAVE_MOD_ARCH_SPECIFIC=y CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_WANTS_EXECMEM_LATE=y CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y CONFIG_SOFTIRQ_ON_OWN_STACK=y CONFIG_ARCH_HAS_ELF_RANDOMIZE=y @@ -657,13 +693,17 @@ CONFIG_HAVE_ARCH_MMAP_RND_BITS=y CONFIG_ARCH_MMAP_RND_BITS=18 CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 +CONFIG_HAVE_PAGE_SIZE_4KB=y +CONFIG_PAGE_SIZE_4KB=y CONFIG_PAGE_SIZE_LESS_THAN_64KB=y CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SHIFT=12 CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y CONFIG_CLONE_BACKWARDS=y CONFIG_OLD_SIGSUSPEND3=y CONFIG_COMPAT_OLD_SIGACTION=y CONFIG_COMPAT_32BIT_TIME=y +CONFIG_ARCH_SUPPORTS_RT=y CONFIG_HAVE_ARCH_VMAP_STACK=y CONFIG_VMAP_STACK=y CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET=y @@ -677,12 +717,17 @@ CONFIG_HAVE_ARCH_COMPILER_H=y CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y # CONFIG_LOCK_EVENT_COUNTS is not set CONFIG_ARCH_HAS_RELR=y +CONFIG_RELR=y +CONFIG_ARCH_HAS_MEM_ENCRYPT=y +CONFIG_ARCH_HAS_CC_PLATFORM=y CONFIG_HAVE_PREEMPT_DYNAMIC=y CONFIG_HAVE_PREEMPT_DYNAMIC_KEY=y CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y CONFIG_ARCH_SUPPORTS_PAGE_TABLE_CHECK=y CONFIG_ARCH_HAVE_TRACE_MMIO_ACCESS=y +CONFIG_ARCH_HAS_HW_PTE_YOUNG=y +CONFIG_ARCH_HAS_KERNEL_FPU_SUPPORT=y # # GCOV-based kernel profiling @@ -696,10 +741,11 @@ CONFIG_GCC_PLUGINS=y # CONFIG_GCC_PLUGIN_LATENT_ENTROPY is not set CONFIG_FUNCTION_ALIGNMENT_4B=y CONFIG_FUNCTION_ALIGNMENT=4 +CONFIG_CC_HAS_MIN_FUNCTION_ALIGNMENT=y +CONFIG_CC_HAS_SANE_FUNCTION_ALIGNMENT=y # end of General architecture-dependent options CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_DEBUG is not set # CONFIG_MODULE_FORCE_LOAD is not set @@ -709,10 +755,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set # CONFIG_MODULE_SIG is not set -CONFIG_MODULE_COMPRESS_NONE=y -# CONFIG_MODULE_COMPRESS_GZIP is not set -# CONFIG_MODULE_COMPRESS_XZ is not set -# CONFIG_MODULE_COMPRESS_ZSTD is not set +# CONFIG_MODULE_COMPRESS is not set # CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set CONFIG_MODPROBE_PATH="/sbin/modprobe" # CONFIG_TRIM_UNUSED_KSYMS is not set @@ -725,9 +768,9 @@ CONFIG_BLK_DEV_BSG_COMMON=y CONFIG_BLK_ICQ=y CONFIG_BLK_DEV_BSGLIB=y # CONFIG_BLK_DEV_INTEGRITY is not set +CONFIG_BLK_DEV_WRITE_MOUNTED=y # CONFIG_BLK_DEV_ZONED is not set CONFIG_BLK_DEV_THROTTLING=y -# CONFIG_BLK_DEV_THROTTLING_LOW is not set # CONFIG_BLK_WBT is not set # CONFIG_BLK_CGROUP_IOLATENCY is not set # CONFIG_BLK_CGROUP_IOCOST is not set @@ -760,8 +803,10 @@ CONFIG_LDM_PARTITION=y CONFIG_EFI_PARTITION=y # CONFIG_SYSV68_PARTITION is not set # CONFIG_CMDLINE_PARTITION is not set +# CONFIG_OF_PARTITION is not set # end of Partition Types +CONFIG_BLK_MQ_PCI=y CONFIG_BLK_PM=y CONFIG_BLOCK_HOLDER_DEPRECATED=y CONFIG_BLK_MQ_STACKING=y @@ -863,18 +908,19 @@ CONFIG_SWAP=y # CONFIG_ZSWAP is not set # -# SLAB allocator options +# Slab allocator options # -# CONFIG_SLAB_DEPRECATED is not set CONFIG_SLUB=y +CONFIG_KVFREE_RCU_BATCHED=y # CONFIG_SLUB_TINY is not set CONFIG_SLAB_MERGE_DEFAULT=y # CONFIG_SLAB_FREELIST_RANDOM is not set # CONFIG_SLAB_FREELIST_HARDENED is not set +CONFIG_SLAB_BUCKETS=y # CONFIG_SLUB_STATS is not set CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_RANDOM_KMALLOC_CACHES is not set -# end of SLAB allocator options +# end of Slab allocator options # CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set # CONFIG_COMPAT_BRK is not set @@ -882,15 +928,16 @@ CONFIG_SPARSEMEM=y CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_HAVE_FAST_GUP=y +CONFIG_HAVE_GUP_FAST=y CONFIG_ARCH_KEEP_MEMBLOCK=y CONFIG_MEMORY_ISOLATION=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y # CONFIG_MEMORY_HOTPLUG is not set CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y -CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_SPLIT_PTE_PTLOCKS=y CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y +CONFIG_SPLIT_PMD_PTLOCKS=y CONFIG_COMPACTION=y CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 # CONFIG_PAGE_REPORTING is not set @@ -904,15 +951,21 @@ CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y # CONFIG_MEMORY_FAILURE is not set CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_MM_ID=y CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y # CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set +# CONFIG_TRANSPARENT_HUGEPAGE_NEVER is not set CONFIG_THP_SWAP=y # CONFIG_READ_ONLY_THP_FOR_FS is not set +# CONFIG_NO_PAGE_MAPCOUNT is not set +CONFIG_PAGE_MAPCOUNT=y +CONFIG_PGTABLE_HAS_HUGE_LEAVES=y +CONFIG_ARCH_SUPPORTS_HUGE_PFNMAP=y +CONFIG_ARCH_SUPPORTS_PMD_PFNMAP=y CONFIG_CMA=y -# CONFIG_CMA_DEBUG is not set CONFIG_CMA_DEBUGFS=y -# CONFIG_CMA_SYSFS is not set +CONFIG_CMA_SYSFS=y CONFIG_CMA_AREAS=7 CONFIG_GENERIC_EARLY_IOREMAP=y # CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set @@ -923,6 +976,7 @@ CONFIG_ARCH_HAS_PTE_DEVMAP=y CONFIG_ARCH_HAS_ZONE_DMA_SET=y CONFIG_ZONE_DMA=y CONFIG_ZONE_DMA32=y +CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y CONFIG_VM_EVENT_COUNTERS=y # CONFIG_PERCPU_STATS is not set # CONFIG_GUP_TEST is not set @@ -935,9 +989,12 @@ CONFIG_SECRETMEM=y CONFIG_LRU_GEN=y # CONFIG_LRU_GEN_ENABLED is not set # CONFIG_LRU_GEN_STATS is not set +CONFIG_LRU_GEN_WALKS_MMU=y CONFIG_ARCH_SUPPORTS_PER_VMA_LOCK=y CONFIG_PER_VMA_LOCK=y CONFIG_LOCK_MM_AND_FIND_VMA=y +CONFIG_EXECMEM=y +CONFIG_ARCH_HAS_USER_SHADOW_STACK=y # # Data Access Monitoring @@ -952,6 +1009,7 @@ CONFIG_NET_INGRESS=y CONFIG_NET_EGRESS=y CONFIG_NET_XGRESS=y CONFIG_SKB_EXTENSIONS=y +CONFIG_NET_DEVMEM=y # # Networking options @@ -959,7 +1017,6 @@ CONFIG_SKB_EXTENSIONS=y CONFIG_PACKET=y # CONFIG_PACKET_DIAG is not set CONFIG_UNIX=y -CONFIG_UNIX_SCM=y CONFIG_AF_UNIX_OOB=y # CONFIG_UNIX_DIAG is not set # CONFIG_TLS is not set @@ -972,6 +1029,7 @@ CONFIG_XFRM_USER=y # CONFIG_XFRM_STATISTICS is not set CONFIG_XFRM_ESP=y # CONFIG_NET_KEY is not set +# CONFIG_XFRM_IPTFS is not set # CONFIG_XDP_SOCKETS is not set CONFIG_NET_HANDSHAKE=y CONFIG_INET=y @@ -1030,6 +1088,7 @@ CONFIG_TCP_CONG_CDG=m CONFIG_DEFAULT_CUBIC=y # CONFIG_DEFAULT_RENO is not set CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_AO is not set # CONFIG_TCP_MD5SIG is not set CONFIG_IPV6=y # CONFIG_IPV6_ROUTER_PREF is not set @@ -1045,7 +1104,8 @@ CONFIG_IPV6_SIT=m CONFIG_IPV6_NDISC_NODETYPE=y # CONFIG_IPV6_TUNNEL is not set CONFIG_IPV6_FOU=m -# CONFIG_IPV6_MULTIPLE_TABLES is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +# CONFIG_IPV6_SUBTREES is not set # CONFIG_IPV6_MROUTE is not set # CONFIG_IPV6_SEG6_LWTUNNEL is not set # CONFIG_IPV6_SEG6_HMAC is not set @@ -1104,13 +1164,14 @@ CONFIG_NF_NAT_REDIRECT=y CONFIG_NF_NAT_MASQUERADE=y # CONFIG_NF_TABLES is not set CONFIG_NETFILTER_XTABLES=m -CONFIG_NETFILTER_XTABLES_COMPAT=y +# CONFIG_NETFILTER_XTABLES_COMPAT is not set # # Xtables combined modules # CONFIG_NETFILTER_XT_MARK=m # CONFIG_NETFILTER_XT_CONNMARK is not set +CONFIG_NETFILTER_XT_SET=m # # Xtables targets @@ -1118,6 +1179,7 @@ CONFIG_NETFILTER_XT_MARK=m # CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set # CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set # CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set +# CONFIG_NETFILTER_XT_TARGET_CT is not set # CONFIG_NETFILTER_XT_TARGET_DSCP is not set # CONFIG_NETFILTER_XT_TARGET_HL is not set # CONFIG_NETFILTER_XT_TARGET_HMARK is not set @@ -1129,11 +1191,13 @@ CONFIG_NETFILTER_XT_NAT=m # CONFIG_NETFILTER_XT_TARGET_NETMAP is not set # CONFIG_NETFILTER_XT_TARGET_NFLOG is not set # CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set # CONFIG_NETFILTER_XT_TARGET_RATEEST is not set CONFIG_NETFILTER_XT_TARGET_REDIRECT=m CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m # CONFIG_NETFILTER_XT_TARGET_TEE is not set # CONFIG_NETFILTER_XT_TARGET_TPROXY is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set # CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set # CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set @@ -1188,7 +1252,24 @@ CONFIG_NETFILTER_XT_MATCH_STATE=m # CONFIG_NETFILTER_XT_MATCH_U32 is not set # end of Core Netfilter Configuration -# CONFIG_IP_SET is not set +CONFIG_IP_SET=m +CONFIG_IP_SET_MAX=256 +# CONFIG_IP_SET_BITMAP_IP is not set +# CONFIG_IP_SET_BITMAP_IPMAC is not set +# CONFIG_IP_SET_BITMAP_PORT is not set +# CONFIG_IP_SET_HASH_IP is not set +# CONFIG_IP_SET_HASH_IPMARK is not set +# CONFIG_IP_SET_HASH_IPPORT is not set +# CONFIG_IP_SET_HASH_IPPORTIP is not set +# CONFIG_IP_SET_HASH_IPPORTNET is not set +# CONFIG_IP_SET_HASH_IPMAC is not set +# CONFIG_IP_SET_HASH_MAC is not set +# CONFIG_IP_SET_HASH_NETPORTNET is not set +CONFIG_IP_SET_HASH_NET=m +# CONFIG_IP_SET_HASH_NETNET is not set +# CONFIG_IP_SET_HASH_NETPORT is not set +# CONFIG_IP_SET_HASH_NETIFACE is not set +# CONFIG_IP_SET_LIST_SET is not set CONFIG_IP_VS=m # CONFIG_IP_VS_IPV6 is not set # CONFIG_IP_VS_DEBUG is not set @@ -1242,6 +1323,7 @@ CONFIG_IP_VS_NFCT=y # IP: Netfilter Configuration # CONFIG_NF_DEFRAG_IPV4=m +CONFIG_IP_NF_IPTABLES_LEGACY=m # CONFIG_NF_SOCKET_IPV4 is not set # CONFIG_NF_TPROXY_IPV4 is not set # CONFIG_NF_DUP_IPV4 is not set @@ -1263,13 +1345,15 @@ CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_MANGLE=m # CONFIG_IP_NF_TARGET_ECN is not set # CONFIG_IP_NF_TARGET_TTL is not set -# CONFIG_IP_NF_RAW is not set +CONFIG_IP_NF_RAW=m # CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_ARPFILTER is not set # end of IP: Netfilter Configuration # # IPv6: Netfilter Configuration # +CONFIG_IP6_NF_IPTABLES_LEGACY=m # CONFIG_NF_SOCKET_IPV6 is not set # CONFIG_NF_TPROXY_IPV6 is not set # CONFIG_NF_DUP_IPV6 is not set @@ -1291,7 +1375,7 @@ CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_REJECT=m # CONFIG_IP6_NF_TARGET_SYNPROXY is not set CONFIG_IP6_NF_MANGLE=m -# CONFIG_IP6_NF_RAW is not set +CONFIG_IP6_NF_RAW=m CONFIG_IP6_NF_NAT=m CONFIG_IP6_NF_TARGET_MASQUERADE=m # CONFIG_IP6_NF_TARGET_NPT is not set @@ -1299,8 +1383,8 @@ CONFIG_IP6_NF_TARGET_MASQUERADE=m CONFIG_NF_DEFRAG_IPV6=m # CONFIG_NF_CONNTRACK_BRIDGE is not set +# CONFIG_BRIDGE_NF_EBTABLES_LEGACY is not set # CONFIG_BRIDGE_NF_EBTABLES is not set -# CONFIG_BPFILTER is not set # CONFIG_IP_DCCP is not set # CONFIG_IP_SCTP is not set # CONFIG_RDS is not set @@ -1434,6 +1518,7 @@ CONFIG_BT_QCA=m CONFIG_BT_HCIBTUSB=m # CONFIG_BT_HCIBTUSB_AUTOSUSPEND is not set CONFIG_BT_HCIBTUSB_POLL_SYNC=y +# CONFIG_BT_HCIBTUSB_AUTO_ISOC_ALT is not set CONFIG_BT_HCIBTUSB_BCM=y # CONFIG_BT_HCIBTUSB_MTK is not set CONFIG_BT_HCIBTUSB_RTL=y @@ -1452,7 +1537,9 @@ CONFIG_BT_HCIUART_BCM=y CONFIG_BT_HCIUART_QCA=y # CONFIG_BT_HCIUART_AG6XX is not set # CONFIG_BT_HCIUART_MRVL is not set +# CONFIG_BT_HCIUART_AML is not set CONFIG_BT_HCIBCM203X=m +# CONFIG_BT_HCIBCM4377 is not set # CONFIG_BT_HCIBPA10X is not set CONFIG_BT_HCIBFUSB=m # CONFIG_BT_HCIVHCI is not set @@ -1461,6 +1548,7 @@ CONFIG_BT_ATH3K=m # CONFIG_BT_MTKSDIO is not set # CONFIG_BT_MTKUART is not set CONFIG_BT_NXPUART=m +# CONFIG_BT_INTEL_PCIE is not set # end of Bluetooth device drivers # CONFIG_AF_RXRPC is not set @@ -1468,10 +1556,8 @@ CONFIG_BT_NXPUART=m # CONFIG_MCTP is not set CONFIG_FIB_RULES=y CONFIG_WIRELESS=y -CONFIG_WIRELESS_EXT=y CONFIG_WEXT_CORE=y CONFIG_WEXT_PROC=y -CONFIG_WEXT_PRIV=y CONFIG_CFG80211=m # CONFIG_NL80211_TESTMODE is not set # CONFIG_CFG80211_DEVELOPER_WARNINGS is not set @@ -1489,7 +1575,6 @@ CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" # CONFIG_MAC80211_MESH is not set CONFIG_MAC80211_LEDS=y -# CONFIG_MAC80211_DEBUGFS is not set # CONFIG_MAC80211_DEBUG_MENU is not set CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 CONFIG_RFKILL=m @@ -1517,8 +1602,95 @@ CONFIG_ETHTOOL_NETLINK=y # CONFIG_ARM_AMBA=y CONFIG_HAVE_PCI=y -# CONFIG_PCI is not set +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_SYSCALL=y +# CONFIG_PCIEPORTBUS is not set +# CONFIG_PCIEASPM is not set +# CONFIG_PCIE_PTM is not set +CONFIG_PCI_MSI=y +CONFIG_PCI_QUIRKS=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_DOE is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_NPEM is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +# CONFIG_PCIE_TPH is not set +CONFIG_PCI_DYNAMIC_OF_NODES=y +# CONFIG_PCIE_BUS_TUNE_OFF is not set +CONFIG_PCIE_BUS_DEFAULT=y +# CONFIG_PCIE_BUS_SAFE is not set +# CONFIG_PCIE_BUS_PERFORMANCE is not set +# CONFIG_PCIE_BUS_PEER2PEER is not set +# CONFIG_VGA_ARB is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# PCI controller drivers +# +# CONFIG_PCIE_ALTERA is not set +# CONFIG_PCI_HOST_THUNDER_PEM is not set +# CONFIG_PCI_HOST_THUNDER_ECAM is not set +# CONFIG_PCI_FTPCI100 is not set +# CONFIG_PCI_HOST_GENERIC is not set +# CONFIG_PCI_XGENE is not set +# CONFIG_PCIE_XILINX is not set + +# +# Cadence-based PCIe controllers +# +# CONFIG_PCIE_CADENCE_PLAT_HOST is not set +# end of Cadence-based PCIe controllers + +# +# DesignWare-based PCIe controllers +# +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_DEBUGFS=y +CONFIG_PCIE_DW_HOST=y +# CONFIG_PCIE_AL is not set +# CONFIG_PCIE_AMD_MDB is not set +# CONFIG_PCI_MESON is not set +CONFIG_PCI_IMX6=y +CONFIG_PCI_IMX6_HOST=y +# CONFIG_PCI_HISI is not set +# CONFIG_PCIE_KIRIN is not set +# CONFIG_PCIE_DW_PLAT_HOST is not set +# end of DesignWare-based PCIe controllers + +# +# Mobiveil-based PCIe controllers +# +# end of Mobiveil-based PCIe controllers + +# +# PLDA-based PCIe controllers +# +# CONFIG_PCIE_MICROCHIP_HOST is not set +# end of PLDA-based PCIe controllers +# end of PCI controller drivers + +# +# PCI Endpoint +# +# CONFIG_PCI_ENDPOINT is not set +# end of PCI Endpoint + +# +# PCI switch controller drivers +# +# CONFIG_PCI_SW_SWITCHTEC is not set +# end of PCI switch controller drivers + +CONFIG_PCI_PWRCTL=m +CONFIG_PCI_PWRCTL_SLOT=m +# CONFIG_CXL_BUS is not set # CONFIG_PCCARD is not set +# CONFIG_RAPIDIO is not set # # Generic Driver Options @@ -1548,6 +1720,7 @@ CONFIG_WANT_DEV_COREDUMP=y # CONFIG_DEBUG_DEVRES is not set # CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set # CONFIG_TEST_ASYNC_DRIVER_PROBE is not set +CONFIG_GENERIC_CPU_DEVICES=y CONFIG_GENERIC_CPU_AUTOPROBE=y CONFIG_GENERIC_CPU_VULNERABILITIES=y CONFIG_SOC_BUS=y @@ -1565,7 +1738,6 @@ CONFIG_GENERIC_ARCH_TOPOLOGY=y # # Bus devices # -# CONFIG_BRCMSTB_GISB_ARB is not set # CONFIG_MOXTET is not set # CONFIG_IMX_WEIM is not set # CONFIG_VEXPRESS_CONFIG is not set @@ -1591,15 +1763,22 @@ CONFIG_GENERIC_ARCH_TOPOLOGY=y # end of ARM System Control and Management Interface Protocol CONFIG_ARM_SCPI_PROTOCOL=y -CONFIG_ARM_SCPI_POWER_DOMAIN=y +# CONFIG_ARM_SDE_INTERFACE is not set # CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_FW_CFG_SYSFS is not set # CONFIG_ARM_FFA_TRANSPORT is not set # CONFIG_GOOGLE_FIRMWARE is not set CONFIG_IMX_DSP=m CONFIG_IMX_SCU=y -CONFIG_IMX_SCU_PD=y +CONFIG_IMX_SCMI_MISC_DRV=y CONFIG_ARM_PSCI_FW=y # CONFIG_ARM_PSCI_CHECKER is not set + +# +# Qualcomm firmware drivers +# +# end of Qualcomm firmware drivers + CONFIG_HAVE_ARM_SMCCC=y CONFIG_HAVE_ARM_SMCCC_DISCOVERY=y CONFIG_ARM_SMCCC_SOC_ID=y @@ -1610,6 +1789,7 @@ CONFIG_ARM_SMCCC_SOC_ID=y # end of Tegra firmware driver # end of Firmware Drivers +# CONFIG_FWCTL is not set # CONFIG_GNSS is not set CONFIG_MTD=y # CONFIG_MTD_TESTS is not set @@ -1617,7 +1797,6 @@ CONFIG_MTD=y # # Partition parsers # -# CONFIG_MTD_AR7_PARTS is not set # CONFIG_MTD_CMDLINE_PARTS is not set CONFIG_MTD_OF_PARTS=y # CONFIG_MTD_AFS_PARTS is not set @@ -1668,6 +1847,7 @@ CONFIG_MTD_CFI_I2=y # # Self-contained MTD device drivers # +# CONFIG_MTD_PMC551 is not set # CONFIG_MTD_DATAFLASH is not set # CONFIG_MTD_MCHP23K256 is not set # CONFIG_MTD_MCHP48L640 is not set @@ -1728,6 +1908,8 @@ CONFIG_OF_OVERLAY=y CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_NULL_BLK is not set CONFIG_CDROM=y +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_ZRAM is not set CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_LOOP_MIN_COUNT=0 # CONFIG_BLK_DEV_DRBD is not set @@ -1743,6 +1925,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # # NVME Support # +# CONFIG_BLK_DEV_NVME is not set # CONFIG_NVME_FC is not set # CONFIG_NVME_TCP is not set # CONFIG_NVME_TARGET is not set @@ -1753,8 +1936,12 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # # CONFIG_AD525X_DPOT is not set # CONFIG_DUMMY_IRQ is not set +# CONFIG_PHANTOM is not set +# CONFIG_RPMB is not set +# CONFIG_TIFM_CORE is not set # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set # CONFIG_APDS9802ALS is not set # CONFIG_ISL29003 is not set # CONFIG_ISL29020 is not set @@ -1765,10 +1952,14 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_DS1682 is not set # CONFIG_LATTICE_ECP3_CONFIG is not set # CONFIG_SRAM is not set +# CONFIG_DW_XDATA_PCIE is not set +# CONFIG_PCI_ENDPOINT_TEST is not set # CONFIG_XILINX_SDFEC is not set # CONFIG_HISI_HIKEY_USB is not set # CONFIG_OPEN_DICE is not set +# CONFIG_NTSYNC is not set # CONFIG_VCPU_STALL_DETECTOR is not set +# CONFIG_MCHP_LAN966X_PCI is not set # CONFIG_C2PORT is not set # @@ -1776,7 +1967,6 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # # CONFIG_EEPROM_AT24 is not set CONFIG_EEPROM_AT25=m -# CONFIG_EEPROM_LEGACY is not set # CONFIG_EEPROM_MAX6875 is not set CONFIG_EEPROM_93CX6=m # CONFIG_EEPROM_93XX46 is not set @@ -1784,19 +1974,21 @@ CONFIG_EEPROM_93CX6=m # CONFIG_EEPROM_EE1004 is not set # end of EEPROM support -# -# Texas Instruments shared transport line discipline -# -# CONFIG_TI_ST is not set -# end of Texas Instruments shared transport line discipline - +# CONFIG_CB710_CORE is not set # CONFIG_SENSORS_LIS3_SPI is not set # CONFIG_SENSORS_LIS3_I2C is not set # CONFIG_ALTERA_STAPL is not set +# CONFIG_VMWARE_VMCI is not set +# CONFIG_GENWQE is not set # CONFIG_ECHO is not set +# CONFIG_BCM_VK is not set +# CONFIG_MISC_ALCOR_PCI is not set +# CONFIG_MISC_RTSX_PCI is not set # CONFIG_MISC_RTSX_USB is not set # CONFIG_UACCE is not set # CONFIG_PVPANIC is not set +# CONFIG_GP_PCI1XXXX is not set +# CONFIG_KEBA_CP500 is not set # end of Misc devices # @@ -1837,7 +2029,52 @@ CONFIG_SCSI_SAS_HOST_SMP=y CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_ESAS2R is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT3SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_MPI3MR is not set +# CONFIG_SCSI_SMARTPQI is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_MYRB is not set +# CONFIG_SCSI_MYRS is not set +# CONFIG_SCSI_SNIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FDOMAIN_PCI is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_WD719X is not set # CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set # CONFIG_SCSI_DH is not set # end of SCSI device support @@ -1874,7 +2111,17 @@ CONFIG_DM_THIN_PROVISIONING=m # CONFIG_DM_SWITCH is not set # CONFIG_DM_LOG_WRITES is not set # CONFIG_DM_INTEGRITY is not set +# CONFIG_DM_VDO is not set # CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# end of IEEE 1394 (FireWire) support + CONFIG_NETDEVICES=y CONFIG_MII=y CONFIG_NET_CORE=y @@ -1883,6 +2130,7 @@ CONFIG_DUMMY=m CONFIG_WIREGUARD=m # CONFIG_WIREGUARD_DEBUG is not set # CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set # CONFIG_NET_TEAM is not set CONFIG_MACVLAN=m # CONFIG_MACVTAP is not set @@ -1893,6 +2141,7 @@ CONFIG_VXLAN=m # CONFIG_GENEVE is not set # CONFIG_BAREUDP is not set # CONFIG_GTP is not set +# CONFIG_PFCP is not set # CONFIG_AMT is not set # CONFIG_MACSEC is not set CONFIG_NETCONSOLE=y @@ -1904,20 +2153,33 @@ CONFIG_TUN=y # CONFIG_TUN_VNET_CROSS_LE is not set CONFIG_VETH=m CONFIG_NLMON=m +# CONFIG_NETKIT is not set +# CONFIG_NET_VRF is not set +# CONFIG_ARCNET is not set CONFIG_ETHERNET=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_ADAPTEC is not set +# CONFIG_NET_VENDOR_AGERE is not set # CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_ALTEON is not set # CONFIG_ALTERA_TSE is not set # CONFIG_NET_VENDOR_AMAZON is not set # CONFIG_NET_VENDOR_AMD is not set # CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_VENDOR_ASIX is not set +# CONFIG_NET_VENDOR_ATHEROS is not set # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_NET_VENDOR_CADENCE is not set # CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CISCO is not set # CONFIG_NET_VENDOR_CORTINA is not set # CONFIG_NET_VENDOR_DAVICOM is not set # CONFIG_DNET is not set +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_DLINK is not set +# CONFIG_NET_VENDOR_EMULEX is not set # CONFIG_NET_VENDOR_ENGLEDER is not set # CONFIG_NET_VENDOR_EZCHIP is not set CONFIG_NET_VENDOR_FREESCALE=y @@ -1925,30 +2187,55 @@ CONFIG_FEC=y # CONFIG_FSL_PQ_MDIO is not set # CONFIG_FSL_XGMAC_MDIO is not set # CONFIG_GIANFAR is not set +# CONFIG_FSL_ENETC is not set +# CONFIG_NXP_ENETC4 is not set +# CONFIG_FSL_ENETC_VF is not set # CONFIG_FSL_ENETC_IERB is not set +# CONFIG_FSL_ENETC_MDIO is not set +# CONFIG_NXP_NETC_BLK_CTRL is not set # CONFIG_NET_VENDOR_FUNGIBLE is not set CONFIG_NET_VENDOR_GOOGLE=y +# CONFIG_GVE is not set # CONFIG_NET_VENDOR_HISILICON is not set # CONFIG_NET_VENDOR_HUAWEI is not set # CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_JME is not set # CONFIG_NET_VENDOR_ADI is not set # CONFIG_NET_VENDOR_LITEX is not set # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_META is not set # CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_MICROCHIP is not set # CONFIG_NET_VENDOR_MICROSEMI is not set # CONFIG_NET_VENDOR_MICROSOFT is not set +# CONFIG_NET_VENDOR_MYRI is not set +# CONFIG_FEALNX is not set # CONFIG_NET_VENDOR_NI is not set # CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETERION is not set # CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NVIDIA is not set +# CONFIG_NET_VENDOR_OKI is not set # CONFIG_ETHOC is not set +# CONFIG_NET_VENDOR_PACKET_ENGINES is not set CONFIG_NET_VENDOR_PENSANDO=y +# CONFIG_IONIC is not set +# CONFIG_NET_VENDOR_QLOGIC is not set +# CONFIG_NET_VENDOR_BROCADE is not set # CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RDC is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +# CONFIG_RTASE is not set # CONFIG_NET_VENDOR_RENESAS is not set # CONFIG_NET_VENDOR_ROCKER is not set # CONFIG_NET_VENDOR_SAMSUNG is not set # CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SILAN is not set +# CONFIG_NET_VENDOR_SIS is not set # CONFIG_NET_VENDOR_SOLARFLARE is not set # CONFIG_NET_VENDOR_SMSC is not set # CONFIG_NET_VENDOR_SOCIONEXT is not set @@ -1960,15 +2247,20 @@ CONFIG_STMMAC_PLATFORM=y CONFIG_DWMAC_GENERIC=y CONFIG_DWMAC_IMX8=y # CONFIG_DWMAC_INTEL_PLAT is not set +# CONFIG_STMMAC_PCI is not set +# CONFIG_NET_VENDOR_SUN is not set # CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_TEHUTI is not set +# CONFIG_NET_VENDOR_TI is not set # CONFIG_NET_VENDOR_VERTEXCOM is not set # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WANGXUN is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_NET_VENDOR_XILINX=y # CONFIG_XILINX_EMACLITE is not set -# CONFIG_XILINX_AXI_EMAC is not set # CONFIG_XILINX_LL_TEMAC is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set CONFIG_PHYLINK=y CONFIG_PHYLIB=y CONFIG_SWPHY=y @@ -1980,6 +2272,7 @@ CONFIG_FIXED_PHY=y # # MII PHY device drivers # +# CONFIG_AIR_EN8811H_PHY is not set # CONFIG_AMD_PHY is not set # CONFIG_ADIN_PHY is not set # CONFIG_ADIN1100_PHY is not set @@ -2014,9 +2307,14 @@ CONFIG_MICROCHIP_PHY=m # CONFIG_NXP_C45_TJA11XX_PHY is not set # CONFIG_NXP_TJA11XX_PHY is not set # CONFIG_NCN26000_PHY is not set +CONFIG_QCOM_NET_PHYLIB=y CONFIG_AT803X_PHY=y +# CONFIG_QCA83XX_PHY is not set +# CONFIG_QCA808X_PHY is not set +# CONFIG_QCA807X_PHY is not set # CONFIG_QSEMI_PHY is not set CONFIG_REALTEK_PHY=y +CONFIG_REALTEK_PHY_HWMON=y # CONFIG_RENESAS_PHY is not set # CONFIG_ROCKCHIP_PHY is not set CONFIG_SMSC_PHY=m @@ -2028,6 +2326,7 @@ CONFIG_SMSC_PHY=m # CONFIG_DP83867_PHY is not set # CONFIG_DP83869_PHY is not set # CONFIG_DP83TD510_PHY is not set +# CONFIG_DP83TG720_PHY is not set # CONFIG_VITESSE_PHY is not set # CONFIG_XILINX_GMII2RGMII is not set # CONFIG_MICREL_KS8995MA is not set @@ -2046,6 +2345,7 @@ CONFIG_MDIO_BITBANG=y # CONFIG_MDIO_OCTEON is not set # CONFIG_MDIO_IPQ4019 is not set # CONFIG_MDIO_IPQ8064 is not set +# CONFIG_MDIO_THUNDER is not set # # MDIO Multiplexers @@ -2102,16 +2402,18 @@ CONFIG_USB_IPHETH=m # CONFIG_USB_NET_AQC111 is not set CONFIG_USB_RTL8153_ECM=m CONFIG_WLAN=y -CONFIG_WLAN_VENDOR_ADMTEK=y +# CONFIG_WLAN_VENDOR_ADMTEK is not set CONFIG_ATH_COMMON=m CONFIG_WLAN_VENDOR_ATH=y # CONFIG_ATH_DEBUG is not set +# CONFIG_ATH5K is not set +# CONFIG_ATH5K_PCI is not set CONFIG_ATH9K_HW=m CONFIG_ATH9K_COMMON=m CONFIG_ATH9K_BTCOEX_SUPPORT=y CONFIG_ATH9K=m +# CONFIG_ATH9K_PCI is not set # CONFIG_ATH9K_AHB is not set -# CONFIG_ATH9K_DEBUGFS is not set # CONFIG_ATH9K_DYNACK is not set # CONFIG_ATH9K_WOW is not set CONFIG_ATH9K_RFKILL=y @@ -2129,14 +2431,20 @@ CONFIG_ATH6KL=m CONFIG_ATH6KL_USB=m # CONFIG_ATH6KL_DEBUG is not set CONFIG_AR5523=m +# CONFIG_WIL6210 is not set CONFIG_ATH10K=m CONFIG_ATH10K_CE=y +CONFIG_ATH10K_PCI=m +# CONFIG_ATH10K_AHB is not set CONFIG_ATH10K_SDIO=m CONFIG_ATH10K_USB=m # CONFIG_ATH10K_DEBUG is not set # CONFIG_ATH10K_DEBUGFS is not set +CONFIG_ATH10K_LEDS=y CONFIG_WCN36XX=m # CONFIG_WCN36XX_DEBUGFS is not set +# CONFIG_ATH11K is not set +# CONFIG_ATH12K is not set CONFIG_WLAN_VENDOR_ATMEL=y # CONFIG_AT76C50X_USB is not set CONFIG_WLAN_VENDOR_BROADCOM=y @@ -2146,6 +2454,8 @@ CONFIG_B43_SSB=y CONFIG_B43_BUSES_BCMA_AND_SSB=y # CONFIG_B43_BUSES_BCMA is not set # CONFIG_B43_BUSES_SSB is not set +CONFIG_B43_PCI_AUTOSELECT=y +CONFIG_B43_PCICORE_AUTOSELECT=y # CONFIG_B43_SDIO is not set CONFIG_B43_BCMA_PIO=y CONFIG_B43_PIO=y @@ -2163,19 +2473,25 @@ CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC_PROTO_BCDC=y CONFIG_BRCMFMAC_SDIO=y CONFIG_BRCMFMAC_USB=y +# CONFIG_BRCMFMAC_PCIE is not set # CONFIG_BRCMDBG is not set -CONFIG_WLAN_VENDOR_CISCO=y CONFIG_WLAN_VENDOR_INTEL=y +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +# CONFIG_IWL4965 is not set +# CONFIG_IWL3945 is not set +# CONFIG_IWLWIFI is not set CONFIG_WLAN_VENDOR_INTERSIL=y -# CONFIG_HOSTAP is not set CONFIG_P54_COMMON=m CONFIG_P54_USB=m +# CONFIG_P54_PCI is not set # CONFIG_P54_SPI is not set CONFIG_P54_LEDS=y CONFIG_WLAN_VENDOR_MARVELL=y # CONFIG_LIBERTAS is not set # CONFIG_LIBERTAS_THINFIRM is not set # CONFIG_MWIFIEX is not set +# CONFIG_MWL8K is not set CONFIG_WLAN_VENDOR_MEDIATEK=y CONFIG_MT7601U=m CONFIG_MT76_CORE=m @@ -2188,19 +2504,32 @@ CONFIG_MT792x_LIB=m CONFIG_MT792x_USB=m CONFIG_MT76x0_COMMON=m CONFIG_MT76x0U=m +# CONFIG_MT76x0E is not set CONFIG_MT76x2_COMMON=m +# CONFIG_MT76x2E is not set CONFIG_MT76x2U=m +# CONFIG_MT7603E is not set +# CONFIG_MT7615E is not set # CONFIG_MT7663U is not set # CONFIG_MT7663S is not set +# CONFIG_MT7915E is not set CONFIG_MT7921_COMMON=m +# CONFIG_MT7921E is not set # CONFIG_MT7921S is not set CONFIG_MT7921U=m +# CONFIG_MT7996E is not set +# CONFIG_MT7925E is not set +# CONFIG_MT7925U is not set CONFIG_WLAN_VENDOR_MICROCHIP=y # CONFIG_WILC1000_SDIO is not set # CONFIG_WILC1000_SPI is not set # CONFIG_WLAN_VENDOR_PURELIFI is not set CONFIG_WLAN_VENDOR_RALINK=y CONFIG_RT2X00=m +# CONFIG_RT2400PCI is not set +# CONFIG_RT2500PCI is not set +# CONFIG_RT61PCI is not set +# CONFIG_RT2800PCI is not set CONFIG_RT2500USB=m CONFIG_RT73USB=m CONFIG_RT2800USB=m @@ -2218,10 +2547,24 @@ CONFIG_RT2X00_LIB_CRYPTO=y CONFIG_RT2X00_LIB_LEDS=y # CONFIG_RT2X00_DEBUG is not set CONFIG_WLAN_VENDOR_REALTEK=y +# CONFIG_RTL8180 is not set CONFIG_RTL8187=m CONFIG_RTL8187_LEDS=y CONFIG_RTL_CARDS=m +# CONFIG_RTL8192CE is not set +# CONFIG_RTL8192SE is not set +# CONFIG_RTL8192DE is not set +# CONFIG_RTL8723AE is not set +# CONFIG_RTL8723BE is not set +# CONFIG_RTL8188EE is not set +# CONFIG_RTL8192EE is not set +# CONFIG_RTL8821AE is not set # CONFIG_RTL8192CU is not set +CONFIG_RTL8192DU=m +CONFIG_RTLWIFI=m +CONFIG_RTLWIFI_USB=m +CONFIG_RTLWIFI_DEBUG=y +CONFIG_RTL8192D_COMMON=m CONFIG_RTL8XXXU=m CONFIG_RTL8XXXU_UNTESTED=y CONFIG_RTW88=m @@ -2229,18 +2572,33 @@ CONFIG_RTW88_CORE=m CONFIG_RTW88_USB=m CONFIG_RTW88_8822B=m CONFIG_RTW88_8822C=m +CONFIG_RTW88_8723X=m CONFIG_RTW88_8723D=m CONFIG_RTW88_8821C=m +CONFIG_RTW88_88XXA=m +CONFIG_RTW88_8821A=m +CONFIG_RTW88_8812A=m +CONFIG_RTW88_8814A=m +# CONFIG_RTW88_8822BE is not set # CONFIG_RTW88_8822BS is not set CONFIG_RTW88_8822BU=m +# CONFIG_RTW88_8822CE is not set # CONFIG_RTW88_8822CS is not set CONFIG_RTW88_8822CU=m +# CONFIG_RTW88_8723DE is not set # CONFIG_RTW88_8723DS is not set +# CONFIG_RTW88_8723CS is not set CONFIG_RTW88_8723DU=m +# CONFIG_RTW88_8821CE is not set # CONFIG_RTW88_8821CS is not set CONFIG_RTW88_8821CU=m +CONFIG_RTW88_8821AU=m +CONFIG_RTW88_8812AU=m +# CONFIG_RTW88_8814AE is not set +CONFIG_RTW88_8814AU=m # CONFIG_RTW88_DEBUG is not set # CONFIG_RTW88_DEBUGFS is not set +CONFIG_RTW88_LEDS=y # CONFIG_RTW89 is not set CONFIG_WLAN_VENDOR_RSI=y # CONFIG_RSI_91X is not set @@ -2255,11 +2613,9 @@ CONFIG_WLCORE=m # CONFIG_WLCORE_SPI is not set CONFIG_WLCORE_SDIO=m CONFIG_WLAN_VENDOR_ZYDAS=y -CONFIG_USB_ZD1201=m CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set # CONFIG_WLAN_VENDOR_QUANTENNA is not set -CONFIG_USB_NET_RNDIS_WLAN=m # CONFIG_MAC80211_HWSIM is not set # CONFIG_VIRT_WIFI is not set # CONFIG_WAN is not set @@ -2270,6 +2626,7 @@ CONFIG_USB_NET_RNDIS_WLAN=m # CONFIG_WWAN is not set # end of Wireless WAN +# CONFIG_VMXNET3 is not set # CONFIG_NETDEVSIM is not set # CONFIG_NET_FAILOVER is not set # CONFIG_ISDN is not set @@ -2292,7 +2649,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 CONFIG_INPUT_JOYDEV=y CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_EVBUG is not set # # Input Device Drivers @@ -2315,7 +2671,6 @@ CONFIG_KEYBOARD_GPIO=m # CONFIG_KEYBOARD_LM8323 is not set # CONFIG_KEYBOARD_LM8333 is not set # CONFIG_KEYBOARD_MAX7359 is not set -# CONFIG_KEYBOARD_MCS is not set # CONFIG_KEYBOARD_MPR121 is not set # CONFIG_KEYBOARD_SNVS_PWRKEY is not set # CONFIG_KEYBOARD_IMX is not set @@ -2376,6 +2731,7 @@ CONFIG_JOYSTICK_PSXPAD_SPI_FF=y # CONFIG_JOYSTICK_QWIIC is not set # CONFIG_JOYSTICK_FSIA6B is not set # CONFIG_JOYSTICK_SENSEHAT is not set +# CONFIG_JOYSTICK_SEESAW is not set # CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set CONFIG_INPUT_MISC=y @@ -2423,7 +2779,7 @@ CONFIG_RMI4_F11=y CONFIG_RMI4_F12=y CONFIG_RMI4_F30=y # CONFIG_RMI4_F34 is not set -# CONFIG_RMI4_F3A is not set +CONFIG_RMI4_F3A=y # CONFIG_RMI4_F55 is not set # @@ -2432,6 +2788,7 @@ CONFIG_RMI4_F30=y CONFIG_SERIO=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_PCIPS2 is not set # CONFIG_SERIO_LIBPS2 is not set # CONFIG_SERIO_RAW is not set # CONFIG_SERIO_ALTERA_PS2 is not set @@ -2452,7 +2809,6 @@ CONFIG_VT=y CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_VT_CONSOLE_SLEEP=y -CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set @@ -2469,10 +2825,13 @@ CONFIG_SERIAL_8250_16550A_VARIANTS=y # CONFIG_SERIAL_8250_FINTEK is not set CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_DMA=y +# CONFIG_SERIAL_8250_PCI is not set +# CONFIG_SERIAL_8250_EXAR is not set CONFIG_SERIAL_8250_NR_UARTS=1 CONFIG_SERIAL_8250_RUNTIME_UARTS=0 CONFIG_SERIAL_8250_EXTENDED=y # CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_PCI1XXXX is not set CONFIG_SERIAL_8250_SHARE_IRQ=y # CONFIG_SERIAL_8250_DETECT_IRQ is not set # CONFIG_SERIAL_8250_RSA is not set @@ -2480,6 +2839,7 @@ CONFIG_SERIAL_8250_DWLIB=y CONFIG_SERIAL_8250_FSL=y CONFIG_SERIAL_8250_DW=y # CONFIG_SERIAL_8250_RT288X is not set +# CONFIG_SERIAL_8250_PERICOM is not set CONFIG_SERIAL_OF_PLATFORM=y # @@ -2496,6 +2856,7 @@ CONFIG_SERIAL_IMX_CONSOLE=y # CONFIG_SERIAL_UARTLITE is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set # CONFIG_SERIAL_SIFIVE is not set # CONFIG_SERIAL_SCCNXP is not set # CONFIG_SERIAL_SC16IS7XX is not set @@ -2503,6 +2864,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_ALTERA_UART is not set # CONFIG_SERIAL_XILINX_PS_UART is not set # CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_RP2 is not set # CONFIG_SERIAL_FSL_LPUART is not set # CONFIG_SERIAL_FSL_LINFLEXUART is not set # CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set @@ -2512,6 +2874,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_MCTRL_GPIO=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_N_GSM is not set +# CONFIG_NOZOMI is not set # CONFIG_NULL_TTY is not set # CONFIG_HVC_DCC is not set CONFIG_SERIAL_DEV_BUS=y @@ -2528,6 +2891,8 @@ CONFIG_HW_RANDOM_OPTEE=m # CONFIG_HW_RANDOM_CCTRNG is not set # CONFIG_HW_RANDOM_XIPHERA is not set CONFIG_HW_RANDOM_ARM_SMCCC_TRNG=m +# CONFIG_HW_RANDOM_CN10K is not set +# CONFIG_APPLICOM is not set CONFIG_DEVMEM=y CONFIG_DEVPORT=y # CONFIG_TCG_TPM is not set @@ -2540,7 +2905,6 @@ CONFIG_DEVPORT=y # CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_COMPAT=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=m @@ -2566,6 +2930,25 @@ CONFIG_I2C_ALGOBIT=m # I2C Hardware Bus support # +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_NVIDIA_GPU is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + # # I2C system bus drivers (mostly embedded / system-on-chip) # @@ -2574,6 +2957,7 @@ CONFIG_I2C_ALGOBIT=m CONFIG_I2C_DESIGNWARE_CORE=y # CONFIG_I2C_DESIGNWARE_SLAVE is not set CONFIG_I2C_DESIGNWARE_PLATFORM=y +# CONFIG_I2C_DESIGNWARE_PCI is not set # CONFIG_I2C_EMEV2 is not set # CONFIG_I2C_GPIO is not set # CONFIG_I2C_HISI is not set @@ -2584,6 +2968,7 @@ CONFIG_I2C_IMX_LPI2C=y # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_RK3X is not set # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_THUNDERX is not set # CONFIG_I2C_XILINX is not set # @@ -2591,6 +2976,7 @@ CONFIG_I2C_IMX_LPI2C=y # # CONFIG_I2C_DIOLAN_U2C is not set # CONFIG_I2C_CP2615 is not set +# CONFIG_I2C_PCI1XXXX is not set # CONFIG_I2C_ROBOTFUZZ_OSIF is not set # CONFIG_I2C_TAOS_EVM is not set # CONFIG_I2C_TINY_USB is not set @@ -2626,6 +3012,7 @@ CONFIG_SPI_BITBANG=y # CONFIG_SPI_CADENCE is not set # CONFIG_SPI_CADENCE_QUADSPI is not set # CONFIG_SPI_CADENCE_XSPI is not set +# CONFIG_SPI_CH341 is not set # CONFIG_SPI_DESIGNWARE is not set # CONFIG_SPI_FSL_LPSPI is not set # CONFIG_SPI_FSL_QUADSPI is not set @@ -2636,11 +3023,13 @@ CONFIG_SPI_IMX=y # CONFIG_SPI_MICROCHIP_CORE is not set # CONFIG_SPI_MICROCHIP_CORE_QSPI is not set # CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PCI1XXXX is not set CONFIG_SPI_PL022=y # CONFIG_SPI_SC18IS602 is not set # CONFIG_SPI_SIFIVE is not set # CONFIG_SPI_SN_F_OSPI is not set # CONFIG_SPI_MXIC is not set +# CONFIG_SPI_THUNDERX is not set # CONFIG_SPI_XCOMM is not set # CONFIG_SPI_XILINX is not set # CONFIG_SPI_ZYNQMP_GQSPI is not set @@ -2670,10 +3059,7 @@ CONFIG_PPS=y # CONFIG_PPS_CLIENT_KTIMER is not set # CONFIG_PPS_CLIENT_LDISC is not set # CONFIG_PPS_CLIENT_GPIO is not set - -# -# PPS generators support -# +# CONFIG_PPS_GENERATOR is not set # # PTP clock support @@ -2692,6 +3078,7 @@ CONFIG_PINMUX=y CONFIG_GENERIC_PINMUX_FUNCTIONS=y CONFIG_PINCONF=y # CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AW9523 is not set # CONFIG_PINCTRL_CY8C95X0 is not set # CONFIG_PINCTRL_MCP23S08 is not set # CONFIG_PINCTRL_MICROCHIP_SGPIO is not set @@ -2709,9 +3096,8 @@ CONFIG_PINCTRL_IMX8QM=y CONFIG_PINCTRL_IMX8QXP=y # CONFIG_PINCTRL_IMX8DXL is not set # CONFIG_PINCTRL_IMX8ULP is not set -# CONFIG_PINCTRL_IMXRT1050 is not set +# CONFIG_PINCTRL_IMX91 is not set # CONFIG_PINCTRL_IMX93 is not set -# CONFIG_PINCTRL_IMXRT1170 is not set # # Renesas pinctrl drivers @@ -2745,6 +3131,7 @@ CONFIG_GPIO_IMX_SCU=y # CONFIG_GPIO_MB86S7X is not set CONFIG_GPIO_MXC=y # CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_POLARFIRE_SOC is not set # CONFIG_GPIO_SIFIVE is not set # CONFIG_GPIO_SYSCON is not set CONFIG_GPIO_VF610=y @@ -2772,9 +3159,19 @@ CONFIG_GPIO_VF610=y # MFD GPIO expanders # # CONFIG_GPIO_ARIZONA is not set +# CONFIG_GPIO_CROS_EC is not set # CONFIG_GPIO_WM8994 is not set # end of MFD GPIO expanders +# +# PCI GPIO expanders +# +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_PCI_IDIO_16 is not set +# CONFIG_GPIO_PCIE_IDIO_24 is not set +# CONFIG_GPIO_RDC321X is not set +# end of PCI GPIO expanders + # # SPI GPIO expanders # @@ -2789,6 +3186,7 @@ CONFIG_GPIO_VF610=y # # USB GPIO expanders # +# CONFIG_GPIO_MPSSE is not set # end of USB GPIO expanders # @@ -2800,9 +3198,15 @@ CONFIG_GPIO_VF610=y # CONFIG_GPIO_SIM is not set # end of Virtual GPIO drivers +# +# GPIO Debugging utilities +# +# CONFIG_GPIO_SLOPPY_LOGIC_ANALYZER is not set +# CONFIG_GPIO_VIRTUSER is not set +# end of GPIO Debugging utilities + # CONFIG_W1 is not set CONFIG_POWER_RESET=y -# CONFIG_POWER_RESET_BRCMSTB is not set CONFIG_POWER_RESET_GPIO=y CONFIG_POWER_RESET_GPIO_RESTART=y # CONFIG_POWER_RESET_LTC2952 is not set @@ -2813,6 +3217,7 @@ CONFIG_POWER_RESET_SYSCON=y # CONFIG_POWER_RESET_SYSCON_POWEROFF is not set # CONFIG_SYSCON_REBOOT_MODE is not set # CONFIG_NVMEM_REBOOT_MODE is not set +# CONFIG_POWER_SEQUENCING is not set CONFIG_POWER_SUPPLY=y # CONFIG_POWER_SUPPLY_DEBUG is not set CONFIG_POWER_SUPPLY_HWMON=y @@ -2831,6 +3236,7 @@ CONFIG_POWER_SUPPLY_HWMON=y # CONFIG_BATTERY_BQ27XXX is not set # CONFIG_BATTERY_MAX17040 is not set # CONFIG_BATTERY_MAX17042 is not set +# CONFIG_BATTERY_MAX1720X is not set # CONFIG_CHARGER_MAX8903 is not set # CONFIG_CHARGER_LP8727 is not set # CONFIG_CHARGER_GPIO is not set @@ -2856,9 +3262,11 @@ CONFIG_POWER_SUPPLY_HWMON=y # CONFIG_CHARGER_RT9471 is not set # CONFIG_CHARGER_CROS_USBPD is not set # CONFIG_CHARGER_CROS_PCHG is not set +# CONFIG_FUEL_GAUGE_STC3117 is not set # CONFIG_CHARGER_UCS1002 is not set # CONFIG_CHARGER_BD99954 is not set # CONFIG_BATTERY_UG3105 is not set +# CONFIG_FUEL_GAUGE_MM8013 is not set CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set @@ -2868,7 +3276,6 @@ CONFIG_HWMON=y # CONFIG_SENSORS_AD7314 is not set # CONFIG_SENSORS_AD7414 is not set # CONFIG_SENSORS_AD7418 is not set -# CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set # CONFIG_SENSORS_ADM1029 is not set @@ -2885,17 +3292,22 @@ CONFIG_HWMON=y # CONFIG_SENSORS_AQUACOMPUTER_D5NEXT is not set # CONFIG_SENSORS_AS370 is not set # CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ASUS_ROG_RYUJIN is not set # CONFIG_SENSORS_AXI_FAN_CONTROL is not set CONFIG_SENSORS_ARM_SCPI=y # CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_CHIPCAP2 is not set # CONFIG_SENSORS_CORSAIR_CPRO is not set # CONFIG_SENSORS_CORSAIR_PSU is not set +# CONFIG_SENSORS_CROS_EC is not set # CONFIG_SENSORS_DS620 is not set # CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_F71882FG is not set # CONFIG_SENSORS_F75375S is not set # CONFIG_SENSORS_FTSTEUTATES is not set +# CONFIG_SENSORS_GIGABYTE_WATERFORCE is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_G760A is not set @@ -2903,15 +3315,19 @@ CONFIG_SENSORS_ARM_SCPI=y CONFIG_SENSORS_GPIO_FAN=m # CONFIG_SENSORS_HIH6130 is not set # CONFIG_SENSORS_HS3001 is not set +# CONFIG_SENSORS_HTU31 is not set # CONFIG_SENSORS_IIO_HWMON is not set +# CONFIG_SENSORS_ISL28022 is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWERZ is not set # CONFIG_SENSORS_POWR1220 is not set # CONFIG_SENSORS_LINEAGE is not set # CONFIG_SENSORS_LTC2945 is not set # CONFIG_SENSORS_LTC2947_I2C is not set # CONFIG_SENSORS_LTC2947_SPI is not set # CONFIG_SENSORS_LTC2990 is not set +# CONFIG_SENSORS_LTC2991 is not set # CONFIG_SENSORS_LTC2992 is not set # CONFIG_SENSORS_LTC4151 is not set # CONFIG_SENSORS_LTC4215 is not set @@ -2919,6 +3335,7 @@ CONFIG_SENSORS_GPIO_FAN=m # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4260 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LTC4282 is not set # CONFIG_SENSORS_MAX1111 is not set # CONFIG_SENSORS_MAX127 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -2932,7 +3349,6 @@ CONFIG_SENSORS_GPIO_FAN=m # CONFIG_SENSORS_MAX6620 is not set # CONFIG_SENSORS_MAX6621 is not set # CONFIG_SENSORS_MAX6639 is not set -# CONFIG_SENSORS_MAX6642 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MAX31790 is not set @@ -2964,14 +3380,17 @@ CONFIG_SENSORS_GPIO_FAN=m # CONFIG_SENSORS_NCT6683 is not set # CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NCT6775_I2C is not set +# CONFIG_SENSORS_NCT7363 is not set # CONFIG_SENSORS_NCT7802 is not set # CONFIG_SENSORS_NCT7904 is not set # CONFIG_SENSORS_NPCM7XX is not set # CONFIG_SENSORS_NZXT_KRAKEN2 is not set +# CONFIG_SENSORS_NZXT_KRAKEN3 is not set # CONFIG_SENSORS_NZXT_SMART2 is not set # CONFIG_SENSORS_OCC_P8_I2C is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_PMBUS is not set +# CONFIG_SENSORS_PT5161L is not set CONFIG_SENSORS_PWM_FAN=m # CONFIG_SENSORS_SBTSI is not set # CONFIG_SENSORS_SBRMI is not set @@ -2980,6 +3399,7 @@ CONFIG_SENSORS_PWM_FAN=m # CONFIG_SENSORS_SHT3x is not set # CONFIG_SENSORS_SHT4x is not set # CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_DME1737 is not set # CONFIG_SENSORS_EMC1403 is not set # CONFIG_SENSORS_EMC2103 is not set @@ -2999,6 +3419,7 @@ CONFIG_SENSORS_PWM_FAN=m # CONFIG_SENSORS_INA2XX is not set # CONFIG_SENSORS_INA238 is not set # CONFIG_SENSORS_INA3221 is not set +# CONFIG_SENSORS_SPD5118 is not set # CONFIG_SENSORS_TC74 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_TMP102 is not set @@ -3008,7 +3429,9 @@ CONFIG_SENSORS_PWM_FAN=m # CONFIG_SENSORS_TMP421 is not set # CONFIG_SENSORS_TMP464 is not set # CONFIG_SENSORS_TMP513 is not set +# CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_W83773G is not set # CONFIG_SENSORS_W83781D is not set # CONFIG_SENSORS_W83791D is not set @@ -3022,10 +3445,11 @@ CONFIG_SENSORS_PWM_FAN=m CONFIG_THERMAL=y # CONFIG_THERMAL_NETLINK is not set # CONFIG_THERMAL_STATISTICS is not set +# CONFIG_THERMAL_DEBUGFS is not set +# CONFIG_THERMAL_CORE_TESTING is not set CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 CONFIG_THERMAL_HWMON=y CONFIG_THERMAL_OF=y -# CONFIG_THERMAL_WRITABLE_TRIPS is not set CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y # CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set # CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set @@ -3059,6 +3483,7 @@ CONFIG_WATCHDOG_OPEN_TIMEOUT=0 # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set +# CONFIG_CROS_EC_WATCHDOG is not set # CONFIG_GPIO_WATCHDOG is not set # CONFIG_XILINX_WATCHDOG is not set # CONFIG_XILINX_WINDOW_WATCHDOG is not set @@ -3072,22 +3497,40 @@ CONFIG_IMX2_WDT=y # CONFIG_IMX_SC_WDT is not set # CONFIG_IMX7ULP_WDT is not set # CONFIG_ARM_SMC_WATCHDOG is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_I6300ESB_WDT is not set +# CONFIG_HP_WATCHDOG is not set # CONFIG_MEN_A21_WDT is not set +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + # # USB-based Watchdog Cards # # CONFIG_USBPCWATCHDOG is not set CONFIG_SSB_POSSIBLE=y CONFIG_SSB=m +CONFIG_SSB_SPROM=y CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_B43_PCI_BRIDGE=y CONFIG_SSB_SDIOHOST_POSSIBLE=y # CONFIG_SSB_SDIOHOST is not set +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_DRIVER_PCICORE=y # CONFIG_SSB_DRIVER_GPIO is not set CONFIG_BCMA_POSSIBLE=y CONFIG_BCMA=m CONFIG_BCMA_BLOCKIO=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +# CONFIG_BCMA_HOST_PCI is not set # CONFIG_BCMA_HOST_SOC is not set +# CONFIG_BCMA_DRIVER_PCI is not set # CONFIG_BCMA_DRIVER_GMAC_CMN is not set # CONFIG_BCMA_DRIVER_GPIO is not set # CONFIG_BCMA_DEBUG is not set @@ -3096,6 +3539,7 @@ CONFIG_BCMA_BLOCKIO=y # Multifunction device drivers # CONFIG_MFD_CORE=y +# CONFIG_MFD_ADP5585 is not set # CONFIG_MFD_ACT8945A is not set # CONFIG_MFD_AS3711 is not set # CONFIG_MFD_SMPRO is not set @@ -3124,17 +3568,22 @@ CONFIG_MFD_CROS_EC_DEV=y # CONFIG_MFD_MC13XXX_I2C is not set # CONFIG_MFD_MP2629 is not set # CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set # CONFIG_MFD_IQS62X is not set +# CONFIG_MFD_JANZ_CMODIO is not set # CONFIG_MFD_KEMPLD is not set # CONFIG_MFD_88PM800 is not set # CONFIG_MFD_88PM805 is not set # CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_88PM886_PMIC is not set # CONFIG_MFD_MAX14577 is not set # CONFIG_MFD_MAX77541 is not set # CONFIG_MFD_MAX77620 is not set # CONFIG_MFD_MAX77650 is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77705 is not set # CONFIG_MFD_MAX77714 is not set # CONFIG_MFD_MAX77843 is not set # CONFIG_MFD_MAX8907 is not set @@ -3151,8 +3600,8 @@ CONFIG_MFD_CROS_EC_DEV=y # CONFIG_MFD_VIPERBOARD is not set # CONFIG_MFD_NTXEC is not set # CONFIG_MFD_RETU is not set -# CONFIG_MFD_PCF50633 is not set # CONFIG_MFD_SY7636A is not set +# CONFIG_MFD_RDC321X is not set # CONFIG_MFD_RT4831 is not set # CONFIG_MFD_RT5033 is not set # CONFIG_MFD_RT5120 is not set @@ -3192,6 +3641,7 @@ CONFIG_MFD_SYSCON=y # CONFIG_MFD_LM3533 is not set # CONFIG_MFD_TC3589X is not set # CONFIG_MFD_TQMX86 is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_LOCHNAGAR is not set CONFIG_MFD_ARIZONA=m CONFIG_MFD_ARIZONA_I2C=m @@ -3209,12 +3659,16 @@ CONFIG_MFD_WM8994=y CONFIG_MFD_ROHM_BD718XX=y # CONFIG_MFD_ROHM_BD71828 is not set # CONFIG_MFD_ROHM_BD957XMUF is not set +# CONFIG_MFD_ROHM_BD96801 is not set # CONFIG_MFD_STPMIC1 is not set # CONFIG_MFD_STMFX is not set # CONFIG_MFD_ATC260X_I2C is not set # CONFIG_MFD_QCOM_PM8008 is not set +# CONFIG_MFD_CS40L50_I2C is not set +# CONFIG_MFD_CS40L50_SPI is not set # CONFIG_RAVE_SP_CORE is not set # CONFIG_MFD_INTEL_M10_BMC_SPI is not set +# CONFIG_MFD_QNAP_MCU is not set # CONFIG_MFD_RSMU_I2C is not set # CONFIG_MFD_RSMU_SPI is not set # end of Multifunction device drivers @@ -3224,6 +3678,7 @@ CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_NETLINK_EVENTS is not set # CONFIG_REGULATOR_88PG86X is not set # CONFIG_REGULATOR_ACT8865 is not set # CONFIG_REGULATOR_AD5398 is not set @@ -3248,6 +3703,7 @@ CONFIG_REGULATOR_GPIO=y # CONFIG_REGULATOR_LTC3589 is not set # CONFIG_REGULATOR_LTC3676 is not set # CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX77503 is not set # CONFIG_REGULATOR_MAX77857 is not set # CONFIG_REGULATOR_MAX8649 is not set # CONFIG_REGULATOR_MAX8660 is not set @@ -3264,6 +3720,7 @@ CONFIG_REGULATOR_GPIO=y # CONFIG_REGULATOR_MPQ7920 is not set # CONFIG_REGULATOR_MT6311 is not set # CONFIG_REGULATOR_PCA9450 is not set +# CONFIG_REGULATOR_PF9453 is not set # CONFIG_REGULATOR_PF8X00 is not set CONFIG_REGULATOR_PFUZE100=y # CONFIG_REGULATOR_PV88060 is not set @@ -3335,15 +3792,15 @@ CONFIG_IR_TTUSBIR=m CONFIG_RC_ATI_REMOTE=m # CONFIG_RC_LOOPBACK is not set CONFIG_RC_XBOX_DVD=m -CONFIG_CEC_CORE=y -CONFIG_CEC_NOTIFIER=y # # CEC support # CONFIG_MEDIA_CEC_SUPPORT=y # CONFIG_CEC_CH7322 is not set +# CONFIG_CEC_NXP_TDA9950 is not set # CONFIG_CEC_CROS_EC is not set +# CONFIG_USB_EXTRON_DA_HD_4K_PLUS_CEC is not set # CONFIG_USB_PULSE8_CEC is not set # CONFIG_USB_RAINSHADOW_CEC is not set # end of CEC support @@ -3393,7 +3850,6 @@ CONFIG_V4L2_ASYNC=m # Media controller options # CONFIG_MEDIA_CONTROLLER_DVB=y -CONFIG_MEDIA_CONTROLLER_REQUEST_API=y # end of Media controller options # @@ -3497,6 +3953,8 @@ CONFIG_DVB_USB_UMT_010=m CONFIG_DVB_USB_VP702X=m CONFIG_DVB_USB_VP7045=m CONFIG_SMS_USB_DRV=m +# CONFIG_DVB_TTUSB_BUDGET is not set +# CONFIG_DVB_TTUSB_DEC is not set # # Webcam, TV (analog/digital) USB devices @@ -3513,6 +3971,7 @@ CONFIG_VIDEO_EM28XX_RC=m # CONFIG_USB_AIRSPY is not set # CONFIG_USB_HACKRF is not set # CONFIG_USB_MSI2500 is not set +# CONFIG_MEDIA_PCI_SUPPORT is not set # CONFIG_RADIO_ADAPTERS is not set CONFIG_MEDIA_PLATFORM_DRIVERS=y # CONFIG_V4L_PLATFORM_DRIVERS is not set @@ -3569,6 +4028,10 @@ CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m # Microchip Technology, Inc. media platform drivers # +# +# Nuvoton media platform drivers +# + # # NVidia media platform drivers # @@ -3589,6 +4052,11 @@ CONFIG_VIDEO_IMX8_JPEG=m # Qualcomm media platform drivers # +# +# Raspberry Pi media platform drivers +# +# CONFIG_VIDEO_RP1_CFE is not set + # # Renesas media platform drivers # @@ -3617,6 +4085,7 @@ CONFIG_VIDEO_IMX8_JPEG=m # Verisilicon media platform drivers # CONFIG_VIDEO_HANTRO=m +CONFIG_VIDEO_HANTRO_HEVC_RFC=y CONFIG_VIDEO_HANTRO_IMX8M=y # @@ -3663,7 +4132,12 @@ CONFIG_MEDIA_ATTACH=y # CONFIG_VIDEO_IR_I2C=m CONFIG_VIDEO_CAMERA_SENSOR=y +# CONFIG_VIDEO_ALVIUM_CSI2 is not set # CONFIG_VIDEO_AR0521 is not set +# CONFIG_VIDEO_GC0308 is not set +# CONFIG_VIDEO_GC05A2 is not set +# CONFIG_VIDEO_GC08A3 is not set +# CONFIG_VIDEO_GC2145 is not set # CONFIG_VIDEO_HI556 is not set # CONFIG_VIDEO_HI846 is not set # CONFIG_VIDEO_HI847 is not set @@ -3672,6 +4146,7 @@ CONFIG_VIDEO_CAMERA_SENSOR=y # CONFIG_VIDEO_IMX219 is not set # CONFIG_VIDEO_IMX258 is not set # CONFIG_VIDEO_IMX274 is not set +# CONFIG_VIDEO_IMX283 is not set # CONFIG_VIDEO_IMX290 is not set # CONFIG_VIDEO_IMX296 is not set # CONFIG_VIDEO_IMX319 is not set @@ -3682,6 +4157,7 @@ CONFIG_VIDEO_CAMERA_SENSOR=y # CONFIG_VIDEO_IMX415 is not set # CONFIG_VIDEO_MT9M001 is not set # CONFIG_VIDEO_MT9M111 is not set +# CONFIG_VIDEO_MT9M114 is not set # CONFIG_VIDEO_MT9P031 is not set # CONFIG_VIDEO_MT9T112 is not set # CONFIG_VIDEO_MT9V011 is not set @@ -3707,6 +4183,7 @@ CONFIG_VIDEO_CAMERA_SENSOR=y # CONFIG_VIDEO_OV5675 is not set # CONFIG_VIDEO_OV5693 is not set # CONFIG_VIDEO_OV5695 is not set +# CONFIG_VIDEO_OV64A40 is not set # CONFIG_VIDEO_OV6650 is not set # CONFIG_VIDEO_OV7251 is not set # CONFIG_VIDEO_OV7640 is not set @@ -3725,10 +4202,16 @@ CONFIG_VIDEO_CAMERA_SENSOR=y # CONFIG_VIDEO_S5C73M3 is not set # CONFIG_VIDEO_S5K5BAF is not set # CONFIG_VIDEO_S5K6A3 is not set -# CONFIG_VIDEO_ST_VGXY61 is not set +# CONFIG_VIDEO_VGXY61 is not set # CONFIG_VIDEO_CCS is not set # CONFIG_VIDEO_ET8EK8 is not set +# +# Camera ISPs +# +# CONFIG_VIDEO_THP7312 is not set +# end of Camera ISPs + # # Lens drivers # @@ -3798,6 +4281,7 @@ CONFIG_VIDEO_SAA711X=m # CONFIG_VIDEO_TVP5150 is not set # CONFIG_VIDEO_TVP7002 is not set # CONFIG_VIDEO_TW2804 is not set +# CONFIG_VIDEO_TW9900 is not set # CONFIG_VIDEO_TW9903 is not set # CONFIG_VIDEO_TW9906 is not set # CONFIG_VIDEO_TW9910 is not set @@ -3858,6 +4342,8 @@ CONFIG_VIDEO_CX25840=m # CONFIG_VIDEO_DS90UB913 is not set # CONFIG_VIDEO_DS90UB953 is not set # CONFIG_VIDEO_DS90UB960 is not set +# CONFIG_VIDEO_MAX96714 is not set +# CONFIG_VIDEO_MAX96717 is not set # end of Video serializers and deserializers # @@ -4085,37 +4571,43 @@ CONFIG_DVB_SP2=m # # Graphics support # -CONFIG_VIDEO_CMDLINE=y -CONFIG_VIDEO_NOMODESET=y +CONFIG_VIDEO=y # CONFIG_AUXDISPLAY is not set CONFIG_DRM=y # CONFIG_DRM_DEBUG_MM is not set CONFIG_DRM_KMS_HELPER=y +# CONFIG_DRM_PANIC is not set # CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set # CONFIG_DRM_DEBUG_MODESET_LOCK is not set +CONFIG_DRM_CLIENT=y +CONFIG_DRM_CLIENT_LIB=y +CONFIG_DRM_CLIENT_SELECTION=y +CONFIG_DRM_CLIENT_SETUP=y + +# +# Supported DRM clients +# CONFIG_DRM_FBDEV_EMULATION=y CONFIG_DRM_FBDEV_OVERALLOC=100 # CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set +# CONFIG_DRM_CLIENT_LOG is not set +CONFIG_DRM_CLIENT_DEFAULT_FBDEV=y +CONFIG_DRM_CLIENT_DEFAULT="fbdev" +# end of Supported DRM clients + CONFIG_DRM_LOAD_EDID_FIRMWARE=y -CONFIG_DRM_DP_AUX_BUS=y +CONFIG_DRM_DISPLAY_DP_AUX_BUS=y CONFIG_DRM_DISPLAY_HELPER=y +CONFIG_DRM_BRIDGE_CONNECTOR=y +# CONFIG_DRM_DISPLAY_DP_AUX_CEC is not set +# CONFIG_DRM_DISPLAY_DP_AUX_CHARDEV is not set CONFIG_DRM_DISPLAY_DP_HELPER=y -CONFIG_DRM_DISPLAY_HDCP_HELPER=y +CONFIG_DRM_DISPLAY_HDMI_AUDIO_HELPER=y CONFIG_DRM_DISPLAY_HDMI_HELPER=y -# CONFIG_DRM_DP_AUX_CHARDEV is not set -# CONFIG_DRM_DP_CEC is not set +CONFIG_DRM_DISPLAY_HDMI_STATE_HELPER=y CONFIG_DRM_GEM_DMA_HELPER=y CONFIG_DRM_SCHED=y -# -# I2C encoder or helper chips -# -# CONFIG_DRM_I2C_CH7006 is not set -# CONFIG_DRM_I2C_SIL164 is not set -# CONFIG_DRM_I2C_NXP_TDA998X is not set -# CONFIG_DRM_I2C_NXP_TDA9950 is not set -# end of I2C encoder or helper chips - # # ARM devices # @@ -4124,9 +4616,17 @@ CONFIG_DRM_SCHED=y # CONFIG_DRM_KOMEDA is not set # end of ARM devices +# CONFIG_DRM_RADEON is not set +# CONFIG_DRM_AMDGPU is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_XE is not set # CONFIG_DRM_VGEM is not set # CONFIG_DRM_VKMS is not set +# CONFIG_DRM_VMWGFX is not set # CONFIG_DRM_UDL is not set +# CONFIG_DRM_AST is not set +# CONFIG_DRM_MGAG200 is not set +# CONFIG_DRM_QXL is not set CONFIG_DRM_PANEL=y # @@ -4136,12 +4636,9 @@ CONFIG_DRM_PANEL=y # CONFIG_DRM_PANEL_ARM_VERSATILE is not set # CONFIG_DRM_PANEL_AUO_A030JTN01 is not set # CONFIG_DRM_PANEL_LVDS is not set -CONFIG_DRM_PANEL_SIMPLE=y -CONFIG_DRM_PANEL_EDP=y # CONFIG_DRM_PANEL_ILITEK_IL9322 is not set # CONFIG_DRM_PANEL_ILITEK_ILI9341 is not set # CONFIG_DRM_PANEL_INNOLUX_EJ030NA is not set -# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set # CONFIG_DRM_PANEL_LG_LB035Q02 is not set # CONFIG_DRM_PANEL_LG_LG4573 is not set # CONFIG_DRM_PANEL_NEC_NL8048HL11 is not set @@ -4149,17 +4646,21 @@ CONFIG_DRM_PANEL_EDP=y # CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set # CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set # CONFIG_DRM_PANEL_ORISETECH_OTA5601A is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set # CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20 is not set # CONFIG_DRM_PANEL_SAMSUNG_DB7430 is not set +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6D27A1 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6D7AA0 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set -# CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set # CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set # CONFIG_DRM_PANEL_SEIKO_43WVF1G is not set # CONFIG_DRM_PANEL_SHARP_LS037V7DW01 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7701 is not set # CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set # CONFIG_DRM_PANEL_SONY_ACX565AKM is not set +CONFIG_DRM_PANEL_EDP=y +CONFIG_DRM_PANEL_SIMPLE=y # CONFIG_DRM_PANEL_TPO_TD028TTEC1 is not set # CONFIG_DRM_PANEL_TPO_TD043MTEA1 is not set # CONFIG_DRM_PANEL_TPO_TPG110 is not set @@ -4176,6 +4677,8 @@ CONFIG_DRM_PANEL_BRIDGE=y # CONFIG_DRM_CHRONTEL_CH7033 is not set # CONFIG_DRM_DISPLAY_CONNECTOR is not set CONFIG_DRM_FSL_LDB=m +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_ITE_IT6263 is not set # CONFIG_DRM_ITE_IT6505 is not set # CONFIG_DRM_LONTIUM_LT8912B is not set # CONFIG_DRM_LONTIUM_LT9211 is not set @@ -4200,6 +4703,7 @@ CONFIG_DRM_FSL_LDB=m # CONFIG_DRM_TOSHIBA_TC358768 is not set # CONFIG_DRM_TOSHIBA_TC358775 is not set # CONFIG_DRM_TI_DLPC3433 is not set +# CONFIG_DRM_TI_TDP158 is not set # CONFIG_DRM_TI_TFP410 is not set # CONFIG_DRM_TI_SN65DSI83 is not set # CONFIG_DRM_TI_SN65DSI86 is not set @@ -4210,29 +4714,29 @@ CONFIG_DRM_FSL_LDB=m # CONFIG_DRM_I2C_ADV7511 is not set # CONFIG_DRM_CDNS_DSI is not set # CONFIG_DRM_CDNS_MHDP8546 is not set -CONFIG_DRM_CDNS_MHDP=y -CONFIG_DRM_CDNS_HDMI=y -CONFIG_DRM_CDNS_DP=y -CONFIG_DRM_CDNS_AUDIO=y -CONFIG_DRM_CDNS_HDMI_HDCP=y -CONFIG_DRM_CDNS_HDMI_CEC=y +CONFIG_DRM_CDNS_MHDP8501=y +# CONFIG_DRM_IMX8MP_DW_HDMI_BRIDGE is not set +# CONFIG_DRM_IMX8MP_HDMI_PVI is not set # CONFIG_DRM_IMX8QM_LDB is not set # CONFIG_DRM_IMX8QXP_LDB is not set # CONFIG_DRM_IMX8QXP_PIXEL_COMBINER is not set # CONFIG_DRM_IMX8QXP_PIXEL_LINK is not set # CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI is not set +# CONFIG_DRM_IMX93_MIPI_DSI is not set # end of Display Interface Bridges CONFIG_DRM_IMX_DCSS=y # CONFIG_DRM_IMX_LCDC is not set -CONFIG_DRM_IMX_CDNS_MHDP=y CONFIG_DRM_ETNAVIV=y CONFIG_DRM_ETNAVIV_THERMAL=y +# CONFIG_DRM_HISI_HIBMC is not set # CONFIG_DRM_HISI_KIRIN is not set # CONFIG_DRM_LOGICVC is not set # CONFIG_DRM_MXSFB is not set # CONFIG_DRM_IMX_LCDIF is not set # CONFIG_DRM_ARCPGU is not set +# CONFIG_DRM_BOCHS is not set +# CONFIG_DRM_CIRRUS_QEMU is not set # CONFIG_DRM_GM12U320 is not set # CONFIG_DRM_PANEL_MIPI_DBI is not set # CONFIG_DRM_SIMPLEDRM is not set @@ -4243,49 +4747,72 @@ CONFIG_DRM_ETNAVIV_THERMAL=y # CONFIG_TINYDRM_ILI9486 is not set # CONFIG_TINYDRM_MI0283QT is not set # CONFIG_TINYDRM_REPAPER is not set +# CONFIG_TINYDRM_SHARP_MEMORY is not set # CONFIG_TINYDRM_ST7586 is not set # CONFIG_TINYDRM_ST7735R is not set # CONFIG_DRM_PL111 is not set # CONFIG_DRM_LIMA is not set # CONFIG_DRM_PANFROST is not set +# CONFIG_DRM_PANTHOR is not set # CONFIG_DRM_TIDSS is not set # CONFIG_DRM_GUD is not set # CONFIG_DRM_SSD130X is not set -# CONFIG_DRM_LEGACY is not set +# CONFIG_DRM_POWERVR is not set +# CONFIG_DRM_WERROR is not set CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y # # Frame buffer Devices # CONFIG_FB=y -CONFIG_FB_ARMCLCD=y +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set # CONFIG_FB_IMX is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set # CONFIG_FB_OPENCORES is not set # CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set # CONFIG_FB_SMSCUFX is not set # CONFIG_FB_UDL is not set # CONFIG_FB_IBM_GXT4500 is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set # CONFIG_FB_SIMPLE is not set # CONFIG_FB_SSD1307 is not set +# CONFIG_FB_SM712 is not set CONFIG_FB_CORE=y CONFIG_FB_NOTIFY=y # CONFIG_FIRMWARE_EDID is not set CONFIG_FB_DEVICE=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y CONFIG_FB_SYS_FILLRECT=y CONFIG_FB_SYS_COPYAREA=y CONFIG_FB_SYS_IMAGEBLIT=y # CONFIG_FB_FOREIGN_ENDIAN is not set -CONFIG_FB_SYS_FOPS=y +CONFIG_FB_SYSMEM_FOPS=y CONFIG_FB_DEFERRED_IO=y CONFIG_FB_DMAMEM_HELPERS=y -CONFIG_FB_IOMEM_FOPS=y -CONFIG_FB_SYSMEM_HELPERS=y -CONFIG_FB_SYSMEM_HELPERS_DEFERRED=y +CONFIG_FB_DMAMEM_HELPERS_DEFERRED=y CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_TILEBLITTING is not set # end of Frame buffer Devices @@ -4296,14 +4823,17 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_LCD_CLASS_DEVICE is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y # CONFIG_BACKLIGHT_KTD253 is not set +# CONFIG_BACKLIGHT_KTD2801 is not set # CONFIG_BACKLIGHT_KTZ8866 is not set # CONFIG_BACKLIGHT_PWM is not set # CONFIG_BACKLIGHT_QCOM_WLED is not set # CONFIG_BACKLIGHT_ADP8860 is not set # CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3509 is not set # CONFIG_BACKLIGHT_LM3630A is not set # CONFIG_BACKLIGHT_LM3639 is not set # CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_MP3309C is not set # CONFIG_BACKLIGHT_GPIO is not set # CONFIG_BACKLIGHT_LV5207LP is not set # CONFIG_BACKLIGHT_BD6107 is not set @@ -4348,10 +4878,10 @@ CONFIG_SND_MAX_CARDS=32 # CONFIG_SND_SUPPORT_OLD_API is not set CONFIG_SND_PROC_FS=y CONFIG_SND_VERBOSE_PROCFS=y -# CONFIG_SND_VERBOSE_PRINTK is not set CONFIG_SND_CTL_FAST_LOOKUP=y # CONFIG_SND_DEBUG is not set # CONFIG_SND_CTL_INPUT_VALIDATION is not set +# CONFIG_SND_UTIMER is not set # CONFIG_SND_SEQUENCER is not set CONFIG_SND_DRIVERS=y # CONFIG_SND_DUMMY is not set @@ -4361,6 +4891,7 @@ CONFIG_SND_DRIVERS=y # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_SERIAL_GENERIC is not set # CONFIG_SND_MPU401 is not set +# CONFIG_SND_PCI is not set # # HD-Audio @@ -4406,7 +4937,6 @@ CONFIG_SND_IMX_SOC=y # CONFIG_SND_SOC_IMX_ES8328=y CONFIG_SND_SOC_IMX_SGTL5000=y -CONFIG_SND_SOC_IMX_SPDIF=y CONFIG_SND_SOC_FSL_ASOC_CARD=y CONFIG_SND_SOC_IMX_AUDMIX=y CONFIG_SND_SOC_IMX_HDMI=y @@ -4415,8 +4945,15 @@ CONFIG_SND_SOC_IMX_CARD=y # CONFIG_SND_SOC_CHV3_I2S is not set # CONFIG_SND_I2S_HI6210_I2S is not set + +# +# SoC Audio for Loongson CPUs +# +# end of SoC Audio for Loongson CPUs + # CONFIG_SND_SOC_IMG is not set # CONFIG_SND_SOC_MTK_BTCVSD is not set +CONFIG_SND_SOC_SDCA_OPTIONAL=y # CONFIG_SND_SOC_SOF_TOPLEVEL is not set # @@ -4437,6 +4974,7 @@ CONFIG_SND_SOC_WM_HUBS=y # CONFIG_SND_SOC_AC97_CODEC is not set # CONFIG_SND_SOC_ADAU1372_I2C is not set # CONFIG_SND_SOC_ADAU1372_SPI is not set +# CONFIG_SND_SOC_ADAU1373 is not set # CONFIG_SND_SOC_ADAU1701 is not set # CONFIG_SND_SOC_ADAU1761_I2C is not set # CONFIG_SND_SOC_ADAU1761_SPI is not set @@ -4449,6 +4987,7 @@ CONFIG_SND_SOC_WM_HUBS=y CONFIG_SND_SOC_AK4458=y # CONFIG_SND_SOC_AK4554 is not set # CONFIG_SND_SOC_AK4613 is not set +# CONFIG_SND_SOC_AK4619 is not set # CONFIG_SND_SOC_AK4642 is not set # CONFIG_SND_SOC_AK5386 is not set CONFIG_SND_SOC_AK5558=y @@ -4456,7 +4995,11 @@ CONFIG_SND_SOC_AK5558=y # CONFIG_SND_SOC_AUDIO_IIO_AUX is not set # CONFIG_SND_SOC_AW8738 is not set # CONFIG_SND_SOC_AW88395 is not set +# CONFIG_SND_SOC_AW88166 is not set # CONFIG_SND_SOC_AW88261 is not set +# CONFIG_SND_SOC_AW88081 is not set +# CONFIG_SND_SOC_AW87390 is not set +# CONFIG_SND_SOC_AW88399 is not set # CONFIG_SND_SOC_BD28623 is not set # CONFIG_SND_SOC_BT_SCO is not set # CONFIG_SND_SOC_CHV3_CODEC is not set @@ -4478,6 +5021,7 @@ CONFIG_SND_SOC_AK5558=y # CONFIG_SND_SOC_CS42L56 is not set # CONFIG_SND_SOC_CS42L73 is not set # CONFIG_SND_SOC_CS42L83 is not set +# CONFIG_SND_SOC_CS42L84 is not set # CONFIG_SND_SOC_CS4234 is not set # CONFIG_SND_SOC_CS4265 is not set # CONFIG_SND_SOC_CS4270 is not set @@ -4488,13 +5032,16 @@ CONFIG_SND_SOC_AK5558=y # CONFIG_SND_SOC_CS4341 is not set # CONFIG_SND_SOC_CS4349 is not set # CONFIG_SND_SOC_CS53L30 is not set +# CONFIG_SND_SOC_CS530X_I2C is not set # CONFIG_SND_SOC_CX2072X is not set # CONFIG_SND_SOC_DA7213 is not set # CONFIG_SND_SOC_DMIC is not set CONFIG_SND_SOC_HDMI_CODEC=y CONFIG_SND_SOC_ES7134=y # CONFIG_SND_SOC_ES7241 is not set +# CONFIG_SND_SOC_ES8311 is not set # CONFIG_SND_SOC_ES8316 is not set +# CONFIG_SND_SOC_ES8323 is not set # CONFIG_SND_SOC_ES8326 is not set CONFIG_SND_SOC_ES8328=y CONFIG_SND_SOC_ES8328_I2C=y @@ -4503,7 +5050,6 @@ CONFIG_SND_SOC_ES8328_SPI=y # CONFIG_SND_SOC_HDA is not set # CONFIG_SND_SOC_ICS43432 is not set # CONFIG_SND_SOC_IDT821034 is not set -# CONFIG_SND_SOC_INNO_RK3036 is not set # CONFIG_SND_SOC_MAX98088 is not set # CONFIG_SND_SOC_MAX98090 is not set # CONFIG_SND_SOC_MAX98357A is not set @@ -4530,17 +5076,19 @@ CONFIG_SND_SOC_ES8328_SPI=y # CONFIG_SND_SOC_PCM5102A is not set # CONFIG_SND_SOC_PCM512x_I2C is not set # CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_PCM6240 is not set # CONFIG_SND_SOC_PEB2466 is not set -# CONFIG_SND_SOC_RK3328 is not set # CONFIG_SND_SOC_RT5616 is not set # CONFIG_SND_SOC_RT5631 is not set # CONFIG_SND_SOC_RT5640 is not set # CONFIG_SND_SOC_RT5659 is not set # CONFIG_SND_SOC_RT9120 is not set +# CONFIG_SND_SOC_RTQ9128 is not set CONFIG_SND_SOC_SGTL5000=y # CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set # CONFIG_SND_SOC_SIMPLE_MUX is not set # CONFIG_SND_SOC_SMA1303 is not set +# CONFIG_SND_SOC_SMA1307 is not set CONFIG_SND_SOC_SPDIF=y # CONFIG_SND_SOC_SRC4XXX_I2C is not set # CONFIG_SND_SOC_SSM2305 is not set @@ -4579,6 +5127,7 @@ CONFIG_SND_SOC_TLV320AIC31XX=y # CONFIG_SND_SOC_TSCS42XX is not set # CONFIG_SND_SOC_TSCS454 is not set # CONFIG_SND_SOC_UDA1334 is not set +# CONFIG_SND_SOC_UDA1342 is not set # CONFIG_SND_SOC_WM8510 is not set # CONFIG_SND_SOC_WM8523 is not set CONFIG_SND_SOC_WM8524=y @@ -4609,6 +5158,7 @@ CONFIG_SND_SOC_WM8994=y # CONFIG_SND_SOC_ZL38060 is not set # CONFIG_SND_SOC_MAX9759 is not set # CONFIG_SND_SOC_MT6351 is not set +# CONFIG_SND_SOC_MT6357 is not set # CONFIG_SND_SOC_MT6358 is not set # CONFIG_SND_SOC_MT6660 is not set # CONFIG_SND_SOC_NAU8315 is not set @@ -4617,6 +5167,8 @@ CONFIG_SND_SOC_WM8994=y # CONFIG_SND_SOC_NAU8821 is not set # CONFIG_SND_SOC_NAU8822 is not set # CONFIG_SND_SOC_NAU8824 is not set +# CONFIG_SND_SOC_NTP8918 is not set +# CONFIG_SND_SOC_NTP8835 is not set # CONFIG_SND_SOC_TPA6130A2 is not set # CONFIG_SND_SOC_LPASS_WSA_MACRO is not set # CONFIG_SND_SOC_LPASS_VA_MACRO is not set @@ -4672,12 +5224,14 @@ CONFIG_HID_EZKEY=y # CONFIG_HID_GFRM is not set # CONFIG_HID_GLORIOUS is not set # CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GOODIX_SPI is not set # CONFIG_HID_GOOGLE_HAMMER is not set # CONFIG_HID_GOOGLE_STADIA_FF is not set # CONFIG_HID_VIVALDI is not set # CONFIG_HID_GT683R is not set # CONFIG_HID_KEYTOUCH is not set CONFIG_HID_KYE=y +# CONFIG_HID_KYSONA is not set # CONFIG_HID_UCLOGIC is not set # CONFIG_HID_WALTOP is not set # CONFIG_HID_VIEWSONIC is not set @@ -4691,7 +5245,6 @@ CONFIG_HID_TWINHAN=y CONFIG_HID_KENSINGTON=y # CONFIG_HID_LCPOWER is not set # CONFIG_HID_LED is not set -CONFIG_HID_LENOVO=y # CONFIG_HID_LETSKETCH is not set CONFIG_HID_LOGITECH=y CONFIG_HID_LOGITECH_DJ=y @@ -4714,7 +5267,6 @@ CONFIG_NINTENDO_FF=y # CONFIG_HID_NTRIG is not set # CONFIG_HID_NVIDIA_SHIELD is not set CONFIG_HID_ORTEK=y -CONFIG_HID_OUYA=y CONFIG_HID_PANTHERLORD=y CONFIG_PANTHERLORD_FF=y CONFIG_HID_PENMOUNT=y @@ -4752,6 +5304,7 @@ CONFIG_HID_TOPSEED=y # CONFIG_HID_U2FZERO is not set # CONFIG_HID_WACOM is not set CONFIG_HID_WIIMOTE=m +# CONFIG_HID_WINWING is not set CONFIG_HID_XINMO=y # CONFIG_HID_ZEROPLUS is not set CONFIG_HID_ZYDACRON=y @@ -4766,6 +5319,11 @@ CONFIG_HID_ZYDACRON=y # # end of HID-BPF support +CONFIG_I2C_HID=y +# CONFIG_I2C_HID_OF is not set +# CONFIG_I2C_HID_OF_ELAN is not set +# CONFIG_I2C_HID_OF_GOODIX is not set + # # USB HID support # @@ -4774,10 +5332,6 @@ CONFIG_USB_HID=y CONFIG_USB_HIDDEV=y # end of USB HID support -CONFIG_I2C_HID=y -# CONFIG_I2C_HID_OF is not set -# CONFIG_I2C_HID_OF_ELAN is not set -# CONFIG_I2C_HID_OF_GOODIX is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_SUPPORT=y CONFIG_USB_COMMON=y @@ -4786,6 +5340,7 @@ CONFIG_USB_COMMON=y # CONFIG_USB_CONN_GPIO is not set CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB=y +# CONFIG_USB_PCI is not set CONFIG_USB_ANNOUNCE_NEW_DEVICES=y # @@ -4800,6 +5355,7 @@ CONFIG_USB_OTG=y # CONFIG_USB_OTG_FSM is not set # CONFIG_USB_LEDS_TRIGGER_USBPORT is not set CONFIG_USB_AUTOSUSPEND_DELAY=2 +CONFIG_USB_DEFAULT_AUTHORIZATION_MODE=1 CONFIG_USB_MON=m # @@ -4808,7 +5364,6 @@ CONFIG_USB_MON=m # CONFIG_USB_C67X00_HCD is not set CONFIG_USB_XHCI_HCD=y # CONFIG_USB_XHCI_DBGCAP is not set -# CONFIG_USB_XHCI_PCI_RENESAS is not set CONFIG_USB_XHCI_PLATFORM=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y @@ -4835,11 +5390,7 @@ CONFIG_USB_ACM=m # CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may -# - -# -# also be needed; see USB_STORAGE Help for more info +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; see USB_STORAGE Help for more info # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set @@ -4978,7 +5529,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_HSIC_USB4604 is not set # CONFIG_USB_LINK_LAYER_TEST is not set # CONFIG_USB_CHAOSKEY is not set -# CONFIG_USB_ONBOARD_HUB is not set +# CONFIG_USB_ONBOARD_DEV is not set # # USB Physical Layer drivers @@ -5056,6 +5607,7 @@ CONFIG_MMC_BLOCK_MINORS=32 # CONFIG_MMC_ARMMMCI is not set CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_IO_ACCESSORS=y +# CONFIG_MMC_SDHCI_PCI is not set CONFIG_MMC_SDHCI_PLTFM=y # CONFIG_MMC_SDHCI_OF_ARASAN is not set # CONFIG_MMC_SDHCI_OF_AT91 is not set @@ -5066,13 +5618,17 @@ CONFIG_MMC_SDHCI_ESDHC_IMX=y # CONFIG_MMC_SDHCI_F_SDH30 is not set # CONFIG_MMC_SDHCI_MILBEAUT is not set # CONFIG_MMC_MXC is not set +# CONFIG_MMC_TIFM_SD is not set CONFIG_MMC_SPI=y +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set # CONFIG_MMC_DW is not set # CONFIG_MMC_VUB300 is not set # CONFIG_MMC_USHC is not set # CONFIG_MMC_USDHI6ROL0 is not set CONFIG_MMC_CQHCI=y # CONFIG_MMC_HSQ is not set +# CONFIG_MMC_TOSHIBA_PCI is not set # CONFIG_MMC_MTK is not set # CONFIG_MMC_SDHCI_XENON is not set # CONFIG_SCSI_UFSHCD is not set @@ -5092,6 +5648,7 @@ CONFIG_LEDS_CLASS_MULTICOLOR=y # CONFIG_LEDS_BCM6328 is not set # CONFIG_LEDS_BCM6358 is not set # CONFIG_LEDS_CR0014114 is not set +# CONFIG_LEDS_CROS_EC is not set # CONFIG_LEDS_EL15203000 is not set # CONFIG_LEDS_LM3530 is not set # CONFIG_LEDS_LM3532 is not set @@ -5104,6 +5661,7 @@ CONFIG_LEDS_GPIO=y # CONFIG_LEDS_LP50XX is not set # CONFIG_LEDS_LP55XX_COMMON is not set # CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_LP8864 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA963X is not set # CONFIG_LEDS_PCA995X is not set @@ -5128,6 +5686,7 @@ CONFIG_LEDS_SYSCON=y # CONFIG_LEDS_USER is not set # CONFIG_LEDS_SPI_BYTE is not set # CONFIG_LEDS_LM3697 is not set +# CONFIG_LEDS_ST1202 is not set # # Flash and Torch LED drivers @@ -5139,11 +5698,14 @@ CONFIG_LEDS_SYSCON=y # CONFIG_LEDS_RT4505 is not set # CONFIG_LEDS_RT8515 is not set # CONFIG_LEDS_SGM3140 is not set +# CONFIG_LEDS_SY7802 is not set # # RGB LED drivers # # CONFIG_LEDS_GROUP_MULTICOLOR is not set +# CONFIG_LEDS_KTD202X is not set +# CONFIG_LEDS_NCP5623 is not set # CONFIG_LEDS_PWM_MULTICOLOR is not set # @@ -5157,6 +5719,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set CONFIG_LEDS_TRIGGER_CPU=y # CONFIG_LEDS_TRIGGER_ACTIVITY is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set # CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set # @@ -5167,11 +5730,11 @@ CONFIG_LEDS_TRIGGER_CPU=y # CONFIG_LEDS_TRIGGER_PANIC is not set # CONFIG_LEDS_TRIGGER_NETDEV is not set # CONFIG_LEDS_TRIGGER_PATTERN is not set -# CONFIG_LEDS_TRIGGER_AUDIO is not set # CONFIG_LEDS_TRIGGER_TTY is not set +# CONFIG_LEDS_TRIGGER_INPUT_EVENTS is not set # -# Simple LED drivers +# Simatic LED drivers # # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set @@ -5205,6 +5768,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_DS1672 is not set # CONFIG_RTC_DRV_HYM8563 is not set # CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_MAX31335 is not set # CONFIG_RTC_DRV_NCT3018Y is not set # CONFIG_RTC_DRV_RS5C372 is not set # CONFIG_RTC_DRV_ISL1208 is not set @@ -5221,6 +5785,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_S35390A is not set # CONFIG_RTC_DRV_FM3130 is not set # CONFIG_RTC_DRV_RX8010 is not set +# CONFIG_RTC_DRV_RX8111 is not set # CONFIG_RTC_DRV_RX8581 is not set # CONFIG_RTC_DRV_RX8025 is not set # CONFIG_RTC_DRV_EM3027 is not set @@ -5228,6 +5793,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_RV3032 is not set # CONFIG_RTC_DRV_RV8803 is not set # CONFIG_RTC_DRV_S5M is not set +# CONFIG_RTC_DRV_SD2405AL is not set # CONFIG_RTC_DRV_SD3078 is not set # @@ -5317,14 +5883,18 @@ CONFIG_IMX_SDMA=m # CONFIG_MV_XOR_V2 is not set # CONFIG_MXS_DMA is not set CONFIG_PL330_DMA=m +# CONFIG_PLX_DMA is not set # CONFIG_XILINX_DMA is not set # CONFIG_XILINX_XDMA is not set # CONFIG_XILINX_ZYNQMP_DMA is not set # CONFIG_XILINX_ZYNQMP_DPDMA is not set +# CONFIG_AMD_QDMA is not set # CONFIG_QCOM_HIDMA_MGMT is not set # CONFIG_QCOM_HIDMA is not set CONFIG_DW_DMAC_CORE=m CONFIG_DW_DMAC=m +# CONFIG_DW_DMAC_PCI is not set +# CONFIG_DW_EDMA is not set # CONFIG_SF_PDMA is not set # @@ -5365,11 +5935,7 @@ CONFIG_VHOST_MENU=y # CONFIG_GREYBUS is not set # CONFIG_COMEDI is not set CONFIG_STAGING=y -# CONFIG_PRISM2_USB is not set -# CONFIG_RTLLIB is not set # CONFIG_RTL8723BS is not set -# CONFIG_R8712U is not set -# CONFIG_VT6656 is not set # # IIO staging drivers @@ -5379,7 +5945,6 @@ CONFIG_STAGING=y # Accelerometers # # CONFIG_ADIS16203 is not set -# CONFIG_ADIS16240 is not set # end of Accelerometers # @@ -5406,30 +5971,28 @@ CONFIG_STAGING=y # # CONFIG_AD5933 is not set # end of Network Analyzer, Impedance Converters - -# -# Resolver to digital converters -# -# CONFIG_AD2S1210 is not set -# end of Resolver to digital converters # end of IIO staging drivers +# CONFIG_FB_SM750 is not set CONFIG_STAGING_MEDIA=y +# CONFIG_DVB_AV7110 is not set # CONFIG_VIDEO_MAX96712 is not set + +# +# StarFive media platform drivers +# CONFIG_STAGING_MEDIA_DEPRECATED=y # # Atmel media platform drivers # -# CONFIG_STAGING_BOARD is not set -# CONFIG_LTE_GDM724X is not set # CONFIG_FB_TFT is not set -# CONFIG_KS7010 is not set -# CONFIG_PI433 is not set # CONFIG_XIL_AXIS_FIFO is not set -# CONFIG_FIELDBUS_DEV is not set +# CONFIG_VME_BUS is not set +# CONFIG_GPIB is not set # CONFIG_GOLDFISH is not set CONFIG_CHROME_PLATFORMS=y +# CONFIG_CHROMEOS_OF_HW_PROBER is not set CONFIG_CROS_EC=y # CONFIG_CROS_EC_I2C is not set # CONFIG_CROS_EC_SPI is not set @@ -5445,6 +6008,7 @@ CONFIG_CROS_EC_SYSFS=y CONFIG_CROS_USBPD_NOTIFY=y # CONFIG_MELLANOX_PLATFORM is not set # CONFIG_SURFACE_PLATFORMS is not set +CONFIG_ARM64_PLATFORM_DEVICES=y CONFIG_HAVE_CLK=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -5487,6 +6051,7 @@ CONFIG_CLK_IMX8MQ=y CONFIG_CLK_IMX8QXP=y # CONFIG_CLK_IMX8ULP is not set # CONFIG_CLK_IMX93 is not set +# CONFIG_CLK_IMX95_BLK_CTL is not set # CONFIG_XILINX_VCU is not set # CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set # CONFIG_HWSPINLOCK is not set @@ -5509,6 +6074,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y CONFIG_MAILBOX=y CONFIG_ARM_MHU=y # CONFIG_ARM_MHU_V2 is not set +CONFIG_ARM_MHU_V3=m CONFIG_IMX_MBOX=y CONFIG_PLATFORM_MHU=y # CONFIG_PL320_MBOX is not set @@ -5565,9 +6131,10 @@ CONFIG_IOMMU_DMA=y # # Broadcom SoC drivers # -# CONFIG_SOC_BRCMSTB is not set # end of Broadcom SoC drivers +CONFIG_CDNS_MHDP_HELPER=y + # # NXP/Freescale QorIQ SoC drivers # @@ -5584,10 +6151,8 @@ CONFIG_FSL_GUTS=y # # i.MX SoC drivers # -CONFIG_IMX_GPCV2_PM_DOMAINS=y CONFIG_SOC_IMX8M=y # CONFIG_SOC_IMX9 is not set -CONFIG_IMX8M_BLK_CTRL=y # end of i.MX SoC drivers # @@ -5611,6 +6176,36 @@ CONFIG_IMX8M_BLK_CTRL=y # end of Xilinx SoC drivers # end of SOC (System On Chip) specific Drivers +# +# PM Domains +# + +# +# Amlogic PM Domains +# +# end of Amlogic PM Domains + +CONFIG_ARM_SCPI_POWER_DOMAIN=y + +# +# Broadcom PM Domains +# +# end of Broadcom PM Domains + +# +# i.MX PM Domains +# +CONFIG_IMX_GPCV2_PM_DOMAINS=y +CONFIG_IMX8M_BLK_CTRL=y +CONFIG_IMX_SCU_PD=y +# end of i.MX PM Domains + +# +# Qualcomm PM Domains +# +# end of Qualcomm PM Domains +# end of PM Domains + CONFIG_PM_DEVFREQ=y # @@ -5636,6 +6231,7 @@ CONFIG_EXTCON=y # CONFIG_EXTCON_ADC_JACK is not set # CONFIG_EXTCON_FSA9480 is not set # CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_LC824206XA is not set # CONFIG_EXTCON_MAX3355 is not set # CONFIG_EXTCON_PTN5150 is not set # CONFIG_EXTCON_RT8973A is not set @@ -5666,6 +6262,8 @@ CONFIG_IIO=y # CONFIG_ADXL367_I2C is not set # CONFIG_ADXL372_SPI is not set # CONFIG_ADXL372_I2C is not set +# CONFIG_ADXL380_SPI is not set +# CONFIG_ADXL380_I2C is not set # CONFIG_BMA180 is not set # CONFIG_BMA220 is not set # CONFIG_BMA400 is not set @@ -5702,37 +6300,49 @@ CONFIG_IIO=y # # Analog to digital converters # +# CONFIG_AD4000 is not set +# CONFIG_AD4030 is not set # CONFIG_AD4130 is not set +# CONFIG_AD4695 is not set +# CONFIG_AD4851 is not set # CONFIG_AD7091R5 is not set +# CONFIG_AD7091R8 is not set # CONFIG_AD7124 is not set +# CONFIG_AD7173 is not set +# CONFIG_AD7191 is not set # CONFIG_AD7192 is not set # CONFIG_AD7266 is not set # CONFIG_AD7280 is not set # CONFIG_AD7291 is not set # CONFIG_AD7292 is not set # CONFIG_AD7298 is not set +# CONFIG_AD7380 is not set # CONFIG_AD7476 is not set # CONFIG_AD7606_IFACE_PARALLEL is not set # CONFIG_AD7606_IFACE_SPI is not set +# CONFIG_AD7625 is not set # CONFIG_AD7766 is not set # CONFIG_AD7768_1 is not set +# CONFIG_AD7779 is not set # CONFIG_AD7780 is not set # CONFIG_AD7791 is not set # CONFIG_AD7793 is not set # CONFIG_AD7887 is not set # CONFIG_AD7923 is not set +# CONFIG_AD7944 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_ENVELOPE_DETECTOR is not set +# CONFIG_GEHC_PMC_ADC is not set # CONFIG_HI8435 is not set # CONFIG_HX711 is not set # CONFIG_INA2XX_ADC is not set # CONFIG_IMX7D_ADC is not set # CONFIG_IMX8QXP_ADC is not set # CONFIG_IMX93_ADC is not set +# CONFIG_LTC2309 is not set # CONFIG_LTC2471 is not set # CONFIG_LTC2485 is not set # CONFIG_LTC2496 is not set @@ -5744,11 +6354,15 @@ CONFIG_IIO=y # CONFIG_MAX11410 is not set # CONFIG_MAX1241 is not set # CONFIG_MAX1363 is not set +# CONFIG_MAX34408 is not set # CONFIG_MAX9611 is not set # CONFIG_MCP320X is not set # CONFIG_MCP3422 is not set +# CONFIG_MCP3564 is not set # CONFIG_MCP3911 is not set # CONFIG_NAU7802 is not set +# CONFIG_PAC1921 is not set +# CONFIG_PAC1934 is not set # CONFIG_RICHTEK_RTQ6056 is not set # CONFIG_SD_ADC_MODULATOR is not set # CONFIG_TI_ADC081C is not set @@ -5759,8 +6373,11 @@ CONFIG_IIO=y # CONFIG_TI_ADC128S052 is not set # CONFIG_TI_ADC161S626 is not set # CONFIG_TI_ADS1015 is not set +# CONFIG_TI_ADS1119 is not set +# CONFIG_TI_ADS7138 is not set # CONFIG_TI_ADS7924 is not set # CONFIG_TI_ADS1100 is not set +# CONFIG_TI_ADS1298 is not set # CONFIG_TI_ADS7950 is not set # CONFIG_TI_ADS8344 is not set # CONFIG_TI_ADS8688 is not set @@ -5804,10 +6421,12 @@ CONFIG_IIO=y # # Chemical Sensors # +# CONFIG_AOSONG_AGS02MA is not set # CONFIG_ATLAS_PH_SENSOR is not set # CONFIG_ATLAS_EZO_SENSOR is not set # CONFIG_BME680 is not set # CONFIG_CCS811 is not set +# CONFIG_ENS160 is not set # CONFIG_IAQCORE is not set # CONFIG_PMS7003 is not set # CONFIG_SCD30_CORE is not set @@ -5841,6 +6460,7 @@ CONFIG_IIO=y # # Digital to analog converters # +# CONFIG_AD3552R_HS is not set # CONFIG_AD3552R is not set # CONFIG_AD5064 is not set # CONFIG_AD5360 is not set @@ -5852,6 +6472,7 @@ CONFIG_IIO=y # CONFIG_AD5593R is not set # CONFIG_AD5504 is not set # CONFIG_AD5624R_SPI is not set +# CONFIG_AD9739A is not set # CONFIG_LTC2688 is not set # CONFIG_AD5686_SPI is not set # CONFIG_AD5696_I2C is not set @@ -5864,17 +6485,21 @@ CONFIG_IIO=y # CONFIG_AD5791 is not set # CONFIG_AD7293 is not set # CONFIG_AD7303 is not set +# CONFIG_AD8460 is not set # CONFIG_AD8801 is not set +# CONFIG_BD79703 is not set # CONFIG_DPOT_DAC is not set # CONFIG_DS4424 is not set # CONFIG_LTC1660 is not set # CONFIG_LTC2632 is not set +# CONFIG_LTC2664 is not set # CONFIG_M62332 is not set # CONFIG_MAX517 is not set # CONFIG_MAX5522 is not set # CONFIG_MAX5821 is not set # CONFIG_MCP4725 is not set # CONFIG_MCP4728 is not set +# CONFIG_MCP4821 is not set # CONFIG_MCP4922 is not set # CONFIG_TI_DAC082S085 is not set # CONFIG_TI_DAC5571 is not set @@ -5910,6 +6535,7 @@ CONFIG_IIO=y # CONFIG_ADF4350 is not set # CONFIG_ADF4371 is not set # CONFIG_ADF4377 is not set +# CONFIG_ADMFM2000 is not set # CONFIG_ADMV1013 is not set # CONFIG_ADMV1014 is not set # CONFIG_ADMV4420 is not set @@ -5952,8 +6578,10 @@ CONFIG_IIO=y # # CONFIG_AM2315 is not set # CONFIG_DHT11 is not set +# CONFIG_ENS210 is not set # CONFIG_HDC100X is not set # CONFIG_HDC2010 is not set +# CONFIG_HDC3020 is not set # CONFIG_HTS221 is not set # CONFIG_HTU21 is not set # CONFIG_SI7005 is not set @@ -5967,8 +6595,13 @@ CONFIG_IIO=y # CONFIG_ADIS16460 is not set # CONFIG_ADIS16475 is not set # CONFIG_ADIS16480 is not set +# CONFIG_ADIS16550 is not set # CONFIG_BMI160_I2C is not set # CONFIG_BMI160_SPI is not set +# CONFIG_BMI270_I2C is not set +# CONFIG_BMI270_SPI is not set +# CONFIG_BMI323_I2C is not set +# CONFIG_BMI323_SPI is not set # CONFIG_BOSCH_BNO055_SERIAL is not set # CONFIG_BOSCH_BNO055_I2C is not set # CONFIG_FXOS8700_I2C is not set @@ -5978,6 +6611,7 @@ CONFIG_IIO=y # CONFIG_INV_ICM42600_SPI is not set # CONFIG_INV_MPU6050_I2C is not set # CONFIG_INV_MPU6050_SPI is not set +# CONFIG_SMI240 is not set # CONFIG_IIO_ST_LSM6DSX is not set # CONFIG_IIO_ST_LSM9DS0 is not set # end of Inertial measurement units @@ -5987,11 +6621,15 @@ CONFIG_IIO=y # # CONFIG_ADJD_S311 is not set # CONFIG_ADUX1020 is not set +# CONFIG_AL3000A is not set # CONFIG_AL3010 is not set # CONFIG_AL3320A is not set +# CONFIG_APDS9160 is not set # CONFIG_APDS9300 is not set +# CONFIG_APDS9306 is not set # CONFIG_APDS9960 is not set # CONFIG_AS73211 is not set +# CONFIG_BH1745 is not set # CONFIG_BH1750 is not set # CONFIG_BH1780 is not set # CONFIG_CM32181 is not set @@ -6004,10 +6642,11 @@ CONFIG_IIO=y # CONFIG_SENSORS_ISL29018 is not set # CONFIG_SENSORS_ISL29028 is not set # CONFIG_ISL29125 is not set +# CONFIG_ISL76682 is not set # CONFIG_JSA1212 is not set -# CONFIG_ROHM_BU27008 is not set # CONFIG_ROHM_BU27034 is not set # CONFIG_RPR0521 is not set +# CONFIG_LTR390 is not set # CONFIG_LTR501 is not set # CONFIG_LTRF216A is not set # CONFIG_LV0104CS is not set @@ -6016,6 +6655,7 @@ CONFIG_IIO=y # CONFIG_NOA1305 is not set # CONFIG_OPT3001 is not set # CONFIG_OPT4001 is not set +# CONFIG_OPT4060 is not set # CONFIG_PA12203001 is not set # CONFIG_SI1133 is not set # CONFIG_SI1145 is not set @@ -6031,8 +6671,11 @@ CONFIG_IIO=y # CONFIG_US5182D is not set # CONFIG_VCNL4000 is not set # CONFIG_VCNL4035 is not set +# CONFIG_VEML3235 is not set # CONFIG_VEML6030 is not set +# CONFIG_VEML6040 is not set # CONFIG_VEML6070 is not set +# CONFIG_VEML6075 is not set # CONFIG_VL6180 is not set # CONFIG_ZOPT2201 is not set # end of Light sensors @@ -6040,9 +6683,11 @@ CONFIG_IIO=y # # Magnetometer sensors # +# CONFIG_AF8133J is not set # CONFIG_AK8974 is not set # CONFIG_AK8975 is not set # CONFIG_AK09911 is not set +# CONFIG_ALS31300 is not set # CONFIG_BMC150_MAGN_I2C is not set # CONFIG_BMC150_MAGN_SPI is not set # CONFIG_MAG3110 is not set @@ -6052,6 +6697,7 @@ CONFIG_IIO=y # CONFIG_SENSORS_HMC5843_SPI is not set # CONFIG_SENSORS_RM3100_I2C is not set # CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SI7210 is not set # CONFIG_TI_TMAG5273 is not set # CONFIG_YAMAHA_YAS530 is not set # end of Magnetometer sensors @@ -6099,10 +6745,12 @@ CONFIG_IIO=y # Pressure sensors # # CONFIG_ABP060MG is not set +# CONFIG_ROHM_BM1390 is not set # CONFIG_BMP280 is not set # CONFIG_DLHL60D is not set # CONFIG_DPS310 is not set # CONFIG_HP03 is not set +# CONFIG_HSC030PA is not set # CONFIG_ICP10100 is not set # CONFIG_MPL115_I2C is not set # CONFIG_MPL115_SPI is not set @@ -6110,6 +6758,7 @@ CONFIG_IIO=y # CONFIG_MPRLS0025PA is not set # CONFIG_MS5611 is not set # CONFIG_MS5637 is not set +# CONFIG_SDP500 is not set # CONFIG_IIO_ST_PRESS is not set # CONFIG_T5403 is not set # CONFIG_HP206C is not set @@ -6126,6 +6775,7 @@ CONFIG_IIO=y # Proximity and distance sensors # # CONFIG_CROS_EC_MKBP_PROXIMITY is not set +# CONFIG_HX9023S is not set # CONFIG_IRSD200 is not set # CONFIG_ISL29501 is not set # CONFIG_LIDAR_LITE_V2 is not set @@ -6140,6 +6790,7 @@ CONFIG_IIO=y # CONFIG_SRF08 is not set # CONFIG_VCNL3020 is not set # CONFIG_VL53L0X_I2C is not set +# CONFIG_AW96103 is not set # end of Proximity and distance sensors # @@ -6147,6 +6798,7 @@ CONFIG_IIO=y # # CONFIG_AD2S90 is not set # CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set # end of Resolver to digital converters # @@ -6156,6 +6808,7 @@ CONFIG_IIO=y # CONFIG_MAXIM_THERMOCOUPLE is not set # CONFIG_MLX90614 is not set # CONFIG_MLX90632 is not set +# CONFIG_MLX90635 is not set # CONFIG_TMP006 is not set # CONFIG_TMP007 is not set # CONFIG_TMP117 is not set @@ -6164,15 +6817,18 @@ CONFIG_IIO=y # CONFIG_MAX30208 is not set # CONFIG_MAX31856 is not set # CONFIG_MAX31865 is not set +# CONFIG_MCP9600 is not set # end of Temperature sensors +# CONFIG_NTB is not set CONFIG_PWM=y -CONFIG_PWM_SYSFS=y # CONFIG_PWM_DEBUG is not set # CONFIG_PWM_ATMEL_TCB is not set # CONFIG_PWM_CLK is not set # CONFIG_PWM_CROS_EC is not set +# CONFIG_PWM_DWC is not set # CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_GPIO is not set # CONFIG_PWM_IMX1 is not set # CONFIG_PWM_IMX27 is not set # CONFIG_PWM_IMX_TPM is not set @@ -6185,8 +6841,10 @@ CONFIG_PWM_SYSFS=y CONFIG_IRQCHIP=y CONFIG_ARM_GIC=y CONFIG_ARM_GIC_MAX_NR=1 +CONFIG_ARM_GIC_V2M=y CONFIG_ARM_GIC_V3=y CONFIG_ARM_GIC_V3_ITS=y +CONFIG_IRQ_MSI_LIB=y # CONFIG_AL_FIC is not set # CONFIG_XILINX_INTC is not set CONFIG_IMX_GPCV2=y @@ -6198,7 +6856,10 @@ CONFIG_IMX_INTMUX=y # CONFIG_IPACK_BUS is not set CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_GPIO is not set +# CONFIG_RESET_IMX_SCU is not set CONFIG_RESET_IMX7=y +# CONFIG_RESET_IMX8MP_AUDIOMIX is not set # CONFIG_RESET_SIMPLE is not set # CONFIG_RESET_TI_SYSCON is not set # CONFIG_RESET_TI_TPS380X is not set @@ -6208,6 +6869,7 @@ CONFIG_RESET_IMX7=y # CONFIG_GENERIC_PHY=y # CONFIG_PHY_CAN_TRANSCEIVER is not set +# CONFIG_PHY_NXP_PTN3222 is not set # # PHY drivers for Broadcom platforms @@ -6224,9 +6886,11 @@ CONFIG_PHY_FSL_IMX8MQ_USB=y # CONFIG_PHY_MIXEL_LVDS_PHY is not set # CONFIG_PHY_MIXEL_MIPI_DPHY is not set CONFIG_PHY_FSL_IMX8M_PCIE=y +CONFIG_PHY_FSL_IMX8MQ_HDPTX=y +# CONFIG_PHY_FSL_IMX8QM_HSIO is not set +# CONFIG_PHY_FSL_SAMSUNG_HDMI_PHY is not set # CONFIG_PHY_PXA_28NM_HSIC is not set # CONFIG_PHY_PXA_28NM_USB2 is not set -# CONFIG_PHY_LAN966X_SERDES is not set # CONFIG_PHY_CPCAP_USB is not set # CONFIG_PHY_MAPPHONE_MDM6600 is not set # CONFIG_PHY_OCELOT_SERDES is not set @@ -6242,6 +6906,7 @@ CONFIG_PHY_FSL_IMX8M_PCIE=y # CONFIG_ARM_CCI_PMU is not set # CONFIG_ARM_CCN is not set # CONFIG_ARM_CMN is not set +# CONFIG_ARM_NI is not set CONFIG_ARM_PMU=y # CONFIG_ARM_SMMU_V3_PMU is not set CONFIG_ARM_PMUV3=y @@ -6249,10 +6914,14 @@ CONFIG_ARM_PMUV3=y CONFIG_FSL_IMX8_DDR_PMU=y # CONFIG_FSL_IMX9_DDR_PMU is not set # CONFIG_ARM_SPE_PMU is not set +# CONFIG_HISI_PCIE_PMU is not set +# CONFIG_HNS3_PMU is not set +# CONFIG_DWC_PCIE_PMU is not set # CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU is not set # end of Performance monitor support # CONFIG_RAS is not set +# CONFIG_USB4 is not set # # Android @@ -6264,12 +6933,14 @@ CONFIG_FSL_IMX8_DDR_PMU=y # CONFIG_DAX is not set CONFIG_NVMEM=y CONFIG_NVMEM_SYSFS=y +CONFIG_NVMEM_LAYOUTS=y # # Layout Types # # CONFIG_NVMEM_LAYOUT_SL28_VPD is not set # CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set +CONFIG_NVMEM_LAYOUT_U_BOOT_ENV=m # end of Layout Types # CONFIG_NVMEM_IMX_IIM is not set @@ -6285,6 +6956,7 @@ CONFIG_NVMEM_U_BOOT_ENV=m # # CONFIG_STM is not set # CONFIG_INTEL_TH is not set +# CONFIG_HISI_PTT is not set # end of HW tracing support # CONFIG_FPGA is not set @@ -6309,6 +6981,7 @@ CONFIG_PM_OPP=y CONFIG_DCACHE_WORD_ACCESS=y CONFIG_VALIDATE_FS_PARSER=y CONFIG_FS_IOMAP=y +CONFIG_FS_STACK=y CONFIG_BUFFER_HEAD=y CONFIG_LEGACY_DIRECT_IO=y # CONFIG_EXT2_FS is not set @@ -6321,7 +6994,6 @@ CONFIG_EXT4_FS_SECURITY=y CONFIG_JBD2=y # CONFIG_JBD2_DEBUG is not set CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set CONFIG_JFS_FS=m # CONFIG_JFS_POSIX_ACL is not set # CONFIG_JFS_SECURITY is not set @@ -6340,10 +7012,10 @@ CONFIG_XFS_SUPPORT_ASCII_CI=y # CONFIG_OCFS2_FS is not set CONFIG_BTRFS_FS=m CONFIG_BTRFS_FS_POSIX_ACL=y -# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set # CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set # CONFIG_BTRFS_DEBUG is not set # CONFIG_BTRFS_ASSERT is not set +# CONFIG_BTRFS_EXPERIMENTAL is not set # CONFIG_BTRFS_FS_REF_VERIFY is not set # CONFIG_NILFS2_FS is not set CONFIG_F2FS_FS=m @@ -6354,6 +7026,7 @@ CONFIG_F2FS_CHECK_FS=y # CONFIG_F2FS_FS_COMPRESSION is not set CONFIG_F2FS_IOSTAT=y # CONFIG_F2FS_UNFAIR_RWSEM is not set +# CONFIG_BCACHEFS_FS is not set CONFIG_FS_POSIX_ACL=y CONFIG_EXPORTFS=y # CONFIG_EXPORTFS_BLOCK_OPS is not set @@ -6364,11 +7037,14 @@ CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y CONFIG_INOTIFY_USER=y CONFIG_FANOTIFY=y +# CONFIG_FANOTIFY_ACCESS_PERMISSIONS is not set # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y CONFIG_FUSE_FS=m # CONFIG_CUSE is not set # CONFIG_VIRTIO_FS is not set +CONFIG_FUSE_PASSTHROUGH=y +CONFIG_FUSE_IO_URING=y CONFIG_OVERLAY_FS=m # CONFIG_OVERLAY_FS_REDIRECT_DIR is not set CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y @@ -6380,12 +7056,6 @@ CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y # # Caches # -CONFIG_NETFS_SUPPORT=y -# CONFIG_NETFS_STATS is not set -CONFIG_FSCACHE=y -# CONFIG_FSCACHE_STATS is not set -# CONFIG_FSCACHE_DEBUG is not set -# CONFIG_CACHEFILES is not set # end of Caches # @@ -6408,11 +7078,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_FAT_DEFAULT_UTF8 is not set CONFIG_EXFAT_FS=m CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" -# CONFIG_NTFS_FS is not set CONFIG_NTFS3_FS=m # CONFIG_NTFS3_64BIT_CLUSTER is not set # CONFIG_NTFS3_LZX_XPRESS is not set # CONFIG_NTFS3_FS_POSIX_ACL is not set +# CONFIG_NTFS_FS is not set # end of DOS/FAT/EXFAT/NT Filesystems # @@ -6473,7 +7143,6 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_QNX6FS_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_PSTORE is not set -# CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_EROFS_FS is not set CONFIG_NETWORK_FILESYSTEMS=y @@ -6491,7 +7160,7 @@ CONFIG_PNFS_FLEXFILE_LAYOUT=y CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" CONFIG_NFS_V4_1_MIGRATION=y CONFIG_ROOT_NFS=y -CONFIG_NFS_FSCACHE=y +# CONFIG_NFS_FSCACHE is not set # CONFIG_NFS_USE_LEGACY_DNS is not set CONFIG_NFS_USE_KERNEL_DNS=y CONFIG_NFS_DISABLE_UDP_SUPPORT=y @@ -6577,6 +7246,7 @@ 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=y @@ -6584,10 +7254,9 @@ CONFIG_KEY_DH_OPERATIONS=y CONFIG_PROC_MEM_ALWAYS_FORCE=y # CONFIG_PROC_MEM_FORCE_PTRACE is not set # CONFIG_PROC_MEM_NO_FORCE is not set +CONFIG_MSEAL_SYSTEM_MAPPINGS=y # CONFIG_SECURITY is not set # CONFIG_SECURITYFS is not set -# CONFIG_HARDENED_USERCOPY is not set -# CONFIG_FORTIFY_SOURCE is not set # CONFIG_STATIC_USERMODEHELPER is not set CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor" @@ -6612,6 +7281,13 @@ CONFIG_CC_HAS_ZERO_CALL_USED_REGS=y # CONFIG_ZERO_CALL_USED_REGS is not set # end of Memory initialization +# +# Bounds checking +# +# CONFIG_FORTIFY_SOURCE is not set +# CONFIG_HARDENED_USERCOPY is not set +# end of Bounds checking + # # Hardening of kernel data structures # @@ -6658,6 +7334,7 @@ CONFIG_CRYPTO_NULL2=y CONFIG_CRYPTO_PCRYPT=y CONFIG_CRYPTO_CRYPTD=y CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_KRB5ENC is not set # CONFIG_CRYPTO_TEST is not set # end of Crypto core or helper @@ -6671,7 +7348,6 @@ CONFIG_CRYPTO_ECC=y CONFIG_CRYPTO_ECDH=y # CONFIG_CRYPTO_ECDSA is not set # CONFIG_CRYPTO_ECRDSA is not set -# CONFIG_CRYPTO_SM2 is not set # CONFIG_CRYPTO_CURVE25519 is not set # end of Public-key cryptography @@ -6704,14 +7380,11 @@ CONFIG_CRYPTO_SM4=y # CONFIG_CRYPTO_ARC4 is not set CONFIG_CRYPTO_CHACHA20=y CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_CFB=y CONFIG_CRYPTO_CTR=y CONFIG_CRYPTO_CTS=y CONFIG_CRYPTO_ECB=y # CONFIG_CRYPTO_HCTR2 is not set -# CONFIG_CRYPTO_KEYWRAP is not set # CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_OFB is not set # CONFIG_CRYPTO_PCBC is not set # CONFIG_CRYPTO_XTS is not set # end of Length-preserving ciphers and modes @@ -6748,7 +7421,6 @@ CONFIG_CRYPTO_SHA3=y CONFIG_CRYPTO_SM3=y # CONFIG_CRYPTO_SM3_GENERIC is not set # CONFIG_CRYPTO_STREEBOG is not set -# CONFIG_CRYPTO_VMAC is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_XCBC is not set CONFIG_CRYPTO_XXHASH=m @@ -6759,7 +7431,6 @@ CONFIG_CRYPTO_XXHASH=m # CONFIG_CRYPTO_CRC32C=y CONFIG_CRYPTO_CRC32=y -CONFIG_CRYPTO_CRCT10DIF=y # end of CRCs (cyclic redundancy checks) # @@ -6783,7 +7454,9 @@ CONFIG_CRYPTO_DRBG_HMAC=y # CONFIG_CRYPTO_DRBG_CTR is not set CONFIG_CRYPTO_DRBG=y CONFIG_CRYPTO_JITTERENTROPY=y -# CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE is not set +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS=64 +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32 +CONFIG_CRYPTO_JITTERENTROPY_OSR=1 CONFIG_CRYPTO_KDF800108_CTR=y # end of Random number generation @@ -6806,7 +7479,7 @@ CONFIG_CRYPTO_CHACHA20_NEON=y # Accelerated Cryptographic Algorithms for CPU (arm64) # CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_POLY1305_NEON=y +CONFIG_CRYPTO_POLY1305_NEON=m CONFIG_CRYPTO_SHA1_ARM64_CE=y CONFIG_CRYPTO_SHA256_ARM64=y CONFIG_CRYPTO_SHA2_ARM64_CE=y @@ -6836,6 +7509,16 @@ CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set # CONFIG_CRYPTO_DEV_CCP is not set # CONFIG_CRYPTO_DEV_MXS_DCP is not set +# CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set +# CONFIG_CRYPTO_DEV_QAT_DH895xCC is not set +# CONFIG_CRYPTO_DEV_QAT_C3XXX is not set +# CONFIG_CRYPTO_DEV_QAT_C62X is not set +# CONFIG_CRYPTO_DEV_QAT_4XXX is not set +# CONFIG_CRYPTO_DEV_QAT_420XX is not set +# CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set +# CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set +# CONFIG_CRYPTO_DEV_QAT_C62XVF is not set +# CONFIG_CRYPTO_DEV_CAVIUM_ZIP is not set # CONFIG_CRYPTO_DEV_SAFEXCEL is not set # CONFIG_CRYPTO_DEV_CCREE is not set # CONFIG_CRYPTO_DEV_HISI_SEC is not set @@ -6859,6 +7542,7 @@ CONFIG_SYSTEM_TRUSTED_KEYS="" # CONFIG_SYSTEM_BLACKLIST_KEYRING is not set # end of Certificates for signature checking +# CONFIG_CRYPTO_KRB5 is not set CONFIG_BINARY_PRINTF=y # @@ -6876,7 +7560,6 @@ CONFIG_GENERIC_NET_UTILS=y CONFIG_CORDIC=m # CONFIG_PRIME_NUMBERS is not set CONFIG_RATIONAL=y -CONFIG_GENERIC_PCI_IOMAP=y CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y CONFIG_ARCH_HAS_FAST_MULTIPLIER=y CONFIG_ARCH_USE_SYM_ANNOTATIONS=y @@ -6892,12 +7575,15 @@ CONFIG_CRYPTO_LIB_GF128MUL=y CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA=y CONFIG_CRYPTO_LIB_CHACHA_GENERIC=y +CONFIG_CRYPTO_LIB_CHACHA_INTERNAL=y CONFIG_CRYPTO_LIB_CHACHA=m CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=m +CONFIG_CRYPTO_LIB_CURVE25519_INTERNAL=m CONFIG_CRYPTO_LIB_CURVE25519=m CONFIG_CRYPTO_LIB_DES=y CONFIG_CRYPTO_LIB_POLY1305_RSIZE=9 CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305=y +CONFIG_CRYPTO_LIB_POLY1305_INTERNAL=m CONFIG_CRYPTO_LIB_POLY1305=m CONFIG_CRYPTO_LIB_CHACHA20POLY1305=m CONFIG_CRYPTO_LIB_SHA1=y @@ -6906,20 +7592,14 @@ CONFIG_CRYPTO_LIB_SHA256=y CONFIG_CRC_CCITT=m CONFIG_CRC16=y -# CONFIG_CRC_T10DIF is not set -# CONFIG_CRC64_ROCKSOFT is not set +CONFIG_ARCH_HAS_CRC_T10DIF=y CONFIG_CRC_ITU_T=y CONFIG_CRC32=y -# CONFIG_CRC32_SELFTEST is not set -CONFIG_CRC32_SLICEBY8=y -# CONFIG_CRC32_SLICEBY4 is not set -# CONFIG_CRC32_SARWATE is not set -# CONFIG_CRC32_BIT is not set -# CONFIG_CRC64 is not set -# CONFIG_CRC4 is not set +CONFIG_ARCH_HAS_CRC32=y +CONFIG_CRC32_ARCH=y CONFIG_CRC7=y -CONFIG_LIBCRC32C=m CONFIG_CRC8=m +CONFIG_CRC_OPTIMIZATIONS=y CONFIG_XXHASH=y CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y # CONFIG_RANDOM32_SELFTEST is not set @@ -6934,10 +7614,11 @@ CONFIG_ZSTD_DECOMPRESS=y CONFIG_XZ_DEC=y # CONFIG_XZ_DEC_X86 is not set # CONFIG_XZ_DEC_POWERPC is not set -# CONFIG_XZ_DEC_IA64 is not set # CONFIG_XZ_DEC_ARM is not set # CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_ARM64 is not set # CONFIG_XZ_DEC_SPARC is not set +# CONFIG_XZ_DEC_RISCV is not set # CONFIG_XZ_DEC_MICROLZMA is not set # CONFIG_XZ_DEC_TEST is not set CONFIG_GENERIC_ALLOCATOR=y @@ -6945,21 +7626,23 @@ CONFIG_XARRAY_MULTI=y CONFIG_ASSOCIATIVE_ARRAY=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y CONFIG_HAS_DMA=y -CONFIG_DMA_OPS=y +CONFIG_DMA_OPS_HELPERS=y CONFIG_NEED_SG_DMA_FLAGS=y CONFIG_NEED_SG_DMA_LENGTH=y CONFIG_NEED_DMA_MAP_STATE=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y CONFIG_DMA_DECLARE_COHERENT=y CONFIG_ARCH_HAS_SETUP_DMA_OPS=y -CONFIG_ARCH_HAS_TEARDOWN_DMA_OPS=y CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU=y CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y +CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED=y CONFIG_SWIOTLB=y # CONFIG_SWIOTLB_DYNAMIC is not set CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_NEED_SYNC=y # CONFIG_DMA_RESTRICTED_POOL is not set CONFIG_DMA_NONCOHERENT_MMAP=y CONFIG_DMA_COHERENT_POOL=y @@ -6969,7 +7652,7 @@ CONFIG_DMA_CMA=y # # Default contiguous memory area size: # -CONFIG_CMA_SIZE_MBYTES=256 +CONFIG_CMA_SIZE_MBYTES=384 CONFIG_CMA_SIZE_SEL_MBYTES=y # CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set # CONFIG_CMA_SIZE_SEL_MIN is not set @@ -6986,11 +7669,14 @@ CONFIG_NLATTR=y CONFIG_CLZ_TAB=y # CONFIG_IRQ_POLL is not set CONFIG_MPILIB=y +CONFIG_DIMLIB=y CONFIG_LIBFDT=y CONFIG_OID_REGISTRY=y CONFIG_HAVE_GENERIC_VDSO=y CONFIG_GENERIC_GETTIMEOFDAY=y CONFIG_GENERIC_VDSO_TIME_NS=y +CONFIG_VDSO_GETRANDOM=y +CONFIG_GENERIC_VDSO_DATA_STORE=y CONFIG_FONT_SUPPORT=y # CONFIG_FONTS is not set CONFIG_FONT_8x8=y @@ -6998,11 +7684,14 @@ CONFIG_FONT_8x16=y CONFIG_SG_POOL=y CONFIG_ARCH_STACKWALK=y CONFIG_STACKDEPOT=y +CONFIG_STACKDEPOT_MAX_FRAMES=64 CONFIG_SBITMAP=y +# CONFIG_LWQ_TEST is not set # end of Library routines CONFIG_GENERIC_IOREMAP=y CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_UNION_FIND=y # # Kernel hacking @@ -7030,7 +7719,7 @@ CONFIG_DEBUG_MISC=y # # Compile-time checks and compiler options # -CONFIG_AS_HAS_NON_CONST_LEB128=y +CONFIG_AS_HAS_NON_CONST_ULEB128=y CONFIG_DEBUG_INFO_NONE=y # CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set # CONFIG_DEBUG_INFO_DWARF4 is not set @@ -7061,7 +7750,7 @@ CONFIG_DEBUG_FS_ALLOW_ALL=y # CONFIG_DEBUG_FS_ALLOW_NONE is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set -CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y +CONFIG_ARCH_HAS_UBSAN=y # CONFIG_UBSAN is not set CONFIG_HAVE_ARCH_KCSAN=y CONFIG_HAVE_KCSAN_COMPILER=y @@ -7074,6 +7763,7 @@ CONFIG_HAVE_KCSAN_COMPILER=y # CONFIG_NET_DEV_REFCNT_TRACKER is not set # CONFIG_NET_NS_REFCNT_TRACKER is not set # CONFIG_DEBUG_NET is not set +# CONFIG_DEBUG_NET_SMALL_RTNL is not set # end of Networking Debugging # @@ -7088,7 +7778,7 @@ CONFIG_SLUB_DEBUG=y # CONFIG_DEBUG_RODATA_TEST is not set CONFIG_ARCH_HAS_DEBUG_WX=y # CONFIG_DEBUG_WX is not set -CONFIG_GENERIC_PTDUMP=y +CONFIG_ARCH_HAS_PTDUMP=y # CONFIG_PTDUMP_DEBUGFS is not set CONFIG_HAVE_DEBUG_KMEMLEAK=y # CONFIG_DEBUG_KMEMLEAK is not set @@ -7098,12 +7788,14 @@ CONFIG_HAVE_DEBUG_KMEMLEAK=y # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_SCHED_STACK_END_CHECK is not set CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y +# CONFIG_DEBUG_VFS is not set # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_VM_PGTABLE is not set CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y # CONFIG_DEBUG_VIRTUAL is not set # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_MEM_ALLOC_PROFILING is not set CONFIG_HAVE_ARCH_KASAN=y CONFIG_HAVE_ARCH_KASAN_SW_TAGS=y CONFIG_HAVE_ARCH_KASAN_VMALLOC=y @@ -7129,6 +7821,7 @@ CONFIG_HAVE_HARDLOCKUP_DETECTOR_BUDDY=y CONFIG_DETECT_HUNG_TASK=y CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_DETECT_HUNG_TASK_BLOCKER=y # CONFIG_WQ_WATCHDOG is not set # CONFIG_WQ_CPU_INTENSIVE_REPORT is not set # CONFIG_TEST_LOCKUP is not set @@ -7137,12 +7830,9 @@ CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 # # Scheduler Debugging # -# CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # end of Scheduler Debugging -# CONFIG_DEBUG_TIMEKEEPING is not set - # # Lock Debugging (spinlocks, mutexes, etc...) # @@ -7194,14 +7884,17 @@ CONFIG_RCU_EXP_CPU_STALL_TIMEOUT=0 # CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set # CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set # CONFIG_LATENCYTOP is not set +CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_RETVAL=y +CONFIG_HAVE_FUNCTION_GRAPH_FREGS=y +CONFIG_HAVE_FTRACE_GRAPH_FUNC=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_BUILDTIME_MCOUNT_SORT=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set # CONFIG_SAMPLES is not set @@ -7236,3 +7929,5 @@ CONFIG_ARCH_USE_MEMTEST=y # # end of Rust hacking # end of Kernel hacking + +CONFIG_IO_URING_ZCRX=y diff --git a/projects/NXP/devices/iMX8/patches/linux/0001-Initial-support-Cadence-MHDP8501-HDMI-DP-for-i-MX8MQ.patch b/projects/NXP/devices/iMX8/patches/linux/0001-Initial-support-Cadence-MHDP8501-HDMI-DP-for-i-MX8MQ.patch new file mode 100644 index 0000000000..02f0c17ec2 --- /dev/null +++ b/projects/NXP/devices/iMX8/patches/linux/0001-Initial-support-Cadence-MHDP8501-HDMI-DP-for-i-MX8MQ.patch @@ -0,0 +1,6735 @@ +From patchwork Tue Dec 17 06:51:43 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [PATCH v20 0/8] Initial support Cadence MHDP8501(HDMI/DP) for i.MX8MQ +From: Sandor Yu +Message-Id: +To: dmitry.baryshkov@linaro.org, andrzej.hajda@intel.com, + neil.armstrong@linaro.org, Laurent.pinchart@ideasonboard.com, + jonas@kwiboo.se, jernej.skrabec@gmail.com, airlied@gmail.com, + daniel@ffwll.ch, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, + vkoul@kernel.org, dri-devel@lists.freedesktop.org, + devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, + mripard@kernel.org +Cc: kernel@pengutronix.de, linux-imx@nxp.com, Sandor.yu@nxp.com, + oliver.brown@nxp.com, alexander.stein@ew.tq-group.com, sam@ravnborg.org +Date: Tue, 17 Dec 2024 14:51:42 +0800 + +The patch set initial support Cadence MHDP8501(HDMI/DP) DRM bridge +driver and Cadence HDP-TX PHY(HDMI/DP) driver for Freescale i.MX8MQ. + +The patch set compose of DRM bridge drivers and PHY driver. + +Both of them need by patch #1 and #3 to pass build. + +DRM bridges driver patches: + #1: soc: cadence: Create helper functions for Cadence MHDP + #2: drm: bridge: cadence: Update mhdp8546 mailbox access functions + #3: phy: Add HDMI configuration options + #4: dt-bindings: display: bridge: Add Cadence MHDP8501 + #5: drm: bridge: Cadence: Add MHDP8501 DP/HDMI driver + +PHY driver patches: + #1: soc: cadence: Create helper functions for Cadence MHDP + #3: phy: Add HDMI configuration options + #6: dt-bindings: phy: Add Freescale iMX8MQ DP and HDMI PHY + #7: phy: freescale: Add DisplayPort/HDMI Combo-PHY driver for i.MX8MQ + +i.MX8M/TQMa8Mx DT patches: + #8: Add DT nodes for DCSS/HDMI pipeline + #9: Enable HDMI for TQMa8Mx/MBa8Mx + +v19->v20: +Patch #1: soc: cadence: Create helper functions for Cadence MHDP +Patch #2: drm: bridge: cadence: Update mhdp8546 mailbox access functions +- The two patches are split from Patch #1 in v19. + The MHDP helper functions have been moved in a new "cadence" directory + under the SOC directory in patch #1, in order to promote code reuse + among MHDP8546, MHDP8501, and the i.MX8MQ HDMI/DP PHY drivers, + +Patch #3: phy: Add HDMI configuration options +- Add a-b tag + +Patch #4: dt-bindings: display: bridge: Add Cadence MHDP8501 +- remove data type link of data-lanes + +Patch #5: drm: bridge: Cadence: Add MHDP8501 DP/HDMI driver +- Dump mhdp FW version by debugfs +- Combine HDMI and DP cable detect functions into one function +- Combine HDMI and DP cable bridge_mode_valid() functions into one function +- Rename cdns_hdmi_reset_link() to cdns_hdmi_handle_hotplug() +- Add comments for EDID in cdns_hdmi_handle_hotplug() and cdns_dp_check_link_state() +- Add atomic_get_input_bus_fmts() and bridge_atomic_check() for DP driver +- Remove bpc and color_fmt init in atomic_enable() function. +- More detail comments for DDC adapter only support SCDC_I2C_SLAVE_ADDRESS + read and write in HDMI driver. + +Patch #7: phy: freescale: Add DisplayPort/HDMI Combo-PHY driver for i.MX8MQ +- implify DP configuration handling by directly copying + the configuration options to the driver's internal structure. +- return the error code directly instead of logging an error message in `hdptx_clk_enable` +- Remove redundant ref_clk_rate check + + +v18->v19: +Patch #1 +- use guard(mutex) +- Add kerneldocs for all new APIs. +- Detail comments for mailbox access specific case. +- remove cdns_mhdp_dp_reg_write() because it is not needed by driver now. + +Patch #3 +- move property data-lanes to endpoint of port@1 + +Patch #4 +- get endpoint for data-lanes as it had move to endpoint of port@1 +- update clock management as devm_clk_get_enabled() introduced. +- Fix clear_infoframe() function is not work issue. +- Manage PHY power state via phy_power_on() and phy_power_off(). + +Patch #6 +- Simplify the PLL table by removing unused and constant data +- Remove PHY power management, controller driver will handle them. +- Remove enum dp_link_rate +- introduce read_pll_timeout. +- update clock management as devm_clk_get_enabled() introduced. +- remove cdns_hdptx_phy_init() and cdns_hdptx_phy_remove(). + +Patch #8: +- move property data-lanes to endpoint of port@1 + +v17->v18: +Patch #1 +- Create three ordinary mailbox access APIs + cdns_mhdp_mailbox_send + cdns_mhdp_mailbox_send_recv + cdns_mhdp_mailbox_send_recv_multi +- Create three secure mailbox access APIs + cdns_mhdp_secure_mailbox_send + cdns_mhdp_secure_mailbox_send_recv + cdns_mhdp_secure_mailbox_send_recv_multi +- MHDP8546 DP and HDCP commands that need access mailbox are rewrited + with above 6 API functions. + +Patch #3 +- remove lane-mapping and replace it with data-lanes +- remove r-b tag as property changed. + +Patch #4 +- MHDP8501 HDMI and DP commands that need access mailbox are rewrited + with new API functions created in patch #1. +- replace lane-mapping with data-lanes, use the value from data-lanes + to reorder HDMI and DP lane mapping. +- create I2C adapter for HDMI SCDC, remove cdns_hdmi_scdc_write() function. +- Rewrite cdns_hdmi_sink_config() function, use HDMI SCDC helper function + drm_scdc_set_high_tmds_clock_ratio() and drm_scdc_set_scrambling() + to config HDMI sink TMDS. +- Remove struct video_info from HDMI driver. +- Remove tmds_char_rate_valid() be called in bridge_mode_valid(), + community had patch in reviewing to implement the function. +- Remove warning message print when get unknown HPD cable status. +- Add more detail comments for HDP plugin and plugout interrupt. +- use dev_dbg to repleace DRM_INFO when cable HPD status changed. +- Remove t-b tag as above code change. + +Patch #6 +- fix build error as code rebase to latest kernel version. + +Patch #8: +- replace lane-mapping with data-lanes + + +v16->v17: +Patch #1: +- Replaces the local mutex mbox_mutex with a global mutex mhdp_mailbox_mutex +Patch #2: +- remove hdmi.h +- add 2024 year to copyright +- Add r-b tag. +Patch #3: +- Add lane-mapping property. +Patch #4: +- Reset the HDMI/DP link when an HPD (Hot Plug Detect) event is detected +- Move the HDMI protocol settings from hdmi_ctrl_init() to a new function + cdns_hdmi_set_hdmi_mode_type(), to align with the introduced link reset functionality. +- Implement logic to check the type of HDMI sink. + If the sink is not a hdmi display, set the default mode to DVI. +- Implement hdmi_reset_infoframe function +- Reorder certain bit definitions in the header file to follow a descending order. +- Add "lane-mapping" property for both HDMI and DP, remove platform data from driver. + lane-mapping should be setting in dts according different board layout. +- Remove variable mode in struct cdns_mhdp8501_device, video mode could get from struct drm_crtc_state +- Remove variable char_rate in struct cdns_mhdp8501_device, it could get from struct struct drm_connector_state.hdmi +- Replaces the local mutex mbox_mutex with a global mutex mhdp_mailbox_mutex +- Remove mutext protect for phy_api access functions. +Patch #6: +- Remove mbox_mutex + +v15->v16: +Patch #2: +- Remove pixel_clk_rate, bpc and color_space fields from struct + phy_configure_opts_hdmi, they were replaced by + unsigned long long tmds_char_rate. +- Remove r-b and a-c tags because this patch have important change. +Patch #4: +- Add DRM_BRIDGE_OP_HDMI flags for HDMI driver, +- Introduce the hdmi info frame helper functions, + added hdmi_clear_infoframe(), hdmi_write_infoframe() and + hdmi_tmds_char_rate_valid() according Dmitry's patch + 'make use of the HDMI connector infrastructure' patchset ([2]). +- mode_fixup() is replaced by atomic_check(). +- Fix video mode 4Kp30 did not work on some displays that support + LTE_340Mcsc_scramble. +- updated for tmds_char_rate added in patch #2. +Patch #6: +- updated for tmds_char_rate added in patch #2. + +v14->v15: +Patch #6 + #7: +- Merged PHY driver into a single combo PHY driver +Patch #7 + #8: +- Add DT patches for a running HDMI setup + +v13->v14: +Patch #4: +- Rebase to next-20240219, replace get_edid function by edid_read + function as commits d807ad80d811b ("drm/bridge: add ->edid_read + hook and drm_bridge_edid_read()") and 27b8f91c08d99 ("drm/bridge: + remove ->get_edid callback") had change the API. + +v12->v13: +Patch #4: +- Explicitly include linux/platform_device.h for cdns-mhdp8501-core.c +- Fix build warning +- Order bit bpc and color_space in descending shit. +Patch #7: +- Fix build warning + +v11->v12: +Patch #1: +- Move status initialize out of mbox_mutex. +- Reorder API functions in alphabetical. +- Add notes for malibox access functions. +- Add year 2024 to copyright. +Patch #4: +- Replace DRM_INFO with dev_info or dev_warn. +- Replace DRM_ERROR with dev_err. +- Return ret when cdns_mhdp_dpcd_read failed in function cdns_dp_aux_transferi(). +- Remove unused parmeter in function cdns_dp_get_msa_misc + and use two separate variables for color space and bpc. +- Add year 2024 to copyright. +Patch #6: +- Return error code to replace -1 for function wait_for_ack(). +- Set cdns_phy->power_up = false in phy_power_down function. +- Remove "RATE_8_1 = 810000", it is not used in driver. +- Add year 2024 to copyright. +Patch #7: +- Adjust clk disable order. +- Return error code to replace -1 for function wait_for_ack(). +- Use bool for variable pclk_in. +- Add year 2024 to copyright. + +v10->v11: +- rewrite cdns_mhdp_set_firmware_active() in mhdp8546 core driver, +use cdns_mhdp_mailbox_send() to replace cdns_mhdp_mailbox_write() +same as the other mailbox access functions. +- use static for cdns_mhdp_mailbox_write() and cdns_mhdp_mailbox_read() +and remove them from EXPORT_SYMBOL_GPL(). +- remove MODULE_ALIAS() from mhdp8501 driver. + +v9->v10: +- Create mhdp helper driver to replace macro functions, +move all mhdp mailbox access functions and common functions +into the helper driver. +Patch #1:drm: bridge: Cadence: Creat mhdp helper driver +it is totaly different with v9. + +v8->v9: +- Remove compatible string "cdns,mhdp8501" that had removed + from dt-bindings file in v8. +- Add Dmitry's R-b tag to patch #2 +- Add Krzysztof's R-b tag to patch #3 + +v7->v8: +MHDP8501 HDMI/DP: +- Correct DT node name to "display-bridge". +- Remove "cdns,mhdp8501" from mhdp8501 dt-binding doc. + +HDMI/DP PHY: +- Introduced functions `wait_for_ack` and `wait_for_ack_clear` to handle + waiting with acknowledgment bits set and cleared respectively. +- Use FIELD_PRE() to set bitfields for both HDMI and DP PHY. + +v6->v7: +MHDP8501 HDMI/DP: +- Combine HDMI and DP driver into one mhdp8501 driver. + Use the connector type to load the corresponding functions. +- Remove connector init functions. +- Add in phy_hdmi.h to reuse 'enum hdmi_colorspace'. + +HDMI/DP PHY: +- Lowercase hex values +- Fix parameters indent issue on some functions +- Replace 'udelay' with 'usleep_range' + +v5->v6: +HDMI/DP bridge driver +- 8501 is the part number of Cadence MHDP on i.MX8MQ. + Use MHDP8501 to name hdmi/dp drivers and files. +- Add compatible "fsl,imx8mq-mhdp8501-dp" for i.MX8MQ DP driver +- Add compatible "fsl,imx8mq-mhdp8501-hdmi" for i.MX8MQ HDMI driver +- Combine HDMI and DP dt-bindings into one file cdns,mhdp8501.yaml +- Fix HDMI scrambling is not enable issue when driver working in 4Kp60 + mode. +- Add HDMI/DP PHY API mailbox protect. + +HDMI/DP PHY driver: +- Rename DP and HDMI PHY files and move to folder phy/freescale/ +- Remove properties num_lanes and link_rate from DP PHY driver. +- Combine HDMI and DP dt-bindings into one file fsl,imx8mq-dp-hdmi-phy.yaml +- Update compatible string to "fsl,imx8mq-dp-phy". +- Update compatible string to "fsl,imx8mq-hdmi-phy". + +v4->v5: +- Drop "clk" suffix in clock name. +- Add output port property in the example of hdmi/dp. + +v3->v4: +dt-bindings: +- Correct dt-bindings coding style and address review comments. +- Add apb_clk description. +- Add output port for HDMI/DP connector +PHY: +- Alphabetically sorted in Kconfig and Makefile for DP and HDMI PHY +- Remove unused registers define from HDMI and DP PHY drivers. +- More description in phy_hdmi.h. +- Add apb_clk to HDMI and DP phy driver. +HDMI/DP: +- Use get_unaligned_le32() to replace hardcode type conversion + in HDMI AVI infoframe data fill function. +- Add mailbox mutex lock in HDMI/DP driver for phy functions + to reslove race conditions between HDMI/DP and PHY drivers. +- Add apb_clk to both HDMI and DP driver. +- Rename some function names and add prefix with "cdns_hdmi/cdns_dp". +- Remove bpc 12 and 16 optional that not supported. + +v2->v3: +Address comments for dt-bindings files. +- Correct dts-bindings file names + Rename phy-cadence-hdptx-dp.yaml to cdns,mhdp-imx8mq-dp.yaml + Rename phy-cadence-hdptx-hdmi.yaml to cdns,mhdp-imx8mq-hdmi.yaml +- Drop redundant words and descriptions. +- Correct hdmi/dp node name. + +v2 is a completely different version compared to v1. +Previous v1 can be available here [1]. + +v1->v2: +- Reuse Cadence mailbox access functions from mhdp8546 instead of + rockchip DP. +- Mailbox access functions be convert to marco functions + that will be referenced by HDP-TX PHY(HDMI/DP) driver too. +- Plain bridge instead of component driver. +- Standalone Cadence HDP-TX PHY(HDMI/DP) driver. +- Audio driver are removed from the patch set, it will be add in another + patch set later. + +[1] https://patchwork.kernel.org/project/linux-rockchip/cover/cover.1590982881.git.Sandor.yu@nxp.com/ + +Alexander Stein (2): + arm64: dts: imx8mq: Add DCSS + HDMI/DP display pipeline + arm64: dts: imx8mq: tqma8mq-mba8mx: Enable HDMI support + +Sandor Yu (7): + soc: cadence: Create helper functions for Cadence MHDP + drm: bridge: cadence: Update mhdp8546 mailbox access functions + phy: Add HDMI configuration options + dt-bindings: display: bridge: Add Cadence MHDP8501 + drm: bridge: Cadence: Add MHDP8501 DP/HDMI driver + dt-bindings: phy: Add Freescale iMX8MQ DP and HDMI PHY + phy: freescale: Add DisplayPort/HDMI Combo-PHY driver for i.MX8MQ + + .../display/bridge/cdns,mhdp8501.yaml | 121 ++ + .../bindings/phy/fsl,imx8mq-dp-hdmi-phy.yaml | 51 + + .../dts/freescale/imx8mq-tqma8mq-mba8mx.dts | 26 + + arch/arm64/boot/dts/freescale/imx8mq.dtsi | 68 + + arch/arm64/boot/dts/freescale/mba8mx.dtsi | 11 + + drivers/gpu/drm/bridge/cadence/Kconfig | 17 + + drivers/gpu/drm/bridge/cadence/Makefile | 2 + + .../drm/bridge/cadence/cdns-mhdp8501-core.c | 379 +++++ + .../drm/bridge/cadence/cdns-mhdp8501-core.h | 380 +++++ + .../gpu/drm/bridge/cadence/cdns-mhdp8501-dp.c | 694 ++++++++++ + .../drm/bridge/cadence/cdns-mhdp8501-hdmi.c | 745 ++++++++++ + .../drm/bridge/cadence/cdns-mhdp8546-core.c | 487 ++----- + .../drm/bridge/cadence/cdns-mhdp8546-core.h | 47 +- + .../drm/bridge/cadence/cdns-mhdp8546-hdcp.c | 212 +-- + .../drm/bridge/cadence/cdns-mhdp8546-hdcp.h | 18 +- + drivers/phy/freescale/Kconfig | 10 + + drivers/phy/freescale/Makefile | 1 + + drivers/phy/freescale/phy-fsl-imx8mq-hdptx.c | 1231 +++++++++++++++++ + drivers/soc/Kconfig | 1 + + drivers/soc/Makefile | 1 + + drivers/soc/cadence/Kconfig | 9 + + drivers/soc/cadence/Makefile | 3 + + drivers/soc/cadence/cdns-mhdp-helper.c | 565 ++++++++ + include/linux/phy/phy-hdmi.h | 19 + + include/linux/phy/phy.h | 7 +- + include/soc/cadence/cdns-mhdp-helper.h | 129 ++ + 26 files changed, 4572 insertions(+), 662 deletions(-) + create mode 100644 Documentation/devicetree/bindings/display/bridge/cdns,mhdp8501.yaml + create mode 100644 Documentation/devicetree/bindings/phy/fsl,imx8mq-dp-hdmi-phy.yaml + create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-core.c + create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-core.h + create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-dp.c + create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-hdmi.c + create mode 100644 drivers/phy/freescale/phy-fsl-imx8mq-hdptx.c + create mode 100644 drivers/soc/cadence/Kconfig + create mode 100644 drivers/soc/cadence/Makefile + create mode 100644 drivers/soc/cadence/cdns-mhdp-helper.c + create mode 100644 include/linux/phy/phy-hdmi.h + create mode 100644 include/soc/cadence/cdns-mhdp-helper.h + +-- +2.34.1 + + + +From patchwork Tue Dec 17 06:51:43 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v20,1/9] soc: cadence: Create helper functions for Cadence MHDP +From: Sandor Yu +X-Patchwork-Id: 629288 +Message-Id: + <7fd5d54e2594aadd66598888ddf512f3d6d30e5d.1734340233.git.Sandor.yu@nxp.com> +To: dmitry.baryshkov@linaro.org, andrzej.hajda@intel.com, + neil.armstrong@linaro.org, Laurent.pinchart@ideasonboard.com, + jonas@kwiboo.se, jernej.skrabec@gmail.com, airlied@gmail.com, + daniel@ffwll.ch, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, + vkoul@kernel.org, dri-devel@lists.freedesktop.org, + devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, + mripard@kernel.org +Cc: kernel@pengutronix.de, linux-imx@nxp.com, Sandor.yu@nxp.com, + oliver.brown@nxp.com, alexander.stein@ew.tq-group.com, sam@ravnborg.org +Date: Tue, 17 Dec 2024 14:51:43 +0800 + +Cadence MHDP IP includes a firmware. Driver and firmware communicate +through a mailbox. The basic mailbox access functions in this patch +are derived from the DRM bridge MHDP8546 driver. +New mailbox access functions have been created based on different mailbox +return values and security types, making them reusable across different +MHDP driver versions and SOCs. + +These helper fucntions will be reused in both the DRM bridge driver MDHP8501 +and the i.MX8MQ HDPTX PHY driver. + +Six mailbox access helper functions are introduced. +Three for non-secure mailbox access: + - cdns_mhdp_mailbox_send() + - cdns_mhdp_mailbox_send_recv() + - cdns_mhdp_mailbox_send_recv_multi() +The other three for secure mailbox access: + - cdns_mhdp_secure_mailbox_send() + - cdns_mhdp_secure_mailbox_send_recv() + - cdns_mhdp_secure_mailbox_send_recv_multi() + +All MHDP commands that need to be passed through the mailbox +should be rewritten using these new helper functions. + +The register read/write and DP DPCD read/write command functions +are also included in this new helper driver. + +Signed-off-by: Sandor Yu +--- +v19->v20: +- new patch in v20. + The patch split from Patch #1 in v19 and move to a new folder drivers/soc/cadence + + drivers/soc/Kconfig | 1 + + drivers/soc/Makefile | 1 + + drivers/soc/cadence/Kconfig | 9 + + drivers/soc/cadence/Makefile | 3 + + drivers/soc/cadence/cdns-mhdp-helper.c | 565 +++++++++++++++++++++++++ + include/soc/cadence/cdns-mhdp-helper.h | 129 ++++++ + 6 files changed, 708 insertions(+) + create mode 100644 drivers/soc/cadence/Kconfig + create mode 100644 drivers/soc/cadence/Makefile + create mode 100644 drivers/soc/cadence/cdns-mhdp-helper.c + create mode 100644 include/soc/cadence/cdns-mhdp-helper.h + +diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig +index 6a8daeb8c4b96..f6c18114b2d68 100644 +--- a/drivers/soc/Kconfig ++++ b/drivers/soc/Kconfig +@@ -6,6 +6,7 @@ source "drivers/soc/apple/Kconfig" + source "drivers/soc/aspeed/Kconfig" + source "drivers/soc/atmel/Kconfig" + source "drivers/soc/bcm/Kconfig" ++source "drivers/soc/cadence/Kconfig" + source "drivers/soc/canaan/Kconfig" + source "drivers/soc/cirrus/Kconfig" + source "drivers/soc/fsl/Kconfig" +diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile +index 2037a8695cb28..a5fa4f4d15321 100644 +--- a/drivers/soc/Makefile ++++ b/drivers/soc/Makefile +@@ -7,6 +7,7 @@ obj-y += apple/ + obj-y += aspeed/ + obj-$(CONFIG_ARCH_AT91) += atmel/ + obj-y += bcm/ ++obj-y += cadence/ + obj-$(CONFIG_ARCH_CANAAN) += canaan/ + obj-$(CONFIG_EP93XX_SOC) += cirrus/ + obj-$(CONFIG_ARCH_DOVE) += dove/ +diff --git a/drivers/soc/cadence/Kconfig b/drivers/soc/cadence/Kconfig +new file mode 100644 +index 0000000000000..b668790660fa5 +--- /dev/null ++++ b/drivers/soc/cadence/Kconfig +@@ -0,0 +1,9 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++config CDNS_MHDP_HELPER ++ tristate "Cadence MHDP Helper driver" ++ help ++ Enable Cadence MHDP helpers for mailbox, HDMI and DP. ++ This driver provides a foundational layer of mailbox communication for ++ various Cadence MHDP IP implementations, such as HDMI and DisplayPort. ++ +diff --git a/drivers/soc/cadence/Makefile b/drivers/soc/cadence/Makefile +new file mode 100644 +index 0000000000000..a1f42e1936ca5 +--- /dev/null ++++ b/drivers/soc/cadence/Makefile +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++obj-$(CONFIG_CDNS_MHDP_HELPER) += cdns-mhdp-helper.o +diff --git a/drivers/soc/cadence/cdns-mhdp-helper.c b/drivers/soc/cadence/cdns-mhdp-helper.c +new file mode 100644 +index 0000000000000..f74b4cae134a2 +--- /dev/null ++++ b/drivers/soc/cadence/cdns-mhdp-helper.c +@@ -0,0 +1,565 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2023, 2024 NXP Semiconductor, Inc. ++ * ++ */ ++#include ++#include ++#include ++ ++/* Protects mailbox communications with the firmware */ ++static DEFINE_MUTEX(mhdp_mailbox_mutex); ++ ++/* Mailbox helper functions */ ++static int mhdp_mailbox_read(void __iomem *regs) ++{ ++ int ret, empty; ++ ++ WARN_ON(!mutex_is_locked(&mhdp_mailbox_mutex)); ++ ++ ret = readx_poll_timeout(readl, regs + CDNS_MAILBOX_EMPTY, ++ empty, !empty, MAILBOX_RETRY_US, ++ MAILBOX_TIMEOUT_US); ++ if (ret < 0) ++ return ret; ++ ++ return readl(regs + CDNS_MAILBOX_RX_DATA) & 0xff; ++} ++ ++static int mhdp_mailbox_write(void __iomem *regs, u8 val) ++{ ++ int ret, full; ++ ++ WARN_ON(!mutex_is_locked(&mhdp_mailbox_mutex)); ++ ++ ret = readx_poll_timeout(readl, regs + CDNS_MAILBOX_FULL, ++ full, !full, MAILBOX_RETRY_US, ++ MAILBOX_TIMEOUT_US); ++ if (ret < 0) ++ return ret; ++ ++ writel(val, regs + CDNS_MAILBOX_TX_DATA); ++ ++ return 0; ++} ++ ++static int mhdp_mailbox_recv_header(void __iomem *regs, ++ u8 module_id, u8 opcode, ++ u16 req_size) ++{ ++ u32 mbox_size, i; ++ u8 header[4]; ++ int ret; ++ ++ /* read the header of the message */ ++ for (i = 0; i < sizeof(header); i++) { ++ ret = mhdp_mailbox_read(regs); ++ if (ret < 0) ++ return ret; ++ ++ header[i] = ret; ++ } ++ ++ mbox_size = get_unaligned_be16(header + 2); ++ ++ /* ++ * If the message in mailbox is not what we want, we need to ++ * clear the mailbox by reading its contents. ++ * Response data length for HDCP TX HDCP_TRAN_IS_REC_ID_VALID depend on case. ++ */ ++ if (opcode != header[0] || ++ module_id != header[1] || ++ (opcode != HDCP_TRAN_IS_REC_ID_VALID && req_size != mbox_size)) { ++ for (i = 0; i < mbox_size; i++) ++ if (mhdp_mailbox_read(regs) < 0) ++ break; ++ ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int mhdp_mailbox_recv_data(void __iomem *regs, ++ u8 *buff, u16 buff_size) ++{ ++ u32 i; ++ int ret; ++ ++ for (i = 0; i < buff_size; i++) { ++ ret = mhdp_mailbox_read(regs); ++ if (ret < 0) ++ return ret; ++ ++ buff[i] = ret; ++ } ++ ++ return 0; ++} ++ ++static int mhdp_mailbox_send(void __iomem *regs, u8 module_id, ++ u8 opcode, u16 size, u8 *message) ++{ ++ u8 header[4]; ++ int ret, i; ++ ++ header[0] = opcode; ++ header[1] = module_id; ++ put_unaligned_be16(size, header + 2); ++ ++ for (i = 0; i < sizeof(header); i++) { ++ ret = mhdp_mailbox_write(regs, header[i]); ++ if (ret) ++ return ret; ++ } ++ ++ for (i = 0; i < size; i++) { ++ ret = mhdp_mailbox_write(regs, message[i]); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/** ++ * cdns_mhdp_mailbox_send - Sends a message via the MHDP mailbox. ++ * ++ * This function sends a message via the MHDP mailbox. ++ * ++ * @base: Pointer to the CDNS MHDP base structure. ++ * @module_id: ID of the module to send the message to. ++ * @opcode: Operation code of the message. ++ * @size: Size of the message data. ++ * @message: Pointer to the message data. ++ * ++ * Returns: 0 on success, negative error code on failure. ++ */ ++int cdns_mhdp_mailbox_send(struct cdns_mhdp_base *base, u8 module_id, ++ u8 opcode, u16 size, u8 *message) ++{ ++ guard(mutex)(&mhdp_mailbox_mutex); ++ ++ return mhdp_mailbox_send(base->regs, module_id, opcode, size, message); ++} ++EXPORT_SYMBOL_GPL(cdns_mhdp_mailbox_send); ++ ++/** ++ * cdns_mhdp_mailbox_send_recv - Sends a message and receives a response. ++ * ++ * This function sends a message via the mailbox and then receives a response. ++ * ++ * @base: Pointer to the CDNS MHDP base structure. ++ * @module_id: ID of the module to send the message to. ++ * @opcode: Operation code of the message. ++ * @msg_size: Size of the message data. ++ * @msg: Pointer to the message data. ++ * @resp_size: Size of the response buffer. ++ * @resp: Pointer to the response buffer. ++ * ++ * Returns: 0 on success, negative error code on failure. ++ */ ++int cdns_mhdp_mailbox_send_recv(struct cdns_mhdp_base *base, ++ u8 module_id, u8 opcode, ++ u16 msg_size, u8 *msg, ++ u16 resp_size, u8 *resp) ++{ ++ int ret; ++ ++ guard(mutex)(&mhdp_mailbox_mutex); ++ ++ ret = mhdp_mailbox_send(base->regs, module_id, ++ opcode, msg_size, msg); ++ if (ret) { ++ dev_err(base->dev, "ModuleID=%d, CMD=%d send failed: %d\n", ++ module_id, opcode, ret); ++ return ret; ++ } ++ ++ ret = mhdp_mailbox_recv_header(base->regs, module_id, ++ opcode, resp_size); ++ if (ret) { ++ dev_err(base->dev, "ModuleID=%d, CMD=%d recv header failed: %d\n", ++ module_id, opcode, ret); ++ return ret; ++ } ++ ++ ret = mhdp_mailbox_recv_data(base->regs, resp, resp_size); ++ if (ret) ++ dev_err(base->dev, "ModuleID=%d, CMD=%d recv data failed: %d\n", ++ module_id, opcode, ret); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(cdns_mhdp_mailbox_send_recv); ++ ++/** ++ * cdns_mhdp_mailbox_send_recv_multi - Sends a message and receives multiple responses. ++ * ++ * This function sends a message to a specified module via the MHDP mailbox and ++ * then receives multiple responses from the module. ++ * ++ * @param base: Pointer to the CDNS MHDP base structure. ++ * @param module_id: ID of the module to send the message to. ++ * @param opcode: Operation code of the message. ++ * @param msg_size: Size of the message data. ++ * @param msg: Pointer to the message data. ++ * @param opcode_resp: Operation code of the response. ++ * @param resp1_size: Size of the first response buffer. ++ * @param resp1: Pointer to the first response buffer. ++ * @param resp2_size: Size of the second response buffer. ++ * @param resp2: Pointer to the second response buffer. ++ * ++ * Returns: 0 on success, negative error code on failure. ++ */ ++int cdns_mhdp_mailbox_send_recv_multi(struct cdns_mhdp_base *base, ++ u8 module_id, u8 opcode, ++ u16 msg_size, u8 *msg, ++ u8 opcode_resp, ++ u16 resp1_size, u8 *resp1, ++ u16 resp2_size, u8 *resp2) ++{ ++ int ret; ++ ++ guard(mutex)(&mhdp_mailbox_mutex); ++ ++ ret = mhdp_mailbox_send(base->regs, module_id, ++ opcode, msg_size, msg); ++ if (ret) { ++ dev_err(base->dev, "ModuleID=%d, CMD=%d send failed: %d\n", ++ module_id, opcode, ret); ++ return ret; ++ } ++ ++ ret = mhdp_mailbox_recv_header(base->regs, module_id, opcode_resp, ++ resp1_size + resp2_size); ++ if (ret) { ++ dev_err(base->dev, "ModuleID=%d, Resp_CMD=%d recv header failed: %d\n", ++ module_id, opcode_resp, ret); ++ return ret; ++ } ++ ++ ret = mhdp_mailbox_recv_data(base->regs, resp1, resp1_size); ++ if (ret) { ++ dev_err(base->dev, "ModuleID=%d, Resp_CMD=%d recv data1 failed: %d\n", ++ module_id, opcode_resp, ret); ++ return ret; ++ } ++ ++ ret = mhdp_mailbox_recv_data(base->regs, resp2, resp2_size); ++ if (ret) ++ dev_err(base->dev, "ModuleID=%d, Resp_CMD=%d recv data1 failed: %d\n", ++ module_id, opcode_resp, ret); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(cdns_mhdp_mailbox_send_recv_multi); ++ ++/** ++ * cdns_mhdp_secure_mailbox_send - Sends a secure message via the mailbox. ++ * ++ * This function sends a secure message to a specified module via the MHDP mailbox. ++ * ++ * @param base: Pointer to the CDNS MHDP base structure. ++ * @param module_id: ID of the module to send the message to. ++ * @param opcode: Operation code of the message. ++ * @param size: Size of the message data. ++ * @param message: Pointer to the message data. ++ * ++ * Returns: 0 on success, negative error code on failure. ++ */ ++int cdns_mhdp_secure_mailbox_send(struct cdns_mhdp_base *base, u8 module_id, ++ u8 opcode, u16 size, u8 *message) ++{ ++ guard(mutex)(&mhdp_mailbox_mutex); ++ ++ return mhdp_mailbox_send(base->sapb_regs, module_id, opcode, size, message); ++} ++EXPORT_SYMBOL_GPL(cdns_mhdp_secure_mailbox_send); ++ ++/** ++ * cdns_mhdp_secure_mailbox_send_recv - Sends a secure message and receives a response. ++ * ++ * This function sends a secure message to a specified module via the mailbox and ++ * then receives a response from the module. ++ * ++ * @param base: Pointer to the CDNS MHDP base structure. ++ * @param module_id: ID of the module to send the message to. ++ * @param opcode: Operation code of the message. ++ * @param msg_size: Size of the message data. ++ * @param msg: Pointer to the message data. ++ * @param resp_size: Size of the response buffer. ++ * @param resp: Pointer to the response buffer. ++ * ++ * Returns: 0 on success, negative error code on failure. ++ */ ++int cdns_mhdp_secure_mailbox_send_recv(struct cdns_mhdp_base *base, ++ u8 module_id, u8 opcode, ++ u16 msg_size, u8 *msg, ++ u16 resp_size, u8 *resp) ++{ ++ int ret; ++ ++ guard(mutex)(&mhdp_mailbox_mutex); ++ ++ ret = mhdp_mailbox_send(base->sapb_regs, module_id, ++ opcode, msg_size, msg); ++ if (ret) { ++ dev_err(base->dev, "ModuleID=%d, CMD=%d send failed: %d\n", ++ module_id, opcode, ret); ++ return ret; ++ } ++ ++ ret = mhdp_mailbox_recv_header(base->sapb_regs, module_id, ++ opcode, resp_size); ++ if (ret) { ++ dev_err(base->dev, "ModuleID=%d, CMD=%d recv header failed: %d\n", ++ module_id, opcode, ret); ++ return ret; ++ } ++ ++ ret = mhdp_mailbox_recv_data(base->sapb_regs, resp, resp_size); ++ if (ret) ++ dev_err(base->dev, "ModuleID=%d, CMD=%d recv data failed: %d\n", ++ module_id, opcode, ret); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(cdns_mhdp_secure_mailbox_send_recv); ++ ++/** ++ * cdns_mhdp_secure_mailbox_send_recv_multi - Sends a secure message and receives multiple responses. ++ * ++ * This function sends a secure message to a specified module and receives multiple responses. ++ * ++ * @param base: Pointer to the CDNS MHDP base structure. ++ * @param module_id: ID of the module to send the message to. ++ * @param opcode: Operation code of the message. ++ * @param msg_size: Size of the message data. ++ * @param msg: Pointer to the message data. ++ * @param opcode_resp: Operation code of the response. ++ * @param resp1_size: Size of the first response buffer. ++ * @param resp1: Pointer to the first response buffer. ++ * @param resp2_size: Size of the second response buffer. ++ * @param resp2: Pointer to the second response buffer. ++ * ++ * Returns: 0 on success, negative error code on failure. ++ */ ++int cdns_mhdp_secure_mailbox_send_recv_multi(struct cdns_mhdp_base *base, ++ u8 module_id, u8 opcode, ++ u16 msg_size, u8 *msg, ++ u8 opcode_resp, ++ u16 resp1_size, u8 *resp1, ++ u16 resp2_size, u8 *resp2) ++{ ++ int ret; ++ ++ guard(mutex)(&mhdp_mailbox_mutex); ++ ++ ret = mhdp_mailbox_send(base->sapb_regs, module_id, ++ opcode, msg_size, msg); ++ if (ret) { ++ dev_err(base->dev, "ModuleID=%d, CMD=%d send failed: %d\n", ++ module_id, opcode, ret); ++ return ret; ++ } ++ ++ ret = mhdp_mailbox_recv_header(base->sapb_regs, module_id, ++ opcode_resp, ++ resp1_size + resp2_size); ++ if (ret) { ++ dev_err(base->dev, "ModuleID=%d, Resp_CMD=%d recv header failed: %d\n", ++ module_id, opcode_resp, ret); ++ return ret; ++ } ++ ++ ret = mhdp_mailbox_recv_data(base->sapb_regs, resp1, resp1_size); ++ if (ret) { ++ dev_err(base->dev, "ModuleID=%d, Resp_CMD=%d recv data1 failed: %d\n", ++ module_id, opcode_resp, ret); ++ return ret; ++ } ++ ++ /* ++ * Response data length for HDCP TX HDCP_TRAN_IS_REC_ID_VALID depend on ++ * the number of HDCP receivers in resp1[0]. ++ * 1 for regular case, more can be in repeater. ++ */ ++ if (module_id == MB_MODULE_ID_HDCP_TX && ++ opcode == HDCP_TRAN_IS_REC_ID_VALID) ++ ret = mhdp_mailbox_recv_data(base->sapb_regs, resp2, 5 * resp1[0]); ++ else ++ ret = mhdp_mailbox_recv_data(base->sapb_regs, resp2, resp2_size); ++ if (ret) ++ dev_err(base->dev, "ModuleID=%d, Resp_CMD=%d recv data2 failed: %d\n", ++ module_id, opcode_resp, ret); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(cdns_mhdp_secure_mailbox_send_recv_multi); ++ ++/** ++ * cdns_mhdp_reg_read - Reads a general register value. ++ * ++ * This function reads the value from a general register ++ * using the mailbox. ++ * ++ * @param base: Pointer to the CDNS MHDP base structure. ++ * @param addr: Address of the register to read. ++ * @param value: Pointer to store the read value. ++ * ++ * Returns: 0 on success, negative error code on failure. ++ */ ++int cdns_mhdp_reg_read(struct cdns_mhdp_base *base, u32 addr, u32 *value) ++{ ++ u8 msg[4], resp[8]; ++ int ret; ++ ++ put_unaligned_be32(addr, msg); ++ ++ ret = cdns_mhdp_mailbox_send_recv(base, MB_MODULE_ID_GENERAL, ++ GENERAL_REGISTER_READ, ++ sizeof(msg), msg, sizeof(resp), resp); ++ if (ret) ++ goto out; ++ ++ /* Returned address value should be the same as requested */ ++ if (memcmp(msg, resp, sizeof(msg))) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ *value = get_unaligned_be32(resp + 4); ++out: ++ if (ret) { ++ dev_err(base->dev, "Failed to read register\n"); ++ *value = 0; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(cdns_mhdp_reg_read); ++ ++/** ++ * cdns_mhdp_reg_write - Writes a value to a general register. ++ * ++ * This function writes a value to a general register using the mailbox. ++ * ++ * @param base: Pointer to the CDNS MHDP base structure. ++ * @param addr: Address of the register to write to. ++ * @param val: Value to write to the register. ++ * ++ * Returns: 0 on success, negative error code on failure. ++ */ ++int cdns_mhdp_reg_write(struct cdns_mhdp_base *base, u32 addr, u32 val) ++{ ++ u8 msg[8]; ++ ++ put_unaligned_be32(addr, msg); ++ put_unaligned_be32(val, msg + 4); ++ ++ return cdns_mhdp_mailbox_send(base, MB_MODULE_ID_GENERAL, ++ GENERAL_REGISTER_WRITE, ++ sizeof(msg), msg); ++} ++EXPORT_SYMBOL_GPL(cdns_mhdp_reg_write); ++ ++/* DPTX helper functions */ ++/** ++ * cdns_mhdp_dp_reg_write_bit - Writes a bit field to a DP register. ++ * ++ * This function writes a specific bit field within a DP register ++ * using the MHDP mailbox. ++ * ++ * @param base: Pointer to the CDNS MHDP base structure. ++ * @param addr: Address of the DP register. ++ * @param start_bit: Starting bit position within the register. ++ * @param bits_no: Number of bits to write. ++ * @param val: Value to write to the bit field. ++ * ++ * Returns: 0 on success, negative error code on failure. ++ */ ++int cdns_mhdp_dp_reg_write_bit(struct cdns_mhdp_base *base, u16 addr, ++ u8 start_bit, u8 bits_no, u32 val) ++{ ++ u8 field[8]; ++ ++ put_unaligned_be16(addr, field); ++ field[2] = start_bit; ++ field[3] = bits_no; ++ put_unaligned_be32(val, field + 4); ++ ++ return cdns_mhdp_mailbox_send(base, MB_MODULE_ID_DP_TX, ++ DPTX_WRITE_FIELD, sizeof(field), field); ++} ++EXPORT_SYMBOL_GPL(cdns_mhdp_dp_reg_write_bit); ++ ++/** ++ * cdns_mhdp_dpcd_read - Reads data from a DPCD register. ++ * ++ * This function reads data from a specified DPCD register ++ * using the MHDP mailbox. ++ * ++ * @param base: Pointer to the CDNS MHDP base structure. ++ * @param addr: Address of the DPCD register to read. ++ * @param data: Buffer to store the read data. ++ * @param len: Length of the data to read. ++ * ++ * Returns: 0 on success, negative error code on failure. ++ */ ++int cdns_mhdp_dpcd_read(struct cdns_mhdp_base *base, ++ u32 addr, u8 *data, u16 len) ++{ ++ u8 msg[5], reg[5]; ++ ++ put_unaligned_be16(len, msg); ++ put_unaligned_be24(addr, msg + 2); ++ ++ return cdns_mhdp_mailbox_send_recv_multi(base, ++ MB_MODULE_ID_DP_TX, ++ DPTX_READ_DPCD, ++ sizeof(msg), msg, ++ DPTX_READ_DPCD, ++ sizeof(reg), reg, ++ len, data); ++} ++EXPORT_SYMBOL_GPL(cdns_mhdp_dpcd_read); ++ ++/** ++ * cdns_mhdp_dpcd_write - Writes data to a DPCD register. ++ * ++ * This function writes data to a specified DPCD register ++ * using the MHDP mailbox. ++ * ++ * @param base: Pointer to the CDNS MHDP base structure. ++ * @param addr: Address of the DPCD register to write to. ++ * @param value: Value to write to the register. ++ * ++ * Returns: 0 on success, negative error code on failure. ++ */ ++int cdns_mhdp_dpcd_write(struct cdns_mhdp_base *base, u32 addr, u8 value) ++{ ++ u8 msg[6], reg[5]; ++ int ret; ++ ++ put_unaligned_be16(1, msg); ++ put_unaligned_be24(addr, msg + 2); ++ msg[5] = value; ++ ++ ret = cdns_mhdp_mailbox_send_recv(base, MB_MODULE_ID_DP_TX, ++ DPTX_WRITE_DPCD, ++ sizeof(msg), msg, sizeof(reg), reg); ++ if (ret) { ++ dev_err(base->dev, "dpcd write failed: %d\n", ret); ++ return ret; ++ } ++ ++ if (addr != get_unaligned_be24(reg + 2)) { ++ dev_err(base->dev, "Invalid response: expected address 0x%06x, got 0x%06x\n", ++ addr, get_unaligned_be24(reg + 2)); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(cdns_mhdp_dpcd_write); ++ ++MODULE_DESCRIPTION("Cadence MHDP Helper driver"); ++MODULE_AUTHOR("Sandor Yu "); ++MODULE_LICENSE("GPL"); +diff --git a/include/soc/cadence/cdns-mhdp-helper.h b/include/soc/cadence/cdns-mhdp-helper.h +new file mode 100644 +index 0000000000000..25b9737de615f +--- /dev/null ++++ b/include/soc/cadence/cdns-mhdp-helper.h +@@ -0,0 +1,129 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (C) 2023-2024 NXP Semiconductor, Inc. ++ */ ++#ifndef __CDNS_MHDP_HELPER_H__ ++#define __CDNS_MHDP_HELPER_H__ ++ ++#include ++#include ++ ++/* mailbox regs offset */ ++#define CDNS_MAILBOX_FULL 0x00008 ++#define CDNS_MAILBOX_EMPTY 0x0000c ++#define CDNS_MAILBOX_TX_DATA 0x00010 ++#define CDNS_MAILBOX_RX_DATA 0x00014 ++ ++#define MAILBOX_RETRY_US 1000 ++#define MAILBOX_TIMEOUT_US 2000000 ++ ++/* Module ID Code */ ++#define MB_MODULE_ID_DP_TX 0x01 ++#define MB_MODULE_ID_HDMI_TX 0x03 ++#define MB_MODULE_ID_HDCP_TX 0x07 ++#define MB_MODULE_ID_HDCP_RX 0x08 ++#define MB_MODULE_ID_HDCP_GENERAL 0x09 ++#define MB_MODULE_ID_GENERAL 0x0A ++ ++/* General Commands */ ++#define GENERAL_MAIN_CONTROL 0x01 ++#define GENERAL_TEST_ECHO 0x02 ++#define GENERAL_BUS_SETTINGS 0x03 ++#define GENERAL_TEST_ACCESS 0x04 ++#define GENERAL_REGISTER_WRITE 0x05 ++#define GENERAL_WRITE_FIELD 0x06 ++#define GENERAL_REGISTER_READ 0x07 ++#define GENERAL_GET_HPD_STATE 0x11 ++ ++/* DPTX Commands */ ++#define DPTX_SET_POWER_MNG 0x00 ++#define DPTX_SET_HOST_CAPABILITIES 0x01 ++#define DPTX_GET_EDID 0x02 ++#define DPTX_READ_DPCD 0x03 ++#define DPTX_WRITE_DPCD 0x04 ++#define DPTX_ENABLE_EVENT 0x05 ++#define DPTX_WRITE_REGISTER 0x06 ++#define DPTX_READ_REGISTER 0x07 ++#define DPTX_WRITE_FIELD 0x08 ++#define DPTX_TRAINING_CONTROL 0x09 ++#define DPTX_READ_EVENT 0x0a ++#define DPTX_READ_LINK_STAT 0x0b ++#define DPTX_SET_VIDEO 0x0c ++#define DPTX_SET_AUDIO 0x0d ++#define DPTX_GET_LAST_AUX_STAUS 0x0e ++#define DPTX_SET_LINK_BREAK_POINT 0x0f ++#define DPTX_FORCE_LANES 0x10 ++#define DPTX_HPD_STATE 0x11 ++#define DPTX_ADJUST_LT 0x12 ++ ++/* HDMI TX Commands */ ++#define HDMI_TX_READ 0x00 ++#define HDMI_TX_WRITE 0x01 ++#define HDMI_TX_UPDATE_READ 0x02 ++#define HDMI_TX_EDID 0x03 ++#define HDMI_TX_EVENTS 0x04 ++#define HDMI_TX_HPD_STATUS 0x05 ++ ++/* HDCP TX Commands */ ++#define HDCP_TRAN_CONFIGURATION 0x00 ++#define HDCP2X_TX_SET_PUBLIC_KEY_PARAMS 0x01 ++#define HDCP2X_TX_SET_DEBUG_RANDOM_NUMBERS 0x02 ++#define HDCP2X_TX_RESPOND_KM 0x03 ++#define HDCP1_TX_SEND_KEYS 0x04 ++#define HDCP1_TX_SEND_RANDOM_AN 0x05 ++#define HDCP_TRAN_STATUS_CHANGE 0x06 ++#define HDCP2X_TX_IS_KM_STORED 0x07 ++#define HDCP2X_TX_STORE_KM 0x08 ++#define HDCP_TRAN_IS_REC_ID_VALID 0x09 ++#define HDCP_TRAN_RESPOND_RECEIVER_ID_VALID 0x09 ++#define HDCP_TRAN_TEST_KEYS 0x0a ++#define HDCP2X_TX_SET_KM_KEY_PARAMS 0x0b ++#define HDCP_NUM_OF_SUPPORTED_MESSAGES 0x0c ++ ++struct cdns_mhdp_base { ++ struct device *dev; ++ void __iomem *regs; ++ void __iomem *sapb_regs; ++}; ++ ++/* Mailbox helper functions */ ++int cdns_mhdp_mailbox_send(struct cdns_mhdp_base *base, ++ u8 module_id, u8 opcode, ++ u16 size, u8 *message); ++int cdns_mhdp_mailbox_send_recv(struct cdns_mhdp_base *base, ++ u8 module_id, u8 opcode, ++ u16 msg_size, u8 *msg, ++ u16 resp_size, u8 *resp); ++int cdns_mhdp_mailbox_send_recv_multi(struct cdns_mhdp_base *base, ++ u8 module_id, u8 opcode, ++ u16 msg_size, u8 *msg, ++ u8 opcode_resp, ++ u16 resp1_size, u8 *resp1, ++ u16 resp2_size, u8 *resp2); ++ ++/* Secure mailbox helper functions */ ++int cdns_mhdp_secure_mailbox_send(struct cdns_mhdp_base *base, ++ u8 module_id, u8 opcode, ++ u16 size, u8 *message); ++int cdns_mhdp_secure_mailbox_send_recv(struct cdns_mhdp_base *base, ++ u8 module_id, u8 opcode, ++ u16 msg_size, u8 *msg, ++ u16 resp_size, u8 *resp); ++int cdns_mhdp_secure_mailbox_send_recv_multi(struct cdns_mhdp_base *base, ++ u8 module_id, u8 opcode, ++ u16 msg_size, u8 *msg, ++ u8 opcode_resp, ++ u16 resp1_size, u8 *resp1, ++ u16 resp2_size, u8 *resp2); ++ ++/* General commands helper functions */ ++int cdns_mhdp_reg_read(struct cdns_mhdp_base *base, u32 addr, u32 *value); ++int cdns_mhdp_reg_write(struct cdns_mhdp_base *base, u32 addr, u32 val); ++ ++/* DPTX commands helper functions */ ++int cdns_mhdp_dp_reg_write_bit(struct cdns_mhdp_base *base, u16 addr, ++ u8 start_bit, u8 bits_no, u32 val); ++int cdns_mhdp_dpcd_read(struct cdns_mhdp_base *base, ++ u32 addr, u8 *data, u16 len); ++int cdns_mhdp_dpcd_write(struct cdns_mhdp_base *base, u32 addr, u8 value); ++#endif /* __CDNS_MHDP_HELPER_H__ */ + +From patchwork Tue Dec 17 06:51:44 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v20,2/9] drm: bridge: cadence: Update mhdp8546 mailbox access + functions +From: Sandor Yu +X-Patchwork-Id: 629289 +Message-Id: + <74bc3f2ff56348afd9d773589236ddf06dc3d45c.1734340233.git.Sandor.yu@nxp.com> +To: dmitry.baryshkov@linaro.org, andrzej.hajda@intel.com, + neil.armstrong@linaro.org, Laurent.pinchart@ideasonboard.com, + jonas@kwiboo.se, jernej.skrabec@gmail.com, airlied@gmail.com, + daniel@ffwll.ch, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, + vkoul@kernel.org, dri-devel@lists.freedesktop.org, + devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, + mripard@kernel.org +Cc: kernel@pengutronix.de, linux-imx@nxp.com, Sandor.yu@nxp.com, + oliver.brown@nxp.com, alexander.stein@ew.tq-group.com, sam@ravnborg.org +Date: Tue, 17 Dec 2024 14:51:44 +0800 + +Basic mailbox access functions are removed, they are replaced by +mailbox helper functions: +- cdns_mhdp_mailbox_send() +- cdns_mhdp_mailbox_send_recv() +- cdns_mhdp_mailbox_send_recv_multi() +- cdns_mhdp_secure_mailbox_send() +- cdns_mhdp_secure_mailbox_send_recv() +- cdns_mhdp_secure_mailbox_send_recv_multi() + +All MHDP commands that need to be passed through the mailbox +have been rewritten using these new helper functions. + +Signed-off-by: Sandor Yu +Reviewed-by: Dmitry Baryshkov +--- +v19->v20: +- remove mhdp helper functions from the patch. + +v18->v19: +- Use guard(mutex) +- Add kerneldocs for all new APIs. +- Detail comments for mailbox access specific case. +- Remove cdns_mhdp_dp_reg_write() because it is not needed by driver now. + +v17->v18: +- Create three ordinary mailbox access APIs + cdns_mhdp_mailbox_send + cdns_mhdp_mailbox_send_recv + cdns_mhdp_mailbox_send_recv_multi +- Create three secure mailbox access APIs + cdns_mhdp_secure_mailbox_send + cdns_mhdp_secure_mailbox_send_recv + cdns_mhdp_secure_mailbox_send_recv_multi +- MHDP8546 DP and HDCP commands that need access mailbox are rewrited + with above 6 API functions. + +v16->v17: +- Replaces the local mutex mbox_mutex with a global mutex mhdp_mailbox_mutex + +v12->v16: + *No change. + + drivers/gpu/drm/bridge/cadence/Kconfig | 1 + + .../drm/bridge/cadence/cdns-mhdp8546-core.c | 487 +++--------------- + .../drm/bridge/cadence/cdns-mhdp8546-core.h | 47 +- + .../drm/bridge/cadence/cdns-mhdp8546-hdcp.c | 212 +------- + .../drm/bridge/cadence/cdns-mhdp8546-hdcp.h | 18 +- + 5 files changed, 104 insertions(+), 661 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig +index cced81633ddcd..dbb06533ccab2 100644 +--- a/drivers/gpu/drm/bridge/cadence/Kconfig ++++ b/drivers/gpu/drm/bridge/cadence/Kconfig +@@ -28,6 +28,7 @@ config DRM_CDNS_MHDP8546 + select DRM_DISPLAY_HELPER + select DRM_KMS_HELPER + select DRM_PANEL_BRIDGE ++ select CDNS_MHDP_HELPER + depends on OF + help + Support Cadence DPI to DP bridge. This is an internal +diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +index d081850e3c03e..bd897c3ae7642 100644 +--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c ++++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +@@ -73,302 +73,18 @@ static void cdns_mhdp_bridge_hpd_disable(struct drm_bridge *bridge) + mhdp->regs + CDNS_APB_INT_MASK); + } + +-static int cdns_mhdp_mailbox_read(struct cdns_mhdp_device *mhdp) +-{ +- int ret, empty; +- +- WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex)); +- +- ret = readx_poll_timeout(readl, mhdp->regs + CDNS_MAILBOX_EMPTY, +- empty, !empty, MAILBOX_RETRY_US, +- MAILBOX_TIMEOUT_US); +- if (ret < 0) +- return ret; +- +- return readl(mhdp->regs + CDNS_MAILBOX_RX_DATA) & 0xff; +-} +- +-static int cdns_mhdp_mailbox_write(struct cdns_mhdp_device *mhdp, u8 val) +-{ +- int ret, full; +- +- WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex)); +- +- ret = readx_poll_timeout(readl, mhdp->regs + CDNS_MAILBOX_FULL, +- full, !full, MAILBOX_RETRY_US, +- MAILBOX_TIMEOUT_US); +- if (ret < 0) +- return ret; +- +- writel(val, mhdp->regs + CDNS_MAILBOX_TX_DATA); +- +- return 0; +-} +- +-static int cdns_mhdp_mailbox_recv_header(struct cdns_mhdp_device *mhdp, +- u8 module_id, u8 opcode, +- u16 req_size) +-{ +- u32 mbox_size, i; +- u8 header[4]; +- int ret; +- +- /* read the header of the message */ +- for (i = 0; i < sizeof(header); i++) { +- ret = cdns_mhdp_mailbox_read(mhdp); +- if (ret < 0) +- return ret; +- +- header[i] = ret; +- } +- +- mbox_size = get_unaligned_be16(header + 2); +- +- if (opcode != header[0] || module_id != header[1] || +- req_size != mbox_size) { +- /* +- * If the message in mailbox is not what we want, we need to +- * clear the mailbox by reading its contents. +- */ +- for (i = 0; i < mbox_size; i++) +- if (cdns_mhdp_mailbox_read(mhdp) < 0) +- break; +- +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int cdns_mhdp_mailbox_recv_data(struct cdns_mhdp_device *mhdp, +- u8 *buff, u16 buff_size) +-{ +- u32 i; +- int ret; +- +- for (i = 0; i < buff_size; i++) { +- ret = cdns_mhdp_mailbox_read(mhdp); +- if (ret < 0) +- return ret; +- +- buff[i] = ret; +- } +- +- return 0; +-} +- +-static int cdns_mhdp_mailbox_send(struct cdns_mhdp_device *mhdp, u8 module_id, +- u8 opcode, u16 size, u8 *message) +-{ +- u8 header[4]; +- int ret, i; +- +- header[0] = opcode; +- header[1] = module_id; +- put_unaligned_be16(size, header + 2); +- +- for (i = 0; i < sizeof(header); i++) { +- ret = cdns_mhdp_mailbox_write(mhdp, header[i]); +- if (ret) +- return ret; +- } +- +- for (i = 0; i < size; i++) { +- ret = cdns_mhdp_mailbox_write(mhdp, message[i]); +- if (ret) +- return ret; +- } +- +- return 0; +-} +- +-static +-int cdns_mhdp_reg_read(struct cdns_mhdp_device *mhdp, u32 addr, u32 *value) +-{ +- u8 msg[4], resp[8]; +- int ret; +- +- put_unaligned_be32(addr, msg); +- +- mutex_lock(&mhdp->mbox_mutex); +- +- ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_GENERAL, +- GENERAL_REGISTER_READ, +- sizeof(msg), msg); +- if (ret) +- goto out; +- +- ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_GENERAL, +- GENERAL_REGISTER_READ, +- sizeof(resp)); +- if (ret) +- goto out; +- +- ret = cdns_mhdp_mailbox_recv_data(mhdp, resp, sizeof(resp)); +- if (ret) +- goto out; +- +- /* Returned address value should be the same as requested */ +- if (memcmp(msg, resp, sizeof(msg))) { +- ret = -EINVAL; +- goto out; +- } +- +- *value = get_unaligned_be32(resp + 4); +- +-out: +- mutex_unlock(&mhdp->mbox_mutex); +- if (ret) { +- dev_err(mhdp->dev, "Failed to read register\n"); +- *value = 0; +- } +- +- return ret; +-} +- +-static +-int cdns_mhdp_reg_write(struct cdns_mhdp_device *mhdp, u16 addr, u32 val) +-{ +- u8 msg[6]; +- int ret; +- +- put_unaligned_be16(addr, msg); +- put_unaligned_be32(val, msg + 2); +- +- mutex_lock(&mhdp->mbox_mutex); +- +- ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_WRITE_REGISTER, sizeof(msg), msg); +- +- mutex_unlock(&mhdp->mbox_mutex); +- +- return ret; +-} +- +-static +-int cdns_mhdp_reg_write_bit(struct cdns_mhdp_device *mhdp, u16 addr, +- u8 start_bit, u8 bits_no, u32 val) +-{ +- u8 field[8]; +- int ret; +- +- put_unaligned_be16(addr, field); +- field[2] = start_bit; +- field[3] = bits_no; +- put_unaligned_be32(val, field + 4); +- +- mutex_lock(&mhdp->mbox_mutex); +- +- ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_WRITE_FIELD, sizeof(field), field); +- +- mutex_unlock(&mhdp->mbox_mutex); +- +- return ret; +-} +- +-static +-int cdns_mhdp_dpcd_read(struct cdns_mhdp_device *mhdp, +- u32 addr, u8 *data, u16 len) +-{ +- u8 msg[5], reg[5]; +- int ret; +- +- put_unaligned_be16(len, msg); +- put_unaligned_be24(addr, msg + 2); +- +- mutex_lock(&mhdp->mbox_mutex); +- +- ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_READ_DPCD, sizeof(msg), msg); +- if (ret) +- goto out; +- +- ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_READ_DPCD, +- sizeof(reg) + len); +- if (ret) +- goto out; +- +- ret = cdns_mhdp_mailbox_recv_data(mhdp, reg, sizeof(reg)); +- if (ret) +- goto out; +- +- ret = cdns_mhdp_mailbox_recv_data(mhdp, data, len); +- +-out: +- mutex_unlock(&mhdp->mbox_mutex); +- +- return ret; +-} +- +-static +-int cdns_mhdp_dpcd_write(struct cdns_mhdp_device *mhdp, u32 addr, u8 value) +-{ +- u8 msg[6], reg[5]; +- int ret; +- +- put_unaligned_be16(1, msg); +- put_unaligned_be24(addr, msg + 2); +- msg[5] = value; +- +- mutex_lock(&mhdp->mbox_mutex); +- +- ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_WRITE_DPCD, sizeof(msg), msg); +- if (ret) +- goto out; +- +- ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_WRITE_DPCD, sizeof(reg)); +- if (ret) +- goto out; +- +- ret = cdns_mhdp_mailbox_recv_data(mhdp, reg, sizeof(reg)); +- if (ret) +- goto out; +- +- if (addr != get_unaligned_be24(reg + 2)) +- ret = -EINVAL; +- +-out: +- mutex_unlock(&mhdp->mbox_mutex); +- +- if (ret) +- dev_err(mhdp->dev, "dpcd write failed: %d\n", ret); +- return ret; +-} +- + static + int cdns_mhdp_set_firmware_active(struct cdns_mhdp_device *mhdp, bool enable) + { +- u8 msg[5]; +- int ret, i; +- +- msg[0] = GENERAL_MAIN_CONTROL; +- msg[1] = MB_MODULE_ID_GENERAL; +- msg[2] = 0; +- msg[3] = 1; +- msg[4] = enable ? FW_ACTIVE : FW_STANDBY; +- +- mutex_lock(&mhdp->mbox_mutex); +- +- for (i = 0; i < sizeof(msg); i++) { +- ret = cdns_mhdp_mailbox_write(mhdp, msg[i]); +- if (ret) +- goto out; +- } +- +- /* read the firmware state */ +- ret = cdns_mhdp_mailbox_recv_data(mhdp, msg, sizeof(msg)); +- if (ret) +- goto out; +- +- ret = 0; ++ u8 status; ++ int ret; + +-out: +- mutex_unlock(&mhdp->mbox_mutex); ++ status = enable ? FW_ACTIVE : FW_STANDBY; + ++ ret = cdns_mhdp_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_GENERAL, ++ GENERAL_MAIN_CONTROL, ++ sizeof(status), &status, ++ sizeof(status), &status); + if (ret < 0) + dev_err(mhdp->dev, "set firmware active failed\n"); + return ret; +@@ -380,34 +96,18 @@ int cdns_mhdp_get_hpd_status(struct cdns_mhdp_device *mhdp) + u8 status; + int ret; + +- mutex_lock(&mhdp->mbox_mutex); +- +- ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_HPD_STATE, 0, NULL); +- if (ret) +- goto err_get_hpd; +- +- ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_HPD_STATE, +- sizeof(status)); +- if (ret) +- goto err_get_hpd; ++ ret = cdns_mhdp_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_DP_TX, ++ DPTX_HPD_STATE, ++ 0, NULL, ++ sizeof(status), &status); + +- ret = cdns_mhdp_mailbox_recv_data(mhdp, &status, sizeof(status)); + if (ret) +- goto err_get_hpd; +- +- mutex_unlock(&mhdp->mbox_mutex); ++ return ret; + + dev_dbg(mhdp->dev, "%s: HPD %splugged\n", __func__, + status ? "" : "un"); + + return status; +- +-err_get_hpd: +- mutex_unlock(&mhdp->mbox_mutex); +- +- return ret; + } + + static +@@ -418,28 +118,17 @@ int cdns_mhdp_get_edid_block(void *data, u8 *edid, + u8 msg[2], reg[2], i; + int ret; + +- mutex_lock(&mhdp->mbox_mutex); +- + for (i = 0; i < 4; i++) { + msg[0] = block / 2; + msg[1] = block % 2; + +- ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_GET_EDID, sizeof(msg), msg); +- if (ret) +- continue; +- +- ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_GET_EDID, +- sizeof(reg) + length); +- if (ret) +- continue; +- +- ret = cdns_mhdp_mailbox_recv_data(mhdp, reg, sizeof(reg)); +- if (ret) +- continue; +- +- ret = cdns_mhdp_mailbox_recv_data(mhdp, edid, length); ++ ret = cdns_mhdp_mailbox_send_recv_multi(&mhdp->base, ++ MB_MODULE_ID_DP_TX, ++ DPTX_GET_EDID, ++ sizeof(msg), msg, ++ DPTX_GET_EDID, ++ sizeof(reg), reg, ++ length, edid); + if (ret) + continue; + +@@ -447,8 +136,6 @@ int cdns_mhdp_get_edid_block(void *data, u8 *edid, + break; + } + +- mutex_unlock(&mhdp->mbox_mutex); +- + if (ret) + dev_err(mhdp->dev, "get block[%d] edid failed: %d\n", + block, ret); +@@ -462,21 +149,9 @@ int cdns_mhdp_read_hpd_event(struct cdns_mhdp_device *mhdp) + u8 event = 0; + int ret; + +- mutex_lock(&mhdp->mbox_mutex); +- +- ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_READ_EVENT, 0, NULL); +- if (ret) +- goto out; +- +- ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_READ_EVENT, sizeof(event)); +- if (ret < 0) +- goto out; +- +- ret = cdns_mhdp_mailbox_recv_data(mhdp, &event, sizeof(event)); +-out: +- mutex_unlock(&mhdp->mbox_mutex); ++ ret = cdns_mhdp_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_DP_TX, ++ DPTX_READ_EVENT, ++ 0, NULL, sizeof(event), &event); + + if (ret < 0) + return ret; +@@ -510,35 +185,23 @@ int cdns_mhdp_adjust_lt(struct cdns_mhdp_device *mhdp, unsigned int nlanes, + put_unaligned_be16(udelay, payload + 1); + memcpy(payload + 3, lanes_data, nlanes); + +- mutex_lock(&mhdp->mbox_mutex); +- +- ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_ADJUST_LT, +- sizeof(payload), payload); +- if (ret) +- goto out; +- + /* Yes, read the DPCD read command response */ +- ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX, +- DPTX_READ_DPCD, +- sizeof(hdr) + DP_LINK_STATUS_SIZE); +- if (ret) +- goto out; +- +- ret = cdns_mhdp_mailbox_recv_data(mhdp, hdr, sizeof(hdr)); ++ ret = cdns_mhdp_mailbox_send_recv_multi(&mhdp->base, ++ MB_MODULE_ID_DP_TX, ++ DPTX_ADJUST_LT, ++ sizeof(payload), payload, ++ DPTX_READ_DPCD, ++ sizeof(hdr), hdr, ++ DP_LINK_STATUS_SIZE, ++ link_status); + if (ret) + goto out; + + addr = get_unaligned_be24(hdr + 2); + if (addr != DP_LANE0_1_STATUS) +- goto out; +- +- ret = cdns_mhdp_mailbox_recv_data(mhdp, link_status, +- DP_LINK_STATUS_SIZE); ++ ret = -EINVAL; + + out: +- mutex_unlock(&mhdp->mbox_mutex); +- + if (ret) + dev_err(mhdp->dev, "Failed to adjust Link Training.\n"); + +@@ -847,7 +510,7 @@ static ssize_t cdns_mhdp_transfer(struct drm_dp_aux *aux, + unsigned int i; + + for (i = 0; i < msg->size; ++i) { +- ret = cdns_mhdp_dpcd_write(mhdp, ++ ret = cdns_mhdp_dpcd_write(&mhdp->base, + msg->address + i, buf[i]); + if (!ret) + continue; +@@ -859,7 +522,7 @@ static ssize_t cdns_mhdp_transfer(struct drm_dp_aux *aux, + return ret; + } + } else { +- ret = cdns_mhdp_dpcd_read(mhdp, msg->address, ++ ret = cdns_mhdp_dpcd_read(&mhdp->base, msg->address, + msg->buffer, msg->size); + if (ret) { + dev_err(mhdp->dev, +@@ -887,12 +550,12 @@ static int cdns_mhdp_link_training_init(struct cdns_mhdp_device *mhdp) + if (!mhdp->host.scrambler) + reg32 |= CDNS_PHY_SCRAMBLER_BYPASS; + +- cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, reg32); ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_PHY_CONFIG, reg32); + +- cdns_mhdp_reg_write(mhdp, CDNS_DP_ENHNCD, ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_ENHNCD, + mhdp->sink.enhanced & mhdp->host.enhanced); + +- cdns_mhdp_reg_write(mhdp, CDNS_DP_LANE_EN, ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_LANE_EN, + CDNS_DP_LANE_EN_LANES(mhdp->link.num_lanes)); + + cdns_mhdp_link_configure(&mhdp->aux, &mhdp->link); +@@ -913,7 +576,7 @@ static int cdns_mhdp_link_training_init(struct cdns_mhdp_device *mhdp) + return ret; + } + +- cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_PHY_CONFIG, + CDNS_PHY_COMMON_CONFIG | + CDNS_PHY_TRAINING_EN | + CDNS_PHY_TRAINING_TYPE(1) | +@@ -1058,7 +721,7 @@ static bool cdns_mhdp_link_training_channel_eq(struct cdns_mhdp_device *mhdp, + CDNS_PHY_TRAINING_TYPE(eq_tps); + if (eq_tps != 4) + reg32 |= CDNS_PHY_SCRAMBLER_BYPASS; +- cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, reg32); ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_PHY_CONFIG, reg32); + + drm_dp_dpcd_writeb(&mhdp->aux, DP_TRAINING_PATTERN_SET, + (eq_tps != 4) ? eq_tps | DP_LINK_SCRAMBLING_DISABLE : +@@ -1322,7 +985,7 @@ static int cdns_mhdp_link_training(struct cdns_mhdp_device *mhdp, + mhdp->host.scrambler ? 0 : + DP_LINK_SCRAMBLING_DISABLE); + +- ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, ®32); ++ ret = cdns_mhdp_reg_read(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, ®32); + if (ret < 0) { + dev_err(mhdp->dev, + "Failed to read CDNS_DP_FRAMER_GLOBAL_CONFIG %d\n", +@@ -1333,13 +996,13 @@ static int cdns_mhdp_link_training(struct cdns_mhdp_device *mhdp, + reg32 |= CDNS_DP_NUM_LANES(mhdp->link.num_lanes); + reg32 |= CDNS_DP_WR_FAILING_EDGE_VSYNC; + reg32 |= CDNS_DP_FRAMER_EN; +- cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, reg32); ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, reg32); + + /* Reset PHY config */ + reg32 = CDNS_PHY_COMMON_CONFIG | CDNS_PHY_TRAINING_TYPE(1); + if (!mhdp->host.scrambler) + reg32 |= CDNS_PHY_SCRAMBLER_BYPASS; +- cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, reg32); ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_PHY_CONFIG, reg32); + + return 0; + err: +@@ -1347,7 +1010,7 @@ static int cdns_mhdp_link_training(struct cdns_mhdp_device *mhdp, + reg32 = CDNS_PHY_COMMON_CONFIG | CDNS_PHY_TRAINING_TYPE(1); + if (!mhdp->host.scrambler) + reg32 |= CDNS_PHY_SCRAMBLER_BYPASS; +- cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, reg32); ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_PHY_CONFIG, reg32); + + drm_dp_dpcd_writeb(&mhdp->aux, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); +@@ -1461,7 +1124,7 @@ static int cdns_mhdp_link_up(struct cdns_mhdp_device *mhdp) + mhdp->link.num_lanes = cdns_mhdp_max_num_lanes(mhdp); + + /* Disable framer for link training */ +- err = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp); ++ err = cdns_mhdp_reg_read(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp); + if (err < 0) { + dev_err(mhdp->dev, + "Failed to read CDNS_DP_FRAMER_GLOBAL_CONFIG %d\n", +@@ -1470,7 +1133,7 @@ static int cdns_mhdp_link_up(struct cdns_mhdp_device *mhdp) + } + + resp &= ~CDNS_DP_FRAMER_EN; +- cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, resp); ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, resp); + + /* Spread AMP if required, enable 8b/10b coding */ + amp[0] = cdns_mhdp_get_ssc_supported(mhdp) ? DP_SPREAD_AMP_0_5 : 0; +@@ -1834,7 +1497,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp, + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + bnd_hsync2vsync |= CDNS_IP_DET_INTERLACE_FORMAT; + +- cdns_mhdp_reg_write(mhdp, CDNS_BND_HSYNC2VSYNC(stream_id), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_BND_HSYNC2VSYNC(stream_id), + bnd_hsync2vsync); + + hsync2vsync_pol_ctrl = 0; +@@ -1842,10 +1505,10 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp, + hsync2vsync_pol_ctrl |= CDNS_H2V_HSYNC_POL_ACTIVE_LOW; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + hsync2vsync_pol_ctrl |= CDNS_H2V_VSYNC_POL_ACTIVE_LOW; +- cdns_mhdp_reg_write(mhdp, CDNS_HSYNC2VSYNC_POL_CTRL(stream_id), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_HSYNC2VSYNC_POL_CTRL(stream_id), + hsync2vsync_pol_ctrl); + +- cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_PXL_REPR(stream_id), pxl_repr); ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_PXL_REPR(stream_id), pxl_repr); + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + dp_framer_sp |= CDNS_DP_FRAMER_INTERLACE; +@@ -1853,19 +1516,19 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp, + dp_framer_sp |= CDNS_DP_FRAMER_HSYNC_POL_LOW; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + dp_framer_sp |= CDNS_DP_FRAMER_VSYNC_POL_LOW; +- cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_SP(stream_id), dp_framer_sp); ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_SP(stream_id), dp_framer_sp); + + front_porch = mode->crtc_hsync_start - mode->crtc_hdisplay; + back_porch = mode->crtc_htotal - mode->crtc_hsync_end; +- cdns_mhdp_reg_write(mhdp, CDNS_DP_FRONT_BACK_PORCH(stream_id), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRONT_BACK_PORCH(stream_id), + CDNS_DP_FRONT_PORCH(front_porch) | + CDNS_DP_BACK_PORCH(back_porch)); + +- cdns_mhdp_reg_write(mhdp, CDNS_DP_BYTE_COUNT(stream_id), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_BYTE_COUNT(stream_id), + mode->crtc_hdisplay * bpp / 8); + + msa_h0 = mode->crtc_htotal - mode->crtc_hsync_start; +- cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_HORIZONTAL_0(stream_id), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_MSA_HORIZONTAL_0(stream_id), + CDNS_DP_MSAH0_H_TOTAL(mode->crtc_htotal) | + CDNS_DP_MSAH0_HSYNC_START(msa_h0)); + +@@ -1874,11 +1537,11 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp, + CDNS_DP_MSAH1_HDISP_WIDTH(mode->crtc_hdisplay); + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + msa_horizontal_1 |= CDNS_DP_MSAH1_HSYNC_POL_LOW; +- cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_HORIZONTAL_1(stream_id), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_MSA_HORIZONTAL_1(stream_id), + msa_horizontal_1); + + msa_v0 = mode->crtc_vtotal - mode->crtc_vsync_start; +- cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_VERTICAL_0(stream_id), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_MSA_VERTICAL_0(stream_id), + CDNS_DP_MSAV0_V_TOTAL(mode->crtc_vtotal) | + CDNS_DP_MSAV0_VSYNC_START(msa_v0)); + +@@ -1887,7 +1550,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp, + CDNS_DP_MSAV1_VDISP_WIDTH(mode->crtc_vdisplay); + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + msa_vertical_1 |= CDNS_DP_MSAV1_VSYNC_POL_LOW; +- cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_VERTICAL_1(stream_id), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_MSA_VERTICAL_1(stream_id), + msa_vertical_1); + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && +@@ -1899,14 +1562,14 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp, + if (pxlfmt == DRM_COLOR_FORMAT_YCBCR420) + misc1 = CDNS_DP_TEST_VSC_SDP; + +- cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_MISC(stream_id), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_MSA_MISC(stream_id), + misc0 | (misc1 << 8)); + +- cdns_mhdp_reg_write(mhdp, CDNS_DP_HORIZONTAL(stream_id), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_HORIZONTAL(stream_id), + CDNS_DP_H_HSYNC_WIDTH(hsync) | + CDNS_DP_H_H_TOTAL(mode->crtc_hdisplay)); + +- cdns_mhdp_reg_write(mhdp, CDNS_DP_VERTICAL_0(stream_id), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_VERTICAL_0(stream_id), + CDNS_DP_V0_VHEIGHT(mode->crtc_vdisplay) | + CDNS_DP_V0_VSTART(msa_v0)); + +@@ -1915,13 +1578,13 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp, + mode->crtc_vtotal % 2 == 0) + dp_vertical_1 |= CDNS_DP_V1_VTOTAL_EVEN; + +- cdns_mhdp_reg_write(mhdp, CDNS_DP_VERTICAL_1(stream_id), dp_vertical_1); ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_VERTICAL_1(stream_id), dp_vertical_1); + +- cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_VB_ID(stream_id), 2, 1, +- (mode->flags & DRM_MODE_FLAG_INTERLACE) ? +- CDNS_DP_VB_ID_INTERLACED : 0); ++ cdns_mhdp_dp_reg_write_bit(&mhdp->base, CDNS_DP_VB_ID(stream_id), 2, 1, ++ (mode->flags & DRM_MODE_FLAG_INTERLACE) ? ++ CDNS_DP_VB_ID_INTERLACED : 0); + +- ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &framer); ++ ret = cdns_mhdp_reg_read(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, &framer); + if (ret < 0) { + dev_err(mhdp->dev, + "Failed to read CDNS_DP_FRAMER_GLOBAL_CONFIG %d\n", +@@ -1930,7 +1593,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp, + } + framer |= CDNS_DP_FRAMER_EN; + framer &= ~CDNS_DP_NO_VIDEO_MODE; +- cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, framer); ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, framer); + } + + static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp, +@@ -1963,15 +1626,15 @@ static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp, + + mhdp->stream_id = 0; + +- cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_TU, ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_TU, + CDNS_DP_FRAMER_TU_VS(vs) | + CDNS_DP_FRAMER_TU_SIZE(tu_size) | + CDNS_DP_FRAMER_TU_CNT_RST_EN); + +- cdns_mhdp_reg_write(mhdp, CDNS_DP_LINE_THRESH(0), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_LINE_THRESH(0), + line_thresh & GENMASK(5, 0)); + +- cdns_mhdp_reg_write(mhdp, CDNS_DP_STREAM_CONFIG_2(0), ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_STREAM_CONFIG_2(0), + CDNS_DP_SC2_TU_VS_DIFF((tu_size - vs > 3) ? + 0 : tu_size - vs)); + +@@ -2006,13 +1669,13 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge, + mhdp->info->ops->enable(mhdp); + + /* Enable VIF clock for stream 0 */ +- ret = cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &resp); ++ ret = cdns_mhdp_reg_read(&mhdp->base, CDNS_DPTX_CAR, &resp); + if (ret < 0) { + dev_err(mhdp->dev, "Failed to read CDNS_DPTX_CAR %d\n", ret); + goto out; + } + +- cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR, ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_CAR, + resp | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN); + + connector = drm_atomic_get_new_connector_for_encoder(state, +@@ -2083,16 +1746,16 @@ static void cdns_mhdp_atomic_disable(struct drm_bridge *bridge, + cdns_mhdp_hdcp_disable(mhdp); + + mhdp->bridge_enabled = false; +- cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp); ++ cdns_mhdp_reg_read(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp); + resp &= ~CDNS_DP_FRAMER_EN; + resp |= CDNS_DP_NO_VIDEO_MODE; +- cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, resp); ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DP_FRAMER_GLOBAL_CONFIG, resp); + + cdns_mhdp_link_down(mhdp); + + /* Disable VIF clock for stream 0 */ +- cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &resp); +- cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR, ++ cdns_mhdp_reg_read(&mhdp->base, CDNS_DPTX_CAR, &resp); ++ cdns_mhdp_reg_write(&mhdp->base, CDNS_DPTX_CAR, + resp & ~(CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN)); + + if (mhdp->info && mhdp->info->ops && mhdp->info->ops->disable) +@@ -2471,7 +2134,6 @@ static int cdns_mhdp_probe(struct platform_device *pdev) + + mhdp->clk = clk; + mhdp->dev = dev; +- mutex_init(&mhdp->mbox_mutex); + mutex_init(&mhdp->link_mutex); + spin_lock_init(&mhdp->start_lock); + +@@ -2502,6 +2164,11 @@ static int cdns_mhdp_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, mhdp); + ++ /* init base struct for access mailbox */ ++ mhdp->base.dev = mhdp->dev; ++ mhdp->base.regs = mhdp->regs; ++ mhdp->base.sapb_regs = mhdp->sapb_regs; ++ + mhdp->info = of_device_get_match_data(dev); + + clk_prepare_enable(clk); +diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h +index bad2fc0c73066..535300d040dea 100644 +--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h ++++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + struct clk; + struct device; +@@ -27,10 +28,6 @@ struct phy; + #define CDNS_APB_CTRL 0x00000 + #define CDNS_CPU_STALL BIT(3) + +-#define CDNS_MAILBOX_FULL 0x00008 +-#define CDNS_MAILBOX_EMPTY 0x0000c +-#define CDNS_MAILBOX_TX_DATA 0x00010 +-#define CDNS_MAILBOX_RX_DATA 0x00014 + #define CDNS_KEEP_ALIVE 0x00018 + #define CDNS_KEEP_ALIVE_MASK GENMASK(7, 0) + +@@ -198,45 +195,10 @@ struct phy; + #define CDNS_DP_BYTE_COUNT(s) (CDNS_DPTX_STREAM(s) + 0x7c) + #define CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT 16 + +-/* mailbox */ +-#define MAILBOX_RETRY_US 1000 +-#define MAILBOX_TIMEOUT_US 2000000 +- +-#define MB_OPCODE_ID 0 +-#define MB_MODULE_ID 1 +-#define MB_SIZE_MSB_ID 2 +-#define MB_SIZE_LSB_ID 3 +-#define MB_DATA_ID 4 +- +-#define MB_MODULE_ID_DP_TX 0x01 +-#define MB_MODULE_ID_HDCP_TX 0x07 +-#define MB_MODULE_ID_HDCP_RX 0x08 +-#define MB_MODULE_ID_HDCP_GENERAL 0x09 +-#define MB_MODULE_ID_GENERAL 0x0a +- +-/* firmware and opcodes */ ++/* firmware */ + #define FW_NAME "cadence/mhdp8546.bin" + #define CDNS_MHDP_IMEM 0x10000 + +-#define GENERAL_MAIN_CONTROL 0x01 +-#define GENERAL_TEST_ECHO 0x02 +-#define GENERAL_BUS_SETTINGS 0x03 +-#define GENERAL_TEST_ACCESS 0x04 +-#define GENERAL_REGISTER_READ 0x07 +- +-#define DPTX_SET_POWER_MNG 0x00 +-#define DPTX_GET_EDID 0x02 +-#define DPTX_READ_DPCD 0x03 +-#define DPTX_WRITE_DPCD 0x04 +-#define DPTX_ENABLE_EVENT 0x05 +-#define DPTX_WRITE_REGISTER 0x06 +-#define DPTX_READ_REGISTER 0x07 +-#define DPTX_WRITE_FIELD 0x08 +-#define DPTX_READ_EVENT 0x0a +-#define DPTX_GET_LAST_AUX_STAUS 0x0e +-#define DPTX_HPD_STATE 0x11 +-#define DPTX_ADJUST_LT 0x12 +- + #define FW_STANDBY 0 + #define FW_ACTIVE 1 + +@@ -352,6 +314,8 @@ struct cdns_mhdp_hdcp { + }; + + struct cdns_mhdp_device { ++ struct cdns_mhdp_base base; ++ + void __iomem *regs; + void __iomem *sapb_regs; + void __iomem *j721e_regs; +@@ -362,9 +326,6 @@ struct cdns_mhdp_device { + + const struct cdns_mhdp_platform_info *info; + +- /* This is to protect mailbox communications with the firmware */ +- struct mutex mbox_mutex; +- + /* + * "link_mutex" protects the access to all the link parameters + * including the link training process. Link training will be +diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c +index 42248f179b69d..3944642f2ebbc 100644 +--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c ++++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c +@@ -15,144 +15,20 @@ + + #include "cdns-mhdp8546-hdcp.h" + +-static int cdns_mhdp_secure_mailbox_read(struct cdns_mhdp_device *mhdp) +-{ +- int ret, empty; +- +- WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex)); +- +- ret = readx_poll_timeout(readl, mhdp->sapb_regs + CDNS_MAILBOX_EMPTY, +- empty, !empty, MAILBOX_RETRY_US, +- MAILBOX_TIMEOUT_US); +- if (ret < 0) +- return ret; +- +- return readl(mhdp->sapb_regs + CDNS_MAILBOX_RX_DATA) & 0xff; +-} +- +-static int cdns_mhdp_secure_mailbox_write(struct cdns_mhdp_device *mhdp, +- u8 val) +-{ +- int ret, full; +- +- WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex)); +- +- ret = readx_poll_timeout(readl, mhdp->sapb_regs + CDNS_MAILBOX_FULL, +- full, !full, MAILBOX_RETRY_US, +- MAILBOX_TIMEOUT_US); +- if (ret < 0) +- return ret; +- +- writel(val, mhdp->sapb_regs + CDNS_MAILBOX_TX_DATA); +- +- return 0; +-} +- +-static int cdns_mhdp_secure_mailbox_recv_header(struct cdns_mhdp_device *mhdp, +- u8 module_id, +- u8 opcode, +- u16 req_size) +-{ +- u32 mbox_size, i; +- u8 header[4]; +- int ret; +- +- /* read the header of the message */ +- for (i = 0; i < sizeof(header); i++) { +- ret = cdns_mhdp_secure_mailbox_read(mhdp); +- if (ret < 0) +- return ret; +- +- header[i] = ret; +- } +- +- mbox_size = get_unaligned_be16(header + 2); +- +- if (opcode != header[0] || module_id != header[1] || +- (opcode != HDCP_TRAN_IS_REC_ID_VALID && req_size != mbox_size)) { +- for (i = 0; i < mbox_size; i++) +- if (cdns_mhdp_secure_mailbox_read(mhdp) < 0) +- break; +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int cdns_mhdp_secure_mailbox_recv_data(struct cdns_mhdp_device *mhdp, +- u8 *buff, u16 buff_size) +-{ +- int ret; +- u32 i; +- +- for (i = 0; i < buff_size; i++) { +- ret = cdns_mhdp_secure_mailbox_read(mhdp); +- if (ret < 0) +- return ret; +- +- buff[i] = ret; +- } +- +- return 0; +-} +- +-static int cdns_mhdp_secure_mailbox_send(struct cdns_mhdp_device *mhdp, +- u8 module_id, +- u8 opcode, +- u16 size, +- u8 *message) +-{ +- u8 header[4]; +- int ret; +- u32 i; +- +- header[0] = opcode; +- header[1] = module_id; +- put_unaligned_be16(size, header + 2); +- +- for (i = 0; i < sizeof(header); i++) { +- ret = cdns_mhdp_secure_mailbox_write(mhdp, header[i]); +- if (ret) +- return ret; +- } +- +- for (i = 0; i < size; i++) { +- ret = cdns_mhdp_secure_mailbox_write(mhdp, message[i]); +- if (ret) +- return ret; +- } +- +- return 0; +-} +- + static int cdns_mhdp_hdcp_get_status(struct cdns_mhdp_device *mhdp, + u16 *hdcp_port_status) + { + u8 hdcp_status[HDCP_STATUS_SIZE]; + int ret; + +- mutex_lock(&mhdp->mbox_mutex); +- ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, +- HDCP_TRAN_STATUS_CHANGE, 0, NULL); +- if (ret) +- goto err_get_hdcp_status; +- +- ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX, +- HDCP_TRAN_STATUS_CHANGE, +- sizeof(hdcp_status)); +- if (ret) +- goto err_get_hdcp_status; +- +- ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, hdcp_status, +- sizeof(hdcp_status)); ++ ret = cdns_mhdp_secure_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_HDCP_TX, ++ HDCP_TRAN_STATUS_CHANGE, 0, NULL, ++ sizeof(hdcp_status), hdcp_status); + if (ret) +- goto err_get_hdcp_status; ++ return ret; + + *hdcp_port_status = ((u16)(hdcp_status[0] << 8) | hdcp_status[1]); + +-err_get_hdcp_status: +- mutex_unlock(&mhdp->mbox_mutex); +- + return ret; + } + +@@ -170,98 +46,52 @@ static u8 cdns_mhdp_hdcp_handle_status(struct cdns_mhdp_device *mhdp, + static int cdns_mhdp_hdcp_rx_id_valid_response(struct cdns_mhdp_device *mhdp, + u8 valid) + { +- int ret; +- +- mutex_lock(&mhdp->mbox_mutex); +- ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, ++ return cdns_mhdp_secure_mailbox_send(&mhdp->base, MB_MODULE_ID_HDCP_TX, + HDCP_TRAN_RESPOND_RECEIVER_ID_VALID, + 1, &valid); +- mutex_unlock(&mhdp->mbox_mutex); +- +- return ret; + } + + static int cdns_mhdp_hdcp_rx_id_valid(struct cdns_mhdp_device *mhdp, + u8 *recv_num, u8 *hdcp_rx_id) + { + u8 rec_id_hdr[2]; +- u8 status; + int ret; + +- mutex_lock(&mhdp->mbox_mutex); +- ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, +- HDCP_TRAN_IS_REC_ID_VALID, 0, NULL); +- if (ret) +- goto err_rx_id_valid; +- +- ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX, +- HDCP_TRAN_IS_REC_ID_VALID, +- sizeof(status)); +- if (ret) +- goto err_rx_id_valid; +- +- ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, rec_id_hdr, 2); ++ ret = cdns_mhdp_secure_mailbox_send_recv_multi(&mhdp->base, ++ MB_MODULE_ID_HDCP_TX, ++ HDCP_TRAN_IS_REC_ID_VALID, ++ 0, NULL, ++ HDCP_TRAN_IS_REC_ID_VALID, ++ sizeof(rec_id_hdr), rec_id_hdr, ++ 0, hdcp_rx_id); + if (ret) +- goto err_rx_id_valid; ++ return ret; + + *recv_num = rec_id_hdr[0]; + +- ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, hdcp_rx_id, 5 * *recv_num); +- +-err_rx_id_valid: +- mutex_unlock(&mhdp->mbox_mutex); +- +- return ret; ++ return 0; + } + + static int cdns_mhdp_hdcp_km_stored_resp(struct cdns_mhdp_device *mhdp, + u32 size, u8 *km) + { +- int ret; +- +- mutex_lock(&mhdp->mbox_mutex); +- ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, +- HDCP2X_TX_RESPOND_KM, size, km); +- mutex_unlock(&mhdp->mbox_mutex); +- +- return ret; ++ return cdns_mhdp_secure_mailbox_send(&mhdp->base, MB_MODULE_ID_HDCP_TX, ++ HDCP2X_TX_RESPOND_KM, size, km); + } + + static int cdns_mhdp_hdcp_tx_is_km_stored(struct cdns_mhdp_device *mhdp, + u8 *resp, u32 size) + { +- int ret; +- +- mutex_lock(&mhdp->mbox_mutex); +- ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, +- HDCP2X_TX_IS_KM_STORED, 0, NULL); +- if (ret) +- goto err_is_km_stored; +- +- ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX, +- HDCP2X_TX_IS_KM_STORED, +- size); +- if (ret) +- goto err_is_km_stored; +- +- ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, resp, size); +-err_is_km_stored: +- mutex_unlock(&mhdp->mbox_mutex); +- +- return ret; ++ return cdns_mhdp_secure_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_HDCP_TX, ++ HDCP2X_TX_IS_KM_STORED, ++ 0, NULL, size, resp); + } + + static int cdns_mhdp_hdcp_tx_config(struct cdns_mhdp_device *mhdp, + u8 hdcp_cfg) + { +- int ret; +- +- mutex_lock(&mhdp->mbox_mutex); +- ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, +- HDCP_TRAN_CONFIGURATION, 1, &hdcp_cfg); +- mutex_unlock(&mhdp->mbox_mutex); +- +- return ret; ++ return cdns_mhdp_secure_mailbox_send(&mhdp->base, MB_MODULE_ID_HDCP_TX, ++ HDCP_TRAN_CONFIGURATION, 1, &hdcp_cfg); + } + + static int cdns_mhdp_hdcp_set_config(struct cdns_mhdp_device *mhdp, +diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.h +index 3b6ec9c3a8d8b..1e68530e72229 100644 +--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.h ++++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.h +@@ -9,6 +9,7 @@ + #ifndef CDNS_MHDP8546_HDCP_H + #define CDNS_MHDP8546_HDCP_H + ++#include + #include "cdns-mhdp8546-core.h" + + #define HDCP_MAX_RECEIVERS 32 +@@ -32,23 +33,6 @@ enum { + HDCP_SET_SEED, + }; + +-enum { +- HDCP_TRAN_CONFIGURATION, +- HDCP2X_TX_SET_PUBLIC_KEY_PARAMS, +- HDCP2X_TX_SET_DEBUG_RANDOM_NUMBERS, +- HDCP2X_TX_RESPOND_KM, +- HDCP1_TX_SEND_KEYS, +- HDCP1_TX_SEND_RANDOM_AN, +- HDCP_TRAN_STATUS_CHANGE, +- HDCP2X_TX_IS_KM_STORED, +- HDCP2X_TX_STORE_KM, +- HDCP_TRAN_IS_REC_ID_VALID, +- HDCP_TRAN_RESPOND_RECEIVER_ID_VALID, +- HDCP_TRAN_TEST_KEYS, +- HDCP2X_TX_SET_KM_KEY_PARAMS, +- HDCP_NUM_OF_SUPPORTED_MESSAGES +-}; +- + enum { + HDCP_CONTENT_TYPE_0, + HDCP_CONTENT_TYPE_1, + +From patchwork Tue Dec 17 06:51:45 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v20,3/9] phy: Add HDMI configuration options +From: Sandor Yu +X-Patchwork-Id: 629290 +Message-Id: + +To: dmitry.baryshkov@linaro.org, andrzej.hajda@intel.com, + neil.armstrong@linaro.org, Laurent.pinchart@ideasonboard.com, + jonas@kwiboo.se, jernej.skrabec@gmail.com, airlied@gmail.com, + daniel@ffwll.ch, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, + vkoul@kernel.org, dri-devel@lists.freedesktop.org, + devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, + mripard@kernel.org +Cc: kernel@pengutronix.de, linux-imx@nxp.com, Sandor.yu@nxp.com, + oliver.brown@nxp.com, alexander.stein@ew.tq-group.com, sam@ravnborg.org +Date: Tue, 17 Dec 2024 14:51:45 +0800 + +Allow HDMI PHYs to be configured through the generic +functions through a custom structure added to the generic union. + +The parameters added here are based on HDMI PHY +implementation practices. The current set of parameters +should cover the potential users. + +Signed-off-by: Sandor Yu +Reviewed-by: Dmitry Baryshkov +Reviewed-by: Maxime Ripard +Acked-by: Vinod Koul +--- +v19->v20: +- Add a-b tag. + +v17->v19: + *No change. + +v16->v17: +- remove headfile hdmi.h +- add 2024 year to copyright +- Add r-b tag. + + include/linux/phy/phy-hdmi.h | 19 +++++++++++++++++++ + include/linux/phy/phy.h | 7 ++++++- + 2 files changed, 25 insertions(+), 1 deletion(-) + create mode 100644 include/linux/phy/phy-hdmi.h + +diff --git a/include/linux/phy/phy-hdmi.h b/include/linux/phy/phy-hdmi.h +new file mode 100644 +index 0000000000000..6a696922bc7f2 +--- /dev/null ++++ b/include/linux/phy/phy-hdmi.h +@@ -0,0 +1,19 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright 2022,2024 NXP ++ */ ++ ++#ifndef __PHY_HDMI_H_ ++#define __PHY_HDMI_H_ ++ ++/** ++ * struct phy_configure_opts_hdmi - HDMI configuration set ++ * @tmds_char_rate: HDMI TMDS Character Rate in Hertz. ++ * ++ * This structure is used to represent the configuration state of a HDMI phy. ++ */ ++struct phy_configure_opts_hdmi { ++ unsigned long long tmds_char_rate; ++}; ++ ++#endif /* __PHY_HDMI_H_ */ +diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h +index 03cd5bae92d3f..4ac486b101fe4 100644 +--- a/include/linux/phy/phy.h ++++ b/include/linux/phy/phy.h +@@ -17,6 +17,7 @@ + #include + + #include ++#include + #include + #include + +@@ -42,7 +43,8 @@ enum phy_mode { + PHY_MODE_MIPI_DPHY, + PHY_MODE_SATA, + PHY_MODE_LVDS, +- PHY_MODE_DP ++ PHY_MODE_DP, ++ PHY_MODE_HDMI, + }; + + enum phy_media { +@@ -60,11 +62,14 @@ enum phy_media { + * the DisplayPort protocol. + * @lvds: Configuration set applicable for phys supporting + * the LVDS phy mode. ++ * @hdmi: Configuration set applicable for phys supporting ++ * the HDMI phy mode. + */ + union phy_configure_opts { + struct phy_configure_opts_mipi_dphy mipi_dphy; + struct phy_configure_opts_dp dp; + struct phy_configure_opts_lvds lvds; ++ struct phy_configure_opts_hdmi hdmi; + }; + + /** + +From patchwork Tue Dec 17 06:51:46 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v20,4/9] dt-bindings: display: bridge: Add Cadence MHDP8501 +From: Sandor Yu +X-Patchwork-Id: 629291 +Message-Id: + +To: dmitry.baryshkov@linaro.org, andrzej.hajda@intel.com, + neil.armstrong@linaro.org, Laurent.pinchart@ideasonboard.com, + jonas@kwiboo.se, jernej.skrabec@gmail.com, airlied@gmail.com, + daniel@ffwll.ch, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, + vkoul@kernel.org, dri-devel@lists.freedesktop.org, + devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, + mripard@kernel.org +Cc: kernel@pengutronix.de, linux-imx@nxp.com, Sandor.yu@nxp.com, + oliver.brown@nxp.com, alexander.stein@ew.tq-group.com, sam@ravnborg.org +Date: Tue, 17 Dec 2024 14:51:46 +0800 + +Add bindings for Cadence MHDP8501 DisplayPort/HDMI bridge. + +Signed-off-by: Sandor Yu +Reviewed-by: Krzysztof Kozlowski +--- +v19->v20: +- remove data type link of data-lanes. + +v18->v19: +- move data-lanes property to endpoint of port@1 + +v17->v18: +- remove lane-mapping and replace it with data-lanes +- remove r-b tag as property changed. + +v16->v17: +- Add lane-mapping property + +v9->v16: + *No change + + .../display/bridge/cdns,mhdp8501.yaml | 121 ++++++++++++++++++ + 1 file changed, 121 insertions(+) + create mode 100644 Documentation/devicetree/bindings/display/bridge/cdns,mhdp8501.yaml + +diff --git a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8501.yaml b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8501.yaml +new file mode 100644 +index 0000000000000..2417f4038b437 +--- /dev/null ++++ b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8501.yaml +@@ -0,0 +1,121 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/display/bridge/cdns,mhdp8501.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Cadence MHDP8501 DP/HDMI bridge ++ ++maintainers: ++ - Sandor Yu ++ ++description: ++ Cadence MHDP8501 DisplayPort/HDMI interface. ++ ++properties: ++ compatible: ++ enum: ++ - fsl,imx8mq-mhdp8501 ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ maxItems: 1 ++ description: MHDP8501 DP/HDMI APB clock. ++ ++ phys: ++ maxItems: 1 ++ description: ++ phandle to the DP/HDMI PHY ++ ++ interrupts: ++ items: ++ - description: Hotplug cable plugin. ++ - description: Hotplug cable plugout. ++ ++ interrupt-names: ++ items: ++ - const: plug_in ++ - const: plug_out ++ ++ ports: ++ $ref: /schemas/graph.yaml#/properties/ports ++ ++ properties: ++ port@0: ++ $ref: /schemas/graph.yaml#/properties/port ++ description: ++ Input port from display controller output. ++ ++ port@1: ++ $ref: /schemas/graph.yaml#/$defs/port-base ++ unevaluatedProperties: false ++ description: ++ Output port to DisplayPort or HDMI connector. ++ ++ properties: ++ endpoint: ++ $ref: /schemas/media/video-interfaces.yaml# ++ unevaluatedProperties: false ++ ++ properties: ++ data-lanes: ++ description: Lane reordering for HDMI or DisplayPort interface. ++ minItems: 4 ++ maxItems: 4 ++ ++ required: ++ - data-lanes ++ ++ required: ++ - port@0 ++ - port@1 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - interrupts ++ - interrupt-names ++ - phys ++ - ports ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ ++ mhdp: display-bridge@32c00000 { ++ compatible = "fsl,imx8mq-mhdp8501"; ++ reg = <0x32c00000 0x100000>; ++ interrupts = , ++ ; ++ interrupt-names = "plug_in", "plug_out"; ++ clocks = <&clk IMX8MQ_CLK_DISP_APB_ROOT>; ++ phys = <&mdhp_phy>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ mhdp_in: endpoint { ++ remote-endpoint = <&dcss_out>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ mhdp_out: endpoint { ++ remote-endpoint = <&dp_connector>; ++ data-lanes = <2 1 0 3>; ++ }; ++ }; ++ }; ++ }; + +From patchwork Tue Dec 17 06:51:47 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v20,5/9] drm: bridge: Cadence: Add MHDP8501 DP/HDMI driver +From: Sandor Yu +X-Patchwork-Id: 629292 +Message-Id: + +To: dmitry.baryshkov@linaro.org, andrzej.hajda@intel.com, + neil.armstrong@linaro.org, Laurent.pinchart@ideasonboard.com, + jonas@kwiboo.se, jernej.skrabec@gmail.com, airlied@gmail.com, + daniel@ffwll.ch, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, + vkoul@kernel.org, dri-devel@lists.freedesktop.org, + devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, + mripard@kernel.org +Cc: kernel@pengutronix.de, linux-imx@nxp.com, Sandor.yu@nxp.com, + oliver.brown@nxp.com, alexander.stein@ew.tq-group.com, sam@ravnborg.org +Date: Tue, 17 Dec 2024 14:51:47 +0800 + +Add a new DRM DisplayPort and HDMI bridge driver for Candence MHDP8501 +used in i.MX8MQ SOC. MHDP8501 could support HDMI or DisplayPort +standards according embedded Firmware running in the uCPU. + +For iMX8MQ SOC, the DisplayPort/HDMI FW was loaded and activated by +SOC's ROM code. Bootload binary included respective specific firmware +is required. + +Driver will check display connector type and +then load the corresponding driver. + +Signed-off-by: Sandor Yu +--- +v19->v20: +- Dump mhdp FW version by debugfs +- Combine HDMI and DP cable detect functions into one function +- Combine HDMI and DP cable bridge_mode_valid() functions into one function +- Rename cdns_hdmi_reset_link() to cdns_hdmi_handle_hotplug() +- Add comments for EDID in cdns_hdmi_handle_hotplug() and cdns_dp_check_link_state() +- Add atomic_get_input_bus_fmts() and bridge_atomic_check() for DP driver +- Remove bpc and color_fmt init in atomic_enable() function. +- More detail comments for DDC adapter only support SCDC_I2C_SLAVE_ADDRESS + read and write in HDMI driver. + + +v18->v19: +- Get endpoint for data-lanes as it had move to endpoint of port@1 +- Update clock management as devm_clk_get_enabled() introduced. +- Fix clear_infoframe() function is not work issue. +- Manage PHY power state via phy_power_on() and phy_power_off(). + +v17->v18: +- MHDP8501 HDMI and DP commands that need access mailbox are rewrited + with new API functions created in patch #1. +- replace lane-mapping with data-lanes, use the value from data-lanes + to reorder HDMI and DP lane mapping. +- create I2C adapter for HDMI SCDC, remove cdns_hdmi_scdc_write() function. +- Rewrite cdns_hdmi_sink_config() function, use HDMI SCDC helper function + drm_scdc_set_high_tmds_clock_ratio() and drm_scdc_set_scrambling() + to config HDMI sink TMDS. +- Remove struct video_info from HDMI driver. +- Remove tmds_char_rate_valid() be called in bridge_mode_valid(), + community had patch in reviewing to implement the function. +- Remove warning message print when get unknown HPD cable status. +- Add more detail comments for HDP plugin and plugout interrupt. +- use dev_dbg to repleace DRM_INFO when cable HPD status changed. +- Remove t-b tag as above code change. + + drivers/gpu/drm/bridge/cadence/Kconfig | 16 + + drivers/gpu/drm/bridge/cadence/Makefile | 2 + + .../drm/bridge/cadence/cdns-mhdp8501-core.c | 379 +++++++++ + .../drm/bridge/cadence/cdns-mhdp8501-core.h | 380 +++++++++ + .../gpu/drm/bridge/cadence/cdns-mhdp8501-dp.c | 694 ++++++++++++++++ + .../drm/bridge/cadence/cdns-mhdp8501-hdmi.c | 745 ++++++++++++++++++ + 6 files changed, 2216 insertions(+) + create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-core.c + create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-core.h + create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-dp.c + create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-hdmi.c + +diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig +index dbb06533ccab2..bd979f3e6df48 100644 +--- a/drivers/gpu/drm/bridge/cadence/Kconfig ++++ b/drivers/gpu/drm/bridge/cadence/Kconfig +@@ -48,3 +48,19 @@ config DRM_CDNS_MHDP8546_J721E + initializes the J721E Display Port and sets up the + clock and data muxes. + endif ++ ++config DRM_CDNS_MHDP8501 ++ tristate "Cadence MHDP8501 DP/HDMI bridge" ++ select DRM_KMS_HELPER ++ select DRM_PANEL_BRIDGE ++ select DRM_DISPLAY_DP_HELPER ++ select DRM_DISPLAY_HELPER ++ select DRM_CDNS_AUDIO ++ select CDNS_MHDP_HELPER ++ depends on OF ++ help ++ Support Cadence MHDP8501 DisplayPort/HDMI bridge. ++ Cadence MHDP8501 support one or more protocols, ++ including DisplayPort and HDMI. ++ To use the DP and HDMI drivers, their respective ++ specific firmware is required. +diff --git a/drivers/gpu/drm/bridge/cadence/Makefile b/drivers/gpu/drm/bridge/cadence/Makefile +index c95fd5b81d137..ea327287d1c14 100644 +--- a/drivers/gpu/drm/bridge/cadence/Makefile ++++ b/drivers/gpu/drm/bridge/cadence/Makefile +@@ -5,3 +5,5 @@ cdns-dsi-$(CONFIG_DRM_CDNS_DSI_J721E) += cdns-dsi-j721e.o + obj-$(CONFIG_DRM_CDNS_MHDP8546) += cdns-mhdp8546.o + cdns-mhdp8546-y := cdns-mhdp8546-core.o cdns-mhdp8546-hdcp.o + cdns-mhdp8546-$(CONFIG_DRM_CDNS_MHDP8546_J721E) += cdns-mhdp8546-j721e.o ++obj-$(CONFIG_DRM_CDNS_MHDP8501) += cdns-mhdp8501.o ++cdns-mhdp8501-y := cdns-mhdp8501-core.o cdns-mhdp8501-dp.o cdns-mhdp8501-hdmi.o +diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-core.c +new file mode 100644 +index 0000000000000..98116ef012fa3 +--- /dev/null ++++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-core.c +@@ -0,0 +1,379 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Cadence Display Port Interface (DP) driver ++ * ++ * Copyright (C) 2023-2024 NXP Semiconductor, Inc. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "cdns-mhdp8501-core.h" ++ ++static ssize_t firmware_version_show(struct device *dev, ++ struct device_attribute *attr, char *buf); ++static struct device_attribute firmware_version = __ATTR_RO(firmware_version); ++ ++ssize_t firmware_version_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct cdns_mhdp8501_device *mhdp = dev_get_drvdata(dev); ++ ++ u32 version = readl(mhdp->base.regs + VER_L) | readl(mhdp->base.regs + VER_H) << 8; ++ u32 lib_version = readl(mhdp->base.regs + VER_LIB_L_ADDR) | ++ readl(mhdp->base.regs + VER_LIB_H_ADDR) << 8; ++ ++ return sprintf(buf, "FW version %d, Lib version %d\n", version, lib_version); ++} ++ ++static void cdns_mhdp8501_create_device_files(struct cdns_mhdp8501_device *mhdp) ++{ ++ if (device_create_file(mhdp->dev, &firmware_version)) { ++ DRM_ERROR("Unable to create firmware_version sysfs\n"); ++ device_remove_file(mhdp->dev, &firmware_version); ++ } ++} ++ ++static void cdns_mhdp8501_remove_device_files(struct cdns_mhdp8501_device *mhdp) ++{ ++ device_remove_file(mhdp->dev, &firmware_version); ++} ++ ++static int cdns_mhdp8501_read_hpd(struct cdns_mhdp8501_device *mhdp) ++{ ++ u8 status; ++ int ret; ++ ++ ret = cdns_mhdp_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_GENERAL, ++ GENERAL_GET_HPD_STATE, ++ 0, NULL, sizeof(status), &status); ++ if (ret) { ++ dev_err(mhdp->dev, "read hpd failed: %d\n", ret); ++ return ret; ++ } ++ ++ return status; ++} ++ ++enum drm_connector_status cdns_mhdp8501_detect(struct drm_bridge *bridge) ++{ ++ struct cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ ++ u8 hpd = 0xf; ++ ++ hpd = cdns_mhdp8501_read_hpd(mhdp); ++ if (hpd == 1) ++ return connector_status_connected; ++ else if (hpd == 0) ++ return connector_status_disconnected; ++ ++ return connector_status_unknown; ++} ++ ++enum drm_mode_status ++cdns_mhdp8501_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, ++ const struct drm_display_mode *mode) ++{ ++ /* We don't support double-clocked */ ++ if (mode->flags & DRM_MODE_FLAG_DBLCLK) ++ return MODE_BAD; ++ ++ /* MAX support pixel clock rate 594MHz */ ++ if (mode->clock > 594000) ++ return MODE_CLOCK_HIGH; ++ ++ if (mode->hdisplay > 3840) ++ return MODE_BAD_HVALUE; ++ ++ if (mode->vdisplay > 2160) ++ return MODE_BAD_VVALUE; ++ ++ return MODE_OK; ++} ++ ++static void hotplug_work_func(struct work_struct *work) ++{ ++ struct cdns_mhdp8501_device *mhdp = container_of(work, ++ struct cdns_mhdp8501_device, ++ hotplug_work.work); ++ enum drm_connector_status status = cdns_mhdp8501_detect(&mhdp->bridge); ++ ++ drm_bridge_hpd_notify(&mhdp->bridge, status); ++ ++ /* ++ * iMX8MQ has two HPD interrupts: one for plugout and one for plugin. ++ * These interrupts cannot be masked and cleaned, so we must enable one ++ * and disable the other to avoid continuous interrupt generation. ++ */ ++ if (status == connector_status_connected) { ++ /* Cable connected */ ++ dev_dbg(mhdp->dev, "HDMI/DP Cable Plug In\n"); ++ enable_irq(mhdp->irq[IRQ_OUT]); ++ ++ /* Reset HDMI/DP link with sink */ ++ if (mhdp->connector_type == DRM_MODE_CONNECTOR_HDMIA) ++ cdns_hdmi_handle_hotplug(mhdp); ++ else ++ cdns_dp_check_link_state(mhdp); ++ ++ } else if (status == connector_status_disconnected) { ++ /* Cable Disconnected */ ++ dev_dbg(mhdp->dev, "HDMI/DP Cable Plug Out\n"); ++ enable_irq(mhdp->irq[IRQ_IN]); ++ } ++} ++ ++static irqreturn_t cdns_mhdp8501_irq_thread(int irq, void *data) ++{ ++ struct cdns_mhdp8501_device *mhdp = data; ++ ++ disable_irq_nosync(irq); ++ ++ mod_delayed_work(system_wq, &mhdp->hotplug_work, ++ msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS)); ++ ++ return IRQ_HANDLED; ++} ++ ++#define DATA_LANES_COUNT 4 ++static int cdns_mhdp8501_dt_parse(struct cdns_mhdp8501_device *mhdp, ++ struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct device_node *remote, *endpoint; ++ u32 data_lanes[DATA_LANES_COUNT]; ++ u32 lane_value; ++ int ret, i; ++ ++ remote = of_graph_get_remote_node(np, 1, 0); ++ if (!remote) { ++ dev_err(dev, "fail to get remote node\n"); ++ of_node_put(remote); ++ return -EINVAL; ++ } ++ ++ /* get connector type */ ++ if (of_device_is_compatible(remote, "hdmi-connector")) { ++ mhdp->connector_type = DRM_MODE_CONNECTOR_HDMIA; ++ ++ } else if (of_device_is_compatible(remote, "dp-connector")) { ++ mhdp->connector_type = DRM_MODE_CONNECTOR_DisplayPort; ++ ++ } else { ++ dev_err(dev, "Unknown connector type\n"); ++ of_node_put(remote); ++ return -EINVAL; ++ } ++ ++ of_node_put(remote); ++ ++ endpoint = of_graph_get_endpoint_by_regs(np, 1, -1); ++ ++ /* Get the data lanes ordering */ ++ ret = of_property_count_u32_elems(endpoint, "data-lanes"); ++ if (ret < 0) ++ return -EINVAL; ++ if (ret != DATA_LANES_COUNT) { ++ dev_err(dev, "expected 4 data lanes\n"); ++ return -EINVAL; ++ } ++ ++ ret = of_property_read_u32_array(endpoint, "data-lanes", ++ data_lanes, DATA_LANES_COUNT); ++ if (ret) ++ return -EINVAL; ++ ++ mhdp->lane_mapping = 0; ++ for (i = 0; i < DATA_LANES_COUNT; i++) { ++ lane_value = (data_lanes[i] >= 0 && data_lanes[i] <= 3) ? data_lanes[i] : 0; ++ mhdp->lane_mapping |= lane_value << (i * 2); ++ } ++ ++ return true; ++} ++ ++static int cdns_mhdp8501_add_bridge(struct cdns_mhdp8501_device *mhdp) ++{ ++ mhdp->bridge.type = mhdp->connector_type; ++ mhdp->bridge.driver_private = mhdp; ++ mhdp->bridge.of_node = mhdp->dev->of_node; ++ mhdp->bridge.vendor = "NXP"; ++ mhdp->bridge.product = "i.MX8"; ++ mhdp->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | ++ DRM_BRIDGE_OP_HPD; ++ ++ if (mhdp->connector_type == DRM_MODE_CONNECTOR_HDMIA) { ++ mhdp->bridge.funcs = &cdns_hdmi_bridge_funcs; ++ mhdp->bridge.ops |= DRM_BRIDGE_OP_HDMI; ++ mhdp->bridge.ddc = cdns_hdmi_i2c_adapter(mhdp); ++ } else if (mhdp->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { ++ mhdp->bridge.funcs = &cdns_dp_bridge_funcs; ++ } else { ++ dev_err(mhdp->dev, "Unsupported connector type!\n"); ++ return -EINVAL; ++ } ++ ++ drm_bridge_add(&mhdp->bridge); ++ ++ return 0; ++} ++ ++static int cdns_mhdp8501_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct cdns_mhdp8501_device *mhdp; ++ struct resource *res; ++ enum phy_mode phy_mode; ++ u32 reg; ++ int ret; ++ ++ mhdp = devm_kzalloc(dev, sizeof(*mhdp), GFP_KERNEL); ++ if (!mhdp) ++ return -ENOMEM; ++ ++ mhdp->dev = dev; ++ ++ INIT_DELAYED_WORK(&mhdp->hotplug_work, hotplug_work_func); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -ENODEV; ++ ++ mhdp->regs = devm_ioremap(dev, res->start, resource_size(res)); ++ if (IS_ERR(mhdp->regs)) ++ return PTR_ERR(mhdp->regs); ++ ++ cdns_mhdp8501_create_device_files(mhdp); ++ ++ ret = cdns_mhdp8501_dt_parse(mhdp, pdev); ++ if (ret < 0) ++ return -EINVAL; ++ ++ mhdp->phy = devm_of_phy_get_by_index(dev, pdev->dev.of_node, 0); ++ if (IS_ERR(mhdp->phy)) ++ return dev_err_probe(dev, PTR_ERR(mhdp->phy), "no PHY configured\n"); ++ ++ mhdp->irq[IRQ_IN] = platform_get_irq_byname(pdev, "plug_in"); ++ if (mhdp->irq[IRQ_IN] < 0) ++ return dev_err_probe(dev, mhdp->irq[IRQ_IN], "No plug_in irq number\n"); ++ ++ mhdp->irq[IRQ_OUT] = platform_get_irq_byname(pdev, "plug_out"); ++ if (mhdp->irq[IRQ_OUT] < 0) ++ return dev_err_probe(dev, mhdp->irq[IRQ_OUT], "No plug_out irq number\n"); ++ ++ irq_set_status_flags(mhdp->irq[IRQ_IN], IRQ_NOAUTOEN); ++ ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_IN], ++ NULL, cdns_mhdp8501_irq_thread, ++ IRQF_ONESHOT, dev_name(dev), mhdp); ++ if (ret < 0) { ++ dev_err(dev, "can't claim irq %d\n", mhdp->irq[IRQ_IN]); ++ return -EINVAL; ++ } ++ ++ irq_set_status_flags(mhdp->irq[IRQ_OUT], IRQ_NOAUTOEN); ++ ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_OUT], ++ NULL, cdns_mhdp8501_irq_thread, ++ IRQF_ONESHOT, dev_name(dev), mhdp); ++ if (ret < 0) { ++ dev_err(dev, "can't claim irq %d\n", mhdp->irq[IRQ_OUT]); ++ return -EINVAL; ++ } ++ ++ /* cdns_mhdp8501_dt_parse() ensures connector_type is valid */ ++ if (mhdp->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ++ phy_mode = PHY_MODE_DP; ++ else if (mhdp->connector_type == DRM_MODE_CONNECTOR_HDMIA) ++ phy_mode = PHY_MODE_HDMI; ++ ++ dev_set_drvdata(dev, mhdp); ++ ++ /* init base struct for access mhdp mailbox */ ++ mhdp->base.dev = mhdp->dev; ++ mhdp->base.regs = mhdp->regs; ++ ++ if (mhdp->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { ++ drm_dp_aux_init(&mhdp->dp.aux); ++ mhdp->dp.aux.name = "mhdp8501_dp_aux"; ++ mhdp->dp.aux.dev = dev; ++ mhdp->dp.aux.transfer = cdns_dp_aux_transfer; ++ } ++ ++ /* Enable APB clock */ ++ mhdp->apb_clk = devm_clk_get_enabled(dev, NULL); ++ if (IS_ERR(mhdp->apb_clk)) ++ return dev_err_probe(dev, PTR_ERR(mhdp->apb_clk), ++ "couldn't get apb clk\n"); ++ /* ++ * Wait for the KEEP_ALIVE "message" on the first 8 bits. ++ * Updated each sched "tick" (~2ms) ++ */ ++ ret = readl_poll_timeout(mhdp->regs + KEEP_ALIVE, reg, ++ reg & CDNS_KEEP_ALIVE_MASK, 500, ++ CDNS_KEEP_ALIVE_TIMEOUT); ++ if (ret) { ++ dev_err(dev, "device didn't give any life sign: reg %d\n", reg); ++ return ret; ++ } ++ ++ ret = phy_init(mhdp->phy); ++ if (ret) { ++ dev_err(dev, "Failed to initialize PHY: %d\n", ret); ++ return ret; ++ } ++ ++ ret = phy_set_mode(mhdp->phy, phy_mode); ++ if (ret) { ++ dev_err(dev, "Failed to configure PHY: %d\n", ret); ++ return ret; ++ } ++ ++ /* Enable cable hotplug detect */ ++ if (cdns_mhdp8501_read_hpd(mhdp)) ++ enable_irq(mhdp->irq[IRQ_OUT]); ++ else ++ enable_irq(mhdp->irq[IRQ_IN]); ++ ++ return cdns_mhdp8501_add_bridge(mhdp); ++} ++ ++static void cdns_mhdp8501_remove(struct platform_device *pdev) ++{ ++ struct cdns_mhdp8501_device *mhdp = platform_get_drvdata(pdev); ++ ++ cdns_mhdp8501_remove_device_files(mhdp); ++ ++ if (mhdp->connector_type == DRM_MODE_CONNECTOR_DisplayPort) ++ cdns_dp_aux_destroy(mhdp); ++ ++ drm_bridge_remove(&mhdp->bridge); ++} ++ ++static const struct of_device_id cdns_mhdp8501_dt_ids[] = { ++ { .compatible = "fsl,imx8mq-mhdp8501", ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, cdns_mhdp8501_dt_ids); ++ ++static struct platform_driver cdns_mhdp8501_driver = { ++ .probe = cdns_mhdp8501_probe, ++ .remove = cdns_mhdp8501_remove, ++ .driver = { ++ .name = "cdns-mhdp8501", ++ .of_match_table = cdns_mhdp8501_dt_ids, ++ }, ++}; ++ ++module_platform_driver(cdns_mhdp8501_driver); ++ ++MODULE_AUTHOR("Sandor Yu "); ++MODULE_DESCRIPTION("Cadence MHDP8501 bridge driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-core.h +new file mode 100644 +index 0000000000000..8fc463098ab84 +--- /dev/null ++++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-core.h +@@ -0,0 +1,380 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Cadence MHDP 8501 Common head file ++ * ++ * Copyright (C) 2019-2024 NXP Semiconductor, Inc. ++ * ++ */ ++ ++#ifndef _CDNS_MHDP8501_CORE_H_ ++#define _CDNS_MHDP8501_CORE_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define ADDR_IMEM 0x10000 ++#define ADDR_DMEM 0x20000 ++ ++/* APB CFG addr */ ++#define APB_CTRL 0 ++#define XT_INT_CTRL 0x04 ++#define MAILBOX_FULL_ADDR 0x08 ++#define MAILBOX_EMPTY_ADDR 0x0c ++#define MAILBOX0_WR_DATA 0x10 ++#define MAILBOX0_RD_DATA 0x14 ++#define KEEP_ALIVE 0x18 ++#define VER_L 0x1c ++#define VER_H 0x20 ++#define VER_LIB_L_ADDR 0x24 ++#define VER_LIB_H_ADDR 0x28 ++#define SW_DEBUG_L 0x2c ++#define SW_DEBUG_H 0x30 ++#define MAILBOX_INT_MASK 0x34 ++#define MAILBOX_INT_STATUS 0x38 ++#define SW_CLK_L 0x3c ++#define SW_CLK_H 0x40 ++#define SW_EVENTS0 0x44 ++#define SW_EVENTS1 0x48 ++#define SW_EVENTS2 0x4c ++#define SW_EVENTS3 0x50 ++#define XT_OCD_CTRL 0x60 ++#define APB_INT_MASK 0x6c ++#define APB_STATUS_MASK 0x70 ++ ++/* Source phy comp */ ++#define PHY_DATA_SEL 0x0818 ++#define LANES_CONFIG 0x0814 ++ ++/* Source CAR Addr */ ++#define SOURCE_HDTX_CAR 0x0900 ++#define SOURCE_DPTX_CAR 0x0904 ++#define SOURCE_PHY_CAR 0x0908 ++#define SOURCE_CEC_CAR 0x090c ++#define SOURCE_CBUS_CAR 0x0910 ++#define SOURCE_PKT_CAR 0x0918 ++#define SOURCE_AIF_CAR 0x091c ++#define SOURCE_CIPHER_CAR 0x0920 ++#define SOURCE_CRYPTO_CAR 0x0924 ++ ++/* clock meters addr */ ++#define CM_CTRL 0x0a00 ++#define CM_I2S_CTRL 0x0a04 ++#define CM_SPDIF_CTRL 0x0a08 ++#define CM_VID_CTRL 0x0a0c ++#define CM_LANE_CTRL 0x0a10 ++#define I2S_NM_STABLE 0x0a14 ++#define I2S_NCTS_STABLE 0x0a18 ++#define SPDIF_NM_STABLE 0x0a1c ++#define SPDIF_NCTS_STABLE 0x0a20 ++#define NMVID_MEAS_STABLE 0x0a24 ++#define I2S_MEAS 0x0a40 ++#define SPDIF_MEAS 0x0a80 ++#define NMVID_MEAS 0x0ac0 ++ ++/* source vif addr */ ++#define BND_HSYNC2VSYNC 0x0b00 ++#define HSYNC2VSYNC_F1_L1 0x0b04 ++#define HSYNC2VSYNC_STATUS 0x0b0c ++#define HSYNC2VSYNC_POL_CTRL 0x0b10 ++ ++/* MHDP TX_top_comp */ ++#define SCHEDULER_H_SIZE 0x1000 ++#define SCHEDULER_V_SIZE 0x1004 ++#define HDTX_SIGNAL_FRONT_WIDTH 0x100c ++#define HDTX_SIGNAL_SYNC_WIDTH 0x1010 ++#define HDTX_SIGNAL_BACK_WIDTH 0x1014 ++#define HDTX_CONTROLLER 0x1018 ++#define HDTX_HPD 0x1020 ++#define HDTX_CLOCK_REG_0 0x1024 ++#define HDTX_CLOCK_REG_1 0x1028 ++ ++/* DPTX hpd addr */ ++#define HPD_IRQ_DET_MIN_TIMER 0x2100 ++#define HPD_IRQ_DET_MAX_TIMER 0x2104 ++#define HPD_UNPLGED_DET_MIN_TIMER 0x2108 ++#define HPD_STABLE_TIMER 0x210c ++#define HPD_FILTER_TIMER 0x2110 ++#define HPD_EVENT_MASK 0x211c ++#define HPD_EVENT_DET 0x2120 ++ ++/* DPTX framer addr */ ++#define DP_FRAMER_GLOBAL_CONFIG 0x2200 ++#define DP_SW_RESET 0x2204 ++#define DP_FRAMER_TU 0x2208 ++#define DP_FRAMER_PXL_REPR 0x220c ++#define DP_FRAMER_SP 0x2210 ++#define AUDIO_PACK_CONTROL 0x2214 ++#define DP_VC_TABLE(x) (0x2218 + ((x) << 2)) ++#define DP_VB_ID 0x2258 ++#define DP_MTPH_LVP_CONTROL 0x225c ++#define DP_MTPH_SYMBOL_VALUES 0x2260 ++#define DP_MTPH_ECF_CONTROL 0x2264 ++#define DP_MTPH_ACT_CONTROL 0x2268 ++#define DP_MTPH_STATUS 0x226c ++#define DP_INTERRUPT_SOURCE 0x2270 ++#define DP_INTERRUPT_MASK 0x2274 ++#define DP_FRONT_BACK_PORCH 0x2278 ++#define DP_BYTE_COUNT 0x227c ++ ++/* DPTX stream addr */ ++#define MSA_HORIZONTAL_0 0x2280 ++#define MSA_HORIZONTAL_1 0x2284 ++#define MSA_VERTICAL_0 0x2288 ++#define MSA_VERTICAL_1 0x228c ++#define MSA_MISC 0x2290 ++#define STREAM_CONFIG 0x2294 ++#define AUDIO_PACK_STATUS 0x2298 ++#define VIF_STATUS 0x229c ++#define PCK_STUFF_STATUS_0 0x22a0 ++#define PCK_STUFF_STATUS_1 0x22a4 ++#define INFO_PACK_STATUS 0x22a8 ++#define RATE_GOVERNOR_STATUS 0x22ac ++#define DP_HORIZONTAL 0x22b0 ++#define DP_VERTICAL_0 0x22b4 ++#define DP_VERTICAL_1 0x22b8 ++#define DP_BLOCK_SDP 0x22bc ++ ++/* DPTX glbl addr */ ++#define DPTX_LANE_EN 0x2300 ++#define DPTX_ENHNCD 0x2304 ++#define DPTX_INT_MASK 0x2308 ++#define DPTX_INT_STATUS 0x230c ++ ++/* DP AUX Addr */ ++#define DP_AUX_HOST_CONTROL 0x2800 ++#define DP_AUX_INTERRUPT_SOURCE 0x2804 ++#define DP_AUX_INTERRUPT_MASK 0x2808 ++#define DP_AUX_SWAP_INVERSION_CONTROL 0x280c ++#define DP_AUX_SEND_NACK_TRANSACTION 0x2810 ++#define DP_AUX_CLEAR_RX 0x2814 ++#define DP_AUX_CLEAR_TX 0x2818 ++#define DP_AUX_TIMER_STOP 0x281c ++#define DP_AUX_TIMER_CLEAR 0x2820 ++#define DP_AUX_RESET_SW 0x2824 ++#define DP_AUX_DIVIDE_2M 0x2828 ++#define DP_AUX_TX_PREACHARGE_LENGTH 0x282c ++#define DP_AUX_FREQUENCY_1M_MAX 0x2830 ++#define DP_AUX_FREQUENCY_1M_MIN 0x2834 ++#define DP_AUX_RX_PRE_MIN 0x2838 ++#define DP_AUX_RX_PRE_MAX 0x283c ++#define DP_AUX_TIMER_PRESET 0x2840 ++#define DP_AUX_NACK_FORMAT 0x2844 ++#define DP_AUX_TX_DATA 0x2848 ++#define DP_AUX_RX_DATA 0x284c ++#define DP_AUX_TX_STATUS 0x2850 ++#define DP_AUX_RX_STATUS 0x2854 ++#define DP_AUX_RX_CYCLE_COUNTER 0x2858 ++#define DP_AUX_MAIN_STATES 0x285c ++#define DP_AUX_MAIN_TIMER 0x2860 ++#define DP_AUX_AFE_OUT 0x2864 ++ ++/* source pif addr */ ++#define SOURCE_PIF_WR_ADDR 0x30800 ++#define SOURCE_PIF_WR_REQ 0x30804 ++#define SOURCE_PIF_RD_ADDR 0x30808 ++#define SOURCE_PIF_RD_REQ 0x3080c ++#define SOURCE_PIF_DATA_WR 0x30810 ++#define SOURCE_PIF_DATA_RD 0x30814 ++#define SOURCE_PIF_FIFO1_FLUSH 0x30818 ++#define SOURCE_PIF_FIFO2_FLUSH 0x3081c ++#define SOURCE_PIF_STATUS 0x30820 ++#define SOURCE_PIF_INTERRUPT_SOURCE 0x30824 ++#define SOURCE_PIF_INTERRUPT_MASK 0x30828 ++#define SOURCE_PIF_PKT_ALLOC_REG 0x3082c ++#define SOURCE_PIF_PKT_ALLOC_WR_EN 0x30830 ++#define SOURCE_PIF_SW_RESET 0x30834 ++ ++#define LINK_TRAINING_NOT_ACTIV 0 ++#define LINK_TRAINING_RUN 1 ++#define LINK_TRAINING_RESTART 2 ++ ++#define CONTROL_VIDEO_IDLE 0 ++#define CONTROL_VIDEO_VALID 1 ++ ++#define INTERLACE_FMT_DET BIT(12) ++#define VIF_BYPASS_INTERLACE BIT(13) ++#define TU_CNT_RST_EN BIT(15) ++#define INTERLACE_DTCT_WIN 0x20 ++ ++#define DP_FRAMER_SP_INTERLACE_EN BIT(2) ++#define DP_FRAMER_SP_HSP BIT(1) ++#define DP_FRAMER_SP_VSP BIT(0) ++ ++/* Capability */ ++#define AUX_HOST_INVERT 3 ++#define FAST_LT_SUPPORT 1 ++#define FAST_LT_NOT_SUPPORT 0 ++#define LANE_MAPPING_FLIPPED 0xe4 ++#define ENHANCED 1 ++#define SCRAMBLER_EN BIT(4) ++ ++#define FULL_LT_STARTED BIT(0) ++#define FASE_LT_STARTED BIT(1) ++#define CLK_RECOVERY_FINISHED BIT(2) ++#define EQ_PHASE_FINISHED BIT(3) ++#define FASE_LT_START_FINISHED BIT(4) ++#define CLK_RECOVERY_FAILED BIT(5) ++#define EQ_PHASE_FAILED BIT(6) ++#define FASE_LT_FAILED BIT(7) ++ ++#define TU_SIZE 30 ++#define CDNS_DP_MAX_LINK_RATE 540000 ++ ++#define F_HDMI2_CTRL_IL_MODE(x) (((x) & ((1 << 1) - 1)) << 19) ++#define F_HDMI2_PREAMBLE_EN(x) (((x) & ((1 << 1) - 1)) << 18) ++#define F_HDMI_ENCODING(x) (((x) & ((1 << 2) - 1)) << 16) ++#define F_DATA_EN(x) (((x) & ((1 << 1) - 1)) << 15) ++#define F_CLEAR_AVMUTE(x) (((x) & ((1 << 1) - 1)) << 14) ++#define F_SET_AVMUTE(x) (((x) & ((1 << 1) - 1)) << 13) ++#define F_GCP_EN(x) (((x) & ((1 << 1) - 1)) << 12) ++#define F_BCH_EN(x) (((x) & ((1 << 1) - 1)) << 11) ++#define F_PIC_3D(x) (((x) & ((1 << 4) - 1)) << 7) ++#define F_VIF_DATA_WIDTH(x) (((x) & ((1 << 2) - 1)) << 2) ++#define F_HDMI_MODE(x) (((x) & ((1 << 2) - 1)) << 0) ++ ++#define F_SOURCE_PHY_MHDP_SEL(x) (((x) & ((1 << 2) - 1)) << 3) ++ ++#define F_HPD_GLITCH_WIDTH(x) (((x) & ((1 << 8) - 1)) << 12) ++#define F_PACKET_TYPE(x) (((x) & ((1 << 8) - 1)) << 8) ++#define F_HPD_VALID_WIDTH(x) (((x) & ((1 << 12) - 1)) << 0) ++ ++#define F_SOURCE_PHY_LANE3_SWAP(x) (((x) & ((1 << 2) - 1)) << 6) ++#define F_SOURCE_PHY_LANE2_SWAP(x) (((x) & ((1 << 2) - 1)) << 4) ++#define F_SOURCE_PHY_LANE1_SWAP(x) (((x) & ((1 << 2) - 1)) << 2) ++#define F_SOURCE_PHY_LANE0_SWAP(x) (((x) & ((1 << 2) - 1)) << 0) ++ ++#define F_ACTIVE_IDLE_TYPE(x) (((x) & ((1 << 1) - 1)) << 17) ++#define F_TYPE_VALID(x) (((x) & ((1 << 1) - 1)) << 16) ++#define F_PKT_ALLOC_ADDRESS(x) (((x) & ((1 << 4) - 1)) << 0) ++ ++#define F_FIFO1_FLUSH(x) (((x) & ((1 << 1) - 1)) << 0) ++#define F_PKT_ALLOC_WR_EN(x) (((x) & ((1 << 1) - 1)) << 0) ++#define F_DATA_WR(x) (x) ++#define F_WR_ADDR(x) (((x) & ((1 << 4) - 1)) << 0) ++#define F_HOST_WR(x) (((x) & ((1 << 1) - 1)) << 0) ++ ++/* Reference cycles when using lane clock as reference */ ++#define LANE_REF_CYC 0x8000 ++ ++/* HPD Debounce */ ++#define HOTPLUG_DEBOUNCE_MS 200 ++ ++/* HPD IRQ Index */ ++#define IRQ_IN 0 ++#define IRQ_OUT 1 ++#define IRQ_NUM 2 ++ ++/* FW check alive timeout */ ++#define CDNS_KEEP_ALIVE_TIMEOUT 2000 ++#define CDNS_KEEP_ALIVE_MASK GENMASK(7, 0) ++ ++enum voltage_swing_level { ++ VOLTAGE_LEVEL_0, ++ VOLTAGE_LEVEL_1, ++ VOLTAGE_LEVEL_2, ++ VOLTAGE_LEVEL_3, ++}; ++ ++enum pre_emphasis_level { ++ PRE_EMPHASIS_LEVEL_0, ++ PRE_EMPHASIS_LEVEL_1, ++ PRE_EMPHASIS_LEVEL_2, ++ PRE_EMPHASIS_LEVEL_3, ++}; ++ ++enum pattern_set { ++ PTS1 = BIT(0), ++ PTS2 = BIT(1), ++ PTS3 = BIT(2), ++ PTS4 = BIT(3), ++ DP_NONE = BIT(4) ++}; ++ ++enum vic_color_depth { ++ BCS_6 = 0x1, ++ BCS_8 = 0x2, ++ BCS_10 = 0x4, ++ BCS_12 = 0x8, ++ BCS_16 = 0x10, ++}; ++ ++enum vic_bt_type { ++ BT_601 = 0x0, ++ BT_709 = 0x1, ++}; ++ ++enum { ++ MODE_DVI, ++ MODE_HDMI_1_4, ++ MODE_HDMI_2_0, ++}; ++ ++struct video_info { ++ int bpc; ++ int color_fmt; ++}; ++ ++struct cdns_hdmi_i2c { ++ struct i2c_adapter adap; ++ ++ struct mutex lock; /* used to serialize data transfers */ ++ struct completion cmp; ++ u8 stat; ++ ++ u8 slave_reg; ++ bool is_regaddr; ++ bool is_segment; ++}; ++ ++struct cdns_mhdp8501_device { ++ struct cdns_mhdp_base base; ++ ++ struct device *dev; ++ void __iomem *regs; ++ struct drm_connector *curr_conn; ++ struct drm_bridge bridge; ++ struct clk *apb_clk; ++ struct phy *phy; ++ ++ struct video_info video_info; ++ ++ int irq[IRQ_NUM]; ++ struct delayed_work hotplug_work; ++ int connector_type; ++ u32 lane_mapping; ++ ++ union { ++ struct _dp_data { ++ u32 rate; ++ u8 num_lanes; ++ struct drm_dp_aux aux; ++ u8 dpcd[DP_RECEIVER_CAP_SIZE]; ++ } dp; ++ struct _hdmi_data { ++ u32 hdmi_type; ++ struct cdns_hdmi_i2c *i2c; ++ } hdmi; ++ }; ++}; ++ ++extern const struct drm_bridge_funcs cdns_dp_bridge_funcs; ++extern const struct drm_bridge_funcs cdns_hdmi_bridge_funcs; ++ ++enum drm_connector_status ++cdns_mhdp8501_detect(struct drm_bridge *bridge); ++enum drm_mode_status ++cdns_mhdp8501_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, ++ const struct drm_display_mode *mode); ++ ++ssize_t cdns_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg); ++int cdns_dp_aux_destroy(struct cdns_mhdp8501_device *mhdp); ++void cdns_dp_check_link_state(struct cdns_mhdp8501_device *mhdp); ++ ++void cdns_hdmi_handle_hotplug(struct cdns_mhdp8501_device *mhdp); ++struct i2c_adapter *cdns_hdmi_i2c_adapter(struct cdns_mhdp8501_device *mhdp); ++#endif +diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-dp.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-dp.c +new file mode 100644 +index 0000000000000..157b4d44b9e2b +--- /dev/null ++++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-dp.c +@@ -0,0 +1,693 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Cadence MHDP8501 DisplayPort(DP) bridge driver ++ * ++ * Copyright (C) 2019-2024 NXP Semiconductor, Inc. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "cdns-mhdp8501-core.h" ++ ++#define LINK_TRAINING_TIMEOUT_MS 500 ++#define LINK_TRAINING_RETRY_MS 20 ++ ++ssize_t cdns_dp_aux_transfer(struct drm_dp_aux *aux, ++ struct drm_dp_aux_msg *msg) ++{ ++ struct cdns_mhdp8501_device *mhdp = dev_get_drvdata(aux->dev); ++ bool native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ); ++ int ret; ++ ++ /* Ignore address only message */ ++ if (!msg->size || !msg->buffer) { ++ msg->reply = native ? ++ DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK; ++ return msg->size; ++ } ++ ++ if (!native) { ++ dev_err(mhdp->dev, "%s: only native messages supported\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* msg sanity check */ ++ if (msg->size > DP_AUX_MAX_PAYLOAD_BYTES) { ++ dev_err(mhdp->dev, "%s: invalid msg: size(%zu), request(%x)\n", ++ __func__, msg->size, (unsigned int)msg->request); ++ return -EINVAL; ++ } ++ ++ if (msg->request == DP_AUX_NATIVE_WRITE) { ++ const u8 *buf = msg->buffer; ++ int i; ++ ++ for (i = 0; i < msg->size; ++i) { ++ ret = cdns_mhdp_dpcd_write(&mhdp->base, ++ msg->address + i, buf[i]); ++ if (ret < 0) { ++ dev_err(mhdp->dev, "Failed to write DPCD\n"); ++ return ret; ++ } ++ } ++ msg->reply = DP_AUX_NATIVE_REPLY_ACK; ++ return msg->size; ++ } ++ ++ if (msg->request == DP_AUX_NATIVE_READ) { ++ ret = cdns_mhdp_dpcd_read(&mhdp->base, msg->address, ++ msg->buffer, msg->size); ++ if (ret < 0) ++ return ret; ++ msg->reply = DP_AUX_NATIVE_REPLY_ACK; ++ return msg->size; ++ } ++ return 0; ++} ++ ++int cdns_dp_aux_destroy(struct cdns_mhdp8501_device *mhdp) ++{ ++ drm_dp_aux_unregister(&mhdp->dp.aux); ++ ++ return 0; ++} ++ ++static int cdns_dp_get_msa_misc(struct video_info *video) ++{ ++ u32 msa_misc; ++ u8 color_space = 0; ++ u8 bpc = 0; ++ ++ switch (video->color_fmt) { ++ /* set YUV default color space conversion to BT601 */ ++ case DRM_COLOR_FORMAT_YCBCR444: ++ color_space = 6 + BT_601 * 8; ++ break; ++ case DRM_COLOR_FORMAT_YCBCR422: ++ color_space = 5 + BT_601 * 8; ++ break; ++ case DRM_COLOR_FORMAT_YCBCR420: ++ color_space = 5; ++ break; ++ case DRM_COLOR_FORMAT_RGB444: ++ default: ++ color_space = 0; ++ break; ++ }; ++ ++ switch (video->bpc) { ++ case 6: ++ bpc = 0; ++ break; ++ case 10: ++ bpc = 2; ++ break; ++ case 12: ++ bpc = 3; ++ break; ++ case 16: ++ bpc = 4; ++ break; ++ case 8: ++ default: ++ bpc = 1; ++ break; ++ }; ++ ++ msa_misc = (bpc << 5) | (color_space << 1); ++ ++ return msa_misc; ++} ++ ++static int cdns_dp_config_video(struct cdns_mhdp8501_device *mhdp, ++ const struct drm_display_mode *mode) ++{ ++ struct video_info *video = &mhdp->video_info; ++ bool h_sync_polarity, v_sync_polarity; ++ u64 symbol; ++ u32 val, link_rate, rem; ++ u8 bit_per_pix, tu_size_reg = TU_SIZE; ++ int ret; ++ ++ bit_per_pix = (video->color_fmt == DRM_COLOR_FORMAT_YCBCR422) ? ++ (video->bpc * 2) : (video->bpc * 3); ++ ++ link_rate = mhdp->dp.rate / 1000; ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, BND_HSYNC2VSYNC, VIF_BYPASS_INTERLACE); ++ if (ret) ++ goto err_config_video; ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, HSYNC2VSYNC_POL_CTRL, 0); ++ if (ret) ++ goto err_config_video; ++ ++ /* ++ * get a best tu_size and valid symbol: ++ * 1. chose Lclk freq(162Mhz, 270Mhz, 540Mhz), set TU to 32 ++ * 2. calculate VS(valid symbol) = TU * Pclk * Bpp / (Lclk * Lanes) ++ * 3. if VS > *.85 or VS < *.1 or VS < 2 or TU < VS + 4, then set ++ * TU += 2 and repeat 2nd step. ++ */ ++ do { ++ tu_size_reg += 2; ++ symbol = tu_size_reg * mode->clock * bit_per_pix; ++ do_div(symbol, mhdp->dp.num_lanes * link_rate * 8); ++ rem = do_div(symbol, 1000); ++ if (tu_size_reg > 64) { ++ ret = -EINVAL; ++ dev_err(mhdp->dev, "tu error, clk:%d, lanes:%d, rate:%d\n", ++ mode->clock, mhdp->dp.num_lanes, link_rate); ++ goto err_config_video; ++ } ++ } while ((symbol <= 1) || (tu_size_reg - symbol < 4) || ++ (rem > 850) || (rem < 100)); ++ ++ val = symbol + (tu_size_reg << 8); ++ val |= TU_CNT_RST_EN; ++ ret = cdns_mhdp_reg_write(&mhdp->base, DP_FRAMER_TU, val); ++ if (ret) ++ goto err_config_video; ++ ++ /* set the FIFO Buffer size */ ++ val = div_u64(mode->clock * (symbol + 1), 1000) + link_rate; ++ val /= (mhdp->dp.num_lanes * link_rate); ++ val = div_u64(8 * (symbol + 1), bit_per_pix) - val; ++ val += 2; ++ ret = cdns_mhdp_reg_write(&mhdp->base, DP_VC_TABLE(15), val); ++ ++ switch (video->bpc) { ++ case 6: ++ val = BCS_6; ++ break; ++ case 10: ++ val = BCS_10; ++ break; ++ case 12: ++ val = BCS_12; ++ break; ++ case 16: ++ val = BCS_16; ++ break; ++ case 8: ++ default: ++ val = BCS_8; ++ break; ++ }; ++ ++ val += video->color_fmt << 8; ++ ret = cdns_mhdp_reg_write(&mhdp->base, DP_FRAMER_PXL_REPR, val); ++ if (ret) ++ goto err_config_video; ++ ++ v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); ++ h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); ++ ++ val = h_sync_polarity ? DP_FRAMER_SP_HSP : 0; ++ val |= v_sync_polarity ? DP_FRAMER_SP_VSP : 0; ++ ret = cdns_mhdp_reg_write(&mhdp->base, DP_FRAMER_SP, val); ++ if (ret) ++ goto err_config_video; ++ ++ val = (mode->hsync_start - mode->hdisplay) << 16; ++ val |= mode->htotal - mode->hsync_end; ++ ret = cdns_mhdp_reg_write(&mhdp->base, DP_FRONT_BACK_PORCH, val); ++ if (ret) ++ goto err_config_video; ++ ++ val = mode->hdisplay * bit_per_pix / 8; ++ ret = cdns_mhdp_reg_write(&mhdp->base, DP_BYTE_COUNT, val); ++ if (ret) ++ goto err_config_video; ++ ++ val = mode->htotal | ((mode->htotal - mode->hsync_start) << 16); ++ ret = cdns_mhdp_reg_write(&mhdp->base, MSA_HORIZONTAL_0, val); ++ if (ret) ++ goto err_config_video; ++ ++ val = mode->hsync_end - mode->hsync_start; ++ val |= (mode->hdisplay << 16) | (h_sync_polarity << 15); ++ ret = cdns_mhdp_reg_write(&mhdp->base, MSA_HORIZONTAL_1, val); ++ if (ret) ++ goto err_config_video; ++ ++ val = mode->vtotal; ++ val |= (mode->vtotal - mode->vsync_start) << 16; ++ ret = cdns_mhdp_reg_write(&mhdp->base, MSA_VERTICAL_0, val); ++ if (ret) ++ goto err_config_video; ++ ++ val = mode->vsync_end - mode->vsync_start; ++ val |= (mode->vdisplay << 16) | (v_sync_polarity << 15); ++ ret = cdns_mhdp_reg_write(&mhdp->base, MSA_VERTICAL_1, val); ++ if (ret) ++ goto err_config_video; ++ ++ val = cdns_dp_get_msa_misc(video); ++ ret = cdns_mhdp_reg_write(&mhdp->base, MSA_MISC, val); ++ if (ret) ++ goto err_config_video; ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, STREAM_CONFIG, 1); ++ if (ret) ++ goto err_config_video; ++ ++ val = mode->hsync_end - mode->hsync_start; ++ val |= mode->hdisplay << 16; ++ ret = cdns_mhdp_reg_write(&mhdp->base, DP_HORIZONTAL, val); ++ if (ret) ++ goto err_config_video; ++ ++ val = mode->vdisplay; ++ val |= (mode->vtotal - mode->vsync_start) << 16; ++ ret = cdns_mhdp_reg_write(&mhdp->base, DP_VERTICAL_0, val); ++ if (ret) ++ goto err_config_video; ++ ++ val = mode->vtotal; ++ ret = cdns_mhdp_reg_write(&mhdp->base, DP_VERTICAL_1, val); ++ if (ret) ++ goto err_config_video; ++ ++ ret = cdns_mhdp_dp_reg_write_bit(&mhdp->base, DP_VB_ID, 2, 1, 0); ++ ++err_config_video: ++ if (ret) ++ dev_err(mhdp->dev, "config video failed: %d\n", ret); ++ return ret; ++} ++ ++static void cdns_dp_pixel_clk_reset(struct cdns_mhdp8501_device *mhdp) ++{ ++ u32 val; ++ ++ /* reset pixel clk */ ++ cdns_mhdp_reg_read(&mhdp->base, SOURCE_HDTX_CAR, &val); ++ cdns_mhdp_reg_write(&mhdp->base, SOURCE_HDTX_CAR, val & 0xFD); ++ cdns_mhdp_reg_write(&mhdp->base, SOURCE_HDTX_CAR, val); ++} ++ ++static int cdns_dp_set_video_status(struct cdns_mhdp8501_device *mhdp, int active) ++{ ++ u8 msg; ++ int ret; ++ ++ msg = !!active; ++ ++ ret = cdns_mhdp_mailbox_send(&mhdp->base, MB_MODULE_ID_DP_TX, ++ DPTX_SET_VIDEO, sizeof(msg), &msg); ++ if (ret) ++ dev_err(mhdp->dev, "set video status failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int cdns_dp_training_start(struct cdns_mhdp8501_device *mhdp) ++{ ++ unsigned long timeout; ++ u8 msg, event[2]; ++ int ret; ++ ++ msg = LINK_TRAINING_RUN; ++ ++ /* start training */ ++ ret = cdns_mhdp_mailbox_send(&mhdp->base, MB_MODULE_ID_DP_TX, ++ DPTX_TRAINING_CONTROL, sizeof(msg), &msg); ++ if (ret) ++ return ret; ++ ++ timeout = jiffies + msecs_to_jiffies(LINK_TRAINING_TIMEOUT_MS); ++ while (time_before(jiffies, timeout)) { ++ msleep(LINK_TRAINING_RETRY_MS); ++ ret = cdns_mhdp_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_DP_TX, ++ DPTX_READ_EVENT, ++ 0, NULL, sizeof(event), event); ++ if (ret) ++ return ret; ++ ++ if (event[1] & CLK_RECOVERY_FAILED) ++ dev_err(mhdp->dev, "clock recovery failed\n"); ++ else if (event[1] & EQ_PHASE_FINISHED) ++ return 0; ++ } ++ ++ return -ETIMEDOUT; ++} ++ ++static int cdns_dp_get_training_status(struct cdns_mhdp8501_device *mhdp) ++{ ++ u8 status[13]; ++ int ret; ++ ++ ret = cdns_mhdp_mailbox_send_recv(&mhdp->base, MB_MODULE_ID_DP_TX, ++ DPTX_READ_LINK_STAT, ++ 0, NULL, sizeof(status), status); ++ if (ret) ++ return ret; ++ ++ mhdp->dp.rate = drm_dp_bw_code_to_link_rate(status[0]); ++ mhdp->dp.num_lanes = status[1]; ++ ++ return ret; ++} ++ ++static int cdns_dp_train_link(struct cdns_mhdp8501_device *mhdp) ++{ ++ int ret; ++ ++ ret = cdns_dp_training_start(mhdp); ++ if (ret) { ++ dev_err(mhdp->dev, "Failed to start training %d\n", ret); ++ return ret; ++ } ++ ++ ret = cdns_dp_get_training_status(mhdp); ++ if (ret) { ++ dev_err(mhdp->dev, "Failed to get training stat %d\n", ret); ++ return ret; ++ } ++ ++ dev_dbg(mhdp->dev, "rate:0x%x, lanes:%d\n", mhdp->dp.rate, ++ mhdp->dp.num_lanes); ++ return ret; ++} ++ ++static int cdns_dp_set_host_cap(struct cdns_mhdp8501_device *mhdp) ++{ ++ u8 msg[8]; ++ int ret; ++ ++ msg[0] = drm_dp_link_rate_to_bw_code(mhdp->dp.rate); ++ msg[1] = mhdp->dp.num_lanes | SCRAMBLER_EN; ++ msg[2] = VOLTAGE_LEVEL_2; ++ msg[3] = PRE_EMPHASIS_LEVEL_3; ++ msg[4] = PTS1 | PTS2 | PTS3 | PTS4; ++ msg[5] = FAST_LT_NOT_SUPPORT; ++ msg[6] = mhdp->lane_mapping; ++ msg[7] = ENHANCED; ++ ++ ret = cdns_mhdp_mailbox_send(&mhdp->base, MB_MODULE_ID_DP_TX, ++ DPTX_SET_HOST_CAPABILITIES, ++ sizeof(msg), msg); ++ if (ret) ++ dev_err(mhdp->dev, "set host cap failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int cdns_dp_get_edid_block(void *data, u8 *edid, ++ unsigned int block, size_t length) ++{ ++ struct cdns_mhdp8501_device *mhdp = data; ++ u8 msg[2], reg[2], i; ++ int ret; ++ ++ for (i = 0; i < 4; i++) { ++ msg[0] = block / 2; ++ msg[1] = block % 2; ++ ++ ret = cdns_mhdp_mailbox_send_recv_multi(&mhdp->base, ++ MB_MODULE_ID_DP_TX, ++ DPTX_GET_EDID, ++ sizeof(msg), msg, ++ DPTX_GET_EDID, ++ sizeof(reg), reg, ++ length, edid); ++ if (ret) ++ continue; ++ ++ if (reg[0] == length && reg[1] == block / 2) ++ break; ++ } ++ ++ if (ret) ++ dev_err(mhdp->dev, "get block[%d] edid failed: %d\n", ++ block, ret); ++ ++ return ret; ++} ++ ++static void cdns_dp_mode_set(struct cdns_mhdp8501_device *mhdp, ++ const struct drm_display_mode *mode) ++{ ++ union phy_configure_opts phy_cfg; ++ int ret; ++ ++ cdns_dp_pixel_clk_reset(mhdp); ++ ++ /* Get DP Caps */ ++ ret = drm_dp_dpcd_read(&mhdp->dp.aux, DP_DPCD_REV, mhdp->dp.dpcd, ++ DP_RECEIVER_CAP_SIZE); ++ if (ret < 0) { ++ dev_err(mhdp->dev, "Failed to get caps %d\n", ret); ++ return; ++ } ++ ++ mhdp->dp.rate = drm_dp_max_link_rate(mhdp->dp.dpcd); ++ mhdp->dp.num_lanes = drm_dp_max_lane_count(mhdp->dp.dpcd); ++ ++ /* check the max link rate */ ++ if (mhdp->dp.rate > CDNS_DP_MAX_LINK_RATE) ++ mhdp->dp.rate = CDNS_DP_MAX_LINK_RATE; ++ ++ phy_cfg.dp.lanes = mhdp->dp.num_lanes; ++ phy_cfg.dp.link_rate = mhdp->dp.rate; ++ phy_cfg.dp.set_lanes = false; ++ phy_cfg.dp.set_rate = false; ++ phy_cfg.dp.set_voltages = false; ++ ++ ret = phy_configure(mhdp->phy, &phy_cfg); ++ if (ret) { ++ dev_err(mhdp->dev, "%s: phy_configure() failed: %d\n", ++ __func__, ret); ++ return; ++ } ++ ++ /* Video off */ ++ ret = cdns_dp_set_video_status(mhdp, CONTROL_VIDEO_IDLE); ++ if (ret) { ++ dev_err(mhdp->dev, "Failed to valid video %d\n", ret); ++ return; ++ } ++ ++ /* Line swapping */ ++ cdns_mhdp_reg_write(&mhdp->base, LANES_CONFIG, 0x00400000 | mhdp->lane_mapping); ++ ++ /* Set DP host capability */ ++ ret = cdns_dp_set_host_cap(mhdp); ++ if (ret) { ++ dev_err(mhdp->dev, "Failed to set host cap %d\n", ret); ++ return; ++ } ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, DP_AUX_SWAP_INVERSION_CONTROL, ++ AUX_HOST_INVERT); ++ if (ret) { ++ dev_err(mhdp->dev, "Failed to set host invert %d\n", ret); ++ return; ++ } ++ ++ ret = cdns_dp_config_video(mhdp, mode); ++ if (ret) ++ dev_err(mhdp->dev, "Failed to config video %d\n", ret); ++} ++ ++static bool ++cdns_dp_needs_link_retrain(struct cdns_mhdp8501_device *mhdp) ++{ ++ u8 link_status[DP_LINK_STATUS_SIZE]; ++ ++ if (drm_dp_dpcd_read_phy_link_status(&mhdp->dp.aux, DP_PHY_DPRX, ++ link_status) < 0) ++ return false; ++ ++ /* Retrain if link not ok */ ++ return !drm_dp_channel_eq_ok(link_status, mhdp->dp.num_lanes); ++} ++ ++void cdns_dp_check_link_state(struct cdns_mhdp8501_device *mhdp) ++{ ++ struct drm_connector *connector = mhdp->curr_conn; ++ const struct drm_edid *drm_edid; ++ struct drm_connector_state *conn_state; ++ struct drm_crtc_state *crtc_state; ++ struct drm_crtc *crtc; ++ ++ if (!connector) ++ return; ++ ++ /* ++ * EDID data needs updating after each cable plugin ++ * due to potential display monitor changes ++ */ ++ drm_edid = drm_edid_read_custom(connector, cdns_dp_get_edid_block, mhdp); ++ drm_edid_connector_update(connector, drm_edid); ++ ++ if (!drm_edid) ++ return; ++ ++ drm_edid_free(drm_edid); ++ ++ conn_state = connector->state; ++ crtc = conn_state->crtc; ++ if (!crtc) ++ return; ++ ++ crtc_state = crtc->state; ++ if (!crtc_state->active) ++ return; ++ ++ if (!cdns_dp_needs_link_retrain(mhdp)) ++ return; ++ ++ /* DP link retrain */ ++ if (cdns_dp_train_link(mhdp)) ++ dev_err(mhdp->dev, "Failed link train\n"); ++} ++ ++static int cdns_dp_bridge_attach(struct drm_bridge *bridge, ++ enum drm_bridge_attach_flags flags) ++{ ++ struct cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ ++ if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { ++ dev_err(mhdp->dev, "do not support creating a drm_connector\n"); ++ return -EINVAL; ++ } ++ ++ mhdp->dp.aux.drm_dev = bridge->dev; ++ ++ return drm_dp_aux_register(&mhdp->dp.aux); ++} ++ ++static const struct drm_edid ++*cdns_dp_bridge_edid_read(struct drm_bridge *bridge, ++ struct drm_connector *connector) ++{ ++ struct cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ ++ return drm_edid_read_custom(connector, cdns_dp_get_edid_block, mhdp); ++} ++ ++/* Currently supported format */ ++static const u32 mhdp8501_input_fmts[] = { ++ MEDIA_BUS_FMT_RGB888_1X24, ++ MEDIA_BUS_FMT_RGB101010_1X30, ++}; ++ ++static u32 *cdns_dp_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; ++ ++ *num_input_fmts = 0; ++ ++ input_fmts = kcalloc(ARRAY_SIZE(mhdp8501_input_fmts), ++ sizeof(*input_fmts), ++ GFP_KERNEL); ++ if (!input_fmts) ++ return NULL; ++ ++ *num_input_fmts = ARRAY_SIZE(mhdp8501_input_fmts); ++ memcpy(input_fmts, mhdp8501_input_fmts, sizeof(mhdp8501_input_fmts)); ++ ++ return input_fmts; ++} ++ ++static int cdns_dp_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 cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ struct video_info *video = &mhdp->video_info; ++ ++ if (bridge_state->input_bus_cfg.format == MEDIA_BUS_FMT_RGB888_1X24) { ++ video->bpc = 8; ++ video->color_fmt = DRM_COLOR_FORMAT_RGB444; ++ } else if (bridge_state->input_bus_cfg.format == MEDIA_BUS_FMT_RGB101010_1X30) { ++ video->bpc = 10; ++ video->color_fmt = DRM_COLOR_FORMAT_RGB444; ++ } else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static void cdns_dp_bridge_atomic_disable(struct drm_bridge *bridge, ++ struct drm_atomic_state *state) ++{ ++ struct cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ ++ cdns_dp_set_video_status(mhdp, CONTROL_VIDEO_IDLE); ++ mhdp->curr_conn = NULL; ++ ++ phy_power_off(mhdp->phy); ++} ++ ++static void cdns_dp_bridge_atomic_enable(struct drm_bridge *bridge, ++ struct drm_atomic_state *state) ++{ ++ struct cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ struct drm_connector *connector; ++ struct drm_crtc_state *crtc_state; ++ struct drm_connector_state *conn_state; ++ int ret; ++ ++ connector = drm_atomic_get_new_connector_for_encoder(state, ++ bridge->encoder); ++ if (WARN_ON(!connector)) ++ return; ++ ++ mhdp->curr_conn = connector; ++ ++ conn_state = drm_atomic_get_new_connector_state(state, connector); ++ if (WARN_ON(!conn_state)) ++ return; ++ ++ crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); ++ if (WARN_ON(!crtc_state)) ++ return; ++ ++ cdns_dp_mode_set(mhdp, &crtc_state->adjusted_mode); ++ ++ /* Power up PHY before link training */ ++ phy_power_on(mhdp->phy); ++ ++ /* Link training */ ++ ret = cdns_dp_train_link(mhdp); ++ if (ret) { ++ dev_err(mhdp->dev, "Failed link train %d\n", ret); ++ return; ++ } ++ ++ ret = cdns_dp_set_video_status(mhdp, CONTROL_VIDEO_VALID); ++ if (ret) { ++ dev_err(mhdp->dev, "Failed to valid video %d\n", ret); ++ return; ++ } ++} ++ ++const struct drm_bridge_funcs cdns_dp_bridge_funcs = { ++ .attach = cdns_dp_bridge_attach, ++ .detect = cdns_mhdp8501_detect, ++ .edid_read = cdns_dp_bridge_edid_read, ++ .mode_valid = cdns_mhdp8501_mode_valid, ++ .atomic_enable = cdns_dp_bridge_atomic_enable, ++ .atomic_disable = cdns_dp_bridge_atomic_disable, ++ .atomic_get_input_bus_fmts = cdns_dp_bridge_atomic_get_input_bus_fmts, ++ .atomic_check = cdns_dp_bridge_atomic_check, ++ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, ++ .atomic_reset = drm_atomic_helper_bridge_reset, ++}; +diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-hdmi.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-hdmi.c +new file mode 100644 +index 0000000000000..9556d0929e21d +--- /dev/null ++++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8501-hdmi.c +@@ -0,0 +1,744 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Cadence MHDP8501 HDMI bridge driver ++ * ++ * Copyright (C) 2019-2024 NXP Semiconductor, Inc. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "cdns-mhdp8501-core.h" ++ ++/** ++ * cdns_hdmi_config_infoframe() - fill the HDMI infoframe ++ * @mhdp: phandle to mhdp device. ++ * @entry_id: The packet memory address in which the data is written. ++ * @len: length of infoframe. ++ * @buf: point to InfoFrame Packet. ++ * @type: Packet Type of InfoFrame in HDMI Specification. ++ * ++ */ ++ ++static void cdns_hdmi_clear_infoframe(struct cdns_mhdp8501_device *mhdp, ++ u8 entry_id, u8 type) ++{ ++ u32 val; ++ ++ /* invalidate entry */ ++ val = F_ACTIVE_IDLE_TYPE(1) | F_PKT_ALLOC_ADDRESS(entry_id) | ++ F_PACKET_TYPE(type); ++ writel(val, mhdp->regs + SOURCE_PIF_PKT_ALLOC_REG); ++ writel(F_PKT_ALLOC_WR_EN(1), mhdp->regs + SOURCE_PIF_PKT_ALLOC_WR_EN); ++} ++ ++static void cdns_hdmi_config_infoframe(struct cdns_mhdp8501_device *mhdp, ++ u8 entry_id, u8 len, ++ const u8 *buf, u8 type) ++{ ++ u8 packet[32], packet_len = 32; ++ u32 packet32, len32; ++ u32 val, i; ++ ++ /* ++ * only support 32 bytes now ++ * packet[0] = 0 ++ * packet[1-3] = HB[0-2] InfoFrame Packet Header ++ * packet[4-31 = PB[0-27] InfoFrame Packet Contents ++ */ ++ if (len >= (packet_len - 1)) ++ return; ++ packet[0] = 0; ++ memcpy(packet + 1, buf, len); ++ ++ cdns_hdmi_clear_infoframe(mhdp, entry_id, type); ++ ++ /* flush fifo 1 */ ++ writel(F_FIFO1_FLUSH(1), mhdp->regs + SOURCE_PIF_FIFO1_FLUSH); ++ ++ /* write packet into memory */ ++ len32 = packet_len / 4; ++ for (i = 0; i < len32; i++) { ++ packet32 = get_unaligned_le32(packet + 4 * i); ++ writel(F_DATA_WR(packet32), mhdp->regs + SOURCE_PIF_DATA_WR); ++ } ++ ++ /* write entry id */ ++ writel(F_WR_ADDR(entry_id), mhdp->regs + SOURCE_PIF_WR_ADDR); ++ ++ /* write request */ ++ writel(F_HOST_WR(1), mhdp->regs + SOURCE_PIF_WR_REQ); ++ ++ /* update entry */ ++ val = F_ACTIVE_IDLE_TYPE(1) | F_TYPE_VALID(1) | ++ F_PACKET_TYPE(type) | F_PKT_ALLOC_ADDRESS(entry_id); ++ writel(val, mhdp->regs + SOURCE_PIF_PKT_ALLOC_REG); ++ ++ writel(F_PKT_ALLOC_WR_EN(1), mhdp->regs + SOURCE_PIF_PKT_ALLOC_WR_EN); ++} ++ ++static int cdns_hdmi_get_edid_block(void *data, u8 *edid, ++ u32 block, size_t length) ++{ ++ struct cdns_mhdp8501_device *mhdp = data; ++ u8 msg[2], reg[5], i; ++ int ret; ++ ++ for (i = 0; i < 4; i++) { ++ msg[0] = block / 2; ++ msg[1] = block % 2; ++ ++ ret = cdns_mhdp_mailbox_send_recv_multi(&mhdp->base, ++ MB_MODULE_ID_HDMI_TX, ++ HDMI_TX_EDID, ++ sizeof(msg), msg, ++ HDMI_TX_EDID, ++ sizeof(reg), reg, ++ length, edid); ++ ++ if (ret) ++ continue; ++ ++ if ((reg[3] << 8 | reg[4]) == length) ++ break; ++ } ++ ++ if (ret) ++ dev_err(mhdp->dev, "get block[%d] edid failed: %d\n", block, ret); ++ return ret; ++} ++ ++static int cdns_hdmi_set_hdmi_mode_type(struct cdns_mhdp8501_device *mhdp) ++{ ++ struct drm_connector_state *conn_state = mhdp->curr_conn->state; ++ u32 protocol = mhdp->hdmi.hdmi_type; ++ u32 val; ++ ++ if (protocol == MODE_HDMI_2_0 && ++ conn_state->hdmi.tmds_char_rate >= 340000000) { ++ cdns_mhdp_reg_write(&mhdp->base, HDTX_CLOCK_REG_0, 0); ++ cdns_mhdp_reg_write(&mhdp->base, HDTX_CLOCK_REG_1, 0xFFFFF); ++ } ++ ++ cdns_mhdp_reg_read(&mhdp->base, HDTX_CONTROLLER, &val); ++ ++ /* set HDMI mode and preemble mode data enable */ ++ val |= F_HDMI_MODE(protocol) | F_HDMI2_PREAMBLE_EN(1) | ++ F_HDMI2_CTRL_IL_MODE(1); ++ return cdns_mhdp_reg_write(&mhdp->base, HDTX_CONTROLLER, val); ++} ++ ++static int cdns_hdmi_ctrl_init(struct cdns_mhdp8501_device *mhdp) ++{ ++ u32 val; ++ int ret; ++ ++ /* Set PHY to HDMI data */ ++ ret = cdns_mhdp_reg_write(&mhdp->base, PHY_DATA_SEL, F_SOURCE_PHY_MHDP_SEL(1)); ++ if (ret < 0) ++ return ret; ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, HDTX_HPD, ++ F_HPD_VALID_WIDTH(4) | F_HPD_GLITCH_WIDTH(0)); ++ if (ret < 0) ++ return ret; ++ ++ /* open CARS */ ++ ret = cdns_mhdp_reg_write(&mhdp->base, SOURCE_PHY_CAR, 0xF); ++ if (ret < 0) ++ return ret; ++ ret = cdns_mhdp_reg_write(&mhdp->base, SOURCE_HDTX_CAR, 0xFF); ++ if (ret < 0) ++ return ret; ++ ret = cdns_mhdp_reg_write(&mhdp->base, SOURCE_PKT_CAR, 0xF); ++ if (ret < 0) ++ return ret; ++ ret = cdns_mhdp_reg_write(&mhdp->base, SOURCE_AIF_CAR, 0xF); ++ if (ret < 0) ++ return ret; ++ ret = cdns_mhdp_reg_write(&mhdp->base, SOURCE_CIPHER_CAR, 0xF); ++ if (ret < 0) ++ return ret; ++ ret = cdns_mhdp_reg_write(&mhdp->base, SOURCE_CRYPTO_CAR, 0xF); ++ if (ret < 0) ++ return ret; ++ ret = cdns_mhdp_reg_write(&mhdp->base, SOURCE_CEC_CAR, 3); ++ if (ret < 0) ++ return ret; ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, HDTX_CLOCK_REG_0, 0x7c1f); ++ if (ret < 0) ++ return ret; ++ ret = cdns_mhdp_reg_write(&mhdp->base, HDTX_CLOCK_REG_1, 0x7c1f); ++ if (ret < 0) ++ return ret; ++ ++ /* init HDMI Controller */ ++ val = F_BCH_EN(1) | F_PIC_3D(0xF) | F_CLEAR_AVMUTE(1); ++ ret = cdns_mhdp_reg_write(&mhdp->base, HDTX_CONTROLLER, val); ++ if (ret < 0) ++ return ret; ++ ++ return cdns_hdmi_set_hdmi_mode_type(mhdp); ++} ++ ++static int cdns_hdmi_mode_config(struct cdns_mhdp8501_device *mhdp, ++ struct drm_display_mode *mode, ++ struct drm_connector_hdmi_state *hdmi) ++{ ++ u32 vsync_lines = mode->vsync_end - mode->vsync_start; ++ u32 eof_lines = mode->vsync_start - mode->vdisplay; ++ u32 sof_lines = mode->vtotal - mode->vsync_end; ++ u32 hblank = mode->htotal - mode->hdisplay; ++ u32 hactive = mode->hdisplay; ++ u32 vblank = mode->vtotal - mode->vdisplay; ++ u32 vactive = mode->vdisplay; ++ u32 hfront = mode->hsync_start - mode->hdisplay; ++ u32 hback = mode->htotal - mode->hsync_end; ++ u32 vfront = eof_lines; ++ u32 hsync = hblank - hfront - hback; ++ u32 vsync = vsync_lines; ++ u32 vback = sof_lines; ++ u32 v_h_polarity = ((mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1) + ++ ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : 2); ++ int ret; ++ u32 val; ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, SCHEDULER_H_SIZE, (hactive << 16) + hblank); ++ if (ret < 0) ++ return ret; ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, SCHEDULER_V_SIZE, (vactive << 16) + vblank); ++ if (ret < 0) ++ return ret; ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, HDTX_SIGNAL_FRONT_WIDTH, (vfront << 16) + hfront); ++ if (ret < 0) ++ return ret; ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, HDTX_SIGNAL_SYNC_WIDTH, (vsync << 16) + hsync); ++ if (ret < 0) ++ return ret; ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, HDTX_SIGNAL_BACK_WIDTH, (vback << 16) + hback); ++ if (ret < 0) ++ return ret; ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, HSYNC2VSYNC_POL_CTRL, v_h_polarity); ++ if (ret < 0) ++ return ret; ++ ++ /* Reset Data Enable */ ++ cdns_mhdp_reg_read(&mhdp->base, HDTX_CONTROLLER, &val); ++ val &= ~F_DATA_EN(1); ++ ret = cdns_mhdp_reg_write(&mhdp->base, HDTX_CONTROLLER, val); ++ if (ret < 0) ++ return ret; ++ ++ /* Set bpc */ ++ val &= ~F_VIF_DATA_WIDTH(3); ++ switch (hdmi->output_bpc) { ++ case 10: ++ val |= F_VIF_DATA_WIDTH(1); ++ break; ++ case 12: ++ val |= F_VIF_DATA_WIDTH(2); ++ break; ++ case 16: ++ val |= F_VIF_DATA_WIDTH(3); ++ break; ++ case 8: ++ default: ++ val |= F_VIF_DATA_WIDTH(0); ++ break; ++ } ++ ++ /* select color encoding */ ++ val &= ~F_HDMI_ENCODING(3); ++ switch (hdmi->output_format) { ++ case HDMI_COLORSPACE_YUV444: ++ val |= F_HDMI_ENCODING(2); ++ break; ++ case HDMI_COLORSPACE_YUV422: ++ val |= F_HDMI_ENCODING(1); ++ break; ++ case HDMI_COLORSPACE_YUV420: ++ val |= F_HDMI_ENCODING(3); ++ break; ++ case HDMI_COLORSPACE_RGB: ++ default: ++ val |= F_HDMI_ENCODING(0); ++ break; ++ } ++ ++ ret = cdns_mhdp_reg_write(&mhdp->base, HDTX_CONTROLLER, val); ++ if (ret < 0) ++ return ret; ++ ++ /* set data enable */ ++ val |= F_DATA_EN(1); ++ return cdns_mhdp_reg_write(&mhdp->base, HDTX_CONTROLLER, val); ++} ++ ++static int cdns_hdmi_disable_gcp(struct cdns_mhdp8501_device *mhdp) ++{ ++ u32 val; ++ ++ cdns_mhdp_reg_read(&mhdp->base, HDTX_CONTROLLER, &val); ++ val &= ~F_GCP_EN(1); ++ ++ return cdns_mhdp_reg_write(&mhdp->base, HDTX_CONTROLLER, val); ++} ++ ++static int cdns_hdmi_enable_gcp(struct cdns_mhdp8501_device *mhdp) ++{ ++ u32 val; ++ ++ cdns_mhdp_reg_read(&mhdp->base, HDTX_CONTROLLER, &val); ++ val |= F_GCP_EN(1); ++ ++ return cdns_mhdp_reg_write(&mhdp->base, HDTX_CONTROLLER, val); ++} ++ ++#define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000) ++static void cdns_hdmi_sink_config(struct cdns_mhdp8501_device *mhdp, ++ unsigned long long tmds_char_rate) ++{ ++ struct drm_connector *connector = mhdp->curr_conn; ++ struct drm_display_info *display = &connector->display_info; ++ struct drm_scdc *scdc = &display->hdmi.scdc; ++ bool hdmi_scrambling = false; ++ bool hdmi_high_tmds_clock_ratio = false; ++ ++ /* check sink type (HDMI or DVI) */ ++ if (!display->is_hdmi) { ++ mhdp->hdmi.hdmi_type = MODE_DVI; ++ return; ++ } ++ ++ /* Default work in HDMI1.4 */ ++ mhdp->hdmi.hdmi_type = MODE_HDMI_1_4; ++ ++ /* check sink support SCDC or not */ ++ if (!scdc->supported) { ++ dev_dbg(mhdp->dev, "Sink Not Support SCDC\n"); ++ return; ++ } ++ ++ if (tmds_char_rate > HDMI_14_MAX_TMDS_CLK) { ++ hdmi_scrambling = true; ++ hdmi_high_tmds_clock_ratio = true; ++ mhdp->hdmi.hdmi_type = MODE_HDMI_2_0; ++ } else if (scdc->scrambling.low_rates) { ++ hdmi_scrambling = true; ++ mhdp->hdmi.hdmi_type = MODE_HDMI_2_0; ++ } ++ ++ /* Set TMDS bit clock ratio to 1/40 or 1/10, and enable/disable scrambling */ ++ drm_scdc_set_high_tmds_clock_ratio(connector, hdmi_high_tmds_clock_ratio); ++ drm_scdc_set_scrambling(connector, hdmi_scrambling); ++} ++ ++static int cdns_hdmi_bridge_attach(struct drm_bridge *bridge, ++ enum drm_bridge_attach_flags flags) ++{ ++ struct cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ ++ if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { ++ dev_err(mhdp->dev, "do not support creating a drm_connector\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int reset_pipe(struct drm_crtc *crtc) ++{ ++ struct drm_atomic_state *state; ++ struct drm_crtc_state *crtc_state; ++ struct drm_modeset_acquire_ctx ctx; ++ int ret; ++ ++ state = drm_atomic_state_alloc(crtc->dev); ++ if (!state) ++ return -ENOMEM; ++ ++ drm_modeset_acquire_init(&ctx, 0); ++ ++ state->acquire_ctx = &ctx; ++ ++ crtc_state = drm_atomic_get_crtc_state(state, crtc); ++ if (IS_ERR(crtc_state)) { ++ ret = PTR_ERR(crtc_state); ++ goto out; ++ } ++ ++ crtc_state->connectors_changed = true; ++ ++ ret = drm_atomic_commit(state); ++out: ++ drm_atomic_state_put(state); ++ drm_modeset_drop_locks(&ctx); ++ drm_modeset_acquire_fini(&ctx); ++ ++ return ret; ++} ++ ++void cdns_hdmi_handle_hotplug(struct cdns_mhdp8501_device *mhdp) ++{ ++ struct drm_connector *connector = mhdp->curr_conn; ++ const struct drm_edid *drm_edid; ++ struct drm_connector_state *conn_state; ++ struct drm_crtc_state *crtc_state; ++ struct drm_crtc *crtc; ++ ++ if (!connector) ++ return; ++ ++ /* ++ * EDID data needs updating after each cable plugin ++ * due to potential display monitor changes ++ */ ++ drm_edid = drm_edid_read_custom(connector, cdns_hdmi_get_edid_block, mhdp); ++ drm_edid_connector_update(connector, drm_edid); ++ ++ if (!drm_edid) ++ return; ++ ++ drm_edid_free(drm_edid); ++ ++ conn_state = connector->state; ++ crtc = conn_state->crtc; ++ if (!crtc) ++ return; ++ ++ crtc_state = crtc->state; ++ if (!crtc_state->active) ++ return; ++ ++ /* ++ * HDMI 2.0 says that one should not send scrambled data ++ * prior to configuring the sink scrambling, and that ++ * TMDS clock/data transmission should be suspended when ++ * changing the TMDS clock rate in the sink. So let's ++ * just do a full modeset here, even though some sinks ++ * would be perfectly happy if were to just reconfigure ++ * the SCDC settings on the fly. ++ */ ++ reset_pipe(crtc); ++} ++ ++static int cdns_hdmi_i2c_write(struct cdns_mhdp8501_device *mhdp, ++ struct i2c_msg *msgs) ++{ ++ u8 msg[5], reg[5]; ++ int ret; ++ ++ msg[0] = msgs->addr; ++ msg[1] = msgs->buf[0]; ++ msg[2] = 0; ++ msg[3] = 1; ++ msg[4] = msgs->buf[1]; ++ ++ ret = cdns_mhdp_mailbox_send_recv(&mhdp->base, ++ MB_MODULE_ID_HDMI_TX, HDMI_TX_WRITE, ++ sizeof(msg), msg, sizeof(reg), reg); ++ if (ret) { ++ dev_err(mhdp->dev, "I2C write failed: %d\n", ret); ++ return ret; ++ } ++ ++ if (reg[0] != 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int cdns_hdmi_i2c_read(struct cdns_mhdp8501_device *mhdp, ++ struct i2c_msg *msgs, int num) ++{ ++ u8 msg[4], reg[5]; ++ u8 addr, offset, *buf, len; ++ int ret, i; ++ ++ for (i = 0; i < num; i++) { ++ if (msgs[i].flags & I2C_M_RD) { ++ addr = msgs[i].addr; ++ buf = msgs[i].buf; ++ len = msgs[i].len; ++ } else { ++ offset = msgs[i].buf[0]; ++ } ++ } ++ ++ msg[0] = addr; ++ msg[1] = offset; ++ put_unaligned_be16(len, msg + 2); ++ ++ ret = cdns_mhdp_mailbox_send_recv_multi(&mhdp->base, ++ MB_MODULE_ID_HDMI_TX, HDMI_TX_READ, ++ sizeof(msg), msg, ++ HDMI_TX_READ, ++ sizeof(reg), reg, ++ len, buf); ++ if (ret) { ++ dev_err(mhdp->dev, "I2c Read failed: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++#define SCDC_I2C_SLAVE_ADDRESS 0x54 ++static int cdns_hdmi_i2c_xfer(struct i2c_adapter *adap, ++ struct i2c_msg *msgs, int num) ++{ ++ struct cdns_mhdp8501_device *mhdp = i2c_get_adapdata(adap); ++ struct cdns_hdmi_i2c *i2c = mhdp->hdmi.i2c; ++ int i, ret = 0; ++ ++ /* ++ * MHDP FW provides mailbox APIs for SCDC registers access, but lacks direct I2C APIs. ++ * While individual I2C registers can be read/written using HDMI general register APIs, ++ * block reads (e.g., EDID) are not supported, making it a limited I2C interface. ++ */ ++ for (i = 0; i < num; i++) { ++ if (msgs[i].addr != SCDC_I2C_SLAVE_ADDRESS) { ++ dev_err(mhdp->dev, "ADDR=%0x is not supported\n", msgs[i].addr); ++ return -EINVAL; ++ } ++ } ++ ++ mutex_lock(&i2c->lock); ++ ++ if (num == 1) ++ ret = cdns_hdmi_i2c_write(mhdp, msgs); ++ else ++ ret = cdns_hdmi_i2c_read(mhdp, msgs, num); ++ ++ if (!ret) ++ ret = num; ++ ++ mutex_unlock(&i2c->lock); ++ ++ return ret; ++} ++ ++static u32 cdns_hdmi_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm cdns_hdmi_algorithm = { ++ .master_xfer = cdns_hdmi_i2c_xfer, ++ .functionality = cdns_hdmi_i2c_func, ++}; ++ ++struct i2c_adapter *cdns_hdmi_i2c_adapter(struct cdns_mhdp8501_device *mhdp) ++{ ++ struct i2c_adapter *adap; ++ struct cdns_hdmi_i2c *i2c; ++ int ret; ++ ++ i2c = devm_kzalloc(mhdp->dev, sizeof(*i2c), GFP_KERNEL); ++ if (!i2c) ++ return ERR_PTR(-ENOMEM); ++ ++ mutex_init(&i2c->lock); ++ ++ adap = &i2c->adap; ++ adap->owner = THIS_MODULE; ++ adap->dev.parent = mhdp->dev; ++ adap->algo = &cdns_hdmi_algorithm; ++ strscpy(adap->name, "MHDP HDMI", sizeof(adap->name)); ++ i2c_set_adapdata(adap, mhdp); ++ ++ ret = i2c_add_adapter(adap); ++ if (ret) { ++ dev_warn(mhdp->dev, "cannot add %s I2C adapter\n", adap->name); ++ devm_kfree(mhdp->dev, i2c); ++ return ERR_PTR(ret); ++ } ++ ++ mhdp->hdmi.i2c = i2c; ++ ++ return adap; ++} ++ ++static enum drm_mode_status ++cdns_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge, ++ const struct drm_display_mode *mode, ++ unsigned long long tmds_rate) ++{ ++ struct cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ union phy_configure_opts phy_cfg; ++ int ret; ++ ++ phy_cfg.hdmi.tmds_char_rate = tmds_rate; ++ ++ ret = phy_validate(mhdp->phy, PHY_MODE_HDMI, 0, &phy_cfg); ++ if (ret < 0) ++ return MODE_CLOCK_RANGE; ++ ++ return MODE_OK; ++} ++ ++static const struct drm_edid ++*cdns_hdmi_bridge_edid_read(struct drm_bridge *bridge, ++ struct drm_connector *connector) ++{ ++ struct cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ ++ return drm_edid_read_custom(connector, cdns_hdmi_get_edid_block, mhdp); ++} ++ ++static void cdns_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, ++ struct drm_atomic_state *state) ++{ ++ struct cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ ++ mhdp->curr_conn = NULL; ++ ++ phy_power_off(mhdp->phy); ++} ++ ++static void cdns_hdmi_bridge_atomic_enable(struct drm_bridge *bridge, ++ struct drm_atomic_state *state) ++{ ++ struct cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ struct drm_connector *connector; ++ struct drm_crtc_state *crtc_state; ++ struct drm_connector_state *conn_state; ++ struct drm_connector_hdmi_state *hdmi; ++ union phy_configure_opts phy_cfg; ++ int ret; ++ ++ connector = drm_atomic_get_new_connector_for_encoder(state, ++ bridge->encoder); ++ if (WARN_ON(!connector)) ++ return; ++ ++ mhdp->curr_conn = connector; ++ ++ conn_state = drm_atomic_get_new_connector_state(state, connector); ++ if (WARN_ON(!conn_state)) ++ return; ++ ++ crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); ++ if (WARN_ON(!crtc_state)) ++ return; ++ ++ drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); ++ ++ /* Line swapping */ ++ cdns_mhdp_reg_write(&mhdp->base, LANES_CONFIG, 0x00400000 | mhdp->lane_mapping); ++ ++ hdmi = &conn_state->hdmi; ++ if (WARN_ON(!hdmi)) ++ return; ++ ++ phy_cfg.hdmi.tmds_char_rate = hdmi->tmds_char_rate; ++ ret = phy_configure(mhdp->phy, &phy_cfg); ++ if (ret) { ++ dev_err(mhdp->dev, "%s: phy_configure() failed: %d\n", ++ __func__, ret); ++ return; ++ } ++ ++ phy_power_on(mhdp->phy); ++ ++ cdns_hdmi_sink_config(mhdp, hdmi->tmds_char_rate); ++ ++ ret = cdns_hdmi_ctrl_init(mhdp); ++ if (ret < 0) { ++ dev_err(mhdp->dev, "hdmi ctrl init failed = %d\n", ret); ++ return; ++ } ++ ++ /* Config GCP */ ++ if (hdmi->output_bpc == 8) ++ cdns_hdmi_disable_gcp(mhdp); ++ else ++ cdns_hdmi_enable_gcp(mhdp); ++ ++ ret = cdns_hdmi_mode_config(mhdp, &crtc_state->adjusted_mode, hdmi); ++ if (ret < 0) { ++ dev_err(mhdp->dev, "CDN_API_HDMITX_SetVic_blocking ret = %d\n", ret); ++ return; ++ } ++} ++ ++static int cdns_hdmi_bridge_clear_infoframe(struct drm_bridge *bridge, ++ enum hdmi_infoframe_type type) ++{ ++ struct cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ ++ switch (type) { ++ case HDMI_INFOFRAME_TYPE_AVI: ++ cdns_hdmi_clear_infoframe(mhdp, 0, HDMI_INFOFRAME_TYPE_AVI); ++ break; ++ case HDMI_INFOFRAME_TYPE_SPD: ++ cdns_hdmi_clear_infoframe(mhdp, 1, HDMI_INFOFRAME_TYPE_SPD); ++ break; ++ case HDMI_INFOFRAME_TYPE_VENDOR: ++ cdns_hdmi_clear_infoframe(mhdp, 2, HDMI_INFOFRAME_TYPE_VENDOR); ++ break; ++ default: ++ dev_dbg(mhdp->dev, "Unsupported infoframe type %x\n", type); ++ } ++ ++ return 0; ++} ++ ++static int cdns_hdmi_bridge_write_infoframe(struct drm_bridge *bridge, ++ enum hdmi_infoframe_type type, ++ const u8 *buffer, size_t len) ++{ ++ struct cdns_mhdp8501_device *mhdp = bridge->driver_private; ++ ++ switch (type) { ++ case HDMI_INFOFRAME_TYPE_AVI: ++ cdns_hdmi_config_infoframe(mhdp, 0, len, buffer, HDMI_INFOFRAME_TYPE_AVI); ++ break; ++ case HDMI_INFOFRAME_TYPE_SPD: ++ cdns_hdmi_config_infoframe(mhdp, 1, len, buffer, HDMI_INFOFRAME_TYPE_SPD); ++ break; ++ case HDMI_INFOFRAME_TYPE_VENDOR: ++ cdns_hdmi_config_infoframe(mhdp, 2, len, buffer, HDMI_INFOFRAME_TYPE_VENDOR); ++ break; ++ default: ++ dev_dbg(mhdp->dev, "Unsupported infoframe type %x\n", type); ++ } ++ ++ return 0; ++} ++ ++static int cdns_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) ++{ ++ return drm_atomic_helper_connector_hdmi_check(conn_state->connector, conn_state->state); ++} ++ ++const struct drm_bridge_funcs cdns_hdmi_bridge_funcs = { ++ .attach = cdns_hdmi_bridge_attach, ++ .detect = cdns_mhdp8501_detect, ++ .edid_read = cdns_hdmi_bridge_edid_read, ++ .mode_valid = cdns_mhdp8501_mode_valid, ++ .atomic_enable = cdns_hdmi_bridge_atomic_enable, ++ .atomic_disable = cdns_hdmi_bridge_atomic_disable, ++ .atomic_check = cdns_hdmi_bridge_atomic_check, ++ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, ++ .atomic_reset = drm_atomic_helper_bridge_reset, ++ .hdmi_clear_infoframe = cdns_hdmi_bridge_clear_infoframe, ++ .hdmi_write_infoframe = cdns_hdmi_bridge_write_infoframe, ++ .hdmi_tmds_char_rate_valid = cdns_hdmi_tmds_char_rate_valid, ++}; + +From patchwork Tue Dec 17 06:51:48 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v20,6/9] dt-bindings: phy: Add Freescale iMX8MQ DP and HDMI PHY +From: Sandor Yu +X-Patchwork-Id: 629293 +Message-Id: + <1f01892a4e462d451a21ddcb4b114283d998cd1b.1734340233.git.Sandor.yu@nxp.com> +To: dmitry.baryshkov@linaro.org, andrzej.hajda@intel.com, + neil.armstrong@linaro.org, Laurent.pinchart@ideasonboard.com, + jonas@kwiboo.se, jernej.skrabec@gmail.com, airlied@gmail.com, + daniel@ffwll.ch, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, + vkoul@kernel.org, dri-devel@lists.freedesktop.org, + devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, + mripard@kernel.org +Cc: kernel@pengutronix.de, linux-imx@nxp.com, Sandor.yu@nxp.com, + oliver.brown@nxp.com, alexander.stein@ew.tq-group.com, sam@ravnborg.org, + Rob Herring +Date: Tue, 17 Dec 2024 14:51:48 +0800 + +Add bindings for Freescale iMX8MQ DP and HDMI PHY. + +Signed-off-by: Sandor Yu +Reviewed-by: Rob Herring +--- +v9->v20: + *No change. + + .../bindings/phy/fsl,imx8mq-dp-hdmi-phy.yaml | 51 +++++++++++++++++++ + 1 file changed, 51 insertions(+) + create mode 100644 Documentation/devicetree/bindings/phy/fsl,imx8mq-dp-hdmi-phy.yaml + +diff --git a/Documentation/devicetree/bindings/phy/fsl,imx8mq-dp-hdmi-phy.yaml b/Documentation/devicetree/bindings/phy/fsl,imx8mq-dp-hdmi-phy.yaml +new file mode 100644 +index 0000000000000..c17a645e71bad +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/fsl,imx8mq-dp-hdmi-phy.yaml +@@ -0,0 +1,51 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/phy/fsl,imx8mq-dp-hdmi-phy.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Cadence HDP-TX DP/HDMI PHY for Freescale i.MX8MQ SoC ++ ++maintainers: ++ - Sandor Yu ++ ++properties: ++ compatible: ++ const: fsl,imx8mq-hdptx-phy ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: PHY reference clock. ++ - description: APB clock. ++ ++ clock-names: ++ items: ++ - const: ref ++ - const: apb ++ ++ "#phy-cells": ++ const: 0 ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - clock-names ++ - "#phy-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ dp_phy: phy@32c00000 { ++ compatible = "fsl,imx8mq-hdptx-phy"; ++ reg = <0x32c00000 0x100000>; ++ #phy-cells = <0>; ++ clocks = <&hdmi_phy_27m>, <&clk IMX8MQ_CLK_DISP_APB_ROOT>; ++ clock-names = "ref", "apb"; ++ }; + +From patchwork Tue Dec 17 06:51:49 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v20,7/9] phy: freescale: Add DisplayPort/HDMI Combo-PHY driver for + i.MX8MQ +From: Sandor Yu +X-Patchwork-Id: 629294 +Message-Id: + +To: dmitry.baryshkov@linaro.org, andrzej.hajda@intel.com, + neil.armstrong@linaro.org, Laurent.pinchart@ideasonboard.com, + jonas@kwiboo.se, jernej.skrabec@gmail.com, airlied@gmail.com, + daniel@ffwll.ch, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, + vkoul@kernel.org, dri-devel@lists.freedesktop.org, + devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, + mripard@kernel.org +Cc: kernel@pengutronix.de, linux-imx@nxp.com, Sandor.yu@nxp.com, + oliver.brown@nxp.com, alexander.stein@ew.tq-group.com, sam@ravnborg.org +Date: Tue, 17 Dec 2024 14:51:49 +0800 + +Add Cadence HDP-TX DisplayPort and HDMI PHY driver for i.MX8MQ. + +Cadence HDP-TX PHY could be put in either DP mode or +HDMI mode base on the configuration chosen. +DisplayPort or HDMI PHY mode is configured in the driver. + +Signed-off-by: Sandor Yu +Signed-off-by: Alexander Stein +--- +v19->v20: +- implify DP configuration handling by directly copying + the configuration options to the driver's internal structure. +- return the error code directly instead of logging an error message in `hdptx_clk_enable` +- Remove redundant ref_clk_rate check + +v18->v19: +- Simplify the PLL tables by removing unused and constant data +- Remove PHY power management, controller driver will handle them. +- Remove enum dp_link_rate +- Introduce read_pll_timeout. +- Update clock management as devm_clk_get_enabled() introduced. +- Remove cdns_hdptx_phy_init() and cdns_hdptx_phy_remove(). + +v17->v18: +- fix build error as code rebase to latest kernel version. + + drivers/phy/freescale/Kconfig | 10 + + drivers/phy/freescale/Makefile | 1 + + drivers/phy/freescale/phy-fsl-imx8mq-hdptx.c | 1231 ++++++++++++++++++ + 3 files changed, 1242 insertions(+) + create mode 100644 drivers/phy/freescale/phy-fsl-imx8mq-hdptx.c + +diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig +index dcd9acff6d01a..2b1210367b31c 100644 +--- a/drivers/phy/freescale/Kconfig ++++ b/drivers/phy/freescale/Kconfig +@@ -35,6 +35,16 @@ config PHY_FSL_IMX8M_PCIE + Enable this to add support for the PCIE PHY as found on + i.MX8M family of SOCs. + ++config PHY_FSL_IMX8MQ_HDPTX ++ tristate "Freescale i.MX8MQ DP/HDMI PHY support" ++ depends on OF && HAS_IOMEM ++ depends on COMMON_CLK ++ select GENERIC_PHY ++ select CDNS_MHDP_HELPER ++ help ++ Enable this to support the Cadence HDPTX DP/HDMI PHY driver ++ on i.MX8MQ SOC. ++ + config PHY_FSL_IMX8QM_HSIO + tristate "Freescale i.MX8QM HSIO PHY" + depends on OF && HAS_IOMEM +diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile +index 658eac7d0a622..a946b87905498 100644 +--- a/drivers/phy/freescale/Makefile ++++ b/drivers/phy/freescale/Makefile +@@ -1,4 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0-only ++obj-$(CONFIG_PHY_FSL_IMX8MQ_HDPTX) += phy-fsl-imx8mq-hdptx.o + obj-$(CONFIG_PHY_FSL_IMX8MQ_USB) += phy-fsl-imx8mq-usb.o + obj-$(CONFIG_PHY_MIXEL_LVDS_PHY) += phy-fsl-imx8qm-lvds-phy.o + obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY) += phy-fsl-imx8-mipi-dphy.o +diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-hdptx.c b/drivers/phy/freescale/phy-fsl-imx8mq-hdptx.c +new file mode 100644 +index 0000000000000..230b7148639b2 +--- /dev/null ++++ b/drivers/phy/freescale/phy-fsl-imx8mq-hdptx.c +@@ -0,0 +1,1231 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Cadence DP/HDMI PHY driver ++ * ++ * Copyright (C) 2022-2024 NXP Semiconductor, Inc. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define ADDR_PHY_AFE 0x80000 ++ ++/* PHY registers */ ++#define CMN_SSM_BIAS_TMR 0x0022 ++#define CMN_PLLSM0_PLLEN_TMR 0x0029 ++#define CMN_PLLSM0_PLLPRE_TMR 0x002a ++#define CMN_PLLSM0_PLLVREF_TMR 0x002b ++#define CMN_PLLSM0_PLLLOCK_TMR 0x002c ++#define CMN_PLLSM0_USER_DEF_CTRL 0x002f ++#define CMN_PSM_CLK_CTRL 0x0061 ++#define CMN_CDIAG_REFCLK_CTRL 0x0062 ++#define CMN_PLL0_VCOCAL_START 0x0081 ++#define CMN_PLL0_VCOCAL_INIT_TMR 0x0084 ++#define CMN_PLL0_VCOCAL_ITER_TMR 0x0085 ++#define CMN_PLL0_INTDIV 0x0094 ++#define CMN_PLL0_FRACDIV 0x0095 ++#define CMN_PLL0_HIGH_THR 0x0096 ++#define CMN_PLL0_DSM_DIAG 0x0097 ++#define CMN_PLL0_SS_CTRL2 0x0099 ++#define CMN_ICAL_INIT_TMR 0x00c4 ++#define CMN_ICAL_ITER_TMR 0x00c5 ++#define CMN_RXCAL_INIT_TMR 0x00d4 ++#define CMN_RXCAL_ITER_TMR 0x00d5 ++#define CMN_TXPUCAL_CTRL 0x00e0 ++#define CMN_TXPUCAL_INIT_TMR 0x00e4 ++#define CMN_TXPUCAL_ITER_TMR 0x00e5 ++#define CMN_TXPDCAL_CTRL 0x00f0 ++#define CMN_TXPDCAL_INIT_TMR 0x00f4 ++#define CMN_TXPDCAL_ITER_TMR 0x00f5 ++#define CMN_ICAL_ADJ_INIT_TMR 0x0102 ++#define CMN_ICAL_ADJ_ITER_TMR 0x0103 ++#define CMN_RX_ADJ_INIT_TMR 0x0106 ++#define CMN_RX_ADJ_ITER_TMR 0x0107 ++#define CMN_TXPU_ADJ_CTRL 0x0108 ++#define CMN_TXPU_ADJ_INIT_TMR 0x010a ++#define CMN_TXPU_ADJ_ITER_TMR 0x010b ++#define CMN_TXPD_ADJ_CTRL 0x010c ++#define CMN_TXPD_ADJ_INIT_TMR 0x010e ++#define CMN_TXPD_ADJ_ITER_TMR 0x010f ++#define CMN_DIAG_PLL0_FBH_OVRD 0x01c0 ++#define CMN_DIAG_PLL0_FBL_OVRD 0x01c1 ++#define CMN_DIAG_PLL0_OVRD 0x01c2 ++#define CMN_DIAG_PLL0_TEST_MODE 0x01c4 ++#define CMN_DIAG_PLL0_V2I_TUNE 0x01c5 ++#define CMN_DIAG_PLL0_CP_TUNE 0x01c6 ++#define CMN_DIAG_PLL0_LF_PROG 0x01c7 ++#define CMN_DIAG_PLL0_PTATIS_TUNE1 0x01c8 ++#define CMN_DIAG_PLL0_PTATIS_TUNE2 0x01c9 ++#define CMN_DIAG_PLL0_INCLK_CTRL 0x01ca ++#define CMN_DIAG_PLL0_PXL_DIVH 0x01cb ++#define CMN_DIAG_PLL0_PXL_DIVL 0x01cc ++#define CMN_DIAG_HSCLK_SEL 0x01e0 ++#define CMN_DIAG_PER_CAL_ADJ 0x01ec ++#define CMN_DIAG_CAL_CTRL 0x01ed ++#define CMN_DIAG_ACYA 0x01ff ++#define XCVR_PSM_RCTRL 0x4001 ++#define XCVR_PSM_CAL_TMR 0x4002 ++#define XCVR_PSM_A0IN_TMR 0x4003 ++#define TX_TXCC_CAL_SCLR_MULT_0 0x4047 ++#define TX_TXCC_CPOST_MULT_00_0 0x404c ++#define XCVR_DIAG_PLLDRC_CTRL 0x40e0 ++#define XCVR_DIAG_HSCLK_SEL 0x40e1 ++#define XCVR_DIAG_BIDI_CTRL 0x40e8 ++#define XCVR_DIAG_LANE_FCM_EN_MGN_TMR 0x40f2 ++#define TX_PSC_A0 0x4100 ++#define TX_PSC_A1 0x4101 ++#define TX_PSC_A2 0x4102 ++#define TX_PSC_A3 0x4103 ++#define TX_RCVDET_EN_TMR 0x4122 ++#define TX_RCVDET_ST_TMR 0x4123 ++#define TX_DIAG_TX_CTRL 0x41e0 ++#define TX_DIAG_TX_DRV 0x41e1 ++#define TX_DIAG_BGREF_PREDRV_DELAY 0x41e7 ++#define TX_DIAG_ACYA_0 0x41ff ++#define TX_DIAG_ACYA_1 0x43ff ++#define TX_DIAG_ACYA_2 0x45ff ++#define TX_DIAG_ACYA_3 0x47ff ++#define TX_ANA_CTRL_REG_1 0x5020 ++#define TX_ANA_CTRL_REG_2 0x5021 ++#define TX_DIG_CTRL_REG_1 0x5023 ++#define TX_DIG_CTRL_REG_2 0x5024 ++#define TXDA_CYA_AUXDA_CYA 0x5025 ++#define TX_ANA_CTRL_REG_3 0x5026 ++#define TX_ANA_CTRL_REG_4 0x5027 ++#define TX_ANA_CTRL_REG_5 0x5029 ++#define RX_PSC_A0 0x8000 ++#define RX_PSC_CAL 0x8006 ++#define PHY_HDP_MODE_CTRL 0xc008 ++#define PHY_HDP_CLK_CTL 0xc009 ++#define PHY_ISO_CMN_CTRL 0xc010 ++#define PHY_PMA_CMN_CTRL1 0xc800 ++#define PHY_PMA_ISO_CMN_CTRL 0xc810 ++#define PHY_PMA_ISO_PLL_CTRL1 0xc812 ++#define PHY_PMA_ISOLATION_CTRL 0xc81f ++ ++/* PHY_HDP_CLK_CTL */ ++#define PLL_DATA_RATE_CLK_DIV_MASK GENMASK(15, 8) ++#define PLL_DATA_RATE_CLK_DIV_HBR 0x24 ++#define PLL_DATA_RATE_CLK_DIV_HBR2 0x12 ++#define PLL_CLK_EN_ACK BIT(3) ++#define PLL_CLK_EN BIT(2) ++#define PLL_READY BIT(1) ++#define PLL_EN BIT(0) ++ ++/* PHY_PMA_CMN_CTRL1 */ ++#define CMA_REF_CLK_DIG_DIV_MASK GENMASK(13, 12) ++#define CMA_REF_CLK_SEL_MASK GENMASK(6, 4) ++#define CMA_REF_CLK_RCV_EN_MASK BIT(3) ++#define CMA_REF_CLK_RCV_EN 1 ++#define CMN_READY BIT(0) ++ ++/* PHY_PMA_ISO_PLL_CTRL1 */ ++#define CMN_PLL0_CLK_DATART_DIV_MASK GENMASK(7, 0) ++ ++/* TX_DIAG_TX_DRV */ ++#define TX_DRIVER_PROG_BOOST_ENABLE BIT(10) ++#define TX_DRIVER_PROG_BOOST_LEVEL_MASK GENMASK(9, 8) ++#define TX_DRIVER_LDO_BG_DEPENDENT_REF_ENABLE BIT(7) ++#define TX_DRIVER_LDO_BANDGAP_REF_ENABLE BIT(6) ++ ++/* TX_TXCC_CAL_SCLR_MULT_0 */ ++#define SCALED_RESISTOR_CALIBRATION_CODE_ADD BIT(8) ++#define RESISTOR_CAL_MULT_VAL_32_128 BIT(5) ++ ++/* CMN_CDIAG_REFCLK_CTRL */ ++#define DIG_REF_CLK_DIV_SCALER_MASK GENMASK(14, 12) ++#define REFCLK_TERMINATION_EN_OVERRIDE_EN BIT(7) ++#define REFCLK_TERMINATION_EN_OVERRIDE BIT(6) ++ ++/* CMN_DIAG_HSCLK_SEL */ ++#define HSCLK1_SEL_MASK GENMASK(5, 4) ++#define HSCLK0_SEL_MASK GENMASK(1, 0) ++#define HSCLK_PLL0_DIV2 1 ++ ++/* XCVR_DIAG_HSCLK_SEL */ ++#define HSCLK_SEL_MODE3_MASK GENMASK(13, 12) ++#define HSCLK_SEL_MODE3_HSCLK1 1 ++ ++/* CMN_PLL0_VCOCAL_START */ ++#define VCO_CALIB_CODE_START_POINT_VAL_MASK GENMASK(8, 0) ++ ++/* CMN_DIAG_PLL0_FBH_OVRD */ ++#define PLL_FEEDBACK_DIV_HI_OVERRIDE_EN BIT(15) ++ ++/* CMN_DIAG_PLL0_FBL_OVRD */ ++#define PLL_FEEDBACK_DIV_LO_OVERRIDE_EN BIT(15) ++ ++/* CMN_DIAG_PLL0_PXL_DIVH */ ++#define PLL_PCLK_DIV_EN BIT(15) ++ ++/* XCVR_DIAG_PLLDRC_CTRL */ ++#define DPLL_CLK_SEL_MODE3 BIT(14) ++#define DPLL_DATA_RATE_DIV_MODE3_MASK GENMASK(13, 12) ++ ++/* TX_DIAG_TX_CTRL */ ++#define TX_IF_SUBRATE_MODE3_MASK GENMASK(7, 6) ++ ++/* PHY_HDP_MODE_CTRL */ ++#define POWER_STATE_A3_ACK BIT(7) ++#define POWER_STATE_A2_ACK BIT(6) ++#define POWER_STATE_A1_ACK BIT(5) ++#define POWER_STATE_A0_ACK BIT(4) ++#define POWER_STATE_A3 BIT(3) ++#define POWER_STATE_A2 BIT(2) ++#define POWER_STATE_A1 BIT(1) ++#define POWER_STATE_A0 BIT(0) ++ ++/* PHY_PMA_ISO_CMN_CTRL */ ++#define CMN_MACRO_PWR_EN_ACK BIT(5) ++ ++#define KEEP_ALIVE 0x18 ++ ++/* FW check alive timeout */ ++#define CDNS_KEEP_ALIVE_TIMEOUT 2000 ++#define CDNS_KEEP_ALIVE_MASK GENMASK(7, 0) ++ ++#define REF_CLK_27MHZ 27000000 ++ ++#define LINK_RATE_2_7 270000 ++#define MAX_LINK_RATE 540000 ++ ++#define CMN_REF_CLK_DIG_DIV 1 ++#define REF_CLK_DIVIDER_SCALER 1 ++ ++/* HDMI TX clock control settings */ ++struct hdptx_hdmi_ctrl { ++ u32 pixel_clk_freq; ++ u32 feedback_factor; ++ u32 cmnda_pll0_ip_div; ++ u32 pll_fb_div_total; ++ u32 cmnda_pll0_fb_div_low; ++ u32 cmnda_pll0_fb_div_high; ++ u32 cmnda_pll0_pxdiv_low; ++ u32 cmnda_pll0_pxdiv_high; ++ u32 vco_ring_select; ++ u32 cmnda_hs_clk_0_sel; ++ u32 cmnda_hs_clk_1_sel; ++ u32 hsclk_div_tx_sub_rate; ++ u32 cmnda_pll0_hs_sym_div_sel; ++}; ++ ++struct cdns_hdptx_phy { ++ struct cdns_mhdp_base base; ++ ++ void __iomem *regs; /* DPTX registers base */ ++ struct device *dev; ++ struct phy *phy; ++ struct clk *ref_clk, *apb_clk; ++ u32 ref_clk_rate; ++ union { ++ struct phy_configure_opts_hdmi hdmi; ++ struct phy_configure_opts_dp dp; ++ }; ++}; ++ ++/* HDMI TX clock control settings, pixel clock is output */ ++static const struct hdptx_hdmi_ctrl pixel_clk_output_ctrl_table[] = { ++ /* clk fbak ipd totl div_l div_h pd_l pd_h v h1 h2 sub sym*/ ++ { 27000, 1000, 3, 240, 0x0bc, 0x30, 0x26, 0x26, 0, 2, 2, 4, 3 }, ++ { 27000, 1250, 3, 300, 0x0ec, 0x3c, 0x30, 0x30, 0, 2, 2, 4, 3 }, ++ { 27000, 1500, 3, 360, 0x11c, 0x48, 0x3a, 0x3a, 0, 2, 2, 4, 3 }, ++ { 27000, 2000, 3, 240, 0x0bc, 0x30, 0x26, 0x26, 0, 2, 2, 4, 2 }, ++ { 54000, 1000, 3, 480, 0x17c, 0x60, 0x26, 0x26, 1, 2, 2, 4, 3 }, ++ { 54000, 1250, 4, 400, 0x13c, 0x50, 0x17, 0x17, 0, 1, 1, 4, 2 }, ++ { 54000, 1500, 4, 480, 0x17c, 0x60, 0x1c, 0x1c, 0, 2, 2, 2, 2 }, ++ { 54000, 2000, 3, 240, 0x0bc, 0x30, 0x12, 0x12, 0, 2, 2, 1, 1 }, ++ { 74250, 1000, 3, 660, 0x20c, 0x84, 0x26, 0x26, 1, 2, 2, 4, 3 }, ++ { 74250, 1250, 4, 550, 0x1b4, 0x6e, 0x17, 0x17, 1, 1, 1, 4, 2 }, ++ { 74250, 1500, 4, 660, 0x20c, 0x84, 0x1c, 0x1c, 1, 2, 2, 2, 2 }, ++ { 74250, 2000, 3, 330, 0x104, 0x42, 0x12, 0x12, 0, 2, 2, 1, 1 }, ++ { 99000, 1000, 3, 440, 0x15c, 0x58, 0x12, 0x12, 1, 2, 2, 2, 2 }, ++ { 99000, 1250, 3, 275, 0x0d8, 0x37, 0x0b, 0x0a, 0, 1, 1, 2, 1 }, ++ { 99000, 1500, 3, 330, 0x104, 0x42, 0x0d, 0x0d, 0, 2, 2, 1, 1 }, ++ { 99000, 2000, 3, 440, 0x15c, 0x58, 0x12, 0x12, 1, 2, 2, 1, 1 }, ++ { 148500, 1000, 3, 660, 0x20c, 0x84, 0x12, 0x12, 1, 2, 2, 2, 2 }, ++ { 148500, 1250, 4, 550, 0x1b4, 0x6e, 0x0b, 0x0a, 1, 1, 1, 2, 1 }, ++ { 148500, 1500, 3, 495, 0x188, 0x63, 0x0d, 0x0d, 1, 1, 1, 2, 1 }, ++ { 148500, 2000, 3, 660, 0x20c, 0x84, 0x12, 0x12, 1, 2, 2, 1, 1 }, ++ { 198000, 1000, 3, 220, 0x0ac, 0x2c, 0x03, 0x03, 0, 1, 1, 1, 0 }, ++ { 198000, 1250, 3, 550, 0x1b4, 0x6e, 0x0b, 0x0a, 1, 1, 1, 2, 1 }, ++ { 198000, 1500, 3, 330, 0x104, 0x42, 0x06, 0x05, 0, 1, 1, 1, 0 }, ++ { 198000, 2000, 3, 440, 0x15c, 0x58, 0x08, 0x08, 1, 1, 1, 1, 0 }, ++ { 297000, 1000, 3, 330, 0x104, 0x42, 0x03, 0x03, 0, 1, 1, 1, 0 }, ++ { 297000, 1500, 3, 495, 0x188, 0x63, 0x06, 0x05, 1, 1, 1, 1, 0 }, ++ { 297000, 2000, 3, 660, 0x20c, 0x84, 0x08, 0x08, 1, 1, 1, 1, 0 }, ++ { 594000, 1000, 3, 660, 0x20c, 0x84, 0x03, 0x03, 1, 1, 1, 1, 0 }, ++ { 594000, 750, 3, 495, 0x188, 0x63, 0x03, 0x03, 1, 1, 1, 1, 0 }, ++ { 594000, 625, 4, 550, 0x1b4, 0x6e, 0x03, 0x03, 1, 1, 1, 1, 0 }, ++ { 594000, 500, 3, 660, 0x20c, 0x84, 0x03, 0x03, 1, 1, 1, 2, 1 }, ++}; ++ ++/* HDMI TX PLL tuning settings */ ++struct hdptx_hdmi_pll_tuning { ++ u32 vco_freq; ++ u32 volt_to_current_coarse; ++ u32 volt_to_current; ++ u32 ndac_ctrl; ++ u32 pmos_ctrl; ++ u32 ptat_ndac_ctrl; ++ u32 feedback_div_total; ++ u32 charge_pump_gain; ++ u32 vco_cal_code; ++}; ++ ++/* HDMI TX PLL tuning settings, pixel clock is output */ ++static const struct hdptx_hdmi_pll_tuning pixel_clk_output_pll_table[] = { ++ /*VCO_f coar cu nd pm ptat fd_d gain cal */ ++ { 1980000, 4, 3, 0, 9, 0x9, 220, 0x42, 183 }, ++ { 2160000, 4, 3, 0, 9, 0x9, 240, 0x42, 208 }, ++ { 2475000, 5, 3, 1, 0, 0x7, 275, 0x42, 209 }, ++ { 2700000, 5, 3, 1, 0, 0x7, 300, 0x42, 230 }, ++ { 2700000, 5, 3, 1, 0, 0x7, 400, 0x4c, 230 }, ++ { 2970000, 6, 3, 1, 0, 0x7, 330, 0x42, 225 }, ++ { 3240000, 6, 3, 1, 0, 0x7, 360, 0x42, 256 }, ++ { 3240000, 6, 3, 1, 0, 0x7, 480, 0x4c, 256 }, ++ { 3712500, 4, 3, 0, 7, 0xF, 550, 0x4c, 257 }, ++ { 3960000, 5, 3, 0, 7, 0xF, 440, 0x42, 226 }, ++ { 4320000, 5, 3, 1, 7, 0xF, 480, 0x42, 258 }, ++ { 4455000, 5, 3, 0, 7, 0xF, 495, 0x42, 272 }, ++ { 4455000, 5, 3, 0, 7, 0xF, 660, 0x4c, 272 }, ++ { 4950000, 6, 3, 1, 0, 0x7, 550, 0x42, 258 }, ++ { 5940000, 7, 3, 1, 0, 0x7, 660, 0x42, 292 }, ++}; ++ ++struct phy_pll_reg { ++ u16 val[7]; ++ u32 addr; ++}; ++ ++static const struct phy_pll_reg phy_pll_27m_cfg[] = { ++ /* 1.62 2.16 2.43 2.7 3.24 4.32 5.4 register address */ ++ {{ 0x010e, 0x010e, 0x010e, 0x010e, 0x010e, 0x010e, 0x010e }, CMN_PLL0_VCOCAL_INIT_TMR }, ++ {{ 0x001b, 0x001b, 0x001b, 0x001b, 0x001b, 0x001b, 0x001b }, CMN_PLL0_VCOCAL_ITER_TMR }, ++ {{ 0x30b9, 0x3087, 0x3096, 0x30b4, 0x30b9, 0x3087, 0x30b4 }, CMN_PLL0_VCOCAL_START }, ++ {{ 0x0077, 0x009f, 0x00b3, 0x00c7, 0x0077, 0x009f, 0x00c7 }, CMN_PLL0_INTDIV }, ++ {{ 0xf9da, 0xf7cd, 0xf6c7, 0xf5c1, 0xf9da, 0xf7cd, 0xf5c1 }, CMN_PLL0_FRACDIV }, ++ {{ 0x001e, 0x0028, 0x002d, 0x0032, 0x001e, 0x0028, 0x0032 }, CMN_PLL0_HIGH_THR }, ++ {{ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 }, CMN_PLL0_DSM_DIAG }, ++ {{ 0x0000, 0x1000, 0x1000, 0x1000, 0x0000, 0x1000, 0x1000 }, CMN_PLLSM0_USER_DEF_CTRL }, ++ {{ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, CMN_DIAG_PLL0_OVRD }, ++ {{ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, CMN_DIAG_PLL0_FBH_OVRD }, ++ {{ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, CMN_DIAG_PLL0_FBL_OVRD }, ++ {{ 0x0006, 0x0007, 0x0007, 0x0007, 0x0006, 0x0007, 0x0007 }, CMN_DIAG_PLL0_V2I_TUNE }, ++ {{ 0x0043, 0x0043, 0x0043, 0x0042, 0x0043, 0x0043, 0x0042 }, CMN_DIAG_PLL0_CP_TUNE }, ++ {{ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008 }, CMN_DIAG_PLL0_LF_PROG }, ++ {{ 0x0100, 0x0001, 0x0001, 0x0001, 0x0100, 0x0001, 0x0001 }, CMN_DIAG_PLL0_PTATIS_TUNE1 }, ++ {{ 0x0007, 0x0001, 0x0001, 0x0001, 0x0007, 0x0001, 0x0001 }, CMN_DIAG_PLL0_PTATIS_TUNE2 }, ++ {{ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 }, CMN_DIAG_PLL0_TEST_MODE}, ++ {{ 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016 }, CMN_PSM_CLK_CTRL } ++}; ++ ++static int dp_link_rate_index(u32 rate) ++{ ++ switch (rate) { ++ case 162000: ++ return 0; ++ case 216000: ++ return 1; ++ case 243000: ++ return 2; ++ case 270000: ++ return 3; ++ case 324000: ++ return 4; ++ case 432000: ++ return 5; ++ case 540000: ++ return 6; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int cdns_phy_reg_write(struct cdns_hdptx_phy *cdns_phy, u32 addr, u32 val) ++{ ++ return cdns_mhdp_reg_write(&cdns_phy->base, ADDR_PHY_AFE + (addr << 2), val); ++} ++ ++static u32 cdns_phy_reg_read(struct cdns_hdptx_phy *cdns_phy, u32 addr) ++{ ++ u32 reg32; ++ ++ cdns_mhdp_reg_read(&cdns_phy->base, ADDR_PHY_AFE + (addr << 2), ®32); ++ ++ return reg32; ++} ++ ++static void hdptx_dp_aux_cfg(struct cdns_hdptx_phy *cdns_phy) ++{ ++ /* Power up Aux */ ++ cdns_phy_reg_write(cdns_phy, TXDA_CYA_AUXDA_CYA, 1); ++ ++ cdns_phy_reg_write(cdns_phy, TX_DIG_CTRL_REG_1, 0x3); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_DIG_CTRL_REG_2, 36); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_2, 0x0100); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_2, 0x0300); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_3, 0x0000); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_1, 0x2008); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_1, 0x2018); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_1, 0xa018); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_2, 0x030c); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_5, 0x0000); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_4, 0x1001); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_1, 0xa098); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_1, 0xa198); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_2, 0x030d); ++ ndelay(150); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_2, 0x030f); ++} ++ ++/* PMA common configuration for 27MHz */ ++static void hdptx_dp_phy_pma_cmn_cfg_27mhz(struct cdns_hdptx_phy *cdns_phy) ++{ ++ u32 num_lanes = cdns_phy->dp.lanes; ++ u16 val; ++ int k; ++ ++ /* Enable PMA input ref clk(CMN_REF_CLK_RCV_EN) */ ++ val = cdns_phy_reg_read(cdns_phy, PHY_PMA_CMN_CTRL1); ++ val &= ~CMA_REF_CLK_RCV_EN_MASK; ++ val |= FIELD_PREP(CMA_REF_CLK_RCV_EN_MASK, CMA_REF_CLK_RCV_EN); ++ cdns_phy_reg_write(cdns_phy, PHY_PMA_CMN_CTRL1, val); ++ ++ /* Startup state machine registers */ ++ cdns_phy_reg_write(cdns_phy, CMN_SSM_BIAS_TMR, 0x0087); ++ cdns_phy_reg_write(cdns_phy, CMN_PLLSM0_PLLEN_TMR, 0x001b); ++ cdns_phy_reg_write(cdns_phy, CMN_PLLSM0_PLLPRE_TMR, 0x0036); ++ cdns_phy_reg_write(cdns_phy, CMN_PLLSM0_PLLVREF_TMR, 0x001b); ++ cdns_phy_reg_write(cdns_phy, CMN_PLLSM0_PLLLOCK_TMR, 0x006c); ++ ++ /* Current calibration registers */ ++ cdns_phy_reg_write(cdns_phy, CMN_ICAL_INIT_TMR, 0x0044); ++ cdns_phy_reg_write(cdns_phy, CMN_ICAL_ITER_TMR, 0x0006); ++ cdns_phy_reg_write(cdns_phy, CMN_ICAL_ADJ_INIT_TMR, 0x0022); ++ cdns_phy_reg_write(cdns_phy, CMN_ICAL_ADJ_ITER_TMR, 0x0006); ++ ++ /* Resistor calibration registers */ ++ cdns_phy_reg_write(cdns_phy, CMN_TXPUCAL_INIT_TMR, 0x0022); ++ cdns_phy_reg_write(cdns_phy, CMN_TXPUCAL_ITER_TMR, 0x0006); ++ cdns_phy_reg_write(cdns_phy, CMN_TXPU_ADJ_INIT_TMR, 0x0022); ++ cdns_phy_reg_write(cdns_phy, CMN_TXPU_ADJ_ITER_TMR, 0x0006); ++ cdns_phy_reg_write(cdns_phy, CMN_TXPDCAL_INIT_TMR, 0x0022); ++ cdns_phy_reg_write(cdns_phy, CMN_TXPDCAL_ITER_TMR, 0x0006); ++ cdns_phy_reg_write(cdns_phy, CMN_TXPD_ADJ_INIT_TMR, 0x0022); ++ cdns_phy_reg_write(cdns_phy, CMN_TXPD_ADJ_ITER_TMR, 0x0006); ++ cdns_phy_reg_write(cdns_phy, CMN_RXCAL_INIT_TMR, 0x0022); ++ cdns_phy_reg_write(cdns_phy, CMN_RXCAL_ITER_TMR, 0x0006); ++ cdns_phy_reg_write(cdns_phy, CMN_RX_ADJ_INIT_TMR, 0x0022); ++ cdns_phy_reg_write(cdns_phy, CMN_RX_ADJ_ITER_TMR, 0x0006); ++ ++ for (k = 0; k < num_lanes; k = k + 1) { ++ /* Power state machine registers */ ++ cdns_phy_reg_write(cdns_phy, XCVR_PSM_CAL_TMR | (k << 9), 0x016d); ++ cdns_phy_reg_write(cdns_phy, XCVR_PSM_A0IN_TMR | (k << 9), 0x016d); ++ /* Transceiver control and diagnostic registers */ ++ cdns_phy_reg_write(cdns_phy, XCVR_DIAG_LANE_FCM_EN_MGN_TMR | (k << 9), 0x00a2); ++ cdns_phy_reg_write(cdns_phy, TX_DIAG_BGREF_PREDRV_DELAY | (k << 9), 0x0097); ++ /* Transmitter receiver detect registers */ ++ cdns_phy_reg_write(cdns_phy, TX_RCVDET_EN_TMR | (k << 9), 0x0a8c); ++ cdns_phy_reg_write(cdns_phy, TX_RCVDET_ST_TMR | (k << 9), 0x0036); ++ } ++ ++ cdns_phy_reg_write(cdns_phy, TX_DIAG_ACYA_0, 1); ++ cdns_phy_reg_write(cdns_phy, TX_DIAG_ACYA_1, 1); ++ cdns_phy_reg_write(cdns_phy, TX_DIAG_ACYA_2, 1); ++ cdns_phy_reg_write(cdns_phy, TX_DIAG_ACYA_3, 1); ++} ++ ++static void hdptx_dp_phy_pma_cmn_pll0_27mhz(struct cdns_hdptx_phy *cdns_phy) ++{ ++ u32 num_lanes = cdns_phy->dp.lanes; ++ u32 link_rate = cdns_phy->dp.link_rate; ++ u16 val; ++ int index, i, k; ++ ++ /* DP PLL data rate 0/1 clock divider value */ ++ val = cdns_phy_reg_read(cdns_phy, PHY_HDP_CLK_CTL); ++ val &= ~PLL_DATA_RATE_CLK_DIV_MASK; ++ if (link_rate <= LINK_RATE_2_7) ++ val |= FIELD_PREP(PLL_DATA_RATE_CLK_DIV_MASK, ++ PLL_DATA_RATE_CLK_DIV_HBR); ++ else ++ val |= FIELD_PREP(PLL_DATA_RATE_CLK_DIV_MASK, ++ PLL_DATA_RATE_CLK_DIV_HBR2); ++ cdns_phy_reg_write(cdns_phy, PHY_HDP_CLK_CTL, val); ++ ++ /* High speed clock 0/1 div */ ++ val = cdns_phy_reg_read(cdns_phy, CMN_DIAG_HSCLK_SEL); ++ val &= ~(HSCLK1_SEL_MASK | HSCLK0_SEL_MASK); ++ if (link_rate <= LINK_RATE_2_7) { ++ val |= FIELD_PREP(HSCLK1_SEL_MASK, HSCLK_PLL0_DIV2); ++ val |= FIELD_PREP(HSCLK0_SEL_MASK, HSCLK_PLL0_DIV2); ++ } ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_HSCLK_SEL, val); ++ ++ for (k = 0; k < num_lanes; k++) { ++ val = cdns_phy_reg_read(cdns_phy, (XCVR_DIAG_HSCLK_SEL | (k << 9))); ++ val &= ~HSCLK_SEL_MODE3_MASK; ++ if (link_rate <= LINK_RATE_2_7) ++ val |= FIELD_PREP(HSCLK_SEL_MODE3_MASK, HSCLK_SEL_MODE3_HSCLK1); ++ cdns_phy_reg_write(cdns_phy, (XCVR_DIAG_HSCLK_SEL | (k << 9)), val); ++ } ++ ++ /* DP PHY PLL 27MHz configuration */ ++ index = dp_link_rate_index(link_rate); ++ if (index < 0) { ++ dev_err(cdns_phy->dev, "Not support link rate %d\n", link_rate); ++ return; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(phy_pll_27m_cfg); i++) ++ cdns_phy_reg_write(cdns_phy, phy_pll_27m_cfg[i].addr, ++ phy_pll_27m_cfg[i].val[index]); ++ ++ /* Transceiver control and diagnostic registers */ ++ for (k = 0; k < num_lanes; k++) { ++ val = cdns_phy_reg_read(cdns_phy, (XCVR_DIAG_PLLDRC_CTRL | (k << 9))); ++ val &= ~(DPLL_DATA_RATE_DIV_MODE3_MASK | DPLL_CLK_SEL_MODE3); ++ if (link_rate <= LINK_RATE_2_7) ++ val |= FIELD_PREP(DPLL_DATA_RATE_DIV_MODE3_MASK, 2); ++ else ++ val |= FIELD_PREP(DPLL_DATA_RATE_DIV_MODE3_MASK, 1); ++ cdns_phy_reg_write(cdns_phy, (XCVR_DIAG_PLLDRC_CTRL | (k << 9)), val); ++ } ++ ++ for (k = 0; k < num_lanes; k = k + 1) { ++ /* Power state machine registers */ ++ cdns_phy_reg_write(cdns_phy, (XCVR_PSM_RCTRL | (k << 9)), 0xbefc); ++ cdns_phy_reg_write(cdns_phy, (TX_PSC_A0 | (k << 9)), 0x6799); ++ cdns_phy_reg_write(cdns_phy, (TX_PSC_A1 | (k << 9)), 0x6798); ++ cdns_phy_reg_write(cdns_phy, (TX_PSC_A2 | (k << 9)), 0x0098); ++ cdns_phy_reg_write(cdns_phy, (TX_PSC_A3 | (k << 9)), 0x0098); ++ /* Receiver calibration power state definition register */ ++ val = cdns_phy_reg_read(cdns_phy, RX_PSC_CAL | (k << 9)); ++ val &= 0xffbb; ++ cdns_phy_reg_write(cdns_phy, (RX_PSC_CAL | (k << 9)), val); ++ val = cdns_phy_reg_read(cdns_phy, RX_PSC_A0 | (k << 9)); ++ val &= 0xffbb; ++ cdns_phy_reg_write(cdns_phy, (RX_PSC_A0 | (k << 9)), val); ++ } ++} ++ ++static void hdptx_dp_phy_ref_clock_type(struct cdns_hdptx_phy *cdns_phy) ++{ ++ u32 val; ++ ++ val = cdns_phy_reg_read(cdns_phy, PHY_PMA_CMN_CTRL1); ++ val &= ~CMA_REF_CLK_SEL_MASK; ++ /* ++ * single ended reference clock (val |= 0x0030); ++ * differential clock (val |= 0x0000); ++ * ++ * for differential clock on the refclk_p and ++ * refclk_m off chip pins: CMN_DIAG_ACYA[8]=1'b1 ++ * cdns_phy_reg_write(cdns_phy, CMN_DIAG_ACYA, 0x0100); ++ */ ++ val |= FIELD_PREP(CMA_REF_CLK_SEL_MASK, 3); ++ cdns_phy_reg_write(cdns_phy, PHY_PMA_CMN_CTRL1, val); ++} ++ ++static int wait_for_ack(struct cdns_hdptx_phy *cdns_phy, ++ u32 reg, u32 mask, ++ const char *err_msg) ++{ ++ int ret; ++ u32 val; ++ ++ ret = read_poll_timeout(cdns_phy_reg_read, ++ val, val & mask, 20, 1000, ++ false, cdns_phy, reg); ++ if (ret < 0) ++ dev_err(cdns_phy->dev, "%s\n", err_msg); ++ ++ return ret; ++} ++ ++static int wait_for_ack_clear(struct cdns_hdptx_phy *cdns_phy, ++ u32 reg, u32 mask, ++ const char *err_msg) ++{ ++ int ret; ++ u32 val; ++ ++ ret = read_poll_timeout(cdns_phy_reg_read, ++ val, !(val & mask), 20, 1000, ++ false, cdns_phy, reg); ++ if (ret < 0) ++ dev_err(cdns_phy->dev, "%s\n", err_msg); ++ ++ return ret; ++} ++ ++static int hdptx_dp_phy_power_up(struct cdns_hdptx_phy *cdns_phy) ++{ ++ u32 val; ++ int ret; ++ ++ /* Enable HDP PLL's for high speed clocks */ ++ val = cdns_phy_reg_read(cdns_phy, PHY_HDP_CLK_CTL); ++ val |= PLL_EN; ++ cdns_phy_reg_write(cdns_phy, PHY_HDP_CLK_CTL, val); ++ ret = wait_for_ack(cdns_phy, PHY_HDP_CLK_CTL, PLL_READY, ++ "Wait PLL Ack failed"); ++ if (ret < 0) ++ return ret; ++ ++ /* Enable HDP PLL's data rate and full rate clocks out of PMA. */ ++ val = cdns_phy_reg_read(cdns_phy, PHY_HDP_CLK_CTL); ++ val |= PLL_CLK_EN; ++ cdns_phy_reg_write(cdns_phy, PHY_HDP_CLK_CTL, val); ++ ret = wait_for_ack(cdns_phy, PHY_HDP_CLK_CTL, PLL_CLK_EN_ACK, ++ "Wait PLL clock enable ACK failed"); ++ if (ret < 0) ++ return ret; ++ ++ /* Configure PHY in A2 Mode */ ++ cdns_phy_reg_write(cdns_phy, PHY_HDP_MODE_CTRL, POWER_STATE_A2); ++ ret = wait_for_ack(cdns_phy, PHY_HDP_MODE_CTRL, POWER_STATE_A2_ACK, ++ "Wait A2 Ack failed"); ++ if (ret < 0) ++ return ret; ++ ++ /* Configure PHY in A0 mode (PHY must be in the A0 power ++ * state in order to transmit data) ++ */ ++ cdns_phy_reg_write(cdns_phy, PHY_HDP_MODE_CTRL, POWER_STATE_A0); ++ ++ return wait_for_ack(cdns_phy, PHY_HDP_MODE_CTRL, POWER_STATE_A0_ACK, ++ "Wait A0 Ack failed"); ++} ++ ++static int hdptx_dp_phy_power_down(struct cdns_hdptx_phy *cdns_phy) ++{ ++ u16 val; ++ int ret; ++ ++ /* Place the PHY lanes in the A3 power state. */ ++ cdns_phy_reg_write(cdns_phy, PHY_HDP_MODE_CTRL, POWER_STATE_A3); ++ ret = wait_for_ack(cdns_phy, PHY_HDP_MODE_CTRL, POWER_STATE_A3_ACK, ++ "Wait A3 Ack failed"); ++ if (ret) ++ return ret; ++ ++ /* Disable HDP PLL's data rate and full rate clocks out of PMA. */ ++ val = cdns_phy_reg_read(cdns_phy, PHY_HDP_CLK_CTL); ++ val &= ~PLL_CLK_EN; ++ cdns_phy_reg_write(cdns_phy, PHY_HDP_CLK_CTL, val); ++ ret = wait_for_ack_clear(cdns_phy, PHY_HDP_CLK_CTL, PLL_CLK_EN_ACK, ++ "Wait PLL clock Ack clear failed"); ++ if (ret) ++ return ret; ++ ++ /* Disable HDP PLL's for high speed clocks */ ++ val = cdns_phy_reg_read(cdns_phy, PHY_HDP_CLK_CTL); ++ val &= ~PLL_EN; ++ cdns_phy_reg_write(cdns_phy, PHY_HDP_CLK_CTL, val); ++ ++ return wait_for_ack_clear(cdns_phy, PHY_HDP_CLK_CTL, PLL_READY, ++ "Wait PLL Ack clear failed"); ++} ++ ++static int hdptx_dp_configure(struct phy *phy, ++ union phy_configure_opts *opts) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &opts->dp; ++ struct cdns_hdptx_phy *cdns_phy = phy_get_drvdata(phy); ++ ++ if (opts->dp.link_rate > MAX_LINK_RATE) { ++ dev_err(cdns_phy->dev, "Link Rate(%d) Not supported\n", opts->dp.link_rate); ++ return false; ++ } ++ ++ memcpy(&cdns_phy->dp, dp_opts, sizeof(*dp_opts)); ++ ++ hdptx_dp_phy_pma_cmn_cfg_27mhz(cdns_phy); ++ hdptx_dp_phy_pma_cmn_pll0_27mhz(cdns_phy); ++ ++ return 0; ++} ++ ++static int hdptx_clk_enable(struct cdns_hdptx_phy *cdns_phy) ++{ ++ struct device *dev = cdns_phy->dev; ++ u32 ref_clk_rate; ++ ++ cdns_phy->ref_clk = devm_clk_get_enabled(dev, "ref"); ++ if (IS_ERR(cdns_phy->ref_clk)) { ++ dev_err(dev, "phy ref clock not found\n"); ++ return PTR_ERR(cdns_phy->ref_clk); ++ } ++ ++ ref_clk_rate = clk_get_rate(cdns_phy->ref_clk); ++ if (!ref_clk_rate) { ++ dev_err(cdns_phy->dev, "Failed to get ref clock rate\n"); ++ return -EINVAL; ++ } ++ ++ if (ref_clk_rate == REF_CLK_27MHZ) { ++ cdns_phy->ref_clk_rate = ref_clk_rate; ++ } else { ++ dev_err(cdns_phy->dev, "Not support Ref Clock Rate(%dHz)\n", ref_clk_rate); ++ return -EINVAL; ++ } ++ ++ cdns_phy->apb_clk = devm_clk_get_enabled(dev, "apb"); ++ if (IS_ERR(cdns_phy->apb_clk)) { ++ dev_err(dev, "phy apb clock not found\n"); ++ return PTR_ERR(cdns_phy->apb_clk); ++ } ++ ++ return 0; ++} ++ ++static void hdptx_hdmi_arc_config(struct cdns_hdptx_phy *cdns_phy) ++{ ++ u16 txpu_calib_code; ++ u16 txpd_calib_code; ++ u16 txpu_adj_calib_code; ++ u16 txpd_adj_calib_code; ++ u16 prev_calib_code; ++ u16 new_calib_code; ++ u16 rdata; ++ ++ /* Power ARC */ ++ cdns_phy_reg_write(cdns_phy, TXDA_CYA_AUXDA_CYA, 0x0001); ++ ++ prev_calib_code = cdns_phy_reg_read(cdns_phy, TX_DIG_CTRL_REG_2); ++ txpu_calib_code = cdns_phy_reg_read(cdns_phy, CMN_TXPUCAL_CTRL); ++ txpd_calib_code = cdns_phy_reg_read(cdns_phy, CMN_TXPDCAL_CTRL); ++ txpu_adj_calib_code = cdns_phy_reg_read(cdns_phy, CMN_TXPU_ADJ_CTRL); ++ txpd_adj_calib_code = cdns_phy_reg_read(cdns_phy, CMN_TXPD_ADJ_CTRL); ++ ++ new_calib_code = ((txpu_calib_code + txpd_calib_code) / 2) ++ + txpu_adj_calib_code + txpd_adj_calib_code; ++ ++ if (new_calib_code != prev_calib_code) { ++ rdata = cdns_phy_reg_read(cdns_phy, TX_ANA_CTRL_REG_1); ++ rdata &= 0xdfff; ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_1, rdata); ++ cdns_phy_reg_write(cdns_phy, TX_DIG_CTRL_REG_2, new_calib_code); ++ mdelay(10); ++ rdata |= 0x2000; ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_1, rdata); ++ usleep_range(150, 250); ++ } ++ ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_2, 0x0100); ++ usleep_range(100, 200); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_2, 0x0300); ++ usleep_range(100, 200); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_3, 0x0000); ++ usleep_range(100, 200); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_1, 0x2008); ++ usleep_range(100, 200); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_1, 0x2018); ++ usleep_range(100, 200); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_1, 0x2098); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_2, 0x030c); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_5, 0x0010); ++ usleep_range(100, 200); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_4, 0x4001); ++ mdelay(5); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_1, 0x2198); ++ mdelay(5); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_2, 0x030d); ++ usleep_range(100, 200); ++ cdns_phy_reg_write(cdns_phy, TX_ANA_CTRL_REG_2, 0x030f); ++} ++ ++static void hdptx_hdmi_phy_set_vswing(struct cdns_hdptx_phy *cdns_phy) ++{ ++ u32 k; ++ const u32 num_lanes = 4; ++ ++ for (k = 0; k < num_lanes; k++) { ++ cdns_phy_reg_write(cdns_phy, (TX_DIAG_TX_DRV | (k << 9)), ++ TX_DRIVER_PROG_BOOST_ENABLE | ++ FIELD_PREP(TX_DRIVER_PROG_BOOST_LEVEL_MASK, 3) | ++ TX_DRIVER_LDO_BG_DEPENDENT_REF_ENABLE | ++ TX_DRIVER_LDO_BANDGAP_REF_ENABLE); ++ cdns_phy_reg_write(cdns_phy, (TX_TXCC_CPOST_MULT_00_0 | (k << 9)), 0x0); ++ cdns_phy_reg_write(cdns_phy, (TX_TXCC_CAL_SCLR_MULT_0 | (k << 9)), ++ SCALED_RESISTOR_CALIBRATION_CODE_ADD | ++ RESISTOR_CAL_MULT_VAL_32_128); ++ } ++} ++ ++static int hdptx_hdmi_phy_config(struct cdns_hdptx_phy *cdns_phy, ++ const struct hdptx_hdmi_ctrl *p_ctrl_table, ++ const struct hdptx_hdmi_pll_tuning *p_pll_table, ++ bool pclk_in) ++{ ++ const u32 num_lanes = 4; ++ u32 val, k; ++ int ret; ++ ++ /* enable PHY isolation mode only for CMN */ ++ cdns_phy_reg_write(cdns_phy, PHY_PMA_ISOLATION_CTRL, 0xd000); ++ ++ /* set cmn_pll0_clk_datart1_div/cmn_pll0_clk_datart0_div dividers */ ++ val = cdns_phy_reg_read(cdns_phy, PHY_PMA_ISO_PLL_CTRL1); ++ val &= ~CMN_PLL0_CLK_DATART_DIV_MASK; ++ val |= FIELD_PREP(CMN_PLL0_CLK_DATART_DIV_MASK, 0x12); ++ cdns_phy_reg_write(cdns_phy, PHY_PMA_ISO_PLL_CTRL1, val); ++ ++ /* assert PHY reset from isolation register */ ++ cdns_phy_reg_write(cdns_phy, PHY_ISO_CMN_CTRL, 0x0000); ++ /* assert PMA CMN reset */ ++ cdns_phy_reg_write(cdns_phy, PHY_PMA_ISO_CMN_CTRL, 0x0000); ++ ++ /* register XCVR_DIAG_BIDI_CTRL */ ++ for (k = 0; k < num_lanes; k++) ++ cdns_phy_reg_write(cdns_phy, XCVR_DIAG_BIDI_CTRL | (k << 9), 0x00ff); ++ ++ /* Describing Task phy_cfg_hdp */ ++ val = cdns_phy_reg_read(cdns_phy, PHY_PMA_CMN_CTRL1); ++ val &= ~CMA_REF_CLK_RCV_EN_MASK; ++ val |= FIELD_PREP(CMA_REF_CLK_RCV_EN_MASK, CMA_REF_CLK_RCV_EN); ++ cdns_phy_reg_write(cdns_phy, PHY_PMA_CMN_CTRL1, val); ++ ++ /* PHY Registers */ ++ val = cdns_phy_reg_read(cdns_phy, PHY_PMA_CMN_CTRL1); ++ val &= ~CMA_REF_CLK_DIG_DIV_MASK; ++ val |= FIELD_PREP(CMA_REF_CLK_DIG_DIV_MASK, CMN_REF_CLK_DIG_DIV); ++ cdns_phy_reg_write(cdns_phy, PHY_PMA_CMN_CTRL1, val); ++ ++ val = cdns_phy_reg_read(cdns_phy, PHY_HDP_CLK_CTL); ++ val &= ~PLL_DATA_RATE_CLK_DIV_MASK; ++ val |= FIELD_PREP(PLL_DATA_RATE_CLK_DIV_MASK, ++ PLL_DATA_RATE_CLK_DIV_HBR2); ++ cdns_phy_reg_write(cdns_phy, PHY_HDP_CLK_CTL, val); ++ ++ /* Common control module control and diagnostic registers */ ++ val = cdns_phy_reg_read(cdns_phy, CMN_CDIAG_REFCLK_CTRL); ++ val &= ~DIG_REF_CLK_DIV_SCALER_MASK; ++ val |= FIELD_PREP(DIG_REF_CLK_DIV_SCALER_MASK, REF_CLK_DIVIDER_SCALER); ++ val |= REFCLK_TERMINATION_EN_OVERRIDE_EN | REFCLK_TERMINATION_EN_OVERRIDE; ++ cdns_phy_reg_write(cdns_phy, CMN_CDIAG_REFCLK_CTRL, val); ++ ++ /* High speed clock used */ ++ val = cdns_phy_reg_read(cdns_phy, CMN_DIAG_HSCLK_SEL); ++ val &= ~(HSCLK1_SEL_MASK | HSCLK0_SEL_MASK); ++ val |= FIELD_PREP(HSCLK1_SEL_MASK, (p_ctrl_table->cmnda_hs_clk_1_sel >> 1)); ++ val |= FIELD_PREP(HSCLK0_SEL_MASK, (p_ctrl_table->cmnda_hs_clk_0_sel >> 1)); ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_HSCLK_SEL, val); ++ ++ for (k = 0; k < num_lanes; k++) { ++ val = cdns_phy_reg_read(cdns_phy, (XCVR_DIAG_HSCLK_SEL | (k << 9))); ++ val &= ~HSCLK_SEL_MODE3_MASK; ++ val |= FIELD_PREP(HSCLK_SEL_MODE3_MASK, ++ (p_ctrl_table->cmnda_hs_clk_0_sel >> 1)); ++ cdns_phy_reg_write(cdns_phy, (XCVR_DIAG_HSCLK_SEL | (k << 9)), val); ++ } ++ ++ /* PLL 0 control state machine registers */ ++ val = p_ctrl_table->vco_ring_select << 12; ++ cdns_phy_reg_write(cdns_phy, CMN_PLLSM0_USER_DEF_CTRL, val); ++ ++ if (pclk_in) { ++ val = 0x30a0; ++ } else { ++ val = cdns_phy_reg_read(cdns_phy, CMN_PLL0_VCOCAL_START); ++ val &= ~VCO_CALIB_CODE_START_POINT_VAL_MASK; ++ val |= FIELD_PREP(VCO_CALIB_CODE_START_POINT_VAL_MASK, ++ p_pll_table->vco_cal_code); ++ } ++ cdns_phy_reg_write(cdns_phy, CMN_PLL0_VCOCAL_START, val); ++ ++ cdns_phy_reg_write(cdns_phy, CMN_PLL0_VCOCAL_INIT_TMR, 0x0064); ++ cdns_phy_reg_write(cdns_phy, CMN_PLL0_VCOCAL_ITER_TMR, 0x000a); ++ ++ /* Common functions control and diagnostics registers */ ++ val = p_ctrl_table->cmnda_pll0_hs_sym_div_sel << 8; ++ val |= p_ctrl_table->cmnda_pll0_ip_div; ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_INCLK_CTRL, val); ++ ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_OVRD, 0x0000); ++ ++ val = p_ctrl_table->cmnda_pll0_fb_div_high; ++ val |= PLL_FEEDBACK_DIV_HI_OVERRIDE_EN; ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_FBH_OVRD, val); ++ ++ val = p_ctrl_table->cmnda_pll0_fb_div_low; ++ val |= PLL_FEEDBACK_DIV_LO_OVERRIDE_EN; ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_FBL_OVRD, val); ++ ++ if (!pclk_in) { ++ val = p_ctrl_table->cmnda_pll0_pxdiv_low; ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_PXL_DIVL, val); ++ ++ val = p_ctrl_table->cmnda_pll0_pxdiv_high; ++ val |= PLL_PCLK_DIV_EN; ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_PXL_DIVH, val); ++ } ++ ++ val = p_pll_table->volt_to_current_coarse; ++ val |= (p_pll_table->volt_to_current) << 4; ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_V2I_TUNE, val); ++ ++ val = p_pll_table->charge_pump_gain; ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_CP_TUNE, val); ++ ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_LF_PROG, 0x0008); ++ ++ val = p_pll_table->pmos_ctrl; ++ val |= (p_pll_table->ndac_ctrl) << 8; ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_PTATIS_TUNE1, val); ++ ++ val = p_pll_table->ptat_ndac_ctrl; ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_PTATIS_TUNE2, val); ++ ++ if (pclk_in) ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_TEST_MODE, 0x0022); ++ else ++ cdns_phy_reg_write(cdns_phy, CMN_DIAG_PLL0_TEST_MODE, 0x0020); ++ ++ cdns_phy_reg_write(cdns_phy, CMN_PSM_CLK_CTRL, 0x0016); ++ ++ /* Transceiver control and diagnostic registers */ ++ for (k = 0; k < num_lanes; k++) { ++ val = cdns_phy_reg_read(cdns_phy, (XCVR_DIAG_PLLDRC_CTRL | (k << 9))); ++ val &= ~DPLL_CLK_SEL_MODE3; ++ cdns_phy_reg_write(cdns_phy, (XCVR_DIAG_PLLDRC_CTRL | (k << 9)), val); ++ } ++ ++ for (k = 0; k < num_lanes; k++) { ++ val = cdns_phy_reg_read(cdns_phy, (TX_DIAG_TX_CTRL | (k << 9))); ++ val &= ~TX_IF_SUBRATE_MODE3_MASK; ++ val |= FIELD_PREP(TX_IF_SUBRATE_MODE3_MASK, ++ (p_ctrl_table->hsclk_div_tx_sub_rate >> 1)); ++ cdns_phy_reg_write(cdns_phy, (TX_DIAG_TX_CTRL | (k << 9)), val); ++ } ++ ++ val = cdns_phy_reg_read(cdns_phy, PHY_PMA_CMN_CTRL1); ++ val &= ~CMA_REF_CLK_SEL_MASK; ++ /* ++ * single ended reference clock (val |= 0x0030); ++ * differential clock (val |= 0x0000); ++ * for differential clock on the refclk_p and ++ * refclk_m off chip pins: CMN_DIAG_ACYA[8]=1'b1 ++ * cdns_phy_reg_write(cdns_phy, CMN_DIAG_ACYA, 0x0100); ++ */ ++ val |= FIELD_PREP(CMA_REF_CLK_SEL_MASK, 3); ++ cdns_phy_reg_write(cdns_phy, PHY_PMA_CMN_CTRL1, val); ++ ++ /* Deassert PHY reset */ ++ cdns_phy_reg_write(cdns_phy, PHY_ISO_CMN_CTRL, 0x0001); ++ cdns_phy_reg_write(cdns_phy, PHY_PMA_ISO_CMN_CTRL, 0x0003); ++ ++ /* Power state machine registers */ ++ for (k = 0; k < num_lanes; k++) ++ cdns_phy_reg_write(cdns_phy, XCVR_PSM_RCTRL | (k << 9), 0xfefc); ++ ++ /* Assert cmn_macro_pwr_en */ ++ cdns_phy_reg_write(cdns_phy, PHY_PMA_ISO_CMN_CTRL, 0x0013); ++ ++ /* wait for cmn_macro_pwr_en_ack */ ++ ret = wait_for_ack(cdns_phy, PHY_PMA_ISO_CMN_CTRL, CMN_MACRO_PWR_EN_ACK, ++ "MA output macro power up failed"); ++ if (ret < 0) ++ return ret; ++ ++ /* wait for cmn_ready */ ++ ret = wait_for_ack(cdns_phy, PHY_PMA_CMN_CTRL1, CMN_READY, ++ "PMA output ready failed"); ++ if (ret < 0) ++ return ret; ++ ++ for (k = 0; k < num_lanes; k++) { ++ cdns_phy_reg_write(cdns_phy, TX_PSC_A0 | (k << 9), 0x6791); ++ cdns_phy_reg_write(cdns_phy, TX_PSC_A1 | (k << 9), 0x6790); ++ cdns_phy_reg_write(cdns_phy, TX_PSC_A2 | (k << 9), 0x0090); ++ cdns_phy_reg_write(cdns_phy, TX_PSC_A3 | (k << 9), 0x0090); ++ ++ val = cdns_phy_reg_read(cdns_phy, RX_PSC_CAL | (k << 9)); ++ val &= 0xffbb; ++ cdns_phy_reg_write(cdns_phy, RX_PSC_CAL | (k << 9), val); ++ ++ val = cdns_phy_reg_read(cdns_phy, RX_PSC_A0 | (k << 9)); ++ val &= 0xffbb; ++ cdns_phy_reg_write(cdns_phy, RX_PSC_A0 | (k << 9), val); ++ } ++ ++ return 0; ++} ++ ++static int hdptx_hdmi_phy_cfg(struct cdns_hdptx_phy *cdns_phy, unsigned long long char_rate) ++{ ++ const struct hdptx_hdmi_ctrl *p_ctrl_table; ++ const struct hdptx_hdmi_pll_tuning *p_pll_table; ++ const u32 refclk_freq_khz = cdns_phy->ref_clk_rate / 1000; ++ const bool pclk_in = false; ++ u32 char_rate_khz = char_rate / 1000; ++ u32 vco_freq, rate; ++ u32 div_total, i; ++ ++ dev_dbg(cdns_phy->dev, "character clock: %d KHz\n ", char_rate_khz); ++ ++ /* Get right row from the ctrl_table table. ++ * check the character rate. ++ */ ++ for (i = 0; i < ARRAY_SIZE(pixel_clk_output_ctrl_table); i++) { ++ rate = pixel_clk_output_ctrl_table[i].feedback_factor * ++ pixel_clk_output_ctrl_table[i].pixel_clk_freq / 1000; ++ if (char_rate_khz == rate) { ++ p_ctrl_table = &pixel_clk_output_ctrl_table[i]; ++ break; ++ } ++ } ++ if (i == ARRAY_SIZE(pixel_clk_output_ctrl_table)) { ++ dev_warn(cdns_phy->dev, ++ "char clk (%d KHz) not supported\n", char_rate_khz); ++ return -EINVAL; ++ } ++ ++ div_total = p_ctrl_table->pll_fb_div_total; ++ vco_freq = refclk_freq_khz * div_total / p_ctrl_table->cmnda_pll0_ip_div; ++ ++ /* Get right row from the pixel_clk_output_pll_table table. ++ * Check if vco_freq_khz and feedback_div_total ++ * column matching with pixel_clk_output_pll_table. ++ */ ++ for (i = 0; i < ARRAY_SIZE(pixel_clk_output_pll_table); i++) { ++ if (vco_freq == pixel_clk_output_pll_table[i].vco_freq && ++ div_total == pixel_clk_output_pll_table[i].feedback_div_total) { ++ p_pll_table = &pixel_clk_output_pll_table[i]; ++ break; ++ } ++ } ++ if (i == ARRAY_SIZE(pixel_clk_output_pll_table)) { ++ dev_warn(cdns_phy->dev, "VCO (%d KHz) not supported\n", vco_freq); ++ return -EINVAL; ++ } ++ dev_dbg(cdns_phy->dev, "VCO frequency is (%d KHz)\n", vco_freq); ++ ++ return hdptx_hdmi_phy_config(cdns_phy, p_ctrl_table, p_pll_table, pclk_in); ++} ++ ++static int hdptx_hdmi_phy_power_up(struct cdns_hdptx_phy *cdns_phy) ++{ ++ int ret; ++ ++ /* set Power State to A2 */ ++ cdns_phy_reg_write(cdns_phy, PHY_HDP_MODE_CTRL, POWER_STATE_A2); ++ ++ cdns_phy_reg_write(cdns_phy, TX_DIAG_ACYA_0, 1); ++ cdns_phy_reg_write(cdns_phy, TX_DIAG_ACYA_1, 1); ++ cdns_phy_reg_write(cdns_phy, TX_DIAG_ACYA_2, 1); ++ cdns_phy_reg_write(cdns_phy, TX_DIAG_ACYA_3, 1); ++ ++ ret = wait_for_ack(cdns_phy, PHY_HDP_MODE_CTRL, POWER_STATE_A2_ACK, ++ "Wait A2 Ack failed"); ++ if (ret < 0) ++ return ret; ++ ++ /* Power up ARC */ ++ hdptx_hdmi_arc_config(cdns_phy); ++ ++ /* Configure PHY in A0 mode (PHY must be in the A0 power ++ * state in order to transmit data) ++ */ ++ cdns_phy_reg_write(cdns_phy, PHY_HDP_MODE_CTRL, POWER_STATE_A0); ++ ++ return wait_for_ack(cdns_phy, PHY_HDP_MODE_CTRL, POWER_STATE_A0_ACK, ++ "Wait A0 Ack failed"); ++} ++ ++static int hdptx_hdmi_phy_power_down(struct cdns_hdptx_phy *cdns_phy) ++{ ++ u32 val; ++ ++ val = cdns_phy_reg_read(cdns_phy, PHY_HDP_MODE_CTRL); ++ val &= ~(POWER_STATE_A0 | POWER_STATE_A1 | POWER_STATE_A2 | POWER_STATE_A3); ++ /* PHY_DP_MODE_CTL set to A3 power state */ ++ cdns_phy_reg_write(cdns_phy, PHY_HDP_MODE_CTRL, val | POWER_STATE_A3); ++ ++ return wait_for_ack(cdns_phy, PHY_HDP_MODE_CTRL, POWER_STATE_A3_ACK, ++ "Wait A3 Ack failed"); ++} ++ ++static int hdptx_hdmi_configure(struct phy *phy, ++ union phy_configure_opts *opts) ++{ ++ struct cdns_hdptx_phy *cdns_phy = phy_get_drvdata(phy); ++ u32 reg; ++ int ret; ++ ++ cdns_phy->hdmi.tmds_char_rate = opts->hdmi.tmds_char_rate; ++ ++ /* Check HDMI FW alive before HDMI PHY init */ ++ ret = readl_poll_timeout(cdns_phy->regs + KEEP_ALIVE, reg, ++ reg & CDNS_KEEP_ALIVE_MASK, 500, ++ CDNS_KEEP_ALIVE_TIMEOUT); ++ if (ret < 0) { ++ dev_err(cdns_phy->dev, "NO HDMI FW running\n"); ++ return -ENXIO; ++ } ++ ++ /* Configure PHY */ ++ if (hdptx_hdmi_phy_cfg(cdns_phy, cdns_phy->hdmi.tmds_char_rate) < 0) { ++ dev_err(cdns_phy->dev, "failed to set phy pclock\n"); ++ return -EINVAL; ++ } ++ ++ hdptx_hdmi_phy_set_vswing(cdns_phy); ++ ++ return 0; ++} ++ ++static int cdns_hdptx_phy_on(struct phy *phy) ++{ ++ struct cdns_hdptx_phy *cdns_phy = phy_get_drvdata(phy); ++ ++ if (phy->attrs.mode == PHY_MODE_DP) ++ return hdptx_dp_phy_power_up(cdns_phy); ++ else ++ return hdptx_hdmi_phy_power_up(cdns_phy); ++} ++ ++static int cdns_hdptx_phy_off(struct phy *phy) ++{ ++ struct cdns_hdptx_phy *cdns_phy = phy_get_drvdata(phy); ++ ++ if (phy->attrs.mode == PHY_MODE_DP) ++ return hdptx_dp_phy_power_down(cdns_phy); ++ else ++ return hdptx_hdmi_phy_power_down(cdns_phy); ++} ++ ++static int ++cdns_hdptx_phy_valid(struct phy *phy, enum phy_mode mode, ++ int submode, union phy_configure_opts *opts) ++{ ++ u32 rate = opts->hdmi.tmds_char_rate / 1000; ++ int i; ++ ++ if (mode == PHY_MODE_DP) ++ return 0; ++ ++ for (i = 0; i < ARRAY_SIZE(pixel_clk_output_ctrl_table); i++) ++ if (rate == pixel_clk_output_ctrl_table[i].pixel_clk_freq) ++ return 0; ++ ++ return -EINVAL; ++} ++ ++static int cdns_hdptx_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) ++{ ++ struct cdns_hdptx_phy *cdns_phy = phy_get_drvdata(phy); ++ int ret = 0; ++ ++ if (mode == PHY_MODE_DP) { ++ hdptx_dp_phy_ref_clock_type(cdns_phy); ++ hdptx_dp_aux_cfg(cdns_phy); ++ } else if (mode != PHY_MODE_HDMI) { ++ dev_err(&phy->dev, "Invalid PHY mode: %u\n", mode); ++ return -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static int cdns_hdptx_configure(struct phy *phy, ++ union phy_configure_opts *opts) ++{ ++ if (phy->attrs.mode == PHY_MODE_DP) ++ return hdptx_dp_configure(phy, opts); ++ else ++ return hdptx_hdmi_configure(phy, opts); ++} ++ ++static const struct phy_ops cdns_hdptx_phy_ops = { ++ .set_mode = cdns_hdptx_phy_set_mode, ++ .configure = cdns_hdptx_configure, ++ .power_on = cdns_hdptx_phy_on, ++ .power_off = cdns_hdptx_phy_off, ++ .validate = cdns_hdptx_phy_valid, ++ .owner = THIS_MODULE, ++}; ++ ++static int cdns_hdptx_phy_probe(struct platform_device *pdev) ++{ ++ struct cdns_hdptx_phy *cdns_phy; ++ struct device *dev = &pdev->dev; ++ struct device_node *node = dev->of_node; ++ struct phy_provider *phy_provider; ++ struct resource *res; ++ struct phy *phy; ++ int ret; ++ ++ cdns_phy = devm_kzalloc(dev, sizeof(*cdns_phy), GFP_KERNEL); ++ if (!cdns_phy) ++ return -ENOMEM; ++ ++ dev_set_drvdata(dev, cdns_phy); ++ cdns_phy->dev = dev; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -ENODEV; ++ cdns_phy->regs = devm_ioremap(dev, res->start, resource_size(res)); ++ if (IS_ERR(cdns_phy->regs)) ++ return PTR_ERR(cdns_phy->regs); ++ ++ phy = devm_phy_create(dev, node, &cdns_hdptx_phy_ops); ++ if (IS_ERR(phy)) ++ return PTR_ERR(phy); ++ ++ cdns_phy->phy = phy; ++ phy_set_drvdata(phy, cdns_phy); ++ ++ /* init base struct for access mhdp mailbox */ ++ cdns_phy->base.dev = cdns_phy->dev; ++ cdns_phy->base.regs = cdns_phy->regs; ++ ++ ret = hdptx_clk_enable(cdns_phy); ++ if (ret) ++ return -EINVAL; ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ if (IS_ERR(phy_provider)) ++ return PTR_ERR(phy_provider); ++ ++ return 0; ++} ++ ++static const struct of_device_id cdns_hdptx_phy_of_match[] = { ++ {.compatible = "fsl,imx8mq-hdptx-phy" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, cdns_hdptx_phy_of_match); ++ ++static struct platform_driver cdns_hdptx_phy_driver = { ++ .probe = cdns_hdptx_phy_probe, ++ .driver = { ++ .name = "cdns-hdptx-phy", ++ .of_match_table = cdns_hdptx_phy_of_match, ++ } ++}; ++module_platform_driver(cdns_hdptx_phy_driver); ++ ++MODULE_AUTHOR("Sandor Yu "); ++MODULE_DESCRIPTION("Cadence HDP-TX DP/HDMI PHY driver"); ++MODULE_LICENSE("GPL"); + +From patchwork Tue Dec 17 06:51:50 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v20,8/9] arm64: dts: imx8mq: Add DCSS + HDMI/DP display pipeline +From: Sandor Yu +X-Patchwork-Id: 629295 +Message-Id: + +To: dmitry.baryshkov@linaro.org, andrzej.hajda@intel.com, + neil.armstrong@linaro.org, Laurent.pinchart@ideasonboard.com, + jonas@kwiboo.se, jernej.skrabec@gmail.com, airlied@gmail.com, + daniel@ffwll.ch, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, + vkoul@kernel.org, dri-devel@lists.freedesktop.org, + devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, + mripard@kernel.org +Cc: kernel@pengutronix.de, linux-imx@nxp.com, Sandor.yu@nxp.com, + oliver.brown@nxp.com, alexander.stein@ew.tq-group.com, sam@ravnborg.org +Date: Tue, 17 Dec 2024 14:51:50 +0800 + +From: Alexander Stein + +This adds DCSS + MHDP + MHDP PHY nodes. PHY mode (DP/HDMI) is selected +by the connector type connected to mhdp port@1 endpoint. + +Signed-off-by: Alexander Stein +--- +v17->v20: + *No change + + arch/arm64/boot/dts/freescale/imx8mq.dtsi | 68 +++++++++++++++++++++++ + 1 file changed, 68 insertions(+) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi +index d51de8d899b2b..df8ba1d5391ae 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi ++++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi +@@ -1602,6 +1602,74 @@ aips4: bus@32c00000 { /* AIPS4 */ + #size-cells = <1>; + ranges = <0x32c00000 0x32c00000 0x400000>; + ++ mdhp_phy: phy@32c00000 { ++ compatible = "fsl,imx8mq-hdptx-phy"; ++ reg = <0x32c00000 0x100000>; ++ #phy-cells = <0>; ++ clocks = <&hdmi_phy_27m>, <&clk IMX8MQ_CLK_DISP_APB_ROOT>; ++ clock-names = "ref", "apb"; ++ }; ++ ++ mhdp: bridge@32c00000 { ++ compatible = "fsl,imx8mq-mhdp8501"; ++ reg = <0x32c00000 0x100000>; ++ interrupts = , ++ ; ++ interrupt-names = "plug_in", "plug_out"; ++ clocks = <&clk IMX8MQ_CLK_DISP_APB_ROOT>; ++ phys = <&mdhp_phy>; ++ status = "disabled"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ mhdp_in: endpoint { ++ remote-endpoint = <&dcss_out>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ mhdp_out: endpoint { ++ }; ++ }; ++ }; ++ }; ++ ++ dcss: display-controller@32e00000 { ++ compatible = "nxp,imx8mq-dcss"; ++ reg = <0x32e00000 0x2d000>, <0x32e2f000 0x1000>; ++ interrupt-parent = <&irqsteer>; ++ interrupts = <6>, <8>, <9>; ++ interrupt-names = "ctxld", "ctxld_kick", "vblank"; ++ clocks = <&clk IMX8MQ_CLK_DISP_APB_ROOT>, ++ <&clk IMX8MQ_CLK_DISP_AXI_ROOT>, ++ <&clk IMX8MQ_CLK_DISP_RTRM_ROOT>, ++ <&clk IMX8MQ_VIDEO2_PLL_OUT>, ++ <&clk IMX8MQ_CLK_DISP_DTRC>; ++ clock-names = "apb", "axi", "rtrm", "pix", "dtrc"; ++ assigned-clocks = <&clk IMX8MQ_CLK_DISP_AXI>, ++ <&clk IMX8MQ_CLK_DISP_RTRM>, ++ <&clk IMX8MQ_VIDEO2_PLL1_REF_SEL>; ++ assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_800M>, ++ <&clk IMX8MQ_SYS1_PLL_800M>, ++ <&clk IMX8MQ_CLK_27M>; ++ assigned-clock-rates = <800000000>, ++ <400000000>; ++ status = "disabled"; ++ ++ port { ++ dcss_out: endpoint { ++ remote-endpoint = <&mhdp_in>; ++ }; ++ }; ++ }; ++ + irqsteer: interrupt-controller@32e2d000 { + compatible = "fsl,imx8m-irqsteer", "fsl,imx-irqsteer"; + reg = <0x32e2d000 0x1000>; + +From patchwork Tue Dec 17 06:51:51 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [v20,9/9] arm64: dts: imx8mq: tqma8mq-mba8mx: Enable HDMI support +From: Sandor Yu +X-Patchwork-Id: 629296 +Message-Id: + +To: dmitry.baryshkov@linaro.org, andrzej.hajda@intel.com, + neil.armstrong@linaro.org, Laurent.pinchart@ideasonboard.com, + jonas@kwiboo.se, jernej.skrabec@gmail.com, airlied@gmail.com, + daniel@ffwll.ch, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + shawnguo@kernel.org, s.hauer@pengutronix.de, festevam@gmail.com, + vkoul@kernel.org, dri-devel@lists.freedesktop.org, + devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, + mripard@kernel.org +Cc: kernel@pengutronix.de, linux-imx@nxp.com, Sandor.yu@nxp.com, + oliver.brown@nxp.com, alexander.stein@ew.tq-group.com, sam@ravnborg.org +Date: Tue, 17 Dec 2024 14:51:51 +0800 + +From: Alexander Stein + +Add HDMI connector and connect it to MHDP output. Enable peripherals +for HDMI output. + +Signed-off-by: Alexander Stein +--- +v19->v20: + *No change + +v18->v19: +- Move property data-lanes to endpoint of port@1 + +v17->v18: +- replace lane-mapping with data-lanes + + .../dts/freescale/imx8mq-tqma8mq-mba8mx.dts | 26 +++++++++++++++++++ + arch/arm64/boot/dts/freescale/mba8mx.dtsi | 11 ++++++++ + 2 files changed, 37 insertions(+) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx.dts b/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx.dts +index 0165f3a259853..5ba06a411c6a1 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx.dts ++++ b/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq-mba8mx.dts +@@ -53,6 +53,10 @@ &btn2 { + gpios = <&gpio3 17 GPIO_ACTIVE_LOW>; + }; + ++&dcss { ++ status = "okay"; ++}; ++ + &gpio_leds { + led3 { + label = "led3"; +@@ -60,6 +64,14 @@ led3 { + }; + }; + ++&hdmi_connector { ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&mhdp_out>; ++ }; ++ }; ++}; ++ + &i2c1 { + expander2: gpio@25 { + compatible = "nxp,pca9555"; +@@ -91,6 +103,20 @@ &led2 { + gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>; + }; + ++&mhdp { ++ status = "okay"; ++ ports { ++ port@1 { ++ reg = <1>; ++ ++ mhdp_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ data-lanes = <0 1 2 3>; ++ }; ++ }; ++ }; ++}; ++ + /* PCIe slot on X36 */ + &pcie0 { + reset-gpio = <&expander0 14 GPIO_ACTIVE_LOW>; +diff --git a/arch/arm64/boot/dts/freescale/mba8mx.dtsi b/arch/arm64/boot/dts/freescale/mba8mx.dtsi +index 58e3865c28895..d04b75a76dfe6 100644 +--- a/arch/arm64/boot/dts/freescale/mba8mx.dtsi ++++ b/arch/arm64/boot/dts/freescale/mba8mx.dtsi +@@ -89,6 +89,17 @@ gpio_delays: gpio-delays { + gpio-line-names = "LVDS_BRIDGE_EN_1V8"; + }; + ++ hdmi_connector: connector { ++ compatible = "hdmi-connector"; ++ label = "X11"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ }; ++ }; ++ }; ++ + panel: panel-lvds { + /* + * Display is not fixed, so compatible has to be added from diff --git a/projects/NXP/devices/iMX8/patches/linux/0001-drm-bridge-mhdp-Add-cdns-mhdp-driver-bridge-driver.patch b/projects/NXP/devices/iMX8/patches/linux/0001-drm-bridge-mhdp-Add-cdns-mhdp-driver-bridge-driver.patch deleted file mode 100644 index e8af890e07..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0001-drm-bridge-mhdp-Add-cdns-mhdp-driver-bridge-driver.patch +++ /dev/null @@ -1,5933 +0,0 @@ -From c50c4f565797ac47544e1f0a2669d9cf1cb9d1c7 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Mon, 20 Apr 2020 23:01:50 +0800 -Subject: [PATCH 01/49] drm: bridge: mhdp: Add cdns mhdp driver bridge driver - -Base on rockchip cdn-dp-reg.c code, -create cdns mhdp DP API functions driver. -Move the driver to a separate directory. -Added HDMI/Audio/CEC API functions. - -Signed-off-by: Sandor Yu -[ Aisheng: fix conflict due to below commit -611e22b1d9f6 ("drm/rockchip: Remove unneeded semicolon") ] -Signed-off-by: Dong Aisheng ---- - drivers/gpu/drm/bridge/cadence/Kconfig | 26 + - drivers/gpu/drm/bridge/cadence/Makefile | 9 + - drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 574 +++++++++++ - .../gpu/drm/bridge/cadence/cdns-hdmi-core.c | 690 +++++++++++++ - .../gpu/drm/bridge/cadence/cdns-mhdp-audio.c | 395 +++++++ - .../gpu/drm/bridge/cadence/cdns-mhdp-cec.c | 341 +++++++ - .../gpu/drm/bridge/cadence/cdns-mhdp-common.c | 795 +++++++++++++++ - drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c | 172 ++++ - .../gpu/drm/bridge/cadence/cdns-mhdp-hdmi.c | 332 ++++++ - drivers/gpu/drm/bridge/cadence/cdns-mhdp.h | 209 ++++ - drivers/gpu/drm/rockchip/Makefile | 2 +- - drivers/gpu/drm/rockchip/cdn-dp-core.c | 241 ++--- - drivers/gpu/drm/rockchip/cdn-dp-core.h | 44 +- - drivers/gpu/drm/rockchip/cdn-dp-reg.c | 960 ------------------ - .../drm/bridge/cdns-mhdp.h | 389 ++++++- - 15 files changed, 4034 insertions(+), 1145 deletions(-) - create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-dp-core.c - create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c - create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c - create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c - create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c - create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c - create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdmi.c - create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp.h - delete mode 100644 drivers/gpu/drm/rockchip/cdn-dp-reg.c - rename drivers/gpu/drm/rockchip/cdn-dp-reg.h => include/drm/bridge/cdns-mhdp.h (53%) - -diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig -index ef8c230e0f62..bb1865b15aca 100644 ---- a/drivers/gpu/drm/bridge/cadence/Kconfig -+++ b/drivers/gpu/drm/bridge/cadence/Kconfig -@@ -22,3 +22,31 @@ config DRM_CDNS_MHDP8546_J721E - initializes the J721E Display Port and sets up the - clock and data muxes. - endif -+ -+config DRM_CDNS_MHDP -+ tristate "Cadence MHDP COMMON API driver" -+ select DRM_KMS_HELPER -+ select DRM_PANEL_BRIDGE -+ depends on OF -+ help -+ Support Cadence MHDP API library. -+ -+config DRM_CDNS_HDMI -+ tristate "Cadence HDMI DRM driver" -+ depends on DRM_CDNS_MHDP -+ select DRM_DISPLAY_HDCP_HELPER -+ select DRM_DISPLAY_HDMI_HELPER -+ -+config DRM_CDNS_DP -+ tristate "Cadence DP DRM driver" -+ depends on DRM_CDNS_MHDP -+ -+config DRM_CDNS_AUDIO -+ tristate "Cadence MHDP Audio driver" -+ depends on DRM_CDNS_MHDP -+ -+config DRM_CDNS_HDMI_CEC -+ tristate "Cadence MHDP HDMI CEC driver" -+ depends on DRM_CDNS_HDMI -+ select CEC_CORE -+ select CEC_NOTIFIER -diff --git a/drivers/gpu/drm/bridge/cadence/Makefile b/drivers/gpu/drm/bridge/cadence/Makefile -index 8f647991b374..618290870ba5 100644 ---- a/drivers/gpu/drm/bridge/cadence/Makefile -+++ b/drivers/gpu/drm/bridge/cadence/Makefile -@@ -4,4 +4,13 @@ - cdns-dsi-$(CONFIG_DRM_CDNS_DSI_J721E) += cdns-dsi-j721e.o - obj-$(CONFIG_DRM_CDNS_MHDP8546) += cdns-mhdp8546.o - cdns-mhdp8546-y := cdns-mhdp8546-core.o cdns-mhdp8546-hdcp.o - cdns-mhdp8546-$(CONFIG_DRM_CDNS_MHDP8546_J721E) += cdns-mhdp8546-j721e.o -+ -+cdns_mhdp_drmcore-y := cdns-mhdp-common.o cdns-mhdp-dp.o cdns-mhdp-hdmi.o -+ -+cdns_mhdp_drmcore-$(CONFIG_DRM_CDNS_HDMI) += cdns-hdmi-core.o -+cdns_mhdp_drmcore-$(CONFIG_DRM_CDNS_DP) += cdns-dp-core.o -+cdns_mhdp_drmcore-$(CONFIG_DRM_CDNS_AUDIO) += cdns-mhdp-audio.o -+cdns_mhdp_drmcore-$(CONFIG_DRM_CDNS_HDMI_CEC) += cdns-mhdp-cec.o -+ -+obj-$(CONFIG_DRM_CDNS_MHDP) += cdns_mhdp_drmcore.o -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -new file mode 100644 -index 000000000000..acb5c860da73 ---- /dev/null -+++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -@@ -0,0 +1,574 @@ -+/* -+ * Cadence Display Port Interface (DP) driver -+ * -+ * Copyright (C) 2019 NXP Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * This function only implements native DPDC reads and writes -+ */ -+static ssize_t dp_aux_transfer(struct drm_dp_aux *aux, -+ struct drm_dp_aux_msg *msg) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(aux->dev); -+ bool native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ); -+ int ret; -+ -+ /* Ignore address only message */ -+ if ((msg->size == 0) || (msg->buffer == NULL)) { -+ msg->reply = native ? -+ DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK; -+ return msg->size; -+ } -+ -+ if (!native) { -+ dev_err(mhdp->dev, "%s: only native messages supported\n", __func__); -+ return -EINVAL; -+ } -+ -+ /* msg sanity check */ -+ if (msg->size > DP_AUX_MAX_PAYLOAD_BYTES) { -+ dev_err(mhdp->dev, "%s: invalid msg: size(%zu), request(%x)\n", -+ __func__, msg->size, (unsigned int)msg->request); -+ return -EINVAL; -+ } -+ -+ if (msg->request == DP_AUX_NATIVE_WRITE) { -+ const u8 *buf = msg->buffer; -+ int i; -+ for (i = 0; i < msg->size; ++i) { -+ ret = cdns_mhdp_dpcd_write(mhdp, -+ msg->address + i, buf[i]); -+ if (!ret) -+ continue; -+ -+ DRM_DEV_ERROR(mhdp->dev, "Failed to write DPCD\n"); -+ -+ return ret; -+ } -+ } -+ -+ if (msg->request == DP_AUX_NATIVE_READ) { -+ ret = cdns_mhdp_dpcd_read(mhdp, msg->address, msg->buffer, msg->size); -+ if (ret < 0) -+ return -EIO; -+ msg->reply = DP_AUX_NATIVE_REPLY_ACK; -+ return msg->size; -+ } -+ return 0; -+} -+ -+static int dp_aux_init(struct cdns_mhdp_device *mhdp, -+ struct device *dev) -+{ -+ int ret; -+ -+ mhdp->dp.aux.name = "imx_dp_aux"; -+ mhdp->dp.aux.dev = dev; -+ mhdp->dp.aux.transfer = dp_aux_transfer; -+ -+ ret = drm_dp_aux_register(&mhdp->dp.aux); -+ -+ return ret; -+} -+ -+static int dp_aux_destroy(struct cdns_mhdp_device *mhdp) -+{ -+ drm_dp_aux_unregister(&mhdp->dp.aux); -+ return 0; -+} -+ -+static void dp_pixel_clk_reset(struct cdns_mhdp_device *mhdp) -+{ -+ u32 val; -+ -+ /* reset pixel clk */ -+ val = cdns_mhdp_reg_read(mhdp, SOURCE_HDTX_CAR); -+ cdns_mhdp_reg_write(mhdp, SOURCE_HDTX_CAR, val & 0xFD); -+ cdns_mhdp_reg_write(mhdp, SOURCE_HDTX_CAR, val); -+} -+ -+static void cdns_dp_mode_set(struct cdns_mhdp_device *mhdp) -+{ -+ u32 lane_mapping = mhdp->lane_mapping; -+ int ret; -+ -+ cdns_mhdp_plat_call(mhdp, pclk_rate); -+ -+ /* delay for DP FW stable after pixel clock relock */ -+ msleep(50); -+ -+ dp_pixel_clk_reset(mhdp); -+ -+ /* Get DP Caps */ -+ ret = drm_dp_dpcd_read(&mhdp->dp.aux, DP_DPCD_REV, mhdp->dp.dpcd, -+ DP_RECEIVER_CAP_SIZE); -+ if (ret < 0) { -+ DRM_ERROR("Failed to get caps %d\n", ret); -+ return; -+ } -+ -+ mhdp->dp.rate = drm_dp_max_link_rate(mhdp->dp.dpcd); -+ mhdp->dp.num_lanes = drm_dp_max_lane_count(mhdp->dp.dpcd); -+ -+ /* check the max link rate */ -+ if (mhdp->dp.rate > CDNS_DP_MAX_LINK_RATE) -+ mhdp->dp.rate = CDNS_DP_MAX_LINK_RATE; -+ -+ /* Initialize link rate/num_lanes as panel max link rate/max_num_lanes */ -+ cdns_mhdp_plat_call(mhdp, phy_set); -+ -+ /* Video off */ -+ ret = cdns_mhdp_set_video_status(mhdp, CONTROL_VIDEO_IDLE); -+ if (ret) { -+ DRM_DEV_ERROR(mhdp->dev, "Failed to valid video %d\n", ret); -+ return; -+ } -+ -+ /* Line swaping */ -+ cdns_mhdp_reg_write(mhdp, LANES_CONFIG, 0x00400000 | lane_mapping); -+ -+ /* Set DP host capability */ -+ ret = cdns_mhdp_set_host_cap(mhdp, false); -+ if (ret) { -+ DRM_DEV_ERROR(mhdp->dev, "Failed to set host cap %d\n", ret); -+ return; -+ } -+ -+ ret = cdns_mhdp_config_video(mhdp); -+ if (ret) { -+ DRM_DEV_ERROR(mhdp->dev, "Failed to config video %d\n", ret); -+ return; -+ } -+ -+ return; -+} -+ -+/* ----------------------------------------------------------------------------- -+ * dp TX Setup -+ */ -+static enum drm_connector_status -+cdns_dp_connector_detect(struct drm_connector *connector, bool force) -+{ -+ struct cdns_mhdp_device *mhdp = container_of(connector, -+ struct cdns_mhdp_device, connector.base); -+ u8 hpd = 0xf; -+ -+ hpd = cdns_mhdp_read_hpd(mhdp); -+ if (hpd == 1) -+ /* Cable Connected */ -+ return connector_status_connected; -+ else if (hpd == 0) -+ /* Cable Disconnedted */ -+ return connector_status_disconnected; -+ else { -+ /* Cable status unknown */ -+ DRM_INFO("Unknow cable status, hdp=%u\n", hpd); -+ return connector_status_unknown; -+ } -+} -+ -+static int cdns_dp_connector_get_modes(struct drm_connector *connector) -+{ -+ struct cdns_mhdp_device *mhdp = container_of(connector, -+ struct cdns_mhdp_device, connector.base); -+ int num_modes = 0; -+ struct edid *edid; -+ -+ edid = drm_do_get_edid(&mhdp->connector.base, -+ cdns_mhdp_get_edid_block, mhdp); -+ if (edid) { -+ dev_info(mhdp->dev, "%x,%x,%x,%x,%x,%x,%x,%x\n", -+ edid->header[0], edid->header[1], -+ edid->header[2], edid->header[3], -+ edid->header[4], edid->header[5], -+ edid->header[6], edid->header[7]); -+ drm_connector_update_edid_property(connector, edid); -+ num_modes = drm_add_edid_modes(connector, edid); -+ kfree(edid); -+ } -+ -+ if (num_modes == 0) -+ DRM_ERROR("Invalid edid\n"); -+ return num_modes; -+} -+ -+static const struct drm_connector_funcs cdns_dp_connector_funcs = { -+ .fill_modes = drm_helper_probe_single_connector_modes, -+ .detect = cdns_dp_connector_detect, -+ .destroy = drm_connector_cleanup, -+ .reset = drm_atomic_helper_connector_reset, -+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -+}; -+ -+static const struct drm_connector_helper_funcs cdns_dp_connector_helper_funcs = { -+ .get_modes = cdns_dp_connector_get_modes, -+}; -+ -+static int cdns_dp_bridge_attach(struct drm_bridge *bridge, -+ enum drm_bridge_attach_flags flags) -+{ -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ struct drm_encoder *encoder = bridge->encoder; -+ struct drm_connector *connector = &mhdp->connector.base; -+ -+ connector->interlace_allowed = 1; -+ -+ if (mhdp->is_hpd) -+ connector->polled = DRM_CONNECTOR_POLL_HPD; -+ else -+ connector->polled = DRM_CONNECTOR_POLL_CONNECT | -+ DRM_CONNECTOR_POLL_DISCONNECT; -+ -+ drm_connector_helper_add(connector, &cdns_dp_connector_helper_funcs); -+ -+ drm_connector_init(bridge->dev, connector, &cdns_dp_connector_funcs, -+ DRM_MODE_CONNECTOR_DisplayPort); -+ -+ drm_connector_attach_encoder(connector, encoder); -+ -+ return 0; -+} -+ -+static enum drm_mode_status -+cdns_dp_bridge_mode_valid(struct drm_bridge *bridge, -+ const struct drm_display_mode *mode) -+{ -+ enum drm_mode_status mode_status = MODE_OK; -+ -+ /* We don't support double-clocked modes */ -+ if (mode->flags & DRM_MODE_FLAG_DBLCLK || -+ mode->flags & DRM_MODE_FLAG_INTERLACE) -+ return MODE_BAD; -+ -+ /* MAX support pixel clock rate 594MHz */ -+ if (mode->clock > 594000) -+ return MODE_CLOCK_HIGH; -+ -+ /* 4096x2160 is not supported now */ -+ if (mode->hdisplay > 3840) -+ return MODE_BAD_HVALUE; -+ -+ if (mode->vdisplay > 2160) -+ return MODE_BAD_VVALUE; -+ -+ return mode_status; -+} -+ -+static void cdns_dp_bridge_mode_set(struct drm_bridge *bridge, -+ const struct drm_display_mode *orig_mode, -+ const struct drm_display_mode *mode) -+{ -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ struct drm_display_info *display_info = &mhdp->connector.base.display_info; -+ struct video_info *video = &mhdp->video_info; -+ -+ switch (display_info->bpc) { -+ case 10: -+ video->color_depth = 10; -+ break; -+ case 6: -+ video->color_depth = 6; -+ break; -+ default: -+ video->color_depth = 8; -+ break; -+ } -+ -+ video->color_fmt = PXL_RGB; -+ video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); -+ video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); -+ -+ DRM_INFO("Mode: %dx%dp%d\n", mode->hdisplay, mode->vdisplay, mode->clock); -+ memcpy(&mhdp->mode, mode, sizeof(struct drm_display_mode)); -+ -+ mutex_lock(&mhdp->lock); -+ cdns_dp_mode_set(mhdp); -+ mutex_unlock(&mhdp->lock); -+ -+ /* reset force mode set flag */ -+ mhdp->force_mode_set = false; -+} -+ -+static void cdn_dp_bridge_enable(struct drm_bridge *bridge) -+{ -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ int ret; -+ -+ /* Link trainning */ -+ ret = cdns_mhdp_train_link(mhdp); -+ if (ret) { -+ DRM_DEV_ERROR(mhdp->dev, "Failed link train %d\n", ret); -+ return; -+ } -+ -+ ret = cdns_mhdp_set_video_status(mhdp, CONTROL_VIDEO_VALID); -+ if (ret) { -+ DRM_DEV_ERROR(mhdp->dev, "Failed to valid video %d\n", ret); -+ return; -+ } -+} -+ -+static void cdn_dp_bridge_disable(struct drm_bridge *bridge) -+{ -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ -+ cdns_mhdp_set_video_status(mhdp, CONTROL_VIDEO_IDLE); -+} -+ -+static const struct drm_bridge_funcs cdns_dp_bridge_funcs = { -+ .attach = cdns_dp_bridge_attach, -+ .enable = cdn_dp_bridge_enable, -+ .disable = cdn_dp_bridge_disable, -+ .mode_set = cdns_dp_bridge_mode_set, -+ .mode_valid = cdns_dp_bridge_mode_valid, -+}; -+ -+static void hotplug_work_func(struct work_struct *work) -+{ -+ struct cdns_mhdp_device *mhdp = container_of(work, -+ struct cdns_mhdp_device, hotplug_work.work); -+ struct drm_connector *connector = &mhdp->connector.base; -+ -+ drm_helper_hpd_irq_event(connector->dev); -+ -+ if (connector->status == connector_status_connected) { -+ /* Cable connedted */ -+ DRM_INFO("HDMI/DP Cable Plug In\n"); -+ enable_irq(mhdp->irq[IRQ_OUT]); -+ } else if (connector->status == connector_status_disconnected) { -+ /* Cable Disconnedted */ -+ DRM_INFO("HDMI/DP Cable Plug Out\n"); -+ /* force mode set for cable replugin to recovery DP video modes */ -+ mhdp->force_mode_set = true; -+ enable_irq(mhdp->irq[IRQ_IN]); -+ } -+} -+ -+static irqreturn_t cdns_dp_irq_thread(int irq, void *data) -+{ -+ struct cdns_mhdp_device *mhdp = data; -+ -+ disable_irq_nosync(irq); -+ -+ mod_delayed_work(system_wq, &mhdp->hotplug_work, -+ msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS)); -+ -+ return IRQ_HANDLED; -+} -+ -+static void cdns_dp_parse_dt(struct cdns_mhdp_device *mhdp) -+{ -+ struct device_node *of_node = mhdp->dev->of_node; -+ int ret; -+ -+ ret = of_property_read_u32(of_node, "lane-mapping", -+ &mhdp->lane_mapping); -+ if (ret) { -+ mhdp->lane_mapping = 0xc6; -+ dev_warn(mhdp->dev, "Failed to get lane_mapping - using default 0xc6\n"); -+ } -+ dev_info(mhdp->dev, "lane-mapping 0x%02x\n", mhdp->lane_mapping); -+} -+ -+static int __cdns_dp_probe(struct platform_device *pdev, -+ struct cdns_mhdp_device *mhdp) -+{ -+ struct device *dev = &pdev->dev; -+ struct resource *iores = NULL; -+ int ret; -+ -+ mutex_init(&mhdp->lock); -+ mutex_init(&mhdp->iolock); -+ -+ INIT_DELAYED_WORK(&mhdp->hotplug_work, hotplug_work_func); -+ -+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (iores) { -+ mhdp->regs_base = devm_ioremap(dev, iores->start, -+ resource_size(iores)); -+ if (IS_ERR(mhdp->regs_base)) -+ return -ENOMEM; -+ } -+ -+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ if (iores) { -+ mhdp->regs_sec = devm_ioremap(dev, iores->start, -+ resource_size(iores)); -+ if (IS_ERR(mhdp->regs_sec)) -+ return -ENOMEM; -+ } -+ -+ mhdp->is_hpd = true; -+ mhdp->is_ls1028a = false; -+ -+ mhdp->irq[IRQ_IN] = platform_get_irq_byname(pdev, "plug_in"); -+ if (mhdp->irq[IRQ_IN] < 0) { -+ mhdp->is_hpd = false; -+ dev_info(dev, "No plug_in irq number\n"); -+ } -+ -+ mhdp->irq[IRQ_OUT] = platform_get_irq_byname(pdev, "plug_out"); -+ if (mhdp->irq[IRQ_OUT] < 0) { -+ mhdp->is_hpd = false; -+ dev_info(dev, "No plug_out irq number\n"); -+ } -+ -+ cdns_dp_parse_dt(mhdp); -+ -+ if (of_device_is_compatible(dev->of_node, "cdn,ls1028a-dp")) -+ mhdp->is_ls1028a = true; -+ -+ cdns_mhdp_plat_call(mhdp, power_on); -+ -+ cdns_mhdp_plat_call(mhdp, firmware_init); -+ -+ /* DP FW alive check */ -+ ret = cdns_mhdp_check_alive(mhdp); -+ if (ret == false) { -+ DRM_ERROR("NO dp FW running\n"); -+ return -ENXIO; -+ } -+ -+ /* DP PHY init before AUX init */ -+ cdns_mhdp_plat_call(mhdp, phy_set); -+ -+ /* Enable Hotplug Detect IRQ thread */ -+ if (mhdp->is_hpd) { -+ irq_set_status_flags(mhdp->irq[IRQ_IN], IRQ_NOAUTOEN); -+ ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_IN], -+ NULL, cdns_dp_irq_thread, -+ IRQF_ONESHOT, dev_name(dev), -+ mhdp); -+ -+ if (ret) { -+ dev_err(dev, "can't claim irq %d\n", -+ mhdp->irq[IRQ_IN]); -+ return -EINVAL; -+ } -+ -+ irq_set_status_flags(mhdp->irq[IRQ_OUT], IRQ_NOAUTOEN); -+ ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_OUT], -+ NULL, cdns_dp_irq_thread, -+ IRQF_ONESHOT, dev_name(dev), -+ mhdp); -+ -+ if (ret) { -+ dev_err(dev, "can't claim irq %d\n", -+ mhdp->irq[IRQ_OUT]); -+ return -EINVAL; -+ } -+ -+ if (cdns_mhdp_read_hpd(mhdp)) -+ enable_irq(mhdp->irq[IRQ_OUT]); -+ else -+ enable_irq(mhdp->irq[IRQ_IN]); -+ } -+ -+ mhdp->bridge.base.driver_private = mhdp; -+ mhdp->bridge.base.funcs = &cdns_dp_bridge_funcs; -+#ifdef CONFIG_OF -+ mhdp->bridge.base.of_node = dev->of_node; -+#endif -+ -+ dev_set_drvdata(dev, mhdp); -+ -+ /* register audio driver */ -+ cdns_mhdp_register_audio_driver(dev); -+ -+ dp_aux_init(mhdp, dev); -+ -+ return 0; -+} -+ -+static void __cdns_dp_remove(struct cdns_mhdp_device *mhdp) -+{ -+ dp_aux_destroy(mhdp); -+ cdns_mhdp_unregister_audio_driver(mhdp->dev); -+} -+ -+/* ----------------------------------------------------------------------------- -+ * Probe/remove API, used from platforms based on the DRM bridge API. -+ */ -+int cdns_dp_probe(struct platform_device *pdev, -+ struct cdns_mhdp_device *mhdp) -+{ -+ int ret; -+ -+ ret = __cdns_dp_probe(pdev, mhdp); -+ if (ret) -+ return ret; -+ -+ drm_bridge_add(&mhdp->bridge.base); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(cdns_dp_probe); -+ -+void cdns_dp_remove(struct platform_device *pdev) -+{ -+ struct cdns_mhdp_device *mhdp = platform_get_drvdata(pdev); -+ -+ drm_bridge_remove(&mhdp->bridge.base); -+ -+ __cdns_dp_remove(mhdp); -+} -+EXPORT_SYMBOL_GPL(cdns_dp_remove); -+ -+/* ----------------------------------------------------------------------------- -+ * Bind/unbind API, used from platforms based on the component framework. -+ */ -+int cdns_dp_bind(struct platform_device *pdev, struct drm_encoder *encoder, -+ struct cdns_mhdp_device *mhdp) -+{ -+ int ret; -+ -+ ret = __cdns_dp_probe(pdev, mhdp); -+ if (ret < 0) -+ return ret; -+ -+ ret = drm_bridge_attach(encoder, &mhdp->bridge.base, NULL, 0); -+ if (ret) { -+ cdns_dp_remove(pdev); -+ DRM_ERROR("Failed to initialize bridge with drm\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(cdns_dp_bind); -+ -+void cdns_dp_unbind(struct device *dev) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ -+ __cdns_dp_remove(mhdp); -+} -+EXPORT_SYMBOL_GPL(cdns_dp_unbind); -+ -+MODULE_AUTHOR("Sandor Yu "); -+MODULE_DESCRIPTION("Cadence Display Port transmitter driver"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:cdn-dp"); -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -new file mode 100644 -index 000000000000..da40f62617ef ---- /dev/null -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -0,0 +1,690 @@ -+/* -+ * Cadence High-Definition Multimedia Interface (HDMI) driver -+ * -+ * Copyright (C) 2019 NXP Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static void hdmi_sink_config(struct cdns_mhdp_device *mhdp) -+{ -+ struct drm_scdc *scdc = &mhdp->connector.base.display_info.hdmi.scdc; -+ u8 buff = 0; -+ -+ /* Default work in HDMI1.4 */ -+ mhdp->hdmi.hdmi_type = MODE_HDMI_1_4; -+ -+ /* check sink support SCDC or not */ -+ if (scdc->supported != true) { -+ DRM_INFO("Sink Not Support SCDC\n"); -+ return; -+ } -+ -+ if (mhdp->hdmi.char_rate > 340000) { -+ /* -+ * TMDS Character Rate above 340MHz should working in HDMI2.0 -+ * Enable scrambling and TMDS_Bit_Clock_Ratio -+ */ -+ buff = SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE; -+ mhdp->hdmi.hdmi_type = MODE_HDMI_2_0; -+ } else if (scdc->scrambling.low_rates) { -+ /* -+ * Enable scrambling and HDMI2.0 when scrambling capability of sink -+ * be indicated in the HF-VSDB LTE_340Mcsc_scramble bit -+ */ -+ buff = SCDC_SCRAMBLING_ENABLE; -+ mhdp->hdmi.hdmi_type = MODE_HDMI_2_0; -+ } -+ -+ /* TMDS config */ -+ cdns_hdmi_scdc_write(mhdp, 0x20, buff); -+} -+ -+static void hdmi_lanes_config(struct cdns_mhdp_device *mhdp) -+{ -+ /* Line swaping */ -+ cdns_mhdp_reg_write(mhdp, LANES_CONFIG, 0x00400000 | mhdp->lane_mapping); -+} -+ -+static int hdmi_avi_info_set(struct cdns_mhdp_device *mhdp, -+ struct drm_display_mode *mode) -+{ -+ struct hdmi_avi_infoframe frame; -+ int format = mhdp->video_info.color_fmt; -+ struct drm_connector_state *conn_state = mhdp->connector.base.state; -+ struct drm_display_mode *adj_mode; -+ enum hdmi_quantization_range qr; -+ u8 buf[32]; -+ int ret; -+ -+ /* Initialise info frame from DRM mode */ -+ drm_hdmi_avi_infoframe_from_display_mode(&frame, &mhdp->connector.base, -+ mode); -+ -+ switch (format) { -+ case YCBCR_4_4_4: -+ frame.colorspace = HDMI_COLORSPACE_YUV444; -+ break; -+ case YCBCR_4_2_2: -+ frame.colorspace = HDMI_COLORSPACE_YUV422; -+ break; -+ case YCBCR_4_2_0: -+ frame.colorspace = HDMI_COLORSPACE_YUV420; -+ break; -+ default: -+ frame.colorspace = HDMI_COLORSPACE_RGB; -+ break; -+ } -+ -+ drm_hdmi_avi_infoframe_colorimetry(&frame, conn_state); -+ -+ adj_mode = &mhdp->bridge.base.encoder->crtc->state->adjusted_mode; -+ -+ qr = drm_default_rgb_quant_range(adj_mode); -+ -+ drm_hdmi_avi_infoframe_quant_range(&frame, &mhdp->connector.base, -+ adj_mode, qr); -+ -+ ret = hdmi_avi_infoframe_check(&frame); -+ if (WARN_ON(ret)) -+ return false; -+ -+ ret = hdmi_avi_infoframe_pack(&frame, buf + 1, sizeof(buf) - 1); -+ if (ret < 0) { -+ DRM_ERROR("failed to pack AVI infoframe: %d\n", ret); -+ return -1; -+ } -+ -+ buf[0] = 0; -+ cdns_mhdp_infoframe_set(mhdp, 0, sizeof(buf), buf, HDMI_INFOFRAME_TYPE_AVI); -+ return 0; -+} -+ -+static void hdmi_vendor_info_set(struct cdns_mhdp_device *mhdp, -+ struct drm_display_mode *mode) -+{ -+ struct hdmi_vendor_infoframe frame; -+ u8 buf[32]; -+ int ret; -+ -+ /* Initialise vendor frame from DRM mode */ -+ ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame, &mhdp->connector.base, mode); -+ if (ret < 0) { -+ DRM_INFO("No vendor infoframe\n"); -+ return; -+ } -+ -+ ret = hdmi_vendor_infoframe_pack(&frame, buf + 1, sizeof(buf) - 1); -+ if (ret < 0) { -+ DRM_WARN("Unable to pack vendor infoframe: %d\n", ret); -+ return; -+ } -+ -+ buf[0] = 0; -+ cdns_mhdp_infoframe_set(mhdp, 3, sizeof(buf), buf, HDMI_INFOFRAME_TYPE_VENDOR); -+} -+ -+static void hdmi_drm_info_set(struct cdns_mhdp_device *mhdp) -+{ -+ struct drm_connector_state *conn_state; -+ struct hdmi_drm_infoframe frame; -+ u8 buf[32]; -+ int ret; -+ -+ conn_state = mhdp->connector.base.state; -+ -+ if (!conn_state->hdr_output_metadata) -+ return; -+ -+ ret = drm_hdmi_infoframe_set_hdr_metadata(&frame, conn_state); -+ if (ret < 0) { -+ DRM_DEBUG_KMS("couldn't set HDR metadata in infoframe\n"); -+ return; -+ } -+ -+ ret = hdmi_drm_infoframe_pack(&frame, buf + 1, sizeof(buf) - 1); -+ if (ret < 0) { -+ DRM_DEBUG_KMS("couldn't pack HDR infoframe\n"); -+ return; -+ } -+ -+ buf[0] = 0; -+ cdns_mhdp_infoframe_set(mhdp, 3, sizeof(buf), -+ buf, HDMI_INFOFRAME_TYPE_DRM); -+} -+ -+void cdns_hdmi_mode_set(struct cdns_mhdp_device *mhdp) -+{ -+ struct drm_display_mode *mode = &mhdp->mode; -+ int ret; -+ -+ /* video mode valid check */ -+ if (mode->clock == 0 || mode->hdisplay == 0 || mode->vdisplay == 0) -+ return; -+ -+ hdmi_lanes_config(mhdp); -+ -+ cdns_mhdp_plat_call(mhdp, pclk_rate); -+ -+ /* delay for HDMI FW stable after pixel clock relock */ -+ msleep(20); -+ -+ cdns_mhdp_plat_call(mhdp, phy_set); -+ -+ hdmi_sink_config(mhdp); -+ -+ ret = cdns_hdmi_ctrl_init(mhdp, mhdp->hdmi.hdmi_type, mhdp->hdmi.char_rate); -+ if (ret < 0) { -+ DRM_ERROR("%s, ret = %d\n", __func__, ret); -+ return; -+ } -+ -+ /* Config GCP */ -+ if (mhdp->video_info.color_depth == 8) -+ cdns_hdmi_disable_gcp(mhdp); -+ else -+ cdns_hdmi_enable_gcp(mhdp); -+ -+ ret = hdmi_avi_info_set(mhdp, mode); -+ if (ret < 0) { -+ DRM_ERROR("%s ret = %d\n", __func__, ret); -+ return; -+ } -+ -+ /* vendor info frame is enable only when HDMI1.4 4K mode */ -+ hdmi_vendor_info_set(mhdp, mode); -+ -+ hdmi_drm_info_set(mhdp); -+ -+ ret = cdns_hdmi_mode_config(mhdp, mode, &mhdp->video_info); -+ if (ret < 0) { -+ DRM_ERROR("CDN_API_HDMITX_SetVic_blocking ret = %d\n", ret); -+ return; -+ } -+} -+ -+static enum drm_connector_status -+cdns_hdmi_connector_detect(struct drm_connector *connector, bool force) -+{ -+ struct cdns_mhdp_device *mhdp = -+ container_of(connector, struct cdns_mhdp_device, connector.base); -+ -+ u8 hpd = 0xf; -+ -+ hpd = cdns_mhdp_read_hpd(mhdp); -+ -+ if (hpd == 1) -+ /* Cable Connected */ -+ return connector_status_connected; -+ else if (hpd == 0) -+ /* Cable Disconnedted */ -+ return connector_status_disconnected; -+ else { -+ /* Cable status unknown */ -+ DRM_INFO("Unknow cable status, hdp=%u\n", hpd); -+ return connector_status_unknown; -+ } -+} -+ -+static int cdns_hdmi_connector_get_modes(struct drm_connector *connector) -+{ -+ struct cdns_mhdp_device *mhdp = -+ container_of(connector, struct cdns_mhdp_device, connector.base); -+ int num_modes = 0; -+ struct edid *edid; -+ -+ edid = drm_do_get_edid(&mhdp->connector.base, -+ cdns_hdmi_get_edid_block, mhdp); -+ if (edid) { -+ dev_info(mhdp->dev, "%x,%x,%x,%x,%x,%x,%x,%x\n", -+ edid->header[0], edid->header[1], -+ edid->header[2], edid->header[3], -+ edid->header[4], edid->header[5], -+ edid->header[6], edid->header[7]); -+ drm_connector_update_edid_property(connector, edid); -+ num_modes = drm_add_edid_modes(connector, edid); -+ kfree(edid); -+ } -+ -+ if (num_modes == 0) -+ DRM_ERROR("Invalid edid\n"); -+ return num_modes; -+} -+ -+static bool blob_equal(const struct drm_property_blob *a, -+ const struct drm_property_blob *b) -+{ -+ if (a && b) -+ return a->length == b->length && -+ !memcmp(a->data, b->data, a->length); -+ -+ return !a == !b; -+} -+ -+static int cdns_hdmi_connector_atomic_check(struct drm_connector *connector, -+ struct drm_atomic_state *state) -+{ -+ struct drm_connector_state *new_con_state = -+ drm_atomic_get_new_connector_state(state, connector); -+ struct drm_connector_state *old_con_state = -+ drm_atomic_get_old_connector_state(state, connector); -+ struct drm_crtc *crtc = new_con_state->crtc; -+ struct drm_crtc_state *new_crtc_state; -+ -+ if (!blob_equal(new_con_state->hdr_output_metadata, -+ old_con_state->hdr_output_metadata) || -+ new_con_state->colorspace != old_con_state->colorspace) { -+ new_crtc_state = drm_atomic_get_crtc_state(state, crtc); -+ if (IS_ERR(new_crtc_state)) -+ return PTR_ERR(new_crtc_state); -+ -+ new_crtc_state->mode_changed = -+ !new_con_state->hdr_output_metadata || -+ !old_con_state->hdr_output_metadata || -+ new_con_state->colorspace != old_con_state->colorspace; -+ } -+ -+ return 0; -+} -+ -+static const struct drm_connector_funcs cdns_hdmi_connector_funcs = { -+ .fill_modes = drm_helper_probe_single_connector_modes, -+ .detect = cdns_hdmi_connector_detect, -+ .destroy = drm_connector_cleanup, -+ .reset = drm_atomic_helper_connector_reset, -+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -+}; -+ -+static const struct drm_connector_helper_funcs cdns_hdmi_connector_helper_funcs = { -+ .get_modes = cdns_hdmi_connector_get_modes, -+ .atomic_check = cdns_hdmi_connector_atomic_check, -+}; -+ -+static int cdns_hdmi_bridge_attach(struct drm_bridge *bridge, -+ enum drm_bridge_attach_flags flags) -+{ -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ struct drm_mode_config *config = &bridge->dev->mode_config; -+ struct drm_encoder *encoder = bridge->encoder; -+ struct drm_connector *connector = &mhdp->connector.base; -+ -+ connector->interlace_allowed = 1; -+ connector->polled = DRM_CONNECTOR_POLL_HPD; -+ -+ drm_connector_helper_add(connector, &cdns_hdmi_connector_helper_funcs); -+ -+ drm_connector_init(bridge->dev, connector, &cdns_hdmi_connector_funcs, -+ DRM_MODE_CONNECTOR_HDMIA); -+ -+ if (!strncmp("imx8mq-hdmi", mhdp->plat_data->plat_name, 11)) { -+ drm_object_attach_property(&connector->base, -+ config->hdr_output_metadata_property, -+ 0); -+ -+ if (!drm_mode_create_hdmi_colorspace_property(connector, 0)) -+ drm_object_attach_property(&connector->base, -+ connector->colorspace_property, -+ 0); -+ } -+ -+ drm_connector_attach_encoder(connector, encoder); -+ -+ return 0; -+} -+ -+static enum drm_mode_status -+cdns_hdmi_bridge_mode_valid(struct drm_bridge *bridge, -+ const struct drm_display_mode *mode) -+{ -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ enum drm_mode_status mode_status = MODE_OK; -+ int ret; -+ -+ /* We don't support double-clocked and Interlaced modes */ -+ if (mode->flags & DRM_MODE_FLAG_DBLCLK || -+ mode->flags & DRM_MODE_FLAG_INTERLACE) -+ return MODE_BAD; -+ -+ /* MAX support pixel clock rate 594MHz */ -+ if (mode->clock > 594000) -+ return MODE_CLOCK_HIGH; -+ -+ /* 4096x2160 is not supported */ -+ if (mode->hdisplay > 3840 || mode->vdisplay > 2160) -+ return MODE_BAD_HVALUE; -+ -+ mhdp->valid_mode = mode; -+ ret = cdns_mhdp_plat_call(mhdp, phy_video_valid); -+ if (ret == false) -+ return MODE_CLOCK_RANGE; -+ -+ return mode_status; -+} -+ -+static void cdns_hdmi_bridge_mode_set(struct drm_bridge *bridge, -+ const struct drm_display_mode *orig_mode, -+ const struct drm_display_mode *mode) -+{ -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ struct video_info *video = &mhdp->video_info; -+ -+ video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); -+ video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); -+ -+ DRM_INFO("Mode: %dx%dp%d\n", mode->hdisplay, mode->vdisplay, mode->clock); -+ memcpy(&mhdp->mode, mode, sizeof(struct drm_display_mode)); -+ -+ mutex_lock(&mhdp->lock); -+ cdns_hdmi_mode_set(mhdp); -+ mutex_unlock(&mhdp->lock); -+ /* reset force mode set flag */ -+ mhdp->force_mode_set = false; -+} -+ -+bool cdns_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, -+ const struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ struct drm_display_info *di = &mhdp->connector.base.display_info; -+ struct video_info *video = &mhdp->video_info; -+ int vic = drm_match_cea_mode(mode); -+ -+ video->color_depth = 8; -+ video->color_fmt = PXL_RGB; -+ -+ /* for all other platforms, other than imx8mq */ -+ if (strncmp("imx8mq-hdmi", mhdp->plat_data->plat_name, 11)) { -+ if (di->bpc == 10 || di->bpc == 6) -+ video->color_depth = di->bpc; -+ -+ return true; -+ } -+ -+ /* imx8mq */ -+ if (vic == 97 || vic == 96) { -+ if (di->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36) -+ video->color_depth = 12; -+ else if (di->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) -+ video->color_depth = 10; -+ -+ if (drm_mode_is_420_only(di, mode) || -+ (drm_mode_is_420_also(di, mode) && -+ video->color_depth > 8)) { -+ video->color_fmt = YCBCR_4_2_0; -+ -+ adjusted_mode->private_flags = 1; -+ return true; -+ } -+ -+ video->color_depth = 8; -+ return true; -+ } -+ -+ /* Any defined maximum tmds clock limit we must not exceed*/ -+ if ((di->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36) && -+ (mode->clock * 3 / 2 <= di->max_tmds_clock)) -+ video->color_depth = 12; -+ else if ((di->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) && -+ (mode->clock * 5 / 4 <= di->max_tmds_clock)) -+ video->color_depth = 10; -+ -+ /* 10-bit color depth for the following modes is not supported */ -+ if ((vic == 95 || vic == 94 || vic == 93) && video->color_depth == 10) -+ video->color_depth = 8; -+ -+ return true; -+} -+ -+static const struct drm_bridge_funcs cdns_hdmi_bridge_funcs = { -+ .attach = cdns_hdmi_bridge_attach, -+ .mode_set = cdns_hdmi_bridge_mode_set, -+ .mode_valid = cdns_hdmi_bridge_mode_valid, -+ .mode_fixup = cdns_hdmi_bridge_mode_fixup, -+}; -+ -+static void hotplug_work_func(struct work_struct *work) -+{ -+ struct cdns_mhdp_device *mhdp = container_of(work, -+ struct cdns_mhdp_device, hotplug_work.work); -+ struct drm_connector *connector = &mhdp->connector.base; -+ -+ drm_helper_hpd_irq_event(connector->dev); -+ -+ if (connector->status == connector_status_connected) { -+ DRM_INFO("HDMI Cable Plug In\n"); -+ mhdp->force_mode_set = true; -+ enable_irq(mhdp->irq[IRQ_OUT]); -+ } else if (connector->status == connector_status_disconnected) { -+ /* Cable Disconnedted */ -+ DRM_INFO("HDMI Cable Plug Out\n"); -+ /* force mode set for cable replugin to recovery HDMI2.0 video modes */ -+ mhdp->force_mode_set = true; -+ enable_irq(mhdp->irq[IRQ_IN]); -+ } -+} -+ -+static irqreturn_t cdns_hdmi_irq_thread(int irq, void *data) -+{ -+ struct cdns_mhdp_device *mhdp = data; -+ -+ disable_irq_nosync(irq); -+ -+ mod_delayed_work(system_wq, &mhdp->hotplug_work, -+ msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS)); -+ -+ return IRQ_HANDLED; -+} -+ -+static void cdns_hdmi_parse_dt(struct cdns_mhdp_device *mhdp) -+{ -+ struct device_node *of_node = mhdp->dev->of_node; -+ int ret; -+ -+ ret = of_property_read_u32(of_node, "lane-mapping", &mhdp->lane_mapping); -+ if (ret) { -+ mhdp->lane_mapping = 0xc6; -+ dev_warn(mhdp->dev, "Failed to get lane_mapping - using default 0xc6\n"); -+ } -+ dev_info(mhdp->dev, "lane-mapping 0x%02x\n", mhdp->lane_mapping); -+} -+ -+static int __cdns_hdmi_probe(struct platform_device *pdev, -+ struct cdns_mhdp_device *mhdp) -+{ -+ struct device *dev = &pdev->dev; -+ struct platform_device_info pdevinfo; -+ struct resource *iores = NULL; -+ int ret; -+ -+ mutex_init(&mhdp->lock); -+ mutex_init(&mhdp->iolock); -+ -+ INIT_DELAYED_WORK(&mhdp->hotplug_work, hotplug_work_func); -+ -+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ mhdp->regs_base = devm_ioremap(dev, iores->start, resource_size(iores)); -+ if (IS_ERR(mhdp->regs_base)) { -+ dev_err(dev, "No regs_base memory\n"); -+ return -ENOMEM; -+ } -+ -+ /* sec register base */ -+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ mhdp->regs_sec = devm_ioremap(dev, iores->start, resource_size(iores)); -+ if (IS_ERR(mhdp->regs_sec)) { -+ dev_err(dev, "No regs_sec memory\n"); -+ return -ENOMEM; -+ } -+ -+ mhdp->irq[IRQ_IN] = platform_get_irq_byname(pdev, "plug_in"); -+ if (mhdp->irq[IRQ_IN] < 0) { -+ dev_info(dev, "No plug_in irq number\n"); -+ return -EPROBE_DEFER; -+ } -+ -+ mhdp->irq[IRQ_OUT] = platform_get_irq_byname(pdev, "plug_out"); -+ if (mhdp->irq[IRQ_OUT] < 0) { -+ dev_info(dev, "No plug_out irq number\n"); -+ return -EPROBE_DEFER; -+ } -+ -+ cdns_mhdp_plat_call(mhdp, power_on); -+ -+ /* Initialize FW */ -+ cdns_mhdp_plat_call(mhdp, firmware_init); -+ -+ /* HDMI FW alive check */ -+ ret = cdns_mhdp_check_alive(mhdp); -+ if (ret == false) { -+ dev_err(dev, "NO HDMI FW running\n"); -+ return -ENXIO; -+ } -+ -+ /* Enable Hotplug Detect thread */ -+ irq_set_status_flags(mhdp->irq[IRQ_IN], IRQ_NOAUTOEN); -+ ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_IN], -+ NULL, cdns_hdmi_irq_thread, -+ IRQF_ONESHOT, dev_name(dev), -+ mhdp); -+ if (ret < 0) { -+ dev_err(dev, "can't claim irq %d\n", -+ mhdp->irq[IRQ_IN]); -+ return -EINVAL; -+ } -+ -+ irq_set_status_flags(mhdp->irq[IRQ_OUT], IRQ_NOAUTOEN); -+ ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_OUT], -+ NULL, cdns_hdmi_irq_thread, -+ IRQF_ONESHOT, dev_name(dev), -+ mhdp); -+ if (ret < 0) { -+ dev_err(dev, "can't claim irq %d\n", -+ mhdp->irq[IRQ_OUT]); -+ return -EINVAL; -+ } -+ -+ cdns_hdmi_parse_dt(mhdp); -+ -+ if (cdns_mhdp_read_hpd(mhdp)) -+ enable_irq(mhdp->irq[IRQ_OUT]); -+ else -+ enable_irq(mhdp->irq[IRQ_IN]); -+ -+ mhdp->bridge.base.driver_private = mhdp; -+ mhdp->bridge.base.funcs = &cdns_hdmi_bridge_funcs; -+#ifdef CONFIG_OF -+ mhdp->bridge.base.of_node = dev->of_node; -+#endif -+ -+ memset(&pdevinfo, 0, sizeof(pdevinfo)); -+ pdevinfo.parent = dev; -+ pdevinfo.id = PLATFORM_DEVID_AUTO; -+ -+ dev_set_drvdata(dev, mhdp); -+ -+ /* register audio driver */ -+ cdns_mhdp_register_audio_driver(dev); -+ -+ /* register cec driver */ -+#ifdef CONFIG_DRM_CDNS_HDMI_CEC -+ cdns_mhdp_register_cec_driver(dev); -+#endif -+ -+ return 0; -+} -+ -+static void __cdns_hdmi_remove(struct cdns_mhdp_device *mhdp) -+{ -+ /* unregister cec driver */ -+#ifdef CONFIG_DRM_CDNS_HDMI_CEC -+ cdns_mhdp_unregister_cec_driver(mhdp->dev); -+#endif -+ cdns_mhdp_unregister_audio_driver(mhdp->dev); -+} -+ -+/* ----------------------------------------------------------------------------- -+ * Probe/remove API, used from platforms based on the DRM bridge API. -+ */ -+int cdns_hdmi_probe(struct platform_device *pdev, -+ struct cdns_mhdp_device *mhdp) -+{ -+ int ret; -+ -+ ret = __cdns_hdmi_probe(pdev, mhdp); -+ if (ret < 0) -+ return ret; -+ -+ drm_bridge_add(&mhdp->bridge.base); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(cdns_hdmi_probe); -+ -+void cdns_hdmi_remove(struct platform_device *pdev) -+{ -+ struct cdns_mhdp_device *mhdp = platform_get_drvdata(pdev); -+ -+ drm_bridge_remove(&mhdp->bridge.base); -+ -+ __cdns_hdmi_remove(mhdp); -+} -+EXPORT_SYMBOL_GPL(cdns_hdmi_remove); -+ -+/* ----------------------------------------------------------------------------- -+ * Bind/unbind API, used from platforms based on the component framework. -+ */ -+int cdns_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, -+ struct cdns_mhdp_device *mhdp) -+{ -+ int ret; -+ -+ ret = __cdns_hdmi_probe(pdev, mhdp); -+ if (ret) -+ return ret; -+ -+ ret = drm_bridge_attach(encoder, &mhdp->bridge.base, NULL, 0); -+ if (ret) { -+ cdns_hdmi_remove(pdev); -+ DRM_ERROR("Failed to initialize bridge with drm\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(cdns_hdmi_bind); -+ -+void cdns_hdmi_unbind(struct device *dev) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ -+ __cdns_hdmi_remove(mhdp); -+} -+EXPORT_SYMBOL_GPL(cdns_hdmi_unbind); -+ -+MODULE_AUTHOR("Sandor Yu "); -+MODULE_DESCRIPTION("Cadence HDMI transmitter driver"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:cdn-hdmi"); -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c -new file mode 100644 -index 000000000000..86174fb633bc ---- /dev/null -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c -@@ -0,0 +1,395 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd -+ * Author: Chris Zhong -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define CDNS_DP_SPDIF_CLK 200000000 -+ -+static u32 TMDS_rate_table[7] = { -+ 25200, 27000, 54000, 74250, 148500, 297000, 594000, -+}; -+ -+static u32 N_table_32k[7] = { -+/* 25200/27000/54000/74250/148500/297000/594000 */ -+ 4096, 4096, 4096, 4096, 4096, 3072, 3072, -+}; -+ -+static u32 N_table_44k[7] = { -+ 6272, 6272, 6272, 6272, 6272, 4704, 9408, -+}; -+ -+static u32 N_table_48k[7] = { -+ 6144, 6144, 6144, 6144, 6144, 5120, 6144, -+}; -+ -+static int select_N_index(u32 pclk) -+{ -+ int num = sizeof(TMDS_rate_table)/sizeof(int); -+ int i = 0; -+ -+ for (i = 0; i < num ; i++) -+ if (pclk == TMDS_rate_table[i]) -+ break; -+ -+ if (i == num) { -+ DRM_WARN("pclkc %d is not supported!\n", pclk); -+ return num-1; -+ } -+ -+ return i; -+} -+ -+static void hdmi_audio_avi_set(struct cdns_mhdp_device *mhdp, -+ u32 channels) -+{ -+ struct hdmi_audio_infoframe frame; -+ u8 buf[32]; -+ int ret; -+ -+ hdmi_audio_infoframe_init(&frame); -+ -+ frame.channels = channels; -+ frame.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM; -+ -+ if (channels == 2) -+ frame.channel_allocation = 0; -+ else if (channels == 4) -+ frame.channel_allocation = 0x3; -+ else if (channels == 8) -+ frame.channel_allocation = 0x13; -+ -+ ret = hdmi_audio_infoframe_pack(&frame, buf + 1, sizeof(buf) - 1); -+ if (ret < 0) { -+ DRM_ERROR("failed to pack audio infoframe: %d\n", ret); -+ return; -+ } -+ -+ buf[0] = 0; -+ -+ cdns_mhdp_infoframe_set(mhdp, 1, sizeof(buf), buf, HDMI_INFOFRAME_TYPE_AUDIO); -+} -+ -+int cdns_mhdp_audio_stop(struct cdns_mhdp_device *mhdp, -+ struct audio_info *audio) -+{ -+ int ret; -+ -+ if (audio->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { -+ ret = cdns_mhdp_reg_write(mhdp, AUDIO_PACK_CONTROL, 0); -+ if (ret) { -+ DRM_DEV_ERROR(mhdp->dev, "audio stop failed: %d\n", ret); -+ return ret; -+ } -+ } -+ -+ cdns_mhdp_bus_write(0, mhdp, SPDIF_CTRL_ADDR); -+ -+ /* clearn the audio config and reset */ -+ cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNTL); -+ cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNFG); -+ cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, AUDIO_SRC_CNTL); -+ cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNTL); -+ -+ /* reset smpl2pckt component */ -+ cdns_mhdp_bus_write(0, mhdp, SMPL2PKT_CNTL); -+ cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, SMPL2PKT_CNTL); -+ cdns_mhdp_bus_write(0, mhdp, SMPL2PKT_CNTL); -+ -+ /* reset FIFO */ -+ cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, FIFO_CNTL); -+ cdns_mhdp_bus_write(0, mhdp, FIFO_CNTL); -+ -+ if (audio->format == AFMT_SPDIF_INT) -+ clk_disable_unprepare(mhdp->spdif_clk); -+ -+ return 0; -+} -+EXPORT_SYMBOL(cdns_mhdp_audio_stop); -+ -+int cdns_mhdp_audio_mute(struct cdns_mhdp_device *mhdp, bool enable) -+{ -+ struct audio_info *audio = &mhdp->audio_info; -+ int ret = true; -+ -+ if (audio->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { -+ ret = cdns_mhdp_reg_write_bit(mhdp, DP_VB_ID, 4, 1, enable); -+ if (ret) -+ DRM_DEV_ERROR(mhdp->dev, "audio mute failed: %d\n", ret); -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_audio_mute); -+ -+static void cdns_mhdp_audio_config_i2s(struct cdns_mhdp_device *mhdp, -+ struct audio_info *audio) -+{ -+ int sub_pckt_num = 1, i2s_port_en_val = 0xf, i; -+ int idx = select_N_index(mhdp->mode.clock); -+ u32 val, ncts; -+ -+ if (audio->channels == 2) { -+ if (mhdp->dp.num_lanes == 1) -+ sub_pckt_num = 2; -+ else -+ sub_pckt_num = 4; -+ -+ i2s_port_en_val = 1; -+ } else if (audio->channels == 4) { -+ i2s_port_en_val = 3; -+ } -+ -+ cdns_mhdp_bus_write(0x0, mhdp, SPDIF_CTRL_ADDR); -+ -+ cdns_mhdp_bus_write(SYNC_WR_TO_CH_ZERO, mhdp, FIFO_CNTL); -+ -+ val = MAX_NUM_CH(audio->channels); -+ val |= NUM_OF_I2S_PORTS(audio->channels); -+ val |= AUDIO_TYPE_LPCM; -+ val |= CFG_SUB_PCKT_NUM(sub_pckt_num); -+ cdns_mhdp_bus_write(val, mhdp, SMPL2PKT_CNFG); -+ -+ if (audio->sample_width == 16) -+ val = 0; -+ else if (audio->sample_width == 24) -+ val = 1 << 9; -+ else -+ val = 2 << 9; -+ -+ val |= AUDIO_CH_NUM(audio->channels); -+ val |= I2S_DEC_PORT_EN(i2s_port_en_val); -+ val |= TRANS_SMPL_WIDTH_32; -+ cdns_mhdp_bus_write(val, mhdp, AUDIO_SRC_CNFG); -+ -+ for (i = 0; i < (audio->channels + 1) / 2; i++) { -+ if (audio->sample_width == 16) -+ val = (0x02 << 8) | (0x02 << 20); -+ else if (audio->sample_width == 24) -+ val = (0x0b << 8) | (0x0b << 20); -+ -+ val |= ((2 * i) << 4) | ((2 * i + 1) << 16); -+ cdns_mhdp_bus_write(val, mhdp, STTS_BIT_CH(i)); -+ } -+ -+ switch (audio->sample_rate) { -+ case 32000: -+ val = SAMPLING_FREQ(3) | -+ ORIGINAL_SAMP_FREQ(0xc); -+ ncts = N_table_32k[idx]; -+ break; -+ case 44100: -+ val = SAMPLING_FREQ(0) | -+ ORIGINAL_SAMP_FREQ(0xf); -+ ncts = N_table_44k[idx]; -+ break; -+ case 48000: -+ val = SAMPLING_FREQ(2) | -+ ORIGINAL_SAMP_FREQ(0xd); -+ ncts = N_table_48k[idx]; -+ break; -+ case 88200: -+ val = SAMPLING_FREQ(8) | -+ ORIGINAL_SAMP_FREQ(0x7); -+ ncts = N_table_44k[idx] * 2; -+ break; -+ case 96000: -+ val = SAMPLING_FREQ(0xa) | -+ ORIGINAL_SAMP_FREQ(5); -+ ncts = N_table_48k[idx] * 2; -+ break; -+ case 176400: -+ val = SAMPLING_FREQ(0xc) | -+ ORIGINAL_SAMP_FREQ(3); -+ ncts = N_table_44k[idx] * 4; -+ break; -+ case 192000: -+ default: -+ val = SAMPLING_FREQ(0xe) | -+ ORIGINAL_SAMP_FREQ(1); -+ ncts = N_table_48k[idx] * 4; -+ break; -+ } -+ val |= 4; -+ cdns_mhdp_bus_write(val, mhdp, COM_CH_STTS_BITS); -+ -+ if (audio->connector_type == DRM_MODE_CONNECTOR_HDMIA) -+ cdns_mhdp_reg_write(mhdp, CM_I2S_CTRL, ncts | 0x4000000); -+ -+ cdns_mhdp_bus_write(SMPL2PKT_EN, mhdp, SMPL2PKT_CNTL); -+ cdns_mhdp_bus_write(I2S_DEC_START, mhdp, AUDIO_SRC_CNTL); -+} -+ -+static void cdns_mhdp_audio_config_spdif(struct cdns_mhdp_device *mhdp) -+{ -+ u32 val; -+ -+ cdns_mhdp_bus_write(SYNC_WR_TO_CH_ZERO, mhdp, FIFO_CNTL); -+ -+ val = MAX_NUM_CH(2) | AUDIO_TYPE_LPCM | CFG_SUB_PCKT_NUM(4); -+ cdns_mhdp_bus_write(val, mhdp, SMPL2PKT_CNFG); -+ cdns_mhdp_bus_write(SMPL2PKT_EN, mhdp, SMPL2PKT_CNTL); -+ -+ val = SPDIF_ENABLE | SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS; -+ cdns_mhdp_bus_write(val, mhdp, SPDIF_CTRL_ADDR); -+ -+ clk_prepare_enable(mhdp->spdif_clk); -+ clk_set_rate(mhdp->spdif_clk, CDNS_DP_SPDIF_CLK); -+} -+ -+int cdns_mhdp_audio_config(struct cdns_mhdp_device *mhdp, -+ struct audio_info *audio) -+{ -+ int ret; -+ -+ /* reset the spdif clk before config */ -+ if (audio->format == AFMT_SPDIF_INT) { -+ reset_control_assert(mhdp->spdif_rst); -+ reset_control_deassert(mhdp->spdif_rst); -+ } -+ -+ if (audio->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { -+ ret = cdns_mhdp_reg_write(mhdp, CM_LANE_CTRL, LANE_REF_CYC); -+ if (ret) -+ goto err_audio_config; -+ -+ ret = cdns_mhdp_reg_write(mhdp, CM_CTRL, 0); -+ if (ret) -+ goto err_audio_config; -+ } else { -+ /* HDMI Mode */ -+ ret = cdns_mhdp_reg_write(mhdp, CM_CTRL, 8); -+ if (ret) -+ goto err_audio_config; -+ } -+ -+ if (audio->format == AFMT_I2S) -+ cdns_mhdp_audio_config_i2s(mhdp, audio); -+ else if (audio->format == AFMT_SPDIF_INT) -+ cdns_mhdp_audio_config_spdif(mhdp); -+ -+ if (audio->connector_type == DRM_MODE_CONNECTOR_DisplayPort) -+ ret = cdns_mhdp_reg_write(mhdp, AUDIO_PACK_CONTROL, AUDIO_PACK_EN); -+ -+ if (audio->connector_type == DRM_MODE_CONNECTOR_HDMIA) -+ hdmi_audio_avi_set(mhdp, audio->channels); -+ -+err_audio_config: -+ if (ret) -+ DRM_DEV_ERROR(mhdp->dev, "audio config failed: %d\n", ret); -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_audio_config); -+ -+static int audio_hw_params(struct device *dev, void *data, -+ struct hdmi_codec_daifmt *daifmt, -+ struct hdmi_codec_params *params) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ struct audio_info audio = { -+ .sample_width = params->sample_width, -+ .sample_rate = params->sample_rate, -+ .channels = params->channels, -+ .connector_type = mhdp->connector.base.connector_type, -+ }; -+ int ret; -+ -+ switch (daifmt->fmt) { -+ case HDMI_I2S: -+ audio.format = AFMT_I2S; -+ break; -+ case HDMI_SPDIF: -+ audio.format = AFMT_SPDIF_EXT; -+ break; -+ default: -+ DRM_DEV_ERROR(dev, "Invalid format %d\n", daifmt->fmt); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ ret = cdns_mhdp_audio_config(mhdp, &audio); -+ if (!ret) -+ mhdp->audio_info = audio; -+ -+out: -+ return ret; -+} -+ -+static void audio_shutdown(struct device *dev, void *data) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = cdns_mhdp_audio_stop(mhdp, &mhdp->audio_info); -+ if (!ret) -+ mhdp->audio_info.format = AFMT_UNUSED; -+} -+ -+static int audio_digital_mute(struct device *dev, void *data, -+ bool enable) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = cdns_mhdp_audio_mute(mhdp, enable); -+ -+ return ret; -+} -+ -+static int audio_get_eld(struct device *dev, void *data, -+ u8 *buf, size_t len) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ -+ memcpy(buf, mhdp->connector.base.eld, -+ min(sizeof(mhdp->connector.base.eld), len)); -+ -+ return 0; -+} -+ -+static const struct hdmi_codec_ops audio_codec_ops = { -+ .hw_params = audio_hw_params, -+ .audio_shutdown = audio_shutdown, -+ .digital_mute = audio_digital_mute, -+ .get_eld = audio_get_eld, -+}; -+ -+int cdns_mhdp_register_audio_driver(struct device *dev) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ struct hdmi_codec_pdata codec_data = { -+ .i2s = 1, -+ .spdif = 1, -+ .ops = &audio_codec_ops, -+ .max_i2s_channels = 8, -+ }; -+ -+ mhdp->audio_pdev = platform_device_register_data( -+ dev, HDMI_CODEC_DRV_NAME, 1, -+ &codec_data, sizeof(codec_data)); -+ -+ return PTR_ERR_OR_ZERO(mhdp->audio_pdev); -+} -+ -+void cdns_mhdp_unregister_audio_driver(struct device *dev) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ -+ platform_device_unregister(mhdp->audio_pdev); -+} -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c -new file mode 100644 -index 000000000000..5717bb0bcb75 ---- /dev/null -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c -@@ -0,0 +1,341 @@ -+/* -+ * Copyright 2019 NXP -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#define CEC_NAME "cdns-mhdp-cec" -+ -+#define REG_ADDR_OFF 4 -+ -+/* regsiter define */ -+#define TX_MSG_HEADER 0x33800 -+#define TX_MSG_LENGTH 0x33840 -+#define TX_MSG_CMD 0x33844 -+#define RX_MSG_CMD 0x33850 -+#define RX_CLEAR_BUF 0x33854 -+#define LOGICAL_ADDRESS_LA0 0x33858 -+ -+#define CLK_DIV_MSB 0x3386c -+#define CLK_DIV_LSB 0x33870 -+#define RX_MSG_DATA1 0x33900 -+#define RX_MSG_LENGTH 0x33940 -+#define RX_MSG_STATUS 0x33944 -+#define NUM_OF_MSG_RX_BUF 0x33948 -+#define TX_MSG_STATUS 0x3394c -+#define DB_L_TIMER 0x33980 -+ -+/** -+ * CEC Transceiver operation. -+ */ -+enum { -+ CEC_TX_STOP, -+ CEC_TX_TRANSMIT, -+ CEC_TX_ABORT, -+ CEC_TX_ABORT_AND_TRANSMIT -+}; -+ -+/** -+ * CEC Transceiver status. -+ */ -+enum { -+ CEC_STS_IDLE, -+ CEC_STS_BUSY, -+ CEC_STS_SUCCESS, -+ CEC_STS_ERROR -+}; -+ -+/** -+ * CEC Receiver operation. -+ */ -+enum { -+ CEC_RX_STOP, -+ CEC_RX_READ, -+ CEC_RX_DISABLE, -+ CEC_RX_ABORT_AND_CLR_FIFO -+}; -+/** -+ * Maximum number of Messages in the RX Buffers. -+ */ -+#define CEC_MAX_RX_MSGS 2 -+ -+static u32 mhdp_cec_read(struct cdns_mhdp_cec *cec, u32 offset) -+{ -+ struct cdns_mhdp_device *mhdp = -+ container_of(cec, struct cdns_mhdp_device, hdmi.cec); -+ return cdns_mhdp_bus_read(mhdp, offset); -+} -+ -+static void mhdp_cec_write(struct cdns_mhdp_cec *cec, u32 offset, u32 val) -+{ -+ struct cdns_mhdp_device *mhdp = -+ container_of(cec, struct cdns_mhdp_device, hdmi.cec); -+ cdns_mhdp_bus_write(val, mhdp, offset); -+} -+ -+static void mhdp_cec_clear_rx_buffer(struct cdns_mhdp_cec *cec) -+{ -+ mhdp_cec_write(cec, RX_CLEAR_BUF, 1); -+ mhdp_cec_write(cec, RX_CLEAR_BUF, 0); -+} -+ -+static void mhdp_cec_set_divider(struct cdns_mhdp_cec *cec) -+{ -+ struct cdns_mhdp_device *mhdp = -+ container_of(cec, struct cdns_mhdp_device, hdmi.cec); -+ u32 clk_div; -+ -+ /* Set clock divider */ -+ clk_div = cdns_mhdp_get_fw_clk(mhdp) * 10; -+ -+ mhdp_cec_write(cec, CLK_DIV_MSB, -+ (clk_div >> 8) & 0xFF); -+ mhdp_cec_write(cec, CLK_DIV_LSB, clk_div & 0xFF); -+} -+ -+static u32 mhdp_cec_read_message(struct cdns_mhdp_cec *cec) -+{ -+ struct cec_msg *msg = &cec->msg; -+ int len; -+ int i; -+ -+ mhdp_cec_write(cec, RX_MSG_CMD, CEC_RX_READ); -+ -+ len = mhdp_cec_read(cec, RX_MSG_LENGTH); -+ msg->len = len + 1; -+ dev_dbg(cec->dev, "RX MSG len =%d\n", len); -+ -+ /* Read RX MSG bytes */ -+ for (i = 0; i < msg->len; ++i) { -+ msg->msg[i] = (u8) mhdp_cec_read(cec, RX_MSG_DATA1 + (i * REG_ADDR_OFF)); -+ dev_dbg(cec->dev, "RX MSG[%d]=0x%x\n", i, msg->msg[i]); -+ } -+ -+ mhdp_cec_write(cec, RX_MSG_CMD, CEC_RX_STOP); -+ -+ return true; -+} -+ -+static u32 mhdp_cec_write_message(struct cdns_mhdp_cec *cec, struct cec_msg *msg) -+{ -+ u8 i; -+ -+ mhdp_cec_write(cec, TX_MSG_CMD, CEC_TX_STOP); -+ -+ if (msg->len > CEC_MAX_MSG_SIZE) { -+ dev_err(cec->dev, "Invalid MSG size!\n"); -+ return -EINVAL; -+ } -+ -+ for (i = 0; i < msg->len; ++i) -+ printk("msg[%d]=0x%x\n",i, msg->msg[i]); -+ -+ /* Write Message to register */ -+ for (i = 0; i < msg->len; ++i) { -+ mhdp_cec_write(cec, TX_MSG_HEADER + (i * REG_ADDR_OFF), -+ msg->msg[i]); -+ } -+ /* Write Message Length (payload + opcode) */ -+ mhdp_cec_write(cec, TX_MSG_LENGTH, msg->len - 1); -+ -+ mhdp_cec_write(cec, TX_MSG_CMD, CEC_TX_TRANSMIT); -+ -+ return true; -+} -+ -+static int mhdp_cec_set_logical_addr(struct cdns_mhdp_cec *cec, u32 la) -+{ -+ u8 la_reg; -+ u8 i; -+ -+ if (la == CEC_LOG_ADDR_INVALID) -+ /* invalid all LA address */ -+ for (i = 0; i < CEC_MAX_LOG_ADDRS; ++i) { -+ mhdp_cec_write(cec, LOGICAL_ADDRESS_LA0 + (i * REG_ADDR_OFF), 0); -+ return 0; -+ } -+ -+ /* In fact cdns mhdp cec could support max 5 La address */ -+ for (i = 0; i < CEC_MAX_LOG_ADDRS; ++i) { -+ la_reg = mhdp_cec_read(cec, LOGICAL_ADDRESS_LA0 + (i * REG_ADDR_OFF)); -+ /* Check LA already used */ -+ if (la_reg & 0x10) -+ continue; -+ -+ if ((la_reg & 0xF) == la) { -+ dev_warn(cec->dev, "Warning. LA already in use.\n"); -+ return 0; -+ } -+ -+ la = (la & 0xF) | (1 << 4); -+ -+ mhdp_cec_write(cec, LOGICAL_ADDRESS_LA0 + (i * REG_ADDR_OFF), la); -+ return 0; -+ } -+ -+ dev_warn(cec->dev, "All LA in use\n"); -+ -+ return -ENXIO; -+} -+ -+static int mhdp_cec_poll_worker(void *_cec) -+{ -+ struct cdns_mhdp_cec *cec = (struct cdns_mhdp_cec *)_cec; -+ int num_rx_msgs, i; -+ int sts; -+ -+ set_freezable(); -+ -+ for (;;) { -+ if (kthread_freezable_should_stop(NULL)) -+ break; -+ -+ /* Check TX State */ -+ sts = mhdp_cec_read(cec, TX_MSG_STATUS); -+ switch (sts) { -+ case CEC_STS_SUCCESS: -+ cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, -+ 0); -+ mhdp_cec_write(cec, TX_MSG_CMD, CEC_TX_STOP); -+ break; -+ case CEC_STS_ERROR: -+ mhdp_cec_write(cec, TX_MSG_CMD, CEC_TX_STOP); -+ cec_transmit_done(cec->adap, -+ CEC_TX_STATUS_MAX_RETRIES | -+ CEC_TX_STATUS_NACK, 0, 1, 0, 0); -+ break; -+ case CEC_STS_BUSY: -+ default: -+ break; -+ } -+ -+ /* Check RX State */ -+ sts = mhdp_cec_read(cec, RX_MSG_STATUS); -+ num_rx_msgs = mhdp_cec_read(cec, NUM_OF_MSG_RX_BUF); -+ switch (sts) { -+ case CEC_STS_SUCCESS: -+ if (num_rx_msgs == 0xf) -+ num_rx_msgs = CEC_MAX_RX_MSGS; -+ -+ if (num_rx_msgs > CEC_MAX_RX_MSGS) { -+ dev_err(cec->dev, "Error rx msg num %d\n", -+ num_rx_msgs); -+ mhdp_cec_clear_rx_buffer(cec); -+ break; -+ } -+ -+ /* Rx FIFO Depth 2 RX MSG */ -+ for (i = 0; i < num_rx_msgs; i++) { -+ mhdp_cec_read_message(cec); -+ cec->msg.rx_status = CEC_RX_STATUS_OK; -+ cec_received_msg(cec->adap, &cec->msg); -+ } -+ break; -+ default: -+ break; -+ } -+ -+ if (!kthread_should_stop()) -+ schedule_timeout_idle(20); -+ } -+ -+ return 0; -+} -+ -+static int mhdp_cec_adap_enable(struct cec_adapter *adap, bool enable) -+{ -+ struct cdns_mhdp_cec *cec = cec_get_drvdata(adap); -+ -+ if (enable) { -+ mhdp_cec_write(cec, DB_L_TIMER, 0x10); -+ mhdp_cec_set_divider(cec); -+ } else -+ mhdp_cec_set_divider(cec); -+ -+ return 0; -+} -+ -+static int mhdp_cec_adap_log_addr(struct cec_adapter *adap, u8 addr) -+{ -+ struct cdns_mhdp_cec *cec = cec_get_drvdata(adap); -+ -+ return mhdp_cec_set_logical_addr(cec, addr); -+} -+ -+static int mhdp_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, -+ u32 signal_free_time, struct cec_msg *msg) -+{ -+ struct cdns_mhdp_cec *cec = cec_get_drvdata(adap); -+ -+ mhdp_cec_write_message(cec, msg); -+ -+ return 0; -+} -+ -+static const struct cec_adap_ops cdns_mhdp_cec_adap_ops = { -+ .adap_enable = mhdp_cec_adap_enable, -+ .adap_log_addr = mhdp_cec_adap_log_addr, -+ .adap_transmit = mhdp_cec_adap_transmit, -+}; -+ -+int cdns_mhdp_register_cec_driver(struct device *dev) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ struct cdns_mhdp_cec *cec = &mhdp->hdmi.cec; -+ int ret; -+ -+ cec->adap = cec_allocate_adapter(&cdns_mhdp_cec_adap_ops, cec, -+ CEC_NAME, -+ CEC_CAP_PHYS_ADDR | CEC_CAP_LOG_ADDRS | -+ CEC_CAP_TRANSMIT | CEC_CAP_PASSTHROUGH -+ | CEC_CAP_RC, CEC_MAX_LOG_ADDRS); -+ ret = PTR_ERR_OR_ZERO(cec->adap); -+ if (ret) -+ return ret; -+ ret = cec_register_adapter(cec->adap, dev); -+ if (ret) { -+ cec_delete_adapter(cec->adap); -+ return ret; -+ } -+ -+ cec->dev = dev; -+ -+ cec->cec_worker = kthread_create(mhdp_cec_poll_worker, cec, "cdns-mhdp-cec"); -+ if (IS_ERR(cec->cec_worker)) -+ dev_err(cec->dev, "failed create hdp cec thread\n"); -+ -+ wake_up_process(cec->cec_worker); -+ -+ dev_dbg(dev, "CEC successfuly probed\n"); -+ return 0; -+} -+ -+int cdns_mhdp_unregister_cec_driver(struct device *dev) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ struct cdns_mhdp_cec *cec = &mhdp->hdmi.cec; -+ -+ if (cec->cec_worker) { -+ kthread_stop(cec->cec_worker); -+ cec->cec_worker = NULL; -+ } -+ cec_unregister_adapter(cec->adap); -+ return 0; -+} -+ -+MODULE_AUTHOR("Sandor.Yu@NXP.com"); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("NXP CDNS MHDP HDMI CEC driver"); -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -new file mode 100644 -index 000000000000..91d1cfd4b2af ---- /dev/null -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -@@ -0,0 +1,795 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd -+ * Author: Chris Zhong -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#define CDNS_DP_SPDIF_CLK 200000000 -+#define FW_ALIVE_TIMEOUT_US 1000000 -+#define MAILBOX_RETRY_US 1000 -+#define MAILBOX_TIMEOUT_US 5000000 -+ -+#define mhdp_readx_poll_timeout(op, addr, offset, val, cond, sleep_us, timeout_us) \ -+({ \ -+ u64 __timeout_us = (timeout_us); \ -+ unsigned long __sleep_us = (sleep_us); \ -+ ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ -+ might_sleep_if((__sleep_us) != 0); \ -+ for (;;) { \ -+ (val) = op(addr, offset); \ -+ if (cond) \ -+ break; \ -+ if (__timeout_us && \ -+ ktime_compare(ktime_get(), __timeout) > 0) { \ -+ (val) = op(addr, offset); \ -+ break; \ -+ } \ -+ if (__sleep_us) \ -+ usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ -+ } \ -+ (cond) ? 0 : -ETIMEDOUT; \ -+}) -+ -+u32 cdns_mhdp_bus_read(struct cdns_mhdp_device *mhdp, u32 offset) -+{ -+ u32 val; -+ -+ mutex_lock(&mhdp->iolock); -+ -+ if (mhdp->bus_type == BUS_TYPE_LOW4K_SAPB) { -+ /* Remap address to low 4K SAPB bus */ -+ writel(offset >> 12, mhdp->regs_sec + 0xc); -+ val = readl((offset & 0xfff) + mhdp->regs_base); -+ } else if (mhdp->bus_type == BUS_TYPE_LOW4K_APB) { -+ /* Remap address to low 4K memory */ -+ writel(offset >> 12, mhdp->regs_sec + 8); -+ val = readl((offset & 0xfff) + mhdp->regs_base); -+ } else if (mhdp->bus_type == BUS_TYPE_NORMAL_SAPB) -+ val = readl(mhdp->regs_sec + offset); -+ else -+ val = readl(mhdp->regs_base + offset); -+ -+ mutex_unlock(&mhdp->iolock); -+ -+ return val; -+} -+EXPORT_SYMBOL(cdns_mhdp_bus_read); -+ -+void cdns_mhdp_bus_write(u32 val, struct cdns_mhdp_device *mhdp, u32 offset) -+{ -+ mutex_lock(&mhdp->iolock); -+ -+ if (mhdp->bus_type == BUS_TYPE_LOW4K_SAPB) { -+ /* Remap address to low 4K SAPB bus */ -+ writel(offset >> 12, mhdp->regs_sec + 0xc); -+ writel(val, (offset & 0xfff) + mhdp->regs_base); -+ } else if (mhdp->bus_type == BUS_TYPE_LOW4K_APB) { -+ /* Remap address to low 4K memory */ -+ writel(offset >> 12, mhdp->regs_sec + 8); -+ writel(val, (offset & 0xfff) + mhdp->regs_base); -+ } else if (mhdp->bus_type == BUS_TYPE_NORMAL_SAPB) -+ writel(val, mhdp->regs_sec + offset); -+ else -+ writel(val, mhdp->regs_base + offset); -+ -+ mutex_unlock(&mhdp->iolock); -+} -+EXPORT_SYMBOL(cdns_mhdp_bus_write); -+ -+u32 cdns_mhdp_get_fw_clk(struct cdns_mhdp_device *mhdp) -+{ -+ return cdns_mhdp_bus_read(mhdp, SW_CLK_H); -+} -+EXPORT_SYMBOL(cdns_mhdp_get_fw_clk); -+ -+void cdns_mhdp_set_fw_clk(struct cdns_mhdp_device *mhdp, unsigned long clk) -+{ -+ cdns_mhdp_bus_write(clk / 1000000, mhdp, SW_CLK_H); -+} -+EXPORT_SYMBOL(cdns_mhdp_set_fw_clk); -+ -+void cdns_mhdp_clock_reset(struct cdns_mhdp_device *mhdp) -+{ -+ u32 val; -+ -+ val = DPTX_FRMR_DATA_CLK_RSTN_EN | -+ DPTX_FRMR_DATA_CLK_EN | -+ DPTX_PHY_DATA_RSTN_EN | -+ DPTX_PHY_DATA_CLK_EN | -+ DPTX_PHY_CHAR_RSTN_EN | -+ DPTX_PHY_CHAR_CLK_EN | -+ SOURCE_AUX_SYS_CLK_RSTN_EN | -+ SOURCE_AUX_SYS_CLK_EN | -+ DPTX_SYS_CLK_RSTN_EN | -+ DPTX_SYS_CLK_EN | -+ CFG_DPTX_VIF_CLK_RSTN_EN | -+ CFG_DPTX_VIF_CLK_EN; -+ cdns_mhdp_bus_write(val, mhdp, SOURCE_DPTX_CAR); -+ -+ val = SOURCE_PHY_RSTN_EN | SOURCE_PHY_CLK_EN; -+ cdns_mhdp_bus_write(val, mhdp, SOURCE_PHY_CAR); -+ -+ val = SOURCE_PKT_SYS_RSTN_EN | -+ SOURCE_PKT_SYS_CLK_EN | -+ SOURCE_PKT_DATA_RSTN_EN | -+ SOURCE_PKT_DATA_CLK_EN; -+ cdns_mhdp_bus_write(val, mhdp, SOURCE_PKT_CAR); -+ -+ val = SPDIF_CDR_CLK_RSTN_EN | -+ SPDIF_CDR_CLK_EN | -+ SOURCE_AIF_SYS_RSTN_EN | -+ SOURCE_AIF_SYS_CLK_EN | -+ SOURCE_AIF_CLK_RSTN_EN | -+ SOURCE_AIF_CLK_EN; -+ cdns_mhdp_bus_write(val, mhdp, SOURCE_AIF_CAR); -+ -+ val = SOURCE_CIPHER_SYSTEM_CLK_RSTN_EN | -+ SOURCE_CIPHER_SYS_CLK_EN | -+ SOURCE_CIPHER_CHAR_CLK_RSTN_EN | -+ SOURCE_CIPHER_CHAR_CLK_EN; -+ cdns_mhdp_bus_write(val, mhdp, SOURCE_CIPHER_CAR); -+ -+ val = SOURCE_CRYPTO_SYS_CLK_RSTN_EN | -+ SOURCE_CRYPTO_SYS_CLK_EN; -+ cdns_mhdp_bus_write(val, mhdp, SOURCE_CRYPTO_CAR); -+ -+ /* enable Mailbox and PIF interrupt */ -+ cdns_mhdp_bus_write(0, mhdp, APB_INT_MASK); -+} -+EXPORT_SYMBOL(cdns_mhdp_clock_reset); -+ -+bool cdns_mhdp_check_alive(struct cdns_mhdp_device *mhdp) -+{ -+ u32 alive, newalive; -+ u8 retries_left = 50; -+ -+ alive = cdns_mhdp_bus_read(mhdp, KEEP_ALIVE); -+ -+ while (retries_left--) { -+ udelay(2); -+ -+ newalive = cdns_mhdp_bus_read(mhdp, KEEP_ALIVE); -+ if (alive == newalive) -+ continue; -+ return true; -+ } -+ return false; -+} -+EXPORT_SYMBOL(cdns_mhdp_check_alive); -+ -+static int mhdp_mailbox_read(struct cdns_mhdp_device *mhdp) -+{ -+ int val, ret; -+ -+ ret = mhdp_readx_poll_timeout(cdns_mhdp_bus_read, mhdp, MAILBOX_EMPTY_ADDR, -+ val, !val, MAILBOX_RETRY_US, -+ MAILBOX_TIMEOUT_US); -+ if (ret < 0) -+ return ret; -+ -+ return cdns_mhdp_bus_read(mhdp, MAILBOX0_RD_DATA) & 0xff; -+} -+ -+static int mhdp_mailbox_write(struct cdns_mhdp_device *mhdp, u8 val) -+{ -+ int ret, full; -+ -+ ret = mhdp_readx_poll_timeout(cdns_mhdp_bus_read, mhdp, MAILBOX_FULL_ADDR, -+ full, !full, MAILBOX_RETRY_US, -+ MAILBOX_TIMEOUT_US); -+ if (ret < 0) -+ return ret; -+ -+ cdns_mhdp_bus_write(val, mhdp, MAILBOX0_WR_DATA); -+ -+ return 0; -+} -+ -+int cdns_mhdp_mailbox_validate_receive(struct cdns_mhdp_device *mhdp, -+ u8 module_id, u8 opcode, -+ u16 req_size) -+{ -+ u32 mbox_size, i; -+ u8 header[4]; -+ int ret; -+ -+ /* read the header of the message */ -+ for (i = 0; i < 4; i++) { -+ ret = mhdp_mailbox_read(mhdp); -+ if (ret < 0) -+ return ret; -+ -+ header[i] = ret; -+ } -+ -+ mbox_size = get_unaligned_be16(header + 2); -+ -+ if (opcode != header[0] || module_id != header[1] || -+ req_size != mbox_size) { -+ /* -+ * If the message in mailbox is not what we want, we need to -+ * clear the mailbox by reading its contents. -+ */ -+ for (i = 0; i < mbox_size; i++) -+ if (mhdp_mailbox_read(mhdp) < 0) -+ break; -+ -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(cdns_mhdp_mailbox_validate_receive); -+ -+int cdns_mhdp_mailbox_read_receive(struct cdns_mhdp_device *mhdp, -+ u8 *buff, u16 buff_size) -+{ -+ u32 i; -+ int ret; -+ -+ for (i = 0; i < buff_size; i++) { -+ ret = mhdp_mailbox_read(mhdp); -+ if (ret < 0) -+ return ret; -+ -+ buff[i] = ret; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(cdns_mhdp_mailbox_read_receive); -+ -+int cdns_mhdp_mailbox_send(struct cdns_mhdp_device *mhdp, u8 module_id, -+ u8 opcode, u16 size, u8 *message) -+{ -+ u8 header[4]; -+ int ret, i; -+ -+ header[0] = opcode; -+ header[1] = module_id; -+ put_unaligned_be16(size, header + 2); -+ -+ for (i = 0; i < 4; i++) { -+ ret = mhdp_mailbox_write(mhdp, header[i]); -+ if (ret) -+ return ret; -+ } -+ -+ for (i = 0; i < size; i++) { -+ ret = mhdp_mailbox_write(mhdp, message[i]); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(cdns_mhdp_mailbox_send); -+ -+int cdns_mhdp_reg_read(struct cdns_mhdp_device *mhdp, u32 addr) -+{ -+ u8 msg[4], resp[8]; -+ u32 val; -+ int ret; -+ -+ if (addr == 0) { -+ ret = -EINVAL; -+ goto err_reg_read; -+ } -+ -+ put_unaligned_be32(addr, msg); -+ -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_GENERAL, -+ GENERAL_READ_REGISTER, -+ sizeof(msg), msg); -+ if (ret) -+ goto err_reg_read; -+ -+ ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_GENERAL, -+ GENERAL_READ_REGISTER, -+ sizeof(resp)); -+ if (ret) -+ goto err_reg_read; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, resp, sizeof(resp)); -+ if (ret) -+ goto err_reg_read; -+ -+ /* Returned address value should be the same as requested */ -+ if (memcmp(msg, resp, sizeof(msg))) { -+ ret = -EINVAL; -+ goto err_reg_read; -+ } -+ -+ val = get_unaligned_be32(resp + 4); -+ -+ return val; -+err_reg_read: -+ DRM_DEV_ERROR(mhdp->dev, "Failed to read register.\n"); -+ -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_reg_read); -+ -+int cdns_mhdp_reg_write(struct cdns_mhdp_device *mhdp, u32 addr, u32 val) -+{ -+ u8 msg[8]; -+ -+ put_unaligned_be32(addr, msg); -+ put_unaligned_be32(val, msg + 4); -+ -+ return cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_GENERAL, -+ GENERAL_WRITE_REGISTER, sizeof(msg), msg); -+} -+EXPORT_SYMBOL(cdns_mhdp_reg_write); -+ -+int cdns_mhdp_reg_write_bit(struct cdns_mhdp_device *mhdp, u16 addr, -+ u8 start_bit, u8 bits_no, u32 val) -+{ -+ u8 field[8]; -+ -+ put_unaligned_be16(addr, field); -+ field[2] = start_bit; -+ field[3] = bits_no; -+ put_unaligned_be32(val, field + 4); -+ -+ return cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_WRITE_FIELD, sizeof(field), field); -+} -+EXPORT_SYMBOL(cdns_mhdp_reg_write_bit); -+ -+int cdns_mhdp_load_firmware(struct cdns_mhdp_device *mhdp, const u32 *i_mem, -+ u32 i_size, const u32 *d_mem, u32 d_size) -+{ -+ u32 reg; -+ int i, ret; -+ -+ /* reset ucpu before load firmware*/ -+ cdns_mhdp_bus_write(APB_IRAM_PATH | APB_DRAM_PATH | APB_XT_RESET, -+ mhdp, APB_CTRL); -+ -+ for (i = 0; i < i_size; i += 4) -+ cdns_mhdp_bus_write(*i_mem++, mhdp, ADDR_IMEM + i); -+ -+ for (i = 0; i < d_size; i += 4) -+ cdns_mhdp_bus_write(*d_mem++, mhdp, ADDR_DMEM + i); -+ -+ /* un-reset ucpu */ -+ cdns_mhdp_bus_write(0, mhdp, APB_CTRL); -+ -+ /* check the keep alive register to make sure fw working */ -+ ret = mhdp_readx_poll_timeout(cdns_mhdp_bus_read, mhdp, KEEP_ALIVE, -+ reg, reg, 2000, FW_ALIVE_TIMEOUT_US); -+ if (ret < 0) { -+ DRM_DEV_ERROR(mhdp->dev, "failed to loaded the FW reg = %x\n", -+ reg); -+ return -EINVAL; -+ } -+ -+ reg = cdns_mhdp_bus_read(mhdp, VER_L) & 0xff; -+ mhdp->fw_version = reg; -+ reg = cdns_mhdp_bus_read(mhdp, VER_H) & 0xff; -+ mhdp->fw_version |= reg << 8; -+ reg = cdns_mhdp_bus_read(mhdp, VER_LIB_L_ADDR) & 0xff; -+ mhdp->fw_version |= reg << 16; -+ reg = cdns_mhdp_bus_read(mhdp, VER_LIB_H_ADDR) & 0xff; -+ mhdp->fw_version |= reg << 24; -+ -+ DRM_DEV_DEBUG(mhdp->dev, "firmware version: %x\n", mhdp->fw_version); -+ -+ return 0; -+} -+EXPORT_SYMBOL(cdns_mhdp_load_firmware); -+ -+int cdns_mhdp_set_firmware_active(struct cdns_mhdp_device *mhdp, bool enable) -+{ -+ u8 msg[5]; -+ int ret, i; -+ -+ msg[0] = GENERAL_MAIN_CONTROL; -+ msg[1] = MB_MODULE_ID_GENERAL; -+ msg[2] = 0; -+ msg[3] = 1; -+ msg[4] = enable ? FW_ACTIVE : FW_STANDBY; -+ -+ for (i = 0; i < sizeof(msg); i++) { -+ ret = mhdp_mailbox_write(mhdp, msg[i]); -+ if (ret) -+ goto err_set_firmware_active; -+ } -+ -+ /* read the firmware state */ -+ for (i = 0; i < sizeof(msg); i++) { -+ ret = mhdp_mailbox_read(mhdp); -+ if (ret < 0) -+ goto err_set_firmware_active; -+ -+ msg[i] = ret; -+ } -+ -+ ret = 0; -+ -+err_set_firmware_active: -+ if (ret < 0) -+ DRM_DEV_ERROR(mhdp->dev, "set firmware active failed\n"); -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_set_firmware_active); -+ -+int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp, bool flip) -+{ -+ u8 msg[8]; -+ int ret; -+ -+ msg[0] = drm_dp_link_rate_to_bw_code(mhdp->dp.rate); -+ msg[1] = mhdp->dp.num_lanes | SCRAMBLER_EN; -+ msg[2] = VOLTAGE_LEVEL_2; -+ msg[3] = PRE_EMPHASIS_LEVEL_3; -+ msg[4] = PTS1 | PTS2 | PTS3 | PTS4; -+ msg[5] = FAST_LT_NOT_SUPPORT; -+ msg[6] = flip ? LANE_MAPPING_FLIPPED : LANE_MAPPING_NORMAL; -+ msg[7] = ENHANCED; -+ -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_SET_HOST_CAPABILITIES, -+ sizeof(msg), msg); -+ if (ret) -+ goto err_set_host_cap; -+ -+/* TODO Sandor */ -+// ret = cdns_mhdp_reg_write(mhdp, DP_AUX_SWAP_INVERSION_CONTROL, -+// AUX_HOST_INVERT); -+ -+err_set_host_cap: -+ if (ret) -+ DRM_DEV_ERROR(mhdp->dev, "set host cap failed: %d\n", ret); -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_set_host_cap); -+ -+int cdns_mhdp_event_config(struct cdns_mhdp_device *mhdp) -+{ -+ u8 msg[5]; -+ int ret; -+ -+ memset(msg, 0, sizeof(msg)); -+ -+ msg[0] = MHDP_EVENT_ENABLE_HPD | MHDP_EVENT_ENABLE_TRAINING; -+ -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_ENABLE_EVENT, sizeof(msg), msg); -+ if (ret) -+ DRM_DEV_ERROR(mhdp->dev, "set event config failed: %d\n", ret); -+ -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_event_config); -+ -+u32 cdns_mhdp_get_event(struct cdns_mhdp_device *mhdp) -+{ -+ return cdns_mhdp_bus_read(mhdp, SW_EVENTS0); -+} -+EXPORT_SYMBOL(cdns_mhdp_get_event); -+ -+int cdns_mhdp_read_hpd(struct cdns_mhdp_device *mhdp) -+{ -+ u8 status; -+ int ret; -+ -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_GENERAL, GENERAL_GET_HPD_STATE, -+ 0, NULL); -+ if (ret) -+ goto err_get_hpd; -+ -+ ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_GENERAL, -+ GENERAL_GET_HPD_STATE, sizeof(status)); -+ if (ret) -+ goto err_get_hpd; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, &status, sizeof(status)); -+ if (ret) -+ goto err_get_hpd; -+ -+ return status; -+ -+err_get_hpd: -+ DRM_ERROR("read hpd failed: %d\n", ret); -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_read_hpd); -+ -+int cdns_mhdp_get_edid_block(void *data, u8 *edid, -+ unsigned int block, size_t length) -+{ -+ struct cdns_mhdp_device *mhdp = data; -+ u8 msg[2], reg[2], i; -+ int ret; -+ -+ for (i = 0; i < 4; i++) { -+ msg[0] = block / 2; -+ msg[1] = block % 2; -+ -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_GET_EDID, sizeof(msg), msg); -+ if (ret) -+ continue; -+ -+ ret = cdns_mhdp_mailbox_validate_receive(mhdp, -+ MB_MODULE_ID_DP_TX, -+ DPTX_GET_EDID, -+ sizeof(reg) + length); -+ if (ret) -+ continue; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, reg, sizeof(reg)); -+ if (ret) -+ continue; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, edid, length); -+ if (ret) -+ continue; -+ -+ if (reg[0] == length && reg[1] == block / 2) -+ break; -+ } -+ -+ if (ret) -+ DRM_DEV_ERROR(mhdp->dev, "get block[%d] edid failed: %d\n", -+ block, ret); -+ -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_get_edid_block); -+ -+int cdns_mhdp_set_video_status(struct cdns_mhdp_device *mhdp, int active) -+{ -+ u8 msg; -+ int ret; -+ -+ msg = !!active; -+ -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_SET_VIDEO, sizeof(msg), &msg); -+ if (ret) -+ DRM_DEV_ERROR(mhdp->dev, "set video status failed: %d\n", ret); -+ -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_set_video_status); -+ -+static int mhdp_get_msa_misc(struct video_info *video, -+ struct drm_display_mode *mode) -+{ -+ u32 msa_misc; -+ u8 val[2] = {0}; -+ -+ switch (video->color_fmt) { -+ case PXL_RGB: -+ case Y_ONLY: -+ val[0] = 0; -+ break; -+ /* set YUV default color space conversion to BT601 */ -+ case YCBCR_4_4_4: -+ val[0] = 6 + BT_601 * 8; -+ break; -+ case YCBCR_4_2_2: -+ val[0] = 5 + BT_601 * 8; -+ break; -+ case YCBCR_4_2_0: -+ val[0] = 5; -+ break; -+ } -+ -+ switch (video->color_depth) { -+ case 6: -+ val[1] = 0; -+ break; -+ case 8: -+ val[1] = 1; -+ break; -+ case 10: -+ val[1] = 2; -+ break; -+ case 12: -+ val[1] = 3; -+ break; -+ case 16: -+ val[1] = 4; -+ break; -+ } -+ -+ msa_misc = 2 * val[0] + 32 * val[1] + -+ ((video->color_fmt == Y_ONLY) ? (1 << 14) : 0); -+ -+ return msa_misc; -+} -+ -+int cdns_mhdp_config_video(struct cdns_mhdp_device *mhdp) -+{ -+ struct video_info *video = &mhdp->video_info; -+ struct drm_display_mode *mode = &mhdp->mode; -+ u64 symbol; -+ u32 val, link_rate, rem; -+ u8 bit_per_pix, tu_size_reg = TU_SIZE; -+ int ret; -+ -+ bit_per_pix = (video->color_fmt == YCBCR_4_2_2) ? -+ (video->color_depth * 2) : (video->color_depth * 3); -+ -+ link_rate = mhdp->dp.rate / 1000; -+ -+ ret = cdns_mhdp_reg_write(mhdp, BND_HSYNC2VSYNC, VIF_BYPASS_INTERLACE); -+ if (ret) -+ goto err_config_video; -+ -+ ret = cdns_mhdp_reg_write(mhdp, HSYNC2VSYNC_POL_CTRL, 0); -+ if (ret) -+ goto err_config_video; -+ -+ /* -+ * get a best tu_size and valid symbol: -+ * 1. chose Lclk freq(162Mhz, 270Mhz, 540Mhz), set TU to 32 -+ * 2. calculate VS(valid symbol) = TU * Pclk * Bpp / (Lclk * Lanes) -+ * 3. if VS > *.85 or VS < *.1 or VS < 2 or TU < VS + 4, then set -+ * TU += 2 and repeat 2nd step. -+ */ -+ do { -+ tu_size_reg += 2; -+ symbol = tu_size_reg * mode->clock * bit_per_pix; -+ do_div(symbol, mhdp->dp.num_lanes * link_rate * 8); -+ rem = do_div(symbol, 1000); -+ if (tu_size_reg > 64) { -+ ret = -EINVAL; -+ DRM_DEV_ERROR(mhdp->dev, -+ "tu error, clk:%d, lanes:%d, rate:%d\n", -+ mode->clock, mhdp->dp.num_lanes, -+ link_rate); -+ goto err_config_video; -+ } -+ } while ((symbol <= 1) || (tu_size_reg - symbol < 4) || -+ (rem > 850) || (rem < 100)); -+ -+ val = symbol + (tu_size_reg << 8); -+ val |= TU_CNT_RST_EN; -+ ret = cdns_mhdp_reg_write(mhdp, DP_FRAMER_TU, val); -+ if (ret) -+ goto err_config_video; -+ -+ /* set the FIFO Buffer size */ -+ val = div_u64(mode->clock * (symbol + 1), 1000) + link_rate; -+ val /= (mhdp->dp.num_lanes * link_rate); -+ val = div_u64(8 * (symbol + 1), bit_per_pix) - val; -+ val += 2; -+ ret = cdns_mhdp_reg_write(mhdp, DP_VC_TABLE(15), val); -+ -+ switch (video->color_depth) { -+ case 6: -+ val = BCS_6; -+ break; -+ case 8: -+ val = BCS_8; -+ break; -+ case 10: -+ val = BCS_10; -+ break; -+ case 12: -+ val = BCS_12; -+ break; -+ case 16: -+ val = BCS_16; -+ break; -+ } -+ -+ val += video->color_fmt << 8; -+ ret = cdns_mhdp_reg_write(mhdp, DP_FRAMER_PXL_REPR, val); -+ if (ret) -+ goto err_config_video; -+ -+ val = video->h_sync_polarity ? DP_FRAMER_SP_HSP : 0; -+ val |= video->v_sync_polarity ? DP_FRAMER_SP_VSP : 0; -+ ret = cdns_mhdp_reg_write(mhdp, DP_FRAMER_SP, val); -+ if (ret) -+ goto err_config_video; -+ -+ val = (mode->hsync_start - mode->hdisplay) << 16; -+ val |= mode->htotal - mode->hsync_end; -+ ret = cdns_mhdp_reg_write(mhdp, DP_FRONT_BACK_PORCH, val); -+ if (ret) -+ goto err_config_video; -+ -+ val = mode->hdisplay * bit_per_pix / 8; -+ ret = cdns_mhdp_reg_write(mhdp, DP_BYTE_COUNT, val); -+ if (ret) -+ goto err_config_video; -+ -+ val = mode->htotal | ((mode->htotal - mode->hsync_start) << 16); -+ ret = cdns_mhdp_reg_write(mhdp, MSA_HORIZONTAL_0, val); -+ if (ret) -+ goto err_config_video; -+ -+ val = mode->hsync_end - mode->hsync_start; -+ val |= (mode->hdisplay << 16) | (video->h_sync_polarity << 15); -+ ret = cdns_mhdp_reg_write(mhdp, MSA_HORIZONTAL_1, val); -+ if (ret) -+ goto err_config_video; -+ -+ val = mode->vtotal; -+ val |= (mode->vtotal - mode->vsync_start) << 16; -+ ret = cdns_mhdp_reg_write(mhdp, MSA_VERTICAL_0, val); -+ if (ret) -+ goto err_config_video; -+ -+ val = mode->vsync_end - mode->vsync_start; -+ val |= (mode->vdisplay << 16) | (video->v_sync_polarity << 15); -+ ret = cdns_mhdp_reg_write(mhdp, MSA_VERTICAL_1, val); -+ if (ret) -+ goto err_config_video; -+ -+ val = mhdp_get_msa_misc(video, mode); -+ ret = cdns_mhdp_reg_write(mhdp, MSA_MISC, val); -+ if (ret) -+ goto err_config_video; -+ -+ ret = cdns_mhdp_reg_write(mhdp, STREAM_CONFIG, 1); -+ if (ret) -+ goto err_config_video; -+ -+ val = mode->hsync_end - mode->hsync_start; -+ val |= mode->hdisplay << 16; -+ ret = cdns_mhdp_reg_write(mhdp, DP_HORIZONTAL, val); -+ if (ret) -+ goto err_config_video; -+ -+ val = mode->vdisplay; -+ val |= (mode->vtotal - mode->vsync_start) << 16; -+ ret = cdns_mhdp_reg_write(mhdp, DP_VERTICAL_0, val); -+ if (ret) -+ goto err_config_video; -+ -+ val = mode->vtotal; -+ ret = cdns_mhdp_reg_write(mhdp, DP_VERTICAL_1, val); -+ if (ret) -+ goto err_config_video; -+ -+ ret = cdns_mhdp_reg_write_bit(mhdp, DP_VB_ID, 2, 1, 0); -+ -+err_config_video: -+ if (ret) -+ DRM_DEV_ERROR(mhdp->dev, "config video failed: %d\n", ret); -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_config_video); -+ -+int cdns_phy_reg_write(struct cdns_mhdp_device *mhdp, u32 addr, u32 val) -+{ -+ return cdns_mhdp_reg_write(mhdp, ADDR_PHY_AFE + (addr << 2), val); -+} -+EXPORT_SYMBOL(cdns_phy_reg_write); -+ -+u32 cdns_phy_reg_read(struct cdns_mhdp_device *mhdp, u32 addr) -+{ -+ return cdns_mhdp_reg_read(mhdp, ADDR_PHY_AFE + (addr << 2)); -+} -+EXPORT_SYMBOL(cdns_phy_reg_read); -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c -new file mode 100644 -index 000000000000..f025c39d12ea ---- /dev/null -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c -@@ -0,0 +1,172 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+ -+#include -+#include -+#include -+#include -+ -+#define LINK_TRAINING_TIMEOUT_MS 500 -+#define LINK_TRAINING_RETRY_MS 20 -+ -+int cdns_mhdp_dpcd_read(struct cdns_mhdp_device *mhdp, -+ u32 addr, u8 *data, u16 len) -+{ -+ u8 msg[5], reg[5]; -+ int ret; -+ -+ put_unaligned_be16(len, msg); -+ put_unaligned_be24(addr, msg + 2); -+ -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_READ_DPCD, sizeof(msg), msg); -+ if (ret) -+ goto err_dpcd_read; -+ -+ ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_READ_DPCD, -+ sizeof(reg) + len); -+ if (ret) -+ goto err_dpcd_read; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, reg, sizeof(reg)); -+ if (ret) -+ goto err_dpcd_read; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, data, len); -+ -+err_dpcd_read: -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_dpcd_read); -+ -+int cdns_mhdp_dpcd_write(struct cdns_mhdp_device *mhdp, u32 addr, u8 value) -+{ -+ u8 msg[6], reg[5]; -+ int ret; -+ -+ put_unaligned_be16(1, msg); -+ put_unaligned_be24(addr, msg + 2); -+ msg[5] = value; -+ -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_WRITE_DPCD, sizeof(msg), msg); -+ if (ret) -+ goto err_dpcd_write; -+ -+ ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_WRITE_DPCD, sizeof(reg)); -+ if (ret) -+ goto err_dpcd_write; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, reg, sizeof(reg)); -+ if (ret) -+ goto err_dpcd_write; -+ -+ if (addr != get_unaligned_be24(reg + 2)) -+ ret = -EINVAL; -+ -+err_dpcd_write: -+ if (ret) -+ DRM_DEV_ERROR(mhdp->dev, "dpcd write failed: %d\n", ret); -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_dpcd_write); -+ -+static int cdns_mhdp_training_start(struct cdns_mhdp_device *mhdp) -+{ -+ unsigned long timeout; -+ u8 msg, event[2]; -+ int ret; -+ -+ msg = LINK_TRAINING_RUN; -+ -+ /* start training */ -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_TRAINING_CONTROL, sizeof(msg), &msg); -+ if (ret) -+ goto err_training_start; -+ -+ timeout = jiffies + msecs_to_jiffies(LINK_TRAINING_TIMEOUT_MS); -+ while (time_before(jiffies, timeout)) { -+ msleep(LINK_TRAINING_RETRY_MS); -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_READ_EVENT, 0, NULL); -+ if (ret) -+ goto err_training_start; -+ -+ ret = cdns_mhdp_mailbox_validate_receive(mhdp, -+ MB_MODULE_ID_DP_TX, -+ DPTX_READ_EVENT, -+ sizeof(event)); -+ if (ret) -+ goto err_training_start; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, event, -+ sizeof(event)); -+ if (ret) -+ goto err_training_start; -+ -+ if (event[1] & EQ_PHASE_FINISHED) -+ return 0; -+ } -+ -+ ret = -ETIMEDOUT; -+ -+err_training_start: -+ DRM_DEV_ERROR(mhdp->dev, "training failed: %d\n", ret); -+ return ret; -+} -+ -+static int cdns_mhdp_get_training_status(struct cdns_mhdp_device *mhdp) -+{ -+ u8 status[10]; -+ int ret; -+ -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_READ_LINK_STAT, 0, NULL); -+ if (ret) -+ goto err_get_training_status; -+ -+ ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_DP_TX, -+ DPTX_READ_LINK_STAT, -+ sizeof(status)); -+ if (ret) -+ goto err_get_training_status; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, status, sizeof(status)); -+ if (ret) -+ goto err_get_training_status; -+ -+ mhdp->dp.rate = drm_dp_bw_code_to_link_rate(status[0]); -+ mhdp->dp.num_lanes = status[1]; -+ -+err_get_training_status: -+ if (ret) -+ DRM_DEV_ERROR(mhdp->dev, "get training status failed: %d\n", -+ ret); -+ return ret; -+} -+ -+int cdns_mhdp_train_link(struct cdns_mhdp_device *mhdp) -+{ -+ int ret; -+ -+ ret = cdns_mhdp_training_start(mhdp); -+ if (ret) { -+ DRM_DEV_ERROR(mhdp->dev, "Failed to start training %d\n", -+ ret); -+ return ret; -+ } -+ -+ ret = cdns_mhdp_get_training_status(mhdp); -+ if (ret) { -+ DRM_DEV_ERROR(mhdp->dev, "Failed to get training stat %d\n", -+ ret); -+ return ret; -+ } -+ -+ DRM_DEV_DEBUG_KMS(mhdp->dev, "rate:0x%x, lanes:%d\n", mhdp->dp.rate, -+ mhdp->dp.num_lanes); -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_train_link); -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdmi.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdmi.c -new file mode 100644 -index 000000000000..c37a7ac6af9b ---- /dev/null -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdmi.c -@@ -0,0 +1,332 @@ -+/* -+ * Copyright (C) 2019 NXP Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+void cdns_mhdp_infoframe_set(struct cdns_mhdp_device *mhdp, -+ u8 entry_id, u8 packet_len, u8 *packet, u8 packet_type) -+{ -+ u32 *packet32, len32; -+ u32 val, i; -+ -+ /* invalidate entry */ -+ val = F_ACTIVE_IDLE_TYPE(1) | F_PKT_ALLOC_ADDRESS(entry_id); -+ cdns_mhdp_bus_write(val, mhdp, SOURCE_PIF_PKT_ALLOC_REG); -+ cdns_mhdp_bus_write(F_PKT_ALLOC_WR_EN(1), mhdp, SOURCE_PIF_PKT_ALLOC_WR_EN); -+ -+ /* flush fifo 1 */ -+ cdns_mhdp_bus_write(F_FIFO1_FLUSH(1), mhdp, SOURCE_PIF_FIFO1_FLUSH); -+ -+ /* write packet into memory */ -+ packet32 = (u32 *)packet; -+ len32 = packet_len / 4; -+ for (i = 0; i < len32; i++) -+ cdns_mhdp_bus_write(F_DATA_WR(packet32[i]), mhdp, SOURCE_PIF_DATA_WR); -+ -+ /* write entry id */ -+ cdns_mhdp_bus_write(F_WR_ADDR(entry_id), mhdp, SOURCE_PIF_WR_ADDR); -+ -+ /* write request */ -+ cdns_mhdp_bus_write(F_HOST_WR(1), mhdp, SOURCE_PIF_WR_REQ); -+ -+ /* update entry */ -+ val = F_ACTIVE_IDLE_TYPE(1) | F_TYPE_VALID(1) | -+ F_PACKET_TYPE(packet_type) | F_PKT_ALLOC_ADDRESS(entry_id); -+ cdns_mhdp_bus_write(val, mhdp, SOURCE_PIF_PKT_ALLOC_REG); -+ -+ cdns_mhdp_bus_write(F_PKT_ALLOC_WR_EN(1), mhdp, SOURCE_PIF_PKT_ALLOC_WR_EN); -+} -+ -+int cdns_hdmi_get_edid_block(void *data, u8 *edid, -+ u32 block, size_t length) -+{ -+ struct cdns_mhdp_device *mhdp = data; -+ u8 msg[2], reg[5], i; -+ int ret; -+ -+ for (i = 0; i < 4; i++) { -+ msg[0] = block / 2; -+ msg[1] = block % 2; -+ -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_HDMI_TX, HDMI_TX_EDID, -+ sizeof(msg), msg); -+ if (ret) -+ continue; -+ -+ ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_HDMI_TX, -+ HDMI_TX_EDID, sizeof(reg) + length); -+ if (ret) -+ continue; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, reg, sizeof(reg)); -+ if (ret) -+ continue; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, edid, length); -+ if (ret) -+ continue; -+ -+ if ((reg[3] << 8 | reg[4]) == length) -+ break; -+ } -+ -+ if (ret) -+ DRM_ERROR("get block[%d] edid failed: %d\n", block, ret); -+ return ret; -+} -+ -+int cdns_hdmi_scdc_read(struct cdns_mhdp_device *mhdp, u8 addr, u8 *data) -+{ -+ u8 msg[4], reg[6]; -+ int ret; -+ -+ msg[0] = 0x54; -+ msg[1] = addr; -+ msg[2] = 0; -+ msg[3] = 1; -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_HDMI_TX, HDMI_TX_READ, -+ sizeof(msg), msg); -+ if (ret) -+ goto err_scdc_read; -+ -+ ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_HDMI_TX, -+ HDMI_TX_READ, sizeof(reg)); -+ if (ret) -+ goto err_scdc_read; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, reg, sizeof(reg)); -+ if (ret) -+ goto err_scdc_read; -+ -+ *data = reg[5]; -+ -+err_scdc_read: -+ if (ret) -+ DRM_ERROR("scdc read failed: %d\n", ret); -+ return ret; -+} -+ -+int cdns_hdmi_scdc_write(struct cdns_mhdp_device *mhdp, u8 addr, u8 value) -+{ -+ u8 msg[5], reg[5]; -+ int ret; -+ -+ msg[0] = 0x54; -+ msg[1] = addr; -+ msg[2] = 0; -+ msg[3] = 1; -+ msg[4] = value; -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_HDMI_TX, HDMI_TX_WRITE, -+ sizeof(msg), msg); -+ if (ret) -+ goto err_scdc_write; -+ -+ ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_HDMI_TX, -+ HDMI_TX_WRITE, sizeof(reg)); -+ if (ret) -+ goto err_scdc_write; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, reg, sizeof(reg)); -+ if (ret) -+ goto err_scdc_write; -+ -+ if (reg[0] != 0) -+ ret = -EINVAL; -+ -+err_scdc_write: -+ if (ret) -+ DRM_ERROR("scdc write failed: %d\n", ret); -+ return ret; -+} -+ -+int cdns_hdmi_ctrl_init(struct cdns_mhdp_device *mhdp, -+ int protocol, -+ u32 char_rate) -+{ -+ u32 reg0; -+ u32 reg1; -+ u32 val; -+ int ret; -+ -+ /* Set PHY to HDMI data */ -+ ret = cdns_mhdp_reg_write(mhdp, PHY_DATA_SEL, F_SOURCE_PHY_MHDP_SEL(1)); -+ if (ret < 0) -+ return ret; -+ -+ ret = cdns_mhdp_reg_write(mhdp, HDTX_HPD, -+ F_HPD_VALID_WIDTH(4) | F_HPD_GLITCH_WIDTH(0)); -+ if (ret < 0) -+ return ret; -+ -+ /* open CARS */ -+ ret = cdns_mhdp_reg_write(mhdp, SOURCE_PHY_CAR, 0xF); -+ if (ret < 0) -+ return ret; -+ ret = cdns_mhdp_reg_write(mhdp, SOURCE_HDTX_CAR, 0xFF); -+ if (ret < 0) -+ return ret; -+ ret = cdns_mhdp_reg_write(mhdp, SOURCE_PKT_CAR, 0xF); -+ if (ret < 0) -+ return ret; -+ ret = cdns_mhdp_reg_write(mhdp, SOURCE_AIF_CAR, 0xF); -+ if (ret < 0) -+ return ret; -+ ret = cdns_mhdp_reg_write(mhdp, SOURCE_CIPHER_CAR, 0xF); -+ if (ret < 0) -+ return ret; -+ ret = cdns_mhdp_reg_write(mhdp, SOURCE_CRYPTO_CAR, 0xF); -+ if (ret < 0) -+ return ret; -+ ret = cdns_mhdp_reg_write(mhdp, SOURCE_CEC_CAR, 3); -+ if (ret < 0) -+ return ret; -+ -+ reg0 = reg1 = 0x7c1f; -+ if (protocol == MODE_HDMI_2_0 && char_rate >= 340000) { -+ reg0 = 0; -+ reg1 = 0xFFFFF; -+ } -+ ret = cdns_mhdp_reg_write(mhdp, HDTX_CLOCK_REG_0, reg0); -+ if (ret < 0) -+ return ret; -+ ret = cdns_mhdp_reg_write(mhdp, HDTX_CLOCK_REG_1, reg1); -+ if (ret < 0) -+ return ret; -+ -+ /* set hdmi mode and preemble mode data enable */ -+ val = F_HDMI_MODE(protocol) | F_HDMI2_PREAMBLE_EN(1) | F_DATA_EN(1) | -+ F_HDMI2_CTRL_IL_MODE(1) | F_BCH_EN(1) | F_PIC_3D(0XF); -+ ret = cdns_mhdp_reg_write(mhdp, HDTX_CONTROLLER, val); -+ -+ return ret; -+} -+ -+int cdns_hdmi_mode_config(struct cdns_mhdp_device *mhdp, -+ struct drm_display_mode *mode, -+ struct video_info *video_info) -+{ -+ int ret; -+ u32 val; -+ u32 vsync_lines = mode->vsync_end - mode->vsync_start; -+ u32 eof_lines = mode->vsync_start - mode->vdisplay; -+ u32 sof_lines = mode->vtotal - mode->vsync_end; -+ u32 hblank = mode->htotal - mode->hdisplay; -+ u32 hactive = mode->hdisplay; -+ u32 vblank = mode->vtotal - mode->vdisplay; -+ u32 vactive = mode->vdisplay; -+ u32 hfront = mode->hsync_start - mode->hdisplay; -+ u32 hback = mode->htotal - mode->hsync_end; -+ u32 vfront = eof_lines; -+ u32 hsync = hblank - hfront - hback; -+ u32 vsync = vsync_lines; -+ u32 vback = sof_lines; -+ u32 v_h_polarity = ((mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1) + -+ ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : 2); -+ -+ ret = cdns_mhdp_reg_write(mhdp, SCHEDULER_H_SIZE, (hactive << 16) + hblank); -+ if (ret < 0) -+ return ret; -+ -+ ret = cdns_mhdp_reg_write(mhdp, SCHEDULER_V_SIZE, (vactive << 16) + vblank); -+ if (ret < 0) -+ return ret; -+ -+ ret = cdns_mhdp_reg_write(mhdp, HDTX_SIGNAL_FRONT_WIDTH, (vfront << 16) + hfront); -+ if (ret < 0) -+ return ret; -+ -+ ret = cdns_mhdp_reg_write(mhdp, HDTX_SIGNAL_SYNC_WIDTH, (vsync << 16) + hsync); -+ if (ret < 0) -+ return ret; -+ -+ ret = cdns_mhdp_reg_write(mhdp, HDTX_SIGNAL_BACK_WIDTH, (vback << 16) + hback); -+ if (ret < 0) -+ return ret; -+ -+ ret = cdns_mhdp_reg_write(mhdp, HSYNC2VSYNC_POL_CTRL, v_h_polarity); -+ if (ret < 0) -+ return ret; -+ -+ /* Reset Data Enable */ -+ val = cdns_mhdp_reg_read(mhdp, HDTX_CONTROLLER); -+ val &= ~F_DATA_EN(1); -+ ret = cdns_mhdp_reg_write(mhdp, HDTX_CONTROLLER, val); -+ if (ret < 0) -+ return ret; -+ -+ /* Set bpc */ -+ val &= ~F_VIF_DATA_WIDTH(3); -+ switch (video_info->color_depth) { -+ case 10: -+ val |= F_VIF_DATA_WIDTH(1); -+ break; -+ case 12: -+ val |= F_VIF_DATA_WIDTH(2); -+ break; -+ case 16: -+ val |= F_VIF_DATA_WIDTH(3); -+ break; -+ case 8: -+ default: -+ val |= F_VIF_DATA_WIDTH(0); -+ break; -+ } -+ -+ /* select color encoding */ -+ val &= ~F_HDMI_ENCODING(3); -+ switch (video_info->color_fmt) { -+ case YCBCR_4_4_4: -+ val |= F_HDMI_ENCODING(2); -+ break; -+ case YCBCR_4_2_2: -+ val |= F_HDMI_ENCODING(1); -+ break; -+ case YCBCR_4_2_0: -+ val |= F_HDMI_ENCODING(3); -+ break; -+ case PXL_RGB: -+ default: -+ val |= F_HDMI_ENCODING(0); -+ break; -+ } -+ -+ ret = cdns_mhdp_reg_write(mhdp, HDTX_CONTROLLER, val); -+ if (ret < 0) -+ return ret; -+ -+ /* set data enable */ -+ val |= F_DATA_EN(1); -+ ret = cdns_mhdp_reg_write(mhdp, HDTX_CONTROLLER, val); -+ -+ return ret; -+} -+ -+int cdns_hdmi_disable_gcp(struct cdns_mhdp_device *mhdp) -+{ -+ u32 val; -+ -+ val = cdns_mhdp_reg_read(mhdp, HDTX_CONTROLLER); -+ val &= ~F_GCP_EN(1); -+ -+ return cdns_mhdp_reg_write(mhdp, HDTX_CONTROLLER, val); -+} -+ -+int cdns_hdmi_enable_gcp(struct cdns_mhdp_device *mhdp) -+{ -+ u32 val; -+ -+ val = cdns_mhdp_reg_read(mhdp, HDTX_CONTROLLER); -+ val |= F_GCP_EN(1); -+ -+ return cdns_mhdp_reg_write(mhdp, HDTX_CONTROLLER, val); -+} -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp.h -new file mode 100644 -index 000000000000..399c3f6f86ad ---- /dev/null -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp.h -@@ -0,0 +1,209 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+/* -+ * Cadence MHDP DP MST bridge driver. -+ * -+ * Copyright: 2018 Cadence Design Systems, Inc. -+ * -+ * Author: Quentin Schulz -+ */ -+ -+ -+#ifndef CDNS_MHDP_H -+#define CDNS_MHDP_H -+ -+#include -+ -+#define CDNS_APB_CFG 0x00000 -+#define CDNS_APB_CTRL (CDNS_APB_CFG + 0x00) -+#define CDNS_MAILBOX_FULL (CDNS_APB_CFG + 0x08) -+#define CDNS_MAILBOX_EMPTY (CDNS_APB_CFG + 0x0c) -+#define CDNS_MAILBOX_TX_DATA (CDNS_APB_CFG + 0x10) -+#define CDNS_MAILBOX_RX_DATA (CDNS_APB_CFG + 0x14) -+#define CDNS_KEEP_ALIVE (CDNS_APB_CFG + 0x18) -+#define CDNS_KEEP_ALIVE_MASK GENMASK(7, 0) -+ -+#define CDNS_MB_INT_MASK (CDNS_APB_CFG + 0x34) -+ -+#define CDNS_SW_CLK_L (CDNS_APB_CFG + 0x3c) -+#define CDNS_SW_CLK_H (CDNS_APB_CFG + 0x40) -+#define CDNS_SW_EVENT0 (CDNS_APB_CFG + 0x44) -+#define CDNS_DPTX_HPD BIT(0) -+ -+#define CDNS_SW_EVENT1 (CDNS_APB_CFG + 0x48) -+#define CDNS_SW_EVENT2 (CDNS_APB_CFG + 0x4c) -+#define CDNS_SW_EVENT3 (CDNS_APB_CFG + 0x50) -+ -+#define CDNS_APB_INT_MASK (CDNS_APB_CFG + 0x6C) -+#define CDNS_APB_INT_MASK_MAILBOX_INT BIT(0) -+#define CDNS_APB_INT_MASK_SW_EVENT_INT BIT(1) -+ -+#define CDNS_DPTX_CAR (CDNS_APB_CFG + 0x904) -+#define CDNS_VIF_CLK_EN BIT(0) -+#define CDNS_VIF_CLK_RSTN BIT(1) -+ -+#define CDNS_SOURCE_VIDEO_IF(s) (0x00b00 + (s * 0x20)) -+#define CDNS_BND_HSYNC2VSYNC(s) (CDNS_SOURCE_VIDEO_IF(s) + \ -+ 0x00) -+#define CDNS_IP_DTCT_WIN GENMASK(11, 0) -+#define CDNS_IP_DET_INTERLACE_FORMAT BIT(12) -+#define CDNS_IP_BYPASS_V_INTERFACE BIT(13) -+ -+#define CDNS_HSYNC2VSYNC_POL_CTRL(s) (CDNS_SOURCE_VIDEO_IF(s) + \ -+ 0x10) -+#define CDNS_H2V_HSYNC_POL_ACTIVE_LOW BIT(1) -+#define CDNS_H2V_VSYNC_POL_ACTIVE_LOW BIT(2) -+ -+#define CDNS_DPTX_PHY_CONFIG 0x02000 -+#define CDNS_PHY_TRAINING_EN BIT(0) -+#define CDNS_PHY_TRAINING_TYPE(x) (((x) & GENMASK(3, 0)) << 1) -+#define CDNS_PHY_SCRAMBLER_BYPASS BIT(5) -+#define CDNS_PHY_ENCODER_BYPASS BIT(6) -+#define CDNS_PHY_SKEW_BYPASS BIT(7) -+#define CDNS_PHY_TRAINING_AUTO BIT(8) -+#define CDNS_PHY_LANE0_SKEW(x) (((x) & GENMASK(2, 0)) << 9) -+#define CDNS_PHY_LANE1_SKEW(x) (((x) & GENMASK(2, 0)) << 12) -+#define CDNS_PHY_LANE2_SKEW(x) (((x) & GENMASK(2, 0)) << 15) -+#define CDNS_PHY_LANE3_SKEW(x) (((x) & GENMASK(2, 0)) << 18) -+#define CDNS_PHY_COMMON_CONFIG (CDNS_PHY_LANE1_SKEW(1) | \ -+ CDNS_PHY_LANE2_SKEW(2) | \ -+ CDNS_PHY_LANE3_SKEW(3)) -+#define CDNS_PHY_10BIT_EN BIT(21) -+ -+#define CDNS_DPTX_FRAMER 0x02200 -+#define CDNS_DP_FRAMER_GLOBAL_CONFIG (CDNS_DPTX_FRAMER + 0x00) -+#define CDNS_DP_NUM_LANES(x) (x - 1) -+#define CDNS_DP_MST_EN BIT(2) -+#define CDNS_DP_FRAMER_EN BIT(3) -+#define CDNS_DP_RATE_GOVERNOR_EN BIT(4) -+#define CDNS_DP_NO_VIDEO_MODE BIT(5) -+#define CDNS_DP_DISABLE_PHY_RST BIT(6) -+#define CDNS_DP_WR_FAILING_EDGE_VSYNC BIT(7) -+ -+#define CDNS_DP_SW_RESET (CDNS_DPTX_FRAMER + 0x04) -+#define CDNS_DP_FRAMER_TU (CDNS_DPTX_FRAMER + 0x08) -+#define CDNS_DP_FRAMER_TU_SIZE(x) (((x) & GENMASK(6, 0)) << 8) -+#define CDNS_DP_FRAMER_TU_VS(x) ((x) & GENMASK(5, 0)) -+#define CDNS_DP_FRAMER_TU_CNT_RST_EN BIT(15) -+ -+#define CDNS_DPTX_STREAM(s) (0x03000 + s * 0x80) -+#define CDNS_DP_MSA_HORIZONTAL_0(s) (CDNS_DPTX_STREAM(s) + 0x00) -+#define CDNS_DP_MSAH0_H_TOTAL(x) (x) -+#define CDNS_DP_MSAH0_HSYNC_START(x) ((x) << 16) -+ -+#define CDNS_DP_MSA_HORIZONTAL_1(s) (CDNS_DPTX_STREAM(s) + 0x04) -+#define CDNS_DP_MSAH1_HSYNC_WIDTH(x) (x) -+#define CDNS_DP_MSAH1_HSYNC_POL_LOW BIT(15) -+#define CDNS_DP_MSAH1_HDISP_WIDTH(x) ((x) << 16) -+ -+#define CDNS_DP_MSA_VERTICAL_0(s) (CDNS_DPTX_STREAM(s) + 0x08) -+#define CDNS_DP_MSAV0_V_TOTAL(x) (x) -+#define CDNS_DP_MSAV0_VSYNC_START(x) ((x) << 16) -+ -+#define CDNS_DP_MSA_VERTICAL_1(s) (CDNS_DPTX_STREAM(s) + 0x0c) -+#define CDNS_DP_MSAV1_VSYNC_WIDTH(x) (x) -+#define CDNS_DP_MSAV1_VSYNC_POL_LOW BIT(15) -+#define CDNS_DP_MSAV1_VDISP_WIDTH(x) ((x) << 16) -+ -+#define CDNS_DP_MSA_MISC(s) (CDNS_DPTX_STREAM(s) + 0x10) -+#define CDNS_DP_STREAM_CONFIGs(s) (CDNS_DPTX_STREAM(s) + 0x14) -+#define CDNS_DP_STREAM_CONFIG_2(s) (CDNS_DPTX_STREAM(s) + 0x2c) -+#define CDNS_DP_SC2_TU_VS_DIFF(x) ((x) << 8) -+ -+#define CDNS_DP_HORIZONTAL(s) (CDNS_DPTX_STREAM(s) + 0x30) -+#define CDNS_DP_H_HSYNC_WIDTH(x) (x) -+#define CDNS_DP_H_H_TOTAL(x) ((x) << 16) -+ -+#define CDNS_DP_VERTICAL_0(s) (CDNS_DPTX_STREAM(s) + 0x34) -+#define CDNS_DP_V0_VHEIGHT(x) (x) -+#define CDNS_DP_V0_VSTART(x) ((x) << 16) -+ -+#define CDNS_DP_VERTICAL_1(s) (CDNS_DPTX_STREAM(s) + 0x38) -+#define CDNS_DP_V1_VTOTAL(x) (x) -+#define CDNS_DP_V1_VTOTAL_EVEN BIT(16) -+ -+#define CDNS_DP_FRAMER_PXL_REPR(s) (CDNS_DPTX_STREAM(s) + 0x4c) -+#define CDNS_DP_FRAMER_6_BPC BIT(0) -+#define CDNS_DP_FRAMER_8_BPC BIT(1) -+#define CDNS_DP_FRAMER_10_BPC BIT(2) -+#define CDNS_DP_FRAMER_12_BPC BIT(3) -+#define CDNS_DP_FRAMER_16_BPC BIT(4) -+#define CDNS_DP_FRAMER_PXL_FORMAT 0x8 -+#define CDNS_DP_FRAMER_RGB BIT(0) -+#define CDNS_DP_FRAMER_YCBCR444 BIT(1) -+#define CDNS_DP_FRAMER_YCBCR422 BIT(2) -+#define CDNS_DP_FRAMER_YCBCR420 BIT(3) -+#define CDNS_DP_FRAMER_Y_ONLY BIT(4) -+ -+#define CDNS_DP_FRAMER_SP(s) (CDNS_DPTX_STREAM(s) + 0x10) -+#define CDNS_DP_FRAMER_VSYNC_POL_LOW BIT(0) -+#define CDNS_DP_FRAMER_HSYNC_POL_LOW BIT(1) -+#define CDNS_DP_FRAMER_INTERLACE BIT(2) -+ -+#define CDNS_DP_LINE_THRESH(s) (CDNS_DPTX_STREAM(s) + 0x64) -+#define CDNS_DP_ACTIVE_LINE_THRESH(x) (x) -+ -+#define CDNS_DP_VB_ID(s) (CDNS_DPTX_STREAM(s) + 0x68) -+#define CDNS_DP_VB_ID_INTERLACED BIT(2) -+#define CDNS_DP_VB_ID_COMPRESSED BIT(6) -+ -+#define CDNS_DP_FRONT_BACK_PORCH(s) (CDNS_DPTX_STREAM(s) + 0x78) -+#define CDNS_DP_BACK_PORCH(x) (x) -+#define CDNS_DP_FRONT_PORCH(x) ((x) << 16) -+ -+#define CDNS_DP_BYTE_COUNT(s) (CDNS_DPTX_STREAM(s) + 0x7c) -+#define CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT 16 -+ -+#define CDNS_DP_MST_STREAM_CONFIG(s) (CDNS_DPTX_STREAM(s) + 0x14) -+#define CDNS_DP_MST_STRM_CFG_STREAM_EN BIT(0) -+#define CDNS_DP_MST_STRM_CFG_NO_VIDEO BIT(1) -+ -+#define CDNS_DP_MST_SLOT_ALLOCATE(s) (CDNS_DPTX_STREAM(s) + 0x44) -+#define CDNS_DP_S_ALLOC_START_SLOT(x) (x) -+#define CDNS_DP_S_ALLOC_END_SLOT(x) ((x) << 8) -+ -+#define CDNS_DP_RATE_GOVERNING(s) (CDNS_DPTX_STREAM(s) + 0x48) -+#define CDNS_DP_RG_TARG_AV_SLOTS_Y(x) (x) -+#define CDNS_DP_RG_TARG_AV_SLOTS_X(x) (x << 4) -+#define CDNS_DP_RG_ENABLE BIT(10) -+ -+#define CDNS_DP_MTPH_CONTROL 0x2264 -+#define CDNS_DP_MTPH_ECF_EN BIT(0) -+#define CDNS_DP_MTPH_ACT_EN BIT(1) -+#define CDNS_DP_MTPH_LVP_EN BIT(2) -+ -+#define CDNS_DP_MTPH_STATUS 0x226C -+#define CDNS_DP_MTPH_ACT_STATUS BIT(0) -+ -+ -+#define CDNS_DPTX_GLOBAL 0x02300 -+#define CDNS_DP_LANE_EN (CDNS_DPTX_GLOBAL + 0x00) -+#define CDNS_DP_LANE_EN_LANES(x) GENMASK(x - 1, 0) -+#define CDNS_DP_ENHNCD (CDNS_DPTX_GLOBAL + 0x04) -+ -+ -+#define to_mhdp_connector(x) container_of(x, struct cdns_mhdp_connector, base) -+#define to_mhdp_bridge(x) container_of(x, struct cdns_mhdp_bridge, base) -+#define mgr_to_mhdp(x) container_of(x, struct cdns_mhdp_device, mst_mgr) -+ -+#define CDNS_MHDP_MAX_STREAMS 4 -+ -+enum pixel_format { -+ PIXEL_FORMAT_RGB = 1, -+ PIXEL_FORMAT_YCBCR_444 = 2, -+ PIXEL_FORMAT_YCBCR_422 = 4, -+ PIXEL_FORMAT_YCBCR_420 = 8, -+ PIXEL_FORMAT_Y_ONLY = 16, -+}; -+ -+ -+int cdns_mhdp_mst_init(struct cdns_mhdp_device *mhdp); -+void cdns_mhdp_mst_deinit(struct cdns_mhdp_device *mhdp); -+bool cdns_mhdp_mst_probe(struct cdns_mhdp_device *mhdp); -+enum pixel_format cdns_mhdp_get_pxlfmt(u32 color_formats); -+u32 cdns_mhdp_get_bpp(u32 bpc, u32 color_formats); -+void cdns_mhdp_configure_video(struct drm_bridge *bridge); -+void cdns_mhdp_mst_enable(struct drm_bridge *bridge); -+void cdns_mhdp_mst_disable(struct drm_bridge *bridge); -+void cdns_mhdp_enable(struct drm_bridge *bridge); -+ -+#endif -diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile -index 17a9e7eb2130..bd013659404f 100644 ---- a/drivers/gpu/drm/rockchip/Makefile -+++ b/drivers/gpu/drm/rockchip/Makefile -@@ -8,7 +8,7 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ - rockchipdrm-$(CONFIG_ROCKCHIP_VOP2) += rockchip_drm_vop2.o rockchip_vop2_reg.o - rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o - rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o --rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o -+rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o - rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o - rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi-rockchip.o - rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o -diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c -index a4a45daf93f2..058bc372f02b 100644 ---- a/drivers/gpu/drm/rockchip/cdn-dp-core.c -+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c -@@ -23,11 +23,10 @@ - #include - - #include "cdn-dp-core.h" --#include "cdn-dp-reg.h" - #include "rockchip_drm_vop.h" - - static inline struct cdn_dp_device *connector_to_dp(struct drm_connector *connector) - { -- return container_of(connector, struct cdn_dp_device, connector); -+ return container_of(connector, struct cdn_dp_device, mhdp.connector.base); - } - -@@ -62,17 +61,18 @@ MODULE_DEVICE_TABLE(of, cdn_dp_dt_ids); - static int cdn_dp_grf_write(struct cdn_dp_device *dp, - unsigned int reg, unsigned int val) - { -+ struct device *dev = dp->mhdp.dev; - int ret; - - ret = clk_prepare_enable(dp->grf_clk); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "Failed to prepare_enable grf clock\n"); -+ DRM_DEV_ERROR(dev, "Failed to prepare_enable grf clock\n"); - return ret; - } - - ret = regmap_write(dp->grf, reg, val); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "Could not write to GRF: %d\n", ret); -+ DRM_DEV_ERROR(dev, "Could not write to GRF: %d\n", ret); - clk_disable_unprepare(dp->grf_clk); - return ret; - } -@@ -83,24 +83,25 @@ static int cdn_dp_grf_write(struct cdn_dp_device *dp, - - static int cdn_dp_clk_enable(struct cdn_dp_device *dp) - { -+ struct device *dev = dp->mhdp.dev; - int ret; - unsigned long rate; - - ret = clk_prepare_enable(dp->pclk); - if (ret < 0) { -- DRM_DEV_ERROR(dp->dev, "cannot enable dp pclk %d\n", ret); -+ DRM_DEV_ERROR(dev, "cannot enable dp pclk %d\n", ret); - goto err_pclk; - } - - ret = clk_prepare_enable(dp->core_clk); - if (ret < 0) { -- DRM_DEV_ERROR(dp->dev, "cannot enable core_clk %d\n", ret); -+ DRM_DEV_ERROR(dev, "cannot enable core_clk %d\n", ret); - goto err_core_clk; - } - -- ret = pm_runtime_get_sync(dp->dev); -+ ret = pm_runtime_get_sync(dev); - if (ret < 0) { -- DRM_DEV_ERROR(dp->dev, "cannot get pm runtime %d\n", ret); -+ DRM_DEV_ERROR(dev, "cannot get pm runtime %d\n", ret); - goto err_pm_runtime_get; - } - -@@ -113,18 +114,18 @@ static int cdn_dp_clk_enable(struct cdn_dp_device *dp) - - rate = clk_get_rate(dp->core_clk); - if (!rate) { -- DRM_DEV_ERROR(dp->dev, "get clk rate failed\n"); -+ DRM_DEV_ERROR(dev, "get clk rate failed\n"); - ret = -EINVAL; - goto err_set_rate; - } - -- cdn_dp_set_fw_clk(dp, rate); -- cdn_dp_clock_reset(dp); -+ cdns_mhdp_set_fw_clk(&dp->mhdp, rate); -+ cdns_mhdp_clock_reset(&dp->mhdp); - - return 0; - - err_set_rate: -- pm_runtime_put(dp->dev); -+ pm_runtime_put(dev); - err_pm_runtime_get: - clk_disable_unprepare(dp->core_clk); - err_core_clk: -@@ -135,7 +136,7 @@ static int cdn_dp_clk_enable(struct cdn_dp_device *dp) - - static void cdn_dp_clk_disable(struct cdn_dp_device *dp) - { -- pm_runtime_put_sync(dp->dev); -+ pm_runtime_put_sync(dp->mhdp.dev); - clk_disable_unprepare(dp->pclk); - clk_disable_unprepare(dp->core_clk); - } -@@ -168,7 +169,7 @@ static int cdn_dp_get_sink_count(struct cdn_dp_device *dp, u8 *sink_count) - u8 value; - - *sink_count = 0; -- ret = cdn_dp_dpcd_read(dp, DP_SINK_COUNT, &value, 1); -+ ret = drm_dp_dpcd_read(&dp->mhdp.dp.aux, DP_SINK_COUNT, &value, 1); - if (ret) - return ret; - -@@ -192,12 +193,13 @@ static struct cdn_dp_port *cdn_dp_connected_port(struct cdn_dp_device *dp) - - static bool cdn_dp_check_sink_connection(struct cdn_dp_device *dp) - { -+ struct device *dev = dp->mhdp.dev; - unsigned long timeout = jiffies + msecs_to_jiffies(CDN_DPCD_TIMEOUT_MS); - struct cdn_dp_port *port; - u8 sink_count = 0; - - if (dp->active_port < 0 || dp->active_port >= dp->ports) { -- DRM_DEV_ERROR(dp->dev, "active_port is wrong!\n"); -+ DRM_DEV_ERROR(dev, "active_port is wrong!\n"); - return false; - } - -@@ -219,7 +221,7 @@ static bool cdn_dp_check_sink_connection(struct cdn_dp_device *dp) - usleep_range(5000, 10000); - } - -- DRM_DEV_ERROR(dp->dev, "Get sink capability timed out\n"); -+ DRM_DEV_ERROR(dev, "Get sink capability timed out\n"); - return false; - } - -@@ -261,7 +263,8 @@ static int cdn_dp_connector_get_modes(struct drm_connector *connector) - mutex_lock(&dp->lock); - edid = dp->edid; - if (edid) { -- DRM_DEV_DEBUG_KMS(dp->dev, "got edid: width[%d] x height[%d]\n", -+ DRM_DEV_DEBUG_KMS(dp->mhdp.dev, -+ "got edid: width[%d] x height[%d]\n", - edid->width_cm, edid->height_cm); - - dp->sink_has_audio = drm_detect_monitor_audio(edid); -@@ -279,7 +282,8 @@ cdn_dp_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) - { - struct cdn_dp_device *dp = connector_to_dp(connector); -- struct drm_display_info *display_info = &dp->connector.display_info; -+ struct drm_display_info *display_info = -+ &dp->mhdp.connector.base.display_info; - u32 requested, actual, rate, sink_max, source_max = 0; - u8 lanes, bpc; - -@@ -302,11 +306,11 @@ static int cdn_dp_connector_mode_valid(struct drm_connector *connector, - requested = mode->clock * bpc * 3 / 1000; - - source_max = dp->lanes; -- sink_max = drm_dp_max_lane_count(dp->dpcd); -+ sink_max = drm_dp_max_lane_count(dp->mhdp.dp.dpcd); - lanes = min(source_max, sink_max); - -- source_max = drm_dp_bw_code_to_link_rate(CDN_DP_MAX_LINK_RATE); -- sink_max = drm_dp_max_link_rate(dp->dpcd); -+ source_max = CDNS_DP_MAX_LINK_RATE; -+ sink_max = drm_dp_max_link_rate(dp->mhdp.dp.dpcd); - rate = min(source_max, sink_max); - - actual = rate * lanes / 100; -@@ -315,7 +319,7 @@ static int cdn_dp_connector_mode_valid(struct drm_connector *connector, - actual = actual * 8 / 10; - - if (requested > actual) { -- DRM_DEV_DEBUG_KMS(dp->dev, -+ DRM_DEV_DEBUG_KMS(dp->mhdp.dev, - "requested=%d, actual=%d, clock=%d\n", - requested, actual, mode->clock); - return MODE_CLOCK_HIGH; -@@ -335,59 +339,62 @@ static int cdn_dp_firmware_init(struct cdn_dp_device *dp) - const u32 *iram_data, *dram_data; - const struct firmware *fw = dp->fw; - const struct cdn_firmware_header *hdr; -+ struct device *dev = dp->mhdp.dev; - - hdr = (struct cdn_firmware_header *)fw->data; - if (fw->size != le32_to_cpu(hdr->size_bytes)) { -- DRM_DEV_ERROR(dp->dev, "firmware is invalid\n"); -+ DRM_DEV_ERROR(dev, "firmware is invalid\n"); - return -EINVAL; - } - - iram_data = (const u32 *)(fw->data + hdr->header_size); - dram_data = (const u32 *)(fw->data + hdr->header_size + hdr->iram_size); - -- ret = cdn_dp_load_firmware(dp, iram_data, hdr->iram_size, -- dram_data, hdr->dram_size); -+ ret = cdns_mhdp_load_firmware(&dp->mhdp, iram_data, hdr->iram_size, -+ dram_data, hdr->dram_size); - if (ret) - return ret; - -- ret = cdn_dp_set_firmware_active(dp, true); -+ ret = cdns_mhdp_set_firmware_active(&dp->mhdp, true); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "active ucpu failed: %d\n", ret); -+ DRM_DEV_ERROR(dev, "active ucpu failed: %d\n", ret); - return ret; - } - -- return cdn_dp_event_config(dp); -+ return cdns_mhdp_event_config(&dp->mhdp); - } - - static int cdn_dp_get_sink_capability(struct cdn_dp_device *dp) - { -+ struct cdns_mhdp_device *mhdp = &dp->mhdp; - int ret; - - if (!cdn_dp_check_sink_connection(dp)) - return -ENODEV; - -- ret = cdn_dp_dpcd_read(dp, DP_DPCD_REV, dp->dpcd, -+ ret = drm_dp_dpcd_read(&mhdp->dp.aux, DP_DPCD_REV, mhdp->dp.dpcd, - DP_RECEIVER_CAP_SIZE); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret); -+ DRM_DEV_ERROR(mhdp->dev, "Failed to get caps %d\n", ret); - return ret; - } - - kfree(dp->edid); -- dp->edid = drm_do_get_edid(&dp->connector, -- cdn_dp_get_edid_block, dp); -+ dp->edid = drm_do_get_edid(&mhdp->connector.base, -+ cdns_mhdp_get_edid_block, mhdp); - return 0; - } - - static int cdn_dp_enable_phy(struct cdn_dp_device *dp, struct cdn_dp_port *port) - { -+ struct device *dev = dp->mhdp.dev; - union extcon_property_value property; - int ret; - - if (!port->phy_enabled) { - ret = phy_power_on(port->phy); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "phy power on failed: %d\n", -+ DRM_DEV_ERROR(dev, "phy power on failed: %d\n", - ret); - goto err_phy; - } -@@ -397,28 +404,28 @@ static int cdn_dp_enable_phy(struct cdn_dp_device *dp, struct cdn_dp_port *port) - ret = cdn_dp_grf_write(dp, GRF_SOC_CON26, - DPTX_HPD_SEL_MASK | DPTX_HPD_SEL); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "Failed to write HPD_SEL %d\n", ret); -+ DRM_DEV_ERROR(dev, "Failed to write HPD_SEL %d\n", ret); - goto err_power_on; - } - -- ret = cdn_dp_get_hpd_status(dp); -+ ret = cdns_mhdp_read_hpd(&dp->mhdp); - if (ret <= 0) { - if (!ret) -- DRM_DEV_ERROR(dp->dev, "hpd does not exist\n"); -+ DRM_DEV_ERROR(dev, "hpd does not exist\n"); - goto err_power_on; - } - - ret = extcon_get_property(port->extcon, EXTCON_DISP_DP, - EXTCON_PROP_USB_TYPEC_POLARITY, &property); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "get property failed\n"); -+ DRM_DEV_ERROR(dev, "get property failed\n"); - goto err_power_on; - } - - port->lanes = cdn_dp_get_port_lanes(port); -- ret = cdn_dp_set_host_cap(dp, port->lanes, property.intval); -+ ret = cdns_mhdp_set_host_cap(&dp->mhdp, property.intval); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "set host capabilities failed: %d\n", -+ DRM_DEV_ERROR(dev, "set host capabilities failed: %d\n", - ret); - goto err_power_on; - } -@@ -428,7 +435,7 @@ static int cdn_dp_enable_phy(struct cdn_dp_device *dp, struct cdn_dp_port *port) - - err_power_on: - if (phy_power_off(port->phy)) -- DRM_DEV_ERROR(dp->dev, "phy power off failed: %d", ret); -+ DRM_DEV_ERROR(dev, "phy power off failed: %d", ret); - else - port->phy_enabled = false; - -@@ -446,7 +453,8 @@ static int cdn_dp_disable_phy(struct cdn_dp_device *dp, - if (port->phy_enabled) { - ret = phy_power_off(port->phy); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "phy power off failed: %d", ret); -+ DRM_DEV_ERROR(dp->mhdp.dev, -+ "phy power off failed: %d", ret); - return ret; - } - } -@@ -470,16 +478,16 @@ static int cdn_dp_disable(struct cdn_dp_device *dp) - ret = cdn_dp_grf_write(dp, GRF_SOC_CON26, - DPTX_HPD_SEL_MASK | DPTX_HPD_DEL); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "Failed to clear hpd sel %d\n", -+ DRM_DEV_ERROR(dp->mhdp.dev, "Failed to clear hpd sel %d\n", - ret); - return ret; - } - -- cdn_dp_set_firmware_active(dp, false); -+ cdns_mhdp_set_firmware_active(&dp->mhdp, false); - cdn_dp_clk_disable(dp); - dp->active = false; -- dp->max_lanes = 0; -- dp->max_rate = 0; -+ dp->mhdp.dp.rate = 0; -+ dp->mhdp.dp.num_lanes = 0; - if (!dp->connected) { - kfree(dp->edid); - dp->edid = NULL; -@@ -492,11 +500,11 @@ static int cdn_dp_enable(struct cdn_dp_device *dp) - { - int ret, i, lanes; - struct cdn_dp_port *port; -+ struct device *dev = dp->mhdp.dev; - - port = cdn_dp_connected_port(dp); - if (!port) { -- DRM_DEV_ERROR(dp->dev, -- "Can't enable without connection\n"); -+ DRM_DEV_ERROR(dev, "Can't enable without connection\n"); - return -ENODEV; - } - -@@ -509,7 +517,7 @@ static int cdn_dp_enable(struct cdn_dp_device *dp) - - ret = cdn_dp_firmware_init(dp); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "firmware init failed: %d", ret); -+ DRM_DEV_ERROR(dp->mhdp.dev, "firmware init failed: %d", ret); - goto err_clk_disable; - } - -@@ -543,8 +551,9 @@ static void cdn_dp_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *adjusted) - { - struct cdn_dp_device *dp = encoder_to_dp(encoder); -- struct drm_display_info *display_info = &dp->connector.display_info; -- struct video_info *video = &dp->video_info; -+ struct drm_display_info *display_info = -+ &dp->mhdp.connector.base.display_info; -+ struct video_info *video = &dp->mhdp.video_info; - - switch (display_info->bpc) { - case 10: -@@ -562,20 +571,20 @@ static void cdn_dp_encoder_mode_set(struct drm_encoder *encoder, - video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); - video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); - -- drm_mode_copy(&dp->mode, adjusted); -+ drm_mode_copy(&dp->mhdp.mode, adjusted); - } - - static bool cdn_dp_check_link_status(struct cdn_dp_device *dp) - { - u8 link_status[DP_LINK_STATUS_SIZE]; - struct cdn_dp_port *port = cdn_dp_connected_port(dp); -- u8 sink_lanes = drm_dp_max_lane_count(dp->dpcd); -+ u8 sink_lanes = drm_dp_max_lane_count(dp->mhdp.dp.dpcd); - -- if (!port || !dp->max_rate || !dp->max_lanes) -+ if (!port || !dp->mhdp.dp.rate || !dp->mhdp.dp.num_lanes) - return false; - -- if (cdn_dp_dpcd_read(dp, DP_LANE0_1_STATUS, link_status, -- DP_LINK_STATUS_SIZE)) { -+ if (drm_dp_dpcd_read(&dp->mhdp.dp.aux, DP_LANE0_1_STATUS, link_status, -+ DP_LINK_STATUS_SIZE)) { - DRM_ERROR("Failed to get link status\n"); - return false; - } -@@ -587,15 +596,16 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device *dp) - static void cdn_dp_encoder_enable(struct drm_encoder *encoder) - { - struct cdn_dp_device *dp = encoder_to_dp(encoder); -+ struct device *dev = dp->mhdp.dev; - int ret, val; - -- ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder); -+ ret = drm_of_encoder_active_endpoint_id(dev->of_node, encoder); - if (ret < 0) { -- DRM_DEV_ERROR(dp->dev, "Could not get vop id, %d", ret); -+ DRM_DEV_ERROR(dev, "Could not get vop id, %d", ret); - return; - } - -- DRM_DEV_DEBUG_KMS(dp->dev, "vop %s output to cdn-dp\n", -+ DRM_DEV_DEBUG_KMS(dev, "vop %s output to cdn-dp\n", - (ret) ? "LIT" : "BIG"); - if (ret) - val = DP_SEL_VOP_LIT | (DP_SEL_VOP_LIT << 16); -@@ -610,33 +620,33 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder) - - ret = cdn_dp_enable(dp); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "Failed to enable encoder %d\n", -+ DRM_DEV_ERROR(dev, "Failed to enable encoder %d\n", - ret); - goto out; - } - if (!cdn_dp_check_link_status(dp)) { -- ret = cdn_dp_train_link(dp); -+ ret = cdns_mhdp_train_link(&dp->mhdp); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "Failed link train %d\n", ret); -+ DRM_DEV_ERROR(dev, "Failed link train %d\n", ret); - goto out; - } - } - -- ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_IDLE); -+ ret = cdns_mhdp_set_video_status(&dp->mhdp, CONTROL_VIDEO_IDLE); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "Failed to idle video %d\n", ret); -+ DRM_DEV_ERROR(dev, "Failed to idle video %d\n", ret); - goto out; - } - -- ret = cdn_dp_config_video(dp); -+ ret = cdns_mhdp_config_video(&dp->mhdp); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "Failed to config video %d\n", ret); -+ DRM_DEV_ERROR(dev, "Failed to config video %d\n", ret); - goto out; - } - -- ret = cdn_dp_set_video_status(dp, CONTROL_VIDEO_VALID); -+ ret = cdns_mhdp_set_video_status(&dp->mhdp, CONTROL_VIDEO_VALID); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret); -+ DRM_DEV_ERROR(dev, "Failed to valid video %d\n", ret); - goto out; - } - -@@ -652,7 +662,8 @@ static void cdn_dp_encoder_disable(struct drm_encoder *encoder) - if (dp->active) { - ret = cdn_dp_disable(dp); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "Failed to disable encoder %d\n", -+ DRM_DEV_ERROR(dp->mhdp.dev, -+ "Failed to disable encoder %d\n", - ret); - } - } -@@ -692,7 +703,7 @@ static const struct drm_encoder_helper_funcs cdn_dp_encoder_helper_funcs = { - - static int cdn_dp_parse_dt(struct cdn_dp_device *dp) - { -- struct device *dev = dp->dev; -+ struct device *dev = dp->mhdp.dev; - struct device_node *np = dev->of_node; - struct platform_device *pdev = to_platform_device(dev); - -@@ -704,10 +715,10 @@ static int cdn_dp_parse_dt(struct cdn_dp_device *dp) - return PTR_ERR(dp->grf); - } - -- dp->regs = devm_platform_ioremap_resource(pdev, 0); -- if (IS_ERR(dp->regs)) { -+ dp->mhdp.regs_base = devm_platform_ioremap_resource(pdev, 0); -+ if (IS_ERR(dp->mhdp.regs_base)) { - DRM_DEV_ERROR(dev, "ioremap reg failed\n"); -- return PTR_ERR(dp->regs); -+ return PTR_ERR(dp->mhdp.regs_base); - } - - dp->core_clk = devm_clk_get(dev, "core-clk"); -@@ -722,10 +733,10 @@ static int cdn_dp_parse_dt(struct cdn_dp_device *dp) - return PTR_ERR(dp->pclk); - } - -- dp->spdif_clk = devm_clk_get(dev, "spdif"); -- if (IS_ERR(dp->spdif_clk)) { -+ dp->mhdp.spdif_clk = devm_clk_get(dev, "spdif"); -+ if (IS_ERR(dp->mhdp.spdif_clk)) { - DRM_DEV_ERROR(dev, "cannot get spdif_clk\n"); -- return PTR_ERR(dp->spdif_clk); -+ return PTR_ERR(dp->mhdp.spdif_clk); - } - - dp->grf_clk = devm_clk_get(dev, "grf"); -@@ -734,10 +745,10 @@ static int cdn_dp_parse_dt(struct cdn_dp_device *dp) - return PTR_ERR(dp->grf_clk); - } - -- dp->spdif_rst = devm_reset_control_get(dev, "spdif"); -- if (IS_ERR(dp->spdif_rst)) { -+ dp->mhdp.spdif_rst = devm_reset_control_get(dev, "spdif"); -+ if (IS_ERR(dp->mhdp.spdif_rst)) { - DRM_DEV_ERROR(dev, "no spdif reset control found\n"); -- return PTR_ERR(dp->spdif_rst); -+ return PTR_ERR(dp->mhdp.spdif_rst); - } - - dp->dptx_rst = devm_reset_control_get(dev, "dptx"); -@@ -784,7 +795,7 @@ static int cdn_dp_audio_hw_params(struct device *dev, void *data, - audio.format = AFMT_I2S; - break; - case HDMI_SPDIF: -- audio.format = AFMT_SPDIF; -+ audio.format = AFMT_SPDIF_INT; - break; - default: - DRM_DEV_ERROR(dev, "Invalid format %d\n", daifmt->fmt); -@@ -792,9 +803,9 @@ static int cdn_dp_audio_hw_params(struct device *dev, void *data, - goto out; - } - -- ret = cdn_dp_audio_config(dp, &audio); -+ ret = cdns_mhdp_audio_config(&dp->mhdp, &audio); - if (!ret) -- dp->audio_info = audio; -+ dp->mhdp.audio_info = audio; - - out: - mutex_unlock(&dp->lock); -@@ -810,9 +821,9 @@ static void cdn_dp_audio_shutdown(struct device *dev, void *data) - if (!dp->active) - goto out; - -- ret = cdn_dp_audio_stop(dp, &dp->audio_info); -+ ret = cdns_mhdp_audio_stop(&dp->mhdp, &dp->mhdp.audio_info); - if (!ret) -- dp->audio_info.format = AFMT_UNUSED; -+ dp->mhdp.audio_info.format = AFMT_UNUSED; - out: - mutex_unlock(&dp->lock); - } -@@ -829,7 +840,7 @@ static int cdn_dp_audio_mute_stream(struct device *dev, void *data, - goto out; - } - -- ret = cdn_dp_audio_mute(dp, enable); -+ ret = cdns_mhdp_audio_mute(&dp->mhdp, enable); - - out: - mutex_unlock(&dp->lock); -@@ -841,7 +852,8 @@ static int cdn_dp_audio_get_eld(struct device *dev, void *data, - { - struct cdn_dp_device *dp = dev_get_drvdata(dev); - -- memcpy(buf, dp->connector.eld, min(sizeof(dp->connector.eld), len)); -+ memcpy(buf, dp->mhdp.connector.base.eld, -+ min(sizeof(dp->mhdp.connector.base.eld), len)); - - return 0; - } -@@ -864,11 +876,11 @@ static int cdn_dp_audio_codec_init(struct cdn_dp_device *dp, - .max_i2s_channels = 8, - }; - -- dp->audio_pdev = platform_device_register_data( -- dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO, -- &codec_data, sizeof(codec_data)); -+ dp->mhdp.audio_pdev = platform_device_register_data( -+ dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO, -+ &codec_data, sizeof(codec_data)); - -- return PTR_ERR_OR_ZERO(dp->audio_pdev); -+ return PTR_ERR_OR_ZERO(dp->mhdp.audio_pdev); - } - - static int cdn_dp_request_firmware(struct cdn_dp_device *dp) -@@ -876,6 +888,7 @@ static int cdn_dp_request_firmware(struct cdn_dp_device *dp) - int ret; - unsigned long timeout = jiffies + msecs_to_jiffies(CDN_FW_TIMEOUT_MS); - unsigned long sleep = 1000; -+ struct device *dev = dp->mhdp.dev; - - WARN_ON(!mutex_is_locked(&dp->lock)); - -@@ -886,13 +899,13 @@ static int cdn_dp_request_firmware(struct cdn_dp_device *dp) - mutex_unlock(&dp->lock); - - while (time_before(jiffies, timeout)) { -- ret = request_firmware(&dp->fw, CDN_DP_FIRMWARE, dp->dev); -+ ret = request_firmware(&dp->fw, CDN_DP_FIRMWARE, dev); - if (ret == -ENOENT) { - msleep(sleep); - sleep *= 2; - continue; - } else if (ret) { -- DRM_DEV_ERROR(dp->dev, -+ DRM_DEV_ERROR(dev, - "failed to request firmware: %d\n", ret); - goto out; - } -@@ -902,7 +915,7 @@ static int cdn_dp_request_firmware(struct cdn_dp_device *dp) - goto out; - } - -- DRM_DEV_ERROR(dp->dev, "Timed out trying to load firmware\n"); -+ DRM_DEV_ERROR(dev, "Timed out trying to load firmware\n"); - ret = -ETIMEDOUT; - out: - mutex_lock(&dp->lock); -@@ -913,8 +926,9 @@ static void cdn_dp_pd_event_work(struct work_struct *work) - { - struct cdn_dp_device *dp = container_of(work, struct cdn_dp_device, - event_work); -- struct drm_connector *connector = &dp->connector; -+ struct drm_connector *connector = &dp->mhdp.connector.base; - enum drm_connector_status old_status; -+ struct device *dev = dp->mhdp.dev; - - int ret; - -@@ -931,44 +945,45 @@ static void cdn_dp_pd_event_work(struct work_struct *work) - - /* Not connected, notify userspace to disable the block */ - if (!cdn_dp_connected_port(dp)) { -- DRM_DEV_INFO(dp->dev, "Not connected. Disabling cdn\n"); -+ DRM_DEV_INFO(dev, "Not connected. Disabling cdn\n"); - dp->connected = false; - - /* Connected but not enabled, enable the block */ - } else if (!dp->active) { -- DRM_DEV_INFO(dp->dev, "Connected, not enabled. Enabling cdn\n"); -+ DRM_DEV_INFO(dev, "Connected, not enabled. Enabling cdn\n"); - ret = cdn_dp_enable(dp); - if (ret) { -- DRM_DEV_ERROR(dp->dev, "Enable dp failed %d\n", ret); -+ DRM_DEV_ERROR(dev, "Enable dp failed %d\n", ret); - dp->connected = false; - } - - /* Enabled and connected to a dongle without a sink, notify userspace */ - } else if (!cdn_dp_check_sink_connection(dp)) { -- DRM_DEV_INFO(dp->dev, "Connected without sink. Assert hpd\n"); -+ DRM_DEV_INFO(dev, "Connected without sink. Assert hpd\n"); - dp->connected = false; - - /* Enabled and connected with a sink, re-train if requested */ - } else if (!cdn_dp_check_link_status(dp)) { -- unsigned int rate = dp->max_rate; -- unsigned int lanes = dp->max_lanes; -- struct drm_display_mode *mode = &dp->mode; -+ unsigned int rate = dp->mhdp.dp.rate; -+ unsigned int lanes = dp->mhdp.dp.num_lanes; -+ struct drm_display_mode *mode = &dp->mhdp.mode; - -- DRM_DEV_INFO(dp->dev, "Connected with sink. Re-train link\n"); -- ret = cdn_dp_train_link(dp); -+ DRM_DEV_INFO(dev, "Connected with sink. Re-train link\n"); -+ ret = cdns_mhdp_train_link(&dp->mhdp); - if (ret) { - dp->connected = false; -- DRM_DEV_ERROR(dp->dev, "Train link failed %d\n", ret); -+ DRM_DEV_ERROR(dev, "Train link failed %d\n", ret); - goto out; - } - - /* If training result is changed, update the video config */ - if (mode->clock && -- (rate != dp->max_rate || lanes != dp->max_lanes)) { -- ret = cdn_dp_config_video(dp); -+ (rate != dp->mhdp.dp.rate || -+ lanes != dp->mhdp.dp.num_lanes)) { -+ ret = cdns_mhdp_config_video(&dp->mhdp); - if (ret) { - dp->connected = false; -- DRM_DEV_ERROR(dp->dev, -+ DRM_DEV_ERROR(dev, - "Failed to config video %d\n", - ret); - } -@@ -1037,7 +1052,7 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data) - - drm_encoder_helper_add(encoder, &cdn_dp_encoder_helper_funcs); - -- connector = &dp->connector; -+ connector = &dp->mhdp.connector.base; - connector->polled = DRM_CONNECTOR_POLL_HPD; - connector->dpms = DRM_MODE_DPMS_OFF; - -@@ -1061,7 +1076,7 @@ static int cdn_dp_bind(struct device *dev, struct device *master, void *data) - port = dp->port[i]; - - port->event_nb.notifier_call = cdn_dp_pd_event; -- ret = devm_extcon_register_notifier(dp->dev, port->extcon, -+ ret = devm_extcon_register_notifier(dp->mhdp.dev, port->extcon, - EXTCON_DISP_DP, - &port->event_nb); - if (ret) { -@@ -1088,7 +1103,7 @@ static void cdn_dp_unbind(struct device *dev, struct device *master, void *data) - { - struct cdn_dp_device *dp = dev_get_drvdata(dev); - struct drm_encoder *encoder = &dp->encoder.encoder; -- struct drm_connector *connector = &dp->connector; -+ struct drm_connector *connector = &dp->mhdp.connector.base; - - cancel_work_sync(&dp->event_work); - cdn_dp_encoder_disable(encoder); -@@ -1148,7 +1163,7 @@ static int cdn_dp_probe(struct platform_device *pdev) - dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); - if (!dp) - return -ENOMEM; -- dp->dev = dev; -+ dp->mhdp.dev = dev; - - match = of_match_node(cdn_dp_dt_ids, pdev->dev.of_node); - dp_data = (struct cdn_dp_data *)match->data; -@@ -1192,8 +1207,8 @@ static int cdn_dp_remove(struct platform_device *pdev) - { - struct cdn_dp_device *dp = platform_get_drvdata(pdev); - -- platform_device_unregister(dp->audio_pdev); -- cdn_dp_suspend(dp->dev); -+ platform_device_unregister(dp->mhdp.audio_pdev); -+ cdn_dp_suspend(dp->mhdp.dev); - component_del(&pdev->dev, &cdn_dp_component_ops); - } - -@@ -1203,7 +1218,7 @@ static void cdn_dp_shutdown(struct platform_device *pdev) - { - struct cdn_dp_device *dp = platform_get_drvdata(pdev); - -- cdn_dp_suspend(dp->dev); -+ cdn_dp_suspend(dp->mhdp.dev); - } - - static const struct dev_pm_ops cdn_dp_pm_ops = { -diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h -index 81ac9b658a70..8b1b15b92503 100644 ---- a/drivers/gpu/drm/rockchip/cdn-dp-core.h -+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h -@@ -7,6 +7,7 @@ - #ifndef _CDN_DP_CORE_H - #define _CDN_DP_CORE_H - -+#include - #include - #include - #include -@@ -15,35 +16,6 @@ - - #define MAX_PHY 2 - --enum audio_format { -- AFMT_I2S = 0, -- AFMT_SPDIF = 1, -- AFMT_UNUSED, --}; -- --struct audio_info { -- enum audio_format format; -- int sample_rate; -- int channels; -- int sample_width; --}; -- --enum vic_pxl_encoding_format { -- PXL_RGB = 0x1, -- YCBCR_4_4_4 = 0x2, -- YCBCR_4_2_2 = 0x4, -- YCBCR_4_2_0 = 0x8, -- Y_ONLY = 0x10, --}; -- --struct video_info { -- bool h_sync_polarity; -- bool v_sync_polarity; -- bool interlaced; -- int color_depth; -- enum vic_pxl_encoding_format color_fmt; --}; -- - struct cdn_firmware_header { - u32 size_bytes; /* size of the entire header+image(s) in bytes */ - u32 header_size; /* size of just the header in bytes */ -@@ -62,12 +34,9 @@ struct cdn_dp_port { - }; - - struct cdn_dp_device { -- struct device *dev; -+ struct cdns_mhdp_device mhdp; - struct drm_device *drm_dev; -- struct drm_connector connector; - struct rockchip_encoder encoder; -- struct drm_display_mode mode; -- struct platform_device *audio_pdev; - struct work_struct event_work; - struct edid *edid; - -@@ -77,29 +46,20 @@ struct cdn_dp_device { - bool suspended; - - const struct firmware *fw; /* cdn dp firmware */ -- unsigned int fw_version; /* cdn fw version */ - bool fw_loaded; - -- void __iomem *regs; - struct regmap *grf; - struct clk *core_clk; - struct clk *pclk; -- struct clk *spdif_clk; - struct clk *grf_clk; -- struct reset_control *spdif_rst; - struct reset_control *dptx_rst; - struct reset_control *apb_rst; - struct reset_control *core_rst; -- struct audio_info audio_info; -- struct video_info video_info; - struct cdn_dp_port *port[MAX_PHY]; - u8 ports; -- u8 max_lanes; -- unsigned int max_rate; - u8 lanes; - int active_port; - -- u8 dpcd[DP_RECEIVER_CAP_SIZE]; - bool sink_has_audio; - - hdmi_codec_plugged_cb plugged_cb; -diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c -deleted file mode 100644 -index 9d2163ef4d6e..000000000000 ---- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c -+++ /dev/null -@@ -1,960 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0-only --/* -- * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd -- * Author: Chris Zhong -- */ -- --#include --#include --#include --#include --#include --#include -- --#include "cdn-dp-core.h" --#include "cdn-dp-reg.h" -- --#define CDN_DP_SPDIF_CLK 200000000 --#define FW_ALIVE_TIMEOUT_US 1000000 --#define MAILBOX_RETRY_US 1000 --#define MAILBOX_TIMEOUT_US 5000000 --#define LINK_TRAINING_RETRY_MS 20 --#define LINK_TRAINING_TIMEOUT_MS 500 -- --void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, unsigned long clk) --{ -- writel(clk / 1000000, dp->regs + SW_CLK_H); --} -- --void cdn_dp_clock_reset(struct cdn_dp_device *dp) --{ -- u32 val; -- -- val = DPTX_FRMR_DATA_CLK_RSTN_EN | -- DPTX_FRMR_DATA_CLK_EN | -- DPTX_PHY_DATA_RSTN_EN | -- DPTX_PHY_DATA_CLK_EN | -- DPTX_PHY_CHAR_RSTN_EN | -- DPTX_PHY_CHAR_CLK_EN | -- SOURCE_AUX_SYS_CLK_RSTN_EN | -- SOURCE_AUX_SYS_CLK_EN | -- DPTX_SYS_CLK_RSTN_EN | -- DPTX_SYS_CLK_EN | -- CFG_DPTX_VIF_CLK_RSTN_EN | -- CFG_DPTX_VIF_CLK_EN; -- writel(val, dp->regs + SOURCE_DPTX_CAR); -- -- val = SOURCE_PHY_RSTN_EN | SOURCE_PHY_CLK_EN; -- writel(val, dp->regs + SOURCE_PHY_CAR); -- -- val = SOURCE_PKT_SYS_RSTN_EN | -- SOURCE_PKT_SYS_CLK_EN | -- SOURCE_PKT_DATA_RSTN_EN | -- SOURCE_PKT_DATA_CLK_EN; -- writel(val, dp->regs + SOURCE_PKT_CAR); -- -- val = SPDIF_CDR_CLK_RSTN_EN | -- SPDIF_CDR_CLK_EN | -- SOURCE_AIF_SYS_RSTN_EN | -- SOURCE_AIF_SYS_CLK_EN | -- SOURCE_AIF_CLK_RSTN_EN | -- SOURCE_AIF_CLK_EN; -- writel(val, dp->regs + SOURCE_AIF_CAR); -- -- val = SOURCE_CIPHER_SYSTEM_CLK_RSTN_EN | -- SOURCE_CIPHER_SYS_CLK_EN | -- SOURCE_CIPHER_CHAR_CLK_RSTN_EN | -- SOURCE_CIPHER_CHAR_CLK_EN; -- writel(val, dp->regs + SOURCE_CIPHER_CAR); -- -- val = SOURCE_CRYPTO_SYS_CLK_RSTN_EN | -- SOURCE_CRYPTO_SYS_CLK_EN; -- writel(val, dp->regs + SOURCE_CRYPTO_CAR); -- -- /* enable Mailbox and PIF interrupt */ -- writel(0, dp->regs + APB_INT_MASK); --} -- --static int cdn_dp_mailbox_read(struct cdn_dp_device *dp) --{ -- int val, ret; -- -- ret = readx_poll_timeout(readl, dp->regs + MAILBOX_EMPTY_ADDR, -- val, !val, MAILBOX_RETRY_US, -- MAILBOX_TIMEOUT_US); -- if (ret < 0) -- return ret; -- -- return readl(dp->regs + MAILBOX0_RD_DATA) & 0xff; --} -- --static int cdp_dp_mailbox_write(struct cdn_dp_device *dp, u8 val) --{ -- int ret, full; -- -- ret = readx_poll_timeout(readl, dp->regs + MAILBOX_FULL_ADDR, -- full, !full, MAILBOX_RETRY_US, -- MAILBOX_TIMEOUT_US); -- if (ret < 0) -- return ret; -- -- writel(val, dp->regs + MAILBOX0_WR_DATA); -- -- return 0; --} -- --static int cdn_dp_mailbox_validate_receive(struct cdn_dp_device *dp, -- u8 module_id, u8 opcode, -- u16 req_size) --{ -- u32 mbox_size, i; -- u8 header[4]; -- int ret; -- -- /* read the header of the message */ -- for (i = 0; i < 4; i++) { -- ret = cdn_dp_mailbox_read(dp); -- if (ret < 0) -- return ret; -- -- header[i] = ret; -- } -- -- mbox_size = (header[2] << 8) | header[3]; -- -- if (opcode != header[0] || module_id != header[1] || -- req_size != mbox_size) { -- /* -- * If the message in mailbox is not what we want, we need to -- * clear the mailbox by reading its contents. -- */ -- for (i = 0; i < mbox_size; i++) -- if (cdn_dp_mailbox_read(dp) < 0) -- break; -- -- return -EINVAL; -- } -- -- return 0; --} -- --static int cdn_dp_mailbox_read_receive(struct cdn_dp_device *dp, -- u8 *buff, u16 buff_size) --{ -- u32 i; -- int ret; -- -- for (i = 0; i < buff_size; i++) { -- ret = cdn_dp_mailbox_read(dp); -- if (ret < 0) -- return ret; -- -- buff[i] = ret; -- } -- -- return 0; --} -- --static int cdn_dp_mailbox_send(struct cdn_dp_device *dp, u8 module_id, -- u8 opcode, u16 size, u8 *message) --{ -- u8 header[4]; -- int ret, i; -- -- header[0] = opcode; -- header[1] = module_id; -- header[2] = (size >> 8) & 0xff; -- header[3] = size & 0xff; -- -- for (i = 0; i < 4; i++) { -- ret = cdp_dp_mailbox_write(dp, header[i]); -- if (ret) -- return ret; -- } -- -- for (i = 0; i < size; i++) { -- ret = cdp_dp_mailbox_write(dp, message[i]); -- if (ret) -- return ret; -- } -- -- return 0; --} -- --static int cdn_dp_reg_write(struct cdn_dp_device *dp, u16 addr, u32 val) --{ -- u8 msg[6]; -- -- msg[0] = (addr >> 8) & 0xff; -- msg[1] = addr & 0xff; -- msg[2] = (val >> 24) & 0xff; -- msg[3] = (val >> 16) & 0xff; -- msg[4] = (val >> 8) & 0xff; -- msg[5] = val & 0xff; -- return cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_REGISTER, -- sizeof(msg), msg); --} -- --static int cdn_dp_reg_write_bit(struct cdn_dp_device *dp, u16 addr, -- u8 start_bit, u8 bits_no, u32 val) --{ -- u8 field[8]; -- -- field[0] = (addr >> 8) & 0xff; -- field[1] = addr & 0xff; -- field[2] = start_bit; -- field[3] = bits_no; -- field[4] = (val >> 24) & 0xff; -- field[5] = (val >> 16) & 0xff; -- field[6] = (val >> 8) & 0xff; -- field[7] = val & 0xff; -- -- return cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_FIELD, -- sizeof(field), field); --} -- --int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len) --{ -- u8 msg[5], reg[5]; -- int ret; -- -- msg[0] = (len >> 8) & 0xff; -- msg[1] = len & 0xff; -- msg[2] = (addr >> 16) & 0xff; -- msg[3] = (addr >> 8) & 0xff; -- msg[4] = addr & 0xff; -- ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_READ_DPCD, -- sizeof(msg), msg); -- if (ret) -- goto err_dpcd_read; -- -- ret = cdn_dp_mailbox_validate_receive(dp, MB_MODULE_ID_DP_TX, -- DPTX_READ_DPCD, -- sizeof(reg) + len); -- if (ret) -- goto err_dpcd_read; -- -- ret = cdn_dp_mailbox_read_receive(dp, reg, sizeof(reg)); -- if (ret) -- goto err_dpcd_read; -- -- ret = cdn_dp_mailbox_read_receive(dp, data, len); -- --err_dpcd_read: -- return ret; --} -- --int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value) --{ -- u8 msg[6], reg[5]; -- int ret; -- -- msg[0] = 0; -- msg[1] = 1; -- msg[2] = (addr >> 16) & 0xff; -- msg[3] = (addr >> 8) & 0xff; -- msg[4] = addr & 0xff; -- msg[5] = value; -- ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_WRITE_DPCD, -- sizeof(msg), msg); -- if (ret) -- goto err_dpcd_write; -- -- ret = cdn_dp_mailbox_validate_receive(dp, MB_MODULE_ID_DP_TX, -- DPTX_WRITE_DPCD, sizeof(reg)); -- if (ret) -- goto err_dpcd_write; -- -- ret = cdn_dp_mailbox_read_receive(dp, reg, sizeof(reg)); -- if (ret) -- goto err_dpcd_write; -- -- if (addr != (reg[2] << 16 | reg[3] << 8 | reg[4])) -- ret = -EINVAL; -- --err_dpcd_write: -- if (ret) -- DRM_DEV_ERROR(dp->dev, "dpcd write failed: %d\n", ret); -- return ret; --} -- --int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem, -- u32 i_size, const u32 *d_mem, u32 d_size) --{ -- u32 reg; -- int i, ret; -- -- /* reset ucpu before load firmware*/ -- writel(APB_IRAM_PATH | APB_DRAM_PATH | APB_XT_RESET, -- dp->regs + APB_CTRL); -- -- for (i = 0; i < i_size; i += 4) -- writel(*i_mem++, dp->regs + ADDR_IMEM + i); -- -- for (i = 0; i < d_size; i += 4) -- writel(*d_mem++, dp->regs + ADDR_DMEM + i); -- -- /* un-reset ucpu */ -- writel(0, dp->regs + APB_CTRL); -- -- /* check the keep alive register to make sure fw working */ -- ret = readx_poll_timeout(readl, dp->regs + KEEP_ALIVE, -- reg, reg, 2000, FW_ALIVE_TIMEOUT_US); -- if (ret < 0) { -- DRM_DEV_ERROR(dp->dev, "failed to loaded the FW reg = %x\n", -- reg); -- return -EINVAL; -- } -- -- reg = readl(dp->regs + VER_L) & 0xff; -- dp->fw_version = reg; -- reg = readl(dp->regs + VER_H) & 0xff; -- dp->fw_version |= reg << 8; -- reg = readl(dp->regs + VER_LIB_L_ADDR) & 0xff; -- dp->fw_version |= reg << 16; -- reg = readl(dp->regs + VER_LIB_H_ADDR) & 0xff; -- dp->fw_version |= reg << 24; -- -- DRM_DEV_DEBUG(dp->dev, "firmware version: %x\n", dp->fw_version); -- -- return 0; --} -- --int cdn_dp_set_firmware_active(struct cdn_dp_device *dp, bool enable) --{ -- u8 msg[5]; -- int ret, i; -- -- msg[0] = GENERAL_MAIN_CONTROL; -- msg[1] = MB_MODULE_ID_GENERAL; -- msg[2] = 0; -- msg[3] = 1; -- msg[4] = enable ? FW_ACTIVE : FW_STANDBY; -- -- for (i = 0; i < sizeof(msg); i++) { -- ret = cdp_dp_mailbox_write(dp, msg[i]); -- if (ret) -- goto err_set_firmware_active; -- } -- -- /* read the firmware state */ -- for (i = 0; i < sizeof(msg); i++) { -- ret = cdn_dp_mailbox_read(dp); -- if (ret < 0) -- goto err_set_firmware_active; -- -- msg[i] = ret; -- } -- -- ret = 0; -- --err_set_firmware_active: -- if (ret < 0) -- DRM_DEV_ERROR(dp->dev, "set firmware active failed\n"); -- return ret; --} -- --int cdn_dp_set_host_cap(struct cdn_dp_device *dp, u8 lanes, bool flip) --{ -- u8 msg[8]; -- int ret; -- -- msg[0] = CDN_DP_MAX_LINK_RATE; -- msg[1] = lanes | SCRAMBLER_EN; -- msg[2] = VOLTAGE_LEVEL_2; -- msg[3] = PRE_EMPHASIS_LEVEL_3; -- msg[4] = PTS1 | PTS2 | PTS3 | PTS4; -- msg[5] = FAST_LT_NOT_SUPPORT; -- msg[6] = flip ? LANE_MAPPING_FLIPPED : LANE_MAPPING_NORMAL; -- msg[7] = ENHANCED; -- -- ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, -- DPTX_SET_HOST_CAPABILITIES, -- sizeof(msg), msg); -- if (ret) -- goto err_set_host_cap; -- -- ret = cdn_dp_reg_write(dp, DP_AUX_SWAP_INVERSION_CONTROL, -- AUX_HOST_INVERT); -- --err_set_host_cap: -- if (ret) -- DRM_DEV_ERROR(dp->dev, "set host cap failed: %d\n", ret); -- return ret; --} -- --int cdn_dp_event_config(struct cdn_dp_device *dp) --{ -- u8 msg[5]; -- int ret; -- -- memset(msg, 0, sizeof(msg)); -- -- msg[0] = DPTX_EVENT_ENABLE_HPD | DPTX_EVENT_ENABLE_TRAINING; -- -- ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_ENABLE_EVENT, -- sizeof(msg), msg); -- if (ret) -- DRM_DEV_ERROR(dp->dev, "set event config failed: %d\n", ret); -- -- return ret; --} -- --u32 cdn_dp_get_event(struct cdn_dp_device *dp) --{ -- return readl(dp->regs + SW_EVENTS0); --} -- --int cdn_dp_get_hpd_status(struct cdn_dp_device *dp) --{ -- u8 status; -- int ret; -- -- ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_HPD_STATE, -- 0, NULL); -- if (ret) -- goto err_get_hpd; -- -- ret = cdn_dp_mailbox_validate_receive(dp, MB_MODULE_ID_DP_TX, -- DPTX_HPD_STATE, sizeof(status)); -- if (ret) -- goto err_get_hpd; -- -- ret = cdn_dp_mailbox_read_receive(dp, &status, sizeof(status)); -- if (ret) -- goto err_get_hpd; -- -- return status; -- --err_get_hpd: -- DRM_DEV_ERROR(dp->dev, "get hpd status failed: %d\n", ret); -- return ret; --} -- --int cdn_dp_get_edid_block(void *data, u8 *edid, -- unsigned int block, size_t length) --{ -- struct cdn_dp_device *dp = data; -- u8 msg[2], reg[2], i; -- int ret; -- -- for (i = 0; i < 4; i++) { -- msg[0] = block / 2; -- msg[1] = block % 2; -- -- ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_GET_EDID, -- sizeof(msg), msg); -- if (ret) -- continue; -- -- ret = cdn_dp_mailbox_validate_receive(dp, MB_MODULE_ID_DP_TX, -- DPTX_GET_EDID, -- sizeof(reg) + length); -- if (ret) -- continue; -- -- ret = cdn_dp_mailbox_read_receive(dp, reg, sizeof(reg)); -- if (ret) -- continue; -- -- ret = cdn_dp_mailbox_read_receive(dp, edid, length); -- if (ret) -- continue; -- -- if (reg[0] == length && reg[1] == block / 2) -- break; -- } -- -- if (ret) -- DRM_DEV_ERROR(dp->dev, "get block[%d] edid failed: %d\n", block, -- ret); -- -- return ret; --} -- --static int cdn_dp_training_start(struct cdn_dp_device *dp) --{ -- unsigned long timeout; -- u8 msg, event[2]; -- int ret; -- -- msg = LINK_TRAINING_RUN; -- -- /* start training */ -- ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_TRAINING_CONTROL, -- sizeof(msg), &msg); -- if (ret) -- goto err_training_start; -- -- timeout = jiffies + msecs_to_jiffies(LINK_TRAINING_TIMEOUT_MS); -- while (time_before(jiffies, timeout)) { -- msleep(LINK_TRAINING_RETRY_MS); -- ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, -- DPTX_READ_EVENT, 0, NULL); -- if (ret) -- goto err_training_start; -- -- ret = cdn_dp_mailbox_validate_receive(dp, MB_MODULE_ID_DP_TX, -- DPTX_READ_EVENT, -- sizeof(event)); -- if (ret) -- goto err_training_start; -- -- ret = cdn_dp_mailbox_read_receive(dp, event, sizeof(event)); -- if (ret) -- goto err_training_start; -- -- if (event[1] & EQ_PHASE_FINISHED) -- return 0; -- } -- -- ret = -ETIMEDOUT; -- --err_training_start: -- DRM_DEV_ERROR(dp->dev, "training failed: %d\n", ret); -- return ret; --} -- --static int cdn_dp_get_training_status(struct cdn_dp_device *dp) --{ -- u8 status[10]; -- int ret; -- -- ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_READ_LINK_STAT, -- 0, NULL); -- if (ret) -- goto err_get_training_status; -- -- ret = cdn_dp_mailbox_validate_receive(dp, MB_MODULE_ID_DP_TX, -- DPTX_READ_LINK_STAT, -- sizeof(status)); -- if (ret) -- goto err_get_training_status; -- -- ret = cdn_dp_mailbox_read_receive(dp, status, sizeof(status)); -- if (ret) -- goto err_get_training_status; -- -- dp->max_rate = drm_dp_bw_code_to_link_rate(status[0]); -- dp->max_lanes = status[1]; -- --err_get_training_status: -- if (ret) -- DRM_DEV_ERROR(dp->dev, "get training status failed: %d\n", ret); -- return ret; --} -- --int cdn_dp_train_link(struct cdn_dp_device *dp) --{ -- int ret; -- -- ret = cdn_dp_training_start(dp); -- if (ret) { -- DRM_DEV_ERROR(dp->dev, "Failed to start training %d\n", ret); -- return ret; -- } -- -- ret = cdn_dp_get_training_status(dp); -- if (ret) { -- DRM_DEV_ERROR(dp->dev, "Failed to get training stat %d\n", ret); -- return ret; -- } -- -- DRM_DEV_DEBUG_KMS(dp->dev, "rate:0x%x, lanes:%d\n", dp->max_rate, -- dp->max_lanes); -- return ret; --} -- --int cdn_dp_set_video_status(struct cdn_dp_device *dp, int active) --{ -- u8 msg; -- int ret; -- -- msg = !!active; -- -- ret = cdn_dp_mailbox_send(dp, MB_MODULE_ID_DP_TX, DPTX_SET_VIDEO, -- sizeof(msg), &msg); -- if (ret) -- DRM_DEV_ERROR(dp->dev, "set video status failed: %d\n", ret); -- -- return ret; --} -- --static int cdn_dp_get_msa_misc(struct video_info *video, -- struct drm_display_mode *mode) --{ -- u32 msa_misc; -- u8 val[2] = {0}; -- -- switch (video->color_fmt) { -- case PXL_RGB: -- case Y_ONLY: -- val[0] = 0; -- break; -- /* set YUV default color space conversion to BT601 */ -- case YCBCR_4_4_4: -- val[0] = 6 + BT_601 * 8; -- break; -- case YCBCR_4_2_2: -- val[0] = 5 + BT_601 * 8; -- break; -- case YCBCR_4_2_0: -- val[0] = 5; -- break; -- } -- -- switch (video->color_depth) { -- case 6: -- val[1] = 0; -- break; -- case 8: -- val[1] = 1; -- break; -- case 10: -- val[1] = 2; -- break; -- case 12: -- val[1] = 3; -- break; -- case 16: -- val[1] = 4; -- break; -- } -- -- msa_misc = 2 * val[0] + 32 * val[1] + -- ((video->color_fmt == Y_ONLY) ? (1 << 14) : 0); -- -- return msa_misc; --} -- --int cdn_dp_config_video(struct cdn_dp_device *dp) --{ -- struct video_info *video = &dp->video_info; -- struct drm_display_mode *mode = &dp->mode; -- u64 symbol; -- u32 val, link_rate, rem; -- u8 bit_per_pix, tu_size_reg = TU_SIZE; -- int ret; -- -- bit_per_pix = (video->color_fmt == YCBCR_4_2_2) ? -- (video->color_depth * 2) : (video->color_depth * 3); -- -- link_rate = dp->max_rate / 1000; -- -- ret = cdn_dp_reg_write(dp, BND_HSYNC2VSYNC, VIF_BYPASS_INTERLACE); -- if (ret) -- goto err_config_video; -- -- ret = cdn_dp_reg_write(dp, HSYNC2VSYNC_POL_CTRL, 0); -- if (ret) -- goto err_config_video; -- -- /* -- * get a best tu_size and valid symbol: -- * 1. chose Lclk freq(162Mhz, 270Mhz, 540Mhz), set TU to 32 -- * 2. calculate VS(valid symbol) = TU * Pclk * Bpp / (Lclk * Lanes) -- * 3. if VS > *.85 or VS < *.1 or VS < 2 or TU < VS + 4, then set -- * TU += 2 and repeat 2nd step. -- */ -- do { -- tu_size_reg += 2; -- symbol = (u64)tu_size_reg * mode->clock * bit_per_pix; -- do_div(symbol, dp->max_lanes * link_rate * 8); -- rem = do_div(symbol, 1000); -- if (tu_size_reg > 64) { -- ret = -EINVAL; -- DRM_DEV_ERROR(dp->dev, -- "tu error, clk:%d, lanes:%d, rate:%d\n", -- mode->clock, dp->max_lanes, link_rate); -- goto err_config_video; -- } -- } while ((symbol <= 1) || (tu_size_reg - symbol < 4) || -- (rem > 850) || (rem < 100)); -- -- val = symbol + (tu_size_reg << 8); -- val |= TU_CNT_RST_EN; -- ret = cdn_dp_reg_write(dp, DP_FRAMER_TU, val); -- if (ret) -- goto err_config_video; -- -- /* set the FIFO Buffer size */ -- val = div_u64(mode->clock * (symbol + 1), 1000) + link_rate; -- val /= (dp->max_lanes * link_rate); -- val = div_u64(8 * (symbol + 1), bit_per_pix) - val; -- val += 2; -- ret = cdn_dp_reg_write(dp, DP_VC_TABLE(15), val); -- -- switch (video->color_depth) { -- case 6: -- val = BCS_6; -- break; -- case 8: -- val = BCS_8; -- break; -- case 10: -- val = BCS_10; -- break; -- case 12: -- val = BCS_12; -- break; -- case 16: -- val = BCS_16; -- break; -- } -- -- val += video->color_fmt << 8; -- ret = cdn_dp_reg_write(dp, DP_FRAMER_PXL_REPR, val); -- if (ret) -- goto err_config_video; -- -- val = video->h_sync_polarity ? DP_FRAMER_SP_HSP : 0; -- val |= video->v_sync_polarity ? DP_FRAMER_SP_VSP : 0; -- ret = cdn_dp_reg_write(dp, DP_FRAMER_SP, val); -- if (ret) -- goto err_config_video; -- -- val = (mode->hsync_start - mode->hdisplay) << 16; -- val |= mode->htotal - mode->hsync_end; -- ret = cdn_dp_reg_write(dp, DP_FRONT_BACK_PORCH, val); -- if (ret) -- goto err_config_video; -- -- val = mode->hdisplay * bit_per_pix / 8; -- ret = cdn_dp_reg_write(dp, DP_BYTE_COUNT, val); -- if (ret) -- goto err_config_video; -- -- val = mode->htotal | ((mode->htotal - mode->hsync_start) << 16); -- ret = cdn_dp_reg_write(dp, MSA_HORIZONTAL_0, val); -- if (ret) -- goto err_config_video; -- -- val = mode->hsync_end - mode->hsync_start; -- val |= (mode->hdisplay << 16) | (video->h_sync_polarity << 15); -- ret = cdn_dp_reg_write(dp, MSA_HORIZONTAL_1, val); -- if (ret) -- goto err_config_video; -- -- val = mode->vtotal; -- val |= (mode->vtotal - mode->vsync_start) << 16; -- ret = cdn_dp_reg_write(dp, MSA_VERTICAL_0, val); -- if (ret) -- goto err_config_video; -- -- val = mode->vsync_end - mode->vsync_start; -- val |= (mode->vdisplay << 16) | (video->v_sync_polarity << 15); -- ret = cdn_dp_reg_write(dp, MSA_VERTICAL_1, val); -- if (ret) -- goto err_config_video; -- -- val = cdn_dp_get_msa_misc(video, mode); -- ret = cdn_dp_reg_write(dp, MSA_MISC, val); -- if (ret) -- goto err_config_video; -- -- ret = cdn_dp_reg_write(dp, STREAM_CONFIG, 1); -- if (ret) -- goto err_config_video; -- -- val = mode->hsync_end - mode->hsync_start; -- val |= mode->hdisplay << 16; -- ret = cdn_dp_reg_write(dp, DP_HORIZONTAL, val); -- if (ret) -- goto err_config_video; -- -- val = mode->vdisplay; -- val |= (mode->vtotal - mode->vsync_start) << 16; -- ret = cdn_dp_reg_write(dp, DP_VERTICAL_0, val); -- if (ret) -- goto err_config_video; -- -- val = mode->vtotal; -- ret = cdn_dp_reg_write(dp, DP_VERTICAL_1, val); -- if (ret) -- goto err_config_video; -- -- ret = cdn_dp_reg_write_bit(dp, DP_VB_ID, 2, 1, 0); -- --err_config_video: -- if (ret) -- DRM_DEV_ERROR(dp->dev, "config video failed: %d\n", ret); -- return ret; --} -- --int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio) --{ -- int ret; -- -- ret = cdn_dp_reg_write(dp, AUDIO_PACK_CONTROL, 0); -- if (ret) { -- DRM_DEV_ERROR(dp->dev, "audio stop failed: %d\n", ret); -- return ret; -- } -- -- writel(0, dp->regs + SPDIF_CTRL_ADDR); -- -- /* clearn the audio config and reset */ -- writel(0, dp->regs + AUDIO_SRC_CNTL); -- writel(0, dp->regs + AUDIO_SRC_CNFG); -- writel(AUDIO_SW_RST, dp->regs + AUDIO_SRC_CNTL); -- writel(0, dp->regs + AUDIO_SRC_CNTL); -- -- /* reset smpl2pckt component */ -- writel(0, dp->regs + SMPL2PKT_CNTL); -- writel(AUDIO_SW_RST, dp->regs + SMPL2PKT_CNTL); -- writel(0, dp->regs + SMPL2PKT_CNTL); -- -- /* reset FIFO */ -- writel(AUDIO_SW_RST, dp->regs + FIFO_CNTL); -- writel(0, dp->regs + FIFO_CNTL); -- -- if (audio->format == AFMT_SPDIF) -- clk_disable_unprepare(dp->spdif_clk); -- -- return 0; --} -- --int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable) --{ -- int ret; -- -- ret = cdn_dp_reg_write_bit(dp, DP_VB_ID, 4, 1, enable); -- if (ret) -- DRM_DEV_ERROR(dp->dev, "audio mute failed: %d\n", ret); -- -- return ret; --} -- --static void cdn_dp_audio_config_i2s(struct cdn_dp_device *dp, -- struct audio_info *audio) --{ -- int sub_pckt_num = 1, i2s_port_en_val = 0xf, i; -- u32 val; -- -- if (audio->channels == 2) { -- if (dp->max_lanes == 1) -- sub_pckt_num = 2; -- else -- sub_pckt_num = 4; -- -- i2s_port_en_val = 1; -- } else if (audio->channels == 4) { -- i2s_port_en_val = 3; -- } -- -- writel(0x0, dp->regs + SPDIF_CTRL_ADDR); -- -- writel(SYNC_WR_TO_CH_ZERO, dp->regs + FIFO_CNTL); -- -- val = MAX_NUM_CH(audio->channels); -- val |= NUM_OF_I2S_PORTS(audio->channels); -- val |= AUDIO_TYPE_LPCM; -- val |= CFG_SUB_PCKT_NUM(sub_pckt_num); -- writel(val, dp->regs + SMPL2PKT_CNFG); -- -- if (audio->sample_width == 16) -- val = 0; -- else if (audio->sample_width == 24) -- val = 1 << 9; -- else -- val = 2 << 9; -- -- val |= AUDIO_CH_NUM(audio->channels); -- val |= I2S_DEC_PORT_EN(i2s_port_en_val); -- val |= TRANS_SMPL_WIDTH_32; -- writel(val, dp->regs + AUDIO_SRC_CNFG); -- -- for (i = 0; i < (audio->channels + 1) / 2; i++) { -- if (audio->sample_width == 16) -- val = (0x02 << 8) | (0x02 << 20); -- else if (audio->sample_width == 24) -- val = (0x0b << 8) | (0x0b << 20); -- -- val |= ((2 * i) << 4) | ((2 * i + 1) << 16); -- writel(val, dp->regs + STTS_BIT_CH(i)); -- } -- -- switch (audio->sample_rate) { -- case 32000: -- val = SAMPLING_FREQ(3) | -- ORIGINAL_SAMP_FREQ(0xc); -- break; -- case 44100: -- val = SAMPLING_FREQ(0) | -- ORIGINAL_SAMP_FREQ(0xf); -- break; -- case 48000: -- val = SAMPLING_FREQ(2) | -- ORIGINAL_SAMP_FREQ(0xd); -- break; -- case 88200: -- val = SAMPLING_FREQ(8) | -- ORIGINAL_SAMP_FREQ(0x7); -- break; -- case 96000: -- val = SAMPLING_FREQ(0xa) | -- ORIGINAL_SAMP_FREQ(5); -- break; -- case 176400: -- val = SAMPLING_FREQ(0xc) | -- ORIGINAL_SAMP_FREQ(3); -- break; -- case 192000: -- val = SAMPLING_FREQ(0xe) | -- ORIGINAL_SAMP_FREQ(1); -- break; -- } -- val |= 4; -- writel(val, dp->regs + COM_CH_STTS_BITS); -- -- writel(SMPL2PKT_EN, dp->regs + SMPL2PKT_CNTL); -- writel(I2S_DEC_START, dp->regs + AUDIO_SRC_CNTL); --} -- --static void cdn_dp_audio_config_spdif(struct cdn_dp_device *dp) --{ -- u32 val; -- -- writel(SYNC_WR_TO_CH_ZERO, dp->regs + FIFO_CNTL); -- -- val = MAX_NUM_CH(2) | AUDIO_TYPE_LPCM | CFG_SUB_PCKT_NUM(4); -- writel(val, dp->regs + SMPL2PKT_CNFG); -- writel(SMPL2PKT_EN, dp->regs + SMPL2PKT_CNTL); -- -- val = SPDIF_ENABLE | SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS; -- writel(val, dp->regs + SPDIF_CTRL_ADDR); -- -- clk_prepare_enable(dp->spdif_clk); -- clk_set_rate(dp->spdif_clk, CDN_DP_SPDIF_CLK); --} -- --int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio) --{ -- int ret; -- -- /* reset the spdif clk before config */ -- if (audio->format == AFMT_SPDIF) { -- reset_control_assert(dp->spdif_rst); -- reset_control_deassert(dp->spdif_rst); -- } -- -- ret = cdn_dp_reg_write(dp, CM_LANE_CTRL, LANE_REF_CYC); -- if (ret) -- goto err_audio_config; -- -- ret = cdn_dp_reg_write(dp, CM_CTRL, 0); -- if (ret) -- goto err_audio_config; -- -- if (audio->format == AFMT_I2S) -- cdn_dp_audio_config_i2s(dp, audio); -- else if (audio->format == AFMT_SPDIF) -- cdn_dp_audio_config_spdif(dp); -- -- ret = cdn_dp_reg_write(dp, AUDIO_PACK_CONTROL, AUDIO_PACK_EN); -- --err_audio_config: -- if (ret) -- DRM_DEV_ERROR(dp->dev, "audio config failed: %d\n", ret); -- return ret; --} -diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.h b/include/drm/bridge/cdns-mhdp.h -similarity index 53% -rename from drivers/gpu/drm/rockchip/cdn-dp-reg.h -rename to include/drm/bridge/cdns-mhdp.h -index 441248b7a79e..d76716d4edc6 100644 ---- a/drivers/gpu/drm/rockchip/cdn-dp-reg.h -+++ b/include/drm/bridge/cdns-mhdp.h -@@ -1,16 +1,31 @@ --/* SPDX-License-Identifier: GPL-2.0-only */ -+/* SPDX-License-Identifier: GPL-2.0 */ - /* - * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd - * Author: Chris Zhong -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. - */ - --#ifndef _CDN_DP_REG_H --#define _CDN_DP_REG_H -+#ifndef CDNS_MHDP_H_ -+#define CDNS_MHDP_H_ - -+#include -+#include -+#include -+#include -+#include - #include - - #define ADDR_IMEM 0x10000 - #define ADDR_DMEM 0x20000 -+#define ADDR_PHY_AFE 0x80000 - - /* APB CFG addr */ - #define APB_CTRL 0 -@@ -78,6 +93,10 @@ - #define SOURCE_PIF_SW_RESET 0x30834 - - /* bellow registers need access by mailbox */ -+/* source phy comp */ -+#define PHY_DATA_SEL 0x0818 -+#define LANES_CONFIG 0x0814 -+ - /* source car addr */ - #define SOURCE_HDTX_CAR 0x0900 - #define SOURCE_DPTX_CAR 0x0904 -@@ -89,6 +108,17 @@ - #define SOURCE_CIPHER_CAR 0x0920 - #define SOURCE_CRYPTO_CAR 0x0924 - -+/* mhdp tx_top_comp */ -+#define SCHEDULER_H_SIZE 0x1000 -+#define SCHEDULER_V_SIZE 0x1004 -+#define HDTX_SIGNAL_FRONT_WIDTH 0x100c -+#define HDTX_SIGNAL_SYNC_WIDTH 0x1010 -+#define HDTX_SIGNAL_BACK_WIDTH 0x1014 -+#define HDTX_CONTROLLER 0x1018 -+#define HDTX_HPD 0x1020 -+#define HDTX_CLOCK_REG_0 0x1024 -+#define HDTX_CLOCK_REG_1 0x1028 -+ - /* clock meters addr */ - #define CM_CTRL 0x0a00 - #define CM_I2S_CTRL 0x0a04 -@@ -308,18 +338,24 @@ - #define MB_SIZE_LSB_ID 3 - #define MB_DATA_ID 4 - --#define MB_MODULE_ID_DP_TX 0x01 -+#define MB_MODULE_ID_DP_TX 0x01 -+#define MB_MODULE_ID_HDMI_TX 0x03 - #define MB_MODULE_ID_HDCP_TX 0x07 - #define MB_MODULE_ID_HDCP_RX 0x08 - #define MB_MODULE_ID_HDCP_GENERAL 0x09 --#define MB_MODULE_ID_GENERAL 0x0a -+#define MB_MODULE_ID_GENERAL 0x0A - - /* general opcode */ - #define GENERAL_MAIN_CONTROL 0x01 - #define GENERAL_TEST_ECHO 0x02 - #define GENERAL_BUS_SETTINGS 0x03 - #define GENERAL_TEST_ACCESS 0x04 -+#define GENERAL_WRITE_REGISTER 0x05 -+#define GENERAL_WRITE_FIELD 0x06 -+#define GENERAL_READ_REGISTER 0x07 -+#define GENERAL_GET_HPD_STATE 0x11 - -+/* DPTX opcode */ - #define DPTX_SET_POWER_MNG 0x00 - #define DPTX_SET_HOST_CAPABILITIES 0x01 - #define DPTX_GET_EDID 0x02 -@@ -338,12 +374,24 @@ - #define DPTX_SET_LINK_BREAK_POINT 0x0f - #define DPTX_FORCE_LANES 0x10 - #define DPTX_HPD_STATE 0x11 -+#define DPTX_ADJUST_LT 0x12 -+ -+/* HDMI TX opcode */ -+#define HDMI_TX_READ 0x00 -+#define HDMI_TX_WRITE 0x01 -+#define HDMI_TX_UPDATE_READ 0x02 -+#define HDMI_TX_EDID 0x03 -+#define HDMI_TX_EVENTS 0x04 -+#define HDMI_TX_HPD_STATUS 0x05 -+#define HDMI_TX_DEBUG_ECHO 0xAA -+#define HDMI_TX_TEST 0xBB -+#define HDMI_TX_EDID_INTERNAL 0xF0 - - #define FW_STANDBY 0 - #define FW_ACTIVE 1 - --#define DPTX_EVENT_ENABLE_HPD BIT(0) --#define DPTX_EVENT_ENABLE_TRAINING BIT(1) -+#define MHDP_EVENT_ENABLE_HPD BIT(0) -+#define MHDP_EVENT_ENABLE_TRAINING BIT(1) - - #define LINK_TRAINING_NOT_ACTIVE 0 - #define LINK_TRAINING_RUN 1 -@@ -387,7 +435,35 @@ - #define HDCP_TX_IS_RECEIVER_ID_VALID_EVENT BIT(7) - - #define TU_SIZE 30 --#define CDN_DP_MAX_LINK_RATE DP_LINK_BW_5_4 -+#define CDNS_DP_MAX_LINK_RATE 540000 -+ -+#define F_HDMI_ENCODING(x) (((x) & ((1 << 2) - 1)) << 16) -+#define F_VIF_DATA_WIDTH(x) (((x) & ((1 << 2) - 1)) << 2) -+#define F_HDMI_MODE(x) (((x) & ((1 << 2) - 1)) << 0) -+#define F_GCP_EN(x) (((x) & ((1 << 1) - 1)) << 12) -+#define F_DATA_EN(x) (((x) & ((1 << 1) - 1)) << 15) -+#define F_HDMI2_PREAMBLE_EN(x) (((x) & ((1 << 1) - 1)) << 18) -+#define F_PIC_3D(x) (((x) & ((1 << 4) - 1)) << 7) -+#define F_BCH_EN(x) (((x) & ((1 << 1) - 1)) << 11) -+#define F_SOURCE_PHY_MHDP_SEL(x) (((x) & ((1 << 2) - 1)) << 3) -+#define F_HPD_VALID_WIDTH(x) (((x) & ((1 << 12) - 1)) << 0) -+#define F_HPD_GLITCH_WIDTH(x) (((x) & ((1 << 8) - 1)) << 12) -+#define F_HDMI2_CTRL_IL_MODE(x) (((x) & ((1 << 1) - 1)) << 19) -+#define F_SOURCE_PHY_LANE0_SWAP(x) (((x) & ((1 << 2) - 1)) << 0) -+#define F_SOURCE_PHY_LANE1_SWAP(x) (((x) & ((1 << 2) - 1)) << 2) -+#define F_SOURCE_PHY_LANE2_SWAP(x) (((x) & ((1 << 2) - 1)) << 4) -+#define F_SOURCE_PHY_LANE3_SWAP(x) (((x) & ((1 << 2) - 1)) << 6) -+#define F_SOURCE_PHY_COMB_BYPASS(x) (((x) & ((1 << 1) - 1)) << 21) -+#define F_SOURCE_PHY_20_10(x) (((x) & ((1 << 1) - 1)) << 22) -+#define F_PKT_ALLOC_ADDRESS(x) (((x) & ((1 << 4) - 1)) << 0) -+#define F_ACTIVE_IDLE_TYPE(x) (((x) & ((1 << 1) - 1)) << 17) -+#define F_FIFO1_FLUSH(x) (((x) & ((1 << 1) - 1)) << 0) -+#define F_PKT_ALLOC_WR_EN(x) (((x) & ((1 << 1) - 1)) << 0) -+#define F_DATA_WR(x) (x) -+#define F_WR_ADDR(x) (((x) & ((1 << 4) - 1)) << 0) -+#define F_HOST_WR(x) (((x) & ((1 << 1) - 1)) << 0) -+#define F_TYPE_VALID(x) (((x) & ((1 << 1) - 1)) << 16) -+#define F_PACKET_TYPE(x) (((x) & ((1 << 8) - 1)) << 8) - - /* audio */ - #define AUDIO_PACK_EN BIT(8) -@@ -416,6 +492,24 @@ - /* Reference cycles when using lane clock as reference */ - #define LANE_REF_CYC 0x8000 - -+#define HOTPLUG_DEBOUNCE_MS 200 -+ -+#define IRQ_IN 0 -+#define IRQ_OUT 1 -+#define IRQ_NUM 2 -+ -+#define cdns_mhdp_plat_call(mhdp, operation) \ -+ (!(mhdp) ? -ENODEV : (((mhdp)->plat_data && (mhdp)->plat_data->operation) ? \ -+ (mhdp)->plat_data->operation(mhdp) : ENOIOCTLCMD)) -+ -+/* bus access type */ -+enum { -+ BUS_TYPE_NORMAL_APB = 0, -+ BUS_TYPE_NORMAL_SAPB = 1, -+ BUS_TYPE_LOW4K_APB = 2, -+ BUS_TYPE_LOW4K_SAPB = 3, -+}; -+ - enum voltage_swing_level { - VOLTAGE_LEVEL_0, - VOLTAGE_LEVEL_1, -@@ -451,24 +545,261 @@ enum vic_bt_type { - BT_709 = 0x1, - }; - --void cdn_dp_clock_reset(struct cdn_dp_device *dp); -+enum audio_format { -+ AFMT_I2S = 0, -+ AFMT_SPDIF_INT = 1, -+ AFMT_SPDIF_EXT = 2, -+ AFMT_UNUSED, -+}; -+ -+enum { -+ MODE_DVI, -+ MODE_HDMI_1_4, -+ MODE_HDMI_2_0, -+}; -+ -+struct audio_info { -+ enum audio_format format; -+ int sample_rate; -+ int channels; -+ int sample_width; -+ int connector_type; -+}; -+ -+enum vic_pxl_encoding_format { -+ PXL_RGB = 0x1, -+ YCBCR_4_4_4 = 0x2, -+ YCBCR_4_2_2 = 0x4, -+ YCBCR_4_2_0 = 0x8, -+ Y_ONLY = 0x10, -+}; -+ -+struct video_info { -+ bool h_sync_polarity; -+ bool v_sync_polarity; -+ bool interlaced; -+ int color_depth; -+ enum vic_pxl_encoding_format color_fmt; -+}; -+ -+struct cdns_mhdp_host { -+ unsigned int link_rate; -+ u8 lanes_cnt; -+ u8 volt_swing; -+ u8 pre_emphasis; -+ u8 pattern_supp; -+ u8 fast_link; -+ u8 lane_mapping; -+ u8 enhanced; -+}; -+ -+struct cdns_mhdp_sink { -+ unsigned int link_rate; -+ u8 lanes_cnt; -+ u8 pattern_supp; -+ u8 fast_link; -+ u8 enhanced; -+}; -+ -+struct cdns_mhdp_bridge; -+struct cdns_mhdp_connector; -+ -+struct cdns_mhdp_bridge { -+ struct cdns_mhdp_device *mhdp; -+ struct drm_bridge base; -+ int pbn; -+ int8_t stream_id; -+ struct cdns_mhdp_connector *connector; -+ bool is_active; -+}; -+ -+struct cdns_mhdp_connector { -+ struct drm_connector base; -+ bool is_mst_connector; -+ struct drm_dp_mst_port *port; -+ struct cdns_mhdp_bridge *bridge; -+}; -+ -+struct cdns_mhdp_cec { -+ struct cec_adapter *adap; -+ struct device *dev; -+ struct mutex lock; -+ -+ struct cec_msg msg; -+ struct task_struct *cec_worker; -+}; -+ -+struct cdns_plat_data { -+ /* Vendor PHY support */ -+ int (*bind)(struct platform_device *pdev, -+ struct drm_encoder *encoder, -+ struct cdns_mhdp_device *mhdp); -+ void (*unbind)(struct device *dev); -+ -+ void (*plat_init)(struct cdns_mhdp_device *mhdp); -+ void (*plat_deinit)(struct cdns_mhdp_device *mhdp); -+ -+ int (*phy_set)(struct cdns_mhdp_device *mhdp); -+ bool (*phy_video_valid)(struct cdns_mhdp_device *mhdp); -+ int (*firmware_init)(struct cdns_mhdp_device *mhdp); -+ void (*pclk_rate)(struct cdns_mhdp_device *mhdp); -+ -+ int (*suspend)(struct cdns_mhdp_device *mhdp); -+ int (*resume)(struct cdns_mhdp_device *mhdp); -+ -+ int (*power_on)(struct cdns_mhdp_device *mhdp); -+ int (*power_off)(struct cdns_mhdp_device *mhdp); -+ -+ int bus_type; -+ int video_format; -+ char is_dp; -+ char *plat_name; -+}; -+ -+struct cdns_mhdp_device { -+ void __iomem *regs_base; -+ void __iomem *regs_sec; -+ -+ int bus_type; -+ -+ struct device *dev; -+ -+ struct cdns_mhdp_connector connector; -+ struct clk *spdif_clk; -+ struct reset_control *spdif_rst; -+ -+ struct platform_device *audio_pdev; -+ struct audio_info audio_info; -+ -+ struct cdns_mhdp_bridge bridge; -+ struct phy *phy; -+ -+ struct video_info video_info; -+ struct drm_display_mode mode; -+ const struct drm_display_mode *valid_mode; -+ unsigned int fw_version; -+ -+ struct drm_dp_mst_topology_mgr mst_mgr; -+ struct delayed_work hotplug_work; -+ -+ u32 lane_mapping; -+ bool link_up; -+ bool power_up; -+ bool plugged; -+ bool force_mode_set; -+ bool is_hpd; -+ bool is_ls1028a; -+ struct mutex lock; -+ struct mutex iolock; -+ -+ int irq[IRQ_NUM]; -+ -+ union { -+ struct _dp_data { -+ u8 dpcd[DP_RECEIVER_CAP_SIZE]; -+ u32 rate; -+ u8 num_lanes; -+ struct drm_dp_aux aux; -+ struct cdns_mhdp_host host; -+ struct cdns_mhdp_sink sink; -+ bool is_mst; -+ bool can_mst; -+ } dp; -+ struct _hdmi_data { -+ struct cdns_mhdp_cec cec; -+ u32 char_rate; -+ u32 hdmi_type; -+ } hdmi; -+ }; -+ const struct cdns_plat_data *plat_data; -+ -+}; -+ -+u32 cdns_mhdp_bus_read(struct cdns_mhdp_device *mhdp, u32 offset); -+void cdns_mhdp_bus_write(u32 val, struct cdns_mhdp_device *mhdp, u32 offset); -+void cdns_mhdp_clock_reset(struct cdns_mhdp_device *mhdp); -+void cdns_mhdp_set_fw_clk(struct cdns_mhdp_device *mhdp, unsigned long clk); -+u32 cdns_mhdp_get_fw_clk(struct cdns_mhdp_device *mhdp); -+int cdns_mhdp_load_firmware(struct cdns_mhdp_device *mhdp, const u32 *i_mem, -+ u32 i_size, const u32 *d_mem, u32 d_size); -+int cdns_mhdp_set_firmware_active(struct cdns_mhdp_device *mhdp, bool enable); -+int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp, bool flip); -+int cdns_mhdp_event_config(struct cdns_mhdp_device *mhdp); -+u32 cdns_mhdp_get_event(struct cdns_mhdp_device *mhdp); -+int cdns_mhdp_dpcd_write(struct cdns_mhdp_device *mhdp, u32 addr, u8 value); -+int cdns_mhdp_dpcd_read(struct cdns_mhdp_device *mhdp, -+ u32 addr, u8 *data, u16 len); -+int cdns_mhdp_get_edid_block(void *mhdp, u8 *edid, -+ unsigned int block, size_t length); -+int cdns_mhdp_train_link(struct cdns_mhdp_device *mhdp); -+int cdns_mhdp_set_video_status(struct cdns_mhdp_device *mhdp, int active); -+int cdns_mhdp_config_video(struct cdns_mhdp_device *mhdp); -+ -+/* Audio */ -+int cdns_mhdp_audio_stop(struct cdns_mhdp_device *mhdp, -+ struct audio_info *audio); -+int cdns_mhdp_audio_mute(struct cdns_mhdp_device *mhdp, bool enable); -+int cdns_mhdp_audio_config(struct cdns_mhdp_device *mhdp, -+ struct audio_info *audio); -+int cdns_mhdp_register_audio_driver(struct device *dev); -+void cdns_mhdp_unregister_audio_driver(struct device *dev); -+ -+int cdns_mhdp_reg_read(struct cdns_mhdp_device *mhdp, u32 addr); -+int cdns_mhdp_reg_write(struct cdns_mhdp_device *mhdp, u32 addr, u32 val); -+int cdns_mhdp_reg_write_bit(struct cdns_mhdp_device *mhdp, u16 addr, -+ u8 start_bit, u8 bits_no, u32 val); -+int cdns_mhdp_adjust_lt(struct cdns_mhdp_device *mhdp, u8 nlanes, -+ u16 udelay, u8 *lanes_data, -+ u8 *dpcd); -+ -+int cdns_mhdp_read_hpd(struct cdns_mhdp_device *mhdp); -+u32 cdns_phy_reg_read(struct cdns_mhdp_device *mhdp, u32 addr); -+int cdns_phy_reg_write(struct cdns_mhdp_device *mhdp, u32 addr, u32 val); -+int cdns_mhdp_mailbox_send(struct cdns_mhdp_device *mhdp, u8 module_id, -+ u8 opcode, u16 size, u8 *message); -+int cdns_mhdp_mailbox_read_receive(struct cdns_mhdp_device *mhdp, -+ u8 *buff, u16 buff_size); -+int cdns_mhdp_mailbox_validate_receive(struct cdns_mhdp_device *mhdp, -+ u8 module_id, u8 opcode, -+ u16 req_size); -+int cdns_mhdp_mailbox_read(struct cdns_mhdp_device *mhdp); -+ -+void cdns_mhdp_infoframe_set(struct cdns_mhdp_device *mhdp, -+ u8 entry_id, u8 packet_len, u8 *packet, u8 packet_type); -+int cdns_hdmi_get_edid_block(void *data, u8 *edid, u32 block, size_t length); -+int cdns_hdmi_scdc_read(struct cdns_mhdp_device *mhdp, u8 addr, u8 *data); -+int cdns_hdmi_scdc_write(struct cdns_mhdp_device *mhdp, u8 addr, u8 value); -+int cdns_hdmi_ctrl_init(struct cdns_mhdp_device *mhdp, int protocol, u32 char_rate); -+int cdns_hdmi_mode_config(struct cdns_mhdp_device *mhdp, struct drm_display_mode *mode, -+ struct video_info *video_info); -+int cdns_hdmi_disable_gcp(struct cdns_mhdp_device *mhdp); -+int cdns_hdmi_enable_gcp(struct cdns_mhdp_device *mhdp); -+ -+bool cdns_mhdp_check_alive(struct cdns_mhdp_device *mhdp); -+ -+/* HDMI */ -+int cdns_hdmi_probe(struct platform_device *pdev, -+ struct cdns_mhdp_device *mhdp); -+void cdns_hdmi_remove(struct platform_device *pdev); -+void cdns_hdmi_unbind(struct device *dev); -+int cdns_hdmi_bind(struct platform_device *pdev, -+ struct drm_encoder *encoder, struct cdns_mhdp_device *mhdp); -+void cdns_hdmi_set_sample_rate(struct cdns_mhdp_device *mhdp, unsigned int rate); -+void cdns_hdmi_audio_enable(struct cdns_mhdp_device *mhdp); -+void cdns_hdmi_audio_disable(struct cdns_mhdp_device *mhdp); -+ -+/* DP */ -+int cdns_dp_probe(struct platform_device *pdev, -+ struct cdns_mhdp_device *mhdp); -+void cdns_dp_remove(struct platform_device *pdev); -+void cdns_dp_unbind(struct device *dev); -+int cdns_dp_bind(struct platform_device *pdev, -+ struct drm_encoder *encoder, struct cdns_mhdp_device *mhdp); -+ -+/* CEC */ -+#ifdef CONFIG_DRM_CDNS_HDMI_CEC -+int cdns_mhdp_register_cec_driver(struct device *dev); -+int cdns_mhdp_unregister_cec_driver(struct device *dev); -+#endif - --void cdn_dp_set_fw_clk(struct cdn_dp_device *dp, unsigned long clk); --int cdn_dp_load_firmware(struct cdn_dp_device *dp, const u32 *i_mem, -- u32 i_size, const u32 *d_mem, u32 d_size); --int cdn_dp_set_firmware_active(struct cdn_dp_device *dp, bool enable); --int cdn_dp_set_host_cap(struct cdn_dp_device *dp, u8 lanes, bool flip); --int cdn_dp_event_config(struct cdn_dp_device *dp); --u32 cdn_dp_get_event(struct cdn_dp_device *dp); --int cdn_dp_get_hpd_status(struct cdn_dp_device *dp); --int cdn_dp_dpcd_write(struct cdn_dp_device *dp, u32 addr, u8 value); --int cdn_dp_dpcd_read(struct cdn_dp_device *dp, u32 addr, u8 *data, u16 len); --int cdn_dp_get_edid_block(void *dp, u8 *edid, -- unsigned int block, size_t length); --int cdn_dp_train_link(struct cdn_dp_device *dp); --int cdn_dp_set_video_status(struct cdn_dp_device *dp, int active); --int cdn_dp_config_video(struct cdn_dp_device *dp); --int cdn_dp_audio_stop(struct cdn_dp_device *dp, struct audio_info *audio); --int cdn_dp_audio_mute(struct cdn_dp_device *dp, bool enable); --int cdn_dp_audio_config(struct cdn_dp_device *dp, struct audio_info *audio); --#endif /* _CDN_DP_REG_H */ -+#endif /* CDNS_MHDP_H_ */ --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0002-MLK-24065-1-drm-bridge-cadence-fix-dp_aux_transfer-w.patch b/projects/NXP/devices/iMX8/patches/linux/0002-MLK-24065-1-drm-bridge-cadence-fix-dp_aux_transfer-w.patch deleted file mode 100644 index 1b560edf51..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0002-MLK-24065-1-drm-bridge-cadence-fix-dp_aux_transfer-w.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 55eb19200d650ead73139ee8444db9119718fd31 Mon Sep 17 00:00:00 2001 -From: Sergey Zhuravlevich -Date: Tue, 12 May 2020 14:23:15 +0200 -Subject: [PATCH 02/49] MLK-24065-1: drm: bridge: cadence: fix dp_aux_transfer - write return value - -After exiting the loop in DP_AUX_NATIVE_WRITE it was returning 0. It's supposed -to return the number of bytes transferred on success. - -Signed-off-by: Sergey Zhuravlevich -Acked-by: Sandor Yu -Tested-By: Sandor Yu ---- - drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -index acb5c860da73..aa92029f44e9 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -@@ -67,6 +67,8 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *aux, - - return ret; - } -+ msg->reply = DP_AUX_NATIVE_REPLY_ACK; -+ return msg->size; - } - - if (msg->request == DP_AUX_NATIVE_READ) { --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0002-arm64-dts-fsl-imx8mq-evk-enable-DCSS-and-HDMI.patch b/projects/NXP/devices/iMX8/patches/linux/0002-arm64-dts-fsl-imx8mq-evk-enable-DCSS-and-HDMI.patch new file mode 100644 index 0000000000..f8fc74e5fd --- /dev/null +++ b/projects/NXP/devices/iMX8/patches/linux/0002-arm64-dts-fsl-imx8mq-evk-enable-DCSS-and-HDMI.patch @@ -0,0 +1,71 @@ +From 5825e6107062b231f1c7449502e04e559f8266e8 Mon Sep 17 00:00:00 2001 +From: Lucas Stach +Date: Tue, 13 Feb 2018 12:47:09 +0100 +Subject: [PATCH 1/4] arm64: dts: fsl: imx8mq-evk: enable DCSS and HDMI + +Adapted for [PATCH v16] Initial support Cadence MHDP8501(HDMI/DP) for i.MX8MQ +Adapted for [PATCH v19] Initial support Cadence MHDP8501(HDMI/DP) for i.MX8MQ + +Signed-off-by: Lucas Stach +--- + arch/arm64/boot/dts/freescale/imx8mq-evk.dts | 31 ++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts +index 7507548cdb16..267e32895aa0 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts ++++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts +@@ -139,6 +139,17 @@ sound-hdmi-arc { + spdif-controller = <&spdif2>; + spdif-in; + }; ++ ++ hdmi_connector: connector { ++ compatible = "hdmi-connector"; ++ label = "X11"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ }; ++ }; ++ }; + }; + + &A53_0 { +@@ -226,6 +237,32 @@ wl-reg-on-hog { + }; + }; + ++&dcss { ++ status = "okay"; ++}; ++ ++&hdmi_connector { ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&mhdp_out>; ++ }; ++ }; ++}; ++ ++&mhdp { ++ status = "okay"; ++ ports { ++ port@1 { ++ reg = <1>; ++ ++ mhdp_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ data-lanes = <0 1 2 3>; ++ }; ++ }; ++ }; ++}; ++ + &i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; +-- +2.43.0 + diff --git a/projects/NXP/devices/iMX8/patches/linux/0003-MLK-24065-3-drm-bridge-cadence-use-the-lane-mapping-.patch b/projects/NXP/devices/iMX8/patches/linux/0003-MLK-24065-3-drm-bridge-cadence-use-the-lane-mapping-.patch deleted file mode 100644 index 76aad36aeb..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0003-MLK-24065-3-drm-bridge-cadence-use-the-lane-mapping-.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 90e1a010995c0a87b0216706b1255ca5d0c36286 Mon Sep 17 00:00:00 2001 -From: Sergey Zhuravlevich -Date: Tue, 12 May 2020 14:23:15 +0200 -Subject: [PATCH 03/49] MLK-24065-3: drm: bridge: cadence: use the lane mapping - from dt when setting host capabilities - -Signed-off-by: Sergey Zhuravlevich -Acked-by: Sandor Yu -Tested-By: Sandor Yu ---- - drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 2 +- - drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c | 4 ++-- - include/drm/bridge/cdns-mhdp.h | 2 +- - 3 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -index aa92029f44e9..c059d56b4f46 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -@@ -152,7 +152,7 @@ static void cdns_dp_mode_set(struct cdns_mhdp_device *mhdp) - cdns_mhdp_reg_write(mhdp, LANES_CONFIG, 0x00400000 | lane_mapping); - - /* Set DP host capability */ -- ret = cdns_mhdp_set_host_cap(mhdp, false); -+ ret = cdns_mhdp_set_host_cap(mhdp); - if (ret) { - DRM_DEV_ERROR(mhdp->dev, "Failed to set host cap %d\n", ret); - return; -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -index 91d1cfd4b2af..9c0a2668e494 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -@@ -438,7 +438,7 @@ int cdns_mhdp_set_firmware_active(struct cdns_mhdp_device *mhdp, bool enable) - } - EXPORT_SYMBOL(cdns_mhdp_set_firmware_active); - --int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp, bool flip) -+int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp) - { - u8 msg[8]; - int ret; -@@ -449,7 +449,7 @@ int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp, bool flip) - msg[3] = PRE_EMPHASIS_LEVEL_3; - msg[4] = PTS1 | PTS2 | PTS3 | PTS4; - msg[5] = FAST_LT_NOT_SUPPORT; -- msg[6] = flip ? LANE_MAPPING_FLIPPED : LANE_MAPPING_NORMAL; -+ msg[6] = mhdp->lane_mapping; - msg[7] = ENHANCED; - - ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, -diff --git a/include/drm/bridge/cdns-mhdp.h b/include/drm/bridge/cdns-mhdp.h -index d76716d4edc6..4dc6e428b5f7 100644 ---- a/include/drm/bridge/cdns-mhdp.h -+++ b/include/drm/bridge/cdns-mhdp.h -@@ -723,7 +723,7 @@ u32 cdns_mhdp_get_fw_clk(struct cdns_mhdp_device *mhdp); - int cdns_mhdp_load_firmware(struct cdns_mhdp_device *mhdp, const u32 *i_mem, - u32 i_size, const u32 *d_mem, u32 d_size); - int cdns_mhdp_set_firmware_active(struct cdns_mhdp_device *mhdp, bool enable); --int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp, bool flip); -+int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp); - int cdns_mhdp_event_config(struct cdns_mhdp_device *mhdp); - u32 cdns_mhdp_get_event(struct cdns_mhdp_device *mhdp); - int cdns_mhdp_dpcd_write(struct cdns_mhdp_device *mhdp, u32 addr, u8 value); --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0003-arm64-dts-fsl-imx8mq-pico-pi-enable-DCSS-and-HDMI.patch b/projects/NXP/devices/iMX8/patches/linux/0003-arm64-dts-fsl-imx8mq-pico-pi-enable-DCSS-and-HDMI.patch new file mode 100644 index 0000000000..d9ef1cc2b0 --- /dev/null +++ b/projects/NXP/devices/iMX8/patches/linux/0003-arm64-dts-fsl-imx8mq-pico-pi-enable-DCSS-and-HDMI.patch @@ -0,0 +1,62 @@ +From 6b9309988072e3b5b7b3900a1254507316eb72cf Mon Sep 17 00:00:00 2001 +From: Lukas Rusak +Date: Tue, 9 Mar 2021 10:47:27 -0800 +Subject: [PATCH 2/4] arm64: dts: fsl: imx8mq-pico-pi: enable DCSS and HDMI + +Adapted for [PATCH v16] Initial support Cadence MHDP8501(HDMI/DP) for i.MX8MQ +Adapted for [PATCH v19] Initial support Cadence MHDP8501(HDMI/DP) for i.MX8MQ +--- + .../boot/dts/freescale/imx8mq-pico-pi.dts | 31 +++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts b/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts +index 89cbec5c41b2..5e2b1a84a85e 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts ++++ b/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts +@@ -54,6 +54,43 @@ ethphy0: ethernet-phy@1 { + reg = <1>; + }; + }; ++ ++ hdmi_connector: connector { ++ compatible = "hdmi-connector"; ++ label = "X11"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ }; ++ }; ++ }; ++}; ++ ++&dcss { ++ status = "okay"; ++}; ++ ++&hdmi_connector { ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&mhdp_out>; ++ }; ++ }; ++}; ++ ++&mhdp { ++ status = "okay"; ++ ports { ++ port@1 { ++ reg = <1>; ++ ++ mhdp_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ data-lanes = <0 1 2 3>; ++ }; ++ }; ++ }; + }; + + &i2c1 { +-- +2.43.0 + diff --git a/projects/NXP/devices/iMX8/patches/linux/0004-MLK-24065-2-drm-bridge-cadence-print-error-when-cloc.patch b/projects/NXP/devices/iMX8/patches/linux/0004-MLK-24065-2-drm-bridge-cadence-print-error-when-cloc.patch deleted file mode 100644 index 23aa13e191..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0004-MLK-24065-2-drm-bridge-cadence-print-error-when-cloc.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 62c1852bc0f94efb6884d34c2c27dcf1efa3b282 Mon Sep 17 00:00:00 2001 -From: Sergey Zhuravlevich -Date: Tue, 12 May 2020 14:23:15 +0200 -Subject: [PATCH 04/49] MLK-24065-2: drm: bridge: cadence: print error when - clock recovery fails - -Signed-off-by: Sergey Zhuravlevich -Acked-by: Sandor Yu -Tested-By: Sandor Yu ---- - drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c -index f025c39d12ea..a032e19765a4 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-dp.c -@@ -106,7 +106,9 @@ static int cdns_mhdp_training_start(struct cdns_mhdp_device *mhdp) - if (ret) - goto err_training_start; - -- if (event[1] & EQ_PHASE_FINISHED) -+ if (event[1] & CLK_RECOVERY_FAILED) -+ DRM_DEV_ERROR(mhdp->dev, "clock recovery failed\n"); -+ else if (event[1] & EQ_PHASE_FINISHED) - return 0; - } - --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0004-arm64-dts-fsl-imx8mq-phanbell.dts-enable-DCSS-and-HD.patch b/projects/NXP/devices/iMX8/patches/linux/0004-arm64-dts-fsl-imx8mq-phanbell.dts-enable-DCSS-and-HD.patch new file mode 100644 index 0000000000..e7d4dfd905 --- /dev/null +++ b/projects/NXP/devices/iMX8/patches/linux/0004-arm64-dts-fsl-imx8mq-phanbell.dts-enable-DCSS-and-HD.patch @@ -0,0 +1,68 @@ +From d7a46875e8cc330cc3f1082c054ecfb0c1b32727 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Sun, 29 Sep 2024 21:08:57 +1000 +Subject: [PATCH 3/4] arm64: dts: fsl: imx8mq-phanbell.dts: enable DCSS and + HDMI + +--- + .../boot/dts/freescale/imx8mq-phanbell.dts | 31 +++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts b/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts +index a3b9d615a3b4..deba4a6f65d5 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts ++++ b/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts +@@ -46,6 +46,17 @@ fan: gpio-fan { + pinctrl-0 = <&pinctrl_gpio_fan>; + status = "okay"; + }; ++ ++ hdmi_connector: connector { ++ compatible = "hdmi-connector"; ++ label = "X11"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ }; ++ }; ++ }; + }; + + &A53_0 { +@@ -111,6 +122,32 @@ map4 { + }; + }; + ++&dcss { ++ status = "okay"; ++}; ++ ++&hdmi_connector { ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&mhdp_out>; ++ }; ++ }; ++}; ++ ++&mhdp { ++ status = "okay"; ++ ports { ++ port@1 { ++ reg = <1>; ++ ++ mhdp_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ data-lanes = <0 1 2 3>; ++ }; ++ }; ++ }; ++}; ++ + &i2c1 { + clock-frequency = <400000>; + pinctrl-names = "default"; +-- +2.43.0 + diff --git a/projects/NXP/devices/iMX8/patches/linux/0005-LF-1511-drm-cdn-cec-replace-i-with-i-in-loop.patch b/projects/NXP/devices/iMX8/patches/linux/0005-LF-1511-drm-cdn-cec-replace-i-with-i-in-loop.patch deleted file mode 100644 index d3cbe09cb7..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0005-LF-1511-drm-cdn-cec-replace-i-with-i-in-loop.patch +++ /dev/null @@ -1,37 +0,0 @@ -From eb19fd99254d6a0aa97bb08c09b9f82ebff306c5 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Fri, 19 Jun 2020 15:32:28 +0800 -Subject: [PATCH 05/49] LF-1511: drm: cdn-cec: replace ++i with i++ in loop - -replace ++i with i++ in loop to prevent Coverity issue. -Coverity ID 9000767 - -Signed-off-by: Sandor Yu -Reviewed-by: Fancy Fang ---- - drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c -index 5717bb0bcb75..029ad761606a 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c -@@ -163,13 +163,13 @@ static int mhdp_cec_set_logical_addr(struct cdns_mhdp_cec *cec, u32 la) - - if (la == CEC_LOG_ADDR_INVALID) - /* invalid all LA address */ -- for (i = 0; i < CEC_MAX_LOG_ADDRS; ++i) { -+ for (i = 0; i < CEC_MAX_LOG_ADDRS; i++) { - mhdp_cec_write(cec, LOGICAL_ADDRESS_LA0 + (i * REG_ADDR_OFF), 0); - return 0; - } - - /* In fact cdns mhdp cec could support max 5 La address */ -- for (i = 0; i < CEC_MAX_LOG_ADDRS; ++i) { -+ for (i = 0; i < CEC_MAX_LOG_ADDRS; i++) { - la_reg = mhdp_cec_read(cec, LOGICAL_ADDRESS_LA0 + (i * REG_ADDR_OFF)); - /* Check LA already used */ - if (la_reg & 0x10) --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0006-LF-1512-drm-cdns-mhdp-avoid-potentially-overflowing.patch b/projects/NXP/devices/iMX8/patches/linux/0006-LF-1512-drm-cdns-mhdp-avoid-potentially-overflowing.patch deleted file mode 100644 index 9e78a7707e..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0006-LF-1512-drm-cdns-mhdp-avoid-potentially-overflowing.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 09dfa5b8ba1a38050e4e95faab1cf07c6a509dad Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Fri, 19 Jun 2020 16:05:42 +0800 -Subject: [PATCH 06/49] LF-1512: drm: cdns mhdp: avoid potentially overflowing - -covert to unsigned 64 bits to avoid potentially overflowing. -Report by Coverity ID 6652952 6652952. - -Signed-off-by: Sandor Yu -Reviewed-by: Fancy Fang ---- - drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -index 9c0a2668e494..890add9b7c67 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -@@ -657,7 +657,7 @@ int cdns_mhdp_config_video(struct cdns_mhdp_device *mhdp) - */ - do { - tu_size_reg += 2; -- symbol = tu_size_reg * mode->clock * bit_per_pix; -+ symbol = (u64) tu_size_reg * mode->clock * bit_per_pix; - do_div(symbol, mhdp->dp.num_lanes * link_rate * 8); - rem = do_div(symbol, 1000); - if (tu_size_reg > 64) { --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0007-MLK-24335-drm-bridge-cdns-hdmi-support-work-in-DVI-m.patch b/projects/NXP/devices/iMX8/patches/linux/0007-MLK-24335-drm-bridge-cdns-hdmi-support-work-in-DVI-m.patch deleted file mode 100644 index 32ae11b0e6..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0007-MLK-24335-drm-bridge-cdns-hdmi-support-work-in-DVI-m.patch +++ /dev/null @@ -1,41 +0,0 @@ -From a1b02ef19cbc24603e1e212f4f4258ca2c59aaad Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Thu, 18 Jun 2020 14:18:04 +0800 -Subject: [PATCH 07/49] MLK-24335: drm: bridge: cdns: hdmi support work in DVI - mode - -hdmi support work in DVI mode. - -Signed-off-by: Sandor Yu ---- - drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index da40f62617ef..5f2442fa761f 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -32,8 +32,9 @@ static void hdmi_sink_config(struct cdns_mhdp_device *mhdp) - struct drm_scdc *scdc = &mhdp->connector.base.display_info.hdmi.scdc; - u8 buff = 0; - -- /* Default work in HDMI1.4 */ -- mhdp->hdmi.hdmi_type = MODE_HDMI_1_4; -+ /* return if hdmi work in DVI mode */ -+ if (mhdp->hdmi.hdmi_type == MODE_DVI) -+ return; - - /* check sink support SCDC or not */ - if (scdc->supported != true) { -@@ -264,6 +265,8 @@ static int cdns_hdmi_connector_get_modes(struct drm_connector *connector) - edid->header[6], edid->header[7]); - drm_connector_update_edid_property(connector, edid); - num_modes = drm_add_edid_modes(connector, edid); -+ mhdp->hdmi.hdmi_type = drm_detect_hdmi_monitor(edid) ? -+ MODE_HDMI_1_4 : MODE_DVI; - kfree(edid); - } - --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0008-LF-1762-21-gpu-drm-bridge-cadence-hdmi-update-API-.m.patch b/projects/NXP/devices/iMX8/patches/linux/0008-LF-1762-21-gpu-drm-bridge-cadence-hdmi-update-API-.m.patch deleted file mode 100644 index 114fa3184b..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0008-LF-1762-21-gpu-drm-bridge-cadence-hdmi-update-API-.m.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 83f932299b9969a1823b085d2269db677362f897 Mon Sep 17 00:00:00 2001 -From: Dong Aisheng -Date: Tue, 14 Jul 2020 19:18:25 +0800 -Subject: [PATCH 08/49] LF-1762-21 gpu: drm: bridge: cadence: hdmi: update API - .mode_valid() - -API changed since: -12c683e12cd8 ("drm: bridge: Pass drm_display_info to drm_bridge_funcs .mode_valid()") - -Signed-off-by: Dong Aisheng ---- - drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 1 + - drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -index c059d56b4f46..cb4897c664f0 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -@@ -256,6 +256,7 @@ static int cdns_dp_bridge_attach(struct drm_bridge *bridge, - - static enum drm_mode_status - cdns_dp_bridge_mode_valid(struct drm_bridge *bridge, -+ const struct drm_display_info *info, - const struct drm_display_mode *mode) - { - enum drm_mode_status mode_status = MODE_OK; -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index 5f2442fa761f..1e5130e295f7 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -359,6 +359,7 @@ static int cdns_hdmi_bridge_attach(struct drm_bridge *bridge, - - static enum drm_mode_status - cdns_hdmi_bridge_mode_valid(struct drm_bridge *bridge, -+ const struct drm_display_info *info, - const struct drm_display_mode *mode) - { - struct cdns_mhdp_device *mhdp = bridge->driver_private; --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0009-LF-2271-1-drm-bridge-cdns-Use-colorspace-connector-p.patch b/projects/NXP/devices/iMX8/patches/linux/0009-LF-2271-1-drm-bridge-cdns-Use-colorspace-connector-p.patch deleted file mode 100644 index 0c1a6a7166..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0009-LF-2271-1-drm-bridge-cdns-Use-colorspace-connector-p.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 150d291f3e5cb47a97790b89e79d8f1a5aa797dd Mon Sep 17 00:00:00 2001 -From: Laurentiu Palcu -Date: Fri, 28 Aug 2020 10:26:31 +0300 -Subject: [PATCH 09/49] LF-2271-1: drm/bridge/cdns: Use colorspace connector - property for imx8mq - -This patch achieves 2 goals: - * Make use of colorspace property when setting up the color_depth and - color_fmt. The userspace can now choose which colorspace to use by changing - the colorspace property; - * Do not use drm_display_mode private_flags to signal CRTC which pixel encoding - is being used by connector. Upstream is getting rid of 'private_flags' usage - and the declaration will probably be removed in the next release; - -Signed-off-by: Laurentiu Palcu -Reviewed-by: Robert Chiras ---- - .../gpu/drm/bridge/cadence/cdns-hdmi-core.c | 58 ++++++++++++------- - 1 file changed, 36 insertions(+), 22 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index 1e5130e295f7..2796252adf68 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -412,6 +412,7 @@ bool cdns_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, - struct drm_display_mode *adjusted_mode) - { - struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ struct drm_connector_state *conn_state = mhdp->connector.base.state; - struct drm_display_info *di = &mhdp->connector.base.display_info; - struct video_info *video = &mhdp->video_info; - int vic = drm_match_cea_mode(mode); -@@ -428,36 +429,49 @@ bool cdns_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, - } - - /* imx8mq */ -- if (vic == 97 || vic == 96) { -- if (di->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36) -- video->color_depth = 12; -- else if (di->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) -- video->color_depth = 10; -- -- if (drm_mode_is_420_only(di, mode) || -- (drm_mode_is_420_also(di, mode) && -- video->color_depth > 8)) { -+ if (conn_state->colorspace == DRM_MODE_COLORIMETRY_DEFAULT) -+ return !drm_mode_is_420_only(di, mode); -+ -+ if (conn_state->colorspace == DRM_MODE_COLORIMETRY_BT2020_RGB) { -+ if (drm_mode_is_420_only(di, mode)) -+ return false; -+ -+ /* 10b RGB is not supported for following VICs */ -+ if (vic == 97 || vic == 96 || vic == 95 || vic == 93 || vic == 94) -+ return false; -+ -+ video->color_depth = 10; -+ -+ return true; -+ } -+ -+ if (conn_state->colorspace == DRM_MODE_COLORIMETRY_BT2020_CYCC || -+ conn_state->colorspace == DRM_MODE_COLORIMETRY_BT2020_YCC) { -+ if (drm_mode_is_420_only(di, mode)) { - video->color_fmt = YCBCR_4_2_0; - -- adjusted_mode->private_flags = 1; -+ if (di->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36) -+ video->color_depth = 12; -+ else if (di->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) -+ video->color_depth = 10; -+ else -+ return false; -+ - return true; - } - -- video->color_depth = 8; -- return true; -- } -+ video->color_fmt = YCBCR_4_2_2; -+ -+ if (!(di->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) -+ return false; - -- /* Any defined maximum tmds clock limit we must not exceed*/ -- if ((di->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36) && -- (mode->clock * 3 / 2 <= di->max_tmds_clock)) - video->color_depth = 12; -- else if ((di->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) && -- (mode->clock * 5 / 4 <= di->max_tmds_clock)) -- video->color_depth = 10; - -- /* 10-bit color depth for the following modes is not supported */ -- if ((vic == 95 || vic == 94 || vic == 93) && video->color_depth == 10) -- video->color_depth = 8; -+ return true; -+ } -+ -+ video->color_fmt = drm_mode_is_420_only(di, mode) ? YCBCR_4_2_0 : YCBCR_4_4_4; -+ video->color_depth = 8; - - return true; - } --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0009-arm64-pci-add-ext_osc.patch b/projects/NXP/devices/iMX8/patches/linux/0009-arm64-pci-add-ext_osc.patch new file mode 100644 index 0000000000..7dfe3a4bdf --- /dev/null +++ b/projects/NXP/devices/iMX8/patches/linux/0009-arm64-pci-add-ext_osc.patch @@ -0,0 +1,35 @@ +From 4e40d36940e9d5159ba8a72e4ad04580025d5b94 Mon Sep 17 00:00:00 2001 +From: Rudi Heitbaum +Date: Tue, 1 Oct 2024 14:28:57 +0000 +Subject: [PATCH] arm64: pci: add ext_osc + +ext_osc from https://lore.kernel.org/lkml/1552467452-538-2-git-send-email-hongxing.zhu@nxp.com/ +--- + drivers/pci/controller/dwc/pci-imx6.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c +index 74703362aeec..603ca50229ec 100644 +--- a/drivers/pci/controller/dwc/pci-imx6.c ++++ b/drivers/pci/controller/dwc/pci-imx6.c +@@ -90,6 +90,7 @@ struct imx_pcie { + u32 tx_deemph_gen2_6db; + u32 tx_swing_full; + u32 tx_swing_low; ++ u32 ext_osc; + struct regulator *vpcie; + struct regulator *vph; + void __iomem *phy_base; +@@ -1287,6 +1288,9 @@ static int imx_pcie_probe(struct platform_device *pdev) + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->dbi_base); + ++ if (of_property_read_u32(node, "ext_osc", &imx_pcie->ext_osc) < 0) ++ imx_pcie->ext_osc = 0; ++ + /* Fetch GPIOs */ + imx_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0); + imx_pcie->gpio_active_high = of_property_read_bool(node, +-- +2.43.0 + diff --git a/projects/NXP/devices/iMX8/patches/linux/0010-MLK-24770-drm-mhdp-Sync-DPTX-capability-with-Cadence.patch b/projects/NXP/devices/iMX8/patches/linux/0010-MLK-24770-drm-mhdp-Sync-DPTX-capability-with-Cadence.patch deleted file mode 100644 index efc243e6f3..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0010-MLK-24770-drm-mhdp-Sync-DPTX-capability-with-Cadence.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 04a71f1da60e51f277d4979c698e52cacb028666 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Mon, 14 Sep 2020 15:06:35 +0800 -Subject: [PATCH 10/49] MLK-24770: drm: mhdp: Sync DPTX capability with Cadence - sample code - -Sync the max vswing and pre-emphasis setting with Cadence sample code. -The max vswing is VOLTAGE_LEVEL_3 and -the max pre-emphasis is PRE_EMPHASIS_LEVEL_2 now. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -index 890add9b7c67..2043016f176b 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -@@ -445,8 +445,8 @@ int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp) - - msg[0] = drm_dp_link_rate_to_bw_code(mhdp->dp.rate); - msg[1] = mhdp->dp.num_lanes | SCRAMBLER_EN; -- msg[2] = VOLTAGE_LEVEL_2; -- msg[3] = PRE_EMPHASIS_LEVEL_3; -+ msg[2] = VOLTAGE_LEVEL_3; -+ msg[3] = PRE_EMPHASIS_LEVEL_2; - msg[4] = PTS1 | PTS2 | PTS3 | PTS4; - msg[5] = FAST_LT_NOT_SUPPORT; - msg[6] = mhdp->lane_mapping; --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0011-MLK-24520-drm-bridge-cdns-increase-maximum-width-fro.patch b/projects/NXP/devices/iMX8/patches/linux/0011-MLK-24520-drm-bridge-cdns-increase-maximum-width-fro.patch deleted file mode 100644 index baf7c0f9dc..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0011-MLK-24520-drm-bridge-cdns-increase-maximum-width-fro.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 11b66e4bdb8ba6dc4e6981ecef69534c3d6d8df8 Mon Sep 17 00:00:00 2001 -From: "Oliver F. Brown" -Date: Thu, 23 Jul 2020 18:24:23 -0500 -Subject: [PATCH 11/49] MLK-24520: drm: bridge: cdns: increase maximum width - from 4096 to 5120. - -This patch increases the maximum width to 5120. - -Signed-off-by: Oliver F. Brown -Reviewed-by: Liu Ying ---- - drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 4 ++-- - drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 4 ++-- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -index cb4897c664f0..0f2a38d19a57 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -@@ -270,8 +270,8 @@ cdns_dp_bridge_mode_valid(struct drm_bridge *bridge, - if (mode->clock > 594000) - return MODE_CLOCK_HIGH; - -- /* 4096x2160 is not supported now */ -- if (mode->hdisplay > 3840) -+ /* 5120 x 2160 is the maximum supported resulution */ -+ if (mode->hdisplay > 5120) - return MODE_BAD_HVALUE; - - if (mode->vdisplay > 2160) -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index 2796252adf68..442df6284c49 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -375,8 +375,8 @@ cdns_hdmi_bridge_mode_valid(struct drm_bridge *bridge, - if (mode->clock > 594000) - return MODE_CLOCK_HIGH; - -- /* 4096x2160 is not supported */ -- if (mode->hdisplay > 3840 || mode->vdisplay > 2160) -+ /* 5120 x 2160 is the maximum supported resolution */ -+ if (mode->hdisplay > 5120 || mode->vdisplay > 2160) - return MODE_BAD_HVALUE; - - mhdp->valid_mode = mode; --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0011-imx8mq-phanbell.dts-Enable-Coral-specifics-e.g.-PCIE.patch b/projects/NXP/devices/iMX8/patches/linux/0011-imx8mq-phanbell.dts-Enable-Coral-specifics-e.g.-PCIE.patch new file mode 100644 index 0000000000..e582fb6e5e --- /dev/null +++ b/projects/NXP/devices/iMX8/patches/linux/0011-imx8mq-phanbell.dts-Enable-Coral-specifics-e.g.-PCIE.patch @@ -0,0 +1,226 @@ +From 2806bcdfbe52eeba6d09d3a952e270bdba4b8f19 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Tue, 7 Mar 2023 21:02:46 -0800 +Subject: [PATCH] imx8mq-phanbell.dts: Enable Coral specifics e.g. PCIE + +Signed-off-by: Khem Raj +--- + .../boot/dts/freescale/imx8mq-phanbell.dts | 155 +++++++++++++++++- + 1 file changed, 154 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts b/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts +index a3b9d615a3b4..5ce4fc21443e 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts ++++ b/arch/arm64/boot/dts/freescale/imx8mq-phanbell.dts +@@ -21,6 +21,10 @@ memory@40000000 { + reg = <0x00000000 0x40000000 0 0x40000000>; + }; + ++ busfreq { ++ status = "disabled"; ++ }; ++ + pmic_osc: clock-pmic { + compatible = "fixed-clock"; + #clock-cells = <0>; +@@ -46,6 +50,12 @@ fan: gpio-fan { + pinctrl-0 = <&pinctrl_gpio_fan>; + status = "okay"; + }; ++ ++ pcie1_refclk: pcie1-refclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <100000000>; ++ }; + }; + + &A53_0 { +@@ -111,6 +121,17 @@ map4 { + }; + }; + ++&gpio3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_wifi_reset>; ++ ++ wl-reg-on { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ }; ++}; ++ + &i2c1 { + clock-frequency = <400000>; + pinctrl-names = "default"; +@@ -126,7 +147,7 @@ pmic: pmic@4b { + clocks = <&pmic_osc>; + clock-output-names = "pmic_clk"; + interrupt-parent = <&gpio1>; +- interrupts = <3 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <3 GPIO_ACTIVE_LOW>; + + regulators { + buck1: BUCK1 { +@@ -259,6 +280,70 @@ ldo7: LDO7 { + }; + }; + ++&i2c2 { ++ clock-frequency = <100000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_i2c2>; ++ status = "okay"; ++}; ++ ++&i2c3 { ++ clock-frequency = <100000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_i2c3>; ++ status = "okay"; ++}; ++ ++&pcie0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_pcie0>; ++ reset-gpio = <&gpio3 10 GPIO_ACTIVE_LOW>; ++ clocks = <&clk IMX8MQ_CLK_PCIE1_ROOT>, ++ <&clk IMX8MQ_CLK_PCIE1_AUX>, ++ <&clk IMX8MQ_CLK_PCIE1_PHY>, ++ <&clk IMX8MQ_CLK_DUMMY>; ++ clock-names = "pcie", "pcie_aux", "pcie_phy", "pcie_bus"; ++ fsl,max-link-speed = <1>; ++ ext_osc = <0>; ++ hard-wired = <1>; ++ status = "okay"; ++}; ++ ++&pcie1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_pcie1>; ++ reset-gpio = <&gpio3 18 GPIO_ACTIVE_LOW>; ++ clocks = <&clk IMX8MQ_CLK_PCIE2_ROOT>, ++ <&clk IMX8MQ_CLK_PCIE2_AUX>, ++ <&clk IMX8MQ_CLK_PCIE2_PHY>, ++ <&pcie1_refclk>; ++ clock-names = "pcie", "pcie_aux", "pcie_phy", "pcie_bus"; ++ ext_osc = <1>; ++ hard-wired = <1>; ++ status = "okay"; ++}; ++ ++&ecspi1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_ecspi1 &pinctrl_ecspi1_cs>; ++ cs-gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>, ++ <&gpio3 2 GPIO_ACTIVE_HIGH>; ++ num-cs = <2>; ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "rohm,dh2228fv"; ++ spi-max-frequency = <20000000>; ++ reg = <0>; ++ }; ++ ++ spidev@1 { ++ compatible = "rohm,dh2228fv"; ++ spi-max-frequency = <20000000>; ++ reg = <1>; ++ }; ++}; ++ + &fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec1>; +@@ -333,6 +418,54 @@ &wdog1 { + }; + + &iomuxc { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_hog>; ++ ++ pinctrl_hog: hoggrp { ++ fsl,pins = < ++ MX8MQ_IOMUXC_GPIO1_IO00_ANAMIX_REF_CLK_32K 0x05 ++ MX8MQ_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x19 ++ MX8MQ_IOMUXC_GPIO1_IO07_GPIO1_IO7 0x19 ++ MX8MQ_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x19 ++ MX8MQ_IOMUXC_NAND_DATA03_GPIO3_IO9 0x19 ++ MX8MQ_IOMUXC_NAND_DATA07_GPIO3_IO13 0x19 ++ MX8MQ_IOMUXC_NAND_READY_B_GPIO3_IO16 0x19 ++ MX8MQ_IOMUXC_NAND_WE_B_GPIO3_IO17 0x19 ++ MX8MQ_IOMUXC_ECSPI2_SCLK_GPIO5_IO10 0x19 ++ MX8MQ_IOMUXC_ECSPI2_MISO_GPIO5_IO12 0x19 ++ MX8MQ_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0x19 ++ >; ++ }; ++ ++ pinctrl_pcie0: pcie0grp { ++ fsl,pins = < ++ MX8MQ_IOMUXC_I2C4_SCL_PCIE1_CLKREQ_B 0x76 ++ MX8MQ_IOMUXC_NAND_DATA04_GPIO3_IO10 0x16 ++ >; ++ }; ++ ++ pinctrl_pcie1: pcie1grp { ++ fsl,pins = < ++ MX8MQ_IOMUXC_I2C4_SDA_PCIE2_CLKREQ_B 0x76 ++ MX8MQ_IOMUXC_NAND_WP_B_GPIO3_IO18 0x19 ++ >; ++ }; ++ ++ pinctrl_ecspi1: ecspi1grp { ++ fsl,pins = < ++ MX8MQ_IOMUXC_ECSPI1_SCLK_ECSPI1_SCLK 0x82 ++ MX8MQ_IOMUXC_ECSPI1_MOSI_ECSPI1_MOSI 0x82 ++ MX8MQ_IOMUXC_ECSPI1_MISO_ECSPI1_MISO 0x82 ++ >; ++ }; ++ ++ pinctrl_ecspi1_cs: ecspi1_cs_grp { ++ fsl,pins = < ++ MX8MQ_IOMUXC_ECSPI1_SS0_GPIO5_IO9 0x82 ++ MX8MQ_IOMUXC_NAND_CE1_B_GPIO3_IO2 0x82 ++ >; ++ }; ++ + pinctrl_fec1: fec1grp { + fsl,pins = < + MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3 +@@ -366,6 +499,20 @@ MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f + >; + }; + ++ pinctrl_i2c2: i2c2grp { ++ fsl,pins = < ++ MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL 0x4000007f ++ MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA 0x4000007f ++ >; ++ }; ++ ++ pinctrl_i2c3: i2c3grp { ++ fsl,pins = < ++ MX8MQ_IOMUXC_I2C3_SCL_I2C3_SCL 0x4000007f ++ MX8MQ_IOMUXC_I2C3_SDA_I2C3_SDA 0x4000007f ++ >; ++ }; ++ + pinctrl_pmic: pmicirqgrp { + fsl,pins = < + MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41 +@@ -478,4 +625,10 @@ pinctrl_wdog: wdoggrp { + MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6 + >; + }; ++ ++ pinctrl_wifi_reset: wifiresetgrp { ++ fsl,pins = < ++ MX8MQ_IOMUXC_NAND_DATA05_GPIO3_IO11 0x16 ++ >; ++ }; + }; +-- +2.39.2 + diff --git a/projects/NXP/devices/iMX8/patches/linux/0012-MLK-24521-drm-bridge-hdmi-Prevent-the-driver-from-re.patch b/projects/NXP/devices/iMX8/patches/linux/0012-MLK-24521-drm-bridge-hdmi-Prevent-the-driver-from-re.patch deleted file mode 100644 index 00199349fd..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0012-MLK-24521-drm-bridge-hdmi-Prevent-the-driver-from-re.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 4cb4fe3262fbbf6b31731b6b076698bcf951b9a1 Mon Sep 17 00:00:00 2001 -From: "Oliver F. Brown" -Date: Fri, 24 Jul 2020 14:28:05 -0500 -Subject: [PATCH 12/49] MLK-24521: drm: bridge: hdmi: Prevent the driver from - rejecting VIC 0 modes - -iMX8QM can support the non CEA modes, iMX8M cannot support non CEA modes. -So driver should allow non CEA modes for iMX8QM. - -Signed-off-by: Oliver F. Brown -Reviewed-by: Liu Ying ---- - drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index 442df6284c49..a8fa559de9e9 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -364,6 +364,7 @@ cdns_hdmi_bridge_mode_valid(struct drm_bridge *bridge, - { - struct cdns_mhdp_device *mhdp = bridge->driver_private; - enum drm_mode_status mode_status = MODE_OK; -+ u32 vic; - int ret; - - /* We don't support double-clocked and Interlaced modes */ -@@ -379,6 +380,13 @@ cdns_hdmi_bridge_mode_valid(struct drm_bridge *bridge, - if (mode->hdisplay > 5120 || mode->vdisplay > 2160) - return MODE_BAD_HVALUE; - -+ /* imx8mq-hdmi does not support non CEA modes */ -+ if (!strncmp("imx8mq-hdmi", mhdp->plat_data->plat_name, 11)) { -+ vic = drm_match_cea_mode(mode); -+ if (vic == 0) -+ return MODE_BAD; -+ } -+ - mhdp->valid_mode = mode; - ret = cdns_mhdp_plat_call(mhdp, phy_video_valid); - if (ret == false) --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0013-MLK-23642-1-drm-bridge-cadence-support-HBR-and-6-cha.patch b/projects/NXP/devices/iMX8/patches/linux/0013-MLK-23642-1-drm-bridge-cadence-support-HBR-and-6-cha.patch deleted file mode 100644 index 7c97e9aabe..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0013-MLK-23642-1-drm-bridge-cadence-support-HBR-and-6-cha.patch +++ /dev/null @@ -1,116 +0,0 @@ -From cd7804fc3777e0b53d69d34058fee39accc72072 Mon Sep 17 00:00:00 2001 -From: Shengjiu Wang -Date: Wed, 29 Apr 2020 17:34:07 +0800 -Subject: [PATCH 13/49] MLK-23642-1: drm: bridge: cadence: support HBR and 6 - channel - -Support HBR and 6 channel. - -For HBR, it only support compressed bitstream, sample rate -is 192kHz, and 8 channels. - -Signed-off-by: Shengjiu Wang -Reviewed-by: Viorel Suman ---- - .../gpu/drm/bridge/cadence/cdns-mhdp-audio.c | 33 ++++++++++++++----- - include/drm/bridge/cdns-mhdp.h | 1 + - 2 files changed, 26 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c -index 86174fb633bc..fa1dcf781539 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c -@@ -72,6 +72,8 @@ static void hdmi_audio_avi_set(struct cdns_mhdp_device *mhdp, - frame.channel_allocation = 0; - else if (channels == 4) - frame.channel_allocation = 0x3; -+ else if (channels == 6) -+ frame.channel_allocation = 0xB; - else if (channels == 8) - frame.channel_allocation = 0x13; - -@@ -143,26 +145,38 @@ static void cdns_mhdp_audio_config_i2s(struct cdns_mhdp_device *mhdp, - { - int sub_pckt_num = 1, i2s_port_en_val = 0xf, i; - int idx = select_N_index(mhdp->mode.clock); -+ int numofchannels = audio->channels; - u32 val, ncts; -+ u32 disable_port3 = 0; -+ u32 audio_type = 0x2; /* L-PCM */ -+ u32 transmission_type = 0; /* not required for L-PCM */ - -- if (audio->channels == 2) { -+ if (numofchannels == 2) { - if (mhdp->dp.num_lanes == 1) - sub_pckt_num = 2; - else - sub_pckt_num = 4; - - i2s_port_en_val = 1; -- } else if (audio->channels == 4) { -+ } else if (numofchannels == 4) { - i2s_port_en_val = 3; -+ } else if (numofchannels == 6) { -+ numofchannels = 8; -+ disable_port3 = 1; -+ } else if ((numofchannels == 8) && (audio->non_pcm)) { -+ audio_type = 0x9; /* HBR packet type */ -+ transmission_type = 0x9; /* HBR packet type */ - } - - cdns_mhdp_bus_write(0x0, mhdp, SPDIF_CTRL_ADDR); - -- cdns_mhdp_bus_write(SYNC_WR_TO_CH_ZERO, mhdp, FIFO_CNTL); -+ val = SYNC_WR_TO_CH_ZERO; -+ val |= disable_port3 << 4; -+ cdns_mhdp_bus_write(val, mhdp, FIFO_CNTL); - -- val = MAX_NUM_CH(audio->channels); -- val |= NUM_OF_I2S_PORTS(audio->channels); -- val |= AUDIO_TYPE_LPCM; -+ val = MAX_NUM_CH(numofchannels); -+ val |= NUM_OF_I2S_PORTS(numofchannels); -+ val |= audio_type << 7; - val |= CFG_SUB_PCKT_NUM(sub_pckt_num); - cdns_mhdp_bus_write(val, mhdp, SMPL2PKT_CNFG); - -@@ -173,12 +187,13 @@ static void cdns_mhdp_audio_config_i2s(struct cdns_mhdp_device *mhdp, - else - val = 2 << 9; - -- val |= AUDIO_CH_NUM(audio->channels); -+ val |= AUDIO_CH_NUM(numofchannels); - val |= I2S_DEC_PORT_EN(i2s_port_en_val); - val |= TRANS_SMPL_WIDTH_32; -+ val |= transmission_type << 13; - cdns_mhdp_bus_write(val, mhdp, AUDIO_SRC_CNFG); - -- for (i = 0; i < (audio->channels + 1) / 2; i++) { -+ for (i = 0; i < (numofchannels + 1) / 2; i++) { - if (audio->sample_width == 16) - val = (0x02 << 8) | (0x02 << 20); - else if (audio->sample_width == 24) -@@ -323,6 +338,8 @@ static int audio_hw_params(struct device *dev, void *data, - goto out; - } - -+ audio.non_pcm = params->iec.status[0] & IEC958_AES0_NONAUDIO; -+ - ret = cdns_mhdp_audio_config(mhdp, &audio); - if (!ret) - mhdp->audio_info = audio; -diff --git a/include/drm/bridge/cdns-mhdp.h b/include/drm/bridge/cdns-mhdp.h -index 4dc6e428b5f7..1f8fd024cdfa 100644 ---- a/include/drm/bridge/cdns-mhdp.h -+++ b/include/drm/bridge/cdns-mhdp.h -@@ -564,6 +564,7 @@ struct audio_info { - int channels; - int sample_width; - int connector_type; -+ bool non_pcm; - }; - - enum vic_pxl_encoding_format { --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0013-PCI-imx-Use-the-external-clock-as-REF_CLK-when-neede.patch b/projects/NXP/devices/iMX8/patches/linux/0013-PCI-imx-Use-the-external-clock-as-REF_CLK-when-neede.patch new file mode 100644 index 0000000000..e81679e278 --- /dev/null +++ b/projects/NXP/devices/iMX8/patches/linux/0013-PCI-imx-Use-the-external-clock-as-REF_CLK-when-neede.patch @@ -0,0 +1,41 @@ +From dd3d8c2c0b77eb742b288cf83e4849f87c8db5c6 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Tue, 7 Mar 2023 21:19:36 -0800 +Subject: [PATCH 3/4] PCI: imx: Use the external clock as REF_CLK when needed + for i.MX8MQ + +Do not use the external clock when the internal PLL is used as PCIe +REF_CLK. + +Signed-off-by: Ryosuke Saito +Signed-off-by: Khem Raj +--- + drivers/pci/controller/dwc/pci-imx6.c | 15 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c +index 3a8350cad812..841af6f55c7d 100644 +--- a/drivers/pci/controller/dwc/pci-imx6.c ++++ b/drivers/pci/controller/dwc/pci-imx6.c +@@ -370,11 +370,13 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) + + static int imx8mq_pcie_init_phy(struct imx_pcie *imx_pcie) + { +- /* TODO: This code assumes external oscillator is being used */ +- regmap_update_bits(imx_pcie->iomuxc_gpr, +- imx_pcie_grp_offset(imx_pcie), +- IMX8MQ_GPR_PCIE_REF_USE_PAD, +- IMX8MQ_GPR_PCIE_REF_USE_PAD); ++ if (imx_pcie->ext_osc) { ++ /* Use the external oscillator as REF clock */ ++ regmap_update_bits(imx_pcie->iomuxc_gpr, ++ imx_pcie_grp_offset(imx_pcie), ++ IMX8MQ_GPR_PCIE_REF_USE_PAD, ++ IMX8MQ_GPR_PCIE_REF_USE_PAD); ++ } + /* + * Per the datasheet, the PCIE_VPH is suggested to be 1.8V. If the + * PCIE_VPH is supplied by 3.3V, the VREG_BYPASS should be cleared +-- +2.39.2 + diff --git a/projects/NXP/devices/iMX8/patches/linux/0014-MLK-24611-2-drm-bridge-cdns-Add-callback-function-fo.patch b/projects/NXP/devices/iMX8/patches/linux/0014-MLK-24611-2-drm-bridge-cdns-Add-callback-function-fo.patch deleted file mode 100644 index 1b2c1413b0..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0014-MLK-24611-2-drm-bridge-cdns-Add-callback-function-fo.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 46bf1dc2ba34440e8f83b3f70e3e4d6b3f9e6183 Mon Sep 17 00:00:00 2001 -From: Shengjiu Wang -Date: Mon, 31 Aug 2020 14:50:29 +0800 -Subject: [PATCH 14/49] MLK-24611-2: drm: bridge: cdns: Add callback function - for plug/unplug event - -cdns-hdmi-core exports a function cdns_hdmi_set_plugged_cb so -platform device can register the callback - -implement hook_plugged_cb to register callback function for hdmi cable -plug/unplug event. - -Signed-off-by: Shengjiu Wang -Reviewed-by: Sandor Yu ---- - .../gpu/drm/bridge/cadence/cdns-hdmi-core.c | 41 +++++++++++++++++-- - .../gpu/drm/bridge/cadence/cdns-mhdp-audio.c | 10 +++++ - include/drm/bridge/cdns-mhdp.h | 6 +++ - 3 files changed, 54 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index a8fa559de9e9..5890da8aa1a1 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -225,11 +225,35 @@ void cdns_hdmi_mode_set(struct cdns_mhdp_device *mhdp) - } - } - -+static void handle_plugged_change(struct cdns_mhdp_device *mhdp, bool plugged) -+{ -+ if (mhdp->plugged_cb && mhdp->codec_dev) -+ mhdp->plugged_cb(mhdp->codec_dev, plugged); -+} -+ -+int cdns_hdmi_set_plugged_cb(struct cdns_mhdp_device *mhdp, -+ hdmi_codec_plugged_cb fn, -+ struct device *codec_dev) -+{ -+ bool plugged; -+ -+ mutex_lock(&mhdp->lock); -+ mhdp->plugged_cb = fn; -+ mhdp->codec_dev = codec_dev; -+ plugged = mhdp->last_connector_result == connector_status_connected; -+ handle_plugged_change(mhdp, plugged); -+ mutex_unlock(&mhdp->lock); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(cdns_hdmi_set_plugged_cb); -+ - static enum drm_connector_status - cdns_hdmi_connector_detect(struct drm_connector *connector, bool force) - { - struct cdns_mhdp_device *mhdp = - container_of(connector, struct cdns_mhdp_device, connector.base); -+ enum drm_connector_status result; - - u8 hpd = 0xf; - -@@ -237,15 +261,25 @@ cdns_hdmi_connector_detect(struct drm_connector *connector, bool force) - - if (hpd == 1) - /* Cable Connected */ -- return connector_status_connected; -+ result = connector_status_connected; - else if (hpd == 0) - /* Cable Disconnedted */ -- return connector_status_disconnected; -+ result = connector_status_disconnected; - else { - /* Cable status unknown */ - DRM_INFO("Unknow cable status, hdp=%u\n", hpd); -- return connector_status_unknown; -+ result = connector_status_unknown; -+ } -+ -+ mutex_lock(&mhdp->lock); -+ if (result != mhdp->last_connector_result) { -+ handle_plugged_change(mhdp, -+ result == connector_status_connected); -+ mhdp->last_connector_result = result; - } -+ mutex_unlock(&mhdp->lock); -+ -+ return result; - } - - static int cdns_hdmi_connector_get_modes(struct drm_connector *connector) -@@ -624,6 +658,7 @@ static int __cdns_hdmi_probe(struct platform_device *pdev, - #ifdef CONFIG_OF - mhdp->bridge.base.of_node = dev->of_node; - #endif -+ mhdp->last_connector_result = connector_status_disconnected; - - memset(&pdevinfo, 0, sizeof(pdevinfo)); - pdevinfo.parent = dev; -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c -index fa1dcf781539..f4f3f9ca437c 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c -@@ -380,11 +380,21 @@ static int audio_get_eld(struct device *dev, void *data, - return 0; - } - -+static int audio_hook_plugged_cb(struct device *dev, void *data, -+ hdmi_codec_plugged_cb fn, -+ struct device *codec_dev) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ -+ return cdns_hdmi_set_plugged_cb(mhdp, fn, codec_dev); -+} -+ - static const struct hdmi_codec_ops audio_codec_ops = { - .hw_params = audio_hw_params, - .audio_shutdown = audio_shutdown, - .digital_mute = audio_digital_mute, - .get_eld = audio_get_eld, -+ .hook_plugged_cb = audio_hook_plugged_cb, - }; - - int cdns_mhdp_register_audio_driver(struct device *dev) -diff --git a/include/drm/bridge/cdns-mhdp.h b/include/drm/bridge/cdns-mhdp.h -index 1f8fd024cdfa..6bfd82a3d9a2 100644 ---- a/include/drm/bridge/cdns-mhdp.h -+++ b/include/drm/bridge/cdns-mhdp.h -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #define ADDR_IMEM 0x10000 - #define ADDR_DMEM 0x20000 -@@ -714,6 +715,9 @@ struct cdns_mhdp_device { - }; - const struct cdns_plat_data *plat_data; - -+ hdmi_codec_plugged_cb plugged_cb; -+ struct device *codec_dev; -+ enum drm_connector_status last_connector_result; - }; - - u32 cdns_mhdp_bus_read(struct cdns_mhdp_device *mhdp, u32 offset); -@@ -796,6 +800,8 @@ void cdns_dp_remove(struct platform_device *pdev); - void cdns_dp_unbind(struct device *dev); - int cdns_dp_bind(struct platform_device *pdev, - struct drm_encoder *encoder, struct cdns_mhdp_device *mhdp); -+int cdns_hdmi_set_plugged_cb(struct cdns_mhdp_device *mhdp, hdmi_codec_plugged_cb fn, -+ struct device *codec_dev); - - /* CEC */ - #ifdef CONFIG_DRM_CDNS_HDMI_CEC --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0014-PCI-imx-Provide-a-clock-to-the-device-for-i.MX8MQ.patch b/projects/NXP/devices/iMX8/patches/linux/0014-PCI-imx-Provide-a-clock-to-the-device-for-i.MX8MQ.patch new file mode 100644 index 0000000000..a65dd7ae83 --- /dev/null +++ b/projects/NXP/devices/iMX8/patches/linux/0014-PCI-imx-Provide-a-clock-to-the-device-for-i.MX8MQ.patch @@ -0,0 +1,69 @@ +From 0845d9b5935ad8b3d450c2dfa62631c9c1df1bea Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Tue, 7 Mar 2023 21:21:57 -0800 +Subject: [PATCH 4/4] PCI: imx: Provide a clock to the device for i.MX8MQ + +When the internal PLL is configured as PCIe REF_CLK, we also have to +output a clock via CLK2_P/N pin to the connector/device to provide it. +Configure 100 MHz clock as its output. + +Signed-off-by: Ryosuke Saito +Signed-off-by: Khem Raj +--- + drivers/pci/controller/dwc/pci-imx6.c | 35 +++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c +index 841af6f55c7d..ac36c7035460 100644 +--- a/drivers/pci/controller/dwc/pci-imx6.c ++++ b/drivers/pci/controller/dwc/pci-imx6.c +@@ -43,6 +43,11 @@ struct imx6_pcie { + #define IMX8MQ_GPR_PCIE_CLK_REQ_OVERRIDE BIT(11) + #define IMX8MQ_GPR_PCIE_VREG_BYPASS BIT(12) + #define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE GENMASK(11, 8) ++#define IMX8MQ_ANA_PLLOUT_MONITOR_CFG_REG 0x74 ++#define IMX8MQ_ANA_PLLOUT_MONITOR_CLK_SEL_MASK GENMASK(3, 0) ++#define IMX8MQ_ANA_PLLOUT_MONITOR_CKE BIT(4) ++#define IMX8MQ_ANA_SCCG_PLLOUT_DIV_CFG_REG 0x7C ++#define IMX8MQ_ANA_SCCG_SYSPLLL1_DIV_MASK GENMASK(2, 0) + + #define IMX95_PCIE_PHY_GEN_CTRL 0x0 + #define IMX95_PCIE_REF_USE_PAD BIT(17) +@@ -370,6 +370,34 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) + imx_pcie_grp_offset(imx_pcie), + IMX8MQ_GPR_PCIE_REF_USE_PAD, + IMX8MQ_GPR_PCIE_REF_USE_PAD); ++ } else { ++ /* ++ * Use the internal PLL as REF clock and also ++ * provide a clock to the device. ++ */ ++ struct regmap *anatop = ++ syscon_regmap_lookup_by_compatible("fsl,imx8mq-anatop"); ++ ++ if (IS_ERR(anatop)) { ++ dev_err(imx_pcie->pci->dev, ++ "Couldn't configure the internal PLL as REF clock\n"); ++ } else { ++ /* Select SYSTEM_PLL1_CLK as the clock source */ ++ regmap_update_bits(anatop, IMX8MQ_ANA_PLLOUT_MONITOR_CFG_REG, ++ IMX8MQ_ANA_PLLOUT_MONITOR_CLK_SEL_MASK, 0xb); ++ ++ /* ++ * SYSTEM_PLL1_CLK is 800 MHz, so divided by 8 ++ * for generating 100 MHz as output. ++ */ ++ regmap_update_bits(anatop, IMX8MQ_ANA_SCCG_PLLOUT_DIV_CFG_REG, ++ IMX8MQ_ANA_SCCG_SYSPLLL1_DIV_MASK, 0x7); ++ ++ /* Enable CLK2_P/N clock to provide it to the device */ ++ regmap_update_bits(anatop, IMX8MQ_ANA_PLLOUT_MONITOR_CFG_REG, ++ IMX8MQ_ANA_PLLOUT_MONITOR_CKE, ++ IMX8MQ_ANA_PLLOUT_MONITOR_CKE); ++ } + } + /* + * Regarding the datasheet, the PCIE_VPH is suggested to be 1.8V. If the PCIE_VPH is +-- +2.39.2 + diff --git a/projects/NXP/devices/iMX8/patches/linux/0015-gpu-drm-dridge-hdp-audio-change-to-mute_stream.patch b/projects/NXP/devices/iMX8/patches/linux/0015-gpu-drm-dridge-hdp-audio-change-to-mute_stream.patch deleted file mode 100644 index 9745c16806..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0015-gpu-drm-dridge-hdp-audio-change-to-mute_stream.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 1b0a179061890c0a2f6748426f03e8cd2176d3e2 Mon Sep 17 00:00:00 2001 -From: Dong Aisheng -Date: Wed, 5 Aug 2020 21:31:04 +0800 -Subject: [PATCH 15/49] gpu: drm: dridge: hdp-audio: change to mute_stream - -To cope with upstream API change: -e2978c45e5ed ("ASoC: soc-dai: remove .digital_mute") - -Signed-off-by: Dong Aisheng ---- - drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c -index f4f3f9ca437c..85f526175439 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c -@@ -358,8 +358,8 @@ static void audio_shutdown(struct device *dev, void *data) - mhdp->audio_info.format = AFMT_UNUSED; - } - --static int audio_digital_mute(struct device *dev, void *data, -- bool enable) -+static int audio_mute_stream(struct device *dev, void *data, -+ bool enable, int direction) - { - struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); - int ret; -@@ -392,9 +392,10 @@ static int audio_hook_plugged_cb(struct device *dev, void *data, - static const struct hdmi_codec_ops audio_codec_ops = { - .hw_params = audio_hw_params, - .audio_shutdown = audio_shutdown, -- .digital_mute = audio_digital_mute, -+ .mute_stream = audio_mute_stream, - .get_eld = audio_get_eld, - .hook_plugged_cb = audio_hook_plugged_cb, -+ .no_capture_mute = 1, - }; - - int cdns_mhdp_register_audio_driver(struct device *dev) --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0016-LF-2744-drm-cdns-reset-force_mode_set-flag-in-atomic.patch b/projects/NXP/devices/iMX8/patches/linux/0016-LF-2744-drm-cdns-reset-force_mode_set-flag-in-atomic.patch deleted file mode 100644 index 6be40ad2f3..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0016-LF-2744-drm-cdns-reset-force_mode_set-flag-in-atomic.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 4a406e182a709718a769c37d33530ed2e6b23b39 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Tue, 17 Nov 2020 15:47:36 +0800 -Subject: [PATCH 16/49] LF-2744: drm: cdns: reset force_mode_set flag in - atomic_check - -Reset force_mode_set flag in atomic_check function -to avoid set mode_changed flag multi times when cable plugin. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index 5890da8aa1a1..e796c2c0e895 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -1,7 +1,7 @@ - /* - * Cadence High-Definition Multimedia Interface (HDMI) driver - * -- * Copyright (C) 2019 NXP Semiconductor, Inc. -+ * Copyright (C) 2019-2020 NXP Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -445,8 +445,6 @@ static void cdns_hdmi_bridge_mode_set(struct drm_bridge *bridge, - mutex_lock(&mhdp->lock); - cdns_hdmi_mode_set(mhdp); - mutex_unlock(&mhdp->lock); -- /* reset force mode set flag */ -- mhdp->force_mode_set = false; - } - - bool cdns_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0017-MLK-24081-03-drm-bridge-cdns-cec-support-hdmi-rx-cec.patch b/projects/NXP/devices/iMX8/patches/linux/0017-MLK-24081-03-drm-bridge-cdns-cec-support-hdmi-rx-cec.patch deleted file mode 100644 index 69014b43b7..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0017-MLK-24081-03-drm-bridge-cdns-cec-support-hdmi-rx-cec.patch +++ /dev/null @@ -1,271 +0,0 @@ -From f7f5ec54b815df2c9a92f0fd6edea4f5d0700937 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Mon, 16 Nov 2020 10:56:44 +0800 -Subject: [PATCH 17/49] MLK-24081-03: drm: bridge: cdns-cec: support hdmi rx - cec - -Create struct cdns_mhdp_cec and cec specific bus_read/write function. -CEC driver could be reuse by hdmi rx. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/bridge/cadence/Kconfig | 1 - - .../gpu/drm/bridge/cadence/cdns-hdmi-core.c | 18 ++++- - .../gpu/drm/bridge/cadence/cdns-mhdp-cec.c | 66 +++++++++++++------ - .../gpu/drm/bridge/cadence/cdns-mhdp-common.c | 6 -- - include/drm/bridge/cdns-mhdp.h | 19 +++--- - 5 files changed, 72 insertions(+), 38 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig -index bb1865b15aca..c271ab24a99a 100644 ---- a/drivers/gpu/drm/bridge/cadence/Kconfig -+++ b/drivers/gpu/drm/bridge/cadence/Kconfig -@@ -45,6 +45,5 @@ config DRM_CDNS_AUDIO - - config DRM_CDNS_HDMI_CEC - tristate "Cadence MHDP HDMI CEC driver" -- depends on DRM_CDNS_HDMI - select CEC_CORE - select CEC_NOTIFIER -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index e796c2c0e895..84c175997740 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -569,6 +569,19 @@ static void cdns_hdmi_parse_dt(struct cdns_mhdp_device *mhdp) - dev_info(mhdp->dev, "lane-mapping 0x%02x\n", mhdp->lane_mapping); - } - -+#ifdef CONFIG_DRM_CDNS_HDMI_CEC -+static void cdns_mhdp_cec_init(struct cdns_mhdp_device *mhdp) -+{ -+ struct cdns_mhdp_cec *cec = &mhdp->hdmi.cec; -+ -+ cec->dev = mhdp->dev; -+ cec->iolock = &mhdp->iolock; -+ cec->regs_base = mhdp->regs_base; -+ cec->regs_sec = mhdp->regs_sec; -+ cec->bus_type = mhdp->bus_type; -+} -+#endif -+ - static int __cdns_hdmi_probe(struct platform_device *pdev, - struct cdns_mhdp_device *mhdp) - { -@@ -669,7 +682,8 @@ static int __cdns_hdmi_probe(struct platform_device *pdev, - - /* register cec driver */ - #ifdef CONFIG_DRM_CDNS_HDMI_CEC -- cdns_mhdp_register_cec_driver(dev); -+ cdns_mhdp_cec_init(mhdp); -+ cdns_mhdp_register_cec_driver(&mhdp->hdmi.cec); - #endif - - return 0; -@@ -679,7 +693,7 @@ static void __cdns_hdmi_remove(struct cdns_mhdp_device *mhdp) - { - /* unregister cec driver */ - #ifdef CONFIG_DRM_CDNS_HDMI_CEC -- cdns_mhdp_unregister_cec_driver(mhdp->dev); -+ cdns_mhdp_unregister_cec_driver(&mhdp->hdmi.cec); - #endif - cdns_mhdp_unregister_audio_driver(mhdp->dev); - } -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c -index 029ad761606a..25cf9e91e64f 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c -@@ -1,5 +1,5 @@ - /* -- * Copyright 2019 NXP -+ * Copyright 2019-2020 NXP - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -74,16 +74,49 @@ enum { - - static u32 mhdp_cec_read(struct cdns_mhdp_cec *cec, u32 offset) - { -- struct cdns_mhdp_device *mhdp = -- container_of(cec, struct cdns_mhdp_device, hdmi.cec); -- return cdns_mhdp_bus_read(mhdp, offset); -+ u32 val; -+ -+ mutex_lock(cec->iolock); -+ -+ if (cec->bus_type == BUS_TYPE_LOW4K_HDMI_RX) { -+ /* Remap address to low 4K HDMI RX */ -+ writel(offset >> 12, cec->regs_sec + 4); -+ val = readl((offset & 0xfff) + cec->regs_base); -+ } else if (cec->bus_type == BUS_TYPE_LOW4K_APB) { -+ /* Remap address to low 4K memory */ -+ writel(offset >> 12, cec->regs_sec + 8); -+ val = readl((offset & 0xfff) + cec->regs_base); -+ } else -+ val = readl(cec->regs_base + offset); -+ -+ mutex_unlock(cec->iolock); -+ -+ return val; - } - - static void mhdp_cec_write(struct cdns_mhdp_cec *cec, u32 offset, u32 val) - { -- struct cdns_mhdp_device *mhdp = -- container_of(cec, struct cdns_mhdp_device, hdmi.cec); -- cdns_mhdp_bus_write(val, mhdp, offset); -+ mutex_lock(cec->iolock); -+ -+ if (cec->bus_type == BUS_TYPE_LOW4K_HDMI_RX) { -+ /* Remap address to low 4K SAPB bus */ -+ writel(offset >> 12, cec->regs_sec + 4); -+ writel(val, (offset & 0xfff) + cec->regs_base); -+ } else if (cec->bus_type == BUS_TYPE_LOW4K_APB) { -+ /* Remap address to low 4K memory */ -+ writel(offset >> 12, cec->regs_sec + 8); -+ writel(val, (offset & 0xfff) + cec->regs_base); -+ } else if (cec->bus_type == BUS_TYPE_NORMAL_SAPB) -+ writel(val, cec->regs_sec + offset); -+ else -+ writel(val, cec->regs_base + offset); -+ -+ mutex_unlock(cec->iolock); -+} -+ -+static u32 mhdp_get_fw_clk(struct cdns_mhdp_cec *cec) -+{ -+ return mhdp_cec_read(cec, SW_CLK_H); - } - - static void mhdp_cec_clear_rx_buffer(struct cdns_mhdp_cec *cec) -@@ -94,12 +127,10 @@ static void mhdp_cec_clear_rx_buffer(struct cdns_mhdp_cec *cec) - - static void mhdp_cec_set_divider(struct cdns_mhdp_cec *cec) - { -- struct cdns_mhdp_device *mhdp = -- container_of(cec, struct cdns_mhdp_device, hdmi.cec); - u32 clk_div; - - /* Set clock divider */ -- clk_div = cdns_mhdp_get_fw_clk(mhdp) * 10; -+ clk_div = mhdp_get_fw_clk(cec) * 10; - - mhdp_cec_write(cec, CLK_DIV_MSB, - (clk_div >> 8) & 0xFF); -@@ -291,10 +322,8 @@ static const struct cec_adap_ops cdns_mhdp_cec_adap_ops = { - .adap_transmit = mhdp_cec_adap_transmit, - }; - --int cdns_mhdp_register_cec_driver(struct device *dev) -+int cdns_mhdp_register_cec_driver(struct cdns_mhdp_cec *cec) - { -- struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -- struct cdns_mhdp_cec *cec = &mhdp->hdmi.cec; - int ret; - - cec->adap = cec_allocate_adapter(&cdns_mhdp_cec_adap_ops, cec, -@@ -305,29 +334,24 @@ int cdns_mhdp_register_cec_driver(struct device *dev) - ret = PTR_ERR_OR_ZERO(cec->adap); - if (ret) - return ret; -- ret = cec_register_adapter(cec->adap, dev); -+ ret = cec_register_adapter(cec->adap, cec->dev); - if (ret) { - cec_delete_adapter(cec->adap); - return ret; - } - -- cec->dev = dev; -- - cec->cec_worker = kthread_create(mhdp_cec_poll_worker, cec, "cdns-mhdp-cec"); - if (IS_ERR(cec->cec_worker)) - dev_err(cec->dev, "failed create hdp cec thread\n"); - - wake_up_process(cec->cec_worker); - -- dev_dbg(dev, "CEC successfuly probed\n"); -+ dev_dbg(cec->dev, "CEC successfuly probed\n"); - return 0; - } - --int cdns_mhdp_unregister_cec_driver(struct device *dev) -+int cdns_mhdp_unregister_cec_driver(struct cdns_mhdp_cec *cec) - { -- struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -- struct cdns_mhdp_cec *cec = &mhdp->hdmi.cec; -- - if (cec->cec_worker) { - kthread_stop(cec->cec_worker); - cec->cec_worker = NULL; -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -index 2043016f176b..ff37cc4e57e6 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -@@ -99,12 +99,6 @@ void cdns_mhdp_bus_write(u32 val, struct cdns_mhdp_device *mhdp, u32 offset) - } - EXPORT_SYMBOL(cdns_mhdp_bus_write); - --u32 cdns_mhdp_get_fw_clk(struct cdns_mhdp_device *mhdp) --{ -- return cdns_mhdp_bus_read(mhdp, SW_CLK_H); --} --EXPORT_SYMBOL(cdns_mhdp_get_fw_clk); -- - void cdns_mhdp_set_fw_clk(struct cdns_mhdp_device *mhdp, unsigned long clk) - { - cdns_mhdp_bus_write(clk / 1000000, mhdp, SW_CLK_H); -diff --git a/include/drm/bridge/cdns-mhdp.h b/include/drm/bridge/cdns-mhdp.h -index 6bfd82a3d9a2..338fa55b8bdf 100644 ---- a/include/drm/bridge/cdns-mhdp.h -+++ b/include/drm/bridge/cdns-mhdp.h -@@ -509,6 +509,7 @@ enum { - BUS_TYPE_NORMAL_SAPB = 1, - BUS_TYPE_LOW4K_APB = 2, - BUS_TYPE_LOW4K_SAPB = 3, -+ BUS_TYPE_LOW4K_HDMI_RX = 4, - }; - - enum voltage_swing_level { -@@ -623,12 +624,15 @@ struct cdns_mhdp_connector { - }; - - struct cdns_mhdp_cec { -- struct cec_adapter *adap; -- struct device *dev; -- struct mutex lock; -+ struct cec_adapter *adap; -+ struct device *dev; -+ struct mutex *iolock; -+ void __iomem *regs_base; -+ void __iomem *regs_sec; -+ int bus_type; - -- struct cec_msg msg; -- struct task_struct *cec_worker; -+ struct cec_msg msg; -+ struct task_struct *cec_worker; - }; - - struct cdns_plat_data { -@@ -724,7 +728,6 @@ u32 cdns_mhdp_bus_read(struct cdns_mhdp_device *mhdp, u32 offset); - void cdns_mhdp_bus_write(u32 val, struct cdns_mhdp_device *mhdp, u32 offset); - void cdns_mhdp_clock_reset(struct cdns_mhdp_device *mhdp); - void cdns_mhdp_set_fw_clk(struct cdns_mhdp_device *mhdp, unsigned long clk); --u32 cdns_mhdp_get_fw_clk(struct cdns_mhdp_device *mhdp); - int cdns_mhdp_load_firmware(struct cdns_mhdp_device *mhdp, const u32 *i_mem, - u32 i_size, const u32 *d_mem, u32 d_size); - int cdns_mhdp_set_firmware_active(struct cdns_mhdp_device *mhdp, bool enable); -@@ -805,8 +808,8 @@ int cdns_hdmi_set_plugged_cb(struct cdns_mhdp_device *mhdp, hdmi_codec_plugged_c - - /* CEC */ - #ifdef CONFIG_DRM_CDNS_HDMI_CEC --int cdns_mhdp_register_cec_driver(struct device *dev); --int cdns_mhdp_unregister_cec_driver(struct device *dev); -+int cdns_mhdp_register_cec_driver(struct cdns_mhdp_cec *cec); -+int cdns_mhdp_unregister_cec_driver(struct cdns_mhdp_cec *cec); - #endif - - #endif /* CDNS_MHDP_H_ */ --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0018-MLK-25199-3-drm-bridge-mhdp_common-add-apb-config-fu.patch b/projects/NXP/devices/iMX8/patches/linux/0018-MLK-25199-3-drm-bridge-mhdp_common-add-apb-config-fu.patch deleted file mode 100644 index 100881ce2a..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0018-MLK-25199-3-drm-bridge-mhdp_common-add-apb-config-fu.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 0021b4b1afc0d88c013e2484009004b19bc2ece4 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Wed, 30 Dec 2020 16:04:20 +0800 -Subject: [PATCH 18/49] MLK-25199-3: drm: bridge: mhdp_common: add apb config - function - -Add apb config function, move mhdp poll function -to mhdp head file, they will be used by hdcp driver. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - .../gpu/drm/bridge/cadence/cdns-mhdp-common.c | 54 ++++++++++--------- - drivers/gpu/drm/bridge/cadence/cdns-mhdp.h | 25 ++++++++- - 2 files changed, 54 insertions(+), 25 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -index ff37cc4e57e6..2a8ab0872f25 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -@@ -27,31 +27,10 @@ - #include - #include - -+#include "cdns-mhdp.h" -+ - #define CDNS_DP_SPDIF_CLK 200000000 - #define FW_ALIVE_TIMEOUT_US 1000000 --#define MAILBOX_RETRY_US 1000 --#define MAILBOX_TIMEOUT_US 5000000 -- --#define mhdp_readx_poll_timeout(op, addr, offset, val, cond, sleep_us, timeout_us) \ --({ \ -- u64 __timeout_us = (timeout_us); \ -- unsigned long __sleep_us = (sleep_us); \ -- ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ -- might_sleep_if((__sleep_us) != 0); \ -- for (;;) { \ -- (val) = op(addr, offset); \ -- if (cond) \ -- break; \ -- if (__timeout_us && \ -- ktime_compare(ktime_get(), __timeout) > 0) { \ -- (val) = op(addr, offset); \ -- break; \ -- } \ -- if (__sleep_us) \ -- usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ -- } \ -- (cond) ? 0 : -ETIMEDOUT; \ --}) - - u32 cdns_mhdp_bus_read(struct cdns_mhdp_device *mhdp, u32 offset) - { -@@ -174,7 +153,7 @@ bool cdns_mhdp_check_alive(struct cdns_mhdp_device *mhdp) - } - EXPORT_SYMBOL(cdns_mhdp_check_alive); - --static int mhdp_mailbox_read(struct cdns_mhdp_device *mhdp) -+int mhdp_mailbox_read(struct cdns_mhdp_device *mhdp) - { - int val, ret; - -@@ -432,6 +411,33 @@ int cdns_mhdp_set_firmware_active(struct cdns_mhdp_device *mhdp, bool enable) - } - EXPORT_SYMBOL(cdns_mhdp_set_firmware_active); - -+int cdns_mhdp_apb_conf(struct cdns_mhdp_device *mhdp, u8 sel) -+{ -+ u8 status; -+ int ret; -+ -+ ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_GENERAL, GENERAL_BUS_SETTINGS, -+ sizeof(sel), &sel); -+ if (ret) -+ goto err_apb_conf; -+ -+ ret = cdns_mhdp_mailbox_validate_receive(mhdp, MB_MODULE_ID_GENERAL, -+ GENERAL_BUS_SETTINGS, sizeof(status)); -+ if (ret) -+ goto err_apb_conf; -+ -+ ret = cdns_mhdp_mailbox_read_receive(mhdp, &status, sizeof(status)); -+ if (ret) -+ goto err_apb_conf; -+ -+ return status; -+ -+err_apb_conf: -+ DRM_ERROR("apb conf failed: %d\n", ret); -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_apb_conf); -+ - int cdns_mhdp_set_host_cap(struct cdns_mhdp_device *mhdp) - { - u8 msg[8]; -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp.h -index 399c3f6f86ad..8ad99eb8f86e 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp.h -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp.h -@@ -174,7 +174,6 @@ - #define CDNS_DP_MTPH_STATUS 0x226C - #define CDNS_DP_MTPH_ACT_STATUS BIT(0) - -- - #define CDNS_DPTX_GLOBAL 0x02300 - #define CDNS_DP_LANE_EN (CDNS_DPTX_GLOBAL + 0x00) - #define CDNS_DP_LANE_EN_LANES(x) GENMASK(x - 1, 0) -@@ -187,6 +186,30 @@ - - #define CDNS_MHDP_MAX_STREAMS 4 - -+#define MAILBOX_RETRY_US 1000 -+#define MAILBOX_TIMEOUT_US 5000000 -+ -+#define mhdp_readx_poll_timeout(op, addr, offset, val, cond, sleep_us, timeout_us) \ -+({ \ -+ u64 __timeout_us = (timeout_us); \ -+ unsigned long __sleep_us = (sleep_us); \ -+ ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \ -+ might_sleep_if((__sleep_us) != 0); \ -+ for (;;) { \ -+ (val) = op(addr, offset); \ -+ if (cond) \ -+ break; \ -+ if (__timeout_us && \ -+ ktime_compare(ktime_get(), __timeout) > 0) { \ -+ (val) = op(addr, offset); \ -+ break; \ -+ } \ -+ if (__sleep_us) \ -+ usleep_range((__sleep_us >> 2) + 1, __sleep_us); \ -+ } \ -+ (cond) ? 0 : -ETIMEDOUT; \ -+}) -+ - enum pixel_format { - PIXEL_FORMAT_RGB = 1, - PIXEL_FORMAT_YCBCR_444 = 2, --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0019-MLK-25199-4-drm-bridge-mhdp_hdmi-set-clear-avmute-bi.patch b/projects/NXP/devices/iMX8/patches/linux/0019-MLK-25199-4-drm-bridge-mhdp_hdmi-set-clear-avmute-bi.patch deleted file mode 100644 index 4da60d1acc..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0019-MLK-25199-4-drm-bridge-mhdp_hdmi-set-clear-avmute-bi.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 1793e95601a15f93e5d9e2846281f86eb19e8fe4 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Wed, 30 Dec 2020 16:05:29 +0800 -Subject: [PATCH 19/49] MLK-25199-4: drm: bridge: mhdp_hdmi: set clear avmute - bit - -Sync HDMI TX configuation with 4.14 hdmi driver. -Clear avmute bit must be set otherwise imx8qm hdcp not work. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdmi.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdmi.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdmi.c -index c37a7ac6af9b..3ff43f7fb0a6 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdmi.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdmi.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2019 NXP Semiconductor, Inc. -+ * Copyright (C) 2019-2021 NXP Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -205,7 +205,7 @@ int cdns_hdmi_ctrl_init(struct cdns_mhdp_device *mhdp, - - /* set hdmi mode and preemble mode data enable */ - val = F_HDMI_MODE(protocol) | F_HDMI2_PREAMBLE_EN(1) | F_DATA_EN(1) | -- F_HDMI2_CTRL_IL_MODE(1) | F_BCH_EN(1) | F_PIC_3D(0XF); -+ F_HDMI2_CTRL_IL_MODE(1) | F_BCH_EN(1) | F_PIC_3D(0XF) | F_CLEAR_AVMUTE(1); - ret = cdns_mhdp_reg_write(mhdp, HDTX_CONTROLLER, val); - - return ret; --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0020-MLK-25199-5-drm-bridge-mhdp_hdcp-add-HDMI-TX-HDCP-dr.patch b/projects/NXP/devices/iMX8/patches/linux/0020-MLK-25199-5-drm-bridge-mhdp_hdcp-add-HDMI-TX-HDCP-dr.patch deleted file mode 100644 index 47c75be296..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0020-MLK-25199-5-drm-bridge-mhdp_hdcp-add-HDMI-TX-HDCP-dr.patch +++ /dev/null @@ -1,2007 +0,0 @@ -From 9d940175bbffc82b5ec70b195312c6f32b35f51f Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Wed, 30 Dec 2020 16:07:41 +0800 -Subject: [PATCH 20/49] MLK-25199-5: drm: bridge: mhdp_hdcp: add HDMI TX HDCP - driver - -This patch adds an initial HDMI TX HDCP driver -for Cadence MHDP HDMI TX hardware. - -Both HDCP2.2 and HDCP1.4 are supported. - -HDCP function could be enabled by command: -modetest -w CONNECTOR_ID:"Content Protection":1 - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/bridge/cadence/Kconfig | 4 + - drivers/gpu/drm/bridge/cadence/Makefile | 1 + - .../gpu/drm/bridge/cadence/cdns-hdmi-core.c | 190 ++- - .../gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c | 1167 +++++++++++++++++ - .../gpu/drm/bridge/cadence/cdns-mhdp-hdcp.c | 300 +++++ - .../gpu/drm/bridge/cadence/cdns-mhdp-hdcp.h | 36 + - include/drm/bridge/cdns-mhdp.h | 92 +- - 7 files changed, 1776 insertions(+), 14 deletions(-) - create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c - create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.c - create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.h - -diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig -index c271ab24a99a..4c27836eb367 100644 ---- a/drivers/gpu/drm/bridge/cadence/Kconfig -+++ b/drivers/gpu/drm/bridge/cadence/Kconfig -@@ -43,6 +43,11 @@ config DRM_CDNS_AUDIO - tristate "Cadence MHDP Audio driver" - depends on DRM_CDNS_MHDP - -+config DRM_CDNS_HDMI_HDCP -+ tristate "Cadence MHDP HDMI HDCP driver" -+ depends on DRM_CDNS_HDMI -+ select DRM_DISPLAY_HDCP_HELPER -+ - config DRM_CDNS_HDMI_CEC - tristate "Cadence MHDP HDMI CEC driver" - select CEC_CORE -diff --git a/drivers/gpu/drm/bridge/cadence/Makefile b/drivers/gpu/drm/bridge/cadence/Makefile -index 618290870ba5..1b824252ae76 100644 ---- a/drivers/gpu/drm/bridge/cadence/Makefile -+++ b/drivers/gpu/drm/bridge/cadence/Makefile -@@ -8,6 +8,7 @@ cdns_mhdp_drmcore-y := cdns-mhdp-common.o cdns-mhdp-dp.o cdns-mhdp-hdmi.o - cdns_mhdp_drmcore-$(CONFIG_DRM_CDNS_HDMI) += cdns-hdmi-core.o - cdns_mhdp_drmcore-$(CONFIG_DRM_CDNS_DP) += cdns-dp-core.o - cdns_mhdp_drmcore-$(CONFIG_DRM_CDNS_AUDIO) += cdns-mhdp-audio.o -+cdns_mhdp_drmcore-$(CONFIG_DRM_CDNS_HDMI_HDCP) += cdns-mhdp-hdcp.o cdns-hdmi-hdcp.o - cdns_mhdp_drmcore-$(CONFIG_DRM_CDNS_HDMI_CEC) += cdns-mhdp-cec.o - - obj-$(CONFIG_DRM_CDNS_MHDP) += cdns_mhdp_drmcore.o -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index 84c175997740..dc393f6b75e7 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -1,7 +1,7 @@ - /* - * Cadence High-Definition Multimedia Interface (HDMI) driver - * -- * Copyright (C) 2019-2020 NXP Semiconductor, Inc. -+ * Copyright (C) 2019-2021 NXP Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -27,6 +28,131 @@ - #include - #include - -+#include "cdns-mhdp-hdcp.h" -+ -+static ssize_t HDCPTX_do_reauth_store(struct device *dev, -+ struct device_attribute *attr, const char *buf, size_t count); -+static struct device_attribute HDCPTX_do_reauth = __ATTR_WO(HDCPTX_do_reauth); -+ -+static ssize_t HDCPTX_do_reauth_store(struct device *dev, -+ struct device_attribute *attr, const char *buf, size_t count) -+{ -+ int value, ret; -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ -+ ret = cdns_mhdp_hdcp_tx_reauth(mhdp, 1); -+ -+ sscanf(buf, "%d", &value); -+ -+ if (ret < 0) { -+ dev_err(dev, "%s cdns_mhdp_hdcp_tx_reauth failed\n", __func__); -+ return -1; -+ } -+ return count; -+} -+ -+static ssize_t HDCPTX_Version_show(struct device *dev, -+ struct device_attribute *attr, char *buf); -+static ssize_t HDCPTX_Version_store(struct device *dev, -+ struct device_attribute *attr, const char *buf, size_t count); -+static struct device_attribute HDCPTX_Version = __ATTR_RW(HDCPTX_Version); -+ -+static ssize_t HDCPTX_Version_store(struct device *dev, -+ struct device_attribute *attr, const char *buf, size_t count) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ int value; -+ -+ sscanf(buf, "%d", &value); -+ if (value == 2) -+ mhdp->hdcp.config = 2; -+ else if (value == 1) -+ mhdp->hdcp.config = 1; -+ else if (value == 3) -+ mhdp->hdcp.config = 3; -+ else -+ mhdp->hdcp.config = 0; -+ -+ return count; -+} -+ -+ssize_t HDCPTX_Version_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ return sprintf(buf, "%d\n", mhdp->hdcp.config); -+} -+ -+static ssize_t HDCPTX_Status_show(struct device *dev, -+ struct device_attribute *attr, char *buf); -+static ssize_t HDCPTX_Status_store(struct device *dev, -+ struct device_attribute *attr, const char *buf, size_t count); -+static struct device_attribute HDCPTX_Status = __ATTR_RW(HDCPTX_Status); -+ -+ssize_t HDCPTX_Status_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ -+ switch (mhdp->hdcp.state) { -+ case HDCP_STATE_NO_AKSV: -+ return sprintf(buf, "%d :HDCP_STATE_NO_AKSV \n", mhdp->hdcp.state); -+ case HDCP_STATE_INACTIVE: -+ return sprintf(buf, "%d :HDCP_STATE_INACTIVE \n", mhdp->hdcp.state); -+ case HDCP_STATE_ENABLING: -+ return sprintf(buf, "%d :HDCP_STATE_ENABLING \n", mhdp->hdcp.state); -+ case HDCP_STATE_AUTHENTICATING: -+ return sprintf(buf, "%d :HDCP_STATE_AUTHENTICATING \n", mhdp->hdcp.state); -+ case HDCP_STATE_AUTHENTICATED: -+ return sprintf(buf, "%d :HDCP_STATE_AUTHENTICATED \n", mhdp->hdcp.state); -+ case HDCP_STATE_DISABLING: -+ return sprintf(buf, "%d :HDCP_STATE_DISABLING \n", mhdp->hdcp.state); -+ case HDCP_STATE_AUTH_FAILED: -+ return sprintf(buf, "%d :HDCP_STATE_AUTH_FAILED \n", mhdp->hdcp.state); -+ default: -+ return sprintf(buf, "%d :HDCP_STATE don't exist \n", mhdp->hdcp.state); -+ } -+} -+ -+ssize_t HDCPTX_Status_store(struct device *dev, -+ struct device_attribute *attr, const char *buf, size_t count) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ int value; -+ -+ if (count == 2) { -+ sscanf(buf, "%d", &value); -+ if ((value >= HDCP_STATE_NO_AKSV) && (value <= HDCP_STATE_AUTH_FAILED)) { -+ mhdp->hdcp.state = value; -+ return count; -+ } else { -+ dev_err(dev, "%s &hdp->state invalid\n", __func__); -+ return -1; -+ } -+ } -+ -+ dev_info(dev, "%s &hdp->state desired %s count=%d\n ", __func__, buf, (int)count); -+ -+ if (strncmp(buf, "HDCP_STATE_NO_AKSV", count - 1) == 0) -+ mhdp->hdcp.state = HDCP_STATE_NO_AKSV; -+ else if (strncmp(buf, "HDCP_STATE_INACTIVE", count - 1) == 0) -+ mhdp->hdcp.state = HDCP_STATE_INACTIVE; -+ else if (strncmp(buf, "HDCP_STATE_ENABLING", count - 1) == 0) -+ mhdp->hdcp.state = HDCP_STATE_ENABLING; -+ else if (strncmp(buf, "HDCP_STATE_AUTHENTICATING", count - 1) == 0) -+ mhdp->hdcp.state = HDCP_STATE_AUTHENTICATING; -+ else if (strncmp(buf, "HDCP_STATE_AUTHENTICATED", count - 1) == 0) -+ mhdp->hdcp.state = HDCP_STATE_AUTHENTICATED; -+ else if (strncmp(buf, "HDCP_STATE_DISABLING", count - 1) == 0) -+ mhdp->hdcp.state = HDCP_STATE_DISABLING; -+ else if (strncmp(buf, "HDCP_STATE_AUTH_FAILED", count - 1) == 0) -+ mhdp->hdcp.state = HDCP_STATE_AUTH_FAILED; -+ else -+ dev_err(dev, "%s &hdp->state invalid\n", __func__); -+ return -1; -+ return count; -+} -+ - static void hdmi_sink_config(struct cdns_mhdp_device *mhdp) - { - struct drm_scdc *scdc = &mhdp->connector.base.display_info.hdmi.scdc; -@@ -319,6 +445,22 @@ static bool blob_equal(const struct drm_property_blob *a, - return !a == !b; - } - -+static void cdns_hdmi_bridge_disable(struct drm_bridge *bridge) -+{ -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ -+ cdns_hdmi_hdcp_disable(mhdp); -+} -+ -+static void cdns_hdmi_bridge_enable(struct drm_bridge *bridge) -+{ -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ struct drm_connector_state *conn_state = mhdp->connector.base.state; -+ -+ if (conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) -+ cdns_hdmi_hdcp_enable(mhdp); -+} -+ - static int cdns_hdmi_connector_atomic_check(struct drm_connector *connector, - struct drm_atomic_state *state) - { -@@ -329,12 +471,17 @@ static int cdns_hdmi_connector_atomic_check(struct drm_connector *connector, - struct drm_crtc *crtc = new_con_state->crtc; - struct drm_crtc_state *new_crtc_state; - -+ cdns_hdmi_hdcp_atomic_check(connector, old_con_state, new_con_state); -+ if (!new_con_state->crtc) -+ return 0; -+ -+ new_crtc_state = drm_atomic_get_crtc_state(state, crtc); -+ if (IS_ERR(new_crtc_state)) -+ return PTR_ERR(new_crtc_state); -+ - if (!blob_equal(new_con_state->hdr_output_metadata, - old_con_state->hdr_output_metadata) || - new_con_state->colorspace != old_con_state->colorspace) { -- new_crtc_state = drm_atomic_get_crtc_state(state, crtc); -- if (IS_ERR(new_crtc_state)) -- return PTR_ERR(new_crtc_state); - - new_crtc_state->mode_changed = - !new_con_state->hdr_output_metadata || -@@ -342,6 +489,15 @@ static int cdns_hdmi_connector_atomic_check(struct drm_connector *connector, - new_con_state->colorspace != old_con_state->colorspace; - } - -+ /* -+ * These properties are handled by fastset, and might not end up in a -+ * modeset. -+ */ -+ if (new_con_state->picture_aspect_ratio != -+ old_con_state->picture_aspect_ratio || -+ new_con_state->content_type != old_con_state->content_type || -+ new_con_state->scaling_mode != old_con_state->scaling_mode) -+ new_crtc_state->mode_changed = true; - return 0; - } - -@@ -388,6 +544,7 @@ static int cdns_hdmi_bridge_attach(struct drm_bridge *bridge, - - drm_connector_attach_encoder(connector, encoder); - -+ drm_connector_attach_content_protection_property(connector, true); - return 0; - } - -@@ -439,7 +596,7 @@ static void cdns_hdmi_bridge_mode_set(struct drm_bridge *bridge, - video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); - video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); - -- DRM_INFO("Mode: %dx%dp%d\n", mode->hdisplay, mode->vdisplay, mode->clock); -+ DRM_INFO("Mode: %dx%dp%d\n", mode->hdisplay, mode->vdisplay, mode->clock); - memcpy(&mhdp->mode, mode, sizeof(struct drm_display_mode)); - - mutex_lock(&mhdp->lock); -@@ -518,6 +675,8 @@ bool cdns_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, - - static const struct drm_bridge_funcs cdns_hdmi_bridge_funcs = { - .attach = cdns_hdmi_bridge_attach, -+ .enable = cdns_hdmi_bridge_enable, -+ .disable = cdns_hdmi_bridge_disable, - .mode_set = cdns_hdmi_bridge_mode_set, - .mode_valid = cdns_hdmi_bridge_mode_valid, - .mode_fixup = cdns_hdmi_bridge_mode_fixup, -@@ -645,7 +804,7 @@ static int __cdns_hdmi_probe(struct platform_device *pdev, - mhdp->irq[IRQ_IN]); - return -EINVAL; - } -- -+ - irq_set_status_flags(mhdp->irq[IRQ_OUT], IRQ_NOAUTOEN); - ret = devm_request_threaded_irq(dev, mhdp->irq[IRQ_OUT], - NULL, cdns_hdmi_irq_thread, -@@ -659,6 +818,25 @@ static int __cdns_hdmi_probe(struct platform_device *pdev, - - cdns_hdmi_parse_dt(mhdp); - -+ ret = cdns_hdmi_hdcp_init(mhdp, pdev->dev.of_node); -+ if (ret < 0) -+ DRM_WARN("Failed to initialize HDCP\n"); -+ -+ if (device_create_file(mhdp->dev, &HDCPTX_do_reauth)) { -+ printk(KERN_ERR "Unable to create HDCPTX_do_reauth sysfs\n"); -+ device_remove_file(mhdp->dev, &HDCPTX_do_reauth); -+ } -+ -+ if (device_create_file(mhdp->dev, &HDCPTX_Version)) { -+ printk(KERN_ERR "Unable to create HDCPTX_Version sysfs\n"); -+ device_remove_file(mhdp->dev, &HDCPTX_Version); -+ } -+ -+ if (device_create_file(mhdp->dev, &HDCPTX_Status)) { -+ printk(KERN_ERR "Unable to create HDCPTX_Status sysfs\n"); -+ device_remove_file(mhdp->dev, &HDCPTX_Status); -+ } -+ - if (cdns_mhdp_read_hpd(mhdp)) - enable_irq(mhdp->irq[IRQ_OUT]); - else -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c -new file mode 100644 -index 000000000000..e2a3bc7fb42b ---- /dev/null -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c -@@ -0,0 +1,1167 @@ -+/* -+ * Cadence HDMI HDCP driver -+ * -+ * Copyright (C) 2021 NXP Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ */ -+#include -+#include -+#include -+#include -+ -+#include "cdns-mhdp-hdcp.h" -+ -+/* Default will be to use KM unless it has been explicitly */ -+#ifndef HDCP_USE_KMKEY -+ #define HDCP_USE_KMKEY 1 -+#endif -+ -+#define CDNS_HDCP_ACTIVATE (0x1 << 2) -+ -+#define IMX_FW_TIMEOUT_MS (64 * 1000) -+#define IMX_HDCP_PAIRING_FIRMWARE "imx/hdcp-pairing.bin" -+ -+#define GENERAL_BUS_SETTINGS_DPCD_BUS_BIT 0 -+#define GENERAL_BUS_SETTINGS_DPCD_BUS_LOCK_BIT 1 -+#define GENERAL_BUS_SETTINGS_HDCP_BUS_BIT 2 -+#define GENERAL_BUS_SETTINGS_HDCP_BUS_LOCK_BIT 3 -+#define GENERAL_BUS_SETTINGS_CAPB_OWNER_BIT 4 -+#define GENERAL_BUS_SETTINGS_CAPB_OWNER_LOCK_BIT 5 -+ -+#define GENERAL_BUS_SETTINGS_RESP_DPCD_BUS_BIT 0 -+#define GENERAL_BUS_SETTINGS_RESP_HDCP_BUS_BIT 1 -+#define GENERAL_BUS_SETTINGS_RESP_CAPB_OWNER_BIT 2 -+ -+/* HDCP TX ports working mode (HDCP 2.2 or 1.4) */ -+enum { -+ HDCP_TX_2, /* lock only with HDCP2 */ -+ HDCP_TX_1, /* lock only with HDCP1 */ -+ HDCP_TX_BOTH, /* lock on HDCP2 or 1 depend on other side */ -+}; -+ -+/* HDCP TX ports stream type (relevant if receiver is repeater) */ -+enum { -+ HDCP_CONTENT_TYPE_0, /* May be transmitted by -+ The HDCP Repeater to all HDCP Devices. */ -+ HDCP_CONTENT_TYPE_1, /* Must not be transmitted by the HDCP Repeater to -+ HDCP 1.x-compliant Devices and HDCP 2.0-compliant Repeaters */ -+}; -+ -+/* different error types for HDCP_TX_STATUS_CHANGE */ -+enum { -+ HDCP_TRAN_ERR_NO_ERROR, -+ HDCP_TRAN_ERR_HPD_IS_DOWN, -+ HDCP_TRAN_ERR_SRM_FAILURE, -+ HDCP_TRAN_ERR_SIGNATURE_VERIFICATION, -+ HDCP_TRAN_ERR_H_TAG_DIFF_H, -+ HDCP_TRAN_ERR_V_TAG_DIFF_V, -+ HDCP_TRAN_ERR_LOCALITY_CHECK, -+ HDCP_TRAN_ERR_DDC, -+ HDCP_TRAN_ERR_REAUTH_REQ, -+ HDCP_TRAN_ERR_TOPOLOGY, -+ HDCP_TRAN_ERR_HDCP_RSVD1, -+ HDCP_TRAN_ERR_HDMI_CAPABILITY, -+ HDCP_TRAN_ERR_RI, -+ HDCP_TRAN_ERR_WATCHDOG_EXPIRED, -+}; -+ -+static char const *g_last_error[16] = { -+ "No Error", -+ "HPD is down", -+ "SRM failure", -+ "Signature verification error", -+ "h tag != h", -+ "V tag diff v", -+ "Locality check", -+ "DDC error", -+ "REAUTH_REQ", -+ "Topology error", -+ "Verify receiver ID list failed", -+ "HDCP_RSVD1 was not 0,0,0", -+ "HDMI capability or mode", -+ "RI result was different than expected", -+ "WatchDog expired", -+ "Repeater integrity failed" -+}; -+ -+#define HDCP_MAX_RECEIVERS 32 -+#define HDCP_RECEIVER_ID_SIZE_BYTES 5 -+#define HPD_EVENT 1 -+#define HDCP_STATUS_SIZE 0x5 -+#define HDCP_PORT_STS_AUTH 0x1 -+#define HDCP_PORT_STS_REPEATER 0x2 -+#define HDCP_PORT_STS_TYPE_MASK 0xc -+#define HDCP_PORT_STS_TYPE_SHIFT 0x2 -+#define HDCP_PORT_STS_AUTH_STREAM_ID_SHIFT 0x4 -+#define HDCP_PORT_STS_AUTH_STREAM_ID_MASK 0x10 -+#define HDCP_PORT_STS_LAST_ERR_SHIFT 0x5 -+#define HDCP_PORT_STS_LAST_ERR_MASK (0x0F << 5) -+#define GET_HDCP_PORT_STS_LAST_ERR(__sts__) \ -+ (((__sts__) & HDCP_PORT_STS_LAST_ERR_MASK) >> \ -+ HDCP_PORT_STS_LAST_ERR_SHIFT) -+#define HDCP_PORT_STS_1_1_FEATURES 0x200 -+ -+#define HDCP_CONFIG_NONE ((u8) 0) -+#define HDCP_CONFIG_1_4 ((u8) 1) /* use HDCP 1.4 only */ -+#define HDCP_CONFIG_2_2 ((u8) 2) /* use HDCP 2.2 only */ -+ -+/* Default timeout to use for wait4event in milliseconds */ -+#define HDCP_EVENT_TO_DEF 800 -+/* Timeout value to use for repeater receiver ID check, spec says 3s */ -+#define HDCP_EVENT_TO_RPT 3500 -+ -+static int hdmi_hdcp_check_link(struct cdns_mhdp_device *mhdp); -+ -+static void print_port_status(u16 sts) -+{ -+ char const *rx_type[4] = { "Unknown", "HDCP 1", "HDCP 2", "Unknown" }; -+ -+ DRM_DEBUG_KMS("INFO: HDCP Port Status: 0x%04x\n", sts); -+ DRM_DEBUG_KMS(" Authenticated: %d\n", sts & HDCP_PORT_STS_AUTH); -+ DRM_DEBUG_KMS(" Receiver is repeater: %d\n", sts & HDCP_PORT_STS_REPEATER); -+ DRM_DEBUG_KMS(" RX Type: %s\n", -+ rx_type[(sts & HDCP_PORT_STS_TYPE_MASK) >> HDCP_PORT_STS_TYPE_SHIFT]); -+ DRM_DEBUG_KMS(" AuthStreamId: %d\n", sts & HDCP_PORT_STS_AUTH_STREAM_ID_MASK); -+ DRM_DEBUG_KMS(" Last Error: %s\n", -+ g_last_error[(sts & HDCP_PORT_STS_LAST_ERR_MASK) >> HDCP_PORT_STS_LAST_ERR_SHIFT]); -+ DRM_DEBUG_KMS(" Enable 1.1 Features: %d\n", sts & HDCP_PORT_STS_1_1_FEATURES); -+} -+ -+static void print_events(u8 events) -+{ -+ if (events & HDMI_TX_HPD_EVENT) -+ DRM_INFO("INFO: HDMI_TX_HPD_EVENT\n"); -+ if (events & HDCPTX_STATUS_EVENT) -+ DRM_INFO("INFO: HDCPTX_STATUS_EVENT\n"); -+ if (events & HDCPTX_IS_KM_STORED_EVENT) -+ DRM_INFO("INFO: HDCPTX_IS_KM_STORED_EVENT\n"); -+ if (events & HDCPTX_STORE_KM_EVENT) -+ DRM_INFO("INFO: HDCPTX_STORE_KM_EVENT\n"); -+ if (events & HDCPTX_IS_RECEIVER_ID_VALID_EVENT) -+ DRM_INFO("INFO: HDCPTX_IS_RECEIVER_ID_VALID_EVENT\n"); -+} -+ -+static u8 wait4event(struct cdns_mhdp_device *mhdp, u8 *events, -+ u32 event_to_wait, u32 timeout_ms) -+{ -+ u8 reg_events; -+ u8 returned_events; -+ u8 event_mask = event_to_wait | HDCPTX_STATUS_EVENT; -+ unsigned timeout; -+ -+ timeout = timeout_ms; -+ do { -+ if (timeout == 0) -+ goto timeout_err; -+ timeout--; -+ udelay(1000); -+ reg_events = cdns_mhdp_get_event(mhdp); -+ *events |= reg_events; -+ } while (((event_mask & *events) == 0) && (event_to_wait > HDMI_TX_HPD_EVENT)); -+ -+ returned_events = *events & event_mask; -+ if (*events != returned_events) { -+ u32 unexpected_events = ~event_mask & *events; -+ -+ DRM_INFO("INFO: %s() all 0x%08x expected 0x%08x unexpected 0x%08x", -+ __func__, *events, returned_events, unexpected_events); -+ DRM_INFO("INFO: %s() All events:\n", __func__); -+ print_events(*events); -+ -+ DRM_INFO("INFO: %s() expected events:\n", __func__); -+ print_events(returned_events); -+ -+ DRM_INFO("INFO: %s() unexpected events:\n", __func__); -+ print_events(unexpected_events); -+ } else -+ print_events(*events); -+ -+ *events &= ~event_mask; -+ -+ return returned_events; -+ -+timeout_err: -+ DRM_INFO("INFO: %s() Timed out with events:\n", __func__); -+ print_events(event_to_wait); -+ return 0; -+} -+ -+static u16 hdmi_hdcp_get_status(struct cdns_mhdp_device *mhdp) -+{ -+ u8 hdcp_status[HDCP_STATUS_SIZE]; -+ u16 hdcp_port_status; -+ -+ cdns_mhdp_hdcp_tx_status_req(mhdp, hdcp_status, HDCP_STATUS_SIZE); -+ hdcp_port_status = (hdcp_status[0] << 8) | hdcp_status[1]; -+ -+ return hdcp_port_status; -+} -+ -+static inline u8 check_event(u8 events, u8 tested) -+{ -+ if ((events & tested) == 0) -+ return 0; -+ return 1; -+} -+ -+/* Prints status. Returns error code (0 = no error) */ -+static u8 hdmi_hdcp_handle_status(u16 status) -+{ -+ print_port_status(status); -+ if (status & HDCP_PORT_STS_LAST_ERR_MASK) -+ DRM_ERROR("ERROR: HDCP error was set to %s\n", -+ g_last_error[((status & HDCP_PORT_STS_LAST_ERR_MASK) -+ >> HDCP_PORT_STS_LAST_ERR_SHIFT)]); -+ return GET_HDCP_PORT_STS_LAST_ERR(status); -+} -+ -+static int hdmi_hdcp_set_config(struct cdns_mhdp_device *mhdp, u8 hdcp_config) -+{ -+ u8 bus_config, retEvents; -+ u16 hdcp_port_status; -+ int ret; -+ -+ /* Clearing out existing events */ -+ wait4event(mhdp, &mhdp->hdcp.events, HDMI_TX_HPD_EVENT, HDCP_EVENT_TO_DEF); -+ mhdp->hdcp.events = 0; -+ -+ if (!strncmp("imx8mq-hdmi", mhdp->plat_data->plat_name, 11)) { -+ DRM_DEBUG_KMS("INFO: Switching HDCP Commands to SAPB.\n"); -+ bus_config = (1 << GENERAL_BUS_SETTINGS_HDCP_BUS_BIT); -+ ret = cdns_mhdp_apb_conf(mhdp, bus_config); -+ if (ret) { -+ DRM_ERROR("Failed to set APB configuration.\n"); -+ if (ret & (1 << GENERAL_BUS_SETTINGS_RESP_HDCP_BUS_BIT))/* 1 - locked */ -+ DRM_ERROR("Failed to switch HDCP to SAPB Mailbox\n"); -+ return -1; -+ } -+ DRM_DEBUG_KMS("INFO: HDCP switched to SAPB\n"); -+ } -+ -+ /* HDCP 2.2(and/or 1.4) | activate | km-key | 0 */ -+ hdcp_config |= CDNS_HDCP_ACTIVATE | (HDCP_USE_KMKEY << 4) | (HDCP_CONTENT_TYPE_0 << 3); -+ -+ DRM_DEBUG_KMS("INFO: Enabling HDCP...\n"); -+ ret = cdns_mhdp_hdcp_tx_config(mhdp, hdcp_config); -+ if (ret < 0) -+ DRM_DEBUG_KMS("cdns_mhdp_hdcp_tx_config failed\n"); -+ -+ /* Wait until HDCP_TX_STATUS EVENT appears */ -+ DRM_DEBUG_KMS("INFO: wait4event -> HDCPTX_STATUS_EVENT\n"); -+ retEvents = wait4event(mhdp, &mhdp->hdcp.events, HDCPTX_STATUS_EVENT, HDCP_EVENT_TO_DEF); -+ -+ /* Set TX STATUS REQUEST */ -+ DRM_DEBUG_KMS("INFO: Getting port status\n"); -+ hdcp_port_status = hdmi_hdcp_get_status(mhdp); -+ if (hdmi_hdcp_handle_status(hdcp_port_status) != 0) -+ return -1; -+ -+ return 0; -+} -+ -+static int hdmi_hdcp_auth_check(struct cdns_mhdp_device *mhdp) -+{ -+ u16 hdcp_port_status; -+ int ret; -+ -+ DRM_DEBUG_KMS("INFO: wait4event -> HDCPTX_STATUS_EVENT\n"); -+ mhdp->hdcp.events = wait4event(mhdp, &mhdp->hdcp.events, HDCPTX_STATUS_EVENT, HDCP_EVENT_TO_DEF+HDCP_EVENT_TO_DEF); -+ if (mhdp->hdcp.events == 0) -+ return -1; -+ -+ DRM_DEBUG_KMS("HDCP: HDCPTX_STATUS_EVENT\n"); -+ hdcp_port_status = hdmi_hdcp_get_status(mhdp); -+ ret = hdmi_hdcp_handle_status(hdcp_port_status); -+ if (ret != 0) { -+ if (ret == HDCP_TRAN_ERR_REAUTH_REQ) { -+ DRM_ERROR("HDCP_TRAN_ERR_REAUTH_REQ-->one more try!\n"); -+ return 1; -+ } else -+ return -1; -+ } -+ -+ if (hdcp_port_status & HDCP_PORT_STS_AUTH) { -+ DRM_INFO("Authentication completed successfully!\n"); -+ /* Dump hdmi and phy register */ -+ mhdp->hdcp.state = HDCP_STATE_AUTHENTICATED; -+ return 0; -+ } -+ -+ DRM_WARN("Authentication failed\n"); -+ mhdp->hdcp.state = HDCP_STATE_AUTH_FAILED; -+ return -1; -+} -+ -+inline void hdmi_hdcp_swap_id(u8 *in, u8 *out) -+{ -+ int i; -+ -+ for (i = 0; i < HDCP_RECEIVER_ID_SIZE_BYTES; i++) -+ out[HDCP_RECEIVER_ID_SIZE_BYTES - (i + 1)] = in[i]; -+} -+ -+inline void hdmi_hdcp_swap_list(u8 *list_in, u8 *list_out, int num_ids) -+{ -+ int i; -+ -+ for (i = 0; i < num_ids; i++) -+ hdmi_hdcp_swap_id(&list_in[i * HDCP_RECEIVER_ID_SIZE_BYTES], -+ &list_out[i * HDCP_RECEIVER_ID_SIZE_BYTES]); -+} -+ -+static int hdmi_hdcp_check_receviers(struct cdns_mhdp_device *mhdp) -+{ -+ u8 ret_events; -+ u8 hdcp_num_rec, i; -+ u8 hdcp_rec_id[HDCP_MAX_RECEIVERS][HDCP_RECEIVER_ID_SIZE_BYTES]; -+ u8 hdcp_rec_id_temp[HDCP_MAX_RECEIVERS][HDCP_RECEIVER_ID_SIZE_BYTES]; -+ u16 hdcp_port_status = 0; -+ int ret; -+ -+ DRM_INFO("INFO: Waiting for Receiver ID valid event\n"); -+ ret_events = 0; -+ do { -+ u8 events = 0; -+ u8 hdcp_last_error = 0; -+ events = check_event(ret_events, -+ HDCPTX_IS_RECEIVER_ID_VALID_EVENT); -+ DRM_DEBUG_KMS("INFO: Waiting HDCPTX_IS_RECEIVER_ID_VALID_EVENT\n"); -+ ret_events = wait4event(mhdp, &mhdp->hdcp.events, -+ HDCPTX_IS_RECEIVER_ID_VALID_EVENT, -+ (mhdp->hdcp.sink_is_repeater ? -+ HDCP_EVENT_TO_RPT : HDCP_EVENT_TO_DEF)); -+ if (ret_events == 0) { -+ /* time out occurred, return error */ -+ DRM_ERROR("HDCP error did not get receiver IDs\n"); -+ return -1; -+ } -+ if (check_event(ret_events, HDCPTX_STATUS_EVENT) != 0) { -+ /* There was a status update, could be due to HPD -+ going down or some other error, check if an error -+ was set, if so exit. -+ */ -+ hdcp_port_status = hdmi_hdcp_get_status(mhdp); -+ hdcp_last_error = GET_HDCP_PORT_STS_LAST_ERR(hdcp_port_status); -+ if (hdmi_hdcp_handle_status(hdcp_port_status)) { -+ DRM_ERROR("HDCP error no: %u\n", hdcp_last_error); -+ return -1; -+ } else { -+ /* No error logged, keep going. -+ * If this somehow happened at same time, then need to -+ * put the HDCPTX_STATUS_EVENT back into the global -+ * events pool and checked later. */ -+ mhdp->hdcp.events |= HDCPTX_STATUS_EVENT; -+ -+ /* Special condition when connected to HDCP 1.4 repeater -+ * with no downstream devices attached, then will not -+ * get receiver ID list but instead will reach -+ * authenticated state. */ -+ if ((mhdp->hdcp.hdcp_version == HDCP_TX_1) && (mhdp->hdcp.sink_is_repeater == 1) && -+ ((hdcp_port_status & HDCP_PORT_STS_AUTH) == HDCP_PORT_STS_AUTH)) { -+ DRM_INFO("Connected to HDCP 1.4 repeater with no downstream devices!\n"); -+ return 0; -+ } -+ -+ msleep(20); -+ } -+ } -+ } while (check_event(ret_events, -+ HDCPTX_IS_RECEIVER_ID_VALID_EVENT) == 0); -+ -+ DRM_INFO("INFO: Requesting Receivers ID's\n"); -+ -+ hdcp_num_rec = 0; -+ memset(&hdcp_rec_id, 0, sizeof(hdcp_rec_id)); -+ -+ ret = cdns_mhdp_hdcp_tx_is_receiver_id_valid(mhdp, (u8 *)hdcp_rec_id, &hdcp_num_rec); -+ if (ret) { -+ DRM_DEV_ERROR(mhdp->dev, "Failed to hdcp tx receiver ID.\n"); -+ return -1; -+ } -+ -+ if (hdcp_num_rec == 0) { -+ DRM_DEBUG_KMS("WARN: Failed to get receiver list\n"); -+ /* Unknown problem, return error */ -+ return -1; -+ } -+ -+ DRM_INFO("INFO: Number of Receivers: %d\n", hdcp_num_rec); -+ -+ for (i = 0; i < hdcp_num_rec; ++i) { -+ DRM_INFO("\tReveiver ID%2d: %.2X%.2X%.2X%.2X%.2X\n", -+ i, -+ hdcp_rec_id[i][0], -+ hdcp_rec_id[i][1], -+ hdcp_rec_id[i][2], -+ hdcp_rec_id[i][3], -+ hdcp_rec_id[i][4] -+ ); -+ } -+ -+ /* swap ids byte order */ -+ hdmi_hdcp_swap_list(&hdcp_rec_id[0][0], -+ &hdcp_rec_id_temp[0][0], hdcp_num_rec); -+ -+ /* Check Receiver ID's against revocation list in SRM */ -+ if (drm_hdcp_check_ksvs_revoked(mhdp->drm_dev, (u8 *)hdcp_rec_id_temp, hdcp_num_rec)) { -+ mhdp->hdcp.state = HDCP_STATE_AUTH_FAILED; -+ DRM_ERROR("INFO: Receiver check fails\n"); -+ return -1; -+ } -+ -+ ret = cdns_mhdp_hdcp_tx_respond_receiver_id_valid(mhdp, 1); -+ DRM_INFO("INFO: Responding with Receiver ID's OK!, ret=%d\n", ret); -+ return ret; -+} -+ -+#ifdef STORE_PAIRING -+static int hdmi_hdcp_get_stored_pairing(struct cdns_mhdp_device *mhdp) -+{ -+ int ret = 0; -+ unsigned long timeout = jiffies + msecs_to_jiffies(IMX_FW_TIMEOUT_MS); -+ unsigned long sleep = 1000; -+ const struct firmware *fw; -+ -+ DRM_DEBUG_KMS("%s()\n", __func__); -+ -+ while (time_before(jiffies, timeout)) { -+ ret = request_firmware(&fw, hdmi_hdcp_PAIRING_FIRMWARE, mhdp->dev); -+ if (ret == -ENOENT) { -+ msleep(sleep); -+ sleep *= 2; -+ continue; -+ } else if (ret) { -+ DRM_DEV_INFO(mhdp->dev, "HDCP pairing data not found\n"); -+ goto out; -+ } -+ -+ mhdp->hdcp.num_paired = fw->size / -+ sizeof(struct hdcp_trans_pairing_data); -+ if (mhdp->hdcp.num_paired > MAX_STORED_KM) { -+ /* todo: handle dropping */ -+ mhdp->hdcp.num_paired = MAX_STORED_KM; -+ DRM_DEV_INFO(mhdp->dev, -+ "too many paired receivers - dropping older entries\n"); -+ } -+ memcpy(&mhdp->hdcp.pairing[0], fw->data, -+ sizeof(struct hdcp_trans_pairing_data) * mhdp->hdcp.num_paired); -+ release_firmware(fw); -+ goto out; -+ } -+ -+ DRM_DEV_ERROR(mhdp->dev, "Timed out trying to load firmware\n"); -+ ret = -ETIMEDOUT; -+ out: -+ return ret; -+} -+#endif -+ -+static int hdmi_hdcp_find_km_store(struct cdns_mhdp_device *mhdp, -+ u8 receiver[HDCP_PAIRING_R_ID]) -+{ -+ int i; -+ -+ DRM_DEBUG_KMS("%s()\n", __func__); -+ for (i = 0; i < mhdp->hdcp.num_paired; i++) { -+ if (memcmp(receiver, mhdp->hdcp.pairing[i].receiver_id, -+ HDCP_PAIRING_R_ID) == 0) { -+ DRM_INFO("HDCP: found receiver id: 0x%x%x%x%x%x\n", -+ receiver[0], receiver[1], receiver[2], receiver[3], receiver[4]); -+ return i; -+ } -+ } -+ DRM_INFO("HDCP: receiver id: 0x%x%x%x%x%x not stored\n", -+ receiver[0], receiver[1], receiver[2], receiver[3], receiver[4]); -+ return -1; -+} -+ -+static int hdmi_hdcp_store_km(struct cdns_mhdp_device *mhdp, -+ struct hdcp_trans_pairing_data *pairing, -+ int stored_km_index) -+{ -+ int i, temp_index; -+ struct hdcp_trans_pairing_data temp_pairing; -+ -+ DRM_DEBUG_KMS("%s()\n", __func__); -+ -+ if (stored_km_index < 0) { -+ /* drop one entry if array is full */ -+ if (mhdp->hdcp.num_paired == MAX_STORED_KM) -+ mhdp->hdcp.num_paired--; -+ -+ temp_index = mhdp->hdcp.num_paired; -+ mhdp->hdcp.num_paired++; -+ if (!pairing) { -+ DRM_ERROR("NULL HDCP pairing data!\n"); -+ return -1; -+ } else -+ /* save the new stored km */ -+ temp_pairing = *pairing; -+ } else { -+ /* save the current stored km */ -+ temp_index = stored_km_index; -+ temp_pairing = mhdp->hdcp.pairing[stored_km_index]; -+ } -+ -+ /* move entries one slot to the end */ -+ for (i = temp_index; i > 0; i--) -+ mhdp->hdcp.pairing[i] = mhdp->hdcp.pairing[i - 1]; -+ -+ /* save the current/new entry at the beginning */ -+ mhdp->hdcp.pairing[0] = temp_pairing; -+ -+ return 0; -+} -+ -+static inline int hdmi_hdcp_auth_22(struct cdns_mhdp_device *mhdp) -+{ -+ int km_idx = -1; -+ u8 retEvents; -+ u16 hdcp_port_status; -+ u8 resp[HDCP_STATUS_SIZE]; -+ struct hdcp_trans_pairing_data pairing; -+ int ret; -+ -+ DRM_DEBUG_KMS("HDCP: Start 2.2 Authentication\n"); -+ mhdp->hdcp.sink_is_repeater = 0; -+ -+ /* Wait until HDCP2_TX_IS_KM_STORED EVENT appears */ -+ retEvents = 0; -+ DRM_DEBUG_KMS("INFO: Wait until HDCP2_TX_IS_KM_STORED EVENT appears\n"); -+ while (check_event(retEvents, HDCPTX_IS_KM_STORED_EVENT) == 0) { -+ DRM_DEBUG_KMS("INFO: Waiting FOR _IS_KM_STORED EVENT\n"); -+ retEvents = wait4event(mhdp, &mhdp->hdcp.events, -+ HDCPTX_IS_KM_STORED_EVENT, HDCP_EVENT_TO_DEF); -+ if (retEvents == 0) -+ /* time out occurred, return error */ -+ return -1; -+ if (check_event(retEvents, HDCPTX_STATUS_EVENT) != 0) { -+ /* There was a status update, could be due to HPD -+ going down or some other error, check if an error -+ was set, if so exit. -+ */ -+ hdcp_port_status = hdmi_hdcp_get_status(mhdp); -+ if (hdmi_hdcp_handle_status(hdcp_port_status) != 0) -+ return -1; -+ } -+ } -+ -+ DRM_DEBUG_KMS("HDCP: HDCPTX_IS_KM_STORED_EVENT\n"); -+ -+ /* Set HDCP2 TX KM STORED REQUEST */ -+ ret = cdns_mhdp_hdcp2_tx_is_km_stored_req(mhdp, resp, HDCP_STATUS_SIZE); -+ if (ret) { -+ DRM_DEV_ERROR(mhdp->dev, "Failed to hdcp2 tx km stored.\n"); -+ return -1; -+ } -+ -+ DRM_DEBUG_KMS("HDCP: CDN_API_HDCP2_TX_IS_KM_STORED_REQ_blocking\n"); -+ DRM_DEBUG_KMS("HDCP: Receiver ID: 0x%x%x%x%x%x\n", -+ resp[0], resp[1], resp[2], resp[3], resp[4]); -+ -+ km_idx = hdmi_hdcp_find_km_store(mhdp, resp); -+ -+ /* Check if KM is stored */ -+ if (km_idx >= 0) { -+ DRM_DEBUG_KMS("INFO: KM is stored\n"); -+ /* Set HDCP2 TX RESPOND KM with stored KM */ -+ ret = cdns_mhdp_hdcp2_tx_respond_km(mhdp, (u8 *)&mhdp->hdcp.pairing[km_idx], -+ sizeof(struct hdcp_trans_pairing_data)); -+ -+ DRM_DEBUG_KMS("HDCP: CDN_API_HDCP2_TX_RESPOND_KM_blocking, ret=%d\n", ret); -+ } else { /* KM is not stored */ -+ /* Set HDCP2 TX RESPOND KM with empty data */ -+ ret = cdns_mhdp_hdcp2_tx_respond_km(mhdp, NULL, 0); -+ DRM_DEBUG_KMS("INFO: KM is not stored ret=%d\n", ret); -+ } -+ -+ if (hdmi_hdcp_check_receviers(mhdp)) -+ return -1; -+ -+ /* Check if KM is not stored */ -+ if (km_idx < 0) { -+ int loop_cnt = 0; -+ -+ /* Wait until HDCP2_TX_STORE_KM EVENT appears */ -+ retEvents = 0; -+ DRM_DEBUG_KMS("INFO: wait4event -> HDCPTX_STORE_KM_EVENT\n"); -+ while (check_event(retEvents, HDCPTX_STORE_KM_EVENT) == 0) { -+ retEvents = wait4event(mhdp, &mhdp->hdcp.events, -+ HDCPTX_STORE_KM_EVENT, HDCP_EVENT_TO_DEF); -+ if (check_event(retEvents, HDCPTX_STATUS_EVENT) -+ != 0) { -+ hdcp_port_status = hdmi_hdcp_get_status(mhdp); -+ if (hdmi_hdcp_handle_status(hdcp_port_status) -+ != 0) -+ return -1; -+ } -+ if (loop_cnt > 2) { -+ DRM_ERROR("Did not get event HDCPTX_STORE_KM_EVENT in time\n"); -+ return -1; -+ } else -+ loop_cnt++; -+ } -+ DRM_DEBUG_KMS("HDCP: HDCPTX_STORE_KM_EVENT\n"); -+ -+ /* Set HDCP2_TX_STORE_KM REQUEST */ -+ ret = cdns_mhdp_hdcp2_tx_store_km(mhdp, (u8 *)&pairing, sizeof(struct hdcp_trans_pairing_data)); -+ DRM_DEBUG_KMS("HDCP: CDN_API_HDCP2_TX_STORE_KM_REQ_blocking ret=%d\n", ret); -+ hdmi_hdcp_store_km(mhdp, &pairing, km_idx); -+ } else -+ hdmi_hdcp_store_km(mhdp, NULL, km_idx); -+ -+ /* Check if device was a repeater */ -+ hdcp_port_status = hdmi_hdcp_get_status(mhdp); -+ -+ /* Exit if there was any errors logged at this point... */ -+ if (GET_HDCP_PORT_STS_LAST_ERR(hdcp_port_status) > 0) { -+ hdmi_hdcp_handle_status(hdcp_port_status); -+ return -1; -+ } -+ -+ if (hdcp_port_status & HDCP_PORT_STS_REPEATER) -+ mhdp->hdcp.sink_is_repeater = 1; -+ -+ /* If sink was a repeater, we will be getting additional IDs to validate... -+ * Note that this one may take some time since spec allows up to 3s... */ -+ if (mhdp->hdcp.sink_is_repeater) -+ if (hdmi_hdcp_check_receviers(mhdp)) -+ return -1; -+ -+ /* Slight delay to allow firmware to finish setting up authenticated state */ -+ msleep(300); -+ -+ DRM_INFO("Finished hdmi_hdcp_auth_22\n"); -+ return 0; -+} -+ -+static inline int hdmi_hdcp_auth_14(struct cdns_mhdp_device *mhdp) -+{ -+ u16 hdcp_port_status; -+ int ret = 0; -+ -+ DRM_DEBUG_KMS("HDCP: Starting 1.4 Authentication\n"); -+ mhdp->hdcp.sink_is_repeater = 0; -+ -+ ret = hdmi_hdcp_check_receviers(mhdp); -+ if (ret) -+ return -1; -+ -+ /* Check if device was a repeater */ -+ hdcp_port_status = hdmi_hdcp_get_status(mhdp); -+ -+ /* Exit if there was any errors logged at this point... */ -+ if (GET_HDCP_PORT_STS_LAST_ERR(hdcp_port_status) > 0) { -+ hdmi_hdcp_handle_status(hdcp_port_status); -+ return -1; -+ } -+ -+ if (hdcp_port_status & HDCP_PORT_STS_REPEATER) { -+ DRM_INFO("Connected to a repeater\n"); -+ mhdp->hdcp.sink_is_repeater = 1; -+ } else -+ DRM_INFO("Connected to a normal sink\n"); -+ -+ /* If sink was a repeater, we will be getting additional IDs to validate... -+ * Note that this one may take some time since spec allows up to 3s... */ -+ if (mhdp->hdcp.sink_is_repeater) -+ ret = hdmi_hdcp_check_receviers(mhdp); -+ -+ /* Slight delay to allow firmware to finish setting up authenticated state */ -+ msleep(300); -+ -+ return ret; -+} -+ -+static int hdmi_hdcp_auth(struct cdns_mhdp_device *mhdp, u8 hdcp_config) -+{ -+ int ret = 0; -+ -+ DRM_DEBUG_KMS("HDCP: Start Authentication\n"); -+ -+ if (mhdp->hdcp.reauth_in_progress == 0) { -+ ret = hdmi_hdcp_set_config(mhdp, hdcp_config); -+ if (ret) { -+ DRM_ERROR("hdmi_hdcp_set_config failed\n"); -+ return -1; -+ } -+ } -+ -+ mhdp->hdcp.reauth_in_progress = 0; -+ mhdp->hdcp.sink_is_repeater = 0; -+ mhdp->hdcp.hdcp_version = hdcp_config; -+ -+ do { -+ if (mhdp->hdcp.cancel == 1) { -+ DRM_ERROR("mhdp->hdcp.cancel is TRUE\n"); -+ return -ECANCELED; -+ } -+ -+ if (hdcp_config == HDCP_TX_1) -+ ret = hdmi_hdcp_auth_14(mhdp); -+ else -+ ret = hdmi_hdcp_auth_22(mhdp); -+ if (ret) { -+ u16 hdcp_port_status; -+ DRM_ERROR("hdmi_hdcp_auth_%s failed\n", -+ (hdcp_config == HDCP_TX_1) ? "14" : "22"); -+ hdcp_port_status = hdmi_hdcp_get_status(mhdp); -+ hdmi_hdcp_handle_status(hdcp_port_status); -+ return -1; -+ } -+ -+ ret = hdmi_hdcp_auth_check(mhdp); -+ } while (ret == 1); -+ -+ return ret; -+} -+ -+static int _hdmi_hdcp_disable(struct cdns_mhdp_device *mhdp) -+{ -+ int ret = 0; -+ u8 hdcp_cfg = (HDCP_USE_KMKEY << 4); -+ -+ DRM_DEBUG_KMS("[%s:%d] HDCP is being disabled...\n", -+ mhdp->connector.base.name, mhdp->connector.base.base.id); -+ DRM_DEBUG_KMS("INFO: Disabling HDCP...\n"); -+ -+ ret = cdns_mhdp_hdcp_tx_config(mhdp, hdcp_cfg); -+ if (ret < 0) -+ DRM_DEBUG_KMS("cdns_mhdp_hdcp_tx_config failed\n"); -+ -+ DRM_DEBUG_KMS("HDCP is disabled\n"); -+ -+ mhdp->hdcp.events = 0; -+ -+ return ret; -+} -+ -+static int _hdmi_hdcp_enable(struct cdns_mhdp_device *mhdp) -+{ -+ int i, ret = 0, tries = 9; -+ u8 hpd_sts; -+ -+ hpd_sts = cdns_mhdp_read_hpd(mhdp); -+ if (1 != hpd_sts) { -+ dev_info(mhdp->dev, "%s HDP detected low, set state to DISABLING\n", __func__); -+ mhdp->hdcp.state = HDCP_STATE_DISABLING; -+ return -1; -+ } -+ -+ DRM_DEBUG_KMS("[%s:%d] HDCP is being enabled...\n", -+ mhdp->connector.base.name, mhdp->connector.base.base.id); -+ -+ mhdp->hdcp.events = 0; -+ -+ /* Incase of authentication failures, HDCP spec expects reauth. */ -+ /* TBD should this actually try 2.2 n times then 1.4? */ -+ for (i = 0; i < tries; i++) { -+ if (mhdp->hdcp.config & HDCP_CONFIG_2_2) { -+ ret = hdmi_hdcp_auth(mhdp, HDCP_TX_2); -+ if (ret == 0) -+ return 0; -+ else if (ret == -ECANCELED) -+ return ret; -+ _hdmi_hdcp_disable(mhdp); -+ } -+ } -+ -+ for (i = 0; i < tries; i++) { -+ if (mhdp->hdcp.config & HDCP_CONFIG_1_4) { -+ ret = hdmi_hdcp_auth(mhdp, HDCP_TX_1); -+ if (ret == 0) -+ return 0; -+ else if (ret == -ECANCELED) -+ return ret; -+ _hdmi_hdcp_disable(mhdp); -+ } -+ DRM_DEBUG_KMS("HDCP Auth failure (%d)\n", ret); -+ } -+ -+ DRM_ERROR("HDCP authentication failed (%d tries/%d)\n", tries, ret); -+ return ret; -+} -+ -+static void hdmi_hdcp_check_work(struct work_struct *work) -+{ -+ struct cdns_mhdp_hdcp *hdcp = container_of(work, -+ struct cdns_mhdp_hdcp, check_work.work); -+ struct cdns_mhdp_device *mhdp = container_of(hdcp, -+ struct cdns_mhdp_device, hdcp); -+ -+ /* todo: maybe we don't need to always schedule */ -+ hdmi_hdcp_check_link(mhdp); -+ schedule_delayed_work(&hdcp->check_work, 50); -+} -+ -+static void hdmi_hdcp_prop_work(struct work_struct *work) -+{ -+ struct cdns_mhdp_hdcp *hdcp = container_of(work, -+ struct cdns_mhdp_hdcp, prop_work); -+ struct cdns_mhdp_device *mhdp = container_of(hdcp, -+ struct cdns_mhdp_device, hdcp); -+ -+ struct drm_device *dev = mhdp->drm_dev; -+ struct drm_connector_state *state; -+ -+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); -+ mutex_lock(&mhdp->hdcp.mutex); -+ -+ /* -+ * This worker is only used to flip between ENABLED/DESIRED. Either of -+ * those to UNDESIRED is handled by core. If hdcp_value == UNDESIRED, -+ * we're running just after hdcp has been disabled, so just exit -+ */ -+ if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { -+ state = mhdp->connector.base.state; -+ state->content_protection = mhdp->hdcp.value; -+ } -+ -+ mutex_unlock(&mhdp->hdcp.mutex); -+ drm_modeset_unlock(&dev->mode_config.connection_mutex); -+} -+ -+static void show_hdcp_supported(struct cdns_mhdp_device *mhdp) -+{ -+ if ((mhdp->hdcp.config & (HDCP_CONFIG_1_4 | HDCP_CONFIG_2_2)) == -+ (HDCP_CONFIG_1_4 | HDCP_CONFIG_2_2)) -+ DRM_INFO("Both HDCP 1.4 and 2 2 are enabled\n"); -+ else if (mhdp->hdcp.config & HDCP_CONFIG_1_4) -+ DRM_INFO("Only HDCP 1.4 is enabled\n"); -+ else if (mhdp->hdcp.config & HDCP_CONFIG_2_2) -+ DRM_INFO("Only HDCP 2.2 is enabled\n"); -+ else -+ DRM_INFO("HDCP is disabled\n"); -+} -+ -+#ifdef DEBUG -+void hdmi_hdcp_show_pairing(struct cdns_mhdp_device *mhdp, struct hdcp_trans_pairing_data *p) -+{ -+ char s[80]; -+ int i, k; -+ -+ DRM_INFO("Reveiver ID: %.2X%.2X%.2X%.2X%.2X\n", -+ p->receiver_id[0], -+ p->receiver_id[1], -+ p->receiver_id[2], -+ p->receiver_id[3], -+ p->receiver_id[4]); -+ for (k = 0, i = 0; k < 16; k++) -+ i += snprintf(&s[i], sizeof(s), "%02x", p->m[k]); -+ -+ DRM_INFO("\tm: %s\n", s); -+ -+ for (k = 0, i = 0; k < 16; k++) -+ i += snprintf(&s[i], sizeof(s), "%02x", p->km[k]); -+ -+ DRM_INFO("\tkm: %s\n", s); -+ -+ for (k = 0, i = 0; k < 16; k++) -+ i += snprintf(&s[i], sizeof(s), "%02x", p->ekh[k]); -+ -+ DRM_INFO("\tekh: %s\n", s); -+} -+#endif -+ -+void hdmi_hdcp_dump_pairing(struct seq_file *s, void *data) -+{ -+ struct cdns_mhdp_device *mhdp = data; -+#ifdef DEBUG -+ int i; -+ for (i = 0; i < mhdp->hdcp.num_paired; i++) -+ hdmi_hdcp_show_pairing(mhdp, &mhdp->hdcp.pairing[i]); -+#endif -+ seq_write(s, &mhdp->hdcp.pairing[0], -+ mhdp->hdcp.num_paired * sizeof(struct hdcp_trans_pairing_data)); -+} -+ -+static int hdmi_hdcp_pairing_show(struct seq_file *s, void *data) -+{ -+ hdmi_hdcp_dump_pairing(s, s->private); -+ return 0; -+} -+ -+static int hdmi_hdcp_dump_pairing_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, hdmi_hdcp_pairing_show, inode->i_private); -+} -+ -+static const struct file_operations hdmi_hdcp_dump_fops = { -+ .open = hdmi_hdcp_dump_pairing_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static void hdmi_hdcp_debugfs_init(struct cdns_mhdp_device *mhdp) -+{ -+ struct dentry *d, *root; -+ -+ root = debugfs_create_dir("imx-hdcp", NULL); -+ if (IS_ERR(root) || !root) -+ goto err; -+ -+ d = debugfs_create_file("dump_pairing", 0444, root, mhdp, -+ &hdmi_hdcp_dump_fops); -+ if (!d) -+ goto err; -+ return; -+ -+err: -+ dev_err(mhdp->dev, "Unable to create debugfs entries\n"); -+} -+ -+int cdns_hdmi_hdcp_init(struct cdns_mhdp_device *mhdp, struct device_node *of_node) -+{ -+ const char *compat; -+ u32 temp; -+ int ret; -+ -+ ret = of_property_read_string(of_node, "compatible", &compat); -+ if (ret) { -+ DRM_ERROR("Failed to compatible dts string\n"); -+ return ret; -+ } -+ if (!strstr(compat, "hdmi")) -+ return -EPERM; -+ -+ ret = of_property_read_u32(of_node, "hdcp-config", &temp); -+ if (ret) { -+ /* using highest level by default */ -+ mhdp->hdcp.config = HDCP_CONFIG_2_2; -+ DRM_INFO("Failed to get HDCP config - using HDCP 2.2 only\n"); -+ } else { -+ mhdp->hdcp.config = temp; -+ show_hdcp_supported(mhdp); -+ } -+ -+ hdmi_hdcp_debugfs_init(mhdp); -+ -+#ifdef USE_DEBUG_KEYS /* reserve for hdcp test key */ -+ { -+ u8 hdcp_cfg; -+ hdcp_cfg = HDCP_TX_2 | (HDCP_USE_KMKEY << 4) | (HDCP_CONTENT_TYPE_0 << 3); -+ imx_hdmi_load_test_keys(mhdp, &hdcp_cfg); -+ } -+#endif -+ -+ mhdp->hdcp.state = HDCP_STATE_INACTIVE; -+ -+ mutex_init(&mhdp->hdcp.mutex); -+ INIT_DELAYED_WORK(&mhdp->hdcp.check_work, hdmi_hdcp_check_work); -+ INIT_WORK(&mhdp->hdcp.prop_work, hdmi_hdcp_prop_work); -+ -+ return 0; -+} -+ -+int cdns_hdmi_hdcp_enable(struct cdns_mhdp_device *mhdp) -+{ -+ int ret = 0; -+ -+ mhdp->hdcp.reauth_in_progress = 0; -+ -+#ifdef STORE_PAIRING -+ hdmi_hdcp_get_stored_pairing(mhdp); -+#endif -+ msleep(500); -+ -+ mutex_lock(&mhdp->hdcp.mutex); -+ -+ mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED; -+ mhdp->hdcp.state = HDCP_STATE_ENABLING; -+ mhdp->hdcp.cancel = 0; -+ -+ schedule_work(&mhdp->hdcp.prop_work); -+ schedule_delayed_work(&mhdp->hdcp.check_work, 50); -+ -+ mutex_unlock(&mhdp->hdcp.mutex); -+ -+ return ret; -+} -+ -+int cdns_hdmi_hdcp_disable(struct cdns_mhdp_device *mhdp) -+{ -+ int ret = 0; -+ -+ mutex_lock(&mhdp->hdcp.mutex); -+ if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { -+ mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED; -+ mhdp->hdcp.state = HDCP_STATE_DISABLING; -+ mhdp->hdcp.cancel = 1; -+ schedule_work(&mhdp->hdcp.prop_work); -+ } -+ -+ mutex_unlock(&mhdp->hdcp.mutex); -+ -+ cancel_delayed_work_sync(&mhdp->hdcp.check_work); -+ -+ return ret; -+} -+ -+void cdns_hdmi_hdcp_atomic_check(struct drm_connector *connector, -+ struct drm_connector_state *old_state, -+ struct drm_connector_state *new_state) -+{ -+ u64 old_cp = old_state->content_protection; -+ u64 new_cp = new_state->content_protection; -+ struct drm_crtc_state *crtc_state; -+ -+ if (!new_state->crtc) { -+ /* -+ * If the connector is being disabled with CP enabled, mark it -+ * desired so it's re-enabled when the connector is brought back -+ */ -+ if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED) -+ new_state->content_protection = -+ DRM_MODE_CONTENT_PROTECTION_DESIRED; -+ return; -+ } -+ -+ /* -+ * Nothing to do if the state didn't change, or HDCP was activated since -+ * the last commit -+ */ -+ if (old_cp == new_cp || -+ (old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED && -+ new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)) -+ return; -+ -+ crtc_state = drm_atomic_get_new_crtc_state(new_state->state, new_state->crtc); -+ crtc_state->mode_changed = true; -+} -+ -+static int hdmi_hdcp_check_link(struct cdns_mhdp_device *mhdp) -+{ -+ u16 hdcp_port_status = 0; -+ u8 hdcp_last_error = 0; -+ u8 hpd_sts; -+ int ret = 0; -+ -+ mhdp->hdcp.reauth_in_progress = 0; -+ mutex_lock(&mhdp->lock); -+ -+ if ((mhdp->hdcp.state == HDCP_STATE_AUTHENTICATED) || -+ (mhdp->hdcp.state == HDCP_STATE_AUTHENTICATING) || -+ (mhdp->hdcp.state == HDCP_STATE_REAUTHENTICATING) || -+ (mhdp->hdcp.state == HDCP_STATE_ENABLING)) { -+ -+ /* In active states, check the HPD signal. Because of the IRQ -+ * debounce delay, the state might not reflect the disconnection. -+ * The FW could already have detected the HDP down and reported error */ -+ hpd_sts = cdns_mhdp_read_hpd(mhdp); -+ if (1 != hpd_sts) -+ mhdp->hdcp.state = HDCP_STATE_DISABLING; -+ } -+ -+ if (mhdp->hdcp.state == HDCP_STATE_INACTIVE) -+ goto out; -+ -+ if (mhdp->hdcp.state == HDCP_STATE_DISABLING) { -+ _hdmi_hdcp_disable(mhdp); -+ mhdp->hdcp.state = HDCP_STATE_INACTIVE; -+ goto out; -+ } -+ -+/* TODO items: -+ Need to make sure that any requests from the firmware are actually -+ processed so want to remove this first jump to 'out', i.e. process -+ reauthentication requests, cleanup errors and repeater receiver id -+ checks. -+*/ -+ if (mhdp->hdcp.state == HDCP_STATE_AUTHENTICATED) { -+ /* get port status */ -+ hdcp_port_status = hdmi_hdcp_get_status(mhdp); -+ hdcp_last_error = GET_HDCP_PORT_STS_LAST_ERR(hdcp_port_status); -+ if (hdcp_last_error == HDCP_TRAN_ERR_REAUTH_REQ) { -+ DRM_INFO("Sink requesting re-authentication\n"); -+ mhdp->hdcp.state = HDCP_STATE_REAUTHENTICATING; -+ } else if (hdcp_last_error) { -+ DRM_ERROR("HDCP error no: %u\n", hdcp_last_error); -+ -+ if (mhdp->hdcp.value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED) -+ goto out; -+ if (hdcp_port_status & HDCP_PORT_STS_AUTH) { -+ if (mhdp->hdcp.value != -+ DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { -+ mhdp->hdcp.value = -+ DRM_MODE_CONTENT_PROTECTION_ENABLED; -+ schedule_work(&mhdp->hdcp.prop_work); -+ goto out; -+ } -+ } -+ -+ mhdp->hdcp.state = HDCP_STATE_AUTH_FAILED; -+ -+ } else if (mhdp->hdcp.sink_is_repeater) { -+ u8 new_events; -+ /* Check events... and process if HDCPTX_IS_RECEIVER_ID_VALID_EVENT. */ -+ new_events = cdns_mhdp_get_event(mhdp); -+ mhdp->hdcp.events |= new_events; -+ if (check_event(mhdp->hdcp.events, HDCPTX_IS_RECEIVER_ID_VALID_EVENT)) { -+ DRM_INFO("Sink repeater updating receiver ID list...\n"); -+ if (hdmi_hdcp_check_receviers(mhdp)) -+ mhdp->hdcp.state = HDCP_STATE_AUTH_FAILED; -+ } -+ } -+ } -+ -+ if (mhdp->hdcp.state == HDCP_STATE_REAUTHENTICATING) { -+ /* For now just deal with HDCP2.2 */ -+ if (mhdp->hdcp.hdcp_version == HDCP_TX_2) -+ mhdp->hdcp.reauth_in_progress = 1; -+ else -+ mhdp->hdcp.state = HDCP_STATE_AUTH_FAILED; -+ } -+ -+ if (mhdp->hdcp.state == HDCP_STATE_ENABLING) { -+ mhdp->hdcp.state = HDCP_STATE_AUTHENTICATING; -+ ret = _hdmi_hdcp_enable(mhdp); -+ if (ret == -ECANCELED) -+ goto out; -+ else if (ret) { -+ DRM_ERROR("Failed to enable hdcp (%d)\n", ret); -+ mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED; -+ schedule_work(&mhdp->hdcp.prop_work); -+ goto out; -+ } -+ } -+ -+ if ((mhdp->hdcp.state == HDCP_STATE_AUTH_FAILED) || -+ (mhdp->hdcp.state == HDCP_STATE_REAUTHENTICATING)) { -+ -+ print_port_status(hdcp_port_status); -+ if (mhdp->hdcp.state == HDCP_STATE_AUTH_FAILED) { -+ DRM_DEBUG_KMS("[%s:%d] HDCP link failed, retrying authentication 0x%2x\n", -+ mhdp->connector.base.name, mhdp->connector.base.base.id, hdcp_port_status); -+ ret = _hdmi_hdcp_disable(mhdp); -+ if (ret) { -+ DRM_ERROR("Failed to disable hdcp (%d)\n", ret); -+ mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED; -+ schedule_work(&mhdp->hdcp.prop_work); -+ goto out; -+ } -+ } else -+ DRM_DEBUG_KMS("[%s:%d] HDCP attempt reauthentication 0x%2x\n", -+ mhdp->connector.base.name, mhdp->connector.base.base.id, hdcp_port_status); -+ -+ ret = _hdmi_hdcp_enable(mhdp); -+ if (ret == -ECANCELED) -+ goto out; -+ else if (ret) { -+ DRM_ERROR("Failed to enable hdcp (%d)\n", ret); -+ mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED; -+ schedule_work(&mhdp->hdcp.prop_work); -+ goto out; -+ } -+ } -+ -+out: -+ mutex_unlock(&mhdp->lock); -+ -+ return ret; -+} -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.c -new file mode 100644 -index 000000000000..587c5f953489 ---- /dev/null -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.c -@@ -0,0 +1,300 @@ -+/* -+ * Cadence HDCP API driver -+ * -+ * Copyright (C) 2021 NXP Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+ -+#include "cdns-mhdp.h" -+ -+static u32 mhdp_hdcp_bus_read(struct cdns_mhdp_device *mhdp, u32 offset) -+{ -+ u32 val; -+ -+ mutex_lock(&mhdp->iolock); -+ -+ if (mhdp->bus_type == BUS_TYPE_LOW4K_APB) { -+ /* Remap address to low 4K APB bus */ -+ writel(offset >> 12, mhdp->regs_sec + 8); -+ val = readl((offset & 0xfff) + mhdp->regs_base); -+ } else if (mhdp->bus_type == BUS_TYPE_NORMAL_APB) -+ val = readl(mhdp->regs_sec + offset); -+ -+ mutex_unlock(&mhdp->iolock); -+ -+ return val; -+} -+ -+static void mhdp_hdcp_bus_write(u32 val, struct cdns_mhdp_device *mhdp, u32 offset) -+{ -+ mutex_lock(&mhdp->iolock); -+ -+ if (mhdp->bus_type == BUS_TYPE_LOW4K_APB) { -+ /* Remap address to low 4K APB bus */ -+ writel(offset >> 12, mhdp->regs_sec + 8); -+ writel(val, (offset & 0xfff) + mhdp->regs_base); -+ } else if (mhdp->bus_type == BUS_TYPE_NORMAL_APB) -+ writel(val, mhdp->regs_sec + offset); -+ -+ mutex_unlock(&mhdp->iolock); -+} -+ -+static int mhdp_hdcp_mailbox_read(struct cdns_mhdp_device *mhdp) -+{ -+ int val, ret; -+ -+ ret = mhdp_readx_poll_timeout(mhdp_hdcp_bus_read, mhdp, MAILBOX_EMPTY_ADDR, -+ val, !val, MAILBOX_RETRY_US, -+ MAILBOX_TIMEOUT_US); -+ if (ret < 0) -+ return ret; -+ -+ return mhdp_hdcp_bus_read(mhdp, MAILBOX0_RD_DATA) & 0xff; -+} -+ -+static int mhdp_hdcp_mailbox_write(struct cdns_mhdp_device *mhdp, u8 val) -+{ -+ int ret, full; -+ -+ ret = mhdp_readx_poll_timeout(mhdp_hdcp_bus_read, mhdp, MAILBOX_FULL_ADDR, -+ full, !full, MAILBOX_RETRY_US, -+ MAILBOX_TIMEOUT_US); -+ if (ret < 0) -+ return ret; -+ -+ mhdp_hdcp_bus_write(val, mhdp, MAILBOX0_WR_DATA); -+ -+ return 0; -+} -+ -+static int mhdp_hdcp_mailbox_validate_receive(struct cdns_mhdp_device *mhdp, -+ u8 module_id, u8 opcode, u16 req_size) -+{ -+ u32 mbox_size, i; -+ u8 header[4]; -+ int ret; -+ -+ /* read the header of the message */ -+ for (i = 0; i < 4; i++) { -+ ret = mhdp_hdcp_mailbox_read(mhdp); -+ if (ret < 0) -+ return ret; -+ -+ header[i] = ret; -+ } -+ -+ mbox_size = get_unaligned_be16(header + 2); -+ -+ if (opcode != header[0] || module_id != header[1] || -+ req_size != mbox_size) { -+ /* -+ * If the message in mailbox is not what we want, we need to -+ * clear the mailbox by reading its contents. -+ */ -+ for (i = 0; i < mbox_size; i++) -+ if (mhdp_hdcp_mailbox_read(mhdp) < 0) -+ break; -+ -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int mhdp_hdcp_mailbox_read_receive(struct cdns_mhdp_device *mhdp, -+ u8 *buff, u16 buff_size) -+{ -+ u32 i; -+ int ret; -+ -+ for (i = 0; i < buff_size; i++) { -+ ret = mhdp_hdcp_mailbox_read(mhdp); -+ if (ret < 0) -+ return ret; -+ -+ buff[i] = ret; -+ } -+ -+ return 0; -+} -+ -+static int mhdp_hdcp_mailbox_send(struct cdns_mhdp_device *mhdp, u8 module_id, -+ u8 opcode, u16 size, u8 *message) -+{ -+ u8 header[4]; -+ int ret, i; -+ -+ header[0] = opcode; -+ header[1] = module_id; -+ put_unaligned_be16(size, header + 2); -+ -+ for (i = 0; i < 4; i++) { -+ ret = mhdp_hdcp_mailbox_write(mhdp, header[i]); -+ if (ret) -+ return ret; -+ } -+ -+ for (i = 0; i < size; i++) { -+ ret = mhdp_hdcp_mailbox_write(mhdp, message[i]); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+/* HDCP API */ -+int cdns_mhdp_hdcp_tx_config(struct cdns_mhdp_device *mhdp, u8 config) -+{ -+ return mhdp_hdcp_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, -+ HDCP_TX_CONFIGURATION, sizeof(config), &config); -+} -+EXPORT_SYMBOL(cdns_mhdp_hdcp_tx_config); -+ -+int cdns_mhdp_hdcp2_tx_respond_km(struct cdns_mhdp_device *mhdp, -+ u8 *msg, u16 len) -+{ -+ return mhdp_hdcp_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, -+ HDCP2_TX_RESPOND_KM, len, msg); -+} -+EXPORT_SYMBOL(cdns_mhdp_hdcp2_tx_respond_km); -+ -+int cdns_mhdp_hdcp_tx_status_req(struct cdns_mhdp_device *mhdp, -+ u8 *status, u16 len) -+{ -+ int ret; -+ -+ ret = mhdp_hdcp_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, -+ HDCP_TX_STATUS_CHANGE, 0, NULL); -+ if (ret) -+ goto err_tx_req; -+ -+ ret = mhdp_hdcp_mailbox_validate_receive(mhdp, MB_MODULE_ID_HDCP_TX, -+ HDCP_TX_STATUS_CHANGE, len); -+ if (ret) -+ goto err_tx_req; -+ -+ ret = mhdp_hdcp_mailbox_read_receive(mhdp, status, len); -+ if (ret) -+ goto err_tx_req; -+ -+err_tx_req: -+ if (ret) -+ DRM_ERROR("hdcp tx status req failed: %d\n", ret); -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_hdcp_tx_status_req); -+ -+int cdns_mhdp_hdcp2_tx_is_km_stored_req(struct cdns_mhdp_device *mhdp, u8 *data, u16 len) -+{ -+ int ret; -+ -+ ret = mhdp_hdcp_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, -+ HDCP2_TX_IS_KM_STORED, 0, NULL); -+ if (ret) -+ goto err_is_km; -+ -+ ret = mhdp_hdcp_mailbox_validate_receive(mhdp, MB_MODULE_ID_HDCP_TX, -+ HDCP2_TX_IS_KM_STORED, len); -+ if (ret) -+ goto err_is_km; -+ -+ ret = mhdp_hdcp_mailbox_read_receive(mhdp, data, len); -+ -+err_is_km: -+ if (ret) -+ DRM_ERROR("hdcp2 tx is km stored req failed: %d\n", ret); -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_hdcp2_tx_is_km_stored_req); -+ -+int cdns_mhdp_hdcp2_tx_store_km(struct cdns_mhdp_device *mhdp, -+ u8 *resp, u16 len) -+{ -+ int ret; -+ -+ ret = mhdp_hdcp_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, -+ HDCP2_TX_STORE_KM, 0, NULL); -+ if (ret) -+ goto err_store_km; -+ -+ ret = mhdp_hdcp_mailbox_validate_receive(mhdp, MB_MODULE_ID_HDCP_TX, -+ HDCP2_TX_STORE_KM, len); -+ if (ret) -+ goto err_store_km; -+ -+ ret = mhdp_hdcp_mailbox_read_receive(mhdp, resp, len); -+ -+err_store_km: -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_hdcp2_tx_store_km); -+ -+int cdns_mhdp_hdcp_tx_is_receiver_id_valid(struct cdns_mhdp_device *mhdp, -+ u8 *rx_id, u8 *num) -+{ -+ u32 mbox_size, i; -+ u8 header[4]; -+ u8 temp; -+ int ret; -+ -+ ret = mhdp_hdcp_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, -+ HDCP_TX_IS_RECEIVER_ID_VALID, 0, NULL); -+ if (ret) -+ goto err_rx_id; -+ -+ /* read the header of the message */ -+ for (i = 0; i < 4; i++) { -+ ret = mhdp_hdcp_mailbox_read(mhdp); -+ if (ret < 0) -+ return ret; -+ -+ header[i] = ret; -+ } -+ -+ mbox_size = get_unaligned_be16(header + 2); -+ -+ if (HDCP_TX_IS_RECEIVER_ID_VALID != header[0] || -+ MB_MODULE_ID_HDCP_TX != header[1]) -+ return -EINVAL; -+ -+ /* First get num of receivers */ -+ ret = mhdp_hdcp_mailbox_read_receive(mhdp, num, 1); -+ if (ret) -+ goto err_rx_id; -+ -+ /* skip second data */ -+ ret = mhdp_hdcp_mailbox_read_receive(mhdp, &temp, 1); -+ if (ret) -+ goto err_rx_id; -+ -+ /* get receivers ID */ -+ ret = mhdp_hdcp_mailbox_read_receive(mhdp, rx_id, mbox_size - 2); -+ -+err_rx_id: -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_hdcp_tx_is_receiver_id_valid); -+ -+int cdns_mhdp_hdcp_tx_respond_receiver_id_valid( -+ struct cdns_mhdp_device *mhdp, u8 val) -+{ -+ return mhdp_hdcp_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, -+ HDCP_TX_RESPOND_RECEIVER_ID_VALID, sizeof(val), &val); -+} -+EXPORT_SYMBOL(cdns_mhdp_hdcp_tx_respond_receiver_id_valid); -+ -+int cdns_mhdp_hdcp_tx_reauth(struct cdns_mhdp_device *mhdp, u8 msg) -+{ -+ return mhdp_hdcp_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, -+ HDCP_TX_DO_AUTH_REQ, sizeof(msg), &msg); -+} -+EXPORT_SYMBOL(cdns_mhdp_hdcp_tx_reauth); -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.h -new file mode 100644 -index 000000000000..4ce76dd1ee58 ---- /dev/null -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.h -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) 2021 NXP Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ */ -+ -+#ifndef CDNS_HDMI_HDCP_H -+#define CDNS_HDMI_HDCP_H -+ -+int cdns_mhdp_hdcp2_tx_respond_km(struct cdns_mhdp_device *mhdp, -+ u8 *msg, u16 len); -+int cdns_mhdp_hdcp_tx_config(struct cdns_mhdp_device *mhdp, u8 config); -+int cdns_mhdp_hdcp_tx_status_req(struct cdns_mhdp_device *mhdp, -+ u8 *status, u16 len); -+int cdns_mhdp_hdcp2_tx_is_km_stored_req(struct cdns_mhdp_device *mhdp, u8 *data, u16 len); -+int cdns_mhdp_hdcp2_tx_store_km(struct cdns_mhdp_device *mhdp, -+ u8 *reg, u16 len); -+int cdns_mhdp_hdcp_tx_is_receiver_id_valid(struct cdns_mhdp_device *mhdp, -+ u8 *rx_id, u8 *num); -+int cdns_mhdp_hdcp_tx_respond_receiver_id_valid(struct cdns_mhdp_device *mhdp, -+ u8 val); -+int cdns_mhdp_hdcp_tx_test_keys(struct cdns_mhdp_device *mhdp, u8 type, u8 resp); -+int cdns_mhdp_hdcp_tx_reauth(struct cdns_mhdp_device *mhdp, u8 msg); -+ -+int cdns_hdmi_hdcp_init(struct cdns_mhdp_device *mhdp, struct device_node *of_node); -+int cdns_hdmi_hdcp_enable(struct cdns_mhdp_device *mhdp); -+int cdns_hdmi_hdcp_disable(struct cdns_mhdp_device *mhdp); -+void cdns_hdmi_hdcp_atomic_check(struct drm_connector *connector, -+ struct drm_connector_state *old_state, -+ struct drm_connector_state *new_state); -+ -+#endif /* CDNS_HDMI_HDCP_H */ -diff --git a/include/drm/bridge/cdns-mhdp.h b/include/drm/bridge/cdns-mhdp.h -index 338fa55b8bdf..5752c47b1a16 100644 ---- a/include/drm/bridge/cdns-mhdp.h -+++ b/include/drm/bridge/cdns-mhdp.h -@@ -388,6 +388,27 @@ - #define HDMI_TX_TEST 0xBB - #define HDMI_TX_EDID_INTERNAL 0xF0 - -+/* HDCP General opcode */ -+#define HDCP_GENERAL_SET_LC_128 0x00 -+#define HDCP_GENERAL_SET_SEED 0x01 -+ -+/* HDCP TX opcode */ -+#define HDCP_TX_CONFIGURATION 0x00 -+#define HDCP2_TX_SET_PUBLIC_KEY_PARAMS 0x01 -+#define HDCP2_TX_SET_DEBUG_RANDOM_NUMBERS 0x02 -+#define HDCP2_TX_RESPOND_KM 0x03 -+#define HDCP1_TX_SEND_KEYS 0x04 -+#define HDCP1_TX_SEND_RANDOM_AN 0x05 -+#define HDCP_TX_STATUS_CHANGE 0x06 -+#define HDCP2_TX_IS_KM_STORED 0x07 -+#define HDCP2_TX_STORE_KM 0x08 -+#define HDCP_TX_IS_RECEIVER_ID_VALID 0x09 -+#define HDCP_TX_RESPOND_RECEIVER_ID_VALID 0x0A -+#define HDCP_TX_TEST_KEYS 0x0B -+#define HDCP2_TX_SET_KM_KEY_PARAMS 0x0C -+#define HDCP_TX_SET_CP_IRQ 0x0D -+#define HDCP_TX_DO_AUTH_REQ 0x0E -+ - #define FW_STANDBY 0 - #define FW_ACTIVE 1 - -@@ -428,12 +449,16 @@ - #define EQ_PHASE_FAILED BIT(6) - #define FASE_LT_FAILED BIT(7) - --#define DPTX_HPD_EVENT BIT(0) --#define DPTX_TRAINING_EVENT BIT(1) --#define HDCP_TX_STATUS_EVENT BIT(4) --#define HDCP2_TX_IS_KM_STORED_EVENT BIT(5) --#define HDCP2_TX_STORE_KM_EVENT BIT(6) --#define HDCP_TX_IS_RECEIVER_ID_VALID_EVENT BIT(7) -+#define DPTX_HPD_EVENT BIT(0) -+#define HDMI_TX_HPD_EVENT BIT(0) -+#define HDMI_RX_5V_EVENT BIT(0) -+#define DPTX_TRAINING_EVENT BIT(1) -+#define HDMI_RX_SCDC_CHANGE_EVENT BIT(1) -+#define HDCPTX_STATUS_EVENT BIT(4) -+#define HDCPRX_STATUS_EVENT BIT(4) -+#define HDCPTX_IS_KM_STORED_EVENT BIT(5) -+#define HDCPTX_STORE_KM_EVENT BIT(6) -+#define HDCPTX_IS_RECEIVER_ID_VALID_EVENT BIT(7) - - #define TU_SIZE 30 - #define CDNS_DP_MAX_LINK_RATE 540000 -@@ -442,6 +467,7 @@ - #define F_VIF_DATA_WIDTH(x) (((x) & ((1 << 2) - 1)) << 2) - #define F_HDMI_MODE(x) (((x) & ((1 << 2) - 1)) << 0) - #define F_GCP_EN(x) (((x) & ((1 << 1) - 1)) << 12) -+#define F_CLEAR_AVMUTE(x) (((x) & ((1 << 1) - 1)) << 14) - #define F_DATA_EN(x) (((x) & ((1 << 1) - 1)) << 15) - #define F_HDMI2_PREAMBLE_EN(x) (((x) & ((1 << 1) - 1)) << 18) - #define F_PIC_3D(x) (((x) & ((1 << 4) - 1)) << 7) -@@ -662,6 +688,55 @@ struct cdns_plat_data { - char *plat_name; - }; - -+/* HDCP */ -+#define MAX_STORED_KM 64 -+#define HDCP_PAIRING_M_LEN 16 -+#define HDCP_PAIRING_M_EKH 16 -+#define HDCP_PAIRING_R_ID 5 -+ -+/* HDCP2_TX_SET_DEBUG_RANDOM_NUMBERS */ -+#define DEBUG_RANDOM_NUMBERS_KM_LEN 16 -+#define DEBUG_RANDOM_NUMBERS_RN_LEN 8 -+#define DEBUG_RANDOM_NUMBERS_KS_LEN 16 -+#define DEBUG_RANDOM_NUMBERS_RIV_LEN 8 -+#define DEBUG_RANDOM_NUMBERS_RTX_LEN 8 -+ -+struct hdcp_trans_pairing_data { -+ u8 receiver_id[HDCP_PAIRING_R_ID]; -+ u8 m[HDCP_PAIRING_M_LEN]; -+ u8 km[DEBUG_RANDOM_NUMBERS_KM_LEN]; -+ u8 ekh[HDCP_PAIRING_M_EKH]; -+}; -+ -+enum hdmi_hdcp_state { -+ HDCP_STATE_NO_AKSV, -+ HDCP_STATE_INACTIVE, -+ HDCP_STATE_ENABLING, -+ HDCP_STATE_AUTHENTICATING, -+ HDCP_STATE_REAUTHENTICATING, -+ HDCP_STATE_AUTHENTICATED, -+ HDCP_STATE_DISABLING, -+ HDCP_STATE_AUTH_FAILED -+}; -+ -+struct cdns_mhdp_hdcp { -+ struct mutex mutex; -+ u64 value; /* protected by hdcp_mutex */ -+ struct delayed_work check_work; -+ struct work_struct prop_work; -+ u8 state; -+ u8 cancel; -+ u8 bus_type; -+ u8 config; -+ struct hdcp_trans_pairing_data pairing[MAX_STORED_KM]; -+ u8 num_paired; -+ -+ u8 events; -+ u8 sink_is_repeater; -+ u8 reauth_in_progress; -+ u8 hdcp_version; -+}; -+ - struct cdns_mhdp_device { - void __iomem *regs_base; - void __iomem *regs_sec; -@@ -669,6 +744,7 @@ struct cdns_mhdp_device { - int bus_type; - - struct device *dev; -+ struct drm_device *drm_dev; - - struct cdns_mhdp_connector connector; - struct clk *spdif_clk; -@@ -722,6 +798,7 @@ struct cdns_mhdp_device { - hdmi_codec_plugged_cb plugged_cb; - struct device *codec_dev; - enum drm_connector_status last_connector_result; -+ struct cdns_mhdp_hdcp hdcp; - }; - - u32 cdns_mhdp_bus_read(struct cdns_mhdp_device *mhdp, u32 offset); -@@ -742,6 +819,7 @@ int cdns_mhdp_get_edid_block(void *mhdp, u8 *edid, - int cdns_mhdp_train_link(struct cdns_mhdp_device *mhdp); - int cdns_mhdp_set_video_status(struct cdns_mhdp_device *mhdp, int active); - int cdns_mhdp_config_video(struct cdns_mhdp_device *mhdp); -+int cdns_mhdp_apb_conf(struct cdns_mhdp_device *mhdp, u8 sel); - - /* Audio */ - int cdns_mhdp_audio_stop(struct cdns_mhdp_device *mhdp, -@@ -770,8 +848,6 @@ int cdns_mhdp_mailbox_read_receive(struct cdns_mhdp_device *mhdp, - int cdns_mhdp_mailbox_validate_receive(struct cdns_mhdp_device *mhdp, - u8 module_id, u8 opcode, - u16 req_size); --int cdns_mhdp_mailbox_read(struct cdns_mhdp_device *mhdp); -- - void cdns_mhdp_infoframe_set(struct cdns_mhdp_device *mhdp, - u8 entry_id, u8 packet_len, u8 *packet, u8 packet_type); - int cdns_hdmi_get_edid_block(void *data, u8 *edid, u32 block, size_t length); --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0021-LF-3272-drm-cdns_mhdp-fix-Coverity-Issue-11566406.patch b/projects/NXP/devices/iMX8/patches/linux/0021-LF-3272-drm-cdns_mhdp-fix-Coverity-Issue-11566406.patch deleted file mode 100644 index bf124e8f71..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0021-LF-3272-drm-cdns_mhdp-fix-Coverity-Issue-11566406.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 2a093769a29f03103195b34c269411ee21b646e2 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Wed, 20 Jan 2021 10:37:09 +0800 -Subject: [PATCH 21/49] LF-3272: drm: cdns_mhdp: fix Coverity Issue: 11566406 - -Add default access hdcp bus to fix -Coverity Issue: 11566406 Uninitialized scalar variable. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.c -index 587c5f953489..b3c931382013 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-hdcp.c -@@ -27,6 +27,8 @@ static u32 mhdp_hdcp_bus_read(struct cdns_mhdp_device *mhdp, u32 offset) - val = readl((offset & 0xfff) + mhdp->regs_base); - } else if (mhdp->bus_type == BUS_TYPE_NORMAL_APB) - val = readl(mhdp->regs_sec + offset); -+ else -+ val = readl(mhdp->regs_base + offset); - - mutex_unlock(&mhdp->iolock); - --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0022-LF-3271-drm-cdns-hdmi-fix-Coverity-Issue-11566407.patch b/projects/NXP/devices/iMX8/patches/linux/0022-LF-3271-drm-cdns-hdmi-fix-Coverity-Issue-11566407.patch deleted file mode 100644 index af85c51c9d..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0022-LF-3271-drm-cdns-hdmi-fix-Coverity-Issue-11566407.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 85ad1a878118a8dbaf9da5f85a2e088880d5ea01 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Wed, 20 Jan 2021 10:44:17 +0800 -Subject: [PATCH 22/49] LF-3271: drm: cdns-hdmi: fix Coverity Issue: 11566407 - -Delete dead code to fix Coverity Issue: 11566407. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index dc393f6b75e7..a89c8cba4788 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -150,7 +150,6 @@ ssize_t HDCPTX_Status_store(struct device *dev, - else - dev_err(dev, "%s &hdp->state invalid\n", __func__); - return -1; -- return count; - } - - static void hdmi_sink_config(struct cdns_mhdp_device *mhdp) --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0023-LF-3270-drm-cdns-hdmi-fix-coverity-Issue-11566405.patch b/projects/NXP/devices/iMX8/patches/linux/0023-LF-3270-drm-cdns-hdmi-fix-coverity-Issue-11566405.patch deleted file mode 100644 index 2ece85029d..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0023-LF-3270-drm-cdns-hdmi-fix-coverity-Issue-11566405.patch +++ /dev/null @@ -1,40 +0,0 @@ -From ddfa5aeb97c12fb7a67e6507ef2ae051658f112b Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Wed, 20 Jan 2021 10:49:13 +0800 -Subject: [PATCH 23/49] LF-3270: drm: cdns-hdmi: fix coverity Issue: 11566405 - -Delete unused code to fix coverity Issue: 11566405. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index a89c8cba4788..2300c3d8a91d 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -37,17 +37,15 @@ static struct device_attribute HDCPTX_do_reauth = __ATTR_WO(HDCPTX_do_reauth); - static ssize_t HDCPTX_do_reauth_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) - { -- int value, ret; -+ int ret; - struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); - - ret = cdns_mhdp_hdcp_tx_reauth(mhdp, 1); -- -- sscanf(buf, "%d", &value); -- - if (ret < 0) { - dev_err(dev, "%s cdns_mhdp_hdcp_tx_reauth failed\n", __func__); - return -1; - } -+ - return count; - } - --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0024-LF-3269-drm-cdns-hdmi-fix-coverity-Issue-11566404.patch b/projects/NXP/devices/iMX8/patches/linux/0024-LF-3269-drm-cdns-hdmi-fix-coverity-Issue-11566404.patch deleted file mode 100644 index 1395849b6f..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0024-LF-3269-drm-cdns-hdmi-fix-coverity-Issue-11566404.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 2812d071eb348d903620f7ebadaf848024b3c672 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Wed, 20 Jan 2021 11:04:41 +0800 -Subject: [PATCH 24/49] LF-3269: drm: cdns-hdmi: fix coverity Issue: 11566404 - -Check return value to fix coverity Issue: 11566404. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index 2300c3d8a91d..df8ac87b3a54 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -59,9 +59,12 @@ static ssize_t HDCPTX_Version_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) - { - struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -- int value; -+ int value, ret; -+ -+ ret = sscanf(buf, "%d", &value); -+ if (ret != 1) -+ return -EINVAL; - -- sscanf(buf, "%d", &value); - if (value == 2) - mhdp->hdcp.config = 2; - else if (value == 1) --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0025-LF-3268-drm-cdns-hdmi-fix-Coverity-Issue-11566403.patch b/projects/NXP/devices/iMX8/patches/linux/0025-LF-3268-drm-cdns-hdmi-fix-Coverity-Issue-11566403.patch deleted file mode 100644 index 0a3c6444ab..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0025-LF-3268-drm-cdns-hdmi-fix-Coverity-Issue-11566403.patch +++ /dev/null @@ -1,36 +0,0 @@ -From cd49375db5c05acb824fa18ae9d19290073cda08 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Wed, 20 Jan 2021 11:07:32 +0800 -Subject: [PATCH 25/49] LF-3268: drm: cdns-hdmi: fix Coverity Issue: 11566403 - -Check return value to fix Coverity Issue: 11566403. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -index df8ac87b3a54..28193178140f 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -119,10 +119,13 @@ ssize_t HDCPTX_Status_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) - { - struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -- int value; -+ int value, ret; - - if (count == 2) { -- sscanf(buf, "%d", &value); -+ ret = sscanf(buf, "%d", &value); -+ if (ret != 1) -+ return -EINVAL; -+ - if ((value >= HDCP_STATE_NO_AKSV) && (value <= HDCP_STATE_AUTH_FAILED)) { - mhdp->hdcp.state = value; - return count; --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0026-LF-3367-1-drm-cdns_hdmi-HDCP_STATE_DISABLING-may-mis.patch b/projects/NXP/devices/iMX8/patches/linux/0026-LF-3367-1-drm-cdns_hdmi-HDCP_STATE_DISABLING-may-mis.patch deleted file mode 100644 index 774398207e..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0026-LF-3367-1-drm-cdns_hdmi-HDCP_STATE_DISABLING-may-mis.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 54a5d4d3ba2de923fa4a4e5ef5e90151fb7f2fd8 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Thu, 18 Feb 2021 16:25:52 +0800 -Subject: [PATCH 26/49] LF-3367-1: drm: cdns_hdmi: HDCP_STATE_DISABLING may - missed by check link - -Polling thread check_work is designed to handle all hdcp state change. -In HDCP disable function, check_work thread will be stopped after -hdcp.state is set to HDCP_STATE_DISABLING. check_work thread may miss -the state change, call check link function make sure HDCP_STATE_DISABLING -state is properly handled. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai -Acked-by: Jason Liu ---- - drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c -index e2a3bc7fb42b..9119f2063098 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c -@@ -988,6 +988,8 @@ int cdns_hdmi_hdcp_disable(struct cdns_mhdp_device *mhdp) - { - int ret = 0; - -+ cancel_delayed_work_sync(&mhdp->hdcp.check_work); -+ - mutex_lock(&mhdp->hdcp.mutex); - if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { - mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED; -@@ -998,7 +1000,8 @@ int cdns_hdmi_hdcp_disable(struct cdns_mhdp_device *mhdp) - - mutex_unlock(&mhdp->hdcp.mutex); - -- cancel_delayed_work_sync(&mhdp->hdcp.check_work); -+ /* Make sure HDCP_STATE_DISABLING state is handled */ -+ hdmi_hdcp_check_link(mhdp); - - return ret; - } --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0027-LF-3367-2-drm-mhdp-more-time-for-FW-alive-check.patch b/projects/NXP/devices/iMX8/patches/linux/0027-LF-3367-2-drm-mhdp-more-time-for-FW-alive-check.patch deleted file mode 100644 index 9c39cf8250..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0027-LF-3367-2-drm-mhdp-more-time-for-FW-alive-check.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 42394af5975326eb20901d65eac47963847006e2 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Fri, 19 Feb 2021 16:41:31 +0800 -Subject: [PATCH 27/49] LF-3367-2: drm: mhdp: more time for FW alive check - -FW alive check function may return false in hdcp enable/disable stress test. -Add more time for FW alive check, make sure get correct state. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai -Acked-by: Jason Liu ---- - drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -index 2a8ab0872f25..3487a2fa335c 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -@@ -142,7 +142,7 @@ bool cdns_mhdp_check_alive(struct cdns_mhdp_device *mhdp) - alive = cdns_mhdp_bus_read(mhdp, KEEP_ALIVE); - - while (retries_left--) { -- udelay(2); -+ msleep(1); - - newalive = cdns_mhdp_bus_read(mhdp, KEEP_ALIVE); - if (alive == newalive) --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0028-LF-3367-3-drm-mhdp-hdcp-adjust-state-handle-priority.patch b/projects/NXP/devices/iMX8/patches/linux/0028-LF-3367-3-drm-mhdp-hdcp-adjust-state-handle-priority.patch deleted file mode 100644 index deeaae4375..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0028-LF-3367-3-drm-mhdp-hdcp-adjust-state-handle-priority.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 60f6b8c90766663303f6005468502798eb2b0f44 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Fri, 19 Feb 2021 17:53:54 +0800 -Subject: [PATCH 28/49] LF-3367-3: drm: mhdp-hdcp: adjust state handle priority - -Handle HDCP_STATE_INACTIVE and HDCP_STATE_DISABLING state priority -to avoid unnecessary HPD state check, drm has check it when hdcp -enable/disable. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai -Acked-by: Jason Liu ---- - .../gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c | 24 ++++++++++--------- - 1 file changed, 13 insertions(+), 11 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c -index 9119f2063098..5dfbd7943306 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c -@@ -1048,6 +1048,15 @@ static int hdmi_hdcp_check_link(struct cdns_mhdp_device *mhdp) - mhdp->hdcp.reauth_in_progress = 0; - mutex_lock(&mhdp->lock); - -+ if (mhdp->hdcp.state == HDCP_STATE_INACTIVE) -+ goto out; -+ -+ if (mhdp->hdcp.state == HDCP_STATE_DISABLING) { -+ _hdmi_hdcp_disable(mhdp); -+ mhdp->hdcp.state = HDCP_STATE_INACTIVE; -+ goto out; -+ } -+ - if ((mhdp->hdcp.state == HDCP_STATE_AUTHENTICATED) || - (mhdp->hdcp.state == HDCP_STATE_AUTHENTICATING) || - (mhdp->hdcp.state == HDCP_STATE_REAUTHENTICATING) || -@@ -1056,18 +1065,11 @@ static int hdmi_hdcp_check_link(struct cdns_mhdp_device *mhdp) - /* In active states, check the HPD signal. Because of the IRQ - * debounce delay, the state might not reflect the disconnection. - * The FW could already have detected the HDP down and reported error */ -- hpd_sts = cdns_mhdp_read_hpd(mhdp); -- if (1 != hpd_sts) -+ hpd_sts = cdns_mhdp_read_hpd(mhdp); -+ if (1 != hpd_sts) { - mhdp->hdcp.state = HDCP_STATE_DISABLING; -- } -- -- if (mhdp->hdcp.state == HDCP_STATE_INACTIVE) -- goto out; -- -- if (mhdp->hdcp.state == HDCP_STATE_DISABLING) { -- _hdmi_hdcp_disable(mhdp); -- mhdp->hdcp.state = HDCP_STATE_INACTIVE; -- goto out; -+ goto out; -+ } - } - - /* TODO items: --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0029-clk-imx8mq-add-27MHz-PHY-ref-clock.patch b/projects/NXP/devices/iMX8/patches/linux/0029-clk-imx8mq-add-27MHz-PHY-ref-clock.patch deleted file mode 100644 index 6175eb5148..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0029-clk-imx8mq-add-27MHz-PHY-ref-clock.patch +++ /dev/null @@ -1,42 +0,0 @@ -From afbe8e0ae318f407d64bbc48b784d93c782b6564 Mon Sep 17 00:00:00 2001 -From: Laurentiu Palcu -Date: Thu, 5 Sep 2019 13:07:22 +0300 -Subject: [PATCH 29/49] clk: imx8mq: add 27MHz PHY ref clock - -This clock is a high precision clock on imx8mq-evk board that will be used by -HDMI phy. - -Signed-off-by: Laurentiu Palcu ---- - drivers/clk/imx/clk-imx8mq.c | 3 ++- - include/dt-bindings/clock/imx8mq-clock.h | 4 +++- - 2 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c -index 06292d4a98ff..6bd2fe0ae71d 100644 ---- a/drivers/clk/imx/clk-imx8mq.c -+++ b/drivers/clk/imx/clk-imx8mq.c -@@ -304,6 +304,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) - hws[IMX8MQ_CLK_EXT2] = imx_get_clk_hw_by_name(np, "clk_ext2"); - hws[IMX8MQ_CLK_EXT3] = imx_get_clk_hw_by_name(np, "clk_ext3"); - hws[IMX8MQ_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4"); -+ hws[IMX8MQ_CLK_PHY_27MHZ] = imx_get_clk_hw_by_name(np, "hdmi_phy_27m"); - - np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-anatop"); - base = of_iomap(np, 0); -diff --git a/include/dt-bindings/clock/imx8mq-clock.h b/include/dt-bindings/clock/imx8mq-clock.h -index 9b8045d75b8b..2a81f96b7c74 100644 ---- a/include/dt-bindings/clock/imx8mq-clock.h -+++ b/include/dt-bindings/clock/imx8mq-clock.h -@@ -431,6 +431,7 @@ - #define IMX8MQ_CLK_MON_SEL 301 - #define IMX8MQ_CLK_MON_CLK2_OUT 302 -+#define IMX8MQ_CLK_PHY_27MHZ 303 - --#define IMX8MQ_CLK_END 303 -+#define IMX8MQ_CLK_END 304 - - #endif /* __DT_BINDINGS_CLOCK_IMX8MQ_H */ --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0030-drm-imx-Add-mhdp-dp-hdmi-driver-for-imx8x-platform.patch b/projects/NXP/devices/iMX8/patches/linux/0030-drm-imx-Add-mhdp-dp-hdmi-driver-for-imx8x-platform.patch deleted file mode 100644 index 2e4a4acb31..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0030-drm-imx-Add-mhdp-dp-hdmi-driver-for-imx8x-platform.patch +++ /dev/null @@ -1,2656 +0,0 @@ -From 09102ec28d08ae95d476ee241ed016d2fe9da894 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Mon, 20 Apr 2020 22:47:36 +0800 -Subject: [PATCH 30/49] drm: imx: Add mhdp dp/hdmi driver for imx8x platform - -Added i.MX8MQ HDMI/DP driver. -Added i.MX8MQ HDMI/DP driver. -Added LS1028A DP driver. - -Signed-off-by: Sandor Yu ---- - drivers/gpu/drm/imx/Kconfig | 1 + - drivers/gpu/drm/imx/Makefile | 1 + - drivers/gpu/drm/imx/mhdp/Kconfig | 11 + - drivers/gpu/drm/imx/mhdp/Makefile | 5 + - drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c | 531 ++++++++++++ - drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c | 764 ++++++++++++++++++ - drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx.h | 75 ++ - drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c | 638 +++++++++++++++ - drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c | 257 ++++++ - drivers/gpu/drm/imx/mhdp/cdns-mhdp-ls1028a.c | 110 +++ - drivers/gpu/drm/imx/mhdp/cdns-mhdp-phy.h | 155 ++++ - 11 files changed, 2548 insertions(+) - create mode 100644 drivers/gpu/drm/imx/mhdp/Kconfig - create mode 100644 drivers/gpu/drm/imx/mhdp/Makefile - create mode 100644 drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c - create mode 100644 drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c - create mode 100644 drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx.h - create mode 100644 drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c - create mode 100644 drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c - create mode 100644 drivers/gpu/drm/imx/mhdp/cdns-mhdp-ls1028a.c - create mode 100644 drivers/gpu/drm/imx/mhdp/cdns-mhdp-phy.h - -diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig -index 6231048aa5aa..4af2f575f04b 100644 ---- a/drivers/gpu/drm/imx/Kconfig -+++ b/drivers/gpu/drm/imx/Kconfig -@@ -2,3 +2,4 @@ config DRM_IMX_HDMI - source "drivers/gpu/drm/imx/dcss/Kconfig" - source "drivers/gpu/drm/imx/ipuv3/Kconfig" - source "drivers/gpu/drm/imx/lcdc/Kconfig" -+source "drivers/gpu/drm/imx/mhdp/Kconfig" -diff --git a/drivers/gpu/drm/imx/Makefile b/drivers/gpu/drm/imx/Makefile -index b644deffe948..0b46c46b19a8 100644 ---- a/drivers/gpu/drm/imx/Makefile -+++ b/drivers/gpu/drm/imx/Makefile -@@ -2,3 +2,4 @@ obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o - obj-$(CONFIG_DRM_IMX_DCSS) += dcss/ - obj-$(CONFIG_DRM_IMX) += ipuv3/ - obj-$(CONFIG_DRM_IMX_LCDC) += lcdc/ -+obj-$(CONFIG_DRM_IMX_CDNS_MHDP) += mhdp/ -diff --git a/drivers/gpu/drm/imx/mhdp/Kconfig b/drivers/gpu/drm/imx/mhdp/Kconfig -new file mode 100644 -index 000000000000..86950badb947 ---- /dev/null -+++ b/drivers/gpu/drm/imx/mhdp/Kconfig -@@ -0,0 +1,11 @@ -+# SPDX-License-Identifier: GPL-2.0-only -+ -+config DRM_IMX_CDNS_MHDP -+ tristate "NXP i.MX MX8 DRM HDMI/DP" -+ select DRM_CDNS_MHDP -+ select DRM_CDNS_DP -+ select DRM_CDNS_HDMI -+ select DRM_CDNS_AUDIO -+ depends on DRM_IMX -+ help -+ Choose this if you want to use HDMI on i.MX8. -diff --git a/drivers/gpu/drm/imx/mhdp/Makefile b/drivers/gpu/drm/imx/mhdp/Makefile -new file mode 100644 -index 000000000000..235fa2d515e9 ---- /dev/null -+++ b/drivers/gpu/drm/imx/mhdp/Makefile -@@ -0,0 +1,5 @@ -+# SPDX-License-Identifier: GPL-2.0 -+ -+cdns_mhdp_imx-objs := cdns-mhdp-imxdrv.o cdns-mhdp-dp-phy.o \ -+ cdns-mhdp-hdmi-phy.o cdns-mhdp-imx8qm.o cdns-mhdp-ls1028a.o -+obj-$(CONFIG_DRM_IMX_CDNS_MHDP) += cdns_mhdp_imx.o -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c -new file mode 100644 -index 000000000000..a6d03c94d196 ---- /dev/null -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c -@@ -0,0 +1,531 @@ -+/* -+ * Cadence Display Port Interface (DP) PHY driver -+ * -+ * Copyright (C) 2019 NXP Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include "cdns-mhdp-phy.h" -+ -+enum dp_link_rate { -+ RATE_1_6 = 162000, -+ RATE_2_1 = 216000, -+ RATE_2_4 = 243000, -+ RATE_2_7 = 270000, -+ RATE_3_2 = 324000, -+ RATE_4_3 = 432000, -+ RATE_5_4 = 540000, -+ RATE_8_1 = 810000, -+}; -+ -+struct phy_pll_reg { -+ u16 val[7]; -+ u32 addr; -+}; -+ -+static const struct phy_pll_reg phy_pll_27m_cfg[] = { -+ /* 1.62 2.16 2.43 2.7 3.24 4.32 5.4 register address */ -+ {{ 0x010E, 0x010E, 0x010E, 0x010E, 0x010E, 0x010E, 0x010E }, CMN_PLL0_VCOCAL_INIT_TMR }, -+ {{ 0x001B, 0x001B, 0x001B, 0x001B, 0x001B, 0x001B, 0x001B }, CMN_PLL0_VCOCAL_ITER_TMR }, -+ {{ 0x30B9, 0x3087, 0x3096, 0x30B4, 0x30B9, 0x3087, 0x30B4 }, CMN_PLL0_VCOCAL_START }, -+ {{ 0x0077, 0x009F, 0x00B3, 0x00C7, 0x0077, 0x009F, 0x00C7 }, CMN_PLL0_INTDIV }, -+ {{ 0xF9DA, 0xF7CD, 0xF6C7, 0xF5C1, 0xF9DA, 0xF7CD, 0xF5C1 }, CMN_PLL0_FRACDIV }, -+ {{ 0x001E, 0x0028, 0x002D, 0x0032, 0x001E, 0x0028, 0x0032 }, CMN_PLL0_HIGH_THR }, -+ {{ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 }, CMN_PLL0_DSM_DIAG }, -+ {{ 0x0000, 0x1000, 0x1000, 0x1000, 0x0000, 0x1000, 0x1000 }, CMN_PLLSM0_USER_DEF_CTRL }, -+ {{ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, CMN_DIAG_PLL0_OVRD }, -+ {{ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, CMN_DIAG_PLL0_FBH_OVRD }, -+ {{ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, CMN_DIAG_PLL0_FBL_OVRD }, -+ {{ 0x0006, 0x0007, 0x0007, 0x0007, 0x0006, 0x0007, 0x0007 }, CMN_DIAG_PLL0_V2I_TUNE }, -+ {{ 0x0043, 0x0043, 0x0043, 0x0042, 0x0043, 0x0043, 0x0042 }, CMN_DIAG_PLL0_CP_TUNE }, -+ {{ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008 }, CMN_DIAG_PLL0_LF_PROG }, -+ {{ 0x0100, 0x0001, 0x0001, 0x0001, 0x0100, 0x0001, 0x0001 }, CMN_DIAG_PLL0_PTATIS_TUNE1 }, -+ {{ 0x0007, 0x0001, 0x0001, 0x0001, 0x0007, 0x0001, 0x0001 }, CMN_DIAG_PLL0_PTATIS_TUNE2 }, -+ {{ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 }, CMN_DIAG_PLL0_TEST_MODE}, -+ {{ 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016 }, CMN_PSM_CLK_CTRL } -+}; -+ -+static const struct phy_pll_reg phy_pll_24m_cfg[] = { -+ /* 1.62 2.16 2.43 2.7 3.24 4.32 5.4 register address */ -+ {{ 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0 }, CMN_PLL0_VCOCAL_INIT_TMR }, -+ {{ 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018 }, CMN_PLL0_VCOCAL_ITER_TMR }, -+ {{ 0x3061, 0x3092, 0x30B3, 0x30D0, 0x3061, 0x3092, 0x30D0 }, CMN_PLL0_VCOCAL_START }, -+ {{ 0x0086, 0x00B3, 0x00CA, 0x00E0, 0x0086, 0x00B3, 0x00E0 }, CMN_PLL0_INTDIV }, -+ {{ 0xF917, 0xF6C7, 0x75A1, 0xF479, 0xF917, 0xF6C7, 0xF479 }, CMN_PLL0_FRACDIV }, -+ {{ 0x0022, 0x002D, 0x0033, 0x0038, 0x0022, 0x002D, 0x0038 }, CMN_PLL0_HIGH_THR }, -+ {{ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020 }, CMN_PLL0_DSM_DIAG }, -+ {{ 0x0000, 0x1000, 0x1000, 0x1000, 0x0000, 0x1000, 0x1000 }, CMN_PLLSM0_USER_DEF_CTRL }, -+ {{ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, CMN_DIAG_PLL0_OVRD }, -+ {{ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, CMN_DIAG_PLL0_FBH_OVRD }, -+ {{ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, CMN_DIAG_PLL0_FBL_OVRD }, -+ {{ 0x0006, 0x0007, 0x0007, 0x0007, 0x0006, 0x0007, 0x0007 }, CMN_DIAG_PLL0_V2I_TUNE }, -+ {{ 0x0026, 0x0029, 0x0029, 0x0029, 0x0026, 0x0029, 0x0029 }, CMN_DIAG_PLL0_CP_TUNE }, -+ {{ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008 }, CMN_DIAG_PLL0_LF_PROG }, -+ {{ 0x008C, 0x008C, 0x008C, 0x008C, 0x008C, 0x008C, 0x008C }, CMN_DIAG_PLL0_PTATIS_TUNE1 }, -+ {{ 0x002E, 0x002E, 0x002E, 0x002E, 0x002E, 0x002E, 0x002E }, CMN_DIAG_PLL0_PTATIS_TUNE2 }, -+ {{ 0x0022, 0x0022, 0x0022, 0x0022, 0x0022, 0x0022, 0x0022 }, CMN_DIAG_PLL0_TEST_MODE}, -+ {{ 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016 }, CMN_PSM_CLK_CTRL } -+}; -+ -+static int link_rate_index(u32 rate) -+{ -+ switch (rate) { -+ case RATE_1_6: -+ return 0; -+ case RATE_2_1: -+ return 1; -+ case RATE_2_4: -+ return 2; -+ case RATE_2_7: -+ return 3; -+ case RATE_3_2: -+ return 4; -+ case RATE_4_3: -+ return 5; -+ case RATE_5_4: -+ return 6; -+ default: -+ return -1; -+ } -+} -+ -+static void dp_aux_cfg(struct cdns_mhdp_device *mhdp) -+{ -+ /* Power up Aux */ -+ cdns_phy_reg_write(mhdp, TXDA_CYA_AUXDA_CYA, 1); -+ -+ cdns_phy_reg_write(mhdp, TX_DIG_CTRL_REG_1, 0x3); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_DIG_CTRL_REG_2, 36); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_2, 0x0100); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_2, 0x0300); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_3, 0x0000); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_1, 0x2008); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_1, 0x2018); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_1, 0xA018); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_2, 0x030C); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_5, 0x0000); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_4, 0x1001); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_1, 0xA098); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_1, 0xA198); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_2, 0x030d); -+ ndelay(150); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_2, 0x030f); -+} -+ -+/* PMA common configuration for 24MHz */ -+static void dp_phy_pma_cmn_cfg_24mhz(struct cdns_mhdp_device *mhdp) -+{ -+ int k; -+ u32 num_lanes = mhdp->dp.num_lanes; -+ u16 val; -+ -+ val = cdns_phy_reg_read(mhdp, PHY_PMA_CMN_CTRL1); -+ val &= 0xFFF7; -+ val |= 0x0008; -+ cdns_phy_reg_write(mhdp, PHY_PMA_CMN_CTRL1, val); -+ -+ for (k = 0; k < num_lanes; k++) { -+ /* Transceiver control and diagnostic registers */ -+ cdns_phy_reg_write(mhdp, XCVR_DIAG_LANE_FCM_EN_MGN_TMR | (k << 9), 0x0090); -+ /* Transmitter receiver detect registers */ -+ cdns_phy_reg_write(mhdp, TX_RCVDET_EN_TMR | (k << 9), 0x0960); -+ cdns_phy_reg_write(mhdp, TX_RCVDET_ST_TMR | (k << 9), 0x0030); -+ } -+} -+ -+/* Valid for 24 MHz only */ -+static void dp_phy_pma_cmn_pll0_24mhz(struct cdns_mhdp_device *mhdp) -+{ -+ u32 num_lanes = mhdp->dp.num_lanes; -+ u32 link_rate = mhdp->dp.rate; -+ u16 val; -+ int index, i, k; -+ -+ /* -+ * PLL reference clock source select -+ * for single ended reference clock val |= 0x0030; -+ * for differential clock val |= 0x0000; -+ */ -+ val = cdns_phy_reg_read(mhdp, PHY_PMA_CMN_CTRL1); -+ val = val & 0xFF8F; -+ val = val | 0x0030; -+ cdns_phy_reg_write(mhdp, PHY_PMA_CMN_CTRL1, val); -+ -+ /* DP PLL data rate 0/1 clock divider value */ -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_CLK_CTL); -+ val &= 0x00FF; -+ if (link_rate <= RATE_2_7) -+ val |= 0x2400; -+ else -+ val |= 0x1200; -+ cdns_phy_reg_write(mhdp, PHY_HDP_CLK_CTL, val); -+ -+ /* High speed clock 0/1 div */ -+ val = cdns_phy_reg_read(mhdp, CMN_DIAG_HSCLK_SEL); -+ val &= 0xFFCC; -+ if (link_rate <= RATE_2_7) -+ val |= 0x0011; -+ cdns_phy_reg_write(mhdp, CMN_DIAG_HSCLK_SEL, val); -+ -+ for (k = 0; k < num_lanes; k = k + 1) { -+ val = cdns_phy_reg_read(mhdp, (XCVR_DIAG_HSCLK_SEL | (k << 9))); -+ val &= 0xCFFF; -+ if (link_rate <= RATE_2_7) -+ val |= 0x1000; -+ cdns_phy_reg_write(mhdp, (XCVR_DIAG_HSCLK_SEL | (k << 9)), val); -+ } -+ -+ /* DP PHY PLL 24MHz configuration */ -+ index = link_rate_index(link_rate); -+ for (i = 0; i < ARRAY_SIZE(phy_pll_24m_cfg); i++) -+ cdns_phy_reg_write(mhdp, phy_pll_24m_cfg[i].addr, phy_pll_24m_cfg[i].val[index]); -+ -+ /* Transceiver control and diagnostic registers */ -+ for (k = 0; k < num_lanes; k = k + 1) { -+ val = cdns_phy_reg_read(mhdp, (XCVR_DIAG_PLLDRC_CTRL | (k << 9))); -+ val &= 0x8FFF; -+ if (link_rate <= RATE_2_7) -+ val |= 0x2000; -+ else -+ val |= 0x1000; -+ cdns_phy_reg_write(mhdp, (XCVR_DIAG_PLLDRC_CTRL | (k << 9)), val); -+ } -+ -+ for (k = 0; k < num_lanes; k = k + 1) { -+ cdns_phy_reg_write(mhdp, (XCVR_PSM_RCTRL | (k << 9)), 0xBEFC); -+ cdns_phy_reg_write(mhdp, (TX_PSC_A0 | (k << 9)), 0x6799); -+ cdns_phy_reg_write(mhdp, (TX_PSC_A1 | (k << 9)), 0x6798); -+ cdns_phy_reg_write(mhdp, (TX_PSC_A2 | (k << 9)), 0x0098); -+ cdns_phy_reg_write(mhdp, (TX_PSC_A3 | (k << 9)), 0x0098); -+ } -+} -+ -+/* PMA common configuration for 27MHz */ -+static void dp_phy_pma_cmn_cfg_27mhz(struct cdns_mhdp_device *mhdp) -+{ -+ u32 num_lanes = mhdp->dp.num_lanes; -+ u16 val; -+ int k; -+ -+ val = cdns_phy_reg_read(mhdp, PHY_PMA_CMN_CTRL1); -+ val &= 0xFFF7; -+ val |= 0x0008; -+ cdns_phy_reg_write(mhdp, PHY_PMA_CMN_CTRL1, val); -+ -+ /* Startup state machine registers */ -+ cdns_phy_reg_write(mhdp, CMN_SSM_BIAS_TMR, 0x0087); -+ cdns_phy_reg_write(mhdp, CMN_PLLSM0_PLLEN_TMR, 0x001B); -+ cdns_phy_reg_write(mhdp, CMN_PLLSM0_PLLPRE_TMR, 0x0036); -+ cdns_phy_reg_write(mhdp, CMN_PLLSM0_PLLVREF_TMR, 0x001B); -+ cdns_phy_reg_write(mhdp, CMN_PLLSM0_PLLLOCK_TMR, 0x006C); -+ -+ /* Current calibration registers */ -+ cdns_phy_reg_write(mhdp, CMN_ICAL_INIT_TMR, 0x0044); -+ cdns_phy_reg_write(mhdp, CMN_ICAL_ITER_TMR, 0x0006); -+ cdns_phy_reg_write(mhdp, CMN_ICAL_ADJ_INIT_TMR, 0x0022); -+ cdns_phy_reg_write(mhdp, CMN_ICAL_ADJ_ITER_TMR, 0x0006); -+ -+ /* Resistor calibration registers */ -+ cdns_phy_reg_write(mhdp, CMN_TXPUCAL_INIT_TMR, 0x0022); -+ cdns_phy_reg_write(mhdp, CMN_TXPUCAL_ITER_TMR, 0x0006); -+ cdns_phy_reg_write(mhdp, CMN_TXPU_ADJ_INIT_TMR, 0x0022); -+ cdns_phy_reg_write(mhdp, CMN_TXPU_ADJ_ITER_TMR, 0x0006); -+ cdns_phy_reg_write(mhdp, CMN_TXPDCAL_INIT_TMR, 0x0022); -+ cdns_phy_reg_write(mhdp, CMN_TXPDCAL_ITER_TMR, 0x0006); -+ cdns_phy_reg_write(mhdp, CMN_TXPD_ADJ_INIT_TMR, 0x0022); -+ cdns_phy_reg_write(mhdp, CMN_TXPD_ADJ_ITER_TMR, 0x0006); -+ cdns_phy_reg_write(mhdp, CMN_RXCAL_INIT_TMR, 0x0022); -+ cdns_phy_reg_write(mhdp, CMN_RXCAL_ITER_TMR, 0x0006); -+ cdns_phy_reg_write(mhdp, CMN_RX_ADJ_INIT_TMR, 0x0022); -+ cdns_phy_reg_write(mhdp, CMN_RX_ADJ_ITER_TMR, 0x0006); -+ -+ for (k = 0; k < num_lanes; k = k + 1) { -+ /* Power state machine registers */ -+ cdns_phy_reg_write(mhdp, XCVR_PSM_CAL_TMR | (k << 9), 0x016D); -+ cdns_phy_reg_write(mhdp, XCVR_PSM_A0IN_TMR | (k << 9), 0x016D); -+ /* Transceiver control and diagnostic registers */ -+ cdns_phy_reg_write(mhdp, XCVR_DIAG_LANE_FCM_EN_MGN_TMR | (k << 9), 0x00A2); -+ cdns_phy_reg_write(mhdp, TX_DIAG_BGREF_PREDRV_DELAY | (k << 9), 0x0097); -+ /* Transmitter receiver detect registers */ -+ cdns_phy_reg_write(mhdp, TX_RCVDET_EN_TMR | (k << 9), 0x0A8C); -+ cdns_phy_reg_write(mhdp, TX_RCVDET_ST_TMR | (k << 9), 0x0036); -+ } -+} -+ -+static void dp_phy_pma_cmn_pll0_27mhz(struct cdns_mhdp_device *mhdp) -+{ -+ u32 num_lanes = mhdp->dp.num_lanes; -+ u32 link_rate = mhdp->dp.rate; -+ u16 val; -+ int index, i, k; -+ -+ /* -+ * PLL reference clock source select -+ * for single ended reference clock val |= 0x0030; -+ * for differential clock val |= 0x0000; -+ */ -+ val = cdns_phy_reg_read(mhdp, PHY_PMA_CMN_CTRL1); -+ val &= 0xFF8F; -+ cdns_phy_reg_write(mhdp, PHY_PMA_CMN_CTRL1, val); -+ -+ /* for differential clock on the refclk_p and refclk_m off chip pins: -+ * CMN_DIAG_ACYA[8]=1'b1 -+ */ -+ cdns_phy_reg_write(mhdp, CMN_DIAG_ACYA, 0x0100); -+ -+ /* DP PLL data rate 0/1 clock divider value */ -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_CLK_CTL); -+ val &= 0x00FF; -+ if (link_rate <= RATE_2_7) -+ val |= 0x2400; -+ else -+ val |= 0x1200; -+ cdns_phy_reg_write(mhdp, PHY_HDP_CLK_CTL, val); -+ -+ /* High speed clock 0/1 div */ -+ val = cdns_phy_reg_read(mhdp, CMN_DIAG_HSCLK_SEL); -+ val &= 0xFFCC; -+ if (link_rate <= RATE_2_7) -+ val |= 0x0011; -+ cdns_phy_reg_write(mhdp, CMN_DIAG_HSCLK_SEL, val); -+ -+ for (k = 0; k < num_lanes; k++) { -+ val = cdns_phy_reg_read(mhdp, (XCVR_DIAG_HSCLK_SEL | (k << 9))); -+ val = val & 0xCFFF; -+ if (link_rate <= RATE_2_7) -+ val |= 0x1000; -+ cdns_phy_reg_write(mhdp, (XCVR_DIAG_HSCLK_SEL | (k << 9)), val); -+ } -+ -+ /* DP PHY PLL 27MHz configuration */ -+ index = link_rate_index(link_rate); -+ for (i = 0; i < ARRAY_SIZE(phy_pll_27m_cfg); i++) -+ cdns_phy_reg_write(mhdp, phy_pll_27m_cfg[i].addr, phy_pll_27m_cfg[i].val[index]); -+ -+ /* Transceiver control and diagnostic registers */ -+ for (k = 0; k < num_lanes; k++) { -+ val = cdns_phy_reg_read(mhdp, (XCVR_DIAG_PLLDRC_CTRL | (k << 9))); -+ val = val & 0x8FFF; -+ if (link_rate <= RATE_2_7) -+ val |= 0x2000; -+ else -+ val |= 0x1000; -+ cdns_phy_reg_write(mhdp, (XCVR_DIAG_PLLDRC_CTRL | (k << 9)), val); -+ } -+ -+ for (k = 0; k < num_lanes; k = k + 1) { -+ /* Power state machine registers */ -+ cdns_phy_reg_write(mhdp, (XCVR_PSM_RCTRL | (k << 9)), 0xBEFC); -+ cdns_phy_reg_write(mhdp, (TX_PSC_A0 | (k << 9)), 0x6799); -+ cdns_phy_reg_write(mhdp, (TX_PSC_A1 | (k << 9)), 0x6798); -+ cdns_phy_reg_write(mhdp, (TX_PSC_A2 | (k << 9)), 0x0098); -+ cdns_phy_reg_write(mhdp, (TX_PSC_A3 | (k << 9)), 0x0098); -+ /* Receiver calibration power state definition register */ -+ val = cdns_phy_reg_read(mhdp, RX_PSC_CAL | (k << 9)); -+ val &= 0xFFBB; -+ cdns_phy_reg_write(mhdp, (RX_PSC_CAL | (k << 9)), val); -+ val = cdns_phy_reg_read(mhdp, RX_PSC_A0 | (k << 9)); -+ val &= 0xFFBB; -+ cdns_phy_reg_write(mhdp, (RX_PSC_A0 | (k << 9)), val); -+ } -+} -+ -+static void dp_phy_power_down(struct cdns_mhdp_device *mhdp) -+{ -+ u16 val; -+ int i; -+ -+ if (!mhdp->power_up) -+ return; -+ -+ /* Place the PHY lanes in the A3 power state. */ -+ cdns_phy_reg_write(mhdp, PHY_HDP_MODE_CTRL, 0x8); -+ /* Wait for Power State A3 Ack */ -+ for (i = 0; i < 10; i++) { -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_MODE_CTRL); -+ if (val & (1 << 7)) -+ break; -+ msleep(20); -+ } -+ if (i == 10) { -+ dev_err(mhdp->dev, "Wait A3 Ack failed\n"); -+ return; -+ } -+ -+ /* Disable HDP PLL’s data rate and full rate clocks out of PMA. */ -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_CLK_CTL); -+ val &= ~(1 << 2); -+ cdns_phy_reg_write(mhdp, PHY_HDP_CLK_CTL, val); -+ /* Wait for PLL clock gate ACK */ -+ for (i = 0; i < 10; i++) { -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_CLK_CTL); -+ if (!(val & (1 << 3))) -+ break; -+ msleep(20); -+ } -+ if (i == 10) { -+ dev_err(mhdp->dev, "Wait PLL clock gate Ack failed\n"); -+ return; -+ } -+ -+ /* Disable HDP PLL’s for high speed clocks */ -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_CLK_CTL); -+ val &= ~(1 << 0); -+ cdns_phy_reg_write(mhdp, PHY_HDP_CLK_CTL, val); -+ /* Wait for PLL disable ACK */ -+ for (i = 0; i < 10; i++) { -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_CLK_CTL); -+ if (!(val & (1 << 1))) -+ break; -+ msleep(20); -+ } -+ if (i == 10) { -+ dev_err(mhdp->dev, "Wait PLL disable Ack failed\n"); -+ return; -+ } -+} -+ -+static int dp_phy_power_up(struct cdns_mhdp_device *mhdp) -+{ -+ u32 val, i; -+ -+ /* Enable HDP PLL’s for high speed clocks */ -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_CLK_CTL); -+ val |= (1 << 0); -+ cdns_phy_reg_write(mhdp, PHY_HDP_CLK_CTL, val); -+ /* Wait for PLL ready ACK */ -+ for (i = 0; i < 10; i++) { -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_CLK_CTL); -+ if (val & (1 << 1)) -+ break; -+ msleep(20); -+ } -+ if (i == 10) { -+ dev_err(mhdp->dev, "Wait PLL Ack failed\n"); -+ return -1; -+ } -+ -+ /* Enable HDP PLL’s data rate and full rate clocks out of PMA. */ -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_CLK_CTL); -+ val |= (1 << 2); -+ cdns_phy_reg_write(mhdp, PHY_HDP_CLK_CTL, val); -+ /* Wait for PLL clock enable ACK */ -+ for (i = 0; i < 10; i++) { -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_CLK_CTL); -+ if (val & (1 << 3)) -+ break; -+ msleep(20); -+ } -+ if (i == 10) { -+ dev_err(mhdp->dev, "Wait PLL clock enable ACk failed\n"); -+ return -1; -+ } -+ -+ /* Configure PHY in A2 Mode */ -+ cdns_phy_reg_write(mhdp, PHY_HDP_MODE_CTRL, 0x0004); -+ /* Wait for Power State A2 Ack */ -+ for (i = 0; i < 10; i++) { -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_MODE_CTRL); -+ if (val & (1 << 6)) -+ break; -+ msleep(20); -+ } -+ if (i == 10) { -+ dev_err(mhdp->dev, "Wait A2 Ack failed\n"); -+ return -1; -+ } -+ -+ /* Configure PHY in A0 mode (PHY must be in the A0 power -+ * state in order to transmit data) -+ */ -+ cdns_phy_reg_write(mhdp, PHY_HDP_MODE_CTRL, 0x0101); -+ -+ /* Wait for Power State A0 Ack */ -+ for (i = 0; i < 10; i++) { -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_MODE_CTRL); -+ if (val & (1 << 4)) -+ break; -+ msleep(20); -+ } -+ if (i == 10) { -+ dev_err(mhdp->dev, "Wait A0 Ack failed\n"); -+ return -1; -+ } -+ -+ mhdp->power_up = true; -+ -+ return 0; -+} -+ -+int cdns_dp_phy_set_imx8mq(struct cdns_mhdp_device *mhdp) -+{ -+ int ret; -+ -+ /* Disable phy clock if PHY in power up state */ -+ dp_phy_power_down(mhdp); -+ -+ dp_phy_pma_cmn_cfg_27mhz(mhdp); -+ -+ dp_phy_pma_cmn_pll0_27mhz(mhdp); -+ -+ cdns_phy_reg_write(mhdp, TX_DIAG_ACYA_0, 1); -+ cdns_phy_reg_write(mhdp, TX_DIAG_ACYA_1, 1); -+ cdns_phy_reg_write(mhdp, TX_DIAG_ACYA_2, 1); -+ cdns_phy_reg_write(mhdp, TX_DIAG_ACYA_3, 1); -+ -+ /* PHY power up */ -+ ret = dp_phy_power_up(mhdp); -+ if (ret < 0) -+ return ret; -+ -+ dp_aux_cfg(mhdp); -+ -+ return ret; -+} -+ -+int cdns_dp_phy_set_imx8qm(struct cdns_mhdp_device *mhdp) -+{ -+ int ret; -+ -+ /* Disable phy clock if PHY in power up state */ -+ dp_phy_power_down(mhdp); -+ -+ dp_phy_pma_cmn_cfg_24mhz(mhdp); -+ -+ dp_phy_pma_cmn_pll0_24mhz(mhdp); -+ -+ cdns_phy_reg_write(mhdp, TX_DIAG_ACYA_0, 1); -+ cdns_phy_reg_write(mhdp, TX_DIAG_ACYA_1, 1); -+ cdns_phy_reg_write(mhdp, TX_DIAG_ACYA_2, 1); -+ cdns_phy_reg_write(mhdp, TX_DIAG_ACYA_3, 1); -+ -+ /* PHY power up */ -+ ret = dp_phy_power_up(mhdp); -+ if (ret < 0) -+ return ret; -+ -+ dp_aux_cfg(mhdp); -+ -+ return true; -+} -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c -new file mode 100644 -index 000000000000..120300e6a2df ---- /dev/null -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c -@@ -0,0 +1,764 @@ -+/* -+ * Cadence High-Definition Multimedia Interface (HDMI) driver -+ * -+ * Copyright (C) 2019 NXP Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include "cdns-mhdp-phy.h" -+ -+/* HDMI TX clock control settings */ -+struct hdmi_ctrl { -+ u32 pixel_clk_freq_min; -+ u32 pixel_clk_freq_max; -+ u32 feedback_factor; -+ u32 data_range_kbps_min; -+ u32 data_range_kbps_max; -+ u32 cmnda_pll0_ip_div; -+ u32 cmn_ref_clk_dig_div; -+ u32 ref_clk_divider_scaler; -+ u32 pll_fb_div_total; -+ u32 cmnda_pll0_fb_div_low; -+ u32 cmnda_pll0_fb_div_high; -+ u32 pixel_div_total; -+ u32 cmnda_pll0_pxdiv_low; -+ u32 cmnda_pll0_pxdiv_high; -+ u32 vco_freq_min; -+ u32 vco_freq_max; -+ u32 vco_ring_select; -+ u32 cmnda_hs_clk_0_sel; -+ u32 cmnda_hs_clk_1_sel; -+ u32 hsclk_div_at_xcvr; -+ u32 hsclk_div_tx_sub_rate; -+ u32 cmnda_pll0_hs_sym_div_sel; -+ u32 cmnda_pll0_clk_freq_min; -+ u32 cmnda_pll0_clk_freq_max; -+}; -+ -+/* HDMI TX clock control settings, pixel clock is output */ -+static const struct hdmi_ctrl imx8mq_ctrl_table[] = { -+/*Minclk Maxclk Fdbak DR_min DR_max ip_d dig DS Totl */ -+{ 27000, 27000, 1000, 270000, 270000, 0x03, 0x1, 0x1, 240, 0x0BC, 0x030, 80, 0x026, 0x026, 2160000, 2160000, 0, 2, 2, 2, 4, 0x3, 27000, 27000}, -+{ 27000, 27000, 1250, 337500, 337500, 0x03, 0x1, 0x1, 300, 0x0EC, 0x03C, 100, 0x030, 0x030, 2700000, 2700000, 0, 2, 2, 2, 4, 0x3, 33750, 33750}, -+{ 27000, 27000, 1500, 405000, 405000, 0x03, 0x1, 0x1, 360, 0x11C, 0x048, 120, 0x03A, 0x03A, 3240000, 3240000, 0, 2, 2, 2, 4, 0x3, 40500, 40500}, -+{ 27000, 27000, 2000, 540000, 540000, 0x03, 0x1, 0x1, 240, 0x0BC, 0x030, 80, 0x026, 0x026, 2160000, 2160000, 0, 2, 2, 2, 4, 0x2, 54000, 54000}, -+{ 54000, 54000, 1000, 540000, 540000, 0x03, 0x1, 0x1, 480, 0x17C, 0x060, 80, 0x026, 0x026, 4320000, 4320000, 1, 2, 2, 2, 4, 0x3, 54000, 54000}, -+{ 54000, 54000, 1250, 675000, 675000, 0x04, 0x1, 0x1, 400, 0x13C, 0x050, 50, 0x017, 0x017, 2700000, 2700000, 0, 1, 1, 2, 4, 0x2, 67500, 67500}, -+{ 54000, 54000, 1500, 810000, 810000, 0x04, 0x1, 0x1, 480, 0x17C, 0x060, 60, 0x01C, 0x01C, 3240000, 3240000, 0, 2, 2, 2, 2, 0x2, 81000, 81000}, -+{ 54000, 54000, 2000, 1080000, 1080000, 0x03, 0x1, 0x1, 240, 0x0BC, 0x030, 40, 0x012, 0x012, 2160000, 2160000, 0, 2, 2, 2, 1, 0x1, 108000, 108000}, -+{ 74250, 74250, 1000, 742500, 742500, 0x03, 0x1, 0x1, 660, 0x20C, 0x084, 80, 0x026, 0x026, 5940000, 5940000, 1, 2, 2, 2, 4, 0x3, 74250, 74250}, -+{ 74250, 74250, 1250, 928125, 928125, 0x04, 0x1, 0x1, 550, 0x1B4, 0x06E, 50, 0x017, 0x017, 3712500, 3712500, 1, 1, 1, 2, 4, 0x2, 92812, 92812}, -+{ 74250, 74250, 1500, 1113750, 1113750, 0x04, 0x1, 0x1, 660, 0x20C, 0x084, 60, 0x01C, 0x01C, 4455000, 4455000, 1, 2, 2, 2, 2, 0x2, 111375, 111375}, -+{ 74250, 74250, 2000, 1485000, 1485000, 0x03, 0x1, 0x1, 330, 0x104, 0x042, 40, 0x012, 0x012, 2970000, 2970000, 0, 2, 2, 2, 1, 0x1, 148500, 148500}, -+{ 99000, 99000, 1000, 990000, 990000, 0x03, 0x1, 0x1, 440, 0x15C, 0x058, 40, 0x012, 0x012, 3960000, 3960000, 1, 2, 2, 2, 2, 0x2, 99000, 99000}, -+{ 99000, 99000, 1250, 1237500, 1237500, 0x03, 0x1, 0x1, 275, 0x0D8, 0x037, 25, 0x00B, 0x00A, 2475000, 2475000, 0, 1, 1, 2, 2, 0x1, 123750, 123750}, -+{ 99000, 99000, 1500, 1485000, 1485000, 0x03, 0x1, 0x1, 330, 0x104, 0x042, 30, 0x00D, 0x00D, 2970000, 2970000, 0, 2, 2, 2, 1, 0x1, 148500, 148500}, -+{ 99000, 99000, 2000, 1980000, 1980000, 0x03, 0x1, 0x1, 440, 0x15C, 0x058, 40, 0x012, 0x012, 3960000, 3960000, 1, 2, 2, 2, 1, 0x1, 198000, 198000}, -+{148500, 148500, 1000, 1485000, 1485000, 0x03, 0x1, 0x1, 660, 0x20C, 0x084, 40, 0x012, 0x012, 5940000, 5940000, 1, 2, 2, 2, 2, 0x2, 148500, 148500}, -+{148500, 148500, 1250, 1856250, 1856250, 0x04, 0x1, 0x1, 550, 0x1B4, 0x06E, 25, 0x00B, 0x00A, 3712500, 3712500, 1, 1, 1, 2, 2, 0x1, 185625, 185625}, -+{148500, 148500, 1500, 2227500, 2227500, 0x03, 0x1, 0x1, 495, 0x188, 0x063, 30, 0x00D, 0x00D, 4455000, 4455000, 1, 1, 1, 2, 2, 0x1, 222750, 222750}, -+{148500, 148500, 2000, 2970000, 2970000, 0x03, 0x1, 0x1, 660, 0x20C, 0x084, 40, 0x012, 0x012, 5940000, 5940000, 1, 2, 2, 2, 1, 0x1, 297000, 297000}, -+{198000, 198000, 1000, 1980000, 1980000, 0x03, 0x1, 0x1, 220, 0x0AC, 0x02C, 10, 0x003, 0x003, 1980000, 1980000, 0, 1, 1, 2, 1, 0x0, 198000, 198000}, -+{198000, 198000, 1250, 2475000, 2475000, 0x03, 0x1, 0x1, 550, 0x1B4, 0x06E, 25, 0x00B, 0x00A, 4950000, 4950000, 1, 1, 1, 2, 2, 0x1, 247500, 247500}, -+{198000, 198000, 1500, 2970000, 2970000, 0x03, 0x1, 0x1, 330, 0x104, 0x042, 15, 0x006, 0x005, 2970000, 2970000, 0, 1, 1, 2, 1, 0x0, 297000, 297000}, -+{198000, 198000, 2000, 3960000, 3960000, 0x03, 0x1, 0x1, 440, 0x15C, 0x058, 20, 0x008, 0x008, 3960000, 3960000, 1, 1, 1, 2, 1, 0x0, 396000, 396000}, -+{297000, 297000, 1000, 2970000, 2970000, 0x03, 0x1, 0x1, 330, 0x104, 0x042, 10, 0x003, 0x003, 2970000, 2970000, 0, 1, 1, 2, 1, 0x0, 297000, 297000}, -+{297000, 297000, 1500, 4455000, 4455000, 0x03, 0x1, 0x1, 495, 0x188, 0x063, 15, 0x006, 0x005, 4455000, 4455000, 1, 1, 1, 2, 1, 0x0, 445500, 445500}, -+{297000, 297000, 2000, 5940000, 5940000, 0x03, 0x1, 0x1, 660, 0x20C, 0x084, 20, 0x008, 0x008, 5940000, 5940000, 1, 1, 1, 2, 1, 0x0, 594000, 594000}, -+{594000, 594000, 1000, 5940000, 5940000, 0x03, 0x1, 0x1, 660, 0x20C, 0x084, 10, 0x003, 0x003, 5940000, 5940000, 1, 1, 1, 2, 1, 0x0, 594000, 594000}, -+{594000, 594000, 750, 4455000, 4455000, 0x03, 0x1, 0x1, 495, 0x188, 0x063, 10, 0x003, 0x003, 4455000, 4455000, 1, 1, 1, 2, 1, 0x0, 445500, 445500}, -+{594000, 594000, 625, 3712500, 3712500, 0x04, 0x1, 0x1, 550, 0x1B4, 0x06E, 10, 0x003, 0x003, 3712500, 3712500, 1, 1, 1, 2, 1, 0x0, 371250, 371250}, -+{594000, 594000, 500, 2970000, 2970000, 0x03, 0x1, 0x1, 660, 0x20C, 0x084, 10, 0x003, 0x003, 5940000, 5940000, 1, 1, 1, 2, 2, 0x1, 297000, 297000}, -+}; -+ -+/* HDMI TX clock control settings, pixel clock is input */ -+static const struct hdmi_ctrl imx8qm_ctrl_table[] = { -+/*pclk_l pclk_h fd DRR_L DRR_H PLLD */ -+{ 25000, 42500, 1000, 250000, 425000, 0x05, 0x01, 0x01, 400, 0x182, 0x00A, 0, 0, 0, 2000000, 3400000, 0, 2, 2, 2, 4, 0x03, 25000, 42500}, -+{ 42500, 85000, 1000, 425000, 850000, 0x08, 0x03, 0x01, 320, 0x132, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 4, 0x02, 42500, 85000}, -+{ 85000, 170000, 1000, 850000, 1700000, 0x11, 0x00, 0x07, 340, 0x146, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 2, 0x01, 85000, 170000}, -+{170000, 340000, 1000, 1700000, 3400000, 0x22, 0x01, 0x07, 340, 0x146, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 1, 0x00, 170000, 340000}, -+{340000, 600000, 1000, 3400000, 6000000, 0x3C, 0x03, 0x06, 600, 0x24A, 0x00A, 0, 0, 0, 3400000, 6000000, 1, 1, 1, 2, 1, 0x00, 340000, 600000}, -+{ 25000, 34000, 1205, 312500, 425000, 0x04, 0x01, 0x01, 400, 0x182, 0x00A, 0, 0, 0, 2500000, 3400000, 0, 2, 2, 2, 4, 0x03, 31250, 42500}, -+{ 34000, 68000, 1205, 425000, 850000, 0x06, 0x02, 0x01, 300, 0x11E, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 4, 0x02, 42500, 85000}, -+{ 68000, 136000, 1205, 850000, 1700000, 0x0D, 0x02, 0x02, 325, 0x137, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 2, 0x01, 85000, 170000}, -+{136000, 272000, 1205, 1700000, 3400000, 0x1A, 0x02, 0x04, 325, 0x137, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 1, 0x00, 170000, 340000}, -+{272000, 480000, 1205, 3400000, 6000000, 0x30, 0x03, 0x05, 600, 0x24A, 0x00A, 0, 0, 0, 3400000, 6000000, 1, 1, 1, 2, 1, 0x00, 340000, 600000}, -+{ 25000, 28000, 1500, 375000, 420000, 0x03, 0x01, 0x01, 360, 0x15A, 0x00A, 0, 0, 0, 3000000, 3360000, 0, 2, 2, 2, 4, 0x03, 37500, 42000}, -+{ 28000, 56000, 1500, 420000, 840000, 0x06, 0x02, 0x01, 360, 0x15A, 0x00A, 0, 0, 0, 1680000, 3360000, 0, 1, 1, 2, 4, 0x02, 42000, 84000}, -+{ 56000, 113000, 1500, 840000, 1695000, 0x0B, 0x00, 0x05, 330, 0x13C, 0x00A, 0, 0, 0, 1680000, 3390000, 0, 1, 1, 2, 2, 0x01, 84000, 169500}, -+{113000, 226000, 1500, 1695000, 3390000, 0x16, 0x01, 0x05, 330, 0x13C, 0x00A, 0, 0, 0, 1695000, 3390000, 0, 1, 1, 2, 1, 0x00, 169500, 339000}, -+{226000, 400000, 1500, 3390000, 6000000, 0x28, 0x03, 0x04, 600, 0x24A, 0x00A, 0, 0, 0, 3390000, 6000000, 1, 1, 1, 2, 1, 0x00, 339000, 600000}, -+{ 25000, 42500, 2000, 500000, 850000, 0x05, 0x01, 0x01, 400, 0x182, 0x00A, 0, 0, 0, 2000000, 3400000, 0, 1, 1, 2, 4, 0x02, 50000, 85000}, -+{ 42500, 85000, 2000, 850000, 1700000, 0x08, 0x03, 0x01, 320, 0x132, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 2, 0x01, 85000, 170000}, -+{ 85000, 170000, 2000, 1700000, 3400000, 0x11, 0x00, 0x07, 340, 0x146, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 1, 0x00, 170000, 340000}, -+{170000, 300000, 2000, 3400000, 6000000, 0x22, 0x01, 0x06, 680, 0x29A, 0x00A, 0, 0, 0, 3400000, 6000000, 1, 1, 1, 2, 1, 0x00, 340000, 600000}, -+{594000, 594000, 5000, 2970000, 2970000, 0x3C, 0x03, 0x06, 600, 0x24A, 0x00A, 0, 0, 0, 5940000, 5940000, 1, 1, 1, 2, 2, 0x01, 297000, 297000}, -+{594000, 594000, 6250, 3712500, 3712500, 0x3C, 0x03, 0x06, 375, 0x169, 0x00A, 0, 0, 0, 3712500, 3712500, 1, 1, 1, 2, 1, 0x00, 371250, 371250}, -+{594000, 594000, 7500, 4455000, 4455000, 0x3C, 0x03, 0x06, 450, 0x1B4, 0x00A, 0, 0, 0, 4455000, 4455000, 1, 1, 1, 2, 1, 0x00, 445500, 445500}, -+}; -+ -+/* HDMI TX PLL tuning settings */ -+struct hdmi_pll_tuning { -+ u32 vco_freq_bin; -+ u32 vco_freq_min; -+ u32 vco_freq_max; -+ u32 volt_to_current_coarse; -+ u32 volt_to_current; -+ u32 ndac_ctrl; -+ u32 pmos_ctrl; -+ u32 ptat_ndac_ctrl; -+ u32 feedback_div_total; -+ u32 charge_pump_gain; -+ u32 coarse_code; -+ u32 v2i_code; -+ u32 vco_cal_code; -+}; -+ -+/* HDMI TX PLL tuning settings, pixel clock is output */ -+static const struct hdmi_pll_tuning imx8mq_pll_table[] = { -+/* bin VCO_freq min/max coar cod NDAC PMOS PTAT div-T P-Gain Coa V2I CAL */ -+ { 1, 1980000, 1980000, 0x4, 0x3, 0x0, 0x09, 0x09, 220, 0x42, 160, 5, 183 }, -+ { 2, 2160000, 2160000, 0x4, 0x3, 0x0, 0x09, 0x09, 240, 0x42, 166, 6, 208 }, -+ { 3, 2475000, 2475000, 0x5, 0x3, 0x1, 0x00, 0x07, 275, 0x42, 167, 6, 209 }, -+ { 4, 2700000, 2700000, 0x5, 0x3, 0x1, 0x00, 0x07, 300, 0x42, 188, 6, 230 }, -+ { 4, 2700000, 2700000, 0x5, 0x3, 0x1, 0x00, 0x07, 400, 0x4C, 188, 6, 230 }, -+ { 5, 2970000, 2970000, 0x6, 0x3, 0x1, 0x00, 0x07, 330, 0x42, 183, 6, 225 }, -+ { 6, 3240000, 3240000, 0x6, 0x3, 0x1, 0x00, 0x07, 360, 0x42, 203, 7, 256 }, -+ { 6, 3240000, 3240000, 0x6, 0x3, 0x1, 0x00, 0x07, 480, 0x4C, 203, 7, 256 }, -+ { 7, 3712500, 3712500, 0x4, 0x3, 0x0, 0x07, 0x0F, 550, 0x4C, 212, 7, 257 }, -+ { 8, 3960000, 3960000, 0x5, 0x3, 0x0, 0x07, 0x0F, 440, 0x42, 184, 6, 226 }, -+ { 9, 4320000, 4320000, 0x5, 0x3, 0x1, 0x07, 0x0F, 480, 0x42, 205, 7, 258 }, -+ { 10, 4455000, 4455000, 0x5, 0x3, 0x0, 0x07, 0x0F, 495, 0x42, 219, 7, 272 }, -+ { 10, 4455000, 4455000, 0x5, 0x3, 0x0, 0x07, 0x0F, 660, 0x4C, 219, 7, 272 }, -+ { 11, 4950000, 4950000, 0x6, 0x3, 0x1, 0x00, 0x07, 550, 0x42, 213, 7, 258 }, -+ { 12, 5940000, 5940000, 0x7, 0x3, 0x1, 0x00, 0x07, 660, 0x42, 244, 8, 292 }, -+}; -+ -+/* HDMI TX PLL tuning settings, pixel clock is input */ -+static const struct hdmi_pll_tuning imx8qm_pll_table[] = { -+/* bin VCO_freq min/max coar cod NDAC PMOS PTAT div-T P-Gain pad only */ -+ { 0, 1700000, 2000000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 300, 0x08D, 0, 0, 0 }, -+ { 0, 1700000, 2000000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 320, 0x08E, 0, 0, 0 }, -+ { 0, 1700000, 2000000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 325, 0x08E, 0, 0, 0 }, -+ { 0, 1700000, 2000000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 330, 0x08E, 0, 0, 0 }, -+ { 0, 1700000, 2000000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 340, 0x08F, 0, 0, 0 }, -+ { 0, 1700000, 2000000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 360, 0x0A7, 0, 0, 0 }, -+ { 0, 1700000, 2000000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 400, 0x0C5, 0, 0, 0 }, -+ { 1, 2000000, 2400000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 300, 0x086, 0, 0, 0 }, -+ { 1, 2000000, 2400000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 320, 0x087, 0, 0, 0 }, -+ { 1, 2000000, 2400000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 325, 0x087, 0, 0, 0 }, -+ { 1, 2000000, 2400000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 330, 0x104, 0, 0, 0 }, -+ { 1, 2000000, 2400000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 340, 0x08B, 0, 0, 0 }, -+ { 1, 2000000, 2400000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 360, 0x08D, 0, 0, 0 }, -+ { 1, 2000000, 2400000, 0x3, 0x1, 0x0, 0x8C, 0x2E, 400, 0x0A6, 0, 0, 0 }, -+ { 2, 2400000, 2800000, 0x3, 0x1, 0x0, 0x04, 0x0D, 300, 0x04E, 0, 0, 0 }, -+ { 2, 2400000, 2800000, 0x3, 0x1, 0x0, 0x04, 0x0D, 320, 0x04F, 0, 0, 0 }, -+ { 2, 2400000, 2800000, 0x3, 0x1, 0x0, 0x04, 0x0D, 325, 0x04F, 0, 0, 0 }, -+ { 2, 2400000, 2800000, 0x3, 0x1, 0x0, 0x04, 0x0D, 330, 0x085, 0, 0, 0 }, -+ { 2, 2400000, 2800000, 0x3, 0x1, 0x0, 0x04, 0x0D, 340, 0x085, 0, 0, 0 }, -+ { 2, 2400000, 2800000, 0x3, 0x1, 0x0, 0x04, 0x0D, 360, 0x086, 0, 0, 0 }, -+ { 2, 2400000, 2800000, 0x3, 0x1, 0x0, 0x04, 0x0D, 400, 0x08B, 0, 0, 0 }, -+ { 3, 2800000, 3400000, 0x3, 0x1, 0x0, 0x04, 0x0D, 300, 0x047, 0, 0, 0 }, -+ { 3, 2800000, 3400000, 0x3, 0x1, 0x0, 0x04, 0x0D, 320, 0x04B, 0, 0, 0 }, -+ { 3, 2800000, 3400000, 0x3, 0x1, 0x0, 0x04, 0x0D, 325, 0x04B, 0, 0, 0 }, -+ { 3, 2800000, 3400000, 0x3, 0x1, 0x0, 0x04, 0x0D, 330, 0x04B, 0, 0, 0 }, -+ { 3, 2800000, 3400000, 0x3, 0x1, 0x0, 0x04, 0x0D, 340, 0x04D, 0, 0, 0 }, -+ { 3, 2800000, 3400000, 0x3, 0x1, 0x0, 0x04, 0x0D, 360, 0x04E, 0, 0, 0 }, -+ { 3, 2800000, 3400000, 0x3, 0x1, 0x0, 0x04, 0x0D, 400, 0x085, 0, 0, 0 }, -+ { 4, 3400000, 3900000, 0x7, 0x1, 0x0, 0x8E, 0x2F, 375, 0x041, 0, 0, 0 }, -+ { 4, 3400000, 3900000, 0x7, 0x1, 0x0, 0x8E, 0x2F, 600, 0x08D, 0, 0, 0 }, -+ { 4, 3400000, 3900000, 0x7, 0x1, 0x0, 0x8E, 0x2F, 680, 0x0A6, 0, 0, 0 }, -+ { 5, 3900000, 4500000, 0x7, 0x1, 0x0, 0x8E, 0x2F, 450, 0x041, 0, 0, 0 }, -+ { 5, 3900000, 4500000, 0x7, 0x1, 0x0, 0x8E, 0x2F, 600, 0x087, 0, 0, 0 }, -+ { 5, 3900000, 4500000, 0x7, 0x1, 0x0, 0x8E, 0x2F, 680, 0x0A4, 0, 0, 0 }, -+ { 6, 4500000, 5200000, 0x7, 0x1, 0x0, 0x04, 0x0D, 600, 0x04F, 0, 0, 0 }, -+ { 6, 4500000, 5200000, 0x7, 0x1, 0x0, 0x04, 0x0D, 680, 0x086, 0, 0, 0 }, -+ { 7, 5200000, 6000000, 0x7, 0x1, 0x0, 0x04, 0x0D, 600, 0x04D, 0, 0, 0 }, -+ { 7, 5200000, 6000000, 0x7, 0x1, 0x0, 0x04, 0x0D, 680, 0x04F, 0, 0, 0 } -+}; -+ -+static void hdmi_arc_config(struct cdns_mhdp_device *mhdp) -+{ -+ u16 txpu_calib_code; -+ u16 txpd_calib_code; -+ u16 txpu_adj_calib_code; -+ u16 txpd_adj_calib_code; -+ u16 prev_calib_code; -+ u16 new_calib_code; -+ u16 rdata; -+ -+ /* Power ARC */ -+ cdns_phy_reg_write(mhdp, TXDA_CYA_AUXDA_CYA, 0x0001); -+ -+ prev_calib_code = cdns_phy_reg_read(mhdp, TX_DIG_CTRL_REG_2); -+ txpu_calib_code = cdns_phy_reg_read(mhdp, CMN_TXPUCAL_CTRL); -+ txpd_calib_code = cdns_phy_reg_read(mhdp, CMN_TXPDCAL_CTRL); -+ txpu_adj_calib_code = cdns_phy_reg_read(mhdp, CMN_TXPU_ADJ_CTRL); -+ txpd_adj_calib_code = cdns_phy_reg_read(mhdp, CMN_TXPD_ADJ_CTRL); -+ -+ new_calib_code = ((txpu_calib_code + txpd_calib_code) / 2) -+ + txpu_adj_calib_code + txpd_adj_calib_code; -+ -+ if (new_calib_code != prev_calib_code) { -+ rdata = cdns_phy_reg_read(mhdp, TX_ANA_CTRL_REG_1); -+ rdata &= 0xDFFF; -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_1, rdata); -+ cdns_phy_reg_write(mhdp, TX_DIG_CTRL_REG_2, new_calib_code); -+ mdelay(10); -+ rdata |= 0x2000; -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_1, rdata); -+ udelay(150); -+ } -+ -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_2, 0x0100); -+ udelay(100); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_2, 0x0300); -+ udelay(100); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_3, 0x0000); -+ udelay(100); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_1, 0x2008); -+ udelay(100); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_1, 0x2018); -+ udelay(100); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_1, 0x2098); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_2, 0x030C); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_5, 0x0010); -+ udelay(100); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_4, 0x4001); -+ mdelay(5); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_1, 0x2198); -+ mdelay(5); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_2, 0x030D); -+ udelay(100); -+ cdns_phy_reg_write(mhdp, TX_ANA_CTRL_REG_2, 0x030F); -+} -+ -+static void hdmi_phy_set_vswing(struct cdns_mhdp_device *mhdp) -+{ -+ const u32 num_lanes = 4; -+ u32 k; -+ -+ for (k = 0; k < num_lanes; k++) { -+ cdns_phy_reg_write(mhdp, (TX_DIAG_TX_DRV | (k << 9)), 0x7c0); -+ cdns_phy_reg_write(mhdp, (TX_TXCC_CPOST_MULT_00_0 | (k << 9)), 0x0); -+ cdns_phy_reg_write(mhdp, (TX_TXCC_CAL_SCLR_MULT_0 | (k << 9)), 0x120); -+ } -+} -+ -+static int hdmi_feedback_factor(struct cdns_mhdp_device *mhdp) -+{ -+ u32 feedback_factor; -+ -+ switch (mhdp->video_info.color_fmt) { -+ case YCBCR_4_2_2: -+ feedback_factor = 1000; -+ break; -+ case YCBCR_4_2_0: -+ switch (mhdp->video_info.color_depth) { -+ case 8: -+ feedback_factor = 500; -+ break; -+ case 10: -+ feedback_factor = 625; -+ break; -+ case 12: -+ feedback_factor = 750; -+ break; -+ case 16: -+ feedback_factor = 1000; -+ break; -+ default: -+ DRM_ERROR("Invalid ColorDepth\n"); -+ return 0; -+ } -+ break; -+ default: -+ /* Assume RGB/YUV444 */ -+ switch (mhdp->video_info.color_depth) { -+ case 10: -+ feedback_factor = 1250; -+ break; -+ case 12: -+ feedback_factor = 1500; -+ break; -+ case 16: -+ feedback_factor = 2000; -+ break; -+ default: -+ feedback_factor = 1000; -+ } -+ } -+ return feedback_factor; -+} -+ -+static int hdmi_phy_config(struct cdns_mhdp_device *mhdp, -+ const struct hdmi_ctrl *p_ctrl_table, -+ const struct hdmi_pll_tuning *p_pll_table, -+ char pclk_in) -+{ -+ const u32 num_lanes = 4; -+ u32 val, i, k; -+ -+ /* enable PHY isolation mode only for CMN */ -+ cdns_phy_reg_write(mhdp, PHY_PMA_ISOLATION_CTRL, 0xD000); -+ -+ /* set cmn_pll0_clk_datart1_div/cmn_pll0_clk_datart0_div dividers */ -+ val = cdns_phy_reg_read(mhdp, PHY_PMA_ISO_PLL_CTRL1); -+ val &= 0xFF00; -+ val |= 0x0012; -+ cdns_phy_reg_write(mhdp, PHY_PMA_ISO_PLL_CTRL1, val); -+ -+ /* assert PHY reset from isolation register */ -+ cdns_phy_reg_write(mhdp, PHY_ISO_CMN_CTRL, 0x0000); -+ /* assert PMA CMN reset */ -+ cdns_phy_reg_write(mhdp, PHY_PMA_ISO_CMN_CTRL, 0x0000); -+ -+ /* register XCVR_DIAG_BIDI_CTRL */ -+ for (k = 0; k < num_lanes; k++) -+ cdns_phy_reg_write(mhdp, XCVR_DIAG_BIDI_CTRL | (k << 9), 0x00FF); -+ -+ /* Describing Task phy_cfg_hdp */ -+ -+ val = cdns_phy_reg_read(mhdp, PHY_PMA_CMN_CTRL1); -+ val &= 0xFFF7; -+ val |= 0x0008; -+ cdns_phy_reg_write(mhdp, PHY_PMA_CMN_CTRL1, val); -+ -+ /* PHY Registers */ -+ val = cdns_phy_reg_read(mhdp, PHY_PMA_CMN_CTRL1); -+ val &= 0xCFFF; -+ val |= p_ctrl_table->cmn_ref_clk_dig_div << 12; -+ cdns_phy_reg_write(mhdp, PHY_PMA_CMN_CTRL1, val); -+ -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_CLK_CTL); -+ val &= 0x00FF; -+ val |= 0x1200; -+ cdns_phy_reg_write(mhdp, PHY_HDP_CLK_CTL, val); -+ -+ /* Common control module control and diagnostic registers */ -+ val = cdns_phy_reg_read(mhdp, CMN_CDIAG_REFCLK_CTRL); -+ val &= 0x8FFF; -+ val |= p_ctrl_table->ref_clk_divider_scaler << 12; -+ val |= 0x00C0; -+ cdns_phy_reg_write(mhdp, CMN_CDIAG_REFCLK_CTRL, val); -+ -+ /* High speed clock used */ -+ val = cdns_phy_reg_read(mhdp, CMN_DIAG_HSCLK_SEL); -+ val &= 0xFF00; -+ val |= (p_ctrl_table->cmnda_hs_clk_0_sel >> 1) << 0; -+ val |= (p_ctrl_table->cmnda_hs_clk_1_sel >> 1) << 4; -+ cdns_phy_reg_write(mhdp, CMN_DIAG_HSCLK_SEL, val); -+ -+ for (k = 0; k < num_lanes; k++) { -+ val = cdns_phy_reg_read(mhdp, (XCVR_DIAG_HSCLK_SEL | (k << 9))); -+ val &= 0xCFFF; -+ val |= (p_ctrl_table->cmnda_hs_clk_0_sel >> 1) << 12; -+ cdns_phy_reg_write(mhdp, (XCVR_DIAG_HSCLK_SEL | (k << 9)), val); -+ } -+ -+ /* PLL 0 control state machine registers */ -+ val = p_ctrl_table->vco_ring_select << 12; -+ cdns_phy_reg_write(mhdp, CMN_PLLSM0_USER_DEF_CTRL, val); -+ -+ if (pclk_in == true) -+ val = 0x30A0; -+ else { -+ val = cdns_phy_reg_read(mhdp, CMN_PLL0_VCOCAL_START); -+ val &= 0xFE00; -+ val |= p_pll_table->vco_cal_code; -+ } -+ cdns_phy_reg_write(mhdp, CMN_PLL0_VCOCAL_START, val); -+ -+ cdns_phy_reg_write(mhdp, CMN_PLL0_VCOCAL_INIT_TMR, 0x0064); -+ cdns_phy_reg_write(mhdp, CMN_PLL0_VCOCAL_ITER_TMR, 0x000A); -+ -+ /* Common functions control and diagnostics registers */ -+ val = p_ctrl_table->cmnda_pll0_hs_sym_div_sel << 8; -+ val |= p_ctrl_table->cmnda_pll0_ip_div; -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_INCLK_CTRL, val); -+ -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_OVRD, 0x0000); -+ -+ val = p_ctrl_table->cmnda_pll0_fb_div_high; -+ val |= (1 << 15); -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_FBH_OVRD, val); -+ -+ val = p_ctrl_table->cmnda_pll0_fb_div_low; -+ val |= (1 << 15); -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_FBL_OVRD, val); -+ -+ if (pclk_in == false) { -+ val = p_ctrl_table->cmnda_pll0_pxdiv_low; -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_PXL_DIVL, val); -+ -+ val = p_ctrl_table->cmnda_pll0_pxdiv_high; -+ val |= (1 << 15); -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_PXL_DIVH, val); -+ } -+ -+ val = p_pll_table->volt_to_current_coarse; -+ val |= (p_pll_table->volt_to_current) << 4; -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_V2I_TUNE, val); -+ -+ val = p_pll_table->charge_pump_gain; -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_CP_TUNE, val); -+ -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_LF_PROG, 0x0008); -+ -+ val = p_pll_table->pmos_ctrl; -+ val |= (p_pll_table->ndac_ctrl) << 8; -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_PTATIS_TUNE1, val); -+ -+ val = p_pll_table->ptat_ndac_ctrl; -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_PTATIS_TUNE2, val); -+ -+ if (pclk_in == true) -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_TEST_MODE, 0x0022); -+ else -+ cdns_phy_reg_write(mhdp, CMN_DIAG_PLL0_TEST_MODE, 0x0020); -+ cdns_phy_reg_write(mhdp, CMN_PSM_CLK_CTRL, 0x0016); -+ -+ /* Transceiver control and diagnostic registers */ -+ for (k = 0; k < num_lanes; k++) { -+ val = cdns_phy_reg_read(mhdp, (XCVR_DIAG_PLLDRC_CTRL | (k << 9))); -+ val &= 0xBFFF; -+ cdns_phy_reg_write(mhdp, (XCVR_DIAG_PLLDRC_CTRL | (k << 9)), val); -+ } -+ -+ for (k = 0; k < num_lanes; k++) { -+ val = cdns_phy_reg_read(mhdp, (TX_DIAG_TX_CTRL | (k << 9))); -+ val &= 0xFF3F; -+ val |= (p_ctrl_table->hsclk_div_tx_sub_rate >> 1) << 6; -+ cdns_phy_reg_write(mhdp, (TX_DIAG_TX_CTRL | (k << 9)), val); -+ } -+ -+ /* -+ * for single ended reference clock val |= 0x0030; -+ * for differential clock val |= 0x0000; -+ */ -+ val = cdns_phy_reg_read(mhdp, PHY_PMA_CMN_CTRL1); -+ val &= 0xFF8F; -+ if (pclk_in == true) -+ val |= 0x0030; -+ cdns_phy_reg_write(mhdp, PHY_PMA_CMN_CTRL1, val); -+ -+ /* for differential clock on the refclk_p and -+ * refclk_m off chip pins: CMN_DIAG_ACYA[8]=1'b1 */ -+ cdns_phy_reg_write(mhdp, CMN_DIAG_ACYA, 0x0100); -+ -+ /* Deassert PHY reset */ -+ cdns_phy_reg_write(mhdp, PHY_ISO_CMN_CTRL, 0x0001); -+ cdns_phy_reg_write(mhdp, PHY_PMA_ISO_CMN_CTRL, 0x0003); -+ -+ /* Power state machine registers */ -+ for (k = 0; k < num_lanes; k++) -+ cdns_phy_reg_write(mhdp, XCVR_PSM_RCTRL | (k << 9), 0xFEFC); -+ -+ /* Assert cmn_macro_pwr_en */ -+ cdns_phy_reg_write(mhdp, PHY_PMA_ISO_CMN_CTRL, 0x0013); -+ -+ /* wait for cmn_macro_pwr_en_ack */ -+ for (i = 0; i < 10; i++) { -+ val = cdns_phy_reg_read(mhdp, PHY_PMA_ISO_CMN_CTRL); -+ if (val & (1 << 5)) -+ break; -+ msleep(20); -+ } -+ if (i == 10) { -+ DRM_ERROR("PMA ouput macro power up failed\n"); -+ return false; -+ } -+ -+ /* wait for cmn_ready */ -+ for (i = 0; i < 10; i++) { -+ val = cdns_phy_reg_read(mhdp, PHY_PMA_CMN_CTRL1); -+ if (val & (1 << 0)) -+ break; -+ msleep(20); -+ } -+ if (i == 10) { -+ DRM_ERROR("PMA output ready failed\n"); -+ return false; -+ } -+ -+ for (k = 0; k < num_lanes; k++) { -+ cdns_phy_reg_write(mhdp, TX_PSC_A0 | (k << 9), 0x6791); -+ cdns_phy_reg_write(mhdp, TX_PSC_A1 | (k << 9), 0x6790); -+ cdns_phy_reg_write(mhdp, TX_PSC_A2 | (k << 9), 0x0090); -+ cdns_phy_reg_write(mhdp, TX_PSC_A3 | (k << 9), 0x0090); -+ -+ val = cdns_phy_reg_read(mhdp, RX_PSC_CAL | (k << 9)); -+ val &= 0xFFBB; -+ cdns_phy_reg_write(mhdp, RX_PSC_CAL | (k << 9), val); -+ -+ val = cdns_phy_reg_read(mhdp, RX_PSC_A0 | (k << 9)); -+ val &= 0xFFBB; -+ cdns_phy_reg_write(mhdp, RX_PSC_A0 | (k << 9), val); -+ } -+ return true; -+} -+ -+static int hdmi_phy_cfg_t28hpc(struct cdns_mhdp_device *mhdp, -+ struct drm_display_mode *mode) -+{ -+ const struct hdmi_ctrl *p_ctrl_table; -+ const struct hdmi_pll_tuning *p_pll_table; -+ const u32 refclk_freq_khz = 27000; -+ const u8 pclk_in = false; -+ u32 pixel_freq = mode->clock; -+ u32 vco_freq, char_freq; -+ u32 div_total, feedback_factor; -+ u32 i, ret; -+ -+ feedback_factor = hdmi_feedback_factor(mhdp); -+ -+ char_freq = pixel_freq * feedback_factor / 1000; -+ -+ DRM_INFO("Pixel clock: %d KHz, character clock: %d, bpc is %0d-bit.\n", -+ pixel_freq, char_freq, mhdp->video_info.color_depth); -+ -+ /* Get right row from the ctrl_table table. -+ * Check if 'pixel_freq_khz' value matches the PIXEL_CLK_FREQ column. -+ * Consider only the rows with FEEDBACK_FACTOR column matching feedback_factor. */ -+ for (i = 0; i < ARRAY_SIZE(imx8mq_ctrl_table); i++) { -+ if (feedback_factor == imx8mq_ctrl_table[i].feedback_factor && -+ pixel_freq == imx8mq_ctrl_table[i].pixel_clk_freq_min) { -+ p_ctrl_table = &imx8mq_ctrl_table[i]; -+ break; -+ } -+ } -+ if (i == ARRAY_SIZE(imx8mq_ctrl_table)) { -+ DRM_WARN("Pixel clk (%d KHz) not supported, color depth (%0d-bit)\n", -+ pixel_freq, mhdp->video_info.color_depth); -+ return 0; -+ } -+ -+ div_total = p_ctrl_table->pll_fb_div_total; -+ vco_freq = refclk_freq_khz * div_total / p_ctrl_table->cmnda_pll0_ip_div; -+ -+ /* Get right row from the imx8mq_pll_table table. -+ * Check if vco_freq_khz and feedback_div_total -+ * column matching with imx8mq_pll_table. */ -+ for (i = 0; i < ARRAY_SIZE(imx8mq_pll_table); i++) { -+ if (vco_freq == imx8mq_pll_table[i].vco_freq_min && -+ div_total == imx8mq_pll_table[i].feedback_div_total) { -+ p_pll_table = &imx8mq_pll_table[i]; -+ break; -+ } -+ } -+ if (i == ARRAY_SIZE(imx8mq_pll_table)) { -+ DRM_WARN("VCO (%d KHz) not supported\n", vco_freq); -+ return 0; -+ } -+ DRM_INFO("VCO frequency is %d KHz\n", vco_freq); -+ -+ ret = hdmi_phy_config(mhdp, p_ctrl_table, p_pll_table, pclk_in); -+ if (ret == false) -+ return 0; -+ -+ return char_freq; -+} -+ -+static int hdmi_phy_cfg_ss28fdsoi(struct cdns_mhdp_device *mhdp, -+ struct drm_display_mode *mode) -+{ -+ const struct hdmi_ctrl *p_ctrl_table; -+ const struct hdmi_pll_tuning *p_pll_table; -+ const u8 pclk_in = true; -+ u32 pixel_freq = mode->clock; -+ u32 vco_freq, char_freq; -+ u32 div_total, feedback_factor; -+ u32 ret, i; -+ -+ feedback_factor = hdmi_feedback_factor(mhdp); -+ -+ char_freq = pixel_freq * feedback_factor / 1000; -+ -+ DRM_INFO("Pixel clock: %d KHz, character clock: %d, bpc is %0d-bit.\n", -+ pixel_freq, char_freq, mhdp->video_info.color_depth); -+ -+ /* Get right row from the ctrl_table table. -+ * Check if 'pixel_freq_khz' value matches the PIXEL_CLK_FREQ column. -+ * Consider only the rows with FEEDBACK_FACTOR column matching feedback_factor. */ -+ for (i = 0; i < ARRAY_SIZE(imx8qm_ctrl_table); i++) { -+ if (feedback_factor == imx8qm_ctrl_table[i].feedback_factor && -+ pixel_freq >= imx8qm_ctrl_table[i].pixel_clk_freq_min && -+ pixel_freq <= imx8qm_ctrl_table[i].pixel_clk_freq_max) { -+ p_ctrl_table = &imx8qm_ctrl_table[i]; -+ break; -+ } -+ } -+ if (i == ARRAY_SIZE(imx8qm_ctrl_table)) { -+ DRM_WARN("Pixel clk (%d KHz) not supported, color depth (%0d-bit)\n", -+ pixel_freq, mhdp->video_info.color_depth); -+ return 0; -+ } -+ -+ div_total = p_ctrl_table->pll_fb_div_total; -+ vco_freq = pixel_freq * div_total / p_ctrl_table->cmnda_pll0_ip_div; -+ -+ /* Get right row from the imx8mq_pll_table table. -+ * Check if vco_freq_khz and feedback_div_total -+ * column matching with imx8mq_pll_table. */ -+ for (i = 0; i < ARRAY_SIZE(imx8qm_pll_table); i++) { -+ if (vco_freq >= imx8qm_pll_table[i].vco_freq_min && -+ vco_freq < imx8qm_pll_table[i].vco_freq_max && -+ div_total == imx8qm_pll_table[i].feedback_div_total) { -+ p_pll_table = &imx8qm_pll_table[i]; -+ break; -+ } -+ } -+ if (i == ARRAY_SIZE(imx8qm_pll_table)) { -+ DRM_WARN("VCO (%d KHz) not supported\n", vco_freq); -+ return 0; -+ } -+ DRM_INFO("VCO frequency is %d KHz\n", vco_freq); -+ -+ ret = hdmi_phy_config(mhdp, p_ctrl_table, p_pll_table, pclk_in); -+ if (ret == false) -+ return 0; -+ -+ return char_freq; -+} -+ -+static int hdmi_phy_power_up(struct cdns_mhdp_device *mhdp) -+{ -+ u32 val, i; -+ -+ /* set Power State to A2 */ -+ cdns_phy_reg_write(mhdp, PHY_HDP_MODE_CTRL, 0x0004); -+ -+ cdns_phy_reg_write(mhdp, TX_DIAG_ACYA_0, 1); -+ cdns_phy_reg_write(mhdp, TX_DIAG_ACYA_1, 1); -+ cdns_phy_reg_write(mhdp, TX_DIAG_ACYA_2, 1); -+ cdns_phy_reg_write(mhdp, TX_DIAG_ACYA_3, 1); -+ -+ /* Wait for Power State A2 Ack */ -+ for (i = 0; i < 10; i++) { -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_MODE_CTRL); -+ if (val & (1 << 6)) -+ break; -+ msleep(20); -+ } -+ if (i == 10) { -+ dev_err(mhdp->dev, "Wait A2 Ack failed\n"); -+ return -1; -+ } -+ -+ /* Power up ARC */ -+ hdmi_arc_config(mhdp); -+ -+ /* Configure PHY in A0 mode (PHY must be in the A0 power -+ * state in order to transmit data) -+ */ -+ //cdns_phy_reg_write(mhdp, PHY_HDP_MODE_CTRL, 0x0101); //imx8mq -+ cdns_phy_reg_write(mhdp, PHY_HDP_MODE_CTRL, 0x0001); -+ -+ /* Wait for Power State A0 Ack */ -+ for (i = 0; i < 10; i++) { -+ val = cdns_phy_reg_read(mhdp, PHY_HDP_MODE_CTRL); -+ if (val & (1 << 4)) -+ break; -+ msleep(20); -+ } -+ if (i == 10) { -+ dev_err(mhdp->dev, "Wait A0 Ack failed\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+bool cdns_hdmi_phy_video_valid_imx8mq(struct cdns_mhdp_device *mhdp) -+{ -+ u32 rate = mhdp->valid_mode->clock; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(imx8mq_ctrl_table); i++) -+ if(rate == imx8mq_ctrl_table[i].pixel_clk_freq_min) -+ return true; -+ return false; -+} -+ -+int cdns_hdmi_phy_set_imx8mq(struct cdns_mhdp_device *mhdp) -+{ -+ struct drm_display_mode *mode = &mhdp->mode; -+ int ret; -+ -+ /* Check HDMI FW alive before HDMI PHY init */ -+ ret = cdns_mhdp_check_alive(mhdp); -+ if (ret == false) { -+ DRM_ERROR("NO HDMI FW running\n"); -+ return -ENXIO; -+ } -+ -+ /* Configure PHY */ -+ mhdp->hdmi.char_rate = hdmi_phy_cfg_t28hpc(mhdp, mode); -+ if (mhdp->hdmi.char_rate == 0) { -+ DRM_ERROR("failed to set phy pclock\n"); -+ return -EINVAL; -+ } -+ -+ ret = hdmi_phy_power_up(mhdp); -+ if (ret < 0) -+ return ret; -+ -+ hdmi_phy_set_vswing(mhdp); -+ -+ return true; -+} -+ -+bool cdns_hdmi_phy_video_valid_imx8qm(struct cdns_mhdp_device *mhdp) -+{ -+ u32 rate = mhdp->valid_mode->clock; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(imx8qm_ctrl_table); i++) -+ if(rate >= imx8qm_ctrl_table[i].pixel_clk_freq_min && -+ rate <= imx8qm_ctrl_table[i].pixel_clk_freq_max) -+ return true; -+ return false; -+} -+ -+int cdns_hdmi_phy_set_imx8qm(struct cdns_mhdp_device *mhdp) -+{ -+ struct drm_display_mode *mode = &mhdp->mode; -+ int ret; -+ -+ /* Check HDMI FW alive before HDMI PHY init */ -+ ret = cdns_mhdp_check_alive(mhdp); -+ if (ret == false) { -+ DRM_ERROR("NO HDMI FW running\n"); -+ return -ENXIO; -+ } -+ -+ /* Configure PHY */ -+ mhdp->hdmi.char_rate = hdmi_phy_cfg_ss28fdsoi(mhdp, mode); -+ if (mhdp->hdmi.char_rate == 0) { -+ DRM_ERROR("failed to set phy pclock\n"); -+ return -EINVAL; -+ } -+ -+ ret = hdmi_phy_power_up(mhdp); -+ if (ret < 0) -+ return ret; -+ -+ hdmi_phy_set_vswing(mhdp); -+ -+ return true; -+} -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx.h b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx.h -new file mode 100644 -index 000000000000..fc3247dada2d ---- /dev/null -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx.h -@@ -0,0 +1,75 @@ -+/* -+ * Cadence High-Definition Multimedia Interface (HDMI) driver -+ * -+ * Copyright (C) 2019 NXP Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ */ -+#ifndef CDNS_MHDP_IMX_H_ -+#define CDNS_MHDP_IMX_H_ -+ -+#include -+#include -+ -+ -+struct imx_mhdp_device; -+ -+struct imx_hdp_clks { -+ struct clk *av_pll; -+ struct clk *dig_pll; -+ struct clk *clk_ipg; -+ struct clk *clk_core; -+ struct clk *clk_pxl; -+ struct clk *clk_pxl_mux; -+ struct clk *clk_pxl_link; -+ -+ struct clk *lpcg_hdp; -+ struct clk *lpcg_msi; -+ struct clk *lpcg_pxl; -+ struct clk *lpcg_vif; -+ struct clk *lpcg_lis; -+ struct clk *lpcg_apb; -+ struct clk *lpcg_apb_csr; -+ struct clk *lpcg_apb_ctrl; -+ -+ struct clk *lpcg_i2s; -+ struct clk *clk_i2s_bypass; -+}; -+ -+struct imx_mhdp_device { -+ struct cdns_mhdp_device mhdp; -+ struct drm_encoder encoder; -+ -+ struct mutex audio_mutex; -+ spinlock_t audio_lock; -+ bool connected; -+ bool active; -+ bool suspended; -+ struct imx_hdp_clks clks; -+ const struct firmware *fw; -+ const char *firmware_name; -+ -+ int bus_type; -+ -+ struct device *pd_mhdp_dev; -+ struct device *pd_pll0_dev; -+ struct device *pd_pll1_dev; -+ struct device_link *pd_mhdp_link; -+ struct device_link *pd_pll0_link; -+ struct device_link *pd_pll1_link; -+}; -+ -+void cdns_mhdp_plat_init_imx8qm(struct cdns_mhdp_device *mhdp); -+void cdns_mhdp_plat_deinit_imx8qm(struct cdns_mhdp_device *mhdp); -+void cdns_mhdp_pclk_rate_imx8qm(struct cdns_mhdp_device *mhdp); -+int cdns_mhdp_firmware_init_imx8qm(struct cdns_mhdp_device *mhdp); -+int cdns_mhdp_resume_imx8qm(struct cdns_mhdp_device *mhdp); -+int cdns_mhdp_suspend_imx8qm(struct cdns_mhdp_device *mhdp); -+int cdns_mhdp_power_on_imx8qm(struct cdns_mhdp_device *mhdp); -+int cdns_mhdp_power_on_ls1028a(struct cdns_mhdp_device *mhdp); -+void cdns_mhdp_pclk_rate_ls1028a(struct cdns_mhdp_device *mhdp); -+#endif /* CDNS_MHDP_IMX_H_ */ -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -new file mode 100644 -index 000000000000..a3ba3da4b05d ---- /dev/null -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -@@ -0,0 +1,638 @@ -+/* -+ * copyright (c) 2019 nxp semiconductor, inc. -+ * -+ * this program is free software; you can redistribute it and/or modify -+ * it under the terms of the gnu general public license version 2 as -+ * published by the free software foundation. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "cdns-mhdp-imx.h" -+ -+#define FW_IRAM_OFFSET 0x2000 -+#define FW_IRAM_SIZE 0x10000 -+#define FW_DRAM_SIZE 0x8000 -+ -+#define PLL_800MHZ (800000000) -+ -+#define HDP_DUAL_MODE_MIN_PCLK_RATE 300000 /* KHz */ -+#define HDP_SINGLE_MODE_MAX_WIDTH 1920 -+ -+#define CSR_PIXEL_LINK_MUX_CTL 0x00 -+#define CSR_PIXEL_LINK_MUX_VCP_OFFSET 5 -+#define CSR_PIXEL_LINK_MUX_HCP_OFFSET 4 -+ -+static bool imx8qm_video_dual_mode(struct cdns_mhdp_device *mhdp) -+{ -+ struct drm_display_mode *mode = &mhdp->mode; -+ return (mode->clock > HDP_DUAL_MODE_MIN_PCLK_RATE || -+ mode->hdisplay > HDP_SINGLE_MODE_MAX_WIDTH) ? true : false; -+} -+ -+static void imx8qm_pixel_link_mux(struct imx_mhdp_device *imx_mhdp) -+{ -+ struct drm_display_mode *mode = &imx_mhdp->mhdp.mode; -+ bool dual_mode; -+ u32 val; -+ -+ dual_mode = imx8qm_video_dual_mode(&imx_mhdp->mhdp); -+ -+ val = 0x4; /* RGB */ -+ if (dual_mode) -+ val |= 0x2; /* pixel link 0 and 1 are active */ -+ if (mode->flags & DRM_MODE_FLAG_PVSYNC) -+ val |= 1 << CSR_PIXEL_LINK_MUX_VCP_OFFSET; -+ if (mode->flags & DRM_MODE_FLAG_PHSYNC) -+ val |= 1 << CSR_PIXEL_LINK_MUX_HCP_OFFSET; -+ if (mode->flags & DRM_MODE_FLAG_INTERLACE) -+ val |= 0x2; -+ -+ writel(val, imx_mhdp->mhdp.regs_sec); -+} -+ -+static void imx8qm_pixel_link_valid(u32 dual_mode) -+{ -+ struct imx_sc_ipc *handle; -+ -+ imx_scu_get_handle(&handle); -+ -+ imx_sc_misc_set_control(handle, IMX_SC_R_DC_0, IMX_SC_C_PXL_LINK_MST1_VLD, 1); -+ if (dual_mode) -+ imx_sc_misc_set_control(handle, IMX_SC_R_DC_0, IMX_SC_C_PXL_LINK_MST2_VLD, 1); -+} -+ -+static void imx8qm_pixel_link_invalid(u32 dual_mode) -+{ -+ struct imx_sc_ipc *handle; -+ -+ imx_scu_get_handle(&handle); -+ -+ imx_sc_misc_set_control(handle, IMX_SC_R_DC_0, IMX_SC_C_PXL_LINK_MST1_VLD, 0); -+ if (dual_mode) -+ imx_sc_misc_set_control(handle, IMX_SC_R_DC_0, IMX_SC_C_PXL_LINK_MST2_VLD, 0); -+} -+ -+static void imx8qm_pixel_link_sync_enable(u32 dual_mode) -+{ -+ struct imx_sc_ipc *handle; -+ -+ imx_scu_get_handle(&handle); -+ -+ if (dual_mode) -+ imx_sc_misc_set_control(handle, IMX_SC_R_DC_0, IMX_SC_C_SYNC_CTRL, 3); -+ else -+ imx_sc_misc_set_control(handle, IMX_SC_R_DC_0, IMX_SC_C_SYNC_CTRL0, 1); -+} -+ -+static void imx8qm_pixel_link_sync_disable(u32 dual_mode) -+{ -+ struct imx_sc_ipc *handle; -+ -+ imx_scu_get_handle(&handle); -+ -+ if (dual_mode) -+ imx_sc_misc_set_control(handle, IMX_SC_R_DC_0, IMX_SC_C_SYNC_CTRL, 0); -+ else -+ imx_sc_misc_set_control(handle, IMX_SC_R_DC_0, IMX_SC_C_SYNC_CTRL0, 0); -+} -+ -+static void imx8qm_phy_reset(u8 reset) -+{ -+ struct imx_sc_ipc *handle; -+ -+ imx_scu_get_handle(&handle); -+ -+ /* set the pixel link mode and pixel type */ -+ imx_sc_misc_set_control(handle, IMX_SC_R_HDMI, IMX_SC_C_PHY_RESET, reset); -+} -+ -+static void imx8qm_clk_mux(u8 is_dp) -+{ -+ struct imx_sc_ipc *handle; -+ -+ imx_scu_get_handle(&handle); -+ -+ if (is_dp) -+ /* Enable the 24MHz for HDP PHY */ -+ imx_sc_misc_set_control(handle, IMX_SC_R_HDMI, IMX_SC_C_MODE, 1); -+ else -+ imx_sc_misc_set_control(handle, IMX_SC_R_HDMI, IMX_SC_C_MODE, 0); -+} -+ -+int imx8qm_clocks_init(struct imx_mhdp_device *imx_mhdp) -+{ -+ struct device *dev = imx_mhdp->mhdp.dev; -+ struct imx_hdp_clks *clks = &imx_mhdp->clks; -+ -+ clks->dig_pll = devm_clk_get(dev, "dig_pll"); -+ if (IS_ERR(clks->dig_pll)) { -+ dev_warn(dev, "failed to get dig pll clk\n"); -+ return PTR_ERR(clks->dig_pll); -+ } -+ -+ clks->av_pll = devm_clk_get(dev, "av_pll"); -+ if (IS_ERR(clks->av_pll)) { -+ dev_warn(dev, "failed to get av pll clk\n"); -+ return PTR_ERR(clks->av_pll); -+ } -+ -+ clks->clk_ipg = devm_clk_get(dev, "clk_ipg"); -+ if (IS_ERR(clks->clk_ipg)) { -+ dev_warn(dev, "failed to get dp ipg clk\n"); -+ return PTR_ERR(clks->clk_ipg); -+ } -+ -+ clks->clk_core = devm_clk_get(dev, "clk_core"); -+ if (IS_ERR(clks->clk_core)) { -+ dev_warn(dev, "failed to get hdp core clk\n"); -+ return PTR_ERR(clks->clk_core); -+ } -+ -+ clks->clk_pxl = devm_clk_get(dev, "clk_pxl"); -+ if (IS_ERR(clks->clk_pxl)) { -+ dev_warn(dev, "failed to get pxl clk\n"); -+ return PTR_ERR(clks->clk_pxl); -+ } -+ -+ clks->clk_pxl_mux = devm_clk_get(dev, "clk_pxl_mux"); -+ if (IS_ERR(clks->clk_pxl_mux)) { -+ dev_warn(dev, "failed to get pxl mux clk\n"); -+ return PTR_ERR(clks->clk_pxl_mux); -+ } -+ -+ clks->clk_pxl_link = devm_clk_get(dev, "clk_pxl_link"); -+ if (IS_ERR(clks->clk_pxl_mux)) { -+ dev_warn(dev, "failed to get pxl link clk\n"); -+ return PTR_ERR(clks->clk_pxl_link); -+ } -+ -+ clks->lpcg_hdp = devm_clk_get(dev, "lpcg_hdp"); -+ if (IS_ERR(clks->lpcg_hdp)) { -+ dev_warn(dev, "failed to get lpcg hdp clk\n"); -+ return PTR_ERR(clks->lpcg_hdp); -+ } -+ -+ clks->lpcg_msi = devm_clk_get(dev, "lpcg_msi"); -+ if (IS_ERR(clks->lpcg_msi)) { -+ dev_warn(dev, "failed to get lpcg msi clk\n"); -+ return PTR_ERR(clks->lpcg_msi); -+ } -+ -+ clks->lpcg_pxl = devm_clk_get(dev, "lpcg_pxl"); -+ if (IS_ERR(clks->lpcg_pxl)) { -+ dev_warn(dev, "failed to get lpcg pxl clk\n"); -+ return PTR_ERR(clks->lpcg_pxl); -+ } -+ -+ clks->lpcg_vif = devm_clk_get(dev, "lpcg_vif"); -+ if (IS_ERR(clks->lpcg_vif)) { -+ dev_warn(dev, "failed to get lpcg vif clk\n"); -+ return PTR_ERR(clks->lpcg_vif); -+ } -+ -+ clks->lpcg_lis = devm_clk_get(dev, "lpcg_lis"); -+ if (IS_ERR(clks->lpcg_lis)) { -+ dev_warn(dev, "failed to get lpcg lis clk\n"); -+ return PTR_ERR(clks->lpcg_lis); -+ } -+ -+ clks->lpcg_apb = devm_clk_get(dev, "lpcg_apb"); -+ if (IS_ERR(clks->lpcg_apb)) { -+ dev_warn(dev, "failed to get lpcg apb clk\n"); -+ return PTR_ERR(clks->lpcg_apb); -+ } -+ -+ clks->lpcg_apb_csr = devm_clk_get(dev, "lpcg_apb_csr"); -+ if (IS_ERR(clks->lpcg_apb_csr)) { -+ dev_warn(dev, "failed to get apb csr clk\n"); -+ return PTR_ERR(clks->lpcg_apb_csr); -+ } -+ -+ clks->lpcg_apb_ctrl = devm_clk_get(dev, "lpcg_apb_ctrl"); -+ if (IS_ERR(clks->lpcg_apb_ctrl)) { -+ dev_warn(dev, "failed to get lpcg apb ctrl clk\n"); -+ return PTR_ERR(clks->lpcg_apb_ctrl); -+ } -+ -+ clks->clk_i2s_bypass = devm_clk_get(dev, "clk_i2s_bypass"); -+ if (IS_ERR(clks->clk_i2s_bypass)) { -+ dev_err(dev, "failed to get i2s bypass clk\n"); -+ return PTR_ERR(clks->clk_i2s_bypass); -+ } -+ -+ clks->lpcg_i2s = devm_clk_get(dev, "lpcg_i2s"); -+ if (IS_ERR(clks->lpcg_i2s)) { -+ dev_err(dev, "failed to get lpcg i2s clk\n"); -+ return PTR_ERR(clks->lpcg_i2s); -+ } -+ return true; -+} -+ -+static int imx8qm_pixel_clk_enable(struct imx_mhdp_device *imx_mhdp) -+{ -+ struct imx_hdp_clks *clks = &imx_mhdp->clks; -+ struct device *dev = imx_mhdp->mhdp.dev; -+ int ret; -+ -+ ret = clk_prepare_enable(clks->av_pll); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre av pll error\n", __func__); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(clks->clk_pxl); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk pxl error\n", __func__); -+ return ret; -+ } -+ ret = clk_prepare_enable(clks->clk_pxl_mux); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk pxl mux error\n", __func__); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(clks->clk_pxl_link); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk pxl link error\n", __func__); -+ return ret; -+ } -+ ret = clk_prepare_enable(clks->lpcg_vif); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk vif error\n", __func__); -+ return ret; -+ } -+ ret = clk_prepare_enable(clks->lpcg_pxl); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre lpcg pxl error\n", __func__); -+ return ret; -+ } -+ ret = clk_prepare_enable(clks->lpcg_hdp); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre lpcg hdp error\n", __func__); -+ return ret; -+ } -+ return ret; -+} -+ -+static void imx8qm_pixel_clk_disable(struct imx_mhdp_device *imx_mhdp) -+{ -+ struct imx_hdp_clks *clks = &imx_mhdp->clks; -+ -+ clk_disable_unprepare(clks->lpcg_pxl); -+ clk_disable_unprepare(clks->lpcg_hdp); -+ clk_disable_unprepare(clks->lpcg_vif); -+ clk_disable_unprepare(clks->clk_pxl); -+ clk_disable_unprepare(clks->clk_pxl_link); -+ clk_disable_unprepare(clks->clk_pxl_mux); -+ clk_disable_unprepare(clks->av_pll); -+} -+ -+static void imx8qm_pixel_clk_set_rate(struct imx_mhdp_device *imx_mhdp, u32 pclock) -+{ -+ bool dual_mode = imx8qm_video_dual_mode(&imx_mhdp->mhdp); -+ struct imx_hdp_clks *clks = &imx_mhdp->clks; -+ -+ /* pixel clock for HDMI */ -+ clk_set_rate(clks->av_pll, pclock); -+ -+ if (dual_mode == true) { -+ clk_set_rate(clks->clk_pxl, pclock/2); -+ clk_set_rate(clks->clk_pxl_link, pclock/2); -+ } else { -+ clk_set_rate(clks->clk_pxl_link, pclock); -+ clk_set_rate(clks->clk_pxl, pclock); -+ } -+ clk_set_rate(clks->clk_pxl_mux, pclock); -+} -+ -+static int imx8qm_ipg_clk_enable(struct imx_mhdp_device *imx_mhdp) -+{ -+ int ret; -+ struct imx_hdp_clks *clks = &imx_mhdp->clks; -+ struct device *dev = imx_mhdp->mhdp.dev; -+ -+ ret = clk_prepare_enable(clks->dig_pll); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre dig pll error\n", __func__); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(clks->clk_ipg); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk_ipg error\n", __func__); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(clks->clk_core); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk core error\n", __func__); -+ return ret; -+ } -+ -+ ret = clk_prepare_enable(clks->lpcg_apb); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk apb error\n", __func__); -+ return ret; -+ } -+ ret = clk_prepare_enable(clks->lpcg_lis); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk lis error\n", __func__); -+ return ret; -+ } -+ ret = clk_prepare_enable(clks->lpcg_msi); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk msierror\n", __func__); -+ return ret; -+ } -+ ret = clk_prepare_enable(clks->lpcg_apb_csr); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk apb csr error\n", __func__); -+ return ret; -+ } -+ ret = clk_prepare_enable(clks->lpcg_apb_ctrl); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk apb ctrl error\n", __func__); -+ return ret; -+ } -+ ret = clk_prepare_enable(clks->lpcg_i2s); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk i2s error\n", __func__); -+ return ret; -+ } -+ ret = clk_prepare_enable(clks->clk_i2s_bypass); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk i2s bypass error\n", __func__); -+ return ret; -+ } -+ return ret; -+} -+ -+static void imx8qm_ipg_clk_set_rate(struct imx_mhdp_device *imx_mhdp) -+{ -+ struct imx_hdp_clks *clks = &imx_mhdp->clks; -+ -+ /* ipg/core clock */ -+ clk_set_rate(clks->dig_pll, PLL_800MHZ); -+ clk_set_rate(clks->clk_core, PLL_800MHZ/4); -+ clk_set_rate(clks->clk_ipg, PLL_800MHZ/8); -+} -+ -+static void imx8qm_detach_pm_domains(struct imx_mhdp_device *imx_mhdp) -+{ -+ if (imx_mhdp->pd_pll1_link && !IS_ERR(imx_mhdp->pd_pll1_link)) -+ device_link_del(imx_mhdp->pd_pll1_link); -+ if (imx_mhdp->pd_pll1_dev && !IS_ERR(imx_mhdp->pd_pll1_dev)) -+ dev_pm_domain_detach(imx_mhdp->pd_pll1_dev, true); -+ -+ if (imx_mhdp->pd_pll0_link && !IS_ERR(imx_mhdp->pd_pll0_link)) -+ device_link_del(imx_mhdp->pd_pll0_link); -+ if (imx_mhdp->pd_pll0_dev && !IS_ERR(imx_mhdp->pd_pll0_dev)) -+ dev_pm_domain_detach(imx_mhdp->pd_pll0_dev, true); -+ -+ if (imx_mhdp->pd_mhdp_link && !IS_ERR(imx_mhdp->pd_mhdp_link)) -+ device_link_del(imx_mhdp->pd_mhdp_link); -+ if (imx_mhdp->pd_mhdp_dev && !IS_ERR(imx_mhdp->pd_mhdp_dev)) -+ dev_pm_domain_detach(imx_mhdp->pd_mhdp_dev, true); -+ -+ imx_mhdp->pd_mhdp_dev = NULL; -+ imx_mhdp->pd_mhdp_link = NULL; -+ imx_mhdp->pd_pll0_dev = NULL; -+ imx_mhdp->pd_pll0_link = NULL; -+ imx_mhdp->pd_pll1_dev = NULL; -+ imx_mhdp->pd_pll1_link = NULL; -+} -+ -+static int imx8qm_attach_pm_domains(struct imx_mhdp_device *imx_mhdp) -+{ -+ struct device *dev = imx_mhdp->mhdp.dev; -+ u32 flags = DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE; -+ int ret = 0; -+ -+ imx_mhdp->pd_mhdp_dev = dev_pm_domain_attach_by_name(dev, "hdmi"); -+ if (IS_ERR(imx_mhdp->pd_mhdp_dev)) { -+ ret = PTR_ERR(imx_mhdp->pd_mhdp_dev); -+ dev_err(dev, "Failed to attach dc pd dev: %d\n", ret); -+ goto fail; -+ } -+ imx_mhdp->pd_mhdp_link = device_link_add(dev, imx_mhdp->pd_mhdp_dev, flags); -+ if (IS_ERR(imx_mhdp->pd_mhdp_link)) { -+ ret = PTR_ERR(imx_mhdp->pd_mhdp_link); -+ dev_err(dev, "Failed to add device link to dc pd dev: %d\n", -+ ret); -+ goto fail; -+ } -+ -+ imx_mhdp->pd_pll0_dev = dev_pm_domain_attach_by_name(dev, "pll0"); -+ if (IS_ERR(imx_mhdp->pd_pll0_dev)) { -+ ret = PTR_ERR(imx_mhdp->pd_pll0_dev); -+ dev_err(dev, "Failed to attach pll0 pd dev: %d\n", ret); -+ goto fail; -+ } -+ imx_mhdp->pd_pll0_link = device_link_add(dev, imx_mhdp->pd_pll0_dev, flags); -+ if (IS_ERR(imx_mhdp->pd_pll0_link)) { -+ ret = PTR_ERR(imx_mhdp->pd_pll0_link); -+ dev_err(dev, "Failed to add device link to pll0 pd dev: %d\n", -+ ret); -+ goto fail; -+ } -+ -+ imx_mhdp->pd_pll1_dev = dev_pm_domain_attach_by_name(dev, "pll1"); -+ if (IS_ERR(imx_mhdp->pd_pll1_dev)) { -+ ret = PTR_ERR(imx_mhdp->pd_pll1_dev); -+ dev_err(dev, "Failed to attach pll0 pd dev: %d\n", ret); -+ goto fail; -+ } -+ imx_mhdp->pd_pll1_link = device_link_add(dev, imx_mhdp->pd_pll1_dev, flags); -+ if (IS_ERR(imx_mhdp->pd_pll1_link)) { -+ ret = PTR_ERR(imx_mhdp->pd_pll1_link); -+ dev_err(dev, "Failed to add device link to pll1 pd dev: %d\n", -+ ret); -+ goto fail; -+ } -+fail: -+ imx8qm_detach_pm_domains(imx_mhdp); -+ return ret; -+} -+ -+int cdns_mhdp_power_on_imx8qm(struct cdns_mhdp_device *mhdp) -+{ -+ struct imx_mhdp_device *imx_mhdp = -+ container_of(mhdp, struct imx_mhdp_device, mhdp); -+ /* Power on PM Domains */ -+ -+ imx8qm_attach_pm_domains(imx_mhdp); -+ -+ /* clock init and rate set */ -+ imx8qm_clocks_init(imx_mhdp); -+ -+ imx8qm_ipg_clk_set_rate(imx_mhdp); -+ -+ /* Init pixel clock with 148.5MHz before FW init */ -+ imx8qm_pixel_clk_set_rate(imx_mhdp, 148500000); -+ -+ imx8qm_ipg_clk_enable(imx_mhdp); -+ -+ imx8qm_clk_mux(imx_mhdp->mhdp.plat_data->is_dp); -+ -+ imx8qm_pixel_clk_enable(imx_mhdp); -+ -+ imx8qm_phy_reset(1); -+ -+ return 0; -+} -+ -+void cdns_mhdp_plat_init_imx8qm(struct cdns_mhdp_device *mhdp) -+{ -+ struct imx_mhdp_device *imx_mhdp = -+ container_of(mhdp, struct imx_mhdp_device, mhdp); -+ bool dual_mode = imx8qm_video_dual_mode(&imx_mhdp->mhdp); -+ -+ imx8qm_pixel_link_sync_disable(dual_mode); -+ imx8qm_pixel_link_invalid(dual_mode); -+} -+ -+void cdns_mhdp_plat_deinit_imx8qm(struct cdns_mhdp_device *mhdp) -+{ -+ struct imx_mhdp_device *imx_mhdp = -+ container_of(mhdp, struct imx_mhdp_device, mhdp); -+ bool dual_mode = imx8qm_video_dual_mode(&imx_mhdp->mhdp); -+ -+ imx8qm_pixel_link_valid(dual_mode); -+ imx8qm_pixel_link_sync_enable(dual_mode); -+} -+ -+void cdns_mhdp_pclk_rate_imx8qm(struct cdns_mhdp_device *mhdp) -+{ -+ struct imx_mhdp_device *imx_mhdp = -+ container_of(mhdp, struct imx_mhdp_device, mhdp); -+ -+ /* set pixel clock before video mode setup */ -+ imx8qm_pixel_clk_disable(imx_mhdp); -+ -+ imx8qm_pixel_clk_set_rate(imx_mhdp, imx_mhdp->mhdp.mode.clock * 1000); -+ -+ imx8qm_pixel_clk_enable(imx_mhdp); -+ -+ /* Config pixel link mux */ -+ imx8qm_pixel_link_mux(imx_mhdp); -+} -+ -+int cdns_mhdp_firmware_write_section(struct imx_mhdp_device *imx_mhdp, -+ const u8 *data, int size, int addr) -+{ -+ int i; -+ -+ for (i = 0; i < size; i += 4) { -+ u32 val = (unsigned int)data[i] << 0 | -+ (unsigned int)data[i + 1] << 8 | -+ (unsigned int)data[i + 2] << 16 | -+ (unsigned int)data[i + 3] << 24; -+ cdns_mhdp_bus_write(val, &imx_mhdp->mhdp, addr + i); -+ } -+ -+ return 0; -+} -+ -+static void cdns_mhdp_firmware_load_cont(const struct firmware *fw, void *context) -+{ -+ struct imx_mhdp_device *imx_mhdp = context; -+ -+ imx_mhdp->fw = fw; -+} -+ -+static int cdns_mhdp_firmware_load(struct imx_mhdp_device *imx_mhdp) -+{ -+ const u8 *iram; -+ const u8 *dram; -+ u32 rate; -+ int ret; -+ -+ /* configure HDMI/DP core clock */ -+ rate = clk_get_rate(imx_mhdp->clks.clk_core); -+ if (imx_mhdp->mhdp.is_ls1028a) -+ rate = rate / 4; -+ -+ cdns_mhdp_set_fw_clk(&imx_mhdp->mhdp, rate); -+ -+ /* skip fw loading if none is specified */ -+ if (!imx_mhdp->firmware_name) -+ goto out; -+ -+ if (!imx_mhdp->fw) { -+ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOUEVENT, -+ imx_mhdp->firmware_name, -+ imx_mhdp->mhdp.dev, GFP_KERNEL, -+ imx_mhdp, -+ cdns_mhdp_firmware_load_cont); -+ if (ret < 0) { -+ DRM_ERROR("failed to load firmware\n"); -+ return -ENOENT; -+ } -+ } else { -+ iram = imx_mhdp->fw->data + FW_IRAM_OFFSET; -+ dram = iram + FW_IRAM_SIZE; -+ -+ cdns_mhdp_firmware_write_section(imx_mhdp, iram, FW_IRAM_SIZE, ADDR_IMEM); -+ cdns_mhdp_firmware_write_section(imx_mhdp, dram, FW_DRAM_SIZE, ADDR_DMEM); -+ } -+ -+out: -+ /* un-reset ucpu */ -+ cdns_mhdp_bus_write(0, &imx_mhdp->mhdp, APB_CTRL); -+ DRM_INFO("Started firmware!\n"); -+ -+ return 0; -+} -+ -+int cdns_mhdp_firmware_init_imx8qm(struct cdns_mhdp_device *mhdp) -+{ -+ struct imx_mhdp_device *imx_mhdp = -+ container_of(mhdp, struct imx_mhdp_device, mhdp); -+ int ret; -+ -+ /* load firmware */ -+ ret = cdns_mhdp_firmware_load(imx_mhdp); -+ if (ret) -+ return ret; -+ -+ ret = cdns_mhdp_check_alive(&imx_mhdp->mhdp); -+ if (ret == false) { -+ DRM_ERROR("NO HDMI FW running\n"); -+ return -ENXIO; -+ } -+ -+ /* turn on IP activity */ -+ cdns_mhdp_set_firmware_active(&imx_mhdp->mhdp, 1); -+ -+ DRM_INFO("HDP FW Version - ver %d verlib %d\n", -+ cdns_mhdp_bus_read(mhdp, VER_L) + (cdns_mhdp_bus_read(mhdp, VER_H) << 8), -+ cdns_mhdp_bus_read(mhdp, VER_LIB_H_ADDR) + (cdns_mhdp_bus_read(mhdp, VER_LIB_H_ADDR) << 8)); -+ -+ return 0; -+} -+ -+int cdns_mhdp_suspend_imx8qm(struct cdns_mhdp_device *mhdp) -+{ -+ struct imx_mhdp_device *imx_mhdp = -+ container_of(mhdp, struct imx_mhdp_device, mhdp); -+ -+ imx8qm_pixel_clk_disable(imx_mhdp); -+ -+ return 0; -+} -+ -+int cdns_mhdp_resume_imx8qm(struct cdns_mhdp_device *mhdp) -+{ -+ struct imx_mhdp_device *imx_mhdp = -+ container_of(mhdp, struct imx_mhdp_device, mhdp); -+ -+ imx8qm_pixel_clk_enable(imx_mhdp); -+ -+ return cdns_mhdp_firmware_init_imx8qm(mhdp); -+} -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c -new file mode 100644 -index 000000000000..3acbdf575ee2 ---- /dev/null -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c -@@ -0,0 +1,259 @@ -+/* -+ * copyright (c) 2019 nxp semiconductor, inc. -+ * -+ * this program is free software; you can redistribute it and/or modify -+ * it under the terms of the gnu general public license version 2 as -+ * published by the free software foundation. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "cdns-mhdp-imx.h" -+#include "cdns-mhdp-phy.h" -+#include "../ipuv3/imx-drm.h" -+ -+static void cdns_mhdp_imx_encoder_disable(struct drm_encoder *encoder) -+{ -+ struct drm_bridge *bridge = drm_bridge_chain_get_first_bridge(encoder); -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ -+ cdns_mhdp_plat_call(mhdp, plat_init); -+} -+ -+static void cdns_mhdp_imx_encoder_enable(struct drm_encoder *encoder) -+{ -+ struct drm_bridge *bridge = drm_bridge_chain_get_first_bridge(encoder); -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ -+ cdns_mhdp_plat_call(mhdp, plat_deinit); -+} -+ -+static int cdns_mhdp_imx_encoder_atomic_check(struct drm_encoder *encoder, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state) -+{ -+ struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc_state); -+ struct drm_bridge *bridge = drm_bridge_chain_get_first_bridge(encoder); -+ struct cdns_mhdp_device *mhdp = bridge->driver_private; -+ -+ if (mhdp->plat_data->video_format != 0) -+ imx_crtc_state->bus_format = mhdp->plat_data->video_format; -+ -+ if (mhdp->force_mode_set) -+ crtc_state->mode_changed = true; -+ -+ return 0; -+} -+ -+static const struct drm_encoder_helper_funcs cdns_mhdp_imx_encoder_helper_funcs = { -+ .enable = cdns_mhdp_imx_encoder_enable, -+ .disable = cdns_mhdp_imx_encoder_disable, -+ .atomic_check = cdns_mhdp_imx_encoder_atomic_check, -+}; -+ -+static const struct drm_encoder_funcs cdns_mhdp_imx_encoder_funcs = { -+ .destroy = drm_encoder_cleanup, -+}; -+ -+static struct cdns_plat_data imx8mq_hdmi_drv_data = { -+ .plat_name = "imx8mq-hdmi", -+ .bind = cdns_hdmi_bind, -+ .unbind = cdns_hdmi_unbind, -+ .phy_set = cdns_hdmi_phy_set_imx8mq, -+ .phy_video_valid = cdns_hdmi_phy_video_valid_imx8mq, -+ .bus_type = BUS_TYPE_NORMAL_APB, -+}; -+ -+static struct cdns_plat_data imx8mq_dp_drv_data = { -+ .plat_name = "imx8mq-dp", -+ .bind = cdns_dp_bind, -+ .unbind = cdns_dp_unbind, -+ .phy_set = cdns_dp_phy_set_imx8mq, -+ .bus_type = BUS_TYPE_NORMAL_APB, -+}; -+ -+static struct cdns_plat_data imx8qm_hdmi_drv_data = { -+ .plat_name = "imx8qm-hdmi", -+ .bind = cdns_hdmi_bind, -+ .unbind = cdns_hdmi_unbind, -+ .phy_set = cdns_hdmi_phy_set_imx8qm, -+ .phy_video_valid = cdns_hdmi_phy_video_valid_imx8qm, -+ .power_on = cdns_mhdp_power_on_imx8qm, -+ .firmware_init = cdns_mhdp_firmware_init_imx8qm, -+ .resume = cdns_mhdp_resume_imx8qm, -+ .suspend = cdns_mhdp_suspend_imx8qm, -+ .pclk_rate = cdns_mhdp_pclk_rate_imx8qm, -+ .plat_init = cdns_mhdp_plat_init_imx8qm, -+ .plat_deinit = cdns_mhdp_plat_deinit_imx8qm, -+ .bus_type = BUS_TYPE_LOW4K_APB, -+ .video_format = MEDIA_BUS_FMT_RGB101010_1X30, -+}; -+ -+static struct cdns_plat_data imx8qm_dp_drv_data = { -+ .plat_name = "imx8qm-dp", -+ .bind = cdns_dp_bind, -+ .unbind = cdns_dp_unbind, -+ .phy_set = cdns_dp_phy_set_imx8qm, -+ .power_on = cdns_mhdp_power_on_imx8qm, -+ .firmware_init = cdns_mhdp_firmware_init_imx8qm, -+ .pclk_rate = cdns_mhdp_pclk_rate_imx8qm, -+ .plat_init = cdns_mhdp_plat_init_imx8qm, -+ .plat_deinit = cdns_mhdp_plat_deinit_imx8qm, -+ .bus_type = BUS_TYPE_LOW4K_APB, -+ .video_format = MEDIA_BUS_FMT_RGB101010_1X30, -+ .is_dp = true, -+}; -+ -+static struct cdns_plat_data ls1028a_dp_drv_data = { -+ .bind = cdns_dp_bind, -+ .unbind = cdns_dp_unbind, -+ .phy_set = cdns_dp_phy_set_imx8mq, -+ .power_on = cdns_mhdp_power_on_ls1028a, -+ .firmware_init = cdns_mhdp_firmware_init_imx8qm, -+ .pclk_rate = cdns_mhdp_pclk_rate_ls1028a, -+ .bus_type = BUS_TYPE_NORMAL_APB, -+}; -+ -+static const struct of_device_id cdns_mhdp_imx_dt_ids[] = { -+ { .compatible = "cdn,imx8mq-hdmi", -+ .data = &imx8mq_hdmi_drv_data -+ }, -+ { .compatible = "cdn,imx8mq-dp", -+ .data = &imx8mq_dp_drv_data -+ }, -+ { .compatible = "cdn,imx8qm-hdmi", -+ .data = &imx8qm_hdmi_drv_data -+ }, -+ { .compatible = "cdn,imx8qm-dp", -+ .data = &imx8qm_dp_drv_data -+ }, -+ { .compatible = "cdn,ls1028a-dp", -+ .data = &ls1028a_dp_drv_data -+ }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, cdns_mhdp_imx_dt_ids); -+ -+static int cdns_mhdp_imx_bind(struct device *dev, struct device *master, -+ void *data) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ const struct cdns_plat_data *plat_data; -+ const struct of_device_id *match; -+ struct drm_device *drm = data; -+ struct drm_encoder *encoder; -+ struct imx_mhdp_device *imx_mhdp; -+ int ret; -+ -+ if (!pdev->dev.of_node) -+ return -ENODEV; -+ -+ imx_mhdp = devm_kzalloc(&pdev->dev, sizeof(*imx_mhdp), GFP_KERNEL); -+ if (!imx_mhdp) -+ return -ENOMEM; -+ -+ match = of_match_node(cdns_mhdp_imx_dt_ids, pdev->dev.of_node); -+ plat_data = match->data; -+ encoder = &imx_mhdp->encoder; -+ -+ encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); -+ -+ ret = of_property_read_string(pdev->dev.of_node, "firmware-name", -+ &imx_mhdp->firmware_name); -+ /* -+ * If we failed to find the CRTC(s) which this encoder is -+ * supposed to be connected to, it's because the CRTC has -+ * not been registered yet. Defer probing, and hope that -+ * the required CRTC is added later. -+ */ -+ if (encoder->possible_crtcs == 0) -+ return -EPROBE_DEFER; -+ -+ drm_encoder_helper_add(encoder, &cdns_mhdp_imx_encoder_helper_funcs); -+ drm_encoder_init(drm, encoder, &cdns_mhdp_imx_encoder_funcs, -+ DRM_MODE_ENCODER_TMDS, NULL); -+ -+ -+ imx_mhdp->mhdp.plat_data = plat_data; -+ imx_mhdp->mhdp.dev = dev; -+ imx_mhdp->mhdp.bus_type = plat_data->bus_type; -+ ret = plat_data->bind(pdev, encoder, &imx_mhdp->mhdp); -+ /* -+ * If cdns_mhdp_bind() fails we'll never call cdns_mhdp_unbind(), -+ * which would have called the encoder cleanup. Do it manually. -+ */ -+ if (ret < 0) -+ drm_encoder_cleanup(encoder); -+ -+ return ret; -+} -+ -+static void cdns_mhdp_imx_unbind(struct device *dev, struct device *master, -+ void *data) -+{ -+ struct imx_mhdp_device *imx_mhdp = dev_get_drvdata(dev); -+ -+ imx_mhdp->mhdp.plat_data->unbind(dev); -+} -+ -+static const struct component_ops cdns_mhdp_imx_ops = { -+ .bind = cdns_mhdp_imx_bind, -+ .unbind = cdns_mhdp_imx_unbind, -+}; -+ -+static int cdns_mhdp_imx_suspend(struct device *dev) -+{ -+ struct imx_mhdp_device *imx_mhdp = dev_get_drvdata(dev); -+ -+ cdns_mhdp_plat_call(&imx_mhdp->mhdp, suspend); -+ -+ return 0; -+} -+ -+static int cdns_mhdp_imx_resume(struct device *dev) -+{ -+ struct imx_mhdp_device *imx_mhdp = dev_get_drvdata(dev); -+ -+ cdns_mhdp_plat_call(&imx_mhdp->mhdp, resume); -+ -+ return 0; -+} -+ -+static int cdns_mhdp_imx_probe(struct platform_device *pdev) -+{ -+ return component_add(&pdev->dev, &cdns_mhdp_imx_ops); -+} -+ -+static int cdns_mhdp_imx_remove(struct platform_device *pdev) -+{ -+ component_del(&pdev->dev, &cdns_mhdp_imx_ops); -+ -+ return 0; -+} -+ -+static const struct dev_pm_ops cdns_mhdp_imx_pm_ops = { -+ SET_LATE_SYSTEM_SLEEP_PM_OPS(cdns_mhdp_imx_suspend, cdns_mhdp_imx_resume) -+}; -+ -+static struct platform_driver cdns_mhdp_imx_platform_driver = { -+ .probe = cdns_mhdp_imx_probe, -+ .remove = cdns_mhdp_imx_remove, -+ .driver = { -+ .name = "cdns-mhdp-imx", -+ .of_match_table = cdns_mhdp_imx_dt_ids, -+ .pm = &cdns_mhdp_imx_pm_ops, -+ }, -+}; -+ -+module_platform_driver(cdns_mhdp_imx_platform_driver); -+ -+MODULE_AUTHOR("Sandor YU "); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:cdnhdmi-imx"); -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-ls1028a.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-ls1028a.c -new file mode 100644 -index 000000000000..4cc71301f5fe ---- /dev/null -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-ls1028a.c -@@ -0,0 +1,110 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright 2019 NXP -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+#include "cdns-mhdp-imx.h" -+ -+static const struct of_device_id scfg_device_ids[] = { -+ { .compatible = "fsl,ls1028a-scfg", }, -+ {} -+}; -+ -+static void ls1028a_phy_reset(u8 reset) -+{ -+ struct device_node *scfg_node; -+ void __iomem *scfg_base = NULL; -+ -+ scfg_node = of_find_matching_node(NULL, scfg_device_ids); -+ if (scfg_node) -+ scfg_base = of_iomap(scfg_node, 0); -+ -+ iowrite32(reset, scfg_base + 0x230); -+} -+ -+int ls1028a_clocks_init(struct imx_mhdp_device *imx_mhdp) -+{ -+ struct device *dev = imx_mhdp->mhdp.dev; -+ struct imx_hdp_clks *clks = &imx_mhdp->clks; -+ -+ clks->clk_core = devm_clk_get(dev, "clk_core"); -+ if (IS_ERR(clks->clk_core)) { -+ dev_warn(dev, "failed to get hdp core clk\n"); -+ return PTR_ERR(clks->clk_core); -+ } -+ -+ clks->clk_pxl = devm_clk_get(dev, "clk_pxl"); -+ if (IS_ERR(clks->clk_pxl)) { -+ dev_warn(dev, "failed to get pxl clk\n"); -+ return PTR_ERR(clks->clk_pxl); -+ } -+ -+ return true; -+} -+ -+static int ls1028a_pixel_clk_enable(struct imx_mhdp_device *imx_mhdp) -+{ -+ struct imx_hdp_clks *clks = &imx_mhdp->clks; -+ struct device *dev = imx_mhdp->mhdp.dev; -+ int ret; -+ -+ ret = clk_prepare_enable(clks->clk_pxl); -+ if (ret < 0) { -+ dev_err(dev, "%s, pre clk pxl error\n", __func__); -+ return ret; -+ } -+ -+ return ret; -+} -+ -+static void ls1028a_pixel_clk_disable(struct imx_mhdp_device *imx_mhdp) -+{ -+ struct imx_hdp_clks *clks = &imx_mhdp->clks; -+ -+ clk_disable_unprepare(clks->clk_pxl); -+} -+ -+static void ls1028a_pixel_clk_set_rate(struct imx_mhdp_device *imx_mhdp, -+ u32 pclock) -+{ -+ struct imx_hdp_clks *clks = &imx_mhdp->clks; -+ -+ clk_set_rate(clks->clk_pxl, pclock); -+} -+ -+int cdns_mhdp_power_on_ls1028a(struct cdns_mhdp_device *mhdp) -+{ -+ struct imx_mhdp_device *imx_mhdp = container_of -+ (mhdp, struct imx_mhdp_device, mhdp); -+ -+ /* clock init and rate set */ -+ ls1028a_clocks_init(imx_mhdp); -+ -+ ls1028a_pixel_clk_enable(imx_mhdp); -+ -+ /* Init pixel clock with 148.5MHz before FW init */ -+ ls1028a_pixel_clk_set_rate(imx_mhdp, 148500000); -+ -+ ls1028a_phy_reset(1); -+ -+ return 0; -+} -+ -+void cdns_mhdp_pclk_rate_ls1028a(struct cdns_mhdp_device *mhdp) -+{ -+ struct imx_mhdp_device *imx_mhdp = container_of -+ (mhdp, struct imx_mhdp_device, mhdp); -+ -+ /* set pixel clock before video mode setup */ -+ ls1028a_pixel_clk_disable(imx_mhdp); -+ -+ ls1028a_pixel_clk_set_rate(imx_mhdp, imx_mhdp->mhdp.mode.clock * 1000); -+ -+ ls1028a_pixel_clk_enable(imx_mhdp); -+} -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-phy.h b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-phy.h -new file mode 100644 -index 000000000000..5682b9fbc90f ---- /dev/null -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-phy.h -@@ -0,0 +1,155 @@ -+/* -+ * Copyright (C) 2019 NXP Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#ifndef _CDN_DP_PHY_H -+#define _CDN_DP_PHY_H -+ -+#include -+ -+#define CMN_SSM_BIAS_TMR 0x0022 -+#define CMN_PLLSM0_PLLEN_TMR 0x0029 -+#define CMN_PLLSM0_PLLPRE_TMR 0x002A -+#define CMN_PLLSM0_PLLVREF_TMR 0x002B -+#define CMN_PLLSM0_PLLLOCK_TMR 0x002C -+#define CMN_PLLSM0_USER_DEF_CTRL 0x002F -+#define CMN_PSM_CLK_CTRL 0x0061 -+#define CMN_CDIAG_REFCLK_CTRL 0x0062 -+#define CMN_PLL0_VCOCAL_START 0x0081 -+#define CMN_PLL0_VCOCAL_INIT_TMR 0x0084 -+#define CMN_PLL0_VCOCAL_ITER_TMR 0x0085 -+#define CMN_PLL0_INTDIV 0x0094 -+#define CMN_PLL0_FRACDIV 0x0095 -+#define CMN_PLL0_HIGH_THR 0x0096 -+#define CMN_PLL0_DSM_DIAG 0x0097 -+#define CMN_PLL0_SS_CTRL1 0x0098 -+#define CMN_PLL0_SS_CTRL2 0x0099 -+#define CMN_ICAL_INIT_TMR 0x00C4 -+#define CMN_ICAL_ITER_TMR 0x00C5 -+#define CMN_RXCAL_INIT_TMR 0x00D4 -+#define CMN_RXCAL_ITER_TMR 0x00D5 -+#define CMN_TXPUCAL_CTRL 0x00E0 -+#define CMN_TXPUCAL_INIT_TMR 0x00E4 -+#define CMN_TXPUCAL_ITER_TMR 0x00E5 -+#define CMN_TXPDCAL_CTRL 0x00F0 -+#define CMN_TXPDCAL_INIT_TMR 0x00F4 -+#define CMN_TXPDCAL_ITER_TMR 0x00F5 -+#define CMN_ICAL_ADJ_INIT_TMR 0x0102 -+#define CMN_ICAL_ADJ_ITER_TMR 0x0103 -+#define CMN_RX_ADJ_INIT_TMR 0x0106 -+#define CMN_RX_ADJ_ITER_TMR 0x0107 -+#define CMN_TXPU_ADJ_CTRL 0x0108 -+#define CMN_TXPU_ADJ_INIT_TMR 0x010A -+#define CMN_TXPU_ADJ_ITER_TMR 0x010B -+#define CMN_TXPD_ADJ_CTRL 0x010c -+#define CMN_TXPD_ADJ_INIT_TMR 0x010E -+#define CMN_TXPD_ADJ_ITER_TMR 0x010F -+#define CMN_DIAG_PLL0_FBH_OVRD 0x01C0 -+#define CMN_DIAG_PLL0_FBL_OVRD 0x01C1 -+#define CMN_DIAG_PLL0_OVRD 0x01C2 -+#define CMN_DIAG_PLL0_TEST_MODE 0x01C4 -+#define CMN_DIAG_PLL0_V2I_TUNE 0x01C5 -+#define CMN_DIAG_PLL0_CP_TUNE 0x01C6 -+#define CMN_DIAG_PLL0_LF_PROG 0x01C7 -+#define CMN_DIAG_PLL0_PTATIS_TUNE1 0x01C8 -+#define CMN_DIAG_PLL0_PTATIS_TUNE2 0x01C9 -+#define CMN_DIAG_PLL0_INCLK_CTRL 0x01CA -+#define CMN_DIAG_PLL0_PXL_DIVH 0x01CB -+#define CMN_DIAG_PLL0_PXL_DIVL 0x01CC -+#define CMN_DIAG_HSCLK_SEL 0x01E0 -+#define CMN_DIAG_PER_CAL_ADJ 0x01EC -+#define CMN_DIAG_CAL_CTRL 0x01ED -+#define CMN_DIAG_ACYA 0x01FF -+#define XCVR_PSM_RCTRL 0x4001 -+#define XCVR_PSM_CAL_TMR 0x4002 -+#define XCVR_PSM_A0IN_TMR 0x4003 -+#define TX_TXCC_CAL_SCLR_MULT_0 0x4047 -+#define TX_TXCC_CPOST_MULT_00_0 0x404C -+#define TX_TXCC_MGNFS_MULT_000_0 0x4050 -+#define XCVR_DIAG_PLLDRC_CTRL 0x40E0 -+#define XCVR_DIAG_PLLDRC_CTRL 0x40E0 -+#define XCVR_DIAG_HSCLK_SEL 0x40E1 -+#define XCVR_DIAG_BIDI_CTRL 0x40E8 -+#define XCVR_DIAG_LANE_FCM_EN_MGN_TMR 0x40F2 -+#define XCVR_DIAG_LANE_FCM_EN_MGN 0x40F2 -+#define TX_PSC_A0 0x4100 -+#define TX_PSC_A1 0x4101 -+#define TX_PSC_A2 0x4102 -+#define TX_PSC_A3 0x4103 -+#define TX_RCVDET_CTRL 0x4120 -+#define TX_RCVDET_EN_TMR 0x4122 -+#define TX_RCVDET_EN_TMR 0x4122 -+#define TX_RCVDET_ST_TMR 0x4123 -+#define TX_RCVDET_ST_TMR 0x4123 -+#define TX_BIST_CTRL 0x4140 -+#define TX_BIST_UDDWR 0x4141 -+#define TX_DIAG_TX_CTRL 0x41E0 -+#define TX_DIAG_TX_DRV 0x41E1 -+#define TX_DIAG_BGREF_PREDRV_DELAY 0x41E7 -+#define TX_DIAG_BGREF_PREDRV_DELAY 0x41E7 -+#define XCVR_PSM_RCTRL_1 0x4201 -+#define TX_TXCC_CAL_SCLR_MULT_1 0x4247 -+#define TX_TXCC_CPOST_MULT_00_1 0x424C -+#define TX_TXCC_MGNFS_MULT_000_1 0x4250 -+#define XCVR_DIAG_PLLDRC_CTRL_1 0x42E0 -+#define XCVR_DIAG_HSCLK_SEL_1 0x42E1 -+#define XCVR_DIAG_LANE_FCM_EN_MGN_TMR_1 0x42F2 -+#define TX_RCVDET_EN_TMR_1 0x4322 -+#define TX_RCVDET_ST_TMR_1 0x4323 -+#define TX_DIAG_ACYA_0 0x41FF -+#define TX_DIAG_ACYA_1 0x43FF -+#define TX_DIAG_ACYA_2 0x45FF -+#define TX_DIAG_ACYA_3 0x47FF -+#define TX_ANA_CTRL_REG_1 0x5020 -+#define TX_ANA_CTRL_REG_2 0x5021 -+#define TXDA_COEFF_CALC 0x5022 -+#define TX_DIG_CTRL_REG_1 0x5023 -+#define TX_DIG_CTRL_REG_2 0x5024 -+#define TXDA_CYA_AUXDA_CYA 0x5025 -+#define TX_ANA_CTRL_REG_3 0x5026 -+#define TX_ANA_CTRL_REG_4 0x5027 -+#define TX_ANA_CTRL_REG_5 0x5029 -+#define RX_PSC_A0 0x8000 -+#define RX_PSC_CAL 0x8006 -+#define PMA_LANE_CFG 0xC000 -+#define PIPE_CMN_CTRL1 0xC001 -+#define PIPE_CMN_CTRL2 0xC002 -+#define PIPE_COM_LOCK_CFG1 0xC003 -+#define PIPE_COM_LOCK_CFG2 0xC004 -+#define PIPE_RCV_DET_INH 0xC005 -+#define PHY_HDP_MODE_CTRL 0xC008 -+#define PHY_HDP_CLK_CTL 0xC009 -+#define STS 0xC00F -+#define PHY_ISO_CMN_CTRL 0xC010 -+#define PHY_ISO_CMN_CTRL 0xC010 -+#define PHY_HDP_TX_CTL_L0 0xC408 -+#define PHY_DP_TX_CTL 0xC408 -+#define PHY_HDP_TX_CTL_L1 0xC448 -+#define PHY_HDP_TX_CTL_L2 0xC488 -+#define PHY_HDP_TX_CTL_L3 0xC4C8 -+#define PHY_PMA_CMN_CTRL1 0xC800 -+#define PMA_CMN_CTRL1 0xC800 -+#define PHY_PMA_ISO_CMN_CTRL 0xC810 -+#define PHY_PMA_ISO_PLL_CTRL1 0xC812 -+#define PHY_PMA_ISOLATION_CTRL 0xC81F -+#define PHY_ISOLATION_CTRL 0xC81F -+#define PHY_PMA_ISO_XCVR_CTRL 0xCC11 -+#define PHY_PMA_ISO_LINK_MODE 0xCC12 -+#define PHY_PMA_ISO_PWRST_CTRL 0xCC13 -+#define PHY_PMA_ISO_TX_DATA_LO 0xCC14 -+#define PHY_PMA_ISO_TX_DATA_HI 0xCC15 -+#define PHY_PMA_ISO_RX_DATA_LO 0xCC16 -+#define PHY_PMA_ISO_RX_DATA_HI 0xCC17 -+ -+int cdns_dp_phy_set_imx8mq(struct cdns_mhdp_device *hdp); -+int cdns_dp_phy_set_imx8qm(struct cdns_mhdp_device *hdp); -+bool cdns_hdmi_phy_video_valid_imx8mq(struct cdns_mhdp_device *hdp); -+bool cdns_hdmi_phy_video_valid_imx8qm(struct cdns_mhdp_device *hdp); -+int cdns_hdmi_phy_set_imx8mq(struct cdns_mhdp_device *hdp); -+int cdns_hdmi_phy_set_imx8qm(struct cdns_mhdp_device *hdp); -+#endif /* _CDNS_MHDP_PHY_H */ --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0031-LF-1514-drm-cdns-mhdp-check-link-rate-index.patch b/projects/NXP/devices/iMX8/patches/linux/0031-LF-1514-drm-cdns-mhdp-check-link-rate-index.patch deleted file mode 100644 index 180ec68d82..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0031-LF-1514-drm-cdns-mhdp-check-link-rate-index.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 8aa7d7baa5eb142261ddafc91b0ba884aa670421 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Fri, 19 Jun 2020 16:17:55 +0800 -Subject: [PATCH 31/49] LF-1514: drm: cdns-mhdp: check link rate index - -Check link rate index to advoid negative array index read. -report by Coverity ID:6652950 6652949. - -Signed-off-by: Sandor Yu -Reviewed-by: Fancy Fang ---- - drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c -index a6d03c94d196..5c75e7d40cc0 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c -@@ -198,6 +198,10 @@ static void dp_phy_pma_cmn_pll0_24mhz(struct cdns_mhdp_device *mhdp) - - /* DP PHY PLL 24MHz configuration */ - index = link_rate_index(link_rate); -+ if (index < 0) { -+ dev_err(mhdp->dev, "wrong link rate index\n"); -+ return; -+ } - for (i = 0; i < ARRAY_SIZE(phy_pll_24m_cfg); i++) - cdns_phy_reg_write(mhdp, phy_pll_24m_cfg[i].addr, phy_pll_24m_cfg[i].val[index]); - -@@ -320,6 +324,10 @@ static void dp_phy_pma_cmn_pll0_27mhz(struct cdns_mhdp_device *mhdp) - - /* DP PHY PLL 27MHz configuration */ - index = link_rate_index(link_rate); -+ if (index < 0) { -+ dev_err(mhdp->dev, "wrong link rate index\n"); -+ return; -+ } - for (i = 0; i < ARRAY_SIZE(phy_pll_27m_cfg); i++) - cdns_phy_reg_write(mhdp, phy_pll_27m_cfg[i].addr, phy_pll_27m_cfg[i].val[index]); - --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0032-LF-1516-drm-cdns-mhdp-fix-error-check-variable-name-.patch b/projects/NXP/devices/iMX8/patches/linux/0032-LF-1516-drm-cdns-mhdp-fix-error-check-variable-name-.patch deleted file mode 100644 index f42d867842..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0032-LF-1516-drm-cdns-mhdp-fix-error-check-variable-name-.patch +++ /dev/null @@ -1,31 +0,0 @@ -From b2ea44969c5e51a5809622384728859d7f3a2b8a Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Fri, 19 Jun 2020 16:25:51 +0800 -Subject: [PATCH 32/49] LF-1516: drm: cdns-mhdp: fix error check variable name - for clk_pxl_link - -fix error check variable name for clk_pxl_link. -Report by Coverity ID:6652947 - -Signed-off-by: Sandor Yu -Reviewed-by: Fancy Fang ---- - drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -index a3ba3da4b05d..2ee4e8748b77 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -@@ -167,7 +167,7 @@ int imx8qm_clocks_init(struct imx_mhdp_device *imx_mhdp) - } - - clks->clk_pxl_link = devm_clk_get(dev, "clk_pxl_link"); -- if (IS_ERR(clks->clk_pxl_mux)) { -+ if (IS_ERR(clks->clk_pxl_link)) { - dev_warn(dev, "failed to get pxl link clk\n"); - return PTR_ERR(clks->clk_pxl_link); - } --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0033-MLK-24601-drm-imx-mhdp-DP-PHY-support-1-2-lanes-mode.patch b/projects/NXP/devices/iMX8/patches/linux/0033-MLK-24601-drm-imx-mhdp-DP-PHY-support-1-2-lanes-mode.patch deleted file mode 100644 index f3076760c9..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0033-MLK-24601-drm-imx-mhdp-DP-PHY-support-1-2-lanes-mode.patch +++ /dev/null @@ -1,58 +0,0 @@ -From c789945d09e4c77eb30af1a8db1425cefab52080 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Fri, 28 Aug 2020 10:09:12 +0800 -Subject: [PATCH 33/49] MLK-24601: drm: imx: mhdp: DP PHY support 1/2 lanes - mode - -All four lanes should be configurated for 1/2/4 lanes modes in driver. -The DP FW will power down unused PHY lanes after negotiation. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c -index 5c75e7d40cc0..3d17840b0941 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-dp-phy.c -@@ -137,7 +137,7 @@ static void dp_aux_cfg(struct cdns_mhdp_device *mhdp) - static void dp_phy_pma_cmn_cfg_24mhz(struct cdns_mhdp_device *mhdp) - { - int k; -- u32 num_lanes = mhdp->dp.num_lanes; -+ u32 num_lanes = 4; - u16 val; - - val = cdns_phy_reg_read(mhdp, PHY_PMA_CMN_CTRL1); -@@ -157,7 +157,7 @@ static void dp_phy_pma_cmn_cfg_24mhz(struct cdns_mhdp_device *mhdp) - /* Valid for 24 MHz only */ - static void dp_phy_pma_cmn_pll0_24mhz(struct cdns_mhdp_device *mhdp) - { -- u32 num_lanes = mhdp->dp.num_lanes; -+ u32 num_lanes = 4; - u32 link_rate = mhdp->dp.rate; - u16 val; - int index, i, k; -@@ -228,7 +228,7 @@ static void dp_phy_pma_cmn_pll0_24mhz(struct cdns_mhdp_device *mhdp) - /* PMA common configuration for 27MHz */ - static void dp_phy_pma_cmn_cfg_27mhz(struct cdns_mhdp_device *mhdp) - { -- u32 num_lanes = mhdp->dp.num_lanes; -+ u32 num_lanes = 4; - u16 val; - int k; - -@@ -279,7 +279,7 @@ static void dp_phy_pma_cmn_cfg_27mhz(struct cdns_mhdp_device *mhdp) - - static void dp_phy_pma_cmn_pll0_27mhz(struct cdns_mhdp_device *mhdp) - { -- u32 num_lanes = mhdp->dp.num_lanes; -+ u32 num_lanes = 4; - u32 link_rate = mhdp->dp.rate; - u16 val; - int index, i, k; --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0034-MLK-24519-2-gpu-imx-Increase-maximum-single-pipe-wid.patch b/projects/NXP/devices/iMX8/patches/linux/0034-MLK-24519-2-gpu-imx-Increase-maximum-single-pipe-wid.patch deleted file mode 100644 index 799824c90b..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0034-MLK-24519-2-gpu-imx-Increase-maximum-single-pipe-wid.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 7772a57acd0e05353caead7eb7d064e36bcb92e6 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Sun, 20 Sep 2020 19:32:28 +0800 -Subject: [PATCH 34/49] MLK-24519-2 gpu: imx: Increase maximum single pipe - width to 2560 - -This patch increase the DPU single pipe maximum from 1920 to 2560 for HDMI/DP. - -Signed-off-by: Oliver F. Brown -Reviewed-by: Liu Ying ---- - drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -index 2ee4e8748b77..cda4d245bab8 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -@@ -22,7 +22,7 @@ - #define PLL_800MHZ (800000000) - - #define HDP_DUAL_MODE_MIN_PCLK_RATE 300000 /* KHz */ --#define HDP_SINGLE_MODE_MAX_WIDTH 1920 -+#define HDP_SINGLE_MODE_MAX_WIDTH 2560 - - #define CSR_PIXEL_LINK_MUX_CTL 0x00 - #define CSR_PIXEL_LINK_MUX_VCP_OFFSET 5 --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0035-MLK-24072-drm-imx8-correct-mhdp-files-copyright.patch b/projects/NXP/devices/iMX8/patches/linux/0035-MLK-24072-drm-imx8-correct-mhdp-files-copyright.patch deleted file mode 100644 index 987690f888..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0035-MLK-24072-drm-imx8-correct-mhdp-files-copyright.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 60077991d60b1ba96e52d5a6568ae65ae7143ee2 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Wed, 20 May 2020 10:56:53 +0800 -Subject: [PATCH 35/49] MLK-24072: drm: imx8: correct mhdp files copyright - -Correct mhdp files copyright. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c | 2 +- - drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -index cda4d245bab8..38f9defa42f8 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -@@ -1,5 +1,5 @@ - /* -- * copyright (c) 2019 nxp semiconductor, inc. -+ * Copyright (c) 2019 NXP semiconductor, inc. - * - * this program is free software; you can redistribute it and/or modify - * it under the terms of the gnu general public license version 2 as -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c -index 3acbdf575ee2..cc429fe48abd 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c -@@ -1,5 +1,5 @@ - /* -- * copyright (c) 2019 nxp semiconductor, inc. -+ * Copyright (c) 2019 NXP semiconductor, inc. - * - * this program is free software; you can redistribute it and/or modify - * it under the terms of the gnu general public license version 2 as --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0036-LF-2744-drm-cdns-reset-force_mode_set-flag-in-atomic.patch b/projects/NXP/devices/iMX8/patches/linux/0036-LF-2744-drm-cdns-reset-force_mode_set-flag-in-atomic.patch deleted file mode 100644 index 8586df89c8..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0036-LF-2744-drm-cdns-reset-force_mode_set-flag-in-atomic.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 93502b984119af556f8a204bf80a62bc1c21fbfd Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Tue, 17 Nov 2020 15:47:36 +0800 -Subject: [PATCH 36/49] LF-2744: drm: cdns: reset force_mode_set flag in - atomic_check - -Reset force_mode_set flag in atomic_check function -to avoid set mode_changed flag multi times when cable plugin. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c -index cc429fe48abd..9fa0df74ad7c 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2019 NXP semiconductor, inc. -+ * Copyright (c) 2019-2020 NXP semiconductor, inc. - * - * this program is free software; you can redistribute it and/or modify - * it under the terms of the gnu general public license version 2 as -@@ -44,8 +44,11 @@ static int cdns_mhdp_imx_encoder_atomic_check(struct drm_encoder *encoder, - if (mhdp->plat_data->video_format != 0) - imx_crtc_state->bus_format = mhdp->plat_data->video_format; - -- if (mhdp->force_mode_set) -+ if (mhdp->force_mode_set) { - crtc_state->mode_changed = true; -+ /* reset force mode set flag */ -+ mhdp->force_mode_set = false; -+ } - - return 0; - } --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0037-MLK-25199-1-drm-mhdp-Add-hdmi-phy-reset-poweroff-fun.patch b/projects/NXP/devices/iMX8/patches/linux/0037-MLK-25199-1-drm-mhdp-Add-hdmi-phy-reset-poweroff-fun.patch deleted file mode 100644 index e70e44eb2e..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0037-MLK-25199-1-drm-mhdp-Add-hdmi-phy-reset-poweroff-fun.patch +++ /dev/null @@ -1,161 +0,0 @@ -From 38f1f4ecd038628f4ce7a47114455123e5db3367 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Wed, 30 Dec 2020 16:02:52 +0800 -Subject: [PATCH 37/49] MLK-25199-1: drm: mhdp: Add hdmi phy reset/poweroff - function - -Add hdmi phy reset and power off function. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c | 28 ++++++++++++++++++- - drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx.h | 3 +- - drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c | 4 +-- - drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c | 2 ++ - drivers/gpu/drm/imx/mhdp/cdns-mhdp-phy.h | 3 +- - 5 files changed, 35 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c -index 120300e6a2df..212f3f4f1e26 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c -@@ -1,7 +1,7 @@ - /* - * Cadence High-Definition Multimedia Interface (HDMI) driver - * -- * Copyright (C) 2019 NXP Semiconductor, Inc. -+ * Copyright (C) 2019-2021 NXP Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -21,6 +21,7 @@ - - #include - #include "cdns-mhdp-phy.h" -+#include "cdns-mhdp-imx.h" - - /* HDMI TX clock control settings */ - struct hdmi_ctrl { -@@ -746,6 +747,7 @@ int cdns_hdmi_phy_set_imx8qm(struct cdns_mhdp_device *mhdp) - DRM_ERROR("NO HDMI FW running\n"); - return -ENXIO; - } -+ imx8qm_phy_reset(0); - - /* Configure PHY */ - mhdp->hdmi.char_rate = hdmi_phy_cfg_ss28fdsoi(mhdp, mode); -@@ -753,6 +755,7 @@ int cdns_hdmi_phy_set_imx8qm(struct cdns_mhdp_device *mhdp) - DRM_ERROR("failed to set phy pclock\n"); - return -EINVAL; - } -+ imx8qm_phy_reset(1); - - ret = hdmi_phy_power_up(mhdp); - if (ret < 0) -@@ -762,3 +765,26 @@ int cdns_hdmi_phy_set_imx8qm(struct cdns_mhdp_device *mhdp) - - return true; - } -+ -+int cdns_hdmi_phy_shutdown(struct cdns_mhdp_device *mhdp) -+{ -+ int timeout; -+ u32 reg_val; -+ -+ reg_val = cdns_phy_reg_read(mhdp, PHY_HDP_MODE_CTRL); -+ reg_val &= 0xfff0; -+ /* PHY_DP_MODE_CTL set to A3 power state*/ -+ cdns_phy_reg_write(mhdp, PHY_HDP_MODE_CTRL, reg_val | 0x8); -+ -+ /* PHY_DP_MODE_CTL */ -+ timeout = 0; -+ do { -+ reg_val = cdns_phy_reg_read(mhdp, PHY_HDP_MODE_CTRL); -+ DRM_INFO("Reg val is 0x%04x\n", reg_val); -+ timeout++; -+ msleep(100); -+ } while (!(reg_val & (0x8 << 4)) && (timeout < 10)); /* Wait for A3 acknowledge */ -+ -+ DRM_INFO("hdmi phy shutdown complete\n"); -+ return 0; -+} -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx.h b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx.h -index fc3247dada2d..a12005ae4c53 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx.h -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx.h -@@ -1,7 +1,7 @@ - /* - * Cadence High-Definition Multimedia Interface (HDMI) driver - * -- * Copyright (C) 2019 NXP Semiconductor, Inc. -+ * Copyright (C) 2019-2021 NXP Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -72,4 +72,5 @@ int cdns_mhdp_suspend_imx8qm(struct cdns_mhdp_device *mhdp); - int cdns_mhdp_power_on_imx8qm(struct cdns_mhdp_device *mhdp); - int cdns_mhdp_power_on_ls1028a(struct cdns_mhdp_device *mhdp); - void cdns_mhdp_pclk_rate_ls1028a(struct cdns_mhdp_device *mhdp); -+void imx8qm_phy_reset(u8 reset); - #endif /* CDNS_MHDP_IMX_H_ */ -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -index 38f9defa42f8..46c0500da4c3 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imx8qm.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2019 NXP semiconductor, inc. -+ * Copyright (c) 2019-2021 NXP semiconductor, inc. - * - * this program is free software; you can redistribute it and/or modify - * it under the terms of the gnu general public license version 2 as -@@ -102,7 +102,7 @@ static void imx8qm_pixel_link_sync_disable(u32 dual_mode) - imx_sc_misc_set_control(handle, IMX_SC_R_DC_0, IMX_SC_C_SYNC_CTRL0, 0); - } - --static void imx8qm_phy_reset(u8 reset) -+void imx8qm_phy_reset(u8 reset) - { - struct imx_sc_ipc *handle; - -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c -index 9fa0df74ad7c..4c4ce9d3c847 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c -@@ -22,6 +22,7 @@ static void cdns_mhdp_imx_encoder_disable(struct drm_encoder *encoder) - struct drm_bridge *bridge = drm_bridge_chain_get_first_bridge(encoder); - struct cdns_mhdp_device *mhdp = bridge->driver_private; - -+ cdns_hdmi_phy_shutdown(mhdp); - cdns_mhdp_plat_call(mhdp, plat_init); - } - -@@ -184,6 +185,7 @@ static int cdns_mhdp_imx_bind(struct device *dev, struct device *master, - - imx_mhdp->mhdp.plat_data = plat_data; - imx_mhdp->mhdp.dev = dev; -+ imx_mhdp->mhdp.drm_dev = drm; - imx_mhdp->mhdp.bus_type = plat_data->bus_type; - ret = plat_data->bind(pdev, encoder, &imx_mhdp->mhdp); - /* -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-phy.h b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-phy.h -index 5682b9fbc90f..9035f1f71eee 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-phy.h -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-phy.h -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2019 NXP Semiconductor, Inc. -+ * Copyright (C) 2019-2021 NXP Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by -@@ -152,4 +152,5 @@ bool cdns_hdmi_phy_video_valid_imx8mq(struct cdns_mhdp_device *hdp); - bool cdns_hdmi_phy_video_valid_imx8qm(struct cdns_mhdp_device *hdp); - int cdns_hdmi_phy_set_imx8mq(struct cdns_mhdp_device *hdp); - int cdns_hdmi_phy_set_imx8qm(struct cdns_mhdp_device *hdp); -+int cdns_hdmi_phy_shutdown(struct cdns_mhdp_device *mhdp); - #endif /* _CDNS_MHDP_PHY_H */ --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0038-MLK-25199-2-drm-mhdp-Fix-typo-for-hdmi-phy-configura.patch b/projects/NXP/devices/iMX8/patches/linux/0038-MLK-25199-2-drm-mhdp-Fix-typo-for-hdmi-phy-configura.patch deleted file mode 100644 index 9fc25f46f8..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0038-MLK-25199-2-drm-mhdp-Fix-typo-for-hdmi-phy-configura.patch +++ /dev/null @@ -1,38 +0,0 @@ -From d77cbee9949eda85baba634bdf6c6c2afe0b64e4 Mon Sep 17 00:00:00 2001 -From: Sandor Yu -Date: Thu, 31 Dec 2020 10:13:55 +0800 -Subject: [PATCH 38/49] MLK-25199-2: drm: mhdp: Fix typo for hdmi phy - configuration table - -Fix typo for imx8qm hdmi phy configuration table. - -Signed-off-by: Sandor Yu -Reviewed-by: Robby Cai ---- - drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c -index 212f3f4f1e26..f96b200885df 100644 ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-hdmi-phy.c -@@ -95,11 +95,11 @@ static const struct hdmi_ctrl imx8qm_ctrl_table[] = { - { 85000, 170000, 1000, 850000, 1700000, 0x11, 0x00, 0x07, 340, 0x146, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 2, 0x01, 85000, 170000}, - {170000, 340000, 1000, 1700000, 3400000, 0x22, 0x01, 0x07, 340, 0x146, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 1, 0x00, 170000, 340000}, - {340000, 600000, 1000, 3400000, 6000000, 0x3C, 0x03, 0x06, 600, 0x24A, 0x00A, 0, 0, 0, 3400000, 6000000, 1, 1, 1, 2, 1, 0x00, 340000, 600000}, --{ 25000, 34000, 1205, 312500, 425000, 0x04, 0x01, 0x01, 400, 0x182, 0x00A, 0, 0, 0, 2500000, 3400000, 0, 2, 2, 2, 4, 0x03, 31250, 42500}, --{ 34000, 68000, 1205, 425000, 850000, 0x06, 0x02, 0x01, 300, 0x11E, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 4, 0x02, 42500, 85000}, --{ 68000, 136000, 1205, 850000, 1700000, 0x0D, 0x02, 0x02, 325, 0x137, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 2, 0x01, 85000, 170000}, --{136000, 272000, 1205, 1700000, 3400000, 0x1A, 0x02, 0x04, 325, 0x137, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 1, 0x00, 170000, 340000}, --{272000, 480000, 1205, 3400000, 6000000, 0x30, 0x03, 0x05, 600, 0x24A, 0x00A, 0, 0, 0, 3400000, 6000000, 1, 1, 1, 2, 1, 0x00, 340000, 600000}, -+{ 25000, 34000, 1250, 312500, 425000, 0x04, 0x01, 0x01, 400, 0x182, 0x00A, 0, 0, 0, 2500000, 3400000, 0, 2, 2, 2, 4, 0x03, 31250, 42500}, -+{ 34000, 68000, 1250, 425000, 850000, 0x06, 0x02, 0x01, 300, 0x11E, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 4, 0x02, 42500, 85000}, -+{ 68000, 136000, 1250, 850000, 1700000, 0x0D, 0x02, 0x02, 325, 0x137, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 2, 0x01, 85000, 170000}, -+{136000, 272000, 1250, 1700000, 3400000, 0x1A, 0x02, 0x04, 325, 0x137, 0x00A, 0, 0, 0, 1700000, 3400000, 0, 1, 1, 2, 1, 0x00, 170000, 340000}, -+{272000, 480000, 1250, 3400000, 6000000, 0x30, 0x03, 0x05, 600, 0x24A, 0x00A, 0, 0, 0, 3400000, 6000000, 1, 1, 1, 2, 1, 0x00, 340000, 600000}, - { 25000, 28000, 1500, 375000, 420000, 0x03, 0x01, 0x01, 360, 0x15A, 0x00A, 0, 0, 0, 3000000, 3360000, 0, 2, 2, 2, 4, 0x03, 37500, 42000}, - { 28000, 56000, 1500, 420000, 840000, 0x06, 0x02, 0x01, 360, 0x15A, 0x00A, 0, 0, 0, 1680000, 3360000, 0, 1, 1, 2, 4, 0x02, 42000, 84000}, - { 56000, 113000, 1500, 840000, 1695000, 0x0B, 0x00, 0x05, 330, 0x13C, 0x00A, 0, 0, 0, 1680000, 3390000, 0, 1, 1, 2, 2, 0x01, 84000, 169500}, --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0040-drm-imx-dcss-use-the-external-27MHz-phy-clock.patch b/projects/NXP/devices/iMX8/patches/linux/0040-drm-imx-dcss-use-the-external-27MHz-phy-clock.patch deleted file mode 100644 index 2bd14ddf27..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0040-drm-imx-dcss-use-the-external-27MHz-phy-clock.patch +++ /dev/null @@ -1,108 +0,0 @@ -From c2af9b24bfa69ffb12e72153f89ed3bb3245fafb Mon Sep 17 00:00:00 2001 -From: Laurentiu Palcu -Date: Fri, 22 Nov 2019 10:00:56 +0200 -Subject: [PATCH 40/49] drm/imx/dcss: use the external 27MHz phy clock - -The 27MHz external oscillator offers a high precision low jitter clock and -is suitable for high pixel clocks modes(ie 4K@60). - -Signed-off-by: Laurentiu Palcu ---- - drivers/gpu/drm/imx/dcss/dcss-dev.c | 25 +++++++++++++++++++------ - drivers/gpu/drm/imx/dcss/dcss-dtg.c | 11 +++++++++++ - 2 files changed, 30 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/imx/dcss/dcss-dev.c b/drivers/gpu/drm/imx/dcss/dcss-dev.c -index c849533ca83e..1977f6b058f8 100644 ---- a/drivers/gpu/drm/imx/dcss/dcss-dev.c -+++ b/drivers/gpu/drm/imx/dcss/dcss-dev.c -@@ -17,6 +17,11 @@ - - static void dcss_clocks_enable(struct dcss_dev *dcss) - { -+ if (dcss->hdmi_output) { -+ clk_prepare_enable(dcss->pll_phy_ref_clk); -+ clk_prepare_enable(dcss->pll_src_clk); -+ } -+ - clk_prepare_enable(dcss->axi_clk); - clk_prepare_enable(dcss->apb_clk); - clk_prepare_enable(dcss->rtrm_clk); -@@ -31,6 +36,11 @@ static void dcss_clocks_disable(struct dcss_dev *dcss) - clk_disable_unprepare(dcss->rtrm_clk); - clk_disable_unprepare(dcss->apb_clk); - clk_disable_unprepare(dcss->axi_clk); -+ -+ if (dcss->hdmi_output) { -+ clk_disable_unprepare(dcss->pll_src_clk); -+ clk_disable_unprepare(dcss->pll_phy_ref_clk); -+ } - } - - static void dcss_disable_dtg_and_ss_cb(void *data) -@@ -133,17 +143,20 @@ static int dcss_clks_init(struct dcss_dev *dcss) - struct { - const char *id; - struct clk **clk; -+ bool required; - } clks[] = { -- {"apb", &dcss->apb_clk}, -- {"axi", &dcss->axi_clk}, -- {"pix", &dcss->pix_clk}, -- {"rtrm", &dcss->rtrm_clk}, -- {"dtrc", &dcss->dtrc_clk}, -+ {"apb", &dcss->apb_clk, true}, -+ {"axi", &dcss->axi_clk, true}, -+ {"pix", &dcss->pix_clk, true}, -+ {"rtrm", &dcss->rtrm_clk, true}, -+ {"dtrc", &dcss->dtrc_clk, true}, -+ {"pll_src", &dcss->pll_src_clk, dcss->hdmi_output}, -+ {"pll_phy_ref", &dcss->pll_phy_ref_clk, dcss->hdmi_output}, - }; - - for (i = 0; i < ARRAY_SIZE(clks); i++) { - *clks[i].clk = devm_clk_get(dcss->dev, clks[i].id); -- if (IS_ERR(*clks[i].clk)) { -+ if (IS_ERR(*clks[i].clk) && clks[i].required) { - dev_err(dcss->dev, "failed to get %s clock\n", - clks[i].id); - return PTR_ERR(*clks[i].clk); -diff --git a/drivers/gpu/drm/imx/dcss/dcss-dtg.c b/drivers/gpu/drm/imx/dcss/dcss-dtg.c -index 30de00540f63..b70785d69ad9 100644 ---- a/drivers/gpu/drm/imx/dcss/dcss-dtg.c -+++ b/drivers/gpu/drm/imx/dcss/dcss-dtg.c -@@ -83,6 +83,7 @@ struct dcss_dtg { - u32 ctx_id; - - bool in_use; -+ bool hdmi_output; - - u32 dis_ulc_x; - u32 dis_ulc_y; -@@ -159,6 +160,7 @@ int dcss_dtg_init(struct dcss_dev *dcss, unsigned long dtg_base) - dcss->dtg = dtg; - dtg->dev = dcss->dev; - dtg->ctxld = dcss->ctxld; -+ dtg->hdmi_output = dcss->hdmi_output; - - dtg->base_reg = ioremap(dtg_base, SZ_4K); - if (!dtg->base_reg) { -@@ -221,6 +223,15 @@ void dcss_dtg_sync_set(struct dcss_dtg *dtg, struct videomode *vm) - vm->vactive - 1; - - clk_disable_unprepare(dcss->pix_clk); -+ if (dcss->hdmi_output) { -+ int err; -+ -+ clk_disable_unprepare(dcss->pll_src_clk); -+ err = clk_set_parent(dcss->pll_src_clk, dcss->pll_phy_ref_clk); -+ if (err < 0) -+ dev_warn(dcss->dev, "clk_set_parent() returned %d", err); -+ clk_prepare_enable(dcss->pll_src_clk); -+ } - clk_set_rate(dcss->pix_clk, vm->pixelclock); - clk_prepare_enable(dcss->pix_clk); - --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0041-drm-imx-dcss-add-component-framework-functionality.patch b/projects/NXP/devices/iMX8/patches/linux/0041-drm-imx-dcss-add-component-framework-functionality.patch deleted file mode 100644 index a1e33406f2..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0041-drm-imx-dcss-add-component-framework-functionality.patch +++ /dev/null @@ -1,230 +0,0 @@ -From ec59d2988d1ac50acea0fdaa63513f216ddf016d Mon Sep 17 00:00:00 2001 -From: Laurentiu Palcu -Date: Thu, 9 Jul 2020 19:47:31 +0300 -Subject: [PATCH 41/49] drm/imx/dcss: add component framework functionality - -Component framework is needed by HDP driver. - -Signed-off-by: Laurentiu Palcu ---- - drivers/gpu/drm/imx/dcss/dcss-drv.c | 89 ++++++++++++++++++++++------- - drivers/gpu/drm/imx/dcss/dcss-kms.c | 23 +++++--- - drivers/gpu/drm/imx/dcss/dcss-kms.h | 4 +- - 3 files changed, 85 insertions(+), 31 deletions(-) - -diff --git a/drivers/gpu/drm/imx/dcss/dcss-drv.c b/drivers/gpu/drm/imx/dcss/dcss-drv.c -index 8dc2f85c514b..09d0ac28e28a 100644 ---- a/drivers/gpu/drm/imx/dcss/dcss-drv.c -+++ b/drivers/gpu/drm/imx/dcss/dcss-drv.c -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - #include - - #include "dcss-dev.h" -@@ -14,6 +15,8 @@ - struct dcss_drv { - struct dcss_dev *dcss; - struct dcss_kms_dev *kms; -+ -+ bool is_componentized; - }; - - struct dcss_dev *dcss_drv_dev_to_dcss(struct device *dev) -@@ -30,30 +33,18 @@ struct drm_device *dcss_drv_dev_to_drm(struct device *dev) - return mdrv ? &mdrv->kms->base : NULL; - } - --static int dcss_drv_platform_probe(struct platform_device *pdev) -+static int dcss_drv_init(struct device *dev, bool componentized) - { -- struct device *dev = &pdev->dev; -- struct device_node *remote; - struct dcss_drv *mdrv; - int err = 0; -- bool hdmi_output = true; -- -- if (!dev->of_node) -- return -ENODEV; -- -- remote = of_graph_get_remote_node(dev->of_node, 0, 0); -- if (!remote) -- return -ENODEV; -- -- hdmi_output = !of_device_is_compatible(remote, "fsl,imx8mq-nwl-dsi"); -- -- of_node_put(remote); - - mdrv = kzalloc(sizeof(*mdrv), GFP_KERNEL); - if (!mdrv) - return -ENOMEM; - -- mdrv->dcss = dcss_dev_create(dev, hdmi_output); -+ mdrv->is_componentized = componentized; -+ -+ mdrv->dcss = dcss_dev_create(dev, componentized); - if (IS_ERR(mdrv->dcss)) { - err = PTR_ERR(mdrv->dcss); - goto err; -@@ -61,7 +52,7 @@ static int dcss_drv_platform_probe(struct platform_device *pdev) - - dev_set_drvdata(dev, mdrv); - -- mdrv->kms = dcss_kms_attach(mdrv->dcss); -+ mdrv->kms = dcss_kms_attach(mdrv->dcss, componentized); - if (IS_ERR(mdrv->kms)) { - err = PTR_ERR(mdrv->kms); - goto dcss_shutoff; -@@ -79,14 +70,68 @@ static int dcss_drv_platform_probe(struct platform_device *pdev) - return err; - } - --static int dcss_drv_platform_remove(struct platform_device *pdev) -+static void dcss_drv_deinit(struct device *dev, bool componentized) - { -- struct dcss_drv *mdrv = dev_get_drvdata(&pdev->dev); -+ struct dcss_drv *mdrv = dev_get_drvdata(dev); - -- dcss_kms_detach(mdrv->kms); -+ dcss_kms_detach(mdrv->kms, componentized); - dcss_dev_destroy(mdrv->dcss); - - kfree(mdrv); -+} -+ -+static int dcss_drv_bind(struct device *dev) -+{ -+ return dcss_drv_init(dev, true); -+} -+ -+static void dcss_drv_unbind(struct device *dev) -+{ -+ return dcss_drv_deinit(dev, true); -+} -+ -+static const struct component_master_ops dcss_master_ops = { -+ .bind = dcss_drv_bind, -+ .unbind = dcss_drv_unbind, -+}; -+ -+static int compare_of(struct device *dev, void *data) -+{ -+ return dev->of_node == data; -+} -+ -+static int dcss_drv_platform_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct component_match *match = NULL; -+ struct device_node *remote; -+ -+ if (!dev->of_node) -+ return -ENODEV; -+ -+ remote = of_graph_get_remote_node(dev->of_node, 0, 0); -+ if (!remote) -+ return -ENODEV; -+ -+ if (of_device_is_compatible(remote, "fsl,imx8mq-nwl-dsi")) { -+ of_node_put(remote); -+ return dcss_drv_init(dev, false); -+ } -+ -+ drm_of_component_match_add(dev, &match, compare_of, remote); -+ of_node_put(remote); -+ -+ return component_master_add_with_match(dev, &dcss_master_ops, match); -+} -+ -+static int dcss_drv_platform_remove(struct platform_device *pdev) -+{ -+ struct dcss_drv *mdrv = dev_get_drvdata(&pdev->dev); -+ -+ if (mdrv->is_componentized) -+ component_master_del(&pdev->dev, &dcss_master_ops); -+ else -+ dcss_drv_deinit(&pdev->dev, false); - - return 0; - } -diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.c b/drivers/gpu/drm/imx/dcss/dcss-kms.c -index 135a62366ab8..cafb09df6c75 100644 ---- a/drivers/gpu/drm/imx/dcss/dcss-kms.c -+++ b/drivers/gpu/drm/imx/dcss/dcss-kms.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - #include "dcss-dev.h" - #include "dcss-kms.h" -@@ -123,7 +124,7 @@ static int dcss_kms_bridge_connector_init(struct dcss_kms_dev *kms) - return 0; - } - --struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss) -+struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss, bool componentized) - { - struct dcss_kms_dev *kms; - struct drm_device *drm; -@@ -148,13 +149,16 @@ struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss) - - goto cleanup_mode_config; - -- ret = dcss_kms_bridge_connector_init(kms); -+ ret = dcss_crtc_init(crtc, drm); - if (ret) - goto cleanup_mode_config; - -- ret = dcss_crtc_init(crtc, drm); -+ if (componentized) -+ ret = component_bind_all(dcss->dev, kms); -+ else -+ ret = dcss_kms_bridge_connector_init(kms); - if (ret) -- goto cleanup_mode_config; -+ goto cleanup_crtc; - - drm_mode_config_reset(drm); - -@@ -182,9 +188,10 @@ struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss) - return ERR_PTR(ret); - } - --void dcss_kms_detach(struct dcss_kms_dev *kms) -+void dcss_kms_detach(struct dcss_kms_dev *kms, bool componentized) - { - struct drm_device *drm = &kms->base; -+ struct dcss_dev *dcss = drm->dev_private; - - drm_dev_unregister(drm); - drm_bridge_connector_disable_hpd(kms->connector); -@@ -194,5 +201,7 @@ void dcss_kms_detach(struct dcss_kms_dev *kms) - drm->irq_enabled = false; - drm_mode_config_cleanup(drm); - dcss_crtc_deinit(&kms->crtc, drm); -+ if (componentized) -+ component_unbind_all(dcss->dev, drm); - drm->dev_private = NULL; - } -diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.h b/drivers/gpu/drm/imx/dcss/dcss-kms.h -index dfe5dd99eea3..e98d9c587a43 100644 ---- a/drivers/gpu/drm/imx/dcss/dcss-kms.h -+++ b/drivers/gpu/drm/imx/dcss/dcss-kms.h -@@ -32,8 +32,8 @@ struct dcss_kms_dev { - struct drm_connector *connector; - }; - --struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss); --void dcss_kms_detach(struct dcss_kms_dev *kms); -+struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss, bool componentized); -+void dcss_kms_detach(struct dcss_kms_dev *kms, bool componentized); - int dcss_crtc_init(struct dcss_crtc *crtc, struct drm_device *drm); - void dcss_crtc_deinit(struct dcss_crtc *crtc, struct drm_device *drm); - struct dcss_plane *dcss_plane_init(struct drm_device *drm, --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0043-arm64-dts-imx8mq-add-DCSS-node.patch b/projects/NXP/devices/iMX8/patches/linux/0043-arm64-dts-imx8mq-add-DCSS-node.patch deleted file mode 100644 index 889d2bfe7a..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0043-arm64-dts-imx8mq-add-DCSS-node.patch +++ /dev/null @@ -1,49 +0,0 @@ -From bd9c83ea41380f584fdd8f2781112b530c84ebba Mon Sep 17 00:00:00 2001 -From: Laurentiu Palcu -Date: Thu, 9 Jul 2020 19:47:33 +0300 -Subject: [PATCH 43/49] arm64: dts: imx8mq: add DCSS node - -This patch adds the node for iMX8MQ Display Controller Subsystem. - -Signed-off-by: Laurentiu Palcu ---- - arch/arm64/boot/dts/freescale/imx8mq.dtsi | 23 +++++++++++++++++++++++ - 1 file changed, 23 insertions(+) - -diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi -index 5e0e7d0f1bc4..5a617f9ed8b5 100644 ---- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi -+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi -@@ -1103,6 +1103,29 @@ bus@32c00000 { /* AIPS4 */ - #size-cells = <1>; - ranges = <0x32c00000 0x32c00000 0x400000>; - -+ dcss: display-controller@32e00000 { -+ compatible = "nxp,imx8mq-dcss"; -+ reg = <0x32e00000 0x2d000>, <0x32e2f000 0x1000>; -+ interrupts = <6>, <8>, <9>; -+ interrupt-names = "ctxld", "ctxld_kick", "vblank"; -+ interrupt-parent = <&irqsteer>; -+ clocks = <&clk IMX8MQ_CLK_DISP_APB_ROOT>, -+ <&clk IMX8MQ_CLK_DISP_AXI_ROOT>, -+ <&clk IMX8MQ_CLK_DISP_RTRM_ROOT>, -+ <&clk IMX8MQ_VIDEO2_PLL_OUT>, -+ <&clk IMX8MQ_CLK_DISP_DTRC>; -+ clock-names = "apb", "axi", "rtrm", "pix", "dtrc"; -+ assigned-clocks = <&clk IMX8MQ_CLK_DISP_AXI>, -+ <&clk IMX8MQ_CLK_DISP_RTRM>, -+ <&clk IMX8MQ_VIDEO2_PLL1_REF_SEL>; -+ assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_800M>, -+ <&clk IMX8MQ_SYS1_PLL_800M>, -+ <&clk IMX8MQ_CLK_27M>; -+ assigned-clock-rates = <800000000>, -+ <400000000>; -+ status = "disabled"; -+ }; -+ - irqsteer: interrupt-controller@32e2d000 { - compatible = "fsl,imx8m-irqsteer", "fsl,imx-irqsteer"; - reg = <0x32e2d000 0x1000>; --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0044-arm64-dts-imx8mq-add-DCSS-external-oscillator-suppor.patch b/projects/NXP/devices/iMX8/patches/linux/0044-arm64-dts-imx8mq-add-DCSS-external-oscillator-suppor.patch deleted file mode 100644 index af0fe275a3..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0044-arm64-dts-imx8mq-add-DCSS-external-oscillator-suppor.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 8e5a885158f430de3ea36b1439dd8c0058ce95df Mon Sep 17 00:00:00 2001 -From: Laurentiu Palcu -Date: Fri, 22 Nov 2019 10:12:50 +0200 -Subject: [PATCH 44/49] arm64: dts: imx8mq: add DCSS external oscillator - support - -The external oscillator, which is high precision, will be used when DCSS output -goes to HDMI. - -Signed-off-by: Laurentiu Palcu ---- - arch/arm64/boot/dts/freescale/imx8mq.dtsi | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi -index 5a617f9ed8b5..b75252a65c44 100644 ---- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi -+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi -@@ -1113,8 +1113,11 @@ dcss: display-controller@32e00000 { - <&clk IMX8MQ_CLK_DISP_AXI_ROOT>, - <&clk IMX8MQ_CLK_DISP_RTRM_ROOT>, - <&clk IMX8MQ_VIDEO2_PLL_OUT>, -- <&clk IMX8MQ_CLK_DISP_DTRC>; -- clock-names = "apb", "axi", "rtrm", "pix", "dtrc"; -+ <&clk IMX8MQ_CLK_DISP_DTRC>, -+ <&clk IMX8MQ_VIDEO2_PLL1_REF_SEL>, -+ <&clk IMX8MQ_CLK_PHY_27MHZ>; -+ clock-names = "apb", "axi", "rtrm", "pix", "dtrc", "pll_src", -+ "pll_phy_ref"; - assigned-clocks = <&clk IMX8MQ_CLK_DISP_AXI>, - <&clk IMX8MQ_CLK_DISP_RTRM>, - <&clk IMX8MQ_VIDEO2_PLL1_REF_SEL>; --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0045-arm64-dts-fsl-imx8mq-add-HDP-bridge-node.patch b/projects/NXP/devices/iMX8/patches/linux/0045-arm64-dts-fsl-imx8mq-add-HDP-bridge-node.patch deleted file mode 100644 index 7eab52d86c..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0045-arm64-dts-fsl-imx8mq-add-HDP-bridge-node.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0327e9fc14269069711cd2d45d60130b318532fe Mon Sep 17 00:00:00 2001 -From: Lucas Stach -Date: Tue, 13 Feb 2018 12:30:58 +0100 -Subject: [PATCH 45/49] arm64: dts: fsl: imx8mq: add HDP bridge node - -Signed-off-by: Lucas Stach ---- - arch/arm64/boot/dts/freescale/imx8mq.dtsi | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi -index b75252a65c44..aad21d6f1da7 100644 ---- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi -+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi -@@ -1103,6 +1103,16 @@ bus@32c00000 { /* AIPS4 */ - #size-cells = <1>; - ranges = <0x32c00000 0x32c00000 0x400000>; - -+ hdmi: hdmi@32c00000 { -+ reg = <0x32c00000 0x33800>, /* HDP registers */ -+ <0x32e40000 0x40000>, /* HDP SEC register */ -+ <0x32e2f000 0x10>; /* RESET register */ -+ interrupts = , -+ ; -+ interrupt-names = "plug_in", "plug_out"; -+ status = "disabled"; -+ }; -+ - dcss: display-controller@32e00000 { - compatible = "nxp,imx8mq-dcss"; - reg = <0x32e00000 0x2d000>, <0x32e2f000 0x1000>; --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0046-arm64-dts-fsl-imx8mq-evk-enable-DCSS-and-HDMI.patch b/projects/NXP/devices/iMX8/patches/linux/0046-arm64-dts-fsl-imx8mq-evk-enable-DCSS-and-HDMI.patch deleted file mode 100644 index 48d5c6da67..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0046-arm64-dts-fsl-imx8mq-evk-enable-DCSS-and-HDMI.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 96ab278661207096c013ad1b39ed36f5f9a35ffd Mon Sep 17 00:00:00 2001 -From: Lucas Stach -Date: Tue, 13 Feb 2018 12:47:09 +0100 -Subject: [PATCH 46/49] arm64: dts: fsl: imx8mq-evk: enable DCSS and HDMI - -Signed-off-by: Lucas Stach ---- - arch/arm64/boot/dts/freescale/imx8mq-evk.dts | 22 ++++++++++++++++++++ - 1 file changed, 22 insertions(+) - -diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts -index 2418cca00bc5..71eeda6de3d7 100644 ---- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts -+++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts -@@ -132,6 +132,16 @@ opp-800M { - }; - }; - -+&dcss { -+ status = "okay"; -+ -+ port { -+ dcss_out: endpoint { -+ remote-endpoint = <&hdmi_in>; -+ }; -+ }; -+}; -+ - &dphy { - status = "okay"; - }; -@@ -168,6 +178,18 @@ wl-reg-on-hog { - }; - }; - -+&hdmi { -+ compatible = "cdn,imx8mq-hdmi"; -+ lane-mapping = <0xe4>; -+ status = "okay"; -+ -+ port { -+ hdmi_in: endpoint { -+ remote-endpoint = <&dcss_out>; -+ }; -+ }; -+}; -+ - &i2c1 { - clock-frequency = <100000>; - pinctrl-names = "default"; --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0047-arm64-dts-fsl-imx8mq-pico-pi-enable-DCSS-and-HDMI.patch b/projects/NXP/devices/iMX8/patches/linux/0047-arm64-dts-fsl-imx8mq-pico-pi-enable-DCSS-and-HDMI.patch deleted file mode 100644 index d9a5d06075..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0047-arm64-dts-fsl-imx8mq-pico-pi-enable-DCSS-and-HDMI.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 5a139d07d03076be7972db4b022558dffcfd685b Mon Sep 17 00:00:00 2001 -From: Lukas Rusak -Date: Tue, 9 Mar 2021 10:47:27 -0800 -Subject: [PATCH 47/49] arm64: dts: fsl: imx8mq-pico-pi: enable DCSS and HDMI - ---- - .../boot/dts/freescale/imx8mq-pico-pi.dts | 22 +++++++++++++++++++ - 1 file changed, 22 insertions(+) - -diff --git a/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts b/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts -index 89cbec5c41b2..03734145c50e 100644 ---- a/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts -+++ b/arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts -@@ -37,6 +37,16 @@ reg_usb_otg_vbus: regulator-usb-otg-vbus { - }; - }; - -+&dcss { -+ status = "okay"; -+ -+ port { -+ dcss_out: endpoint { -+ remote-endpoint = <&hdmi_in>; -+ }; -+ }; -+}; -+ - &fec1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_fec1 &pinctrl_enet_3v3>; -@@ -56,6 +66,18 @@ ethphy0: ethernet-phy@1 { - }; - }; - -+&hdmi { -+ compatible = "cdn,imx8mq-hdmi"; -+ lane-mapping = <0xe4>; -+ status = "okay"; -+ -+ port { -+ hdmi_in: endpoint { -+ remote-endpoint = <&dcss_out>; -+ }; -+ }; -+}; -+ - &i2c1 { - clock-frequency = <100000>; - pinctrl-names = "default"; --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0048-drm-imx-mhdp-don-t-depend-on-DRM_IMX.patch b/projects/NXP/devices/iMX8/patches/linux/0048-drm-imx-mhdp-don-t-depend-on-DRM_IMX.patch deleted file mode 100644 index c49bd36ee2..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0048-drm-imx-mhdp-don-t-depend-on-DRM_IMX.patch +++ /dev/null @@ -1,23 +0,0 @@ -From f94717816b9a39869219ede859fe74af3f2ecd19 Mon Sep 17 00:00:00 2001 -From: Lukas Rusak -Date: Wed, 24 Mar 2021 14:27:43 -0700 -Subject: [PATCH 48/49] drm: imx: mhdp: don't depend on DRM_IMX - ---- - drivers/gpu/drm/imx/mhdp/Kconfig | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/drivers/gpu/drm/imx/mhdp/Kconfig b/drivers/gpu/drm/imx/mhdp/Kconfig -index 86950badb947..cf7dfacdd434 100644 ---- a/drivers/gpu/drm/imx/mhdp/Kconfig -+++ b/drivers/gpu/drm/imx/mhdp/Kconfig -@@ -6,6 +6,5 @@ config DRM_IMX_CDNS_MHDP - select DRM_CDNS_DP - select DRM_CDNS_HDMI - select DRM_CDNS_AUDIO -- depends on DRM_IMX - help - Choose this if you want to use HDMI on i.MX8. --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0049-drm-cadence-shutup-cec-logging.patch b/projects/NXP/devices/iMX8/patches/linux/0049-drm-cadence-shutup-cec-logging.patch deleted file mode 100644 index 5589e19370..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0049-drm-cadence-shutup-cec-logging.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 3111faf58971c2c517457e62f84d138a3d62464e Mon Sep 17 00:00:00 2001 -From: Lukas Rusak -Date: Wed, 24 Mar 2021 15:14:57 -0700 -Subject: [PATCH 49/49] drm: cadence: shutup cec logging - ---- - drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c -index 25cf9e91e64f..e91de13eae58 100644 ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-cec.c -@@ -171,8 +171,8 @@ static u32 mhdp_cec_write_message(struct cdns_mhdp_cec *cec, struct cec_msg *msg - return -EINVAL; - } - -- for (i = 0; i < msg->len; ++i) -- printk("msg[%d]=0x%x\n",i, msg->msg[i]); -+ // for (i = 0; i < msg->len; ++i) -+ // printk("msg[%d]=0x%x\n",i, msg->msg[i]); - - /* Write Message to register */ - for (i = 0; i < msg->len; ++i) { --- -2.29.2 - diff --git a/projects/NXP/devices/iMX8/patches/linux/0050-drm-display-drm-hdmi-helper-h.patch b/projects/NXP/devices/iMX8/patches/linux/0050-drm-display-drm-hdmi-helper-h.patch deleted file mode 100644 index 9d4a322234..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0050-drm-display-drm-hdmi-helper-h.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c 2022-06-28 15:48:27.254022595 +0000 -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c 2022-06-28 15:46:14.919939083 +0000 -@@ -14,6 +14,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c 2022-06-28 15:53:59.618466556 +0000 -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-hdcp.c 2022-06-28 15:56:01.987635836 +0000 -@@ -11,6 +11,7 @@ - */ - #include - #include -+#include - #include - #include - diff --git a/projects/NXP/devices/iMX8/patches/linux/0060-mhdp-dp-hdmi-add-missing-include-patch-for-6-3.patch b/projects/NXP/devices/iMX8/patches/linux/0060-mhdp-dp-hdmi-add-missing-include-patch-for-6-3.patch deleted file mode 100644 index 081fc3affa..0000000000 --- a/projects/NXP/devices/iMX8/patches/linux/0060-mhdp-dp-hdmi-add-missing-include-patch-for-6-3.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c 2023-04-24 10:04:54.095068512 +0000 -+++ b/drivers/gpu/drm/imx/mhdp/cdns-mhdp-imxdrv.c 2023-04-25 13:35:44.405261313 +0000 -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - - #include - diff --git a/scripts/uboot_helper b/scripts/uboot_helper index a68bb30a02..499db71ac7 100755 --- a/scripts/uboot_helper +++ b/scripts/uboot_helper @@ -258,6 +258,10 @@ devices = \ 'dtb' : 'imx8mq-evk.dtb', 'config' : 'imx8mq_evk_defconfig' }, + 'phanbell' : { + 'dtb' : 'imx8mq-phanbell.dtb', + 'config' : 'imx8mq_phanbell_defconfig' + }, 'pico-mq' : { 'dtb' : 'imx8mq-pico-pi.dtb', 'config' : 'pico-imx8mq_defconfig'