From edbc7960bef7fd71ef1e44d0df15b864784b14c8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 19 May 2022 01:38:44 +0200 Subject: drm/bridge: ti-sn65dsi83: Handle dsi_lanes == 0 as invalid Handle empty data-lanes = < >; property, which translates to dsi_lanes = 0 as invalid. Fixes: ceb515ba29ba6 ("drm/bridge: ti-sn65dsi83: Add TI SN65DSI83 and SN65DSI84 driver") Signed-off-by: Marek Vasut Cc: Jonas Karlman Cc: Laurent Pinchart Cc: Lucas Stach Cc: Marek Vasut Cc: Maxime Ripard Cc: Neil Armstrong Cc: Robert Foss Cc: Sam Ravnborg Reviewed-by: Andrzej Hajda Reviewed-by: Lucas Stach Link: https://patchwork.freedesktop.org/patch/msgid/20220518233844.248504-1-marex@denx.de --- drivers/gpu/drm/bridge/ti-sn65dsi83.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c index 19daaddd29a4..3d58110465fe 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c @@ -573,7 +573,7 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model) ctx->host_node = of_graph_get_remote_port_parent(endpoint); of_node_put(endpoint); - if (ctx->dsi_lanes < 0 || ctx->dsi_lanes > 4) { + if (ctx->dsi_lanes <= 0 || ctx->dsi_lanes > 4) { ret = -EINVAL; goto err_put_node; } -- cgit From 6e516faf04317db2c46cbec4e3b78b4653a5b109 Mon Sep 17 00:00:00 2001 From: Steven Price Date: Thu, 19 May 2022 16:20:03 +0100 Subject: drm/panfrost: Job should reference MMU not file_priv For a while now it's been allowed for a MMU context to outlive it's corresponding panfrost_priv, however the job structure still references panfrost_priv to get hold of the MMU context. If panfrost_priv has been freed this is a use-after-free which I've been able to trigger resulting in a splat. To fix this, drop the reference to panfrost_priv in the job structure and add a direct reference to the MMU structure which is what's actually needed. Fixes: 7fdc48cc63a3 ("drm/panfrost: Make sure MMU context lifetime is not bound to panfrost_priv") Signed-off-by: Steven Price Acked-by: Alyssa Rosenzweig Link: https://patchwork.freedesktop.org/patch/msgid/20220519152003.81081-1-steven.price@arm.com --- drivers/gpu/drm/panfrost/panfrost_drv.c | 5 +++-- drivers/gpu/drm/panfrost/panfrost_job.c | 6 +++--- drivers/gpu/drm/panfrost/panfrost_job.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index 94b6f0a19c83..47780fe597f2 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -233,6 +233,7 @@ static int panfrost_ioctl_submit(struct drm_device *dev, void *data, struct drm_file *file) { struct panfrost_device *pfdev = dev->dev_private; + struct panfrost_file_priv *file_priv = file->driver_priv; struct drm_panfrost_submit *args = data; struct drm_syncobj *sync_out = NULL; struct panfrost_job *job; @@ -262,12 +263,12 @@ static int panfrost_ioctl_submit(struct drm_device *dev, void *data, job->jc = args->jc; job->requirements = args->requirements; job->flush_id = panfrost_gpu_get_latest_flush_id(pfdev); - job->file_priv = file->driver_priv; + job->mmu = file_priv->mmu; slot = panfrost_job_get_slot(job); ret = drm_sched_job_init(&job->base, - &job->file_priv->sched_entity[slot], + &file_priv->sched_entity[slot], NULL); if (ret) goto out_put_job; diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c index a6925dbb6224..22c2af1a4627 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.c +++ b/drivers/gpu/drm/panfrost/panfrost_job.c @@ -201,7 +201,7 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js) return; } - cfg = panfrost_mmu_as_get(pfdev, job->file_priv->mmu); + cfg = panfrost_mmu_as_get(pfdev, job->mmu); job_write(pfdev, JS_HEAD_NEXT_LO(js), lower_32_bits(jc_head)); job_write(pfdev, JS_HEAD_NEXT_HI(js), upper_32_bits(jc_head)); @@ -431,7 +431,7 @@ static void panfrost_job_handle_err(struct panfrost_device *pfdev, job->jc = 0; } - panfrost_mmu_as_put(pfdev, job->file_priv->mmu); + panfrost_mmu_as_put(pfdev, job->mmu); panfrost_devfreq_record_idle(&pfdev->pfdevfreq); if (signal_fence) @@ -452,7 +452,7 @@ static void panfrost_job_handle_done(struct panfrost_device *pfdev, * happen when we receive the DONE interrupt while doing a GPU reset). */ job->jc = 0; - panfrost_mmu_as_put(pfdev, job->file_priv->mmu); + panfrost_mmu_as_put(pfdev, job->mmu); panfrost_devfreq_record_idle(&pfdev->pfdevfreq); dma_fence_signal_locked(job->done_fence); diff --git a/drivers/gpu/drm/panfrost/panfrost_job.h b/drivers/gpu/drm/panfrost/panfrost_job.h index 77e6d0e6f612..8becc1ba0eb9 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.h +++ b/drivers/gpu/drm/panfrost/panfrost_job.h @@ -17,7 +17,7 @@ struct panfrost_job { struct kref refcount; struct panfrost_device *pfdev; - struct panfrost_file_priv *file_priv; + struct panfrost_mmu *mmu; /* Fence to be signaled by IRQ handler when the job is complete. */ struct dma_fence *done_fence; -- cgit From 743cdb7bd0f1cb32c03680c8b38257957db2e692 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 19 May 2022 17:45:21 +1000 Subject: powerpc/kasan: Mark more real-mode code as not to be instrumented This marks more files and functions that can possibly be called in real mode as not to be instrumented by KASAN. Most were found by inspection, except for get_pseries_errorlog() which was reported as causing a crash in testing. Reported-by: Nageswara R Sastry Signed-off-by: Paul Mackerras Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/YoX1kZPnmUX4RZEK@cleo --- arch/powerpc/kernel/Makefile | 2 ++ arch/powerpc/kernel/rtas.c | 4 ++-- arch/powerpc/kexec/crash.c | 2 +- arch/powerpc/platforms/powernv/Makefile | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 2e2a2a9bcf43..f91f0f29a566 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -37,6 +37,8 @@ KASAN_SANITIZE_paca.o := n KASAN_SANITIZE_setup_64.o := n KASAN_SANITIZE_mce.o := n KASAN_SANITIZE_mce_power.o := n +KASAN_SANITIZE_udbg.o := n +KASAN_SANITIZE_udbg_16550.o := n # we have to be particularly careful in ppc64 to exclude code that # runs with translations off, as we cannot access the shadow with diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 9bb43aa53d43..a6fce3106e02 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -993,8 +993,8 @@ int rtas_call_reentrant(int token, int nargs, int nret, int *outputs, ...) * * Return: A pointer to the specified errorlog or NULL if not found. */ -struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log, - uint16_t section_id) +noinstr struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log, + uint16_t section_id) { struct rtas_ext_event_log_v6 *ext_log = (struct rtas_ext_event_log_v6 *)log->buffer; diff --git a/arch/powerpc/kexec/crash.c b/arch/powerpc/kexec/crash.c index d85fa9fc6f3c..80f54723cf6d 100644 --- a/arch/powerpc/kexec/crash.c +++ b/arch/powerpc/kexec/crash.c @@ -224,7 +224,7 @@ void crash_kexec_secondary(struct pt_regs *regs) /* wait for all the CPUs to hit real mode but timeout if they don't come in */ #if defined(CONFIG_SMP) && defined(CONFIG_PPC64) -static void __maybe_unused crash_kexec_wait_realmode(int cpu) +noinstr static void __maybe_unused crash_kexec_wait_realmode(int cpu) { unsigned int msecs; int i; diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile index 6488b3842199..19f0fc5c6f1b 100644 --- a/arch/powerpc/platforms/powernv/Makefile +++ b/arch/powerpc/platforms/powernv/Makefile @@ -4,6 +4,7 @@ # in particular, idle code runs a bunch of things in real mode KASAN_SANITIZE_idle.o := n KASAN_SANITIZE_pci-ioda.o := n +KASAN_SANITIZE_pci-ioda-tce.o := n # pnv_machine_check_early KASAN_SANITIZE_setup.o := n -- cgit From a1b29ba2f2c171b9bea73be993bfdf0a62d37d15 Mon Sep 17 00:00:00 2001 From: He Ying Date: Thu, 20 Jan 2022 20:44:18 -0500 Subject: powerpc/kasan: Silence KASAN warnings in __get_wchan() The following KASAN warning was reported in our kernel. BUG: KASAN: stack-out-of-bounds in get_wchan+0x188/0x250 Read of size 4 at addr d216f958 by task ps/14437 CPU: 3 PID: 14437 Comm: ps Tainted: G O 5.10.0 #1 Call Trace: [daa63858] [c0654348] dump_stack+0x9c/0xe4 (unreliable) [daa63888] [c035cf0c] print_address_description.constprop.3+0x8c/0x570 [daa63908] [c035d6bc] kasan_report+0x1ac/0x218 [daa63948] [c00496e8] get_wchan+0x188/0x250 [daa63978] [c0461ec8] do_task_stat+0xce8/0xe60 [daa63b98] [c0455ac8] proc_single_show+0x98/0x170 [daa63bc8] [c03cab8c] seq_read_iter+0x1ec/0x900 [daa63c38] [c03cb47c] seq_read+0x1dc/0x290 [daa63d68] [c037fc94] vfs_read+0x164/0x510 [daa63ea8] [c03808e4] ksys_read+0x144/0x1d0 [daa63f38] [c005b1dc] ret_from_syscall+0x0/0x38 --- interrupt: c00 at 0x8fa8f4 LR = 0x8fa8cc The buggy address belongs to the page: page:98ebcdd2 refcount:0 mapcount:0 mapping:00000000 index:0x2 pfn:0x1216f flags: 0x0() raw: 00000000 00000000 01010122 00000000 00000002 00000000 ffffffff 00000000 raw: 00000000 page dumped because: kasan: bad access detected Memory state around the buggy address: d216f800: 00 00 00 00 00 f1 f1 f1 f1 00 00 00 00 00 00 00 d216f880: f2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >d216f900: 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 ^ d216f980: f2 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00 00 00 00 d216fa00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 After looking into this issue, I find the buggy address belongs to the task stack region. It seems KASAN has something wrong. I look into the code of __get_wchan in x86 architecture and find the same issue has been resolved by the commit f7d27c35ddff ("x86/mm, kasan: Silence KASAN warnings in get_wchan()"). The solution could be applied to powerpc architecture too. As Andrey Ryabinin said, get_wchan() is racy by design, it may access volatile stack of running task, thus it may access redzone in a stack frame and cause KASAN to warn about this. Use READ_ONCE_NOCHECK() to silence these warnings. Reported-by: Wanming Hu Signed-off-by: He Ying Signed-off-by: Chen Jingwen Reviewed-by: Kees Cook Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20220121014418.155675-1-heying24@huawei.com --- arch/powerpc/kernel/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index d00b20c65966..ca4d97688da9 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -2157,12 +2157,12 @@ static unsigned long ___get_wchan(struct task_struct *p) return 0; do { - sp = *(unsigned long *)sp; + sp = READ_ONCE_NOCHECK(*(unsigned long *)sp); if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD) || task_is_running(p)) return 0; if (count > 0) { - ip = ((unsigned long *)sp)[STACK_FRAME_LR_SAVE]; + ip = READ_ONCE_NOCHECK(((unsigned long *)sp)[STACK_FRAME_LR_SAVE]); if (!in_sched_functions(ip)) return ip; } -- cgit From 1346d00e1bdfd4067f92bc14e8a6131a01de4190 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 25 May 2022 13:26:39 +1000 Subject: powerpc: Don't select HAVE_IRQ_EXIT_ON_IRQ_STACK The HAVE_IRQ_EXIT_ON_IRQ_STACK option tells generic code that irq_exit() is called while still running on the hard irq stack (hardirq_ctx[] in the powerpc code). Selecting the option means the generic code will *not* switch to the softirq stack before running softirqs, because the code is already running on the (mostly empty) hard irq stack. But since commit 1b1b6a6f4cc0 ("powerpc: handle irq_enter/irq_exit in interrupt handler wrappers"), irq_exit() is now called on the regular task stack, not the hard irq stack. That's because previously irq_exit() was called in __do_irq() which is run on the hard irq stack, but now it is called in interrupt_async_exit_prepare() which is called from do_irq() constructed by the wrapper macro, which is after the switch back to the task stack. So drop HAVE_IRQ_EXIT_ON_IRQ_STACK from the Kconfig. This will mean an extra stack switch when processing some interrupts, but should significantly reduce the likelihood of stack overflow. It also means the softirq stack will be used for running softirqs from other interrupts that don't use the hard irq stack, eg. timer interrupts. Fixes: 1b1b6a6f4cc0 ("powerpc: handle irq_enter/irq_exit in interrupt handler wrappers") Cc: stable@vger.kernel.org # v5.12+ Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20220525032639.1947280-1-mpe@ellerman.id.au --- arch/powerpc/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 3eaddb8997a9..54dbbb1d4b36 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -223,7 +223,6 @@ config PPC select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI && !HAVE_HARDLOCKUP_DETECTOR_ARCH select HAVE_HW_BREAKPOINT if PERF_EVENTS && (PPC_BOOK3S || PPC_8xx) select HAVE_IOREMAP_PROT - select HAVE_IRQ_EXIT_ON_IRQ_STACK select HAVE_IRQ_TIME_ACCOUNTING select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZMA if DEFAULT_UIMAGE -- cgit From 9ff9f77f34e44a0054eadb9041e459548c955ccb Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 24 May 2022 06:31:54 -0400 Subject: MAINTAINERS: reciprocal co-maintainership for file locking and nfsd Chuck has agreed to backstop me as maintainer of the file locking code, and I'll do the same for him on knfsd. Signed-off-by: Jeff Layton Signed-off-by: Chuck Lever --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d6d879cb0afd..82f89b035cce 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7572,6 +7572,7 @@ F: include/uapi/scsi/fc/ FILE LOCKING (flock() and fcntl()/lockf()) M: Jeff Layton +M: Chuck Lever L: linux-fsdevel@vger.kernel.org S: Maintained F: fs/fcntl.c @@ -10646,6 +10647,7 @@ W: http://kernelnewbies.org/KernelJanitors KERNEL NFSD, SUNRPC, AND LOCKD SERVERS M: Chuck Lever +M: Jeff Layton L: linux-nfs@vger.kernel.org S: Supported W: http://nfs.sourceforge.net/ -- cgit From 07bf9431b1590d1cd7a8d62075d0b50b073f0495 Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Tue, 24 May 2022 16:53:53 +0530 Subject: powerpc/papr_scm: don't requests stats with '0' sized stats buffer Sachin reported [1] that on a POWER-10 lpar he is seeing a kernel panic being reported with vPMEM when papr_scm probe is being called. The panic is of the form below and is observed only with following option disabled(profile) for the said LPAR 'Enable Performance Information Collection' in the HMC: Kernel attempted to write user page (1c) - exploit attempt? (uid: 0) BUG: Kernel NULL pointer dereference on write at 0x0000001c Faulting instruction address: 0xc008000001b90844 Oops: Kernel access of bad area, sig: 11 [#1] NIP [c008000001b90844] drc_pmem_query_stats+0x5c/0x270 [papr_scm] LR [c008000001b92794] papr_scm_probe+0x2ac/0x6ec [papr_scm] Call Trace: 0xc00000000941bca0 (unreliable) papr_scm_probe+0x2ac/0x6ec [papr_scm] platform_probe+0x98/0x150 really_probe+0xfc/0x510 __driver_probe_device+0x17c/0x230 ---[ end trace 0000000000000000 ]--- Kernel panic - not syncing: Fatal exception On investigation looks like this panic was caused due to a 'stat_buffer' of size==0 being provided to drc_pmem_query_stats() to fetch all performance stats-ids of an NVDIMM. However drc_pmem_query_stats() shouldn't have been called since the vPMEM NVDIMM doesn't support and performance stat-id's. This was caused due to missing check for 'p->stat_buffer_len' at the beginning of papr_scm_pmu_check_events() which indicates that the NVDIMM doesn't support performance-stats. Fix this by introducing the check for 'p->stat_buffer_len' at the beginning of papr_scm_pmu_check_events(). [1] https://lore.kernel.org/all/6B3A522A-6A5F-4CC9-B268-0C63AA6E07D3@linux.ibm.com Fixes: 0e0946e22f3665d2732 ("powerpc/papr_scm: Fix leaking nvdimm_events_map elements") Reported-by: Sachin Sant Signed-off-by: Vaibhav Jain Tested-by: Sachin Sant Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20220524112353.1718454-1-vaibhav@linux.ibm.com --- arch/powerpc/platforms/pseries/papr_scm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c index 181b855b3050..82cae08976bc 100644 --- a/arch/powerpc/platforms/pseries/papr_scm.c +++ b/arch/powerpc/platforms/pseries/papr_scm.c @@ -465,6 +465,9 @@ static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu u32 available_events; int index, rc = 0; + if (!p->stat_buffer_len) + return -ENOENT; + available_events = (p->stat_buffer_len - sizeof(struct papr_scm_perf_stats)) / sizeof(struct papr_scm_perf_stat); if (available_events == 0) -- cgit From 291e7d52d19f114cad6cbf802f3f19ef12a011f8 Mon Sep 17 00:00:00 2001 From: Ben Chuang Date: Fri, 20 May 2022 19:42:42 +0800 Subject: mmc: sdhci-pci-gli: Fix GL9763E runtime PM when the system resumes from suspend When the system resumes from suspend (S3 or S4), the power mode is MMC_POWER_OFF. In this status, gl9763e_runtime_resume() should not enable PLL. Add a condition to this function to enable PLL only when the power mode is MMC_POWER_ON. Fixes: d607667bb8fa (mmc: sdhci-pci-gli: Add runtime PM for GL9763E) Signed-off-by: Ben Chuang Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20220520114242.150235-1-benchuanggli@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-gli.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index 1499a64ec3aa..f13c08db3da5 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -982,6 +982,9 @@ static int gl9763e_runtime_resume(struct sdhci_pci_chip *chip) struct sdhci_host *host = slot->host; u16 clock; + if (host->mmc->ios.power_mode != MMC_POWER_ON) + return 0; + clock = sdhci_readw(host, SDHCI_CLOCK_CONTROL); clock |= SDHCI_CLOCK_PLL_EN; -- cgit From 5f92df8ddacb4b97f6865a3bf687f240072f4f68 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 31 May 2022 08:54:02 -0700 Subject: Input: raspberrypi-ts - add missing HAS_IOMEM dependency Since JOYSTICK_SENSEHAT selects MFD_SIMPLE_MFD_I2C and the latter depends on HAS_IOMEM, and since 'select' does not follow any dependency chains, JOYSTICK_SENSEHAT should also depend on HAS_IOMEM to prevent a kconfig warning and a build error: WARNING: unmet direct dependencies detected for MFD_SIMPLE_MFD_I2C Depends on [n]: HAS_IOMEM [=n] && I2C [=y] Selected by [y]: - JOYSTICK_SENSEHAT [=y] && INPUT_JOYSTICK [=y] && INPUT [=y] && I2C [=y] s390-linux-ld: drivers/mfd/simple-mfd-i2c.o: in function `simple_mfd_i2c_probe': simple-mfd-i2c.c:(.text+0xc8): undefined reference to `devm_mfd_add_devices' Fixes: 41657514c796 ("Input: add Raspberry Pi Sense HAT joystick driver") Signed-off-by: Randy Dunlap Link: https://lore.kernel.org/r/20220531022942.16340-1-rdunlap@infradead.org Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 505a032e2786..9dcf3f51f2dd 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig @@ -402,6 +402,7 @@ config JOYSTICK_N64 config JOYSTICK_SENSEHAT tristate "Raspberry Pi Sense HAT joystick" depends on INPUT && I2C + depends on HAS_IOMEM select MFD_SIMPLE_MFD_I2C help Say Y here if you want to enable the driver for the -- cgit From a051246b786af7e4a9d9219cc7038a6e8a411531 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 31 May 2022 20:19:22 +0300 Subject: mmc: block: Fix CQE recovery reset success The intention of the use of mmc_blk_reset_success() in mmc_blk_cqe_recovery() was to prevent repeated resets when retrying and getting the same error. However, that may not be the case - any amount of time and I/O may pass before another recovery is needed, in which case there would be no reason to deny it the opportunity to recover via a reset if necessary. CQE recovery is expected seldom and failure to recover (if the clear tasks command fails), even more seldom, so it is better to allow the reset always, which can be done by calling mmc_blk_reset_success() always. Fixes: 1e8e55b67030c6 ("mmc: block: Add CQE support") Cc: stable@vger.kernel.org Signed-off-by: Adrian Hunter Link: https://lore.kernel.org/r/20220531171922.76080-1-adrian.hunter@intel.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/block.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 1259ca22d625..f4a1281658db 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1499,8 +1499,7 @@ void mmc_blk_cqe_recovery(struct mmc_queue *mq) err = mmc_cqe_recovery(host); if (err) mmc_blk_reset(mq->blkdata, host, MMC_BLK_CQE_RECOVERY); - else - mmc_blk_reset_success(mq->blkdata, MMC_BLK_CQE_RECOVERY); + mmc_blk_reset_success(mq->blkdata, MMC_BLK_CQE_RECOVERY); pr_debug("%s: CQE recovery done\n", mmc_hostname(host)); } -- cgit From 282e5f8fe907dc3f2fbf9f2103b0e62ffc3a68a5 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 1 Jun 2022 10:47:35 +0200 Subject: netfilter: nat: really support inet nat without l3 address When no l3 address is given, priv->family is set to NFPROTO_INET and the evaluation function isn't called. Call it too so l4-only rewrite can work. Also add a test case for this. Fixes: a33f387ecd5aa ("netfilter: nft_nat: allow to specify layer 4 protocol NAT only") Reported-by: Yi Chen Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_nat.c | 3 +- tools/testing/selftests/netfilter/nft_nat.sh | 43 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c index 4394df4bc99b..e5fd6995e4bf 100644 --- a/net/netfilter/nft_nat.c +++ b/net/netfilter/nft_nat.c @@ -335,7 +335,8 @@ static void nft_nat_inet_eval(const struct nft_expr *expr, { const struct nft_nat *priv = nft_expr_priv(expr); - if (priv->family == nft_pf(pkt)) + if (priv->family == nft_pf(pkt) || + priv->family == NFPROTO_INET) nft_nat_eval(expr, regs, pkt); } diff --git a/tools/testing/selftests/netfilter/nft_nat.sh b/tools/testing/selftests/netfilter/nft_nat.sh index eb8543b9a5c4..924ecb3f1f73 100755 --- a/tools/testing/selftests/netfilter/nft_nat.sh +++ b/tools/testing/selftests/netfilter/nft_nat.sh @@ -374,6 +374,45 @@ EOF return $lret } +test_local_dnat_portonly() +{ + local family=$1 + local daddr=$2 + local lret=0 + local sr_s + local sr_r + +ip netns exec "$ns0" nft -f /dev/stdin < Date: Wed, 1 Jun 2022 16:00:00 +0200 Subject: netfilter: nf_tables: use kfree_rcu(ptr, rcu) to release hooks in clean_net path Use kfree_rcu(ptr, rcu) variant instead as described by ae089831ff28 ("netfilter: nf_tables: prefer kfree_rcu(ptr, rcu) variant"). Fixes: f9a43007d3f7 ("netfilter: nf_tables: double hook unregistration in netns path") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 746be13438ef..129d3ebd6ce5 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -7332,7 +7332,7 @@ static void __nft_unregister_flowtable_net_hooks(struct net *net, nf_unregister_net_hook(net, &hook->ops); if (release_netdev) { list_del(&hook->list); - kfree_rcu(hook); + kfree_rcu(hook, rcu); } } } -- cgit From 479260419fa4cb30e3e5d935a857fbdf0ffdd854 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 25 May 2022 20:42:04 -0500 Subject: dt-bindings: mmc: Fix unevaluatedProperties warnings in examples The 'unevaluatedProperties' schema checks is not fully working and doesn't catch some cases where there's a $ref to another schema. A fix is pending, but results in new warnings in examples. Fix the warnings by removing spurious properties or adding a missing property to the schema. Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220526014204.2873107-1-robh@kernel.org Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml | 2 -- Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml index b672202fff4e..5ecdac9de484 100644 --- a/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml +++ b/Documentation/devicetree/bindings/mmc/brcm,sdhci-brcmstb.yaml @@ -75,7 +75,6 @@ examples: sd-uhs-sdr104; sdhci,auto-cmd12; interrupts = <0x0 0x26 0x4>; - interrupt-names = "sdio0_0"; clocks = <&scmi_clk 245>; clock-names = "sw_sdio"; }; @@ -94,7 +93,6 @@ examples: non-removable; bus-width = <0x8>; interrupts = <0x0 0x27 0x4>; - interrupt-names = "sdio1_0"; clocks = <&scmi_clk 245>; clock-names = "sw_sdio"; }; diff --git a/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml b/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml index c79639e9027e..aca1a4a8daea 100644 --- a/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml @@ -56,6 +56,9 @@ properties: - const: core - const: axi + interrupts: + maxItems: 1 + marvell,xenon-sdhc-id: $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 -- cgit From 4b81dd2cc6f4f4e8cea0ed6ee8d5193a8ae14a72 Mon Sep 17 00:00:00 2001 From: Sherry Wang Date: Tue, 10 May 2022 18:42:18 +0800 Subject: drm/amd/display: Read Golden Settings Table from VBIOS [Why] Dmub read AUX_DPHY_RX_CONTROL0 from Golden Setting Table, but driver will set it to default value 0x103d1110, which causes issue in some case [How] Remove the driver code, use the value set by dmub in dp_aux_init Reviewed-by: Nicholas Kazlauskas Acked-by: Jasdeep Dhillon Tested-by: Daniel Wheeler Signed-off-by: Sherry Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c index d94fd1010deb..8b12b4111c88 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c @@ -230,9 +230,7 @@ static void enc31_hw_init(struct link_encoder *enc) AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 AUX_RX_DETECTION_THRESHOLD [30:28] = 1 */ - AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); - - AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); + // dmub will read AUX_DPHY_RX_CONTROL0/AUX_DPHY_TX_CONTROL from vbios table in dp_aux_init //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk -- cgit From 0ec744084793db817990424cc3cc9da63f665f3f Mon Sep 17 00:00:00 2001 From: "Leung, Martin" Date: Tue, 10 May 2022 12:27:08 -0400 Subject: drm/amd/display: revert Blank eDP on disable/enable drv why and how: Revert this change. It was causing a black screen with certain blocks Reviewed-by: George Shen Acked-by: Jasdeep Dhillon Tested-by: Daniel Wheeler Signed-off-by: Leung, Martin Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 8 +++++++- .../drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.h | 2 ++ .../amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 5 +++-- .../amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 3 ++- drivers/gpu/drm/amd/display/dc/dc.h | 3 +++ drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c | 4 ---- drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h | 1 + drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h | 18 ++++++++++++------ .../gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c | 19 ++++++++++++++----- 9 files changed, 44 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index ceb34376decb..051322580014 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -638,8 +638,14 @@ static void dcn31_set_low_power_state(struct clk_mgr *clk_mgr_base) } } +int dcn31_get_dtb_ref_freq_khz(struct clk_mgr *clk_mgr_base) +{ + return clk_mgr_base->clks.ref_dtbclk_khz; +} + static struct clk_mgr_funcs dcn31_funcs = { .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, + .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz, .update_clocks = dcn31_update_clocks, .init_clocks = dcn31_init_clocks, .enable_pme_wa = dcn31_enable_pme_wa, @@ -719,7 +725,7 @@ void dcn31_clk_mgr_construct( } clk_mgr->base.base.dprefclk_khz = 600000; - clk_mgr->base.dccg->ref_dtbclk_khz = 600000; + clk_mgr->base.base.clks.ref_dtbclk_khz = 600000; dce_clock_read_ss_info(&clk_mgr->base); /*if bios enabled SS, driver needs to adjust dtb clock, only enable with correct bios*/ //clk_mgr->base.dccg->ref_dtbclk_khz = dce_adjust_dp_ref_freq_for_ss(clk_mgr_internal, clk_mgr->base.base.dprefclk_khz); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.h index 961b10a49486..be06fdbd0c22 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.h @@ -51,6 +51,8 @@ void dcn31_clk_mgr_construct(struct dc_context *ctx, struct pp_smu_funcs *pp_smu, struct dccg *dccg); +int dcn31_get_dtb_ref_freq_khz(struct clk_mgr *clk_mgr_base); + void dcn31_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int); #endif //__DCN31_CLK_MGR_H__ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index a2ade6e93f5e..29a3bf57b157 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -580,6 +580,7 @@ static void dcn315_enable_pme_wa(struct clk_mgr *clk_mgr_base) static struct clk_mgr_funcs dcn315_funcs = { .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, + .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz, .update_clocks = dcn315_update_clocks, .init_clocks = dcn31_init_clocks, .enable_pme_wa = dcn315_enable_pme_wa, @@ -656,9 +657,9 @@ void dcn315_clk_mgr_construct( clk_mgr->base.base.dprefclk_khz = 600000; clk_mgr->base.base.dprefclk_khz = dcn315_smu_get_dpref_clk(&clk_mgr->base); - clk_mgr->base.dccg->ref_dtbclk_khz = clk_mgr->base.base.dprefclk_khz; + clk_mgr->base.base.clks.ref_dtbclk_khz = clk_mgr->base.base.dprefclk_khz; dce_clock_read_ss_info(&clk_mgr->base); - clk_mgr->base.dccg->ref_dtbclk_khz = dce_adjust_dp_ref_freq_for_ss(&clk_mgr->base, clk_mgr->base.base.dprefclk_khz); + clk_mgr->base.base.clks.ref_dtbclk_khz = dce_adjust_dp_ref_freq_for_ss(&clk_mgr->base, clk_mgr->base.base.dprefclk_khz); clk_mgr->base.base.bw_params = &dcn315_bw_params; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c index fc3af81ed6c6..e4bb9c6193b5 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c @@ -571,6 +571,7 @@ static void dcn316_clk_mgr_helper_populate_bw_params( static struct clk_mgr_funcs dcn316_funcs = { .enable_pme_wa = dcn316_enable_pme_wa, .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, + .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz, .update_clocks = dcn316_update_clocks, .init_clocks = dcn31_init_clocks, .are_clock_states_equal = dcn31_are_clock_states_equal, @@ -685,7 +686,7 @@ void dcn316_clk_mgr_construct( clk_mgr->base.base.dprefclk_khz = 600000; clk_mgr->base.base.dprefclk_khz = dcn316_smu_get_dpref_clk(&clk_mgr->base); - clk_mgr->base.dccg->ref_dtbclk_khz = clk_mgr->base.base.dprefclk_khz; + clk_mgr->base.base.clks.ref_dtbclk_khz = clk_mgr->base.base.dprefclk_khz; dce_clock_read_ss_info(&clk_mgr->base); /*clk_mgr->base.dccg->ref_dtbclk_khz = dce_adjust_dp_ref_freq_for_ss(&clk_mgr->base, clk_mgr->base.base.dprefclk_khz);*/ diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 3960c74482be..4c1f977838b5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -416,6 +416,7 @@ struct dc_clocks { bool p_state_change_support; enum dcn_zstate_support_state zstate_support; bool dtbclk_en; + int ref_dtbclk_khz; enum dcn_pwr_state pwr_state; /* * Elements below are not compared for the purposes of @@ -719,6 +720,8 @@ struct dc_debug_options { bool apply_vendor_specific_lttpr_wa; bool extended_blank_optimization; union aux_wake_wa_options aux_wake_wa; + /* uses value at boot and disables switch */ + bool disable_dtb_ref_clk_switch; uint8_t psr_power_use_phy_fsm; enum dml_hostvm_override_opts dml_hostvm_override; }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c index 287a1066b547..616013c618a5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c @@ -606,16 +606,12 @@ void dccg31_set_audio_dtbclk_dto( REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, 4); // 04 - DCCG_AUDIO_DTO_SEL_AUDIO_DTO_DTBCLK - - dccg->audio_dtbclk_khz = req_audio_dtbclk_khz; } else { REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, 0); REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, 0); REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, 3); // 03 - DCCG_AUDIO_DTO_SEL_NO_AUDIO_DTO - - dccg->audio_dtbclk_khz = 0; } } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index 46ce5a0ee4ec..b5570aa8e39d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -237,6 +237,7 @@ struct clk_mgr_funcs { bool safe_to_lower); int (*get_dp_ref_clk_frequency)(struct clk_mgr *clk_mgr); + int (*get_dtb_ref_clk_frequency)(struct clk_mgr *clk_mgr); void (*set_low_power_state)(struct clk_mgr *clk_mgr); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h index b2fa4de47734..cc358a5ba537 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h @@ -60,8 +60,17 @@ struct dccg { const struct dccg_funcs *funcs; int pipe_dppclk_khz[MAX_PIPES]; int ref_dppclk; - int dtbclk_khz[MAX_PIPES]; - int audio_dtbclk_khz; + //int dtbclk_khz[MAX_PIPES];/* TODO needs to be removed */ + //int audio_dtbclk_khz;/* TODO needs to be removed */ + //int ref_dtbclk_khz;/* TODO needs to be removed */ +}; + +struct dtbclk_dto_params { + const struct dc_crtc_timing *timing; + int otg_inst; + int pixclk_khz; + int req_audio_dtbclk_khz; + int num_odm_segments; int ref_dtbclk_khz; }; @@ -111,10 +120,7 @@ struct dccg_funcs { void (*set_dtbclk_dto)( struct dccg *dccg, - int dtbclk_inst, - int req_dtbclk_khz, - int num_odm_segments, - const struct dc_crtc_timing *timing); + const struct dtbclk_dto_params *params); void (*set_audio_dtbclk_dto)( struct dccg *dccg, diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c index 87972dc8443d..ea6cf8bfce30 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c @@ -27,6 +27,7 @@ #include "core_types.h" #include "dccg.h" #include "dc_link_dp.h" +#include "clk_mgr.h" static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link) { @@ -106,14 +107,18 @@ static void setup_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx) struct hpo_dp_link_encoder *link_enc = pipe_ctx->link_res.hpo_dp_link_enc; struct dccg *dccg = dc->res_pool->dccg; struct timing_generator *tg = pipe_ctx->stream_res.tg; - int odm_segment_count = get_odm_segment_count(pipe_ctx); + struct dtbclk_dto_params dto_params = {0}; enum phyd32clk_clock_source phyd32clk = get_phyd32clk_src(pipe_ctx->stream->link); + dto_params.otg_inst = tg->inst; + dto_params.pixclk_khz = pipe_ctx->stream->phy_pix_clk; + dto_params.num_odm_segments = get_odm_segment_count(pipe_ctx); + dto_params.timing = &pipe_ctx->stream->timing; + dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr); + dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst); dccg->funcs->enable_symclk32_se(dccg, stream_enc->inst, phyd32clk); - dccg->funcs->set_dtbclk_dto(dccg, tg->inst, pipe_ctx->stream->phy_pix_clk, - odm_segment_count, - &pipe_ctx->stream->timing); + dccg->funcs->set_dtbclk_dto(dccg, &dto_params); stream_enc->funcs->enable_stream(stream_enc); stream_enc->funcs->map_stream_to_link(stream_enc, stream_enc->inst, link_enc->inst); } @@ -124,9 +129,13 @@ static void reset_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx) struct hpo_dp_stream_encoder *stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc; struct dccg *dccg = dc->res_pool->dccg; struct timing_generator *tg = pipe_ctx->stream_res.tg; + struct dtbclk_dto_params dto_params = {0}; + + dto_params.otg_inst = tg->inst; + dto_params.timing = &pipe_ctx->stream->timing; stream_enc->funcs->disable(stream_enc); - dccg->funcs->set_dtbclk_dto(dccg, tg->inst, 0, 0, &pipe_ctx->stream->timing); + dccg->funcs->set_dtbclk_dto(dccg, &dto_params); dccg->funcs->disable_symclk32_se(dccg, stream_enc->inst); dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst); } -- cgit From 8440f57532496d398a461887e56ca6f45089fbcf Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Fri, 6 May 2022 12:56:38 -0400 Subject: drm/amd/display: Pass the new context into disable OTG WA [Why] When enabling an HPO stream for the first time after having previously enabled a DIO stream there may be lingering DIO FIFO errors even though the DIO is no longer enabled. These can cause display clock change to hang if we don't apply the OTG disable workaround since the ramping logic is tied to OTG on. [How] The workaround wasn't being applied in the sequence of: 1 DIO stream 0 streams 1 HPO stream because current_state has no stream or planes in its context - and it's only swapped after optimize has finished. We should be using the incoming context instead to determine whether this logic is needed or not. Reviewed-by: Dmytro Laktyushkin Reviewed-by: Dmytro Laktyushkin Acked-by: Jasdeep Dhillon Tested-by: Daniel Wheeler Signed-off-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 051322580014..7310482b2784 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -99,13 +99,13 @@ static int dcn31_get_active_display_cnt_wa( return display_count; } -static void dcn31_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable) +static void dcn31_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) { struct dc *dc = clk_mgr_base->ctx->dc; int i; for (i = 0; i < dc->res_pool->pipe_count; ++i) { - struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; if (pipe->top_pipe || pipe->prev_odm_pipe) continue; @@ -211,11 +211,11 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base, } if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { - dcn31_disable_otg_wa(clk_mgr_base, true); + dcn31_disable_otg_wa(clk_mgr_base, context, true); clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; dcn31_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); - dcn31_disable_otg_wa(clk_mgr_base, false); + dcn31_disable_otg_wa(clk_mgr_base, context, false); update_dispclk = true; } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index 29a3bf57b157..a50e1e519dff 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -81,13 +81,13 @@ static int dcn315_get_active_display_cnt_wa( return display_count; } -static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable) +static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) { struct dc *dc = clk_mgr_base->ctx->dc; int i; for (i = 0; i < dc->res_pool->pipe_count; ++i) { - struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; if (pipe->top_pipe || pipe->prev_odm_pipe) continue; @@ -175,11 +175,11 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, } if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { - dcn315_disable_otg_wa(clk_mgr_base, true); + dcn315_disable_otg_wa(clk_mgr_base, context, true); clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; dcn315_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); - dcn315_disable_otg_wa(clk_mgr_base, false); + dcn315_disable_otg_wa(clk_mgr_base, context, false); update_dispclk = true; } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c index e4bb9c6193b5..7192f30858eb 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c @@ -112,13 +112,13 @@ static int dcn316_get_active_display_cnt_wa( return display_count; } -static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable) +static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) { struct dc *dc = clk_mgr_base->ctx->dc; int i; for (i = 0; i < dc->res_pool->pipe_count; ++i) { - struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; if (pipe->top_pipe || pipe->prev_odm_pipe) continue; @@ -221,11 +221,11 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, } if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { - dcn316_disable_otg_wa(clk_mgr_base, true); + dcn316_disable_otg_wa(clk_mgr_base, context, true); clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; dcn316_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); - dcn316_disable_otg_wa(clk_mgr_base, false); + dcn316_disable_otg_wa(clk_mgr_base, context, false); update_dispclk = true; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h index cc358a5ba537..4c880b64f8ca 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h @@ -120,7 +120,7 @@ struct dccg_funcs { void (*set_dtbclk_dto)( struct dccg *dccg, - const struct dtbclk_dto_params *params); + struct dtbclk_dto_params *dto_params); void (*set_audio_dtbclk_dto)( struct dccg *dccg, -- cgit From 92909cde3235f894d7cdf59709d86e9b22f897ce Mon Sep 17 00:00:00 2001 From: hengzhou Date: Sat, 7 May 2022 09:43:08 +0800 Subject: drm/amd/display: Wait DMCUB to idle state before reset. [WHY] Very low rate to cause memory access issue while resetting DMCUB after the halt command was sent to it. The process of stopping fw of DMCUB may be timeout, that means it is not in idle state, such as the window frames may still be kept in cache, so reset by force will cause MMHUB hang. [HOW] After the halt command was sent, keep checking the DMCUB state until it is idle. Reviewed-by: Eric Yang Reviewed-by: Nicholas Kazlauskas Acked-by: Jasdeep Dhillon Tested-by: Daniel Wheeler Signed-off-by: hengzhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h | 2 +- drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 9 ++++++++- drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h index 4c880b64f8ca..c7021915bac8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h @@ -62,7 +62,7 @@ struct dccg { int ref_dppclk; //int dtbclk_khz[MAX_PIPES];/* TODO needs to be removed */ //int audio_dtbclk_khz;/* TODO needs to be removed */ - //int ref_dtbclk_khz;/* TODO needs to be removed */ + int ref_dtbclk_khz;/* TODO needs to be removed */ }; struct dtbclk_dto_params { diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index 7c9330a61ac1..8d4574895757 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -84,7 +84,7 @@ void dmub_dcn31_reset(struct dmub_srv *dmub) { union dmub_gpint_data_register cmd; const uint32_t timeout = 100; - uint32_t in_reset, scratch, i; + uint32_t in_reset, scratch, i, pwait_mode; REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); @@ -115,6 +115,13 @@ void dmub_dcn31_reset(struct dmub_srv *dmub) udelay(1); } + for (i = 0; i < timeout; ++i) { + REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &pwait_mode); + if (pwait_mode & (1 << 0)) + break; + + udelay(1); + } /* Force reset in case we timed out, DMCUB is likely hung. */ } diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h index 59ddc81b5a0e..f6db6f89d45d 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h @@ -151,7 +151,8 @@ struct dmub_srv; DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \ DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR) \ DMUB_SF(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN) \ - DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK) + DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK) \ + DMUB_SF(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS) struct dmub_srv_dcn31_reg_offset { #define DMUB_SR(reg) uint32_t reg; -- cgit From 6ecf9773a5030aa4932096754bacff20e1b944b8 Mon Sep 17 00:00:00 2001 From: "Hung, Cruise" Date: Fri, 13 May 2022 09:16:42 +0800 Subject: drm/amd/display: Fix DMUB outbox trace in S4 (#4465) [Why] DMUB Outbox0 read/write pointer not sync after resumed from S4. And that caused old traces were sent to outbox. [How] Disable DMUB Outbox0 interrupt and clear DMUB Outbox0 read/write pointer when resumes from S4. And then enable Outbox0 interrupt before starts DMCUB. Reviewed-by: Nicholas Kazlauskas Acked-by: Jasdeep Dhillon Tested-by: Daniel Wheeler Signed-off-by: Cruise Hung Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c | 61 +++++++++++------------ drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 2 + 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c index 616013c618a5..0eb89e117a6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c @@ -513,12 +513,10 @@ void dccg31_set_physymclk( /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */ static void dccg31_set_dtbclk_dto( struct dccg *dccg, - int dtbclk_inst, - int req_dtbclk_khz, - int num_odm_segments, - const struct dc_crtc_timing *timing) + struct dtbclk_dto_params *params) { struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + int req_dtbclk_khz = params->pixclk_khz; uint32_t dtbdto_div; /* Mode DTBDTO Rate DTBCLK_DTO_DIV Register @@ -529,57 +527,56 @@ static void dccg31_set_dtbclk_dto( * DSC native 4:2:2 pixel rate/2 4 * Other modes pixel rate 8 */ - if (num_odm_segments == 4) { + if (params->num_odm_segments == 4) { dtbdto_div = 2; - req_dtbclk_khz = req_dtbclk_khz / 4; - } else if ((num_odm_segments == 2) || - (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) || - (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 - && !timing->dsc_cfg.ycbcr422_simple)) { + req_dtbclk_khz = params->pixclk_khz / 4; + } else if ((params->num_odm_segments == 2) || + (params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) || + (params->timing->flags.DSC && params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 + && !params->timing->dsc_cfg.ycbcr422_simple)) { dtbdto_div = 4; - req_dtbclk_khz = req_dtbclk_khz / 2; + req_dtbclk_khz = params->pixclk_khz / 2; } else dtbdto_div = 8; - if (dccg->ref_dtbclk_khz && req_dtbclk_khz) { + if (params->ref_dtbclk_khz && req_dtbclk_khz) { uint32_t modulo, phase; // phase / modulo = dtbclk / dtbclk ref - modulo = dccg->ref_dtbclk_khz * 1000; - phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + dccg->ref_dtbclk_khz - 1), - dccg->ref_dtbclk_khz); + modulo = params->ref_dtbclk_khz * 1000; + phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + params->ref_dtbclk_khz - 1), + params->ref_dtbclk_khz); - REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst], - DTBCLK_DTO_DIV[dtbclk_inst], dtbdto_div); + REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], + DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div); - REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], modulo); - REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], phase); + REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo); + REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase); - REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst], - DTBCLK_DTO_ENABLE[dtbclk_inst], 1); + REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], + DTBCLK_DTO_ENABLE[params->otg_inst], 1); - REG_WAIT(OTG_PIXEL_RATE_CNTL[dtbclk_inst], - DTBCLKDTO_ENABLE_STATUS[dtbclk_inst], 1, + REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst], + DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1, 1, 100); /* The recommended programming sequence to enable DTBCLK DTO to generate * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should * be set only after DTO is enabled */ - REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst], - PIPE_DTO_SRC_SEL[dtbclk_inst], 1); - - dccg->dtbclk_khz[dtbclk_inst] = req_dtbclk_khz; + REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], + PIPE_DTO_SRC_SEL[params->otg_inst], 1); } else { - REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[dtbclk_inst], - DTBCLK_DTO_ENABLE[dtbclk_inst], 0, - PIPE_DTO_SRC_SEL[dtbclk_inst], 0, - DTBCLK_DTO_DIV[dtbclk_inst], dtbdto_div); + REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[params->otg_inst], + DTBCLK_DTO_ENABLE[params->otg_inst], 0, + PIPE_DTO_SRC_SEL[params->otg_inst], 0, + DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div); REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], 0); REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], 0); - dccg->dtbclk_khz[dtbclk_inst] = 0; + REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0); + REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0); } } diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index 8d4574895757..c7bd7e216710 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -132,6 +132,8 @@ void dmub_dcn31_reset(struct dmub_srv *dmub) REG_WRITE(DMCUB_INBOX1_WPTR, 0); REG_WRITE(DMCUB_OUTBOX1_RPTR, 0); REG_WRITE(DMCUB_OUTBOX1_WPTR, 0); + REG_WRITE(DMCUB_OUTBOX0_RPTR, 0); + REG_WRITE(DMCUB_OUTBOX0_WPTR, 0); REG_WRITE(DMCUB_SCRATCH0, 0); /* Clear the GPINT command manually so we don't send anything during boot. */ -- cgit From f0ad66f42a3d914ac5f9972731ec5bc97f35002d Mon Sep 17 00:00:00 2001 From: Alvin Date: Thu, 12 May 2022 16:49:16 -0400 Subject: drm/amd/display: Don't clear ref_dtbclk value [Description] ref_dtbclk value is assigned in clk_mgr_construct, but the clks struct is cleared in init_clocks. Make sure to restore the value or we will get 0 value for ref_dtbclk in DCN31. Reviewed-by: Chris Park Acked-by: Jasdeep Dhillon Tested-by: Daniel Wheeler Signed-off-by: Alvin Lee Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 3 +++ drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c | 3 --- drivers/gpu/drm/amd/display/include/ddc_service_types.h | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 7310482b2784..6a81c1aea0be 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -287,8 +287,11 @@ static void dcn31_enable_pme_wa(struct clk_mgr *clk_mgr_base) void dcn31_init_clocks(struct clk_mgr *clk_mgr) { + uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz; + memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks)); // Assumption is that boot state always supports pstate + clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk; // restore ref_dtbclk clk_mgr->clks.p_state_change_support = true; clk_mgr->clks.prev_p_state_change_support = true; clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c index 0eb89e117a6a..bbc58d167c63 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c @@ -572,9 +572,6 @@ static void dccg31_set_dtbclk_dto( PIPE_DTO_SRC_SEL[params->otg_inst], 0, DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div); - REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], 0); - REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], 0); - REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0); REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0); } diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h index 73b9e0a87e54..20a3d4e23f66 100644 --- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -127,6 +127,8 @@ struct av_sync_data { static const uint8_t DP_SINK_DEVICE_STR_ID_1[] = {7, 1, 8, 7, 3, 0}; static const uint8_t DP_SINK_DEVICE_STR_ID_2[] = {7, 1, 8, 7, 5, 0}; +static const u8 DP_SINK_BRANCH_DEV_NAME_7580[] = "7580\x80u"; + /*MST Dock*/ static const uint8_t SYNAPTICS_DEVICE_ID[] = "SYNA"; -- cgit From 583ad88871b38dc39f05a316dcde909e444b09a6 Mon Sep 17 00:00:00 2001 From: Ilya Date: Mon, 7 Feb 2022 17:39:10 -0500 Subject: drm/amd/display: Fix possible infinite loop in DP LT fallback [Why] It's possible for some fallback scenarios to result in infinite looping during link training. [How] This change modifies DP LT fallback behavior to more closely match the DP standard. Keep track of the link rate during the EQ_FAIL fallback, and use it as the maximum link rate for the CR sequence. Reviewed-by: Wenjing Liu Tested-by: Daniel Wheeler Signed-off-by: Ilya Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 106 +++++++++++------------ 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 3c9523218c19..03eedffbb5b2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -114,8 +114,8 @@ static const struct dc_link_settings fail_safe_link_settings = { static bool decide_fallback_link_setting( struct dc_link *link, - struct dc_link_settings initial_link_settings, - struct dc_link_settings *current_link_setting, + struct dc_link_settings *max, + struct dc_link_settings *cur, enum link_training_result training_result); static void maximize_lane_settings(const struct link_training_settings *lt_settings, struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); @@ -2784,6 +2784,7 @@ bool perform_link_training_with_retries( enum dp_panel_mode panel_mode = dp_get_panel_mode(link); enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0; struct dc_link_settings cur_link_settings = *link_setting; + struct dc_link_settings max_link_settings = *link_setting; const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); int fail_count = 0; bool is_link_bw_low = false; /* link bandwidth < stream bandwidth */ @@ -2793,7 +2794,6 @@ bool perform_link_training_with_retries( dp_trace_commit_lt_init(link); - if (dp_get_link_encoding_format(&cur_link_settings) == DP_8b_10b_ENCODING) /* We need to do this before the link training to ensure the idle * pattern in SST mode will be sent right after the link training @@ -2909,19 +2909,15 @@ bool perform_link_training_with_retries( uint32_t req_bw; uint32_t link_bw; - decide_fallback_link_setting(link, *link_setting, &cur_link_settings, status); - /* Flag if reduced link bandwidth no longer meets stream requirements or fallen back to - * minimum link bandwidth. + decide_fallback_link_setting(link, &max_link_settings, + &cur_link_settings, status); + /* Fail link training if reduced link bandwidth no longer meets + * stream requirements. */ req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing); link_bw = dc_link_bandwidth_kbps(link, &cur_link_settings); - is_link_bw_low = (req_bw > link_bw); - is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) && - (cur_link_settings.lane_count <= LANE_COUNT_ONE)); - - if (is_link_bw_low) - DC_LOG_WARNING("%s: Link bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n", - __func__, req_bw, link_bw); + if (req_bw > link_bw) + break; } msleep(delay_between_attempts); @@ -3309,7 +3305,7 @@ static bool dp_verify_link_cap( int *fail_count) { struct dc_link_settings cur_link_settings = {0}; - struct dc_link_settings initial_link_settings = *known_limit_link_setting; + struct dc_link_settings max_link_settings = *known_limit_link_setting; bool success = false; bool skip_video_pattern; enum clock_source_id dp_cs_id = get_clock_source_id(link); @@ -3318,7 +3314,7 @@ static bool dp_verify_link_cap( struct link_resource link_res; memset(&irq_data, 0, sizeof(irq_data)); - cur_link_settings = initial_link_settings; + cur_link_settings = max_link_settings; /* Grant extended timeout request */ if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (link->dpcd_caps.lttpr_caps.max_ext_timeout > 0)) { @@ -3361,7 +3357,7 @@ static bool dp_verify_link_cap( dp_trace_lt_result_update(link, status, true); dp_disable_link_phy(link, &link_res, link->connector_signal); } while (!success && decide_fallback_link_setting(link, - initial_link_settings, &cur_link_settings, status)); + &max_link_settings, &cur_link_settings, status)); link->verified_link_cap = success ? cur_link_settings : fail_safe_link_settings; @@ -3596,16 +3592,19 @@ static bool decide_fallback_link_setting_max_bw_policy( */ static bool decide_fallback_link_setting( struct dc_link *link, - struct dc_link_settings initial_link_settings, - struct dc_link_settings *current_link_setting, + struct dc_link_settings *max, + struct dc_link_settings *cur, enum link_training_result training_result) { - if (!current_link_setting) + if (!cur) return false; - if (dp_get_link_encoding_format(&initial_link_settings) == DP_128b_132b_ENCODING || + if (!max) + return false; + + if (dp_get_link_encoding_format(max) == DP_128b_132b_ENCODING || link->dc->debug.force_dp2_lt_fallback_method) - return decide_fallback_link_setting_max_bw_policy(link, &initial_link_settings, - current_link_setting, training_result); + return decide_fallback_link_setting_max_bw_policy(link, max, cur, + training_result); switch (training_result) { case LINK_TRAINING_CR_FAIL_LANE0: @@ -3613,28 +3612,18 @@ static bool decide_fallback_link_setting( case LINK_TRAINING_CR_FAIL_LANE23: case LINK_TRAINING_LQA_FAIL: { - if (!reached_minimum_link_rate - (current_link_setting->link_rate)) { - current_link_setting->link_rate = - reduce_link_rate( - current_link_setting->link_rate); - } else if (!reached_minimum_lane_count - (current_link_setting->lane_count)) { - current_link_setting->link_rate = - initial_link_settings.link_rate; + if (!reached_minimum_link_rate(cur->link_rate)) { + cur->link_rate = reduce_link_rate(cur->link_rate); + } else if (!reached_minimum_lane_count(cur->lane_count)) { + cur->link_rate = max->link_rate; if (training_result == LINK_TRAINING_CR_FAIL_LANE0) return false; else if (training_result == LINK_TRAINING_CR_FAIL_LANE1) - current_link_setting->lane_count = - LANE_COUNT_ONE; - else if (training_result == - LINK_TRAINING_CR_FAIL_LANE23) - current_link_setting->lane_count = - LANE_COUNT_TWO; + cur->lane_count = LANE_COUNT_ONE; + else if (training_result == LINK_TRAINING_CR_FAIL_LANE23) + cur->lane_count = LANE_COUNT_TWO; else - current_link_setting->lane_count = - reduce_lane_count( - current_link_setting->lane_count); + cur->lane_count = reduce_lane_count(cur->lane_count); } else { return false; } @@ -3642,17 +3631,17 @@ static bool decide_fallback_link_setting( } case LINK_TRAINING_EQ_FAIL_EQ: { - if (!reached_minimum_lane_count - (current_link_setting->lane_count)) { - current_link_setting->lane_count = - reduce_lane_count( - current_link_setting->lane_count); - } else if (!reached_minimum_link_rate - (current_link_setting->link_rate)) { - current_link_setting->link_rate = - reduce_link_rate( - current_link_setting->link_rate); - current_link_setting->lane_count = initial_link_settings.lane_count; + if (!reached_minimum_lane_count(cur->lane_count)) { + cur->lane_count = reduce_lane_count(cur->lane_count); + } else if (!reached_minimum_link_rate(cur->link_rate)) { + cur->link_rate = reduce_link_rate(cur->link_rate); + /* Reduce max link rate to avoid potential infinite loop. + * Needed so that any subsequent CR_FAIL fallback can't + * re-set the link rate higher than the link rate from + * the latest EQ_FAIL fallback. + */ + max->link_rate = cur->link_rate; + cur->lane_count = max->lane_count; } else { return false; } @@ -3660,12 +3649,15 @@ static bool decide_fallback_link_setting( } case LINK_TRAINING_EQ_FAIL_CR: { - if (!reached_minimum_link_rate - (current_link_setting->link_rate)) { - current_link_setting->link_rate = - reduce_link_rate( - current_link_setting->link_rate); - current_link_setting->lane_count = initial_link_settings.lane_count; + if (!reached_minimum_link_rate(cur->link_rate)) { + cur->link_rate = reduce_link_rate(cur->link_rate); + /* Reduce max link rate to avoid potential infinite loop. + * Needed so that any subsequent CR_FAIL fallback can't + * re-set the link rate higher than the link rate from + * the latest EQ_FAIL fallback. + */ + max->link_rate = cur->link_rate; + cur->lane_count = max->lane_count; } else { return false; } -- cgit From 067541847781b8e3abd7400ffdc0d402432613c8 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 15 May 2022 21:52:38 -0400 Subject: drm/amd/display: 3.2.187 This version brings along the following fixes: * Changes to DP LT fallback behavior to more closely match the DP standard * Added new interfaces for lut pipeline * Restore ref_dtblck value when clk struct is cleared in init_clocks * Fixes DMUB outbox trace in S4 * Fixes lingering DIO FIFO errors when DIO no longer enabled * Reads Golden Settings Table from VBIOS Acked-by: Jasdeep Dhillon Signed-off-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4c1f977838b5..817028d3c4a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.186" +#define DC_VER "3.2.187" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 11594fa114276ed41b9fa3849f7eb79be10162d6 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Wed, 25 May 2022 17:37:02 +0800 Subject: drm/amdgpu: make program_imu_rlc_ram static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This symbol is not used outside of imu_v11_0.c, so marks it static. Fixes the following w1 warning: drivers/gpu/drm/amd/amdgpu/imu_v11_0.c:302:6: warning: no previous prototype for ‘program_imu_rlc_ram’ [-Wmissing-prototypes]. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/imu_v11_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c b/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c index 5d2dfeff8fe5..d63d3f2b8a16 100644 --- a/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c @@ -299,7 +299,7 @@ static const struct imu_rlc_ram_golden imu_rlc_ram_golden_11_0_2[] = IMU_RLC_RAM_GOLDEN_VALUE(GC, 0, regCPG_PSP_DEBUG, CPG_PSP_DEBUG__GPA_OVERRIDE_MASK, 0) }; -void program_imu_rlc_ram(struct amdgpu_device *adev, +static void program_imu_rlc_ram(struct amdgpu_device *adev, const struct imu_rlc_ram_golden *regs, const u32 array_size) { -- cgit From 97e50305542f384741a5b45699aba349fe9fca73 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 26 May 2022 16:34:55 -0400 Subject: drm/amdgpu: update VCN codec support for Yellow Carp Supports AV1. Mesa already has support for this and doesn't rely on the kernel caps for yellow carp, so this was already working from an application perspective. Fixes: 554398174d98 ("amdgpu/nv.c - Added video codec support for Yellow Carp") Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2002 Reviewed-by: Leo Liu Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/nv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index d016e3c3e221..b3fba8dea63c 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -170,6 +170,7 @@ static const struct amdgpu_video_codec_info yc_video_codecs_decode_array[] = { {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, }; static const struct amdgpu_video_codecs yc_video_codecs_decode = { -- cgit From ae969b62e7a1e17affae24b815b217b9b87a62f4 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 25 May 2022 17:20:21 -0400 Subject: drm/amdgpu: fix aper_base for APU [Why] Wrong fb offset results in dmub f/w errors and white screen. [drm:dc_dmub_srv_wait_idle [amdgpu]] *ERROR* Error waiting for DMUB idle: status=3 [How] Read aper_base from mmhub because GC is off by default v2: use BAR for passthrough (Alex) Signed-off-by: Roman Li Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index a0c0b7d9f444..7f4b480ae66e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -638,6 +638,12 @@ static int gmc_v11_0_mc_init(struct amdgpu_device *adev) adev->gmc.aper_base = pci_resource_start(adev->pdev, 0); adev->gmc.aper_size = pci_resource_len(adev->pdev, 0); +#ifdef CONFIG_X86_64 + if ((adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev)) { + adev->gmc.aper_base = adev->mmhub.funcs->get_mc_fb_offset(adev); + adev->gmc.aper_size = adev->gmc.real_vram_size; + } +#endif /* In case the PCI BAR is larger than the actual amount of vram */ adev->gmc.visible_vram_size = adev->gmc.aper_size; if (adev->gmc.visible_vram_size > adev->gmc.real_vram_size) -- cgit From 418214ddcf6e79e4e572f8c7a18e1de7cab195b4 Mon Sep 17 00:00:00 2001 From: sunliming Date: Sun, 29 May 2022 15:26:31 +0800 Subject: drm/amdgpu: fix a missing break in gfx_v11_0_handle_priv_fault Fixes the following w1 warning: drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c:5873:2: warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough]. Reported-by: kernel test robot Signed-off-by: sunliming Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 8c0a3fc7aaa6..4353192ecd99 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -6028,6 +6028,7 @@ static void gfx_v11_0_handle_priv_fault(struct amdgpu_device *adev, break; default: BUG(); + break; } } -- cgit From 8365ed22d00b5e5889425c8d96462ad88ae463bc Mon Sep 17 00:00:00 2001 From: sunliming Date: Sun, 29 May 2022 14:26:31 +0800 Subject: drm/amdgpu: make gfx_v11_0_rlc_stop static This symbol is not used outside of gfx_v11_0.c, so marks it static. Fixes the following w1 warning: drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c:1945:6: warning: no previous prototype for function 'gfx_v11_0_rlc_stop' [-Wmissing-prototypes]. Reported-by: kernel test robot Signed-off-by: sunliming Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 4353192ecd99..628d3536938e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -1983,7 +1983,7 @@ static int gfx_v11_0_init_csb(struct amdgpu_device *adev) return 0; } -void gfx_v11_0_rlc_stop(struct amdgpu_device *adev) +static void gfx_v11_0_rlc_stop(struct amdgpu_device *adev) { u32 tmp = RREG32_SOC15(GC, 0, regRLC_CNTL); -- cgit From fd843d03418ead2bba369159bb19b60e9d4b7b1e Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Thu, 14 Apr 2022 15:48:30 -0400 Subject: drm/amd/display: remove stale config guards This code should be executed. Signed-off-by: Aurabindo Pillai Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 2 -- drivers/gpu/drm/amd/display/dc/dml/dml_wrapper.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index a50e1e519dff..aa01a18df419 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -41,9 +41,7 @@ #include "dc_dmub_srv.h" -#if defined (CONFIG_DRM_AMD_DC_DP2_0) #include "dc_link_dp.h" -#endif #define TO_CLK_MGR_DCN315(clk_mgr)\ container_of(clk_mgr, struct clk_mgr_dcn315, base) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper.c index 789f7562cdc7..d2273674e872 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper.c @@ -1284,10 +1284,8 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) for (i = 0; i < dc->res_pool->pipe_count; i++) { if (!context->res_ctx.pipe_ctx[i].stream) continue; -#if defined (CONFIG_DRM_AMD_DC_DP2_0) if (is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) return true; -#endif } return false; } -- cgit From 28caf8c467e2cb98b90a760b65767fa9aaf52ffb Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" Date: Tue, 31 May 2022 18:57:06 +0800 Subject: drm/amdgpu: fix ras supported check Fix aldebaran ras supported check on SRIOV guest side, the previous check conditicon block all ras feature on baremetal Signed-off-by: Stanley.Yang Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 2de9309a4193..1b1b502897ef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2278,8 +2278,9 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev) !amdgpu_ras_asic_supported(adev)) return; - if (!(amdgpu_sriov_vf(adev) && - (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2)))) + /* If driver run on sriov guest side, only enable ras for aldebaran */ + if (amdgpu_sriov_vf(adev) && + adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 2)) return; if (!adev->gmc.xgmi.connected_to_cpu) { -- cgit From 2a460963350ec6b1534d28d7f943b5f84815aff2 Mon Sep 17 00:00:00 2001 From: Candice Li Date: Wed, 1 Jun 2022 17:10:44 +0800 Subject: drm/amdgpu: Resolve RAS GFX error count issue after cold boot on Arcturus Adjust the sequence for ras late init and separate ras reset error status from query status. v2: squash in fix from Candice Signed-off-by: Candice Li Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 9 ++++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 27 ++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index ede2fa56f6c9..16699158e00d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -594,17 +594,20 @@ int amdgpu_get_gfx_off_status(struct amdgpu_device *adev, uint32_t *value) int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block) { int r; - r = amdgpu_ras_block_late_init(adev, ras_block); - if (r) - return r; if (amdgpu_ras_is_supported(adev, ras_block->block)) { if (!amdgpu_persistent_edc_harvesting_supported(adev)) amdgpu_ras_reset_error_status(adev, AMDGPU_RAS_BLOCK__GFX); + r = amdgpu_ras_block_late_init(adev, ras_block); + if (r) + return r; + r = amdgpu_irq_get(adev, &adev->gfx.cp_ecc_error_irq, 0); if (r) goto late_fini; + } else { + amdgpu_ras_feature_enable_on_boot(adev, ras_block, 0); } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 1b1b502897ef..dac202ae864d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -197,6 +197,13 @@ static ssize_t amdgpu_ras_debugfs_read(struct file *f, char __user *buf, if (amdgpu_ras_query_error_status(obj->adev, &info)) return -EINVAL; + /* Hardware counter will be reset automatically after the query on Vega20 and Arcturus */ + if (obj->adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 2) && + obj->adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 4)) { + if (amdgpu_ras_reset_error_status(obj->adev, info.head.block)) + dev_warn(obj->adev->dev, "Failed to reset error counter and error status"); + } + s = snprintf(val, sizeof(val), "%s: %lu\n%s: %lu\n", "ue", info.ue_count, "ce", info.ce_count); @@ -550,9 +557,10 @@ static ssize_t amdgpu_ras_sysfs_read(struct device *dev, if (amdgpu_ras_query_error_status(obj->adev, &info)) return -EINVAL; - if (obj->adev->asic_type == CHIP_ALDEBARAN) { + if (obj->adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 2) && + obj->adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 4)) { if (amdgpu_ras_reset_error_status(obj->adev, info.head.block)) - DRM_WARN("Failed to reset error counter and error status"); + dev_warn(obj->adev->dev, "Failed to reset error counter and error status"); } return sysfs_emit(buf, "%s: %lu\n%s: %lu\n", "ue", info.ue_count, @@ -1027,9 +1035,6 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, } } - if (!amdgpu_persistent_edc_harvesting_supported(adev)) - amdgpu_ras_reset_error_status(adev, info->head.block); - return 0; } @@ -1149,6 +1154,12 @@ int amdgpu_ras_query_error_count(struct amdgpu_device *adev, if (res) return res; + if (adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 2) && + adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 4)) { + if (amdgpu_ras_reset_error_status(adev, info.head.block)) + dev_warn(adev->dev, "Failed to reset error counter and error status"); + } + ce += info.ce_count; ue += info.ue_count; } @@ -1792,6 +1803,12 @@ static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev) continue; amdgpu_ras_query_error_status(adev, &info); + + if (adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 2) && + adev->ip_versions[MP0_HWIP][0] != IP_VERSION(11, 0, 4)) { + if (amdgpu_ras_reset_error_status(adev, info.head.block)) + dev_warn(adev->dev, "Failed to reset error counter and error status"); + } } } -- cgit From fa582c6f3684ac0098a9d02ddf0ed52a02b37127 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Thu, 26 May 2022 16:15:38 -0400 Subject: drm/amdkfd: Use mmget_not_zero in MMU notifier MMU notifier callback may pass in mm with mm->mm_users==0 when process is exiting, use mmget_no_zero to avoid accessing invalid mm in deferred list work after mm is gone. Signed-off-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 2ebf0132c25b..3bd0f1a670bb 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -2307,6 +2307,8 @@ svm_range_cpu_invalidate_pagetables(struct mmu_interval_notifier *mni, if (range->event == MMU_NOTIFY_RELEASE) return true; + if (!mmget_not_zero(mni->mm)) + return true; start = mni->interval_tree.start; last = mni->interval_tree.last; @@ -2333,6 +2335,7 @@ svm_range_cpu_invalidate_pagetables(struct mmu_interval_notifier *mni, } svm_range_unlock(prange); + mmput(mni->mm); return true; } -- cgit From e19f8fa6ce1ca9b8b934ba7d2e8f34c95abc6e60 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 1 Jun 2022 07:51:16 -0700 Subject: dma-debug: make things less spammy under memory pressure Limit the error msg to avoid flooding the console. If you have a lot of threads hitting this at once, they could have already gotten passed the dma_debug_disabled() check before they get to the point of allocation failure, resulting in quite a lot of this error message spamming the log. Use pr_err_once() to limit that. Signed-off-by: Rob Clark Signed-off-by: Christoph Hellwig --- kernel/dma/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c index ac740630c79c..2caafd13f8aa 100644 --- a/kernel/dma/debug.c +++ b/kernel/dma/debug.c @@ -564,7 +564,7 @@ static void add_dma_entry(struct dma_debug_entry *entry, unsigned long attrs) rc = active_cacheline_insert(entry); if (rc == -ENOMEM) { - pr_err("cacheline tracking ENOMEM, dma-debug disabled\n"); + pr_err_once("cacheline tracking ENOMEM, dma-debug disabled\n"); global_disable = true; } else if (rc == -EEXIST && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) { err_printk(entry->dev, entry, -- cgit From e15db62bc5648ab459a570862f654e787c498faf Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 1 Jun 2022 20:49:39 +0200 Subject: swiotlb: fix setting ->force_bounce The swiotlb_init refactor messed up assigning ->force_bounce by doing it in different places based on what caused the setting of the flag. Fix this by passing the SWIOTLB_* flags to swiotlb_init_io_tlb_mem and just setting it there. Fixes: c6af2aa9ffc9 ("swiotlb: make the swiotlb_init interface more useful") Reported-by: Nathan Chancellor Signed-off-by: Christoph Hellwig Tested-by: Nathan Chancellor --- kernel/dma/swiotlb.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index dfa1de89dc94..cb50f8d38360 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -192,7 +192,7 @@ void __init swiotlb_update_mem_attributes(void) } static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start, - unsigned long nslabs, bool late_alloc) + unsigned long nslabs, unsigned int flags, bool late_alloc) { void *vaddr = phys_to_virt(start); unsigned long bytes = nslabs << IO_TLB_SHIFT, i; @@ -203,8 +203,7 @@ static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start, mem->index = 0; mem->late_alloc = late_alloc; - if (swiotlb_force_bounce) - mem->force_bounce = true; + mem->force_bounce = swiotlb_force_bounce || (flags & SWIOTLB_FORCE); spin_lock_init(&mem->lock); for (i = 0; i < mem->nslabs; i++) { @@ -275,8 +274,7 @@ retry: panic("%s: Failed to allocate %zu bytes align=0x%lx\n", __func__, alloc_size, PAGE_SIZE); - swiotlb_init_io_tlb_mem(mem, __pa(tlb), nslabs, false); - mem->force_bounce = flags & SWIOTLB_FORCE; + swiotlb_init_io_tlb_mem(mem, __pa(tlb), nslabs, flags, false); if (flags & SWIOTLB_VERBOSE) swiotlb_print_info(); @@ -348,7 +346,7 @@ retry: set_memory_decrypted((unsigned long)vstart, (nslabs << IO_TLB_SHIFT) >> PAGE_SHIFT); - swiotlb_init_io_tlb_mem(mem, virt_to_phys(vstart), nslabs, true); + swiotlb_init_io_tlb_mem(mem, virt_to_phys(vstart), nslabs, 0, true); swiotlb_print_info(); return 0; @@ -835,8 +833,8 @@ static int rmem_swiotlb_device_init(struct reserved_mem *rmem, set_memory_decrypted((unsigned long)phys_to_virt(rmem->base), rmem->size >> PAGE_SHIFT); - swiotlb_init_io_tlb_mem(mem, rmem->base, nslabs, false); - mem->force_bounce = true; + swiotlb_init_io_tlb_mem(mem, rmem->base, nslabs, SWIOTLB_FORCE, + false); mem->for_alloc = true; rmem->priv = mem; -- cgit From b6d9014a3335194590abdd2a2471ef5147a67645 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 30 May 2022 18:40:06 +0200 Subject: netfilter: nf_tables: delete flowtable hooks via transaction list Remove inactive bool field in nft_hook object that was introduced in abadb2f865d7 ("netfilter: nf_tables: delete devices from flowtable"). Move stale flowtable hooks to transaction list instead. Deleting twice the same device does not result in ENOENT. Fixes: abadb2f865d7 ("netfilter: nf_tables: delete devices from flowtable") Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 1 - net/netfilter/nf_tables_api.c | 31 ++++++------------------------- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 20af9d3557b9..279ae0fff7ad 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -1090,7 +1090,6 @@ struct nft_stats { struct nft_hook { struct list_head list; - bool inactive; struct nf_hook_ops ops; struct rcu_head rcu; }; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 129d3ebd6ce5..30588349f96c 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1914,7 +1914,6 @@ static struct nft_hook *nft_netdev_hook_alloc(struct net *net, goto err_hook_dev; } hook->ops.dev = dev; - hook->inactive = false; return hook; @@ -7618,6 +7617,7 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx, { const struct nlattr * const *nla = ctx->nla; struct nft_flowtable_hook flowtable_hook; + LIST_HEAD(flowtable_del_list); struct nft_hook *this, *hook; struct nft_trans *trans; int err; @@ -7633,7 +7633,7 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx, err = -ENOENT; goto err_flowtable_del_hook; } - hook->inactive = true; + list_move(&hook->list, &flowtable_del_list); } trans = nft_trans_alloc(ctx, NFT_MSG_DELFLOWTABLE, @@ -7646,6 +7646,7 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx, nft_trans_flowtable(trans) = flowtable; nft_trans_flowtable_update(trans) = true; INIT_LIST_HEAD(&nft_trans_flowtable_hooks(trans)); + list_splice(&flowtable_del_list, &nft_trans_flowtable_hooks(trans)); nft_flowtable_hook_release(&flowtable_hook); nft_trans_commit_list_add_tail(ctx->net, trans); @@ -7653,13 +7654,7 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx, return 0; err_flowtable_del_hook: - list_for_each_entry(this, &flowtable_hook.list, list) { - hook = nft_hook_list_find(&flowtable->hook_list, this); - if (!hook) - break; - - hook->inactive = false; - } + list_splice(&flowtable_del_list, &flowtable->hook_list); nft_flowtable_hook_release(&flowtable_hook); return err; @@ -8563,17 +8558,6 @@ void nft_chain_del(struct nft_chain *chain) list_del_rcu(&chain->list); } -static void nft_flowtable_hooks_del(struct nft_flowtable *flowtable, - struct list_head *hook_list) -{ - struct nft_hook *hook, *next; - - list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) { - if (hook->inactive) - list_move(&hook->list, hook_list); - } -} - static void nf_tables_module_autoload_cleanup(struct net *net) { struct nftables_pernet *nft_net = nft_pernet(net); @@ -8918,8 +8902,6 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) break; case NFT_MSG_DELFLOWTABLE: if (nft_trans_flowtable_update(trans)) { - nft_flowtable_hooks_del(nft_trans_flowtable(trans), - &nft_trans_flowtable_hooks(trans)); nf_tables_flowtable_notify(&trans->ctx, nft_trans_flowtable(trans), &nft_trans_flowtable_hooks(trans), @@ -9000,7 +8982,6 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action) struct nftables_pernet *nft_net = nft_pernet(net); struct nft_trans *trans, *next; struct nft_trans_elem *te; - struct nft_hook *hook; if (action == NFNL_ABORT_VALIDATE && nf_tables_validate(net) < 0) @@ -9131,8 +9112,8 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action) break; case NFT_MSG_DELFLOWTABLE: if (nft_trans_flowtable_update(trans)) { - list_for_each_entry(hook, &nft_trans_flowtable(trans)->hook_list, list) - hook->inactive = false; + list_splice(&nft_trans_flowtable_hooks(trans), + &nft_trans_flowtable(trans)->hook_list); } else { trans->ctx.table->use++; nft_clear(trans->ctx.net, nft_trans_flowtable(trans)); -- cgit From 3e8635fb2e072672cbc650989ffedf8300ad67fb Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 2 Jun 2022 00:31:14 +1000 Subject: powerpc/kasan: Force thread size increase with KASAN KASAN causes increased stack usage, which can lead to stack overflows. The logic in Kconfig to suggest a larger default doesn't work if a user has CONFIG_EXPERT enabled and has an existing .config with a smaller value. Follow the lead of x86 and arm64, and force the thread size to be increased when KASAN is enabled. That also has the effect of enlarging the stack for 64-bit KASAN builds, which is also desirable. Fixes: edbadaf06710 ("powerpc/kasan: Fix stack overflow by increasing THREAD_SHIFT") Reported-by: Erhard Furtner Reported-by: Christophe Leroy [mpe: Use MIN_THREAD_SHIFT as suggested by Christophe] Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20220601143114.133524-1-mpe@ellerman.id.au --- arch/powerpc/Kconfig | 1 - arch/powerpc/include/asm/thread_info.h | 10 ++++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 54dbbb1d4b36..b1760d615bb7 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -790,7 +790,6 @@ config THREAD_SHIFT range 13 15 default "15" if PPC_256K_PAGES default "14" if PPC64 - default "14" if KASAN default "13" help Used to define the stack size. The default is almost always what you diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 125328d1b980..af58f1ed3952 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -14,10 +14,16 @@ #ifdef __KERNEL__ -#if defined(CONFIG_VMAP_STACK) && CONFIG_THREAD_SHIFT < PAGE_SHIFT +#ifdef CONFIG_KASAN +#define MIN_THREAD_SHIFT (CONFIG_THREAD_SHIFT + 1) +#else +#define MIN_THREAD_SHIFT CONFIG_THREAD_SHIFT +#endif + +#if defined(CONFIG_VMAP_STACK) && MIN_THREAD_SHIFT < PAGE_SHIFT #define THREAD_SHIFT PAGE_SHIFT #else -#define THREAD_SHIFT CONFIG_THREAD_SHIFT +#define THREAD_SHIFT MIN_THREAD_SHIFT #endif #define THREAD_SIZE (1 << THREAD_SHIFT) -- cgit From b6c71c66b0ad8f2b59d9bc08c7a5079b110bec01 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 31 May 2022 19:49:01 -0400 Subject: NFSD: Fix potential use-after-free in nfsd_file_put() nfsd_file_put_noref() can free @nf, so don't dereference @nf immediately upon return from nfsd_file_put_noref(). Suggested-by: Trond Myklebust Fixes: 999397926ab3 ("nfsd: Clean up nfsd_file_put()") Signed-off-by: Chuck Lever --- fs/nfsd/filecache.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index d32fcd8ad457..148b25a43caf 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -308,11 +308,12 @@ nfsd_file_put(struct nfsd_file *nf) if (test_bit(NFSD_FILE_HASHED, &nf->nf_flags) == 0) { nfsd_file_flush(nf); nfsd_file_put_noref(nf); - } else { + } else if (nf->nf_file) { nfsd_file_put_noref(nf); - if (nf->nf_file) - nfsd_file_schedule_laundrette(); - } + nfsd_file_schedule_laundrette(); + } else + nfsd_file_put_noref(nf); + if (atomic_long_read(&nfsd_filecache_count) >= NFSD_FILE_LRU_LIMIT) nfsd_file_gc(); } -- cgit From f012e95b377c73c0283f009823c633104dedb337 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 1 Jun 2022 12:46:52 -0400 Subject: SUNRPC: Trap RDMA segment overflows Prevent svc_rdma_build_writes() from walking off the end of a Write chunk's segment array. Caught with KASAN. The test that this fix replaces is invalid, and might have been left over from an earlier prototype of the PCL work. Fixes: 7a1cbfa18059 ("svcrdma: Use parsed chunk lists to construct RDMA Writes") Signed-off-by: Chuck Lever --- net/sunrpc/xprtrdma/svc_rdma_rw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/xprtrdma/svc_rdma_rw.c b/net/sunrpc/xprtrdma/svc_rdma_rw.c index 5f0155fdefc7..11cf7c646644 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_rw.c +++ b/net/sunrpc/xprtrdma/svc_rdma_rw.c @@ -478,10 +478,10 @@ svc_rdma_build_writes(struct svc_rdma_write_info *info, unsigned int write_len; u64 offset; - seg = &info->wi_chunk->ch_segments[info->wi_seg_no]; - if (!seg) + if (info->wi_seg_no >= info->wi_chunk->ch_segcount) goto out_overflow; + seg = &info->wi_chunk->ch_segments[info->wi_seg_no]; write_len = min(remaining, seg->rs_length - info->wi_seg_off); if (!write_len) goto out_overflow; -- cgit From 587b9bfe0668bc997e51af9526a0c7c084d4660f Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Wed, 1 Jun 2022 01:11:02 +0300 Subject: kernel/reboot: Use static handler for register_platform_power_off() The register_platform_power_off() fails on m68k platform due to the memory allocation error that happens at a very early boot time when memory allocator isn't available yet. Fix it by using a static sys-off handler for the platform-level power-off handlers. Fixes: f0f7e5265b3b ("m68k: Switch to new sys-off handler API") Reported-by: Geert Uytterhoeven Signed-off-by: Dmitry Osipenko Reviewed-by: Geert Uytterhoeven Tested-by: Geert Uytterhoeven Signed-off-by: Rafael J. Wysocki --- kernel/reboot.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/kernel/reboot.c b/kernel/reboot.c index a091145ee710..3b19b123efec 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -315,6 +315,37 @@ static int sys_off_notify(struct notifier_block *nb, return handler->sys_off_cb(&data); } +static struct sys_off_handler platform_sys_off_handler; + +static struct sys_off_handler *alloc_sys_off_handler(int priority) +{ + struct sys_off_handler *handler; + + /* + * Platforms like m68k can't allocate sys_off handler dynamically + * at the early boot time because memory allocator isn't available yet. + */ + if (priority == SYS_OFF_PRIO_PLATFORM) { + handler = &platform_sys_off_handler; + if (handler->cb_data) + return ERR_PTR(-EBUSY); + } else { + handler = kzalloc(sizeof(*handler), GFP_KERNEL); + if (!handler) + return ERR_PTR(-ENOMEM); + } + + return handler; +} + +static void free_sys_off_handler(struct sys_off_handler *handler) +{ + if (handler == &platform_sys_off_handler) + memset(handler, 0, sizeof(*handler)); + else + kfree(handler); +} + /** * register_sys_off_handler - Register sys-off handler * @mode: Sys-off mode @@ -345,9 +376,9 @@ register_sys_off_handler(enum sys_off_mode mode, struct sys_off_handler *handler; int err; - handler = kzalloc(sizeof(*handler), GFP_KERNEL); - if (!handler) - return ERR_PTR(-ENOMEM); + handler = alloc_sys_off_handler(priority); + if (IS_ERR(handler)) + return handler; switch (mode) { case SYS_OFF_MODE_POWER_OFF_PREPARE: @@ -364,7 +395,7 @@ register_sys_off_handler(enum sys_off_mode mode, break; default: - kfree(handler); + free_sys_off_handler(handler); return ERR_PTR(-EINVAL); } @@ -391,7 +422,7 @@ register_sys_off_handler(enum sys_off_mode mode, } if (err) { - kfree(handler); + free_sys_off_handler(handler); return ERR_PTR(err); } @@ -422,7 +453,7 @@ void unregister_sys_off_handler(struct sys_off_handler *handler) /* sanity check, shall never happen */ WARN_ON(err); - kfree(handler); + free_sys_off_handler(handler); } EXPORT_SYMBOL_GPL(unregister_sys_off_handler); -- cgit From 2c9e4559773c261900c674a86b8e455911675d71 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 1 Jun 2022 17:49:36 +0200 Subject: netfilter: nf_tables: always initialize flowtable hook list in transaction The hook list is used if nft_trans_flowtable_update(trans) == true. However, initialize this list for other cases for safety reasons. Fixes: 78d9f48f7f44 ("netfilter: nf_tables: add devices to existing flowtable") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 30588349f96c..2faa77cd2fe2 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -544,6 +544,7 @@ static int nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type, if (msg_type == NFT_MSG_NEWFLOWTABLE) nft_activate_next(ctx->net, flowtable); + INIT_LIST_HEAD(&nft_trans_flowtable_hooks(trans)); nft_trans_flowtable(trans) = flowtable; nft_trans_commit_list_add_tail(ctx->net, trans); -- cgit From 7c4f4f197e0c5c93a70329627f17fcc5883f3593 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 31 May 2022 18:56:41 -0500 Subject: drm/amdkfd: Add GC 10.3.6 and 10.3.7 KFD definitions Loading amdgpu on GC 10.3.7 shows an ERR level message: `kfd kfd: amdgpu: GC IP 0a0307 not supported in kfd` Add these targets to match yellow carp structures. Reported-by: David Chang Reviewed-by: Felix Kuehling Tested-by: Jesse(Jie) Zhang Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 5.18.x --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 2 ++ drivers/gpu/drm/amd/amdkfd/kfd_device.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index 5e9adbc71bbd..cbfb32b3d235 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -1516,6 +1516,8 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev, num_of_cache_types = ARRAY_SIZE(beige_goby_cache_info); break; case IP_VERSION(10, 3, 3): + case IP_VERSION(10, 3, 6): /* TODO: Double check these on production silicon */ + case IP_VERSION(10, 3, 7): /* TODO: Double check these on production silicon */ pcache_info = yellow_carp_cache_info; num_of_cache_types = ARRAY_SIZE(yellow_carp_cache_info); break; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 8667e3df2d0b..f8635e768513 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -73,6 +73,8 @@ static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd) case IP_VERSION(4, 1, 2):/* RENOIR */ case IP_VERSION(5, 2, 1):/* VANGOGH */ case IP_VERSION(5, 2, 3):/* YELLOW_CARP */ + case IP_VERSION(5, 2, 6):/* GC 10.3.6 */ + case IP_VERSION(5, 2, 7):/* GC 10.3.7 */ case IP_VERSION(6, 0, 1): kfd->device_info.num_sdma_queues_per_engine = 2; break; @@ -127,6 +129,8 @@ static void kfd_device_info_set_event_interrupt_class(struct kfd_dev *kfd) case IP_VERSION(9, 4, 2): /* ALDEBARAN */ case IP_VERSION(10, 3, 1): /* VANGOGH */ case IP_VERSION(10, 3, 3): /* YELLOW_CARP */ + case IP_VERSION(10, 3, 6): /* GC 10.3.6 */ + case IP_VERSION(10, 3, 7): /* GC 10.3.7 */ case IP_VERSION(10, 1, 3): /* CYAN_SKILLFISH */ case IP_VERSION(10, 1, 4): case IP_VERSION(10, 1, 10): /* NAVI10 */ @@ -368,6 +372,16 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) if (!vf) f2g = &gfx_v10_3_kfd2kgd; break; + case IP_VERSION(10, 3, 6): + gfx_target_version = 100306; + if (!vf) + f2g = &gfx_v10_3_kfd2kgd; + break; + case IP_VERSION(10, 3, 7): + gfx_target_version = 100307; + if (!vf) + f2g = &gfx_v10_3_kfd2kgd; + break; case IP_VERSION(11, 0, 0): gfx_target_version = 110000; f2g = &gfx_v11_kfd2kgd; -- cgit From 371017309a9f1725bfd3283afe61efa4ac34d30c Mon Sep 17 00:00:00 2001 From: Sunil Khatri Date: Mon, 30 May 2022 23:24:09 +0530 Subject: drm/amdgpu: enable tmz by default for GC 10.3.7 Add IP GC 10.3.7 in the list of target to have tmz enabled by default. Signed-off-by: Sunil Khatri Reviewed-by: Alexander Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 5.18.x --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 798c56214a23..aebc384531ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -518,6 +518,8 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) case IP_VERSION(9, 1, 0): /* RENOIR looks like RAVEN */ case IP_VERSION(9, 3, 0): + /* GC 10.3.7 */ + case IP_VERSION(10, 3, 7): if (amdgpu_tmz == 0) { adev->gmc.tmz_enabled = false; dev_info(adev->dev, @@ -540,8 +542,6 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) case IP_VERSION(10, 3, 1): /* YELLOW_CARP*/ case IP_VERSION(10, 3, 3): - /* GC 10.3.7 */ - case IP_VERSION(10, 3, 7): /* Don't enable it by default yet. */ if (amdgpu_tmz < 1) { -- cgit From 4d1e5f12b7a0d2ade73003d2522a23b4559c7e02 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Wed, 1 Jun 2022 19:02:45 -0400 Subject: drm/amdgpu: Update PDEs flush TLB if PTB/PDB moved MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flush TLBs when existing PDEs are updated because a PTB or PDB moved, but avoids unnecessary TLB flushes when new PDBs or PTBs are added to the page table, which commonly happens when memory is mapped for the first time. Suggested-by: Christian König Signed-off-by: Philip Yang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 2ceeaa4c793a..109d8dd71c11 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -679,6 +679,7 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev, { struct amdgpu_vm_update_params params; struct amdgpu_vm_bo_base *entry; + bool flush_tlb_needed = false; int r, idx; if (list_empty(&vm->relocated)) @@ -697,6 +698,9 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev, goto error; list_for_each_entry(entry, &vm->relocated, vm_status) { + /* vm_flush_needed after updating moved PDEs */ + flush_tlb_needed |= entry->moved; + r = amdgpu_vm_pde_update(¶ms, entry); if (r) goto error; @@ -706,8 +710,8 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev, if (r) goto error; - /* vm_flush_needed after updating PDEs */ - atomic64_inc(&vm->tlb_seq); + if (flush_tlb_needed) + atomic64_inc(&vm->tlb_seq); while (!list_empty(&vm->relocated)) { entry = list_first_entry(&vm->relocated, -- cgit From 4fac4fcf4500bce515b0f32195e7bb86aa0246c6 Mon Sep 17 00:00:00 2001 From: Lang Yu Date: Tue, 31 May 2022 09:19:43 +0800 Subject: drm/amdkfd: add pinned BOs to kfd_bo_list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kfd_bo_list is used to restore process BOs after evictions. As page tables could be destroyed during evictions, we should also update pinned BOs' page tables during restoring to make sure they are valid. So for pinned BOs, 1, Validate them and update their page tables. 2, Don't add eviction fence for them. v2: - Don't handle pinned ones specially in BO validation.(Felix) Signed-off-by: Lang Yu Acked-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 67abf8dcd30a..6b6d46e29e6e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1918,9 +1918,6 @@ int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct amdgpu_device *adev, return -EINVAL; } - /* delete kgd_mem from kfd_bo_list to avoid re-validating - * this BO in BO's restoring after eviction. - */ mutex_lock(&mem->process_info->lock); ret = amdgpu_bo_reserve(bo, true); @@ -1943,7 +1940,6 @@ int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct amdgpu_device *adev, amdgpu_amdkfd_remove_eviction_fence( bo, mem->process_info->eviction_fence); - list_del_init(&mem->validate_list.head); if (size) *size = amdgpu_bo_size(bo); @@ -2512,12 +2508,15 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) process_info->eviction_fence = new_fence; *ef = dma_fence_get(&new_fence->base); - /* Attach new eviction fence to all BOs */ + /* Attach new eviction fence to all BOs except pinned ones */ list_for_each_entry(mem, &process_info->kfd_bo_list, - validate_list.head) + validate_list.head) { + if (mem->bo->tbo.pin_count) + continue; + amdgpu_bo_fence(mem->bo, &process_info->eviction_fence->base, true); - + } /* Attach eviction fence to PD / PT BOs */ list_for_each_entry(peer_vm, &process_info->vm_list_head, vm_list_node) { -- cgit From 88467db6e2f46a2e79b1b67ce6873c284e4cf417 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Fri, 3 Jun 2022 09:19:34 -0400 Subject: drm/amdkfd: Fix partial migration bugs Migration range from system memory to VRAM, if system page can not be locked or unmapped, we do partial migration and leave some pages in system memory. Several bugs found to copy pages and update GPU mapping for this situation: 1. copy to vram should use migrate->npage which is total pages of range as npages, not migrate->cpages which is number of pages can be migrated. 2. After partial copy, set VRAM res cursor as j + 1, j is number of system pages copied plus 1 page to skip copy. 3. copy to ram, should collect all continuous VRAM pages and copy together. 4. Call amdgpu_vm_update_range, should pass in offset as bytes, not as number of pages. Signed-off-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 6 +++--- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index 997650d597ec..e44376c2ecdc 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -296,7 +296,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, struct migrate_vma *migrate, struct dma_fence **mfence, dma_addr_t *scratch) { - uint64_t npages = migrate->cpages; + uint64_t npages = migrate->npages; struct device *dev = adev->dev; struct amdgpu_res_cursor cursor; dma_addr_t *src; @@ -344,7 +344,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, mfence); if (r) goto out_free_vram_pages; - amdgpu_res_next(&cursor, j << PAGE_SHIFT); + amdgpu_res_next(&cursor, (j + 1) << PAGE_SHIFT); j = 0; } else { amdgpu_res_next(&cursor, PAGE_SIZE); @@ -590,7 +590,7 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange, continue; } src[i] = svm_migrate_addr(adev, spage); - if (i > 0 && src[i] != src[i - 1] + PAGE_SIZE) { + if (j > 0 && src[i] != src[i - 1] + PAGE_SIZE) { r = svm_migrate_copy_memory_gart(adev, dst + i - j, src + i - j, j, FROM_VRAM_TO_RAM, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 3bd0f1a670bb..7b332246eda3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -1295,7 +1295,7 @@ svm_range_map_to_gpu(struct kfd_process_device *pdd, struct svm_range *prange, r = amdgpu_vm_update_range(adev, vm, false, false, flush_tlb, NULL, last_start, prange->start + i, pte_flags, - last_start - prange->start, + (last_start - prange->start) << PAGE_SHIFT, bo_adev ? bo_adev->vm_manager.vram_base_offset : 0, NULL, dma_addr, &vm->last_update); -- cgit From 4513edf74cc82c15bc1cefc2ab62ff25fe67028e Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 30 May 2022 11:37:07 +0800 Subject: drm/amd/pm: suppress compile warnings about possible unaligned accesses Suppress the following compile warnings: >> drivers/gpu/drm/amd/amdgpu/../pm/swsmu/inc/smu_v11_0_pptable.h:163:17: warning: field smc_pptable within 'struct smu_11_0_powerplay_table' is less aligned than 'PPTable_t' and is usually due to 'struct smu_11_0_powerplay_table' being packed, which can lead to unaligned accesses [-Wunaligned-access] PPTable_t smc_pptable; //PPTable_t in smu11_driver_if.h ^ 1 warning generated. -- >> drivers/gpu/drm/amd/amdgpu/../pm/swsmu/inc/smu_v11_0_7_pptable.h:193:17: warning: field smc_pptable within 'struct smu_11_0_7_powerplay_table' is less aligned than 'PPTable_t' and is usually due to 'struct smu_11_0_7_powerplay_table' being packed, which can lead to unaligned accesses [-Wunaligned-access] PPTable_t smc_pptable; //PPTable_t in smu11_driver_if.h ^ 1 warning generated. -- >> drivers/gpu/drm/amd/amdgpu/../pm/swsmu/inc/smu_v13_0_pptable.h:161:12: warning: field smc_pptable within 'struct smu_13_0_powerplay_table' is less aligned than 'PPTable_t' and is usually due to 'struct smu_13_0_powerplay_table' being packed, which can lead to unaligned accesses [-Wunaligned-access] Signed-off-by: Evan Quan Reported-by: kernel test robot Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_7_pptable.h | 9 ++++++--- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_pptable.h | 9 ++++++--- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h | 5 ++++- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_pptable.h | 10 +++++++--- 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_7_pptable.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_7_pptable.h index 247c6e9632ba..1cb399dbc7cc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_7_pptable.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_7_pptable.h @@ -22,6 +22,7 @@ #ifndef SMU_11_0_7_PPTABLE_H #define SMU_11_0_7_PPTABLE_H +#pragma pack(push, 1) #define SMU_11_0_7_TABLE_FORMAT_REVISION 15 @@ -139,7 +140,7 @@ struct smu_11_0_7_overdrive_table uint32_t max[SMU_11_0_7_MAX_ODSETTING]; //default maximum settings uint32_t min[SMU_11_0_7_MAX_ODSETTING]; //default minimum settings int16_t pm_setting[SMU_11_0_7_MAX_PMSETTING]; //Optimized power mode feature settings -} __attribute__((packed)); +}; enum SMU_11_0_7_PPCLOCK_ID { SMU_11_0_7_PPCLOCK_GFXCLK = 0, @@ -166,7 +167,7 @@ struct smu_11_0_7_power_saving_clock_table uint32_t count; //power_saving_clock_count = SMU_11_0_7_PPCLOCK_COUNT uint32_t max[SMU_11_0_7_MAX_PPCLOCK]; //PowerSavingClock Mode Clock Maximum array In MHz uint32_t min[SMU_11_0_7_MAX_PPCLOCK]; //PowerSavingClock Mode Clock Minimum array In MHz -} __attribute__((packed)); +}; struct smu_11_0_7_powerplay_table { @@ -191,6 +192,8 @@ struct smu_11_0_7_powerplay_table struct smu_11_0_7_overdrive_table overdrive_table; PPTable_t smc_pptable; //PPTable_t in smu11_driver_if.h -} __attribute__((packed)); +}; + +#pragma pack(pop) #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_pptable.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_pptable.h index 7a63cf8e85ed..0116e3d04fad 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_pptable.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_pptable.h @@ -22,6 +22,7 @@ #ifndef SMU_11_0_PPTABLE_H #define SMU_11_0_PPTABLE_H +#pragma pack(push, 1) #define SMU_11_0_TABLE_FORMAT_REVISION 12 @@ -109,7 +110,7 @@ struct smu_11_0_overdrive_table uint8_t cap[SMU_11_0_MAX_ODFEATURE]; //OD feature support flags uint32_t max[SMU_11_0_MAX_ODSETTING]; //default maximum settings uint32_t min[SMU_11_0_MAX_ODSETTING]; //default minimum settings -} __attribute__((packed)); +}; enum SMU_11_0_PPCLOCK_ID { SMU_11_0_PPCLOCK_GFXCLK = 0, @@ -133,7 +134,7 @@ struct smu_11_0_power_saving_clock_table uint32_t count; //power_saving_clock_count = SMU_11_0_PPCLOCK_COUNT uint32_t max[SMU_11_0_MAX_PPCLOCK]; //PowerSavingClock Mode Clock Maximum array In MHz uint32_t min[SMU_11_0_MAX_PPCLOCK]; //PowerSavingClock Mode Clock Minimum array In MHz -} __attribute__((packed)); +}; struct smu_11_0_powerplay_table { @@ -162,6 +163,8 @@ struct smu_11_0_powerplay_table #ifndef SMU_11_0_PARTIAL_PPTABLE PPTable_t smc_pptable; //PPTable_t in smu11_driver_if.h #endif -} __attribute__((packed)); +}; + +#pragma pack(pop) #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h index 3f29f4327378..478862ded0bd 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h @@ -22,6 +22,8 @@ #ifndef SMU_13_0_7_PPTABLE_H #define SMU_13_0_7_PPTABLE_H +#pragma pack(push, 1) + #define SMU_13_0_7_TABLE_FORMAT_REVISION 15 //// POWERPLAYTABLE::ulPlatformCaps @@ -194,7 +196,8 @@ struct smu_13_0_7_powerplay_table struct smu_13_0_7_overdrive_table overdrive_table; uint8_t padding1; PPTable_t smc_pptable; //PPTable_t in driver_if.h -} __attribute__((packed)); +}; +#pragma pack(pop) #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_pptable.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_pptable.h index 1f311396b706..043307485528 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_pptable.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_pptable.h @@ -22,6 +22,8 @@ #ifndef SMU_13_0_PPTABLE_H #define SMU_13_0_PPTABLE_H +#pragma pack(push, 1) + #define SMU_13_0_TABLE_FORMAT_REVISION 1 //// POWERPLAYTABLE::ulPlatformCaps @@ -109,7 +111,7 @@ struct smu_13_0_overdrive_table { uint8_t cap[SMU_13_0_MAX_ODFEATURE]; //OD feature support flags uint32_t max[SMU_13_0_MAX_ODSETTING]; //default maximum settings uint32_t min[SMU_13_0_MAX_ODSETTING]; //default minimum settings -} __attribute__((packed)); +}; enum SMU_13_0_PPCLOCK_ID { SMU_13_0_PPCLOCK_GFXCLK = 0, @@ -132,7 +134,7 @@ struct smu_13_0_power_saving_clock_table { uint32_t count; //power_saving_clock_count = SMU_11_0_PPCLOCK_COUNT uint32_t max[SMU_13_0_MAX_PPCLOCK]; //PowerSavingClock Mode Clock Maximum array In MHz uint32_t min[SMU_13_0_MAX_PPCLOCK]; //PowerSavingClock Mode Clock Minimum array In MHz -} __attribute__((packed)); +}; struct smu_13_0_powerplay_table { struct atom_common_table_header header; @@ -160,6 +162,8 @@ struct smu_13_0_powerplay_table { #ifndef SMU_13_0_PARTIAL_PPTABLE PPTable_t smc_pptable; //PPTable_t in driver_if.h #endif -} __attribute__((packed)); +}; + +#pragma pack(pop) #endif -- cgit From 12d6c18cfa708e954a7de27dd76cf45054c8855a Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 30 May 2022 14:58:08 +0800 Subject: drm/amdgpu: suppress the compile warning about 64 bit type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suppress the compile warning below: drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c:1292 gfx_v11_0_rlc_backdoor_autoload_copy_ucode() warn: should '1 << id' be a 64 bit type? Reported-by: kernel test robot Reported-by: Dan Carpenter Signed-off-by: Evan Quan Reviewed-by: Guchun Chen Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 628d3536938e..10e180b2d0f5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -1316,7 +1316,7 @@ static void gfx_v11_0_rlc_backdoor_autoload_copy_ucode(struct amdgpu_device *ade memset(ptr + toc_offset + fw_size, 0, toc_fw_size - fw_size); if ((id != SOC21_FIRMWARE_ID_RS64_PFP) && (id != SOC21_FIRMWARE_ID_RS64_ME)) - *(uint64_t *)fw_autoload_mask |= 1 << id; + *(uint64_t *)fw_autoload_mask |= 1ULL << id; } static void gfx_v11_0_rlc_backdoor_autoload_copy_toc_ucode(struct amdgpu_device *adev, -- cgit From 7ad4bd887d27c6b6ffbef216f19c19f8fe2b8f52 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 4 Jun 2022 17:50:50 +0900 Subject: powerpc/book3e: get rid of #include You cannot include here because it is generated in init/Makefile but there is no guarantee that it happens before arch/powerpc/mm/nohash/kaslr_booke.c is compiled for parallel builds. The places where you can reliably include are: - init/ (because init/Makefile can specify the dependency) - arch/*/boot/ (because it is compiled after vmlinux) Commit f231e4333312 ("hexagon: get rid of #include ") fixed the last breakage at that time, but powerpc re-added this. was unneeded because 'build_str' is almost the same as 'linux_banner' defined in init/version.c Let's copy the solution from MIPS. (get_random_boot() in arch/mips/kernel/relocate.c) Fixes: 6a38ea1d7b94 ("powerpc/fsl_booke/32: randomize the kernel image offset") Signed-off-by: Masahiro Yamada Acked-by: Scott Wood Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20220604085050.4078927-1-masahiroy@kernel.org --- arch/powerpc/mm/nohash/kaslr_booke.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/mm/nohash/kaslr_booke.c b/arch/powerpc/mm/nohash/kaslr_booke.c index 1f3f9fedf1bc..0d04f9d5da8d 100644 --- a/arch/powerpc/mm/nohash/kaslr_booke.c +++ b/arch/powerpc/mm/nohash/kaslr_booke.c @@ -19,7 +19,6 @@ #include #include #include -#include #include struct regions { @@ -37,10 +36,6 @@ struct regions { int reserved_mem_size_cells; }; -/* Simplified build-specific string for starting entropy. */ -static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@" - LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION; - struct regions __initdata regions; static __init void kaslr_get_cmdline(void *fdt) @@ -71,7 +66,8 @@ static unsigned long __init get_boot_seed(void *fdt) { unsigned long hash = 0; - hash = rotate_xor(hash, build_str, sizeof(build_str)); + /* build-specific string for starting entropy. */ + hash = rotate_xor(hash, linux_banner, strlen(linux_banner)); hash = rotate_xor(hash, fdt, fdt_totalsize(fdt)); return hash; -- cgit From a734510fa8b4e61e6a37176f0da01f4c55fa52de Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 25 May 2022 13:49:42 +0200 Subject: ata: libata: drop 'sas_last_tag' Unused now. Fixes: 4f1a22ee7b57 ("libata: Improve ATA queued command allocation") Cc: John Garry Signed-off-by: Hannes Reinecke Reviewed-by: John Garry Signed-off-by: Damien Le Moal --- include/linux/libata.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/libata.h b/include/linux/libata.h index 732de9014626..0f2a59c9c735 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -822,7 +822,6 @@ struct ata_port { struct ata_queued_cmd qcmd[ATA_MAX_QUEUE + 1]; u64 qc_active; int nr_active_links; /* #links with active qcs */ - unsigned int sas_last_tag; /* track next tag hw expects */ struct ata_link link; /* host default link */ struct ata_link *slave_link; /* see ata_slave_link_init() */ -- cgit From bf476fe22aa1851bab4728e0c49025a6a0bea307 Mon Sep 17 00:00:00 2001 From: Sergey Shtylyov Date: Sat, 21 May 2022 23:34:10 +0300 Subject: ata: libata-core: fix NULL pointer deref in ata_host_alloc_pinfo() In an unlikely (and probably wrong?) case that the 'ppi' parameter of ata_host_alloc_pinfo() points to an array starting with a NULL pointer, there's going to be a kernel oops as the 'pi' local variable won't get reassigned from the initial value of NULL. Initialize 'pi' instead to '&ata_dummy_port_info' to fix the possible kernel oops for good... Found by Linux Verification Center (linuxtesting.org) with the SVACE static analysis tool. Signed-off-by: Sergey Shtylyov Signed-off-by: Damien Le Moal --- drivers/ata/libata-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 40e816419f48..c214ff928e45 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5462,7 +5462,7 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev, const struct ata_port_info * const * ppi, int n_ports) { - const struct ata_port_info *pi; + const struct ata_port_info *pi = &ata_dummy_port_info; struct ata_host *host; int i, j; @@ -5470,7 +5470,7 @@ struct ata_host *ata_host_alloc_pinfo(struct device *dev, if (!host) return NULL; - for (i = 0, j = 0, pi = NULL; i < host->n_ports; i++) { + for (i = 0, j = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; if (ppi[j]) -- cgit From 10d6bdf532902be1d8aa5900b3c03c5671612aa2 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Wed, 1 Jun 2022 12:59:26 +0400 Subject: ata: pata_octeon_cf: Fix refcount leak in octeon_cf_probe of_find_device_by_node() takes reference, we should use put_device() to release it when not need anymore. Add missing put_device() to avoid refcount leak. Fixes: 43f01da0f279 ("MIPS/OCTEON/ata: Convert pata_octeon_cf.c to use device tree.") Signed-off-by: Miaoqian Lin Reviewed-by: Sergey Shtylyov Signed-off-by: Damien Le Moal --- drivers/ata/pata_octeon_cf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index 6b5ed3046b44..35608a0cf552 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -856,12 +856,14 @@ static int octeon_cf_probe(struct platform_device *pdev) int i; res_dma = platform_get_resource(dma_dev, IORESOURCE_MEM, 0); if (!res_dma) { + put_device(&dma_dev->dev); of_node_put(dma_node); return -EINVAL; } cf_port->dma_base = (u64)devm_ioremap(&pdev->dev, res_dma->start, resource_size(res_dma)); if (!cf_port->dma_base) { + put_device(&dma_dev->dev); of_node_put(dma_node); return -EINVAL; } @@ -871,6 +873,7 @@ static int octeon_cf_probe(struct platform_device *pdev) irq = i; irq_handler = octeon_cf_interrupt; } + put_device(&dma_dev->dev); } of_node_put(dma_node); } -- cgit From c36ee7dab7749f7be21f7a72392744490b2a9a2b Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Sun, 5 Jun 2022 19:54:26 -0300 Subject: cifs: fix reconnect on smb3 mount types cifs.ko defines two file system types: cifs & smb3, and __cifs_get_super() was not including smb3 file system type when looking up superblocks, therefore failing to reconnect tcons in cifs_tree_connect(). Fix this by calling iterate_supers_type() on both file system types. Link: https://lore.kernel.org/r/CAFrh3J9soC36+BVuwHB=g9z_KB5Og2+p2_W+BBoBOZveErz14w@mail.gmail.com Cc: stable@vger.kernel.org Tested-by: Satadru Pramanik Reported-by: Satadru Pramanik Signed-off-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 2 +- fs/cifs/cifsfs.h | 2 +- fs/cifs/misc.c | 27 ++++++++++++++++----------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 12c872800326..325423180fd2 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -1086,7 +1086,7 @@ struct file_system_type cifs_fs_type = { }; MODULE_ALIAS_FS("cifs"); -static struct file_system_type smb3_fs_type = { +struct file_system_type smb3_fs_type = { .owner = THIS_MODULE, .name = "smb3", .init_fs_context = smb3_init_fs_context, diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index dd7e070ca243..b17be47a8e59 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -38,7 +38,7 @@ static inline unsigned long cifs_get_time(struct dentry *dentry) return (unsigned long) dentry->d_fsdata; } -extern struct file_system_type cifs_fs_type; +extern struct file_system_type cifs_fs_type, smb3_fs_type; extern const struct address_space_operations cifs_addr_ops; extern const struct address_space_operations cifs_addr_ops_smallbuf; diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 35962a1a23b9..8e67a2d406ab 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -1211,18 +1211,23 @@ static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void .data = data, .sb = NULL, }; + struct file_system_type **fs_type = (struct file_system_type *[]) { + &cifs_fs_type, &smb3_fs_type, NULL, + }; - iterate_supers_type(&cifs_fs_type, f, &sd); - - if (!sd.sb) - return ERR_PTR(-EINVAL); - /* - * Grab an active reference in order to prevent automounts (DFS links) - * of expiring and then freeing up our cifs superblock pointer while - * we're doing failover. - */ - cifs_sb_active(sd.sb); - return sd.sb; + for (; *fs_type; fs_type++) { + iterate_supers_type(*fs_type, f, &sd); + if (sd.sb) { + /* + * Grab an active reference in order to prevent automounts (DFS links) + * of expiring and then freeing up our cifs superblock pointer while + * we're doing failover. + */ + cifs_sb_active(sd.sb); + return sd.sb; + } + } + return ERR_PTR(-EINVAL); } static void __cifs_put_super(struct super_block *sb) -- cgit From 2130a790ca49763f724ec45cf93b9dd765e2023e Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Thu, 2 Jun 2022 15:05:26 +0200 Subject: kernel: add platform_has() infrastructure Add a simple infrastructure for setting, resetting and querying platform feature flags. Flags can be either global or architecture specific. Signed-off-by: Juergen Gross Reviewed-by: Oleksandr Tyshchenko Tested-by: Oleksandr Tyshchenko # Arm64 only Reviewed-by: Christoph Hellwig Acked-by: Borislav Petkov Signed-off-by: Juergen Gross --- MAINTAINERS | 8 ++++++++ include/asm-generic/Kbuild | 1 + include/asm-generic/platform-feature.h | 8 ++++++++ include/linux/platform-feature.h | 15 +++++++++++++++ kernel/Makefile | 2 +- kernel/platform-feature.c | 27 +++++++++++++++++++++++++++ 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 include/asm-generic/platform-feature.h create mode 100644 include/linux/platform-feature.h create mode 100644 kernel/platform-feature.c diff --git a/MAINTAINERS b/MAINTAINERS index a6d3bd9d2a8d..06678abc22ca 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15824,6 +15824,14 @@ S: Maintained F: Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml F: drivers/iio/chemical/pms7003.c +PLATFORM FEATURE INFRASTRUCTURE +M: Juergen Gross +S: Maintained +F: arch/*/include/asm/platform-feature.h +F: include/asm-generic/platform-feature.h +F: include/linux/platform-feature.h +F: kernel/platform-feature.c + PLDMFW LIBRARY M: Jacob Keller S: Maintained diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild index 302506bbc2a4..8e47d483b524 100644 --- a/include/asm-generic/Kbuild +++ b/include/asm-generic/Kbuild @@ -44,6 +44,7 @@ mandatory-y += msi.h mandatory-y += pci.h mandatory-y += percpu.h mandatory-y += pgalloc.h +mandatory-y += platform-feature.h mandatory-y += preempt.h mandatory-y += rwonce.h mandatory-y += sections.h diff --git a/include/asm-generic/platform-feature.h b/include/asm-generic/platform-feature.h new file mode 100644 index 000000000000..4b0af3d51588 --- /dev/null +++ b/include/asm-generic/platform-feature.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_GENERIC_PLATFORM_FEATURE_H +#define _ASM_GENERIC_PLATFORM_FEATURE_H + +/* Number of arch specific feature flags. */ +#define PLATFORM_ARCH_FEAT_N 0 + +#endif /* _ASM_GENERIC_PLATFORM_FEATURE_H */ diff --git a/include/linux/platform-feature.h b/include/linux/platform-feature.h new file mode 100644 index 000000000000..6ed859928b97 --- /dev/null +++ b/include/linux/platform-feature.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _PLATFORM_FEATURE_H +#define _PLATFORM_FEATURE_H + +#include +#include + +/* The platform features are starting with the architecture specific ones. */ +#define PLATFORM_FEAT_N (0 + PLATFORM_ARCH_FEAT_N) + +void platform_set(unsigned int feature); +void platform_clear(unsigned int feature); +bool platform_has(unsigned int feature); + +#endif /* _PLATFORM_FEATURE_H */ diff --git a/kernel/Makefile b/kernel/Makefile index 318789c728d3..a7e1f49ab2b3 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -7,7 +7,7 @@ obj-y = fork.o exec_domain.o panic.o \ cpu.o exit.o softirq.o resource.o \ sysctl.o capability.o ptrace.o user.o \ signal.o sys.o umh.o workqueue.o pid.o task_work.o \ - extable.o params.o \ + extable.o params.o platform-feature.o \ kthread.o sys_ni.o nsproxy.o \ notifier.o ksysfs.o cred.o reboot.o \ async.o range.o smpboot.o ucount.o regset.o diff --git a/kernel/platform-feature.c b/kernel/platform-feature.c new file mode 100644 index 000000000000..cb6a6c3e4fed --- /dev/null +++ b/kernel/platform-feature.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include + +#define PLATFORM_FEAT_ARRAY_SZ BITS_TO_LONGS(PLATFORM_FEAT_N) +static unsigned long __read_mostly platform_features[PLATFORM_FEAT_ARRAY_SZ]; + +void platform_set(unsigned int feature) +{ + set_bit(feature, platform_features); +} +EXPORT_SYMBOL_GPL(platform_set); + +void platform_clear(unsigned int feature) +{ + clear_bit(feature, platform_features); +} +EXPORT_SYMBOL_GPL(platform_clear); + +bool platform_has(unsigned int feature) +{ + return test_bit(feature, platform_features); +} +EXPORT_SYMBOL_GPL(platform_has); -- cgit From 3f9dfbebdc48cebfbda738f6f3d1dbf6d7232f90 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Mon, 6 Jun 2022 08:09:16 +0200 Subject: virtio: replace arch_has_restricted_virtio_memory_access() Instead of using arch_has_restricted_virtio_memory_access() together with CONFIG_ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS, replace those with platform_has() and a new platform feature PLATFORM_VIRTIO_RESTRICTED_MEM_ACCESS. Signed-off-by: Juergen Gross Reviewed-by: Oleksandr Tyshchenko Tested-by: Oleksandr Tyshchenko # Arm64 only Reviewed-by: Christoph Hellwig Acked-by: Borislav Petkov --- arch/s390/Kconfig | 1 - arch/s390/mm/init.c | 13 +++---------- arch/x86/Kconfig | 1 - arch/x86/mm/mem_encrypt.c | 7 ------- arch/x86/mm/mem_encrypt_amd.c | 4 ++++ drivers/virtio/Kconfig | 6 ------ drivers/virtio/virtio.c | 5 ++--- include/linux/platform-feature.h | 6 +++++- include/linux/virtio_config.h | 9 --------- 9 files changed, 14 insertions(+), 38 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index b1a88f6cc349..bf253628c136 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -768,7 +768,6 @@ menu "Virtualization" config PROTECTED_VIRTUALIZATION_GUEST def_bool n prompt "Protected virtualization guest support" - select ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS help Select this option, if you want to be able to run this kernel as a protected virtualization KVM guest. diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 6fb6bf64326f..6a0ac00d5a42 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -168,22 +169,14 @@ bool force_dma_unencrypted(struct device *dev) return is_prot_virt_guest(); } -#ifdef CONFIG_ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS - -int arch_has_restricted_virtio_memory_access(void) -{ - return is_prot_virt_guest(); -} -EXPORT_SYMBOL(arch_has_restricted_virtio_memory_access); - -#endif - /* protected virtualization */ static void pv_init(void) { if (!is_prot_virt_guest()) return; + platform_set(PLATFORM_VIRTIO_RESTRICTED_MEM_ACCESS); + /* make sure bounce buffers are shared */ swiotlb_init(true, SWIOTLB_FORCE | SWIOTLB_VERBOSE); swiotlb_update_mem_attributes(); diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9783ebc4e021..be0b95e51df6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1542,7 +1542,6 @@ config X86_CPA_STATISTICS config X86_MEM_ENCRYPT select ARCH_HAS_FORCE_DMA_UNENCRYPTED select DYNAMIC_PHYSICAL_MASK - select ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS def_bool n config AMD_MEM_ENCRYPT diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c index 11350e2fd736..9f27e14e185f 100644 --- a/arch/x86/mm/mem_encrypt.c +++ b/arch/x86/mm/mem_encrypt.c @@ -12,7 +12,6 @@ #include #include #include -#include /* Override for DMA direct allocation check - ARCH_HAS_FORCE_DMA_UNENCRYPTED */ bool force_dma_unencrypted(struct device *dev) @@ -87,9 +86,3 @@ void __init mem_encrypt_init(void) print_mem_encrypt_feature_info(); } - -int arch_has_restricted_virtio_memory_access(void) -{ - return cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT); -} -EXPORT_SYMBOL_GPL(arch_has_restricted_virtio_memory_access); diff --git a/arch/x86/mm/mem_encrypt_amd.c b/arch/x86/mm/mem_encrypt_amd.c index e8f7953fda83..f6d038e2cd8e 100644 --- a/arch/x86/mm/mem_encrypt_amd.c +++ b/arch/x86/mm/mem_encrypt_amd.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -242,6 +243,9 @@ void __init sev_setup_arch(void) size = total_mem * 6 / 100; size = clamp_val(size, IO_TLB_DEFAULT_SIZE, SZ_1G); swiotlb_adjust_size(size); + + /* Set restricted memory access for virtio. */ + platform_set(PLATFORM_VIRTIO_RESTRICTED_MEM_ACCESS); } static unsigned long pg_level_to_pfn(int level, pte_t *kpte, pgprot_t *ret_prot) diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index b5adf6abd241..a6dc8b5846fe 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -6,12 +6,6 @@ config VIRTIO bus, such as CONFIG_VIRTIO_PCI, CONFIG_VIRTIO_MMIO, CONFIG_RPMSG or CONFIG_S390_GUEST. -config ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS - bool - help - This option is selected if the architecture may need to enforce - VIRTIO_F_ACCESS_PLATFORM - config VIRTIO_PCI_LIB tristate help diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index ef04a96942bf..6bace84ae37e 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -5,6 +5,7 @@ #include #include #include +#include #include /* Unique numbering for virtio devices. */ @@ -170,12 +171,10 @@ EXPORT_SYMBOL_GPL(virtio_add_status); static int virtio_features_ok(struct virtio_device *dev) { unsigned int status; - int ret; might_sleep(); - ret = arch_has_restricted_virtio_memory_access(); - if (ret) { + if (platform_has(PLATFORM_VIRTIO_RESTRICTED_MEM_ACCESS)) { if (!virtio_has_feature(dev, VIRTIO_F_VERSION_1)) { dev_warn(&dev->dev, "device must provide VIRTIO_F_VERSION_1\n"); diff --git a/include/linux/platform-feature.h b/include/linux/platform-feature.h index 6ed859928b97..b2f48be999fa 100644 --- a/include/linux/platform-feature.h +++ b/include/linux/platform-feature.h @@ -6,7 +6,11 @@ #include /* The platform features are starting with the architecture specific ones. */ -#define PLATFORM_FEAT_N (0 + PLATFORM_ARCH_FEAT_N) + +/* Used to enable platform specific DMA handling for virtio devices. */ +#define PLATFORM_VIRTIO_RESTRICTED_MEM_ACCESS (0 + PLATFORM_ARCH_FEAT_N) + +#define PLATFORM_FEAT_N (1 + PLATFORM_ARCH_FEAT_N) void platform_set(unsigned int feature); void platform_clear(unsigned int feature); diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 9a36051ceb76..49c7c32815f1 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -604,13 +604,4 @@ static inline void virtio_cwrite64(struct virtio_device *vdev, _r; \ }) -#ifdef CONFIG_ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS -int arch_has_restricted_virtio_memory_access(void); -#else -static inline int arch_has_restricted_virtio_memory_access(void) -{ - return 0; -} -#endif /* CONFIG_ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS */ - #endif /* _LINUX_VIRTIO_CONFIG_H */ -- cgit From 9bf22421dc8a69cade3c994771637e9693ff0216 Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshchenko Date: Thu, 2 Jun 2022 22:23:46 +0300 Subject: arm/xen: Introduce xen_setup_dma_ops() This patch introduces new helper and places it in new header. The helper's purpose is to assign any Xen specific DMA ops in a single place. For now, we deal with xen-swiotlb DMA ops only. The one of the subsequent commits in current series will add xen-grant DMA ops case. Also re-use the xen_swiotlb_detect() check on Arm32. Signed-off-by: Oleksandr Tyshchenko Reviewed-by: Stefano Stabellini [For arm64] Acked-by: Catalin Marinas Link: https://lore.kernel.org/r/1654197833-25362-2-git-send-email-olekstysh@gmail.com Signed-off-by: Juergen Gross --- arch/arm/include/asm/xen/xen-ops.h | 2 ++ arch/arm/mm/dma-mapping.c | 7 ++----- arch/arm64/include/asm/xen/xen-ops.h | 2 ++ arch/arm64/mm/dma-mapping.c | 7 ++----- include/xen/arm/xen-ops.h | 15 +++++++++++++++ 5 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 arch/arm/include/asm/xen/xen-ops.h create mode 100644 arch/arm64/include/asm/xen/xen-ops.h create mode 100644 include/xen/arm/xen-ops.h diff --git a/arch/arm/include/asm/xen/xen-ops.h b/arch/arm/include/asm/xen/xen-ops.h new file mode 100644 index 000000000000..7ebb7eb0bd93 --- /dev/null +++ b/arch/arm/include/asm/xen/xen-ops.h @@ -0,0 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 82ffac621854..059cce018570 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include "dma.h" #include "mm.h" @@ -2287,10 +2287,7 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, set_dma_ops(dev, dma_ops); -#ifdef CONFIG_XEN - if (xen_initial_domain()) - dev->dma_ops = &xen_swiotlb_dma_ops; -#endif + xen_setup_dma_ops(dev); dev->archdata.dma_ops_setup = true; } diff --git a/arch/arm64/include/asm/xen/xen-ops.h b/arch/arm64/include/asm/xen/xen-ops.h new file mode 100644 index 000000000000..7ebb7eb0bd93 --- /dev/null +++ b/arch/arm64/include/asm/xen/xen-ops.h @@ -0,0 +1,2 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index 6719f9efea09..6099c81b9322 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -9,9 +9,9 @@ #include #include #include -#include #include +#include void arch_sync_dma_for_device(phys_addr_t paddr, size_t size, enum dma_data_direction dir) @@ -52,8 +52,5 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, if (iommu) iommu_setup_dma_ops(dev, dma_base, dma_base + size - 1); -#ifdef CONFIG_XEN - if (xen_swiotlb_detect()) - dev->dma_ops = &xen_swiotlb_dma_ops; -#endif + xen_setup_dma_ops(dev); } diff --git a/include/xen/arm/xen-ops.h b/include/xen/arm/xen-ops.h new file mode 100644 index 000000000000..288deb1c3ac9 --- /dev/null +++ b/include/xen/arm/xen-ops.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_ARM_XEN_OPS_H +#define _ASM_ARM_XEN_OPS_H + +#include + +static inline void xen_setup_dma_ops(struct device *dev) +{ +#ifdef CONFIG_XEN + if (xen_swiotlb_detect()) + dev->dma_ops = &xen_swiotlb_dma_ops; +#endif +} + +#endif /* _ASM_ARM_XEN_OPS_H */ -- cgit From 02a9e681a3f7998074f39ec265080bf934871530 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Thu, 2 Jun 2022 22:23:47 +0300 Subject: xen/grants: support allocating consecutive grants For support of virtio via grant mappings in rare cases larger mappings using consecutive grants are needed. Support those by adding a bitmap of free grants. As consecutive grants will be needed only in very rare cases (e.g. when configuring a virtio device with a multi-page ring), optimize for the normal case of non-consecutive allocations. Signed-off-by: Juergen Gross Reviewed-by: Boris Ostrovsky Link: https://lore.kernel.org/r/1654197833-25362-3-git-send-email-olekstysh@gmail.com Signed-off-by: Juergen Gross --- drivers/xen/grant-table.c | 251 +++++++++++++++++++++++++++++++++++++++------- include/xen/grant_table.h | 4 + 2 files changed, 219 insertions(+), 36 deletions(-) diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 7a18292540bc..738029de3c67 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -33,6 +33,7 @@ #define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -70,9 +71,32 @@ static grant_ref_t **gnttab_list; static unsigned int nr_grant_frames; + +/* + * Handling of free grants: + * + * Free grants are in a simple list anchored in gnttab_free_head. They are + * linked by grant ref, the last element contains GNTTAB_LIST_END. The number + * of free entries is stored in gnttab_free_count. + * Additionally there is a bitmap of free entries anchored in + * gnttab_free_bitmap. This is being used for simplifying allocation of + * multiple consecutive grants, which is needed e.g. for support of virtio. + * gnttab_last_free is used to add free entries of new frames at the end of + * the free list. + * gnttab_free_tail_ptr specifies the variable which references the start + * of consecutive free grants ending with gnttab_last_free. This pointer is + * updated in a rather defensive way, in order to avoid performance hits in + * hot paths. + * All those variables are protected by gnttab_list_lock. + */ static int gnttab_free_count; -static grant_ref_t gnttab_free_head; +static unsigned int gnttab_size; +static grant_ref_t gnttab_free_head = GNTTAB_LIST_END; +static grant_ref_t gnttab_last_free = GNTTAB_LIST_END; +static grant_ref_t *gnttab_free_tail_ptr; +static unsigned long *gnttab_free_bitmap; static DEFINE_SPINLOCK(gnttab_list_lock); + struct grant_frames xen_auto_xlat_grant_frames; static unsigned int xen_gnttab_version; module_param_named(version, xen_gnttab_version, uint, 0); @@ -168,16 +192,116 @@ static int get_free_entries(unsigned count) ref = head = gnttab_free_head; gnttab_free_count -= count; - while (count-- > 1) - head = gnttab_entry(head); + while (count--) { + bitmap_clear(gnttab_free_bitmap, head, 1); + if (gnttab_free_tail_ptr == __gnttab_entry(head)) + gnttab_free_tail_ptr = &gnttab_free_head; + if (count) + head = gnttab_entry(head); + } gnttab_free_head = gnttab_entry(head); gnttab_entry(head) = GNTTAB_LIST_END; + if (!gnttab_free_count) { + gnttab_last_free = GNTTAB_LIST_END; + gnttab_free_tail_ptr = NULL; + } + spin_unlock_irqrestore(&gnttab_list_lock, flags); return ref; } +static int get_seq_entry_count(void) +{ + if (gnttab_last_free == GNTTAB_LIST_END || !gnttab_free_tail_ptr || + *gnttab_free_tail_ptr == GNTTAB_LIST_END) + return 0; + + return gnttab_last_free - *gnttab_free_tail_ptr + 1; +} + +/* Rebuilds the free grant list and tries to find count consecutive entries. */ +static int get_free_seq(unsigned int count) +{ + int ret = -ENOSPC; + unsigned int from, to; + grant_ref_t *last; + + gnttab_free_tail_ptr = &gnttab_free_head; + last = &gnttab_free_head; + + for (from = find_first_bit(gnttab_free_bitmap, gnttab_size); + from < gnttab_size; + from = find_next_bit(gnttab_free_bitmap, gnttab_size, to + 1)) { + to = find_next_zero_bit(gnttab_free_bitmap, gnttab_size, + from + 1); + if (ret < 0 && to - from >= count) { + ret = from; + bitmap_clear(gnttab_free_bitmap, ret, count); + from += count; + gnttab_free_count -= count; + if (from == to) + continue; + } + + /* + * Recreate the free list in order to have it properly sorted. + * This is needed to make sure that the free tail has the maximum + * possible size. + */ + while (from < to) { + *last = from; + last = __gnttab_entry(from); + gnttab_last_free = from; + from++; + } + if (to < gnttab_size) + gnttab_free_tail_ptr = __gnttab_entry(to - 1); + } + + *last = GNTTAB_LIST_END; + if (gnttab_last_free != gnttab_size - 1) + gnttab_free_tail_ptr = NULL; + + return ret; +} + +static int get_free_entries_seq(unsigned int count) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&gnttab_list_lock, flags); + + if (gnttab_free_count < count) { + ret = gnttab_expand(count - gnttab_free_count); + if (ret < 0) + goto out; + } + + if (get_seq_entry_count() < count) { + ret = get_free_seq(count); + if (ret >= 0) + goto out; + ret = gnttab_expand(count - get_seq_entry_count()); + if (ret < 0) + goto out; + } + + ret = *gnttab_free_tail_ptr; + *gnttab_free_tail_ptr = gnttab_entry(ret + count - 1); + gnttab_free_count -= count; + if (!gnttab_free_count) + gnttab_free_tail_ptr = NULL; + bitmap_clear(gnttab_free_bitmap, ret, count); + + out: + spin_unlock_irqrestore(&gnttab_list_lock, flags); + + return ret; +} + static void do_free_callbacks(void) { struct gnttab_free_callback *callback, *next; @@ -204,21 +328,51 @@ static inline void check_free_callbacks(void) do_free_callbacks(); } -static void put_free_entry(grant_ref_t ref) +static void put_free_entry_locked(grant_ref_t ref) { - unsigned long flags; - if (unlikely(ref < GNTTAB_NR_RESERVED_ENTRIES)) return; - spin_lock_irqsave(&gnttab_list_lock, flags); gnttab_entry(ref) = gnttab_free_head; gnttab_free_head = ref; + if (!gnttab_free_count) + gnttab_last_free = ref; + if (gnttab_free_tail_ptr == &gnttab_free_head) + gnttab_free_tail_ptr = __gnttab_entry(ref); gnttab_free_count++; + bitmap_set(gnttab_free_bitmap, ref, 1); +} + +static void put_free_entry(grant_ref_t ref) +{ + unsigned long flags; + + spin_lock_irqsave(&gnttab_list_lock, flags); + put_free_entry_locked(ref); check_free_callbacks(); spin_unlock_irqrestore(&gnttab_list_lock, flags); } +static void gnttab_set_free(unsigned int start, unsigned int n) +{ + unsigned int i; + + for (i = start; i < start + n - 1; i++) + gnttab_entry(i) = i + 1; + + gnttab_entry(i) = GNTTAB_LIST_END; + if (!gnttab_free_count) { + gnttab_free_head = start; + gnttab_free_tail_ptr = &gnttab_free_head; + } else { + gnttab_entry(gnttab_last_free) = start; + } + gnttab_free_count += n; + gnttab_last_free = i; + + bitmap_set(gnttab_free_bitmap, start, n); +} + /* * Following applies to gnttab_update_entry_v1 and gnttab_update_entry_v2. * Introducing a valid entry into the grant table: @@ -450,23 +604,31 @@ void gnttab_free_grant_references(grant_ref_t head) { grant_ref_t ref; unsigned long flags; - int count = 1; - if (head == GNTTAB_LIST_END) - return; + spin_lock_irqsave(&gnttab_list_lock, flags); - ref = head; - while (gnttab_entry(ref) != GNTTAB_LIST_END) { - ref = gnttab_entry(ref); - count++; + while (head != GNTTAB_LIST_END) { + ref = gnttab_entry(head); + put_free_entry_locked(head); + head = ref; } - gnttab_entry(ref) = gnttab_free_head; - gnttab_free_head = head; - gnttab_free_count += count; check_free_callbacks(); spin_unlock_irqrestore(&gnttab_list_lock, flags); } EXPORT_SYMBOL_GPL(gnttab_free_grant_references); +void gnttab_free_grant_reference_seq(grant_ref_t head, unsigned int count) +{ + unsigned long flags; + unsigned int i; + + spin_lock_irqsave(&gnttab_list_lock, flags); + for (i = count; i > 0; i--) + put_free_entry_locked(head + i - 1); + check_free_callbacks(); + spin_unlock_irqrestore(&gnttab_list_lock, flags); +} +EXPORT_SYMBOL_GPL(gnttab_free_grant_reference_seq); + int gnttab_alloc_grant_references(u16 count, grant_ref_t *head) { int h = get_free_entries(count); @@ -480,6 +642,24 @@ int gnttab_alloc_grant_references(u16 count, grant_ref_t *head) } EXPORT_SYMBOL_GPL(gnttab_alloc_grant_references); +int gnttab_alloc_grant_reference_seq(unsigned int count, grant_ref_t *first) +{ + int h; + + if (count == 1) + h = get_free_entries(1); + else + h = get_free_entries_seq(count); + + if (h < 0) + return -ENOSPC; + + *first = h; + + return 0; +} +EXPORT_SYMBOL_GPL(gnttab_alloc_grant_reference_seq); + int gnttab_empty_grant_references(const grant_ref_t *private_head) { return (*private_head == GNTTAB_LIST_END); @@ -572,16 +752,13 @@ static int grow_gnttab_list(unsigned int more_frames) goto grow_nomem; } + gnttab_set_free(gnttab_size, extra_entries); - for (i = grefs_per_frame * nr_grant_frames; - i < grefs_per_frame * new_nr_grant_frames - 1; i++) - gnttab_entry(i) = i + 1; - - gnttab_entry(i) = gnttab_free_head; - gnttab_free_head = grefs_per_frame * nr_grant_frames; - gnttab_free_count += extra_entries; + if (!gnttab_free_tail_ptr) + gnttab_free_tail_ptr = __gnttab_entry(gnttab_size); nr_grant_frames = new_nr_grant_frames; + gnttab_size += extra_entries; check_free_callbacks(); @@ -1424,20 +1601,20 @@ static int gnttab_expand(unsigned int req_entries) int gnttab_init(void) { int i; - unsigned long max_nr_grant_frames; + unsigned long max_nr_grant_frames, max_nr_grefs; unsigned int max_nr_glist_frames, nr_glist_frames; - unsigned int nr_init_grefs; int ret; gnttab_request_version(); max_nr_grant_frames = gnttab_max_grant_frames(); + max_nr_grefs = max_nr_grant_frames * + gnttab_interface->grefs_per_grant_frame; nr_grant_frames = 1; /* Determine the maximum number of frames required for the * grant reference free list on the current hypervisor. */ - max_nr_glist_frames = (max_nr_grant_frames * - gnttab_interface->grefs_per_grant_frame / RPP); + max_nr_glist_frames = max_nr_grefs / RPP; gnttab_list = kmalloc_array(max_nr_glist_frames, sizeof(grant_ref_t *), @@ -1454,6 +1631,12 @@ int gnttab_init(void) } } + gnttab_free_bitmap = bitmap_zalloc(max_nr_grefs, GFP_KERNEL); + if (!gnttab_free_bitmap) { + ret = -ENOMEM; + goto ini_nomem; + } + ret = arch_gnttab_init(max_nr_grant_frames, nr_status_frames(max_nr_grant_frames)); if (ret < 0) @@ -1464,15 +1647,10 @@ int gnttab_init(void) goto ini_nomem; } - nr_init_grefs = nr_grant_frames * - gnttab_interface->grefs_per_grant_frame; - - for (i = GNTTAB_NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) - gnttab_entry(i) = i + 1; + gnttab_size = nr_grant_frames * gnttab_interface->grefs_per_grant_frame; - gnttab_entry(nr_init_grefs - 1) = GNTTAB_LIST_END; - gnttab_free_count = nr_init_grefs - GNTTAB_NR_RESERVED_ENTRIES; - gnttab_free_head = GNTTAB_NR_RESERVED_ENTRIES; + gnttab_set_free(GNTTAB_NR_RESERVED_ENTRIES, + gnttab_size - GNTTAB_NR_RESERVED_ENTRIES); printk("Grant table initialized\n"); return 0; @@ -1481,6 +1659,7 @@ int gnttab_init(void) for (i--; i >= 0; i--) free_page((unsigned long)gnttab_list[i]); kfree(gnttab_list); + bitmap_free(gnttab_free_bitmap); return ret; } EXPORT_SYMBOL_GPL(gnttab_init); diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 527c9907f99c..e279be353e3f 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -127,10 +127,14 @@ int gnttab_try_end_foreign_access(grant_ref_t ref); */ int gnttab_alloc_grant_references(u16 count, grant_ref_t *pprivate_head); +int gnttab_alloc_grant_reference_seq(unsigned int count, grant_ref_t *first); + void gnttab_free_grant_reference(grant_ref_t ref); void gnttab_free_grant_references(grant_ref_t head); +void gnttab_free_grant_reference_seq(grant_ref_t head, unsigned int count); + int gnttab_empty_grant_references(const grant_ref_t *pprivate_head); int gnttab_claim_grant_reference(grant_ref_t *pprivate_head); -- cgit From d6aca3504c7ded5f4f46957e3685b9344d9743dd Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Thu, 2 Jun 2022 22:23:48 +0300 Subject: xen/grant-dma-ops: Add option to restrict memory access under Xen Introduce Xen grant DMA-mapping layer which contains special DMA-mapping routines for providing grant references as DMA addresses to be used by frontends (e.g. virtio) in Xen guests. Add the needed functionality by providing a special set of DMA ops handling the needed grant operations for the I/O pages. The subsequent commit will introduce the use case for xen-grant DMA ops layer to enable using virtio devices in Xen guests in a safe manner. Signed-off-by: Juergen Gross Signed-off-by: Oleksandr Tyshchenko Reviewed-by: Stefano Stabellini Link: https://lore.kernel.org/r/1654197833-25362-4-git-send-email-olekstysh@gmail.com Signed-off-by: Juergen Gross --- drivers/xen/Kconfig | 4 + drivers/xen/Makefile | 1 + drivers/xen/grant-dma-ops.c | 312 ++++++++++++++++++++++++++++++++++++++++++++ include/xen/xen-ops.h | 8 ++ 4 files changed, 325 insertions(+) create mode 100644 drivers/xen/grant-dma-ops.c diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 120d32f164ac..313a9127fd5c 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -335,4 +335,8 @@ config XEN_UNPOPULATED_ALLOC having to balloon out RAM regions in order to obtain physical memory space to create such mappings. +config XEN_GRANT_DMA_OPS + bool + select DMA_OPS + endmenu diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 5aae66e638a7..1a23cb0dc188 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -39,3 +39,4 @@ xen-gntalloc-y := gntalloc.o xen-privcmd-y := privcmd.o privcmd-buf.o obj-$(CONFIG_XEN_FRONT_PGDIR_SHBUF) += xen-front-pgdir-shbuf.o obj-$(CONFIG_XEN_UNPOPULATED_ALLOC) += unpopulated-alloc.o +obj-$(CONFIG_XEN_GRANT_DMA_OPS) += grant-dma-ops.o diff --git a/drivers/xen/grant-dma-ops.c b/drivers/xen/grant-dma-ops.c new file mode 100644 index 000000000000..aaff35cda517 --- /dev/null +++ b/drivers/xen/grant-dma-ops.c @@ -0,0 +1,312 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Xen grant DMA-mapping layer - contains special DMA-mapping routines + * for providing grant references as DMA addresses to be used by frontends + * (e.g. virtio) in Xen guests + * + * Copyright (c) 2021, Juergen Gross + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct xen_grant_dma_data { + /* The ID of backend domain */ + domid_t backend_domid; + /* Is device behaving sane? */ + bool broken; +}; + +static DEFINE_XARRAY(xen_grant_dma_devices); + +#define XEN_GRANT_DMA_ADDR_OFF (1ULL << 63) + +static inline dma_addr_t grant_to_dma(grant_ref_t grant) +{ + return XEN_GRANT_DMA_ADDR_OFF | ((dma_addr_t)grant << PAGE_SHIFT); +} + +static inline grant_ref_t dma_to_grant(dma_addr_t dma) +{ + return (grant_ref_t)((dma & ~XEN_GRANT_DMA_ADDR_OFF) >> PAGE_SHIFT); +} + +static struct xen_grant_dma_data *find_xen_grant_dma_data(struct device *dev) +{ + struct xen_grant_dma_data *data; + + xa_lock(&xen_grant_dma_devices); + data = xa_load(&xen_grant_dma_devices, (unsigned long)dev); + xa_unlock(&xen_grant_dma_devices); + + return data; +} + +/* + * DMA ops for Xen frontends (e.g. virtio). + * + * Used to act as a kind of software IOMMU for Xen guests by using grants as + * DMA addresses. + * Such a DMA address is formed by using the grant reference as a frame + * number and setting the highest address bit (this bit is for the backend + * to be able to distinguish it from e.g. a mmio address). + * + * Note that for now we hard wire dom0 to be the backend domain. In order + * to support any domain as backend we'd need to add a way to communicate + * the domid of this backend, e.g. via Xenstore, via the PCI-device's + * config space or DT/ACPI. + */ +static void *xen_grant_dma_alloc(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp, + unsigned long attrs) +{ + struct xen_grant_dma_data *data; + unsigned int i, n_pages = PFN_UP(size); + unsigned long pfn; + grant_ref_t grant; + void *ret; + + data = find_xen_grant_dma_data(dev); + if (!data) + return NULL; + + if (unlikely(data->broken)) + return NULL; + + ret = alloc_pages_exact(n_pages * PAGE_SIZE, gfp); + if (!ret) + return NULL; + + pfn = virt_to_pfn(ret); + + if (gnttab_alloc_grant_reference_seq(n_pages, &grant)) { + free_pages_exact(ret, n_pages * PAGE_SIZE); + return NULL; + } + + for (i = 0; i < n_pages; i++) { + gnttab_grant_foreign_access_ref(grant + i, data->backend_domid, + pfn_to_gfn(pfn + i), 0); + } + + *dma_handle = grant_to_dma(grant); + + return ret; +} + +static void xen_grant_dma_free(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle, unsigned long attrs) +{ + struct xen_grant_dma_data *data; + unsigned int i, n_pages = PFN_UP(size); + grant_ref_t grant; + + data = find_xen_grant_dma_data(dev); + if (!data) + return; + + if (unlikely(data->broken)) + return; + + grant = dma_to_grant(dma_handle); + + for (i = 0; i < n_pages; i++) { + if (unlikely(!gnttab_end_foreign_access_ref(grant + i))) { + dev_alert(dev, "Grant still in use by backend domain, disabled for further use\n"); + data->broken = true; + return; + } + } + + gnttab_free_grant_reference_seq(grant, n_pages); + + free_pages_exact(vaddr, n_pages * PAGE_SIZE); +} + +static struct page *xen_grant_dma_alloc_pages(struct device *dev, size_t size, + dma_addr_t *dma_handle, + enum dma_data_direction dir, + gfp_t gfp) +{ + void *vaddr; + + vaddr = xen_grant_dma_alloc(dev, size, dma_handle, gfp, 0); + if (!vaddr) + return NULL; + + return virt_to_page(vaddr); +} + +static void xen_grant_dma_free_pages(struct device *dev, size_t size, + struct page *vaddr, dma_addr_t dma_handle, + enum dma_data_direction dir) +{ + xen_grant_dma_free(dev, size, page_to_virt(vaddr), dma_handle, 0); +} + +static dma_addr_t xen_grant_dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction dir, + unsigned long attrs) +{ + struct xen_grant_dma_data *data; + unsigned int i, n_pages = PFN_UP(size); + grant_ref_t grant; + dma_addr_t dma_handle; + + if (WARN_ON(dir == DMA_NONE)) + return DMA_MAPPING_ERROR; + + data = find_xen_grant_dma_data(dev); + if (!data) + return DMA_MAPPING_ERROR; + + if (unlikely(data->broken)) + return DMA_MAPPING_ERROR; + + if (gnttab_alloc_grant_reference_seq(n_pages, &grant)) + return DMA_MAPPING_ERROR; + + for (i = 0; i < n_pages; i++) { + gnttab_grant_foreign_access_ref(grant + i, data->backend_domid, + xen_page_to_gfn(page) + i, dir == DMA_TO_DEVICE); + } + + dma_handle = grant_to_dma(grant) + offset; + + return dma_handle; +} + +static void xen_grant_dma_unmap_page(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction dir, + unsigned long attrs) +{ + struct xen_grant_dma_data *data; + unsigned int i, n_pages = PFN_UP(size); + grant_ref_t grant; + + if (WARN_ON(dir == DMA_NONE)) + return; + + data = find_xen_grant_dma_data(dev); + if (!data) + return; + + if (unlikely(data->broken)) + return; + + grant = dma_to_grant(dma_handle); + + for (i = 0; i < n_pages; i++) { + if (unlikely(!gnttab_end_foreign_access_ref(grant + i))) { + dev_alert(dev, "Grant still in use by backend domain, disabled for further use\n"); + data->broken = true; + return; + } + } + + gnttab_free_grant_reference_seq(grant, n_pages); +} + +static void xen_grant_dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, + unsigned long attrs) +{ + struct scatterlist *s; + unsigned int i; + + if (WARN_ON(dir == DMA_NONE)) + return; + + for_each_sg(sg, s, nents, i) + xen_grant_dma_unmap_page(dev, s->dma_address, sg_dma_len(s), dir, + attrs); +} + +static int xen_grant_dma_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, + unsigned long attrs) +{ + struct scatterlist *s; + unsigned int i; + + if (WARN_ON(dir == DMA_NONE)) + return -EINVAL; + + for_each_sg(sg, s, nents, i) { + s->dma_address = xen_grant_dma_map_page(dev, sg_page(s), s->offset, + s->length, dir, attrs); + if (s->dma_address == DMA_MAPPING_ERROR) + goto out; + + sg_dma_len(s) = s->length; + } + + return nents; + +out: + xen_grant_dma_unmap_sg(dev, sg, i, dir, attrs | DMA_ATTR_SKIP_CPU_SYNC); + sg_dma_len(sg) = 0; + + return -EIO; +} + +static int xen_grant_dma_supported(struct device *dev, u64 mask) +{ + return mask == DMA_BIT_MASK(64); +} + +static const struct dma_map_ops xen_grant_dma_ops = { + .alloc = xen_grant_dma_alloc, + .free = xen_grant_dma_free, + .alloc_pages = xen_grant_dma_alloc_pages, + .free_pages = xen_grant_dma_free_pages, + .mmap = dma_common_mmap, + .get_sgtable = dma_common_get_sgtable, + .map_page = xen_grant_dma_map_page, + .unmap_page = xen_grant_dma_unmap_page, + .map_sg = xen_grant_dma_map_sg, + .unmap_sg = xen_grant_dma_unmap_sg, + .dma_supported = xen_grant_dma_supported, +}; + +void xen_grant_setup_dma_ops(struct device *dev) +{ + struct xen_grant_dma_data *data; + + data = find_xen_grant_dma_data(dev); + if (data) { + dev_err(dev, "Xen grant DMA data is already created\n"); + return; + } + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + goto err; + + /* XXX The dom0 is hardcoded as the backend domain for now */ + data->backend_domid = 0; + + if (xa_err(xa_store(&xen_grant_dma_devices, (unsigned long)dev, data, + GFP_KERNEL))) { + dev_err(dev, "Cannot store Xen grant DMA data\n"); + goto err; + } + + dev->dma_ops = &xen_grant_dma_ops; + + return; + +err: + dev_err(dev, "Cannot set up Xen grant DMA ops, retain platform DMA ops\n"); +} + +MODULE_DESCRIPTION("Xen grant DMA-mapping layer"); +MODULE_AUTHOR("Juergen Gross "); +MODULE_LICENSE("GPL"); diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index c7c1b46ff4cd..afd586d717a4 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h @@ -214,4 +214,12 @@ static inline void xen_preemptible_hcall_end(void) { } #endif /* CONFIG_XEN_PV && !CONFIG_PREEMPTION */ +#ifdef CONFIG_XEN_GRANT_DMA_OPS +void xen_grant_setup_dma_ops(struct device *dev); +#else +static inline void xen_grant_setup_dma_ops(struct device *dev) +{ +} +#endif /* CONFIG_XEN_GRANT_DMA_OPS */ + #endif /* INCLUDE_XEN_OPS_H */ -- cgit From 2aab03b86766a27f99a0b24f63e1730faac128d0 Mon Sep 17 00:00:00 2001 From: Xiang wangx Date: Sun, 5 Jun 2022 20:55:09 +0800 Subject: fs: Fix syntax errors in comments Delete the redundant word 'not'. Link: https://lore.kernel.org/r/20220605125509.14837-1-wangxiang@cdjrlc.com Signed-off-by: Xiang wangx Signed-off-by: Jan Kara --- fs/ext2/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 360ce3604a2d..e6b932219803 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -1549,7 +1549,7 @@ static int __ext2_write_inode(struct inode *inode, int do_sync) if (IS_ERR(raw_inode)) return -EIO; - /* For fields not not tracking in the in-memory inode, + /* For fields not tracking in the in-memory inode, * initialise them to zero for new inodes. */ if (ei->i_state & EXT2_STATE_NEW) memset(raw_inode, 0, EXT2_SB(sb)->s_inode_size); -- cgit From 10e14073107dd0b6d97d9516a02845a8e501c2c9 Mon Sep 17 00:00:00 2001 From: Jchao Sun Date: Tue, 24 May 2022 08:05:40 -0700 Subject: writeback: Fix inode->i_io_list not be protected by inode->i_lock error Commit b35250c0816c ("writeback: Protect inode->i_io_list with inode->i_lock") made inode->i_io_list not only protected by wb->list_lock but also inode->i_lock, but inode_io_list_move_locked() was missed. Add lock there and also update comment describing things protected by inode->i_lock. This also fixes a race where __mark_inode_dirty() could move inode under flush worker's hands and thus sync(2) could miss writing some inodes. Fixes: b35250c0816c ("writeback: Protect inode->i_io_list with inode->i_lock") Link: https://lore.kernel.org/r/20220524150540.12552-1-sunjunchao2870@gmail.com CC: stable@vger.kernel.org Signed-off-by: Jchao Sun Signed-off-by: Jan Kara --- fs/fs-writeback.c | 37 ++++++++++++++++++++++++++++--------- fs/inode.c | 2 +- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index a21d8f1a56d1..05221366a16d 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -120,6 +120,7 @@ static bool inode_io_list_move_locked(struct inode *inode, struct list_head *head) { assert_spin_locked(&wb->list_lock); + assert_spin_locked(&inode->i_lock); list_move(&inode->i_io_list, head); @@ -1365,9 +1366,9 @@ static int move_expired_inodes(struct list_head *delaying_queue, inode = wb_inode(delaying_queue->prev); if (inode_dirtied_after(inode, dirtied_before)) break; + spin_lock(&inode->i_lock); list_move(&inode->i_io_list, &tmp); moved++; - spin_lock(&inode->i_lock); inode->i_state |= I_SYNC_QUEUED; spin_unlock(&inode->i_lock); if (sb_is_blkdev_sb(inode->i_sb)) @@ -1383,7 +1384,12 @@ static int move_expired_inodes(struct list_head *delaying_queue, goto out; } - /* Move inodes from one superblock together */ + /* + * Although inode's i_io_list is moved from 'tmp' to 'dispatch_queue', + * we don't take inode->i_lock here because it is just a pointless overhead. + * Inode is already marked as I_SYNC_QUEUED so writeback list handling is + * fully under our control. + */ while (!list_empty(&tmp)) { sb = wb_inode(tmp.prev)->i_sb; list_for_each_prev_safe(pos, node, &tmp) { @@ -1826,8 +1832,8 @@ static long writeback_sb_inodes(struct super_block *sb, * We'll have another go at writing back this inode * when we completed a full scan of b_io. */ - spin_unlock(&inode->i_lock); requeue_io(inode, wb); + spin_unlock(&inode->i_lock); trace_writeback_sb_inodes_requeue(inode); continue; } @@ -2358,6 +2364,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) { struct super_block *sb = inode->i_sb; int dirtytime = 0; + struct bdi_writeback *wb = NULL; trace_writeback_mark_inode_dirty(inode, flags); @@ -2409,6 +2416,17 @@ void __mark_inode_dirty(struct inode *inode, int flags) inode->i_state &= ~I_DIRTY_TIME; inode->i_state |= flags; + /* + * Grab inode's wb early because it requires dropping i_lock and we + * need to make sure following checks happen atomically with dirty + * list handling so that we don't move inodes under flush worker's + * hands. + */ + if (!was_dirty) { + wb = locked_inode_to_wb_and_lock_list(inode); + spin_lock(&inode->i_lock); + } + /* * If the inode is queued for writeback by flush worker, just * update its dirty state. Once the flush worker is done with @@ -2416,7 +2434,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) * list, based upon its state. */ if (inode->i_state & I_SYNC_QUEUED) - goto out_unlock_inode; + goto out_unlock; /* * Only add valid (hashed) inodes to the superblock's @@ -2424,22 +2442,19 @@ void __mark_inode_dirty(struct inode *inode, int flags) */ if (!S_ISBLK(inode->i_mode)) { if (inode_unhashed(inode)) - goto out_unlock_inode; + goto out_unlock; } if (inode->i_state & I_FREEING) - goto out_unlock_inode; + goto out_unlock; /* * If the inode was already on b_dirty/b_io/b_more_io, don't * reposition it (that would break b_dirty time-ordering). */ if (!was_dirty) { - struct bdi_writeback *wb; struct list_head *dirty_list; bool wakeup_bdi = false; - wb = locked_inode_to_wb_and_lock_list(inode); - inode->dirtied_when = jiffies; if (dirtytime) inode->dirtied_time_when = jiffies; @@ -2453,6 +2468,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) dirty_list); spin_unlock(&wb->list_lock); + spin_unlock(&inode->i_lock); trace_writeback_dirty_inode_enqueue(inode); /* @@ -2467,6 +2483,9 @@ void __mark_inode_dirty(struct inode *inode, int flags) return; } } +out_unlock: + if (wb) + spin_unlock(&wb->list_lock); out_unlock_inode: spin_unlock(&inode->i_lock); } diff --git a/fs/inode.c b/fs/inode.c index 9d9b422504d1..bd4da9c5207e 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -27,7 +27,7 @@ * Inode locking rules: * * inode->i_lock protects: - * inode->i_state, inode->i_hash, __iget() + * inode->i_state, inode->i_hash, __iget(), inode->i_io_list * Inode LRU list locks protect: * inode->i_sb->s_inode_lru, inode->i_lru * inode->i_sb->s_inode_list_lock protects: -- cgit From 537e11cdc7a6b3ce94fa25ed41306193df9677b7 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Sun, 5 Jun 2022 15:38:13 +0100 Subject: quota: Prevent memory allocation recursion while holding dq_lock As described in commit 02117b8ae9c0 ("f2fs: Set GF_NOFS in read_cache_page_gfp while doing f2fs_quota_read"), we must not enter filesystem reclaim while holding the dq_lock. Prevent this more generally by using memalloc_nofs_save() while holding the lock. Link: https://lore.kernel.org/r/20220605143815.2330891-2-willy@infradead.org Signed-off-by: Matthew Wilcox (Oracle) Signed-off-by: Jan Kara --- fs/quota/dquot.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index a74aef99bd3d..09d1307959d0 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -79,6 +79,7 @@ #include #include #include +#include #include "../internal.h" /* ugh */ #include @@ -425,9 +426,11 @@ EXPORT_SYMBOL(mark_info_dirty); int dquot_acquire(struct dquot *dquot) { int ret = 0, ret2 = 0; + unsigned int memalloc; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); mutex_lock(&dquot->dq_lock); + memalloc = memalloc_nofs_save(); if (!test_bit(DQ_READ_B, &dquot->dq_flags)) { ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot); if (ret < 0) @@ -458,6 +461,7 @@ int dquot_acquire(struct dquot *dquot) smp_mb__before_atomic(); set_bit(DQ_ACTIVE_B, &dquot->dq_flags); out_iolock: + memalloc_nofs_restore(memalloc); mutex_unlock(&dquot->dq_lock); return ret; } @@ -469,9 +473,11 @@ EXPORT_SYMBOL(dquot_acquire); int dquot_commit(struct dquot *dquot) { int ret = 0; + unsigned int memalloc; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); mutex_lock(&dquot->dq_lock); + memalloc = memalloc_nofs_save(); if (!clear_dquot_dirty(dquot)) goto out_lock; /* Inactive dquot can be only if there was error during read/init @@ -481,6 +487,7 @@ int dquot_commit(struct dquot *dquot) else ret = -EIO; out_lock: + memalloc_nofs_restore(memalloc); mutex_unlock(&dquot->dq_lock); return ret; } @@ -492,9 +499,11 @@ EXPORT_SYMBOL(dquot_commit); int dquot_release(struct dquot *dquot) { int ret = 0, ret2 = 0; + unsigned int memalloc; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); mutex_lock(&dquot->dq_lock); + memalloc = memalloc_nofs_save(); /* Check whether we are not racing with some other dqget() */ if (dquot_is_busy(dquot)) goto out_dqlock; @@ -510,6 +519,7 @@ int dquot_release(struct dquot *dquot) } clear_bit(DQ_ACTIVE_B, &dquot->dq_flags); out_dqlock: + memalloc_nofs_restore(memalloc); mutex_unlock(&dquot->dq_lock); return ret; } -- cgit From 386cbe7f1b152c8476a7d322d39512b1b4259ed5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 12 May 2022 20:39:21 +0300 Subject: gpio: crystalcove: make irq_chip immutable Since recently, the kernel is nagging about mutable irq_chips: "not an immutable chip, please consider fixing it!" Drop the unneeded copy, flag it as IRQCHIP_IMMUTABLE, add the new helper functions and call the appropriate gpiolib functions. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-crystalcove.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c index b55c74a5e064..cf33041533aa 100644 --- a/drivers/gpio/gpio-crystalcove.c +++ b/drivers/gpio/gpio-crystalcove.c @@ -15,6 +15,7 @@ #include #include #include +#include #define CRYSTALCOVE_GPIO_NUM 16 #define CRYSTALCOVE_VGPIO_NUM 95 @@ -238,34 +239,43 @@ static void crystalcove_bus_sync_unlock(struct irq_data *data) static void crystalcove_irq_unmask(struct irq_data *data) { - struct crystalcove_gpio *cg = - gpiochip_get_data(irq_data_get_irq_chip_data(data)); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct crystalcove_gpio *cg = gpiochip_get_data(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(data); - if (data->hwirq < CRYSTALCOVE_GPIO_NUM) { - cg->set_irq_mask = false; - cg->update |= UPDATE_IRQ_MASK; - } + if (hwirq >= CRYSTALCOVE_GPIO_NUM) + return; + + gpiochip_enable_irq(gc, hwirq); + + cg->set_irq_mask = false; + cg->update |= UPDATE_IRQ_MASK; } static void crystalcove_irq_mask(struct irq_data *data) { - struct crystalcove_gpio *cg = - gpiochip_get_data(irq_data_get_irq_chip_data(data)); + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); + struct crystalcove_gpio *cg = gpiochip_get_data(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(data); - if (data->hwirq < CRYSTALCOVE_GPIO_NUM) { - cg->set_irq_mask = true; - cg->update |= UPDATE_IRQ_MASK; - } + if (hwirq >= CRYSTALCOVE_GPIO_NUM) + return; + + cg->set_irq_mask = true; + cg->update |= UPDATE_IRQ_MASK; + + gpiochip_disable_irq(gc, hwirq); } -static struct irq_chip crystalcove_irqchip = { +static const struct irq_chip crystalcove_irqchip = { .name = "Crystal Cove", .irq_mask = crystalcove_irq_mask, .irq_unmask = crystalcove_irq_unmask, .irq_set_type = crystalcove_irq_type, .irq_bus_lock = crystalcove_bus_lock, .irq_bus_sync_unlock = crystalcove_bus_sync_unlock, - .flags = IRQCHIP_SKIP_SET_WAKE, + .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data) @@ -353,7 +363,7 @@ static int crystalcove_gpio_probe(struct platform_device *pdev) cg->regmap = pmic->regmap; girq = &cg->chip.irq; - girq->chip = &crystalcove_irqchip; + gpio_irq_chip_set_chip(girq, &crystalcove_irqchip); /* This will let us handle the parent IRQ in the driver */ girq->parent_handler = NULL; girq->num_parents = 0; -- cgit From b34d2ad73af3c58dbaf8aa71b7308f17d9863780 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 1 Jun 2022 17:18:02 +0300 Subject: gpio: crystalcove: Use specific type and API for IRQ number Use specific type and API for IRQ number in the callbacks. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-crystalcove.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c index cf33041533aa..36870d14323f 100644 --- a/drivers/gpio/gpio-crystalcove.c +++ b/drivers/gpio/gpio-crystalcove.c @@ -188,8 +188,9 @@ static int crystalcove_irq_type(struct irq_data *data, unsigned int type) { struct crystalcove_gpio *cg = gpiochip_get_data(irq_data_get_irq_chip_data(data)); + irq_hw_number_t hwirq = irqd_to_hwirq(data); - if (data->hwirq >= CRYSTALCOVE_GPIO_NUM) + if (hwirq >= CRYSTALCOVE_GPIO_NUM) return 0; switch (type) { @@ -226,12 +227,12 @@ static void crystalcove_bus_sync_unlock(struct irq_data *data) { struct crystalcove_gpio *cg = gpiochip_get_data(irq_data_get_irq_chip_data(data)); - int gpio = data->hwirq; + irq_hw_number_t hwirq = irqd_to_hwirq(data); if (cg->update & UPDATE_IRQ_TYPE) - crystalcove_update_irq_ctrl(cg, gpio); + crystalcove_update_irq_ctrl(cg, hwirq); if (cg->update & UPDATE_IRQ_MASK) - crystalcove_update_irq_mask(cg, gpio); + crystalcove_update_irq_mask(cg, hwirq); cg->update = 0; mutex_unlock(&cg->buslock); -- cgit From 68a12c19e1cb0f3332d3f59e1d5447f2aff97cd7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 1 Jun 2022 17:22:04 +0300 Subject: gpio: crystalcove: Join function declarations and long lines There is no more hard limit of 80 characters for long lines, so join a few of them for better readability. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-crystalcove.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c index 36870d14323f..1ee62cd58582 100644 --- a/drivers/gpio/gpio-crystalcove.c +++ b/drivers/gpio/gpio-crystalcove.c @@ -111,8 +111,7 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type) return reg + gpio % 8; } -static void crystalcove_update_irq_mask(struct crystalcove_gpio *cg, - int gpio) +static void crystalcove_update_irq_mask(struct crystalcove_gpio *cg, int gpio) { u8 mirqs0 = gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0; int mask = BIT(gpio % 8); @@ -141,8 +140,7 @@ static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned int gpio) return regmap_write(cg->regmap, reg, CTLO_INPUT_SET); } -static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned int gpio, - int value) +static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned int gpio, int value) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); int reg = to_reg(gpio, CTRL_OUT); @@ -169,8 +167,7 @@ static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned int gpio) return val & 0x1; } -static void crystalcove_gpio_set(struct gpio_chip *chip, - unsigned int gpio, int value) +static void crystalcove_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); int reg = to_reg(gpio, CTRL_OUT); @@ -186,8 +183,7 @@ static void crystalcove_gpio_set(struct gpio_chip *chip, static int crystalcove_irq_type(struct irq_data *data, unsigned int type) { - struct crystalcove_gpio *cg = - gpiochip_get_data(irq_data_get_irq_chip_data(data)); + struct crystalcove_gpio *cg = gpiochip_get_data(irq_data_get_irq_chip_data(data)); irq_hw_number_t hwirq = irqd_to_hwirq(data); if (hwirq >= CRYSTALCOVE_GPIO_NUM) @@ -217,16 +213,14 @@ static int crystalcove_irq_type(struct irq_data *data, unsigned int type) static void crystalcove_bus_lock(struct irq_data *data) { - struct crystalcove_gpio *cg = - gpiochip_get_data(irq_data_get_irq_chip_data(data)); + struct crystalcove_gpio *cg = gpiochip_get_data(irq_data_get_irq_chip_data(data)); mutex_lock(&cg->buslock); } static void crystalcove_bus_sync_unlock(struct irq_data *data) { - struct crystalcove_gpio *cg = - gpiochip_get_data(irq_data_get_irq_chip_data(data)); + struct crystalcove_gpio *cg = gpiochip_get_data(irq_data_get_irq_chip_data(data)); irq_hw_number_t hwirq = irqd_to_hwirq(data); if (cg->update & UPDATE_IRQ_TYPE) @@ -304,8 +298,7 @@ static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static void crystalcove_gpio_dbg_show(struct seq_file *s, - struct gpio_chip *chip) +static void crystalcove_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) { struct crystalcove_gpio *cg = gpiochip_get_data(chip); int gpio, offset; -- cgit From 41a18c4918dcd57a49b0d046d9f2d587878de739 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 12 May 2022 20:39:21 +0300 Subject: gpio: wcove: make irq_chip immutable Since recently, the kernel is nagging about mutable irq_chips: "not an immutable chip, please consider fixing it!" Drop the unneeded copy, flag it as IRQCHIP_IMMUTABLE, add the new helper functions and call the appropriate gpiolib functions. Signed-off-by: Andy Shevchenko Reviewed-by: Kuppuswamy Sathyanarayanan --- drivers/gpio/gpio-wcove.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c index 16a0fae1e32e..c18b6b47384f 100644 --- a/drivers/gpio/gpio-wcove.c +++ b/drivers/gpio/gpio-wcove.c @@ -299,6 +299,8 @@ static void wcove_irq_unmask(struct irq_data *data) if (gpio >= WCOVE_GPIO_NUM) return; + gpiochip_enable_irq(chip, gpio); + wg->set_irq_mask = false; wg->update |= UPDATE_IRQ_MASK; } @@ -314,15 +316,19 @@ static void wcove_irq_mask(struct irq_data *data) wg->set_irq_mask = true; wg->update |= UPDATE_IRQ_MASK; + + gpiochip_disable_irq(chip, gpio); } -static struct irq_chip wcove_irqchip = { +static const struct irq_chip wcove_irqchip = { .name = "Whiskey Cove", .irq_mask = wcove_irq_mask, .irq_unmask = wcove_irq_unmask, .irq_set_type = wcove_irq_type, .irq_bus_lock = wcove_bus_lock, .irq_bus_sync_unlock = wcove_bus_sync_unlock, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static irqreturn_t wcove_gpio_irq_handler(int irq, void *data) @@ -452,7 +458,7 @@ static int wcove_gpio_probe(struct platform_device *pdev) } girq = &wg->chip.irq; - girq->chip = &wcove_irqchip; + gpio_irq_chip_set_chip(girq, &wcove_irqchip); /* This will let us handle the parent IRQ in the driver */ girq->parent_handler = NULL; girq->num_parents = 0; -- cgit From a80fed9fb643175832e2fb8481d38f5d92cbcd34 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 12 May 2022 20:39:21 +0300 Subject: gpio: merrifield: make irq_chip immutable Since recently, the kernel is nagging about mutable irq_chips: "not an immutable chip, please consider fixing it!" Drop the unneeded copy, flag it as IRQCHIP_IMMUTABLE, add the new helper functions and call the appropriate gpiolib functions. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-merrifield.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index f3d1baeacbe9..72ac09a59702 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -220,10 +220,8 @@ static void mrfld_irq_ack(struct irq_data *d) raw_spin_unlock_irqrestore(&priv->lock, flags); } -static void mrfld_irq_unmask_mask(struct irq_data *d, bool unmask) +static void mrfld_irq_unmask_mask(struct mrfld_gpio *priv, u32 gpio, bool unmask) { - struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d); - u32 gpio = irqd_to_hwirq(d); void __iomem *gimr = gpio_reg(&priv->chip, gpio, GIMR); unsigned long flags; u32 value; @@ -241,12 +239,20 @@ static void mrfld_irq_unmask_mask(struct irq_data *d, bool unmask) static void mrfld_irq_mask(struct irq_data *d) { - mrfld_irq_unmask_mask(d, false); + struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d); + u32 gpio = irqd_to_hwirq(d); + + mrfld_irq_unmask_mask(priv, gpio, false); + gpiochip_disable_irq(&priv->chip, gpio); } static void mrfld_irq_unmask(struct irq_data *d) { - mrfld_irq_unmask_mask(d, true); + struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d); + u32 gpio = irqd_to_hwirq(d); + + gpiochip_enable_irq(&priv->chip, gpio); + mrfld_irq_unmask_mask(priv, gpio, true); } static int mrfld_irq_set_type(struct irq_data *d, unsigned int type) @@ -329,13 +335,15 @@ static int mrfld_irq_set_wake(struct irq_data *d, unsigned int on) return 0; } -static struct irq_chip mrfld_irqchip = { +static const struct irq_chip mrfld_irqchip = { .name = "gpio-merrifield", .irq_ack = mrfld_irq_ack, .irq_mask = mrfld_irq_mask, .irq_unmask = mrfld_irq_unmask, .irq_set_type = mrfld_irq_set_type, .irq_set_wake = mrfld_irq_set_wake, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static void mrfld_irq_handler(struct irq_desc *desc) @@ -482,7 +490,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id return retval; girq = &priv->chip.irq; - girq->chip = &mrfld_irqchip; + gpio_irq_chip_set_chip(girq, &mrfld_irqchip); girq->init_hw = mrfld_irq_init_hw; girq->parent_handler = mrfld_irq_handler; girq->num_parents = 1; -- cgit From f1138dacb7ff5221c4a37b823e42fc0a34df8731 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 1 Jun 2022 18:36:56 +0300 Subject: gpio: sch: make irq_chip immutable Since recently, the kernel is nagging about mutable irq_chips: "not an immutable chip, please consider fixing it!" Drop the unneeded copy, flag it as IRQCHIP_IMMUTABLE, add the new helper functions and call the appropriate gpiolib functions. Signed-off-by: Andy Shevchenko Reviewed-by: Bartosz Golaszewski --- drivers/gpio/gpio-sch.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index acda4c5052d3..8a83f7bf4382 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c @@ -38,7 +38,6 @@ struct sch_gpio { struct gpio_chip chip; - struct irq_chip irqchip; spinlock_t lock; unsigned short iobase; unsigned short resume_base; @@ -218,11 +217,9 @@ static void sch_irq_ack(struct irq_data *d) spin_unlock_irqrestore(&sch->lock, flags); } -static void sch_irq_mask_unmask(struct irq_data *d, int val) +static void sch_irq_mask_unmask(struct gpio_chip *gc, irq_hw_number_t gpio_num, int val) { - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct sch_gpio *sch = gpiochip_get_data(gc); - irq_hw_number_t gpio_num = irqd_to_hwirq(d); unsigned long flags; spin_lock_irqsave(&sch->lock, flags); @@ -232,14 +229,32 @@ static void sch_irq_mask_unmask(struct irq_data *d, int val) static void sch_irq_mask(struct irq_data *d) { - sch_irq_mask_unmask(d, 0); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t gpio_num = irqd_to_hwirq(d); + + sch_irq_mask_unmask(gc, gpio_num, 0); + gpiochip_disable_irq(gc, gpio_num); } static void sch_irq_unmask(struct irq_data *d) { - sch_irq_mask_unmask(d, 1); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t gpio_num = irqd_to_hwirq(d); + + gpiochip_enable_irq(gc, gpio_num); + sch_irq_mask_unmask(gc, gpio_num, 1); } +static const struct irq_chip sch_irqchip = { + .name = "sch_gpio", + .irq_ack = sch_irq_ack, + .irq_mask = sch_irq_mask, + .irq_unmask = sch_irq_unmask, + .irq_set_type = sch_irq_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static u32 sch_gpio_gpe_handler(acpi_handle gpe_device, u32 gpe, void *context) { struct sch_gpio *sch = context; @@ -367,14 +382,8 @@ static int sch_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, sch); - sch->irqchip.name = "sch_gpio"; - sch->irqchip.irq_ack = sch_irq_ack; - sch->irqchip.irq_mask = sch_irq_mask; - sch->irqchip.irq_unmask = sch_irq_unmask; - sch->irqchip.irq_set_type = sch_irq_type; - girq = &sch->chip.irq; - girq->chip = &sch->irqchip; + gpio_irq_chip_set_chip(girq, &sch_irqchip); girq->num_parents = 0; girq->parents = NULL; girq->parent_handler = NULL; -- cgit From b93a8b2c5161696e732185311d309e0aaf0575be Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 12 May 2022 20:39:21 +0300 Subject: gpio: dln2: make irq_chip immutable Since recently, the kernel is nagging about mutable irq_chips: "not an immutable chip, please consider fixing it!" Drop the unneeded copy, flag it as IRQCHIP_IMMUTABLE, add the new helper functions and call the appropriate gpiolib functions. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-dln2.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c index 08b9e2cf4f2d..71fa437b491f 100644 --- a/drivers/gpio/gpio-dln2.c +++ b/drivers/gpio/gpio-dln2.c @@ -46,7 +46,6 @@ struct dln2_gpio { struct platform_device *pdev; struct gpio_chip gpio; - struct irq_chip irqchip; /* * Cache pin direction to save us one transfer, since the hardware has @@ -306,6 +305,7 @@ static void dln2_irq_unmask(struct irq_data *irqd) struct dln2_gpio *dln2 = gpiochip_get_data(gc); int pin = irqd_to_hwirq(irqd); + gpiochip_enable_irq(gc, pin); set_bit(pin, dln2->unmasked_irqs); } @@ -316,6 +316,7 @@ static void dln2_irq_mask(struct irq_data *irqd) int pin = irqd_to_hwirq(irqd); clear_bit(pin, dln2->unmasked_irqs); + gpiochip_disable_irq(gc, pin); } static int dln2_irq_set_type(struct irq_data *irqd, unsigned type) @@ -384,6 +385,17 @@ static void dln2_irq_bus_unlock(struct irq_data *irqd) mutex_unlock(&dln2->irq_lock); } +static const struct irq_chip dln2_irqchip = { + .name = "dln2-irq", + .irq_mask = dln2_irq_mask, + .irq_unmask = dln2_irq_unmask, + .irq_set_type = dln2_irq_set_type, + .irq_bus_lock = dln2_irq_bus_lock, + .irq_bus_sync_unlock = dln2_irq_bus_unlock, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + static void dln2_gpio_event(struct platform_device *pdev, u16 echo, const void *data, int len) { @@ -465,15 +477,8 @@ static int dln2_gpio_probe(struct platform_device *pdev) dln2->gpio.direction_output = dln2_gpio_direction_output; dln2->gpio.set_config = dln2_gpio_set_config; - dln2->irqchip.name = "dln2-irq", - dln2->irqchip.irq_mask = dln2_irq_mask, - dln2->irqchip.irq_unmask = dln2_irq_unmask, - dln2->irqchip.irq_set_type = dln2_irq_set_type, - dln2->irqchip.irq_bus_lock = dln2_irq_bus_lock, - dln2->irqchip.irq_bus_sync_unlock = dln2_irq_bus_unlock, - girq = &dln2->gpio.irq; - girq->chip = &dln2->irqchip; + gpio_irq_chip_set_chip(girq, &dln2_irqchip); /* The event comes from the outside so no parent handler */ girq->parent_handler = NULL; girq->num_parents = 0; -- cgit From fed3d9297a9bf8b342c034e74a1fdba6940fe84a Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Mon, 30 May 2022 12:01:51 +0800 Subject: ASoC: nau8822: Disable internal PLL if freq_out is zero After finishing the playback or recording, the machine driver might call snd_soc_dai_set_pll(codec, pll_id, 0, 0, 0) to stop the internal PLL, but with the codec driver nau8822, it will print error as below: nau8822 0-001a: Unsupported input clock 0 fsl-asoc-card sound-nau8822: failed to stop FLL: -22 Refer to the function wm8962_set_fll() in the codec driver wm8962, if the freq_out is zero, turn off the internal PLL and return 0. Cc: David Lin Cc: John Hsu Cc: Seven Li Signed-off-by: Hui Wang Link: https://lore.kernel.org/r/20220530040151.95221-3-hui.wang@canonical.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8822.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c index 08f6c56dc387..fd9c766e277f 100644 --- a/sound/soc/codecs/nau8822.c +++ b/sound/soc/codecs/nau8822.c @@ -726,6 +726,13 @@ static int nau8822_set_pll(struct snd_soc_dai *dai, int pll_id, int source, struct nau8822_pll *pll_param = &nau8822->pll; int ret, fs; + if (freq_out == 0) { + dev_dbg(component->dev, "PLL disabled\n"); + snd_soc_component_update_bits(component, + NAU8822_REG_POWER_MANAGEMENT_1, NAU8822_PLL_EN_MASK, NAU8822_PLL_OFF); + return 0; + } + fs = freq_out / 256; ret = nau8822_calc_pll(freq_in, fs, pll_param); -- cgit From 45c6c5e052df2ee0d87e74743d8bb72e70fd0887 Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Fri, 3 Jun 2022 12:06:07 +0530 Subject: ASoC: tegra: Add binding doc for OPE module This patch adds YAML schema for DT bindings of Output Processing Engine (OPE) module. It consists of Parametric Equalizer (PEQ) and Multi Band Dynamic Range Compressor (MBDRC) sub blocks and binding doc for these blocks are added as well. The OPE will be registered as an ASoC component and can be plugged into an audio path as per need via ALSA mixer controls. The DT bindings are applicable on Tegra210 and later SoCs where OPE module is present. Signed-off-by: Sameer Pujar Link: https://lore.kernel.org/r/1654238172-16293-2-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- .../bindings/sound/nvidia,tegra210-ahub.yaml | 4 + .../bindings/sound/nvidia,tegra210-mbdrc.yaml | 47 ++++++++++++ .../bindings/sound/nvidia,tegra210-ope.yaml | 87 ++++++++++++++++++++++ .../bindings/sound/nvidia,tegra210-peq.yaml | 48 ++++++++++++ 4 files changed, 186 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-mbdrc.yaml create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-ope.yaml create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra210-peq.yaml diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml index 6df6f858038c..47b6e712e4fb 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml @@ -110,6 +110,10 @@ patternProperties: type: object $ref: nvidia,tegra186-asrc.yaml# + '^processing-engine@[0-9a-f]+$': + type: object + $ref: nvidia,tegra210-ope.yaml# + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-mbdrc.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mbdrc.yaml new file mode 100644 index 000000000000..5b9198602fc6 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mbdrc.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra210-mbdrc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Tegra210 MBDRC + +description: + The Multi Band Dynamic Range Compressor (MBDRC) is part of Output + Processing Engine (OPE) which interfaces with Audio Hub (AHUB) via + Audio Client Interface (ACIF). MBDRC can be used as a traditional + single full band or a dual band or a multi band dynamic processor. + +maintainers: + - Jon Hunter + - Mohan Kumar + - Sameer Pujar + +properties: + compatible: + oneOf: + - const: nvidia,tegra210-mbdrc + - items: + - enum: + - nvidia,tegra234-mbdrc + - nvidia,tegra194-mbdrc + - nvidia,tegra186-mbdrc + - const: nvidia,tegra210-mbdrc + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + dynamic-range-compressor@702d8200 { + compatible = "nvidia,tegra210-mbdrc"; + reg = <0x702d8200 0x200>; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ope.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ope.yaml new file mode 100644 index 000000000000..9dc9ba590fa3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ope.yaml @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra210-ope.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Tegra210 OPE + +description: + The Output Processing Engine (OPE) is one of the AHUB client. It has + PEQ (Parametric Equalizer) and MBDRC (Multi Band Dynamic Range Compressor) + sub blocks for data processing. + +maintainers: + - Jon Hunter + - Mohan Kumar + - Sameer Pujar + +allOf: + - $ref: name-prefix.yaml# + +properties: + compatible: + oneOf: + - const: nvidia,tegra210-ope + - items: + - enum: + - nvidia,tegra234-ope + - nvidia,tegra194-ope + - nvidia,tegra186-ope + - const: nvidia,tegra210-ope + + reg: + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + ranges: true + + sound-name-prefix: + pattern: "^OPE[1-9]$" + + ports: + $ref: /schemas/graph.yaml#/properties/ports + properties: + port@0: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + description: + OPE ACIF (Audio Client Interface) input port. This is connected + to corresponding ACIF output port on AHUB (Audio Hub). + + port@1: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + description: + OPE ACIF output port. This is connected to corresponding ACIF + input port on AHUB. + +patternProperties: + '^equalizer@[0-9a-f]+$': + type: object + $ref: nvidia,tegra210-peq.yaml# + + '^dynamic-range-compressor@[0-9a-f]+$': + type: object + $ref: nvidia,tegra210-mbdrc.yaml# + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + processing-engine@702d8000 { + compatible = "nvidia,tegra210-ope"; + reg = <0x702d8000 0x100>; + sound-name-prefix = "OPE1"; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-peq.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-peq.yaml new file mode 100644 index 000000000000..1e373c49d639 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-peq.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra210-peq.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Tegra210 PEQ + +description: + The Parametric Equalizer (PEQ) is a cascade of biquad filters with + each filter tuned based on certain parameters. It can be used to + equalize the irregularities in the speaker frequency response. + PEQ sits inside Output Processing Engine (OPE) which interfaces + with Audio Hub (AHUB) via Audio Client Interface (ACIF). + +maintainers: + - Jon Hunter + - Mohan Kumar + - Sameer Pujar + +properties: + compatible: + oneOf: + - const: nvidia,tegra210-peq + - items: + - enum: + - nvidia,tegra234-peq + - nvidia,tegra194-peq + - nvidia,tegra186-peq + - const: nvidia,tegra210-peq + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + equalizer@702d8100 { + compatible = "nvidia,tegra210-peq"; + reg = <0x702d8100 0x100>; + }; + +... -- cgit From 7358a803c778f28314721e78339f3fa5b787f55c Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Fri, 3 Jun 2022 12:06:08 +0530 Subject: ASoC: tegra: Add Tegra210 based OPE driver The Output Processing Engine (OPE) is one of the AHUB client. It has PEQ (Parametric Equalizer) and MBDRC (Multi Band Dynamic Range Compressor) sub blocks for data processing. The PEQ block gets samples from the MBDRC block. This patch registers OPE driver with ASoC framework. The component driver exposes DAPM widgets, routes and kcontrols for the device. The DAI driver exposes OPE interfaces, which can be used to connect different components in the ASoC layer. Makefile and Kconfig support is added to allow build the driver. Signed-off-by: Sameer Pujar Link: https://lore.kernel.org/r/1654238172-16293-3-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- sound/soc/tegra/Kconfig | 9 + sound/soc/tegra/Makefile | 2 + sound/soc/tegra/tegra210_mbdrc.c | 1012 ++++++++++++++++++++++++++++++++++++++ sound/soc/tegra/tegra210_mbdrc.h | 215 ++++++++ sound/soc/tegra/tegra210_ope.c | 419 ++++++++++++++++ sound/soc/tegra/tegra210_ope.h | 90 ++++ sound/soc/tegra/tegra210_peq.c | 434 ++++++++++++++++ sound/soc/tegra/tegra210_peq.h | 56 +++ 8 files changed, 2237 insertions(+) create mode 100644 sound/soc/tegra/tegra210_mbdrc.c create mode 100644 sound/soc/tegra/tegra210_mbdrc.h create mode 100644 sound/soc/tegra/tegra210_ope.c create mode 100644 sound/soc/tegra/tegra210_ope.h create mode 100644 sound/soc/tegra/tegra210_peq.c create mode 100644 sound/soc/tegra/tegra210_peq.h diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 2482d9867357..b6712a3d1fa1 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -85,6 +85,15 @@ config SND_SOC_TEGRA210_I2S compatible devices. Say Y or M if you want to add support for Tegra210 I2S module. +config SND_SOC_TEGRA210_OPE + tristate "Tegra210 OPE module" + help + Config to enable the Output Processing Engine (OPE) which includes + Parametric Equalizer (PEQ) and Multi Band Dynamic Range Compressor + (MBDRC) sub blocks for data processing. It can support up to 8 + channels. + Say Y or M if you want to add support for Tegra210 OPE module. + config SND_SOC_TEGRA186_ASRC tristate "Tegra186 ASRC module" help diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index 70a498ddb2fa..b723c78e665d 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile @@ -19,6 +19,7 @@ snd-soc-tegra210-sfc-objs := tegra210_sfc.o snd-soc-tegra210-amx-objs := tegra210_amx.o snd-soc-tegra210-adx-objs := tegra210_adx.o snd-soc-tegra210-mixer-objs := tegra210_mixer.o +snd-soc-tegra210-ope-objs := tegra210_ope.o tegra210_mbdrc.o tegra210_peq.o obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o obj-$(CONFIG_SND_SOC_TEGRA20_AC97) += snd-soc-tegra20-ac97.o @@ -38,6 +39,7 @@ obj-$(CONFIG_SND_SOC_TEGRA210_SFC) += snd-soc-tegra210-sfc.o obj-$(CONFIG_SND_SOC_TEGRA210_AMX) += snd-soc-tegra210-amx.o obj-$(CONFIG_SND_SOC_TEGRA210_ADX) += snd-soc-tegra210-adx.o obj-$(CONFIG_SND_SOC_TEGRA210_MIXER) += snd-soc-tegra210-mixer.o +obj-$(CONFIG_SND_SOC_TEGRA210_OPE) += snd-soc-tegra210-ope.o # Tegra machine Support snd-soc-tegra-wm8903-objs := tegra_wm8903.o diff --git a/sound/soc/tegra/tegra210_mbdrc.c b/sound/soc/tegra/tegra210_mbdrc.c new file mode 100644 index 000000000000..7d9da33a9951 --- /dev/null +++ b/sound/soc/tegra/tegra210_mbdrc.c @@ -0,0 +1,1012 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra210_mbdrc.c - Tegra210 MBDRC driver +// +// Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tegra210_mbdrc.h" +#include "tegra210_ope.h" + +#define MBDRC_FILTER_REG(reg, id) \ + ((reg) + ((id) * TEGRA210_MBDRC_FILTER_PARAM_STRIDE)) + +#define MBDRC_FILTER_REG_DEFAULTS(id) \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_IIR_CFG, id), 0x00000005}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_IN_ATTACK, id), 0x3e48590c}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_IN_RELEASE, id), 0x08414e9f}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_FAST_ATTACK, id), 0x7fffffff}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_IN_THRESHOLD, id), 0x06145082}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_OUT_THRESHOLD, id), 0x060d379b}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_1ST, id), 0x0000a000}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_2ND, id), 0x00002000}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_3RD, id), 0x00000b33}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_4TH, id), 0x00000800}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_RATIO_5TH, id), 0x0000019a}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_MAKEUP_GAIN, id), 0x00000002}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_INIT_GAIN, id), 0x00066666}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_GAIN_ATTACK, id), 0x00d9ba0e}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_GAIN_RELEASE, id), 0x3e48590c}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_FAST_RELEASE, id), 0x7ffff26a}, \ + { MBDRC_FILTER_REG(TEGRA210_MBDRC_CFG_RAM_CTRL, id), 0x4000} + +static const struct reg_default tegra210_mbdrc_reg_defaults[] = { + { TEGRA210_MBDRC_CFG, 0x0030de51}, + { TEGRA210_MBDRC_CHANNEL_MASK, 0x00000003}, + { TEGRA210_MBDRC_FAST_FACTOR, 0x30000800}, + + MBDRC_FILTER_REG_DEFAULTS(0), + MBDRC_FILTER_REG_DEFAULTS(1), + MBDRC_FILTER_REG_DEFAULTS(2), +}; + +/* Default MBDRC parameters */ +static const struct tegra210_mbdrc_config mbdrc_init_config = { + .mode = 0, /* Bypass */ + .rms_off = 48, + .peak_rms_mode = 1, /* PEAK */ + .fliter_structure = 0, /* All-pass tree */ + .shift_ctrl = 30, + .frame_size = 32, + .channel_mask = 0x3, + .fa_factor = 2048, + .fr_factor = 14747, + + .band_params[MBDRC_LOW_BAND] = { + .band = MBDRC_LOW_BAND, + .iir_stages = 5, + .in_attack_tc = 1044928780, + .in_release_tc = 138497695, + .fast_attack_tc = 2147483647, + .in_threshold = {130, 80, 20, 6}, + .out_threshold = {155, 55, 13, 6}, + .ratio = {40960, 8192, 2867, 2048, 410}, + .makeup_gain = 4, + .gain_init = 419430, + .gain_attack_tc = 14268942, + .gain_release_tc = 1440547090, + .fast_release_tc = 2147480170, + + .biquad_params = { + /* + * Gains: + * + * b0, b1, a0, + * a1, a2, + */ + + /* Band-0 */ + 961046798, -2030431983, 1073741824, + 2030431983, -961046798, + /* Band-1 */ + 1030244425, -2099481453, 1073741824, + 2099481453, -1030244425, + /* Band-2 */ + 1067169294, -2136327263, 1073741824, + 2136327263, -1067169294, + /* Band-3 */ + 434951949, -1306567134, 1073741824, + 1306567134, -434951949, + /* Band-4 */ + 780656019, -1605955641, 1073741824, + 1605955641, -780656019, + /* Band-5 */ + 1024497031, -1817128152, 1073741824, + 1817128152, -1024497031, + /* Band-6 */ + 1073741824, 0, 0, + 0, 0, + /* Band-7 */ + 1073741824, 0, 0, + 0, 0, + } + }, + + .band_params[MBDRC_MID_BAND] = { + .band = MBDRC_MID_BAND, + .iir_stages = 5, + .in_attack_tc = 1581413104, + .in_release_tc = 35494783, + .fast_attack_tc = 2147483647, + .in_threshold = {130, 50, 30, 6}, + .out_threshold = {106, 50, 30, 13}, + .ratio = {40960, 2867, 4096, 2867, 410}, + .makeup_gain = 6, + .gain_init = 419430, + .gain_attack_tc = 4766887, + .gain_release_tc = 1044928780, + .fast_release_tc = 2147480170, + + .biquad_params = { + /* + * Gains: + * + * b0, b1, a0, + * a1, a2, + */ + + /* Band-0 */ + -1005668963, 1073741824, 0, + 1005668963, 0, + /* Band-1 */ + 998437058, -2067742187, 1073741824, + 2067742187, -998437058, + /* Band-2 */ + 1051963422, -2121153948, 1073741824, + 2121153948, -1051963422, + /* Band-3 */ + 434951949, -1306567134, 1073741824, + 1306567134, -434951949, + /* Band-4 */ + 780656019, -1605955641, 1073741824, + 1605955641, -780656019, + /* Band-5 */ + 1024497031, -1817128152, 1073741824, + 1817128152, -1024497031, + /* Band-6 */ + 1073741824, 0, 0, + 0, 0, + /* Band-7 */ + 1073741824, 0, 0, + 0, 0, + } + }, + + .band_params[MBDRC_HIGH_BAND] = { + .band = MBDRC_HIGH_BAND, + .iir_stages = 5, + .in_attack_tc = 2144750688, + .in_release_tc = 70402888, + .fast_attack_tc = 2147483647, + .in_threshold = {130, 50, 30, 6}, + .out_threshold = {106, 50, 30, 13}, + .ratio = {40960, 2867, 4096, 2867, 410}, + .makeup_gain = 6, + .gain_init = 419430, + .gain_attack_tc = 4766887, + .gain_release_tc = 1044928780, + .fast_release_tc = 2147480170, + + .biquad_params = { + /* + * Gains: + * + * b0, b1, a0, + * a1, a2, + */ + + /* Band-0 */ + 1073741824, 0, 0, + 0, 0, + /* Band-1 */ + 1073741824, 0, 0, + 0, 0, + /* Band-2 */ + 1073741824, 0, 0, + 0, 0, + /* Band-3 */ + -619925131, 1073741824, 0, + 619925131, 0, + /* Band-4 */ + 606839335, -1455425976, 1073741824, + 1455425976, -606839335, + /* Band-5 */ + 917759617, -1724690840, 1073741824, + 1724690840, -917759617, + /* Band-6 */ + 1073741824, 0, 0, + 0, 0, + /* Band-7 */ + 1073741824, 0, 0, + 0, 0, + } + } +}; + +static void tegra210_mbdrc_write_ram(struct regmap *regmap, unsigned int reg_ctrl, + unsigned int reg_data, unsigned int ram_offset, + unsigned int *data, size_t size) +{ + unsigned int val; + unsigned int i; + + val = ram_offset & TEGRA210_MBDRC_RAM_CTRL_RAM_ADDR_MASK; + val |= TEGRA210_MBDRC_RAM_CTRL_ADDR_INIT_EN; + val |= TEGRA210_MBDRC_RAM_CTRL_SEQ_ACCESS_EN; + val |= TEGRA210_MBDRC_RAM_CTRL_RW_WRITE; + + regmap_write(regmap, reg_ctrl, val); + + for (i = 0; i < size; i++) + regmap_write(regmap, reg_data, data[i]); +} + +static int tegra210_mbdrc_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + unsigned int val; + + regmap_read(ope->mbdrc_regmap, mc->reg, &val); + + ucontrol->value.integer.value[0] = (val >> mc->shift) & mc->max; + + return 0; +} + +static int tegra210_mbdrc_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + unsigned int val = ucontrol->value.integer.value[0]; + bool change = false; + + val = val << mc->shift; + + regmap_update_bits_check(ope->mbdrc_regmap, mc->reg, + (mc->max << mc->shift), val, &change); + + return change ? 1 : 0; +} + +static int tegra210_mbdrc_get_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int val; + + regmap_read(ope->mbdrc_regmap, e->reg, &val); + + ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; + + return 0; +} + +static int tegra210_mbdrc_put_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + bool change = false; + unsigned int val; + unsigned int mask; + + if (ucontrol->value.enumerated.item[0] > e->items - 1) + return -EINVAL; + + val = ucontrol->value.enumerated.item[0] << e->shift_l; + mask = e->mask << e->shift_l; + + regmap_update_bits_check(ope->mbdrc_regmap, e->reg, mask, val, + &change); + + return change ? 1 : 0; +} + +static int tegra210_mbdrc_band_params_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tegra_soc_bytes *params = (void *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + u32 *data = (u32 *)ucontrol->value.bytes.data; + u32 regs = params->soc.base; + u32 mask = params->soc.mask; + u32 shift = params->shift; + unsigned int i; + + for (i = 0; i < params->soc.num_regs; i++, regs += cmpnt->val_bytes) { + regmap_read(ope->mbdrc_regmap, regs, &data[i]); + + data[i] = ((data[i] & mask) >> shift); + } + + return 0; +} + +static int tegra210_mbdrc_band_params_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tegra_soc_bytes *params = (void *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + u32 *data = (u32 *)ucontrol->value.bytes.data; + u32 regs = params->soc.base; + u32 mask = params->soc.mask; + u32 shift = params->shift; + bool change = false; + unsigned int i; + + for (i = 0; i < params->soc.num_regs; i++, regs += cmpnt->val_bytes) { + bool update = false; + + regmap_update_bits_check(ope->mbdrc_regmap, regs, mask, + data[i] << shift, &update); + + change |= update; + } + + return change ? 1 : 0; +} + +static int tegra210_mbdrc_threshold_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tegra_soc_bytes *params = (void *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + u32 *data = (u32 *)ucontrol->value.bytes.data; + u32 regs = params->soc.base; + u32 num_regs = params->soc.num_regs; + u32 val; + unsigned int i; + + for (i = 0; i < num_regs; i += 4, regs += cmpnt->val_bytes) { + regmap_read(ope->mbdrc_regmap, regs, &val); + + data[i] = (val & TEGRA210_MBDRC_THRESH_1ST_MASK) >> + TEGRA210_MBDRC_THRESH_1ST_SHIFT; + data[i + 1] = (val & TEGRA210_MBDRC_THRESH_2ND_MASK) >> + TEGRA210_MBDRC_THRESH_2ND_SHIFT; + data[i + 2] = (val & TEGRA210_MBDRC_THRESH_3RD_MASK) >> + TEGRA210_MBDRC_THRESH_3RD_SHIFT; + data[i + 3] = (val & TEGRA210_MBDRC_THRESH_4TH_MASK) >> + TEGRA210_MBDRC_THRESH_4TH_SHIFT; + } + + return 0; +} + +static int tegra210_mbdrc_threshold_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tegra_soc_bytes *params = (void *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + u32 *data = (u32 *)ucontrol->value.bytes.data; + u32 regs = params->soc.base; + u32 num_regs = params->soc.num_regs; + bool change = false; + unsigned int i; + + for (i = 0; i < num_regs; i += 4, regs += cmpnt->val_bytes) { + bool update = false; + + data[i] = (((data[i] >> TEGRA210_MBDRC_THRESH_1ST_SHIFT) & + TEGRA210_MBDRC_THRESH_1ST_MASK) | + ((data[i + 1] >> TEGRA210_MBDRC_THRESH_2ND_SHIFT) & + TEGRA210_MBDRC_THRESH_2ND_MASK) | + ((data[i + 2] >> TEGRA210_MBDRC_THRESH_3RD_SHIFT) & + TEGRA210_MBDRC_THRESH_3RD_MASK) | + ((data[i + 3] >> TEGRA210_MBDRC_THRESH_4TH_SHIFT) & + TEGRA210_MBDRC_THRESH_4TH_MASK)); + + regmap_update_bits_check(ope->mbdrc_regmap, regs, 0xffffffff, + data[i], &update); + + change |= update; + } + + return change ? 1 : 0; +} + +static int tegra210_mbdrc_biquad_coeffs_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tegra_soc_bytes *params = (void *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + u32 *data = (u32 *)ucontrol->value.bytes.data; + + memset(data, 0, params->soc.num_regs * cmpnt->val_bytes); + + return 0; +} + +static int tegra210_mbdrc_biquad_coeffs_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tegra_soc_bytes *params = (void *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + u32 reg_ctrl = params->soc.base; + u32 reg_data = reg_ctrl + cmpnt->val_bytes; + u32 *data = (u32 *)ucontrol->value.bytes.data; + + tegra210_mbdrc_write_ram(ope->mbdrc_regmap, reg_ctrl, reg_data, + params->shift, data, params->soc.num_regs); + + return 1; +} + +static int tegra210_mbdrc_param_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct soc_bytes *params = (void *)kcontrol->private_value; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = params->num_regs * sizeof(u32); + + return 0; +} + +static int tegra210_mbdrc_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + int val; + + regmap_read(ope->mbdrc_regmap, mc->reg, &val); + + ucontrol->value.integer.value[0] = + ((val >> mc->shift) - TEGRA210_MBDRC_MASTER_VOL_MIN); + + return 0; +} + +static int tegra210_mbdrc_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + int val = ucontrol->value.integer.value[0]; + bool change = false; + + val += TEGRA210_MBDRC_MASTER_VOL_MIN; + + regmap_update_bits_check(ope->mbdrc_regmap, mc->reg, + mc->max << mc->shift, val << mc->shift, + &change); + + regmap_read(ope->mbdrc_regmap, mc->reg, &val); + + return change ? 1 : 0; +} + +static const char * const tegra210_mbdrc_mode_text[] = { + "Bypass", "Fullband", "Dualband", "Multiband" +}; + +static const struct soc_enum tegra210_mbdrc_mode_enum = + SOC_ENUM_SINGLE(TEGRA210_MBDRC_CFG, TEGRA210_MBDRC_CFG_MBDRC_MODE_SHIFT, + 4, tegra210_mbdrc_mode_text); + +static const char * const tegra210_mbdrc_peak_rms_text[] = { + "Peak", "RMS" +}; + +static const struct soc_enum tegra210_mbdrc_peak_rms_enum = + SOC_ENUM_SINGLE(TEGRA210_MBDRC_CFG, TEGRA210_MBDRC_CFG_PEAK_RMS_SHIFT, + 2, tegra210_mbdrc_peak_rms_text); + +static const char * const tegra210_mbdrc_filter_structure_text[] = { + "All-pass-tree", "Flexible" +}; + +static const struct soc_enum tegra210_mbdrc_filter_structure_enum = + SOC_ENUM_SINGLE(TEGRA210_MBDRC_CFG, + TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_SHIFT, 2, + tegra210_mbdrc_filter_structure_text); + +static const char * const tegra210_mbdrc_frame_size_text[] = { + "N1", "N2", "N4", "N8", "N16", "N32", "N64" +}; + +static const struct soc_enum tegra210_mbdrc_frame_size_enum = + SOC_ENUM_SINGLE(TEGRA210_MBDRC_CFG, TEGRA210_MBDRC_CFG_FRAME_SIZE_SHIFT, + 7, tegra210_mbdrc_frame_size_text); + +#define TEGRA_MBDRC_BYTES_EXT(xname, xbase, xregs, xshift, xmask, xinfo) \ + TEGRA_SOC_BYTES_EXT(xname, xbase, xregs, xshift, xmask, \ + tegra210_mbdrc_band_params_get, \ + tegra210_mbdrc_band_params_put, \ + tegra210_mbdrc_param_info) + +#define TEGRA_MBDRC_BAND_BYTES_EXT(xname, xbase, xshift, xmask, xinfo) \ + TEGRA_MBDRC_BYTES_EXT(xname, xbase, TEGRA210_MBDRC_FILTER_COUNT, \ + xshift, xmask, xinfo) + +static const DECLARE_TLV_DB_MINMAX(mdbrc_vol_tlv, -25600, 25500); + +static const struct snd_kcontrol_new tegra210_mbdrc_controls[] = { + SOC_ENUM_EXT("MBDRC Peak RMS Mode", tegra210_mbdrc_peak_rms_enum, + tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum), + + SOC_ENUM_EXT("MBDRC Filter Structure", + tegra210_mbdrc_filter_structure_enum, + tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum), + + SOC_ENUM_EXT("MBDRC Frame Size", tegra210_mbdrc_frame_size_enum, + tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum), + + SOC_ENUM_EXT("MBDRC Mode", tegra210_mbdrc_mode_enum, + tegra210_mbdrc_get_enum, tegra210_mbdrc_put_enum), + + SOC_SINGLE_EXT("MBDRC RMS Offset", TEGRA210_MBDRC_CFG, + TEGRA210_MBDRC_CFG_RMS_OFFSET_SHIFT, 0x1ff, 0, + tegra210_mbdrc_get, tegra210_mbdrc_put), + + SOC_SINGLE_EXT("MBDRC Shift Control", TEGRA210_MBDRC_CFG, + TEGRA210_MBDRC_CFG_SHIFT_CTRL_SHIFT, 0x1f, 0, + tegra210_mbdrc_get, tegra210_mbdrc_put), + + SOC_SINGLE_EXT("MBDRC Fast Attack Factor", TEGRA210_MBDRC_FAST_FACTOR, + TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT, 0xffff, 0, + tegra210_mbdrc_get, tegra210_mbdrc_put), + + SOC_SINGLE_EXT("MBDRC Fast Release Factor", TEGRA210_MBDRC_FAST_FACTOR, + TEGRA210_MBDRC_FAST_FACTOR_RELEASE_SHIFT, 0xffff, 0, + tegra210_mbdrc_get, tegra210_mbdrc_put), + + SOC_SINGLE_RANGE_EXT_TLV("MBDRC Master Volume", + TEGRA210_MBDRC_MASTER_VOL, + TEGRA210_MBDRC_MASTER_VOL_SHIFT, + 0, 0x1ff, 0, + tegra210_mbdrc_vol_get, tegra210_mbdrc_vol_put, + mdbrc_vol_tlv), + + TEGRA_SOC_BYTES_EXT("MBDRC IIR Stages", TEGRA210_MBDRC_IIR_CFG, + TEGRA210_MBDRC_FILTER_COUNT, + TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_SHIFT, + TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_MASK, + tegra210_mbdrc_band_params_get, + tegra210_mbdrc_band_params_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC In Attack Time Const", TEGRA210_MBDRC_IN_ATTACK, + TEGRA210_MBDRC_FILTER_COUNT, + TEGRA210_MBDRC_IN_ATTACK_TC_SHIFT, + TEGRA210_MBDRC_IN_ATTACK_TC_MASK, + tegra210_mbdrc_band_params_get, + tegra210_mbdrc_band_params_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC In Release Time Const", TEGRA210_MBDRC_IN_RELEASE, + TEGRA210_MBDRC_FILTER_COUNT, + TEGRA210_MBDRC_IN_RELEASE_TC_SHIFT, + TEGRA210_MBDRC_IN_RELEASE_TC_MASK, + tegra210_mbdrc_band_params_get, + tegra210_mbdrc_band_params_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC Fast Attack Time Const", TEGRA210_MBDRC_FAST_ATTACK, + TEGRA210_MBDRC_FILTER_COUNT, + TEGRA210_MBDRC_FAST_ATTACK_TC_SHIFT, + TEGRA210_MBDRC_FAST_ATTACK_TC_MASK, + tegra210_mbdrc_band_params_get, + tegra210_mbdrc_band_params_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC In Threshold", TEGRA210_MBDRC_IN_THRESHOLD, + TEGRA210_MBDRC_FILTER_COUNT * 4, 0, 0xffffffff, + tegra210_mbdrc_threshold_get, + tegra210_mbdrc_threshold_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC Out Threshold", TEGRA210_MBDRC_OUT_THRESHOLD, + TEGRA210_MBDRC_FILTER_COUNT * 4, 0, 0xffffffff, + tegra210_mbdrc_threshold_get, + tegra210_mbdrc_threshold_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC Ratio", TEGRA210_MBDRC_RATIO_1ST, + TEGRA210_MBDRC_FILTER_COUNT * 5, + TEGRA210_MBDRC_RATIO_1ST_SHIFT, TEGRA210_MBDRC_RATIO_1ST_MASK, + tegra210_mbdrc_band_params_get, + tegra210_mbdrc_band_params_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC Makeup Gain", TEGRA210_MBDRC_MAKEUP_GAIN, + TEGRA210_MBDRC_FILTER_COUNT, + TEGRA210_MBDRC_MAKEUP_GAIN_SHIFT, + TEGRA210_MBDRC_MAKEUP_GAIN_MASK, + tegra210_mbdrc_band_params_get, + tegra210_mbdrc_band_params_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC Init Gain", TEGRA210_MBDRC_INIT_GAIN, + TEGRA210_MBDRC_FILTER_COUNT, + TEGRA210_MBDRC_INIT_GAIN_SHIFT, + TEGRA210_MBDRC_INIT_GAIN_MASK, + tegra210_mbdrc_band_params_get, + tegra210_mbdrc_band_params_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC Attack Gain", TEGRA210_MBDRC_GAIN_ATTACK, + TEGRA210_MBDRC_FILTER_COUNT, + TEGRA210_MBDRC_GAIN_ATTACK_SHIFT, + TEGRA210_MBDRC_GAIN_ATTACK_MASK, + tegra210_mbdrc_band_params_get, + tegra210_mbdrc_band_params_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC Release Gain", TEGRA210_MBDRC_GAIN_RELEASE, + TEGRA210_MBDRC_FILTER_COUNT, + TEGRA210_MBDRC_GAIN_RELEASE_SHIFT, + TEGRA210_MBDRC_GAIN_RELEASE_MASK, + tegra210_mbdrc_band_params_get, + tegra210_mbdrc_band_params_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC Fast Release Gain", + TEGRA210_MBDRC_FAST_RELEASE, + TEGRA210_MBDRC_FILTER_COUNT, + TEGRA210_MBDRC_FAST_RELEASE_SHIFT, + TEGRA210_MBDRC_FAST_RELEASE_MASK, + tegra210_mbdrc_band_params_get, + tegra210_mbdrc_band_params_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC Low Band Biquad Coeffs", + TEGRA210_MBDRC_CFG_RAM_CTRL, + TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5, 0, 0xffffffff, + tegra210_mbdrc_biquad_coeffs_get, + tegra210_mbdrc_biquad_coeffs_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC Mid Band Biquad Coeffs", + TEGRA210_MBDRC_CFG_RAM_CTRL + + TEGRA210_MBDRC_FILTER_PARAM_STRIDE, + TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5, 0, 0xffffffff, + tegra210_mbdrc_biquad_coeffs_get, + tegra210_mbdrc_biquad_coeffs_put, + tegra210_mbdrc_param_info), + + TEGRA_SOC_BYTES_EXT("MBDRC High Band Biquad Coeffs", + TEGRA210_MBDRC_CFG_RAM_CTRL + + (TEGRA210_MBDRC_FILTER_PARAM_STRIDE * 2), + TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5, 0, 0xffffffff, + tegra210_mbdrc_biquad_coeffs_get, + tegra210_mbdrc_biquad_coeffs_put, + tegra210_mbdrc_param_info), +}; + +static bool tegra210_mbdrc_wr_reg(struct device *dev, unsigned int reg) +{ + if (reg >= TEGRA210_MBDRC_IIR_CFG) + reg -= ((reg - TEGRA210_MBDRC_IIR_CFG) % + (TEGRA210_MBDRC_FILTER_PARAM_STRIDE * + TEGRA210_MBDRC_FILTER_COUNT)); + + switch (reg) { + case TEGRA210_MBDRC_SOFT_RESET: + case TEGRA210_MBDRC_CG: + case TEGRA210_MBDRC_CFG ... TEGRA210_MBDRC_CFG_RAM_DATA: + return true; + default: + return false; + } +} + +static bool tegra210_mbdrc_rd_reg(struct device *dev, unsigned int reg) +{ + if (tegra210_mbdrc_wr_reg(dev, reg)) + return true; + + if (reg >= TEGRA210_MBDRC_IIR_CFG) + reg -= ((reg - TEGRA210_MBDRC_IIR_CFG) % + (TEGRA210_MBDRC_FILTER_PARAM_STRIDE * + TEGRA210_MBDRC_FILTER_COUNT)); + + switch (reg) { + case TEGRA210_MBDRC_STATUS: + return true; + default: + return false; + } +} + +static bool tegra210_mbdrc_volatile_reg(struct device *dev, unsigned int reg) +{ + if (reg >= TEGRA210_MBDRC_IIR_CFG) + reg -= ((reg - TEGRA210_MBDRC_IIR_CFG) % + (TEGRA210_MBDRC_FILTER_PARAM_STRIDE * + TEGRA210_MBDRC_FILTER_COUNT)); + + switch (reg) { + case TEGRA210_MBDRC_SOFT_RESET: + case TEGRA210_MBDRC_STATUS: + case TEGRA210_MBDRC_CFG_RAM_CTRL: + case TEGRA210_MBDRC_CFG_RAM_DATA: + return true; + default: + return false; + } +} + +static bool tegra210_mbdrc_precious_reg(struct device *dev, unsigned int reg) +{ + if (reg >= TEGRA210_MBDRC_IIR_CFG) + reg -= ((reg - TEGRA210_MBDRC_IIR_CFG) % + (TEGRA210_MBDRC_FILTER_PARAM_STRIDE * + TEGRA210_MBDRC_FILTER_COUNT)); + + switch (reg) { + case TEGRA210_MBDRC_CFG_RAM_DATA: + return true; + default: + return false; + } +} + +static const struct regmap_config tegra210_mbdrc_regmap_cfg = { + .name = "mbdrc", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA210_MBDRC_MAX_REG, + .writeable_reg = tegra210_mbdrc_wr_reg, + .readable_reg = tegra210_mbdrc_rd_reg, + .volatile_reg = tegra210_mbdrc_volatile_reg, + .precious_reg = tegra210_mbdrc_precious_reg, + .reg_defaults = tegra210_mbdrc_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tegra210_mbdrc_reg_defaults), + .cache_type = REGCACHE_FLAT, +}; + +int tegra210_mbdrc_hw_params(struct snd_soc_component *cmpnt) +{ + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + const struct tegra210_mbdrc_config *conf = &mbdrc_init_config; + u32 val = 0; + unsigned int i; + + regmap_read(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, &val); + + if (val & TEGRA210_MBDRC_CFG_MBDRC_MODE_BYPASS) + return 0; + + for (i = 0; i < MBDRC_NUM_BAND; i++) { + const struct tegra210_mbdrc_band_params *params = + &conf->band_params[i]; + + u32 reg_off = i * TEGRA210_MBDRC_FILTER_PARAM_STRIDE; + + tegra210_mbdrc_write_ram(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_CFG_RAM_CTRL, + reg_off + TEGRA210_MBDRC_CFG_RAM_DATA, + 0, (u32 *)¶ms->biquad_params[0], + TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5); + } + return 0; +} + +int tegra210_mbdrc_component_init(struct snd_soc_component *cmpnt) +{ + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + const struct tegra210_mbdrc_config *conf = &mbdrc_init_config; + unsigned int i; + u32 val; + + pm_runtime_get_sync(cmpnt->dev); + + /* Initialize MBDRC registers and AHUB RAM with default params */ + regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, + TEGRA210_MBDRC_CFG_MBDRC_MODE_MASK, + conf->mode << TEGRA210_MBDRC_CFG_MBDRC_MODE_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, + TEGRA210_MBDRC_CFG_RMS_OFFSET_MASK, + conf->rms_off << TEGRA210_MBDRC_CFG_RMS_OFFSET_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, + TEGRA210_MBDRC_CFG_PEAK_RMS_MASK, + conf->peak_rms_mode << TEGRA210_MBDRC_CFG_PEAK_RMS_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, + TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_MASK, + conf->fliter_structure << + TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, + TEGRA210_MBDRC_CFG_SHIFT_CTRL_MASK, + conf->shift_ctrl << TEGRA210_MBDRC_CFG_SHIFT_CTRL_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CFG, + TEGRA210_MBDRC_CFG_FRAME_SIZE_MASK, + __ffs(conf->frame_size) << + TEGRA210_MBDRC_CFG_FRAME_SIZE_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_CHANNEL_MASK, + TEGRA210_MBDRC_CHANNEL_MASK_MASK, + conf->channel_mask << TEGRA210_MBDRC_CHANNEL_MASK_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_FAST_FACTOR, + TEGRA210_MBDRC_FAST_FACTOR_ATTACK_MASK, + conf->fa_factor << TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, TEGRA210_MBDRC_FAST_FACTOR, + TEGRA210_MBDRC_FAST_FACTOR_ATTACK_MASK, + conf->fr_factor << TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT); + + for (i = 0; i < MBDRC_NUM_BAND; i++) { + const struct tegra210_mbdrc_band_params *params = + &conf->band_params[i]; + u32 reg_off = i * TEGRA210_MBDRC_FILTER_PARAM_STRIDE; + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_IIR_CFG, + TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_MASK, + params->iir_stages << + TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_IN_ATTACK, + TEGRA210_MBDRC_IN_ATTACK_TC_MASK, + params->in_attack_tc << + TEGRA210_MBDRC_IN_ATTACK_TC_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_IN_RELEASE, + TEGRA210_MBDRC_IN_RELEASE_TC_MASK, + params->in_release_tc << + TEGRA210_MBDRC_IN_RELEASE_TC_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_FAST_ATTACK, + TEGRA210_MBDRC_FAST_ATTACK_TC_MASK, + params->fast_attack_tc << + TEGRA210_MBDRC_FAST_ATTACK_TC_SHIFT); + + val = (((params->in_threshold[0] >> + TEGRA210_MBDRC_THRESH_1ST_SHIFT) & + TEGRA210_MBDRC_THRESH_1ST_MASK) | + ((params->in_threshold[1] >> + TEGRA210_MBDRC_THRESH_2ND_SHIFT) & + TEGRA210_MBDRC_THRESH_2ND_MASK) | + ((params->in_threshold[2] >> + TEGRA210_MBDRC_THRESH_3RD_SHIFT) & + TEGRA210_MBDRC_THRESH_3RD_MASK) | + ((params->in_threshold[3] >> + TEGRA210_MBDRC_THRESH_4TH_SHIFT) & + TEGRA210_MBDRC_THRESH_4TH_MASK)); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_IN_THRESHOLD, + 0xffffffff, val); + + val = (((params->out_threshold[0] >> + TEGRA210_MBDRC_THRESH_1ST_SHIFT) & + TEGRA210_MBDRC_THRESH_1ST_MASK) | + ((params->out_threshold[1] >> + TEGRA210_MBDRC_THRESH_2ND_SHIFT) & + TEGRA210_MBDRC_THRESH_2ND_MASK) | + ((params->out_threshold[2] >> + TEGRA210_MBDRC_THRESH_3RD_SHIFT) & + TEGRA210_MBDRC_THRESH_3RD_MASK) | + ((params->out_threshold[3] >> + TEGRA210_MBDRC_THRESH_4TH_SHIFT) & + TEGRA210_MBDRC_THRESH_4TH_MASK)); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_OUT_THRESHOLD, + 0xffffffff, val); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_RATIO_1ST, + TEGRA210_MBDRC_RATIO_1ST_MASK, + params->ratio[0] << TEGRA210_MBDRC_RATIO_1ST_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_RATIO_2ND, + TEGRA210_MBDRC_RATIO_2ND_MASK, + params->ratio[1] << TEGRA210_MBDRC_RATIO_2ND_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_RATIO_3RD, + TEGRA210_MBDRC_RATIO_3RD_MASK, + params->ratio[2] << TEGRA210_MBDRC_RATIO_3RD_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_RATIO_4TH, + TEGRA210_MBDRC_RATIO_4TH_MASK, + params->ratio[3] << TEGRA210_MBDRC_RATIO_4TH_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_RATIO_5TH, + TEGRA210_MBDRC_RATIO_5TH_MASK, + params->ratio[4] << TEGRA210_MBDRC_RATIO_5TH_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_MAKEUP_GAIN, + TEGRA210_MBDRC_MAKEUP_GAIN_MASK, + params->makeup_gain << + TEGRA210_MBDRC_MAKEUP_GAIN_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_INIT_GAIN, + TEGRA210_MBDRC_INIT_GAIN_MASK, + params->gain_init << + TEGRA210_MBDRC_INIT_GAIN_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_GAIN_ATTACK, + TEGRA210_MBDRC_GAIN_ATTACK_MASK, + params->gain_attack_tc << + TEGRA210_MBDRC_GAIN_ATTACK_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_GAIN_RELEASE, + TEGRA210_MBDRC_GAIN_RELEASE_MASK, + params->gain_release_tc << + TEGRA210_MBDRC_GAIN_RELEASE_SHIFT); + + regmap_update_bits(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_FAST_RELEASE, + TEGRA210_MBDRC_FAST_RELEASE_MASK, + params->fast_release_tc << + TEGRA210_MBDRC_FAST_RELEASE_SHIFT); + + tegra210_mbdrc_write_ram(ope->mbdrc_regmap, + reg_off + TEGRA210_MBDRC_CFG_RAM_CTRL, + reg_off + TEGRA210_MBDRC_CFG_RAM_DATA, 0, + (u32 *)¶ms->biquad_params[0], + TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5); + } + + pm_runtime_put_sync(cmpnt->dev); + + snd_soc_add_component_controls(cmpnt, tegra210_mbdrc_controls, + ARRAY_SIZE(tegra210_mbdrc_controls)); + + return 0; +} + +int tegra210_mbdrc_regmap_init(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tegra210_ope *ope = dev_get_drvdata(dev); + struct device_node *child; + struct resource mem; + void __iomem *regs; + int err; + + child = of_get_child_by_name(dev->of_node, "dynamic-range-compressor"); + if (!child) + return -ENODEV; + + err = of_address_to_resource(child, 0, &mem); + of_node_put(child); + if (err < 0) { + dev_err(dev, "fail to get MBDRC resource\n"); + return err; + } + + mem.flags = IORESOURCE_MEM; + regs = devm_ioremap_resource(dev, &mem); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + ope->mbdrc_regmap = devm_regmap_init_mmio(dev, regs, + &tegra210_mbdrc_regmap_cfg); + if (IS_ERR(ope->mbdrc_regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(ope->mbdrc_regmap); + } + + regcache_cache_only(ope->mbdrc_regmap, true); + + return 0; +} diff --git a/sound/soc/tegra/tegra210_mbdrc.h b/sound/soc/tegra/tegra210_mbdrc.h new file mode 100644 index 000000000000..4c48da0e1dea --- /dev/null +++ b/sound/soc/tegra/tegra210_mbdrc.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra210_mbdrc.h - Definitions for Tegra210 MBDRC driver + * + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA210_MBDRC_H__ +#define __TEGRA210_MBDRC_H__ + +#include +#include + +/* Register offsets from TEGRA210_MBDRC*_BASE */ +#define TEGRA210_MBDRC_SOFT_RESET 0x4 +#define TEGRA210_MBDRC_CG 0x8 +#define TEGRA210_MBDRC_STATUS 0xc +#define TEGRA210_MBDRC_CFG 0x28 +#define TEGRA210_MBDRC_CHANNEL_MASK 0x2c +#define TEGRA210_MBDRC_MASTER_VOL 0x30 +#define TEGRA210_MBDRC_FAST_FACTOR 0x34 + +#define TEGRA210_MBDRC_FILTER_COUNT 3 +#define TEGRA210_MBDRC_FILTER_PARAM_STRIDE 0x4 + +#define TEGRA210_MBDRC_IIR_CFG 0x38 +#define TEGRA210_MBDRC_IN_ATTACK 0x44 +#define TEGRA210_MBDRC_IN_RELEASE 0x50 +#define TEGRA210_MBDRC_FAST_ATTACK 0x5c +#define TEGRA210_MBDRC_IN_THRESHOLD 0x68 +#define TEGRA210_MBDRC_OUT_THRESHOLD 0x74 +#define TEGRA210_MBDRC_RATIO_1ST 0x80 +#define TEGRA210_MBDRC_RATIO_2ND 0x8c +#define TEGRA210_MBDRC_RATIO_3RD 0x98 +#define TEGRA210_MBDRC_RATIO_4TH 0xa4 +#define TEGRA210_MBDRC_RATIO_5TH 0xb0 +#define TEGRA210_MBDRC_MAKEUP_GAIN 0xbc +#define TEGRA210_MBDRC_INIT_GAIN 0xc8 +#define TEGRA210_MBDRC_GAIN_ATTACK 0xd4 +#define TEGRA210_MBDRC_GAIN_RELEASE 0xe0 +#define TEGRA210_MBDRC_FAST_RELEASE 0xec +#define TEGRA210_MBDRC_CFG_RAM_CTRL 0xf8 +#define TEGRA210_MBDRC_CFG_RAM_DATA 0x104 + +#define TEGRA210_MBDRC_MAX_REG (TEGRA210_MBDRC_CFG_RAM_DATA + \ + (TEGRA210_MBDRC_FILTER_PARAM_STRIDE * \ + (TEGRA210_MBDRC_FILTER_COUNT - 1))) + +/* Fields for TEGRA210_MBDRC_CFG */ +#define TEGRA210_MBDRC_CFG_RMS_OFFSET_SHIFT 16 +#define TEGRA210_MBDRC_CFG_RMS_OFFSET_MASK (0x1ff << TEGRA210_MBDRC_CFG_RMS_OFFSET_SHIFT) + +#define TEGRA210_MBDRC_CFG_PEAK_RMS_SHIFT 14 +#define TEGRA210_MBDRC_CFG_PEAK_RMS_MASK (0x1 << TEGRA210_MBDRC_CFG_PEAK_RMS_SHIFT) +#define TEGRA210_MBDRC_CFG_PEAK (1 << TEGRA210_MBDRC_CFG_PEAK_RMS_SHIFT) + +#define TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_SHIFT 13 +#define TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_MASK (0x1 << TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_SHIFT) +#define TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_FLEX (1 << TEGRA210_MBDRC_CFG_FILTER_STRUCTURE_SHIFT) + +#define TEGRA210_MBDRC_CFG_SHIFT_CTRL_SHIFT 8 +#define TEGRA210_MBDRC_CFG_SHIFT_CTRL_MASK (0x1f << TEGRA210_MBDRC_CFG_SHIFT_CTRL_SHIFT) + +#define TEGRA210_MBDRC_CFG_FRAME_SIZE_SHIFT 4 +#define TEGRA210_MBDRC_CFG_FRAME_SIZE_MASK (0xf << TEGRA210_MBDRC_CFG_FRAME_SIZE_SHIFT) + +#define TEGRA210_MBDRC_CFG_MBDRC_MODE_SHIFT 0 +#define TEGRA210_MBDRC_CFG_MBDRC_MODE_MASK (0x3 << TEGRA210_MBDRC_CFG_MBDRC_MODE_SHIFT) +#define TEGRA210_MBDRC_CFG_MBDRC_MODE_BYPASS (0 << TEGRA210_MBDRC_CFG_MBDRC_MODE_SHIFT) + +/* Fields for TEGRA210_MBDRC_CHANNEL_MASK */ +#define TEGRA210_MBDRC_CHANNEL_MASK_SHIFT 0 +#define TEGRA210_MBDRC_CHANNEL_MASK_MASK (0xff << TEGRA210_MBDRC_CHANNEL_MASK_SHIFT) + +/* Fields for TEGRA210_MBDRC_MASTER_VOL */ +#define TEGRA210_MBDRC_MASTER_VOL_SHIFT 23 +#define TEGRA210_MBDRC_MASTER_VOL_MIN -256 +#define TEGRA210_MBDRC_MASTER_VOL_MAX 256 + +/* Fields for TEGRA210_MBDRC_FAST_FACTOR */ +#define TEGRA210_MBDRC_FAST_FACTOR_RELEASE_SHIFT 16 +#define TEGRA210_MBDRC_FAST_FACTOR_RELEASE_MASK (0xffff << TEGRA210_MBDRC_FAST_FACTOR_RELEASE_SHIFT) + +#define TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT 0 +#define TEGRA210_MBDRC_FAST_FACTOR_ATTACK_MASK (0xffff << TEGRA210_MBDRC_FAST_FACTOR_ATTACK_SHIFT) + +/* Fields for TEGRA210_MBDRC_IIR_CFG */ +#define TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_SHIFT 0 +#define TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_MASK (0xf << TEGRA210_MBDRC_IIR_CFG_NUM_STAGES_SHIFT) + +/* Fields for TEGRA210_MBDRC_IN_ATTACK */ +#define TEGRA210_MBDRC_IN_ATTACK_TC_SHIFT 0 +#define TEGRA210_MBDRC_IN_ATTACK_TC_MASK (0xffffffff << TEGRA210_MBDRC_IN_ATTACK_TC_SHIFT) + +/* Fields for TEGRA210_MBDRC_IN_RELEASE */ +#define TEGRA210_MBDRC_IN_RELEASE_TC_SHIFT 0 +#define TEGRA210_MBDRC_IN_RELEASE_TC_MASK (0xffffffff << TEGRA210_MBDRC_IN_RELEASE_TC_SHIFT) + +/* Fields for TEGRA210_MBDRC_FAST_ATTACK */ +#define TEGRA210_MBDRC_FAST_ATTACK_TC_SHIFT 0 +#define TEGRA210_MBDRC_FAST_ATTACK_TC_MASK (0xffffffff << TEGRA210_MBDRC_FAST_ATTACK_TC_SHIFT) + +/* Fields for TEGRA210_MBDRC_IN_THRESHOLD / TEGRA210_MBDRC_OUT_THRESHOLD */ +#define TEGRA210_MBDRC_THRESH_4TH_SHIFT 24 +#define TEGRA210_MBDRC_THRESH_4TH_MASK (0xff << TEGRA210_MBDRC_THRESH_4TH_SHIFT) + +#define TEGRA210_MBDRC_THRESH_3RD_SHIFT 16 +#define TEGRA210_MBDRC_THRESH_3RD_MASK (0xff << TEGRA210_MBDRC_THRESH_3RD_SHIFT) + +#define TEGRA210_MBDRC_THRESH_2ND_SHIFT 8 +#define TEGRA210_MBDRC_THRESH_2ND_MASK (0xff << TEGRA210_MBDRC_THRESH_2ND_SHIFT) + +#define TEGRA210_MBDRC_THRESH_1ST_SHIFT 0 +#define TEGRA210_MBDRC_THRESH_1ST_MASK (0xff << TEGRA210_MBDRC_THRESH_1ST_SHIFT) + +/* Fields for TEGRA210_MBDRC_RATIO_1ST */ +#define TEGRA210_MBDRC_RATIO_1ST_SHIFT 0 +#define TEGRA210_MBDRC_RATIO_1ST_MASK (0xffff << TEGRA210_MBDRC_RATIO_1ST_SHIFT) + +/* Fields for TEGRA210_MBDRC_RATIO_2ND */ +#define TEGRA210_MBDRC_RATIO_2ND_SHIFT 0 +#define TEGRA210_MBDRC_RATIO_2ND_MASK (0xffff << TEGRA210_MBDRC_RATIO_2ND_SHIFT) + +/* Fields for TEGRA210_MBDRC_RATIO_3RD */ +#define TEGRA210_MBDRC_RATIO_3RD_SHIFT 0 +#define TEGRA210_MBDRC_RATIO_3RD_MASK (0xffff << TEGRA210_MBDRC_RATIO_3RD_SHIFT) + +/* Fields for TEGRA210_MBDRC_RATIO_4TH */ +#define TEGRA210_MBDRC_RATIO_4TH_SHIFT 0 +#define TEGRA210_MBDRC_RATIO_4TH_MASK (0xffff << TEGRA210_MBDRC_RATIO_4TH_SHIFT) + +/* Fields for TEGRA210_MBDRC_RATIO_5TH */ +#define TEGRA210_MBDRC_RATIO_5TH_SHIFT 0 +#define TEGRA210_MBDRC_RATIO_5TH_MASK (0xffff << TEGRA210_MBDRC_RATIO_5TH_SHIFT) + +/* Fields for TEGRA210_MBDRC_MAKEUP_GAIN */ +#define TEGRA210_MBDRC_MAKEUP_GAIN_SHIFT 0 +#define TEGRA210_MBDRC_MAKEUP_GAIN_MASK (0x3f << TEGRA210_MBDRC_MAKEUP_GAIN_SHIFT) + +/* Fields for TEGRA210_MBDRC_INIT_GAIN */ +#define TEGRA210_MBDRC_INIT_GAIN_SHIFT 0 +#define TEGRA210_MBDRC_INIT_GAIN_MASK (0xffffffff << TEGRA210_MBDRC_INIT_GAIN_SHIFT) + +/* Fields for TEGRA210_MBDRC_GAIN_ATTACK */ +#define TEGRA210_MBDRC_GAIN_ATTACK_SHIFT 0 +#define TEGRA210_MBDRC_GAIN_ATTACK_MASK (0xffffffff << TEGRA210_MBDRC_GAIN_ATTACK_SHIFT) + +/* Fields for TEGRA210_MBDRC_GAIN_RELEASE */ +#define TEGRA210_MBDRC_GAIN_RELEASE_SHIFT 0 +#define TEGRA210_MBDRC_GAIN_RELEASE_MASK (0xffffffff << TEGRA210_MBDRC_GAIN_RELEASE_SHIFT) + +/* Fields for TEGRA210_MBDRC_FAST_RELEASE */ +#define TEGRA210_MBDRC_FAST_RELEASE_SHIFT 0 +#define TEGRA210_MBDRC_FAST_RELEASE_MASK (0xffffffff << TEGRA210_MBDRC_FAST_RELEASE_SHIFT) + +#define TEGRA210_MBDRC_RAM_CTRL_RW_READ 0 +#define TEGRA210_MBDRC_RAM_CTRL_RW_WRITE (1 << 14) +#define TEGRA210_MBDRC_RAM_CTRL_ADDR_INIT_EN (1 << 13) +#define TEGRA210_MBDRC_RAM_CTRL_SEQ_ACCESS_EN (1 << 12) +#define TEGRA210_MBDRC_RAM_CTRL_RAM_ADDR_MASK 0x1ff + +/* + * Order and size of each structure element for following structures should not + * be altered size order of elements and their size are based on PEQ co-eff ram + * and shift ram layout. + */ +#define TEGRA210_MBDRC_THRESHOLD_NUM 4 +#define TEGRA210_MBDRC_RATIO_NUM (TEGRA210_MBDRC_THRESHOLD_NUM + 1) +#define TEGRA210_MBDRC_MAX_BIQUAD_STAGES 8 + +/* Order of these enums are same as the order of band specific hw registers */ +enum { + MBDRC_LOW_BAND, + MBDRC_MID_BAND, + MBDRC_HIGH_BAND, + MBDRC_NUM_BAND, +}; + +struct tegra210_mbdrc_band_params { + u32 band; + u32 iir_stages; + u32 in_attack_tc; + u32 in_release_tc; + u32 fast_attack_tc; + u32 in_threshold[TEGRA210_MBDRC_THRESHOLD_NUM]; + u32 out_threshold[TEGRA210_MBDRC_THRESHOLD_NUM]; + u32 ratio[TEGRA210_MBDRC_RATIO_NUM]; + u32 makeup_gain; + u32 gain_init; + u32 gain_attack_tc; + u32 gain_release_tc; + u32 fast_release_tc; + /* For biquad_params[][5] order of coeff is b0, b1, a0, a1, a2 */ + u32 biquad_params[TEGRA210_MBDRC_MAX_BIQUAD_STAGES * 5]; +}; + +struct tegra210_mbdrc_config { + unsigned int mode; + unsigned int rms_off; + unsigned int peak_rms_mode; + unsigned int fliter_structure; + unsigned int shift_ctrl; + unsigned int frame_size; + unsigned int channel_mask; + unsigned int fa_factor; /* Fast attack factor */ + unsigned int fr_factor; /* Fast release factor */ + struct tegra210_mbdrc_band_params band_params[MBDRC_NUM_BAND]; +}; + +int tegra210_mbdrc_regmap_init(struct platform_device *pdev); +int tegra210_mbdrc_component_init(struct snd_soc_component *cmpnt); +int tegra210_mbdrc_hw_params(struct snd_soc_component *cmpnt); + +#endif diff --git a/sound/soc/tegra/tegra210_ope.c b/sound/soc/tegra/tegra210_ope.c new file mode 100644 index 000000000000..3dd2bdec657b --- /dev/null +++ b/sound/soc/tegra/tegra210_ope.c @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra210_ope.c - Tegra210 OPE driver +// +// Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tegra210_mbdrc.h" +#include "tegra210_ope.h" +#include "tegra210_peq.h" +#include "tegra_cif.h" + +static const struct reg_default tegra210_ope_reg_defaults[] = { + { TEGRA210_OPE_RX_INT_MASK, 0x00000001}, + { TEGRA210_OPE_RX_CIF_CTRL, 0x00007700}, + { TEGRA210_OPE_TX_INT_MASK, 0x00000001}, + { TEGRA210_OPE_TX_CIF_CTRL, 0x00007700}, + { TEGRA210_OPE_CG, 0x1}, +}; + +static int tegra210_ope_set_audio_cif(struct tegra210_ope *ope, + struct snd_pcm_hw_params *params, + unsigned int reg) +{ + int channels, audio_bits; + struct tegra_cif_conf cif_conf; + + memset(&cif_conf, 0, sizeof(struct tegra_cif_conf)); + + channels = params_channels(params); + if (channels < 2) + return -EINVAL; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + audio_bits = TEGRA_ACIF_BITS_16; + break; + case SNDRV_PCM_FORMAT_S32_LE: + audio_bits = TEGRA_ACIF_BITS_32; + break; + default: + return -EINVAL; + } + + cif_conf.audio_ch = channels; + cif_conf.client_ch = channels; + cif_conf.audio_bits = audio_bits; + cif_conf.client_bits = audio_bits; + + tegra_set_cif(ope->regmap, reg, &cif_conf); + + return 0; +} + +static int tegra210_ope_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct device *dev = dai->dev; + struct tegra210_ope *ope = snd_soc_dai_get_drvdata(dai); + int err; + + /* Set RX and TX CIF */ + err = tegra210_ope_set_audio_cif(ope, params, + TEGRA210_OPE_RX_CIF_CTRL); + if (err) { + dev_err(dev, "Can't set OPE RX CIF: %d\n", err); + return err; + } + + err = tegra210_ope_set_audio_cif(ope, params, + TEGRA210_OPE_TX_CIF_CTRL); + if (err) { + dev_err(dev, "Can't set OPE TX CIF: %d\n", err); + return err; + } + + tegra210_mbdrc_hw_params(dai->component); + + return err; +} + +static int tegra210_ope_component_probe(struct snd_soc_component *cmpnt) +{ + struct tegra210_ope *ope = dev_get_drvdata(cmpnt->dev); + + tegra210_peq_component_init(cmpnt); + tegra210_mbdrc_component_init(cmpnt); + + /* + * The OPE, PEQ and MBDRC functionalities are combined under one + * device registered by OPE driver. In fact OPE HW block includes + * sub blocks PEQ and MBDRC. However driver registers separate + * regmap interfaces for each of these. ASoC core depends on + * dev_get_regmap() to populate the regmap field for a given ASoC + * component. A component can have one regmap reference and since + * the DAPM routes depend on OPE regmap only, below explicit + * assignment is done to highlight this. This is needed for ASoC + * core to access correct regmap during DAPM path setup. + */ + snd_soc_component_init_regmap(cmpnt, ope->regmap); + + return 0; +} + +static const struct snd_soc_dai_ops tegra210_ope_dai_ops = { + .hw_params = tegra210_ope_hw_params, +}; + +static struct snd_soc_dai_driver tegra210_ope_dais[] = { + { + .name = "OPE-RX-CIF", + .playback = { + .stream_name = "RX-CIF-Playback", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = { + .stream_name = "RX-CIF-Capture", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + }, + { + .name = "OPE-TX-CIF", + .playback = { + .stream_name = "TX-CIF-Playback", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = { + .stream_name = "TX-CIF-Capture", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &tegra210_ope_dai_ops, + } +}; + +static const struct snd_soc_dapm_widget tegra210_ope_widgets[] = { + SND_SOC_DAPM_AIF_IN("RX", NULL, 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("TX", NULL, 0, TEGRA210_OPE_ENABLE, + TEGRA210_OPE_EN_SHIFT, 0), +}; + +#define OPE_ROUTES(sname) \ + { "RX XBAR-" sname, NULL, "XBAR-TX" }, \ + { "RX-CIF-" sname, NULL, "RX XBAR-" sname }, \ + { "RX", NULL, "RX-CIF-" sname }, \ + { "TX-CIF-" sname, NULL, "TX" }, \ + { "TX XBAR-" sname, NULL, "TX-CIF-" sname }, \ + { "XBAR-RX", NULL, "TX XBAR-" sname } + +static const struct snd_soc_dapm_route tegra210_ope_routes[] = { + { "TX", NULL, "RX" }, + OPE_ROUTES("Playback"), + OPE_ROUTES("Capture"), +}; + +static const char * const tegra210_ope_data_dir_text[] = { + "MBDRC to PEQ", + "PEQ to MBDRC" +}; + +static const struct soc_enum tegra210_ope_data_dir_enum = + SOC_ENUM_SINGLE(TEGRA210_OPE_DIR, TEGRA210_OPE_DIR_SHIFT, + 2, tegra210_ope_data_dir_text); + +static int tegra210_ope_get_data_dir(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + + ucontrol->value.enumerated.item[0] = ope->data_dir; + + return 0; +} + +static int tegra210_ope_put_data_dir(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + unsigned int value = ucontrol->value.enumerated.item[0]; + + if (value == ope->data_dir) + return 0; + + ope->data_dir = value; + + return 1; +} + +static const struct snd_kcontrol_new tegra210_ope_controls[] = { + SOC_ENUM_EXT("Data Flow Direction", tegra210_ope_data_dir_enum, + tegra210_ope_get_data_dir, tegra210_ope_put_data_dir), +}; + +static const struct snd_soc_component_driver tegra210_ope_cmpnt = { + .probe = tegra210_ope_component_probe, + .dapm_widgets = tegra210_ope_widgets, + .num_dapm_widgets = ARRAY_SIZE(tegra210_ope_widgets), + .dapm_routes = tegra210_ope_routes, + .num_dapm_routes = ARRAY_SIZE(tegra210_ope_routes), + .controls = tegra210_ope_controls, + .num_controls = ARRAY_SIZE(tegra210_ope_controls), +}; + +static bool tegra210_ope_wr_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_OPE_RX_INT_MASK ... TEGRA210_OPE_RX_CIF_CTRL: + case TEGRA210_OPE_TX_INT_MASK ... TEGRA210_OPE_TX_CIF_CTRL: + case TEGRA210_OPE_ENABLE ... TEGRA210_OPE_CG: + case TEGRA210_OPE_DIR: + return true; + default: + return false; + } +} + +static bool tegra210_ope_rd_reg(struct device *dev, unsigned int reg) +{ + if (tegra210_ope_wr_reg(dev, reg)) + return true; + + switch (reg) { + case TEGRA210_OPE_RX_STATUS: + case TEGRA210_OPE_RX_INT_STATUS: + case TEGRA210_OPE_TX_STATUS: + case TEGRA210_OPE_TX_INT_STATUS: + case TEGRA210_OPE_STATUS: + case TEGRA210_OPE_INT_STATUS: + return true; + default: + return false; + } +} + +static bool tegra210_ope_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_OPE_RX_STATUS: + case TEGRA210_OPE_RX_INT_STATUS: + case TEGRA210_OPE_TX_STATUS: + case TEGRA210_OPE_TX_INT_STATUS: + case TEGRA210_OPE_SOFT_RESET: + case TEGRA210_OPE_STATUS: + case TEGRA210_OPE_INT_STATUS: + return true; + default: + return false; + } +} + +static const struct regmap_config tegra210_ope_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA210_OPE_DIR, + .writeable_reg = tegra210_ope_wr_reg, + .readable_reg = tegra210_ope_rd_reg, + .volatile_reg = tegra210_ope_volatile_reg, + .reg_defaults = tegra210_ope_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tegra210_ope_reg_defaults), + .cache_type = REGCACHE_FLAT, +}; + +static int tegra210_ope_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tegra210_ope *ope; + void __iomem *regs; + int err; + + ope = devm_kzalloc(dev, sizeof(*ope), GFP_KERNEL); + if (!ope) + return -ENOMEM; + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); + + ope->regmap = devm_regmap_init_mmio(dev, regs, + &tegra210_ope_regmap_config); + if (IS_ERR(ope->regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(ope->regmap); + } + + regcache_cache_only(ope->regmap, true); + + dev_set_drvdata(dev, ope); + + err = tegra210_peq_regmap_init(pdev); + if (err < 0) { + dev_err(dev, "PEQ init failed\n"); + return err; + } + + err = tegra210_mbdrc_regmap_init(pdev); + if (err < 0) { + dev_err(dev, "MBDRC init failed\n"); + return err; + } + + err = devm_snd_soc_register_component(dev, &tegra210_ope_cmpnt, + tegra210_ope_dais, + ARRAY_SIZE(tegra210_ope_dais)); + if (err) { + dev_err(dev, "can't register OPE component, err: %d\n", err); + return err; + } + + pm_runtime_enable(dev); + + return 0; +} + +static int tegra210_ope_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static int __maybe_unused tegra210_ope_runtime_suspend(struct device *dev) +{ + struct tegra210_ope *ope = dev_get_drvdata(dev); + + tegra210_peq_save(ope->peq_regmap, ope->peq_biquad_gains, + ope->peq_biquad_shifts); + + regcache_cache_only(ope->mbdrc_regmap, true); + regcache_cache_only(ope->peq_regmap, true); + regcache_cache_only(ope->regmap, true); + + regcache_mark_dirty(ope->regmap); + regcache_mark_dirty(ope->peq_regmap); + regcache_mark_dirty(ope->mbdrc_regmap); + + return 0; +} + +static int __maybe_unused tegra210_ope_runtime_resume(struct device *dev) +{ + struct tegra210_ope *ope = dev_get_drvdata(dev); + + regcache_cache_only(ope->regmap, false); + regcache_cache_only(ope->peq_regmap, false); + regcache_cache_only(ope->mbdrc_regmap, false); + + regcache_sync(ope->regmap); + regcache_sync(ope->peq_regmap); + regcache_sync(ope->mbdrc_regmap); + + tegra210_peq_restore(ope->peq_regmap, ope->peq_biquad_gains, + ope->peq_biquad_shifts); + + return 0; +} + +static const struct dev_pm_ops tegra210_ope_pm_ops = { + SET_RUNTIME_PM_OPS(tegra210_ope_runtime_suspend, + tegra210_ope_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static const struct of_device_id tegra210_ope_of_match[] = { + { .compatible = "nvidia,tegra210-ope" }, + {}, +}; +MODULE_DEVICE_TABLE(of, tegra210_ope_of_match); + +static struct platform_driver tegra210_ope_driver = { + .driver = { + .name = "tegra210-ope", + .of_match_table = tegra210_ope_of_match, + .pm = &tegra210_ope_pm_ops, + }, + .probe = tegra210_ope_probe, + .remove = tegra210_ope_remove, +}; +module_platform_driver(tegra210_ope_driver) + +MODULE_AUTHOR("Sumit Bhattacharya "); +MODULE_DESCRIPTION("Tegra210 OPE ASoC driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/tegra/tegra210_ope.h b/sound/soc/tegra/tegra210_ope.h new file mode 100644 index 000000000000..2835af6ce631 --- /dev/null +++ b/sound/soc/tegra/tegra210_ope.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra210_ope.h - Definitions for Tegra210 OPE driver + * + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA210_OPE_H__ +#define __TEGRA210_OPE_H__ + +#include +#include + +#include "tegra210_peq.h" + +/* + * OPE_RX registers are with respect to XBAR. + * The data comes from XBAR to OPE + */ +#define TEGRA210_OPE_RX_STATUS 0xc +#define TEGRA210_OPE_RX_INT_STATUS 0x10 +#define TEGRA210_OPE_RX_INT_MASK 0x14 +#define TEGRA210_OPE_RX_INT_SET 0x18 +#define TEGRA210_OPE_RX_INT_CLEAR 0x1c +#define TEGRA210_OPE_RX_CIF_CTRL 0x20 + +/* + * OPE_TX registers are with respect to XBAR. + * The data goes out from OPE to XBAR + */ +#define TEGRA210_OPE_TX_STATUS 0x4c +#define TEGRA210_OPE_TX_INT_STATUS 0x50 +#define TEGRA210_OPE_TX_INT_MASK 0x54 +#define TEGRA210_OPE_TX_INT_SET 0x58 +#define TEGRA210_OPE_TX_INT_CLEAR 0x5c +#define TEGRA210_OPE_TX_CIF_CTRL 0x60 + +/* OPE Gloabal registers */ +#define TEGRA210_OPE_ENABLE 0x80 +#define TEGRA210_OPE_SOFT_RESET 0x84 +#define TEGRA210_OPE_CG 0x88 +#define TEGRA210_OPE_STATUS 0x8c +#define TEGRA210_OPE_INT_STATUS 0x90 +#define TEGRA210_OPE_DIR 0x94 + +/* Fields for TEGRA210_OPE_ENABLE */ +#define TEGRA210_OPE_EN_SHIFT 0 +#define TEGRA210_OPE_EN (1 << TEGRA210_OPE_EN_SHIFT) + +/* Fields for TEGRA210_OPE_SOFT_RESET */ +#define TEGRA210_OPE_SOFT_RESET_SHIFT 0 +#define TEGRA210_OPE_SOFT_RESET_EN (1 << TEGRA210_OPE_SOFT_RESET_SHIFT) + +#define TEGRA210_OPE_DIR_SHIFT 0 + +struct tegra210_ope { + struct regmap *regmap; + struct regmap *peq_regmap; + struct regmap *mbdrc_regmap; + u32 peq_biquad_gains[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH]; + u32 peq_biquad_shifts[TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH]; + unsigned int data_dir; +}; + +/* Extension of soc_bytes structure defined in sound/soc.h */ +struct tegra_soc_bytes { + struct soc_bytes soc; + u32 shift; /* Used as offset for AHUB RAM related programing */ +}; + +/* Utility structures for using mixer control of type snd_soc_bytes */ +#define TEGRA_SOC_BYTES_EXT(xname, xbase, xregs, xshift, xmask, \ + xhandler_get, xhandler_put, xinfo) \ +{ \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .info = xinfo, \ + .get = xhandler_get, \ + .put = xhandler_put, \ + .private_value = ((unsigned long)&(struct tegra_soc_bytes) \ + { \ + .soc.base = xbase, \ + .soc.num_regs = xregs, \ + .soc.mask = xmask, \ + .shift = xshift \ + }) \ +} + +#endif diff --git a/sound/soc/tegra/tegra210_peq.c b/sound/soc/tegra/tegra210_peq.c new file mode 100644 index 000000000000..205d956abb42 --- /dev/null +++ b/sound/soc/tegra/tegra210_peq.c @@ -0,0 +1,434 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// tegra210_peq.c - Tegra210 PEQ driver +// +// Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tegra210_ope.h" +#include "tegra210_peq.h" + +static const struct reg_default tegra210_peq_reg_defaults[] = { + { TEGRA210_PEQ_CFG, 0x00000013}, + { TEGRA210_PEQ_CFG_RAM_CTRL, 0x00004000}, + { TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, 0x00004000}, +}; + +static const u32 biquad_init_gains[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH] = { + 1495012349, /* Pre-gain */ + + /* Gains : b0, b1, a0, a1, a2 */ + 536870912, -1073741824, 536870912, 2143508246, -1069773768, /* Band-0 */ + 134217728, -265414508, 131766272, 2140402222, -1071252997, /* Band-1 */ + 268435456, -233515765, -33935948, 1839817267, -773826124, /* Band-2 */ + 536870912, -672537913, 139851540, 1886437554, -824433167, /* Band-3 */ + 268435456, -114439279, 173723964, 205743566, 278809729, /* Band-4 */ + 1, 0, 0, 0, 0, /* Band-5 */ + 1, 0, 0, 0, 0, /* Band-6 */ + 1, 0, 0, 0, 0, /* Band-7 */ + 1, 0, 0, 0, 0, /* Band-8 */ + 1, 0, 0, 0, 0, /* Band-9 */ + 1, 0, 0, 0, 0, /* Band-10 */ + 1, 0, 0, 0, 0, /* Band-11 */ + + 963423114, /* Post-gain */ +}; + +static const u32 biquad_init_shifts[TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH] = { + 23, /* Pre-shift */ + 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, /* Shift for bands */ + 28, /* Post-shift */ +}; + +static s32 biquad_coeff_buffer[TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH]; + +static void tegra210_peq_read_ram(struct regmap *regmap, unsigned int reg_ctrl, + unsigned int reg_data, unsigned int ram_offset, + unsigned int *data, size_t size) +{ + unsigned int val; + unsigned int i; + + val = ram_offset & TEGRA210_PEQ_RAM_CTRL_RAM_ADDR_MASK; + val |= TEGRA210_PEQ_RAM_CTRL_ADDR_INIT_EN; + val |= TEGRA210_PEQ_RAM_CTRL_SEQ_ACCESS_EN; + val |= TEGRA210_PEQ_RAM_CTRL_RW_READ; + + regmap_write(regmap, reg_ctrl, val); + + /* + * Since all ahub non-io modules work under same ahub clock it is not + * necessary to check ahub read busy bit after every read. + */ + for (i = 0; i < size; i++) + regmap_read(regmap, reg_data, &data[i]); +} + +static void tegra210_peq_write_ram(struct regmap *regmap, unsigned int reg_ctrl, + unsigned int reg_data, unsigned int ram_offset, + unsigned int *data, size_t size) +{ + unsigned int val; + unsigned int i; + + val = ram_offset & TEGRA210_PEQ_RAM_CTRL_RAM_ADDR_MASK; + val |= TEGRA210_PEQ_RAM_CTRL_ADDR_INIT_EN; + val |= TEGRA210_PEQ_RAM_CTRL_SEQ_ACCESS_EN; + val |= TEGRA210_PEQ_RAM_CTRL_RW_WRITE; + + regmap_write(regmap, reg_ctrl, val); + + for (i = 0; i < size; i++) + regmap_write(regmap, reg_data, data[i]); +} + +static int tegra210_peq_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + unsigned int mask = (1 << fls(mc->max)) - 1; + unsigned int val; + + regmap_read(ope->peq_regmap, mc->reg, &val); + + ucontrol->value.integer.value[0] = (val >> mc->shift) & mask; + + if (!mc->invert) + return 0; + + ucontrol->value.integer.value[0] = + mc->max - ucontrol->value.integer.value[0]; + + return 0; +} + +static int tegra210_peq_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + unsigned int mask = (1 << fls(mc->max)) - 1; + bool change = false; + unsigned int val; + + val = (ucontrol->value.integer.value[0] & mask); + + if (mc->invert) + val = mc->max - val; + + val = val << mc->shift; + + regmap_update_bits_check(ope->peq_regmap, mc->reg, (mask << mc->shift), + val, &change); + + return change ? 1 : 0; +} + +static int tegra210_peq_ram_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tegra_soc_bytes *params = (void *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + u32 i, reg_ctrl = params->soc.base; + u32 reg_data = reg_ctrl + cmpnt->val_bytes; + s32 *data = (s32 *)biquad_coeff_buffer; + + pm_runtime_get_sync(cmpnt->dev); + + tegra210_peq_read_ram(ope->peq_regmap, reg_ctrl, reg_data, + params->shift, data, params->soc.num_regs); + + pm_runtime_put_sync(cmpnt->dev); + + for (i = 0; i < params->soc.num_regs; i++) + ucontrol->value.integer.value[i] = (long)data[i]; + + return 0; +} + +static int tegra210_peq_ram_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tegra_soc_bytes *params = (void *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + u32 i, reg_ctrl = params->soc.base; + u32 reg_data = reg_ctrl + cmpnt->val_bytes; + s32 *data = (s32 *)biquad_coeff_buffer; + + for (i = 0; i < params->soc.num_regs; i++) + data[i] = (s32)ucontrol->value.integer.value[i]; + + pm_runtime_get_sync(cmpnt->dev); + + tegra210_peq_write_ram(ope->peq_regmap, reg_ctrl, reg_data, + params->shift, data, params->soc.num_regs); + + pm_runtime_put_sync(cmpnt->dev); + + return 1; +} + +static int tegra210_peq_param_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct soc_bytes *params = (void *)kcontrol->private_value; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->value.integer.min = INT_MIN; + uinfo->value.integer.max = INT_MAX; + uinfo->count = params->num_regs; + + return 0; +} + +#define TEGRA210_PEQ_GAIN_PARAMS_CTRL(chan) \ + TEGRA_SOC_BYTES_EXT("PEQ Channel-" #chan " Biquad Gain Params", \ + TEGRA210_PEQ_CFG_RAM_CTRL, \ + TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH, \ + (TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH * chan), 0xffffffff, \ + tegra210_peq_ram_get, tegra210_peq_ram_put, \ + tegra210_peq_param_info) + +#define TEGRA210_PEQ_SHIFT_PARAMS_CTRL(chan) \ + TEGRA_SOC_BYTES_EXT("PEQ Channel-" #chan " Biquad Shift Params", \ + TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, \ + TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH, \ + (TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH * chan), 0x1f, \ + tegra210_peq_ram_get, tegra210_peq_ram_put, \ + tegra210_peq_param_info) + +static const struct snd_kcontrol_new tegra210_peq_controls[] = { + SOC_SINGLE_EXT("PEQ Active", TEGRA210_PEQ_CFG, + TEGRA210_PEQ_CFG_MODE_SHIFT, 1, 0, + tegra210_peq_get, tegra210_peq_put), + + SOC_SINGLE_EXT("PEQ Biquad Stages", TEGRA210_PEQ_CFG, + TEGRA210_PEQ_CFG_BIQUAD_STAGES_SHIFT, + TEGRA210_PEQ_MAX_BIQUAD_STAGES - 1, 0, + tegra210_peq_get, tegra210_peq_put), + + TEGRA210_PEQ_GAIN_PARAMS_CTRL(0), + TEGRA210_PEQ_GAIN_PARAMS_CTRL(1), + TEGRA210_PEQ_GAIN_PARAMS_CTRL(2), + TEGRA210_PEQ_GAIN_PARAMS_CTRL(3), + TEGRA210_PEQ_GAIN_PARAMS_CTRL(4), + TEGRA210_PEQ_GAIN_PARAMS_CTRL(5), + TEGRA210_PEQ_GAIN_PARAMS_CTRL(6), + TEGRA210_PEQ_GAIN_PARAMS_CTRL(7), + + TEGRA210_PEQ_SHIFT_PARAMS_CTRL(0), + TEGRA210_PEQ_SHIFT_PARAMS_CTRL(1), + TEGRA210_PEQ_SHIFT_PARAMS_CTRL(2), + TEGRA210_PEQ_SHIFT_PARAMS_CTRL(3), + TEGRA210_PEQ_SHIFT_PARAMS_CTRL(4), + TEGRA210_PEQ_SHIFT_PARAMS_CTRL(5), + TEGRA210_PEQ_SHIFT_PARAMS_CTRL(6), + TEGRA210_PEQ_SHIFT_PARAMS_CTRL(7), +}; + +static bool tegra210_peq_wr_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_PEQ_SOFT_RESET: + case TEGRA210_PEQ_CG: + case TEGRA210_PEQ_CFG ... TEGRA210_PEQ_CFG_RAM_SHIFT_DATA: + return true; + default: + return false; + } +} + +static bool tegra210_peq_rd_reg(struct device *dev, unsigned int reg) +{ + if (tegra210_peq_wr_reg(dev, reg)) + return true; + + switch (reg) { + case TEGRA210_PEQ_STATUS: + return true; + default: + return false; + } +} + +static bool tegra210_peq_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_PEQ_SOFT_RESET: + case TEGRA210_PEQ_STATUS: + case TEGRA210_PEQ_CFG_RAM_CTRL ... TEGRA210_PEQ_CFG_RAM_SHIFT_DATA: + return true; + default: + return false; + } +} + +static bool tegra210_peq_precious_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_PEQ_CFG_RAM_DATA: + case TEGRA210_PEQ_CFG_RAM_SHIFT_DATA: + return true; + default: + return false; + } +} + +static const struct regmap_config tegra210_peq_regmap_config = { + .name = "peq", + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = TEGRA210_PEQ_CFG_RAM_SHIFT_DATA, + .writeable_reg = tegra210_peq_wr_reg, + .readable_reg = tegra210_peq_rd_reg, + .volatile_reg = tegra210_peq_volatile_reg, + .precious_reg = tegra210_peq_precious_reg, + .reg_defaults = tegra210_peq_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tegra210_peq_reg_defaults), + .cache_type = REGCACHE_FLAT, +}; + +void tegra210_peq_restore(struct regmap *regmap, u32 *biquad_gains, + u32 *biquad_shifts) +{ + unsigned int i; + + for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) { + tegra210_peq_write_ram(regmap, TEGRA210_PEQ_CFG_RAM_CTRL, + TEGRA210_PEQ_CFG_RAM_DATA, + (i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH), + biquad_gains, + TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH); + + tegra210_peq_write_ram(regmap, + TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, + TEGRA210_PEQ_CFG_RAM_SHIFT_DATA, + (i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH), + biquad_shifts, + TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH); + + } +} + +void tegra210_peq_save(struct regmap *regmap, u32 *biquad_gains, + u32 *biquad_shifts) +{ + unsigned int i; + + for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) { + tegra210_peq_read_ram(regmap, + TEGRA210_PEQ_CFG_RAM_CTRL, + TEGRA210_PEQ_CFG_RAM_DATA, + (i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH), + biquad_gains, + TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH); + + tegra210_peq_read_ram(regmap, + TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, + TEGRA210_PEQ_CFG_RAM_SHIFT_DATA, + (i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH), + biquad_shifts, + TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH); + } +} + +int tegra210_peq_component_init(struct snd_soc_component *cmpnt) +{ + struct tegra210_ope *ope = snd_soc_component_get_drvdata(cmpnt); + unsigned int i; + + pm_runtime_get_sync(cmpnt->dev); + regmap_update_bits(ope->peq_regmap, TEGRA210_PEQ_CFG, + TEGRA210_PEQ_CFG_MODE_MASK, + 0 << TEGRA210_PEQ_CFG_MODE_SHIFT); + regmap_update_bits(ope->peq_regmap, TEGRA210_PEQ_CFG, + TEGRA210_PEQ_CFG_BIQUAD_STAGES_MASK, + (TEGRA210_PEQ_BIQUAD_INIT_STAGE - 1) << + TEGRA210_PEQ_CFG_BIQUAD_STAGES_SHIFT); + + /* Initialize PEQ AHUB RAM with default params */ + for (i = 0; i < TEGRA210_PEQ_MAX_CHANNELS; i++) { + + /* Set default gain params */ + tegra210_peq_write_ram(ope->peq_regmap, + TEGRA210_PEQ_CFG_RAM_CTRL, + TEGRA210_PEQ_CFG_RAM_DATA, + (i * TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH), + (u32 *)&biquad_init_gains, + TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH); + + /* Set default shift params */ + tegra210_peq_write_ram(ope->peq_regmap, + TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL, + TEGRA210_PEQ_CFG_RAM_SHIFT_DATA, + (i * TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH), + (u32 *)&biquad_init_shifts, + TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH); + + } + + pm_runtime_put_sync(cmpnt->dev); + + snd_soc_add_component_controls(cmpnt, tegra210_peq_controls, + ARRAY_SIZE(tegra210_peq_controls)); + + return 0; +} + +int tegra210_peq_regmap_init(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tegra210_ope *ope = dev_get_drvdata(dev); + struct device_node *child; + struct resource mem; + void __iomem *regs; + int err; + + child = of_get_child_by_name(dev->of_node, "equalizer"); + if (!child) + return -ENODEV; + + err = of_address_to_resource(child, 0, &mem); + of_node_put(child); + if (err < 0) { + dev_err(dev, "fail to get PEQ resource\n"); + return err; + } + + mem.flags = IORESOURCE_MEM; + regs = devm_ioremap_resource(dev, &mem); + if (IS_ERR(regs)) + return PTR_ERR(regs); + ope->peq_regmap = devm_regmap_init_mmio(dev, regs, + &tegra210_peq_regmap_config); + if (IS_ERR(ope->peq_regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(ope->peq_regmap); + } + + regcache_cache_only(ope->peq_regmap, true); + + return 0; +} diff --git a/sound/soc/tegra/tegra210_peq.h b/sound/soc/tegra/tegra210_peq.h new file mode 100644 index 000000000000..6d3de4ff05cc --- /dev/null +++ b/sound/soc/tegra/tegra210_peq.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * tegra210_peq.h - Definitions for Tegra210 PEQ driver + * + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + */ + +#ifndef __TEGRA210_PEQ_H__ +#define __TEGRA210_PEQ_H__ + +#include +#include +#include + +/* Register offsets from PEQ base */ +#define TEGRA210_PEQ_SOFT_RESET 0x0 +#define TEGRA210_PEQ_CG 0x4 +#define TEGRA210_PEQ_STATUS 0x8 +#define TEGRA210_PEQ_CFG 0xc +#define TEGRA210_PEQ_CFG_RAM_CTRL 0x10 +#define TEGRA210_PEQ_CFG_RAM_DATA 0x14 +#define TEGRA210_PEQ_CFG_RAM_SHIFT_CTRL 0x18 +#define TEGRA210_PEQ_CFG_RAM_SHIFT_DATA 0x1c + +/* Fields in TEGRA210_PEQ_CFG */ +#define TEGRA210_PEQ_CFG_BIQUAD_STAGES_SHIFT 2 +#define TEGRA210_PEQ_CFG_BIQUAD_STAGES_MASK (0xf << TEGRA210_PEQ_CFG_BIQUAD_STAGES_SHIFT) + +#define TEGRA210_PEQ_CFG_MODE_SHIFT 0 +#define TEGRA210_PEQ_CFG_MODE_MASK (0x1 << TEGRA210_PEQ_CFG_MODE_SHIFT) + +#define TEGRA210_PEQ_RAM_CTRL_RW_READ 0 +#define TEGRA210_PEQ_RAM_CTRL_RW_WRITE (1 << 14) +#define TEGRA210_PEQ_RAM_CTRL_ADDR_INIT_EN (1 << 13) +#define TEGRA210_PEQ_RAM_CTRL_SEQ_ACCESS_EN (1 << 12) +#define TEGRA210_PEQ_RAM_CTRL_RAM_ADDR_MASK 0x1ff + +/* PEQ register definition ends here */ +#define TEGRA210_PEQ_MAX_BIQUAD_STAGES 12 + +#define TEGRA210_PEQ_MAX_CHANNELS 8 + +#define TEGRA210_PEQ_BIQUAD_INIT_STAGE 5 + +#define TEGRA210_PEQ_GAIN_PARAM_SIZE_PER_CH (2 + TEGRA210_PEQ_MAX_BIQUAD_STAGES * 5) +#define TEGRA210_PEQ_SHIFT_PARAM_SIZE_PER_CH (2 + TEGRA210_PEQ_MAX_BIQUAD_STAGES) + +int tegra210_peq_regmap_init(struct platform_device *pdev); +int tegra210_peq_component_init(struct snd_soc_component *cmpnt); +void tegra210_peq_restore(struct regmap *regmap, u32 *biquad_gains, + u32 *biquad_shifts); +void tegra210_peq_save(struct regmap *regmap, u32 *biquad_gains, + u32 *biquad_shifts); + +#endif -- cgit From 7ee0910d03168535ffeea2f4ce924eebb3b24863 Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Fri, 3 Jun 2022 12:06:09 +0530 Subject: ASoC: tegra: AHUB routes for OPE module Add AHUB routes for OPE module. The OPE module can be plugged into audio path as per the need. The routing controls can be used to setup the audio path with OPE similar to the already existing routes. The support is added on Tegra210 and later Tegra SoCs where OPE module is present. Signed-off-by: Sameer Pujar Link: https://lore.kernel.org/r/1654238172-16293-4-git-send-email-spujar@nvidia.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra210_ahub.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c index e1f90daea7a1..b38d205b69cc 100644 --- a/sound/soc/tegra/tegra210_ahub.c +++ b/sound/soc/tegra/tegra210_ahub.c @@ -170,6 +170,11 @@ static struct snd_soc_dai_driver tegra210_ahub_dais[] = { DAI(MIXER1 TX3), DAI(MIXER1 TX4), DAI(MIXER1 TX5), + /* XBAR -> OPE -> XBAR */ + DAI(OPE1 RX), + DAI(OPE1 TX), + DAI(OPE2 RX), + DAI(OPE2 TX), }; static struct snd_soc_dai_driver tegra186_ahub_dais[] = { @@ -294,6 +299,9 @@ static struct snd_soc_dai_driver tegra186_ahub_dais[] = { DAI(ASRC1 RX6), DAI(ASRC1 TX6), DAI(ASRC1 RX7), + /* XBAR -> OPE -> XBAR */ + DAI(OPE1 RX), + DAI(OPE1 TX), }; static const char * const tegra210_ahub_mux_texts[] = { @@ -337,6 +345,8 @@ static const char * const tegra210_ahub_mux_texts[] = { "MIXER1 TX3", "MIXER1 TX4", "MIXER1 TX5", + "OPE1", + "OPE2", }; static const char * const tegra186_ahub_mux_texts[] = { @@ -408,6 +418,7 @@ static const char * const tegra186_ahub_mux_texts[] = { "ASRC1 TX4", "ASRC1 TX5", "ASRC1 TX6", + "OPE1", }; static const unsigned int tegra210_ahub_mux_values[] = { @@ -459,6 +470,9 @@ static const unsigned int tegra210_ahub_mux_values[] = { MUX_VALUE(1, 2), MUX_VALUE(1, 3), MUX_VALUE(1, 4), + /* OPE */ + MUX_VALUE(2, 0), + MUX_VALUE(2, 1), }; static const unsigned int tegra186_ahub_mux_values[] = { @@ -540,6 +554,8 @@ static const unsigned int tegra186_ahub_mux_values[] = { MUX_VALUE(3, 27), MUX_VALUE(3, 28), MUX_VALUE(3, 29), + /* OPE */ + MUX_VALUE(2, 0), }; /* Controls for t210 */ @@ -584,6 +600,8 @@ MUX_ENUM_CTRL_DECL(t210_mixer17_tx, 0x26); MUX_ENUM_CTRL_DECL(t210_mixer18_tx, 0x27); MUX_ENUM_CTRL_DECL(t210_mixer19_tx, 0x28); MUX_ENUM_CTRL_DECL(t210_mixer110_tx, 0x29); +MUX_ENUM_CTRL_DECL(t210_ope1_tx, 0x40); +MUX_ENUM_CTRL_DECL(t210_ope2_tx, 0x41); /* Controls for t186 */ MUX_ENUM_CTRL_DECL_186(t186_admaif1_tx, 0x00); @@ -657,6 +675,7 @@ MUX_ENUM_CTRL_DECL_186(t186_asrc14_tx, 0x6f); MUX_ENUM_CTRL_DECL_186(t186_asrc15_tx, 0x70); MUX_ENUM_CTRL_DECL_186(t186_asrc16_tx, 0x71); MUX_ENUM_CTRL_DECL_186(t186_asrc17_tx, 0x72); +MUX_ENUM_CTRL_DECL_186(t186_ope1_tx, 0x40); /* Controls for t234 */ MUX_ENUM_CTRL_DECL_234(t234_mvc1_tx, 0x44); @@ -758,6 +777,8 @@ static const struct snd_soc_dapm_widget tegra210_ahub_widgets[] = { TX_WIDGETS("MIXER1 TX3"), TX_WIDGETS("MIXER1 TX4"), TX_WIDGETS("MIXER1 TX5"), + WIDGETS("OPE1", t210_ope1_tx), + WIDGETS("OPE2", t210_ope2_tx), }; static const struct snd_soc_dapm_widget tegra186_ahub_widgets[] = { @@ -867,6 +888,7 @@ static const struct snd_soc_dapm_widget tegra186_ahub_widgets[] = { TX_WIDGETS("ASRC1 TX4"), TX_WIDGETS("ASRC1 TX5"), TX_WIDGETS("ASRC1 TX6"), + WIDGETS("OPE1", t186_ope1_tx), }; static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = { @@ -976,6 +998,7 @@ static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = { TX_WIDGETS("ASRC1 TX4"), TX_WIDGETS("ASRC1 TX5"), TX_WIDGETS("ASRC1 TX6"), + WIDGETS("OPE1", t186_ope1_tx), }; #define TEGRA_COMMON_MUX_ROUTES(name) \ @@ -1018,7 +1041,11 @@ static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = { { name " Mux", "MIXER1 TX2", "MIXER1 TX2 XBAR-RX" }, \ { name " Mux", "MIXER1 TX3", "MIXER1 TX3 XBAR-RX" }, \ { name " Mux", "MIXER1 TX4", "MIXER1 TX4 XBAR-RX" }, \ - { name " Mux", "MIXER1 TX5", "MIXER1 TX5 XBAR-RX" }, + { name " Mux", "MIXER1 TX5", "MIXER1 TX5 XBAR-RX" }, \ + { name " Mux", "OPE1", "OPE1 XBAR-RX" }, + +#define TEGRA210_ONLY_MUX_ROUTES(name) \ + { name " Mux", "OPE2", "OPE2 XBAR-RX" }, #define TEGRA186_ONLY_MUX_ROUTES(name) \ { name " Mux", "ADMAIF11", "ADMAIF11 XBAR-RX" }, \ @@ -1050,10 +1077,11 @@ static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = { { name " Mux", "ASRC1 TX5", "ASRC1 TX5 XBAR-RX" }, \ { name " Mux", "ASRC1 TX6", "ASRC1 TX6 XBAR-RX" }, -#define TEGRA210_MUX_ROUTES(name) \ - TEGRA_COMMON_MUX_ROUTES(name) +#define TEGRA210_MUX_ROUTES(name) \ + TEGRA_COMMON_MUX_ROUTES(name) \ + TEGRA210_ONLY_MUX_ROUTES(name) -#define TEGRA186_MUX_ROUTES(name) \ +#define TEGRA186_MUX_ROUTES(name) \ TEGRA_COMMON_MUX_ROUTES(name) \ TEGRA186_ONLY_MUX_ROUTES(name) @@ -1121,6 +1149,8 @@ static const struct snd_soc_dapm_route tegra210_ahub_routes[] = { TEGRA210_MUX_ROUTES("MIXER1 RX8") TEGRA210_MUX_ROUTES("MIXER1 RX9") TEGRA210_MUX_ROUTES("MIXER1 RX10") + TEGRA210_MUX_ROUTES("OPE1") + TEGRA210_MUX_ROUTES("OPE2") }; static const struct snd_soc_dapm_route tegra186_ahub_routes[] = { @@ -1215,6 +1245,7 @@ static const struct snd_soc_dapm_route tegra186_ahub_routes[] = { TEGRA186_MUX_ROUTES("ASRC1 RX5") TEGRA186_MUX_ROUTES("ASRC1 RX6") TEGRA186_MUX_ROUTES("ASRC1 RX7") + TEGRA186_MUX_ROUTES("OPE1") }; static const struct snd_soc_component_driver tegra210_ahub_component = { -- cgit From 90b12a88b710cdc80c00552dfbd589228978bffe Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:23:50 +0200 Subject: ALSA: Add snd_pcm_direction_name() helper Allow for retrieving string naming a direction of a stream without the need of substream pointer. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- include/sound/pcm.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 6b99310b5b88..26523cfe428d 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -1392,6 +1392,20 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max) const char *snd_pcm_format_name(snd_pcm_format_t format); +/** + * snd_pcm_direction_name - Get a string naming the direction of a stream + * @direction: Stream's direction, one of SNDRV_PCM_STREAM_XXX + * + * Returns a string naming the direction of the stream. + */ +static inline const char *snd_pcm_direction_name(int direction) +{ + if (direction == SNDRV_PCM_STREAM_PLAYBACK) + return "Playback"; + else + return "Capture"; +} + /** * snd_pcm_stream_str - Get a string naming the direction of a stream * @substream: the pcm substream instance @@ -1400,10 +1414,7 @@ const char *snd_pcm_format_name(snd_pcm_format_t format); */ static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream) { - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - return "Playback"; - else - return "Capture"; + return snd_pcm_direction_name(substream->stream); } /* -- cgit From b5df2a7dca1cc6c66eee0005c92094855dc2028c Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:23:51 +0200 Subject: ASoC: codecs: Add HD-Audio codec driver Add generic ASoC equivalent of ALSA HD-Audio codec. This codec is designed to follow HDA_DEV_LEGACY convention. Driver wrapps existing hda_codec.c handlers to prevent code duplication within the newly added code. Number of DAIs created is dependent on capabilities exposed by the codec itself. Because of this, single solution can be applied to support every single HD-Audio codec type. At the same time, through the ASoC topology, platform drivers may limit the number of endpoints available to the userspace as codec driver exposes BE DAIs only. Both hda_codec_probe() and hda_codec_remove() declare their expectations on device's usage_count and suspended-status. This is to catch any unexpected behavior as PM-related code for HD-Audio has been changing quite a bit throughout the years. In order for codec DAI list to reflect its actual PCM capabilities, PCMs need to be built and that can only happen once codec device is constructed. To do that, a valid component->card->snd_card pointer is needed. Said pointer will be provided by the framework once all card components are accounted for and their probing can begin. Usage of "binder" BE DAI solves the problem - codec can be listed as one of HD-Audio card components without declaring any actual BE DAIs statically. Relation with hdac_hda: Addition of parallel solution is motivated by behavioral differences between hdac_hda.c and its legacy equivalent found in sound/pci/hda e.g.: lack of dynamic, based on codec capabilities, resource allocation and high cost of removing such differences on actively used targets. Major goal of codec driver presented here is to follow HD-Audio legacy behavior in 1:1 fashion by becoming a wrapper. Doing so increases code coverage of the legacy code and reduces the maintenance cost for both solutions. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 10 ++ sound/soc/codecs/Makefile | 2 + sound/soc/codecs/hda-dai.c | 102 ++++++++++++ sound/soc/codecs/hda.c | 395 +++++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/hda.h | 19 +++ 5 files changed, 528 insertions(+) create mode 100644 sound/soc/codecs/hda-dai.c create mode 100644 sound/soc/codecs/hda.c create mode 100644 sound/soc/codecs/hda.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 6165db92a629..5a60633a196c 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -937,6 +937,16 @@ config SND_SOC_HDAC_HDA tristate select SND_HDA +config SND_SOC_HDA + tristate "HD-Audio codec driver" + select SND_HDA_EXT_CORE + select SND_HDA + help + This enables HD-Audio codec support in ASoC subsystem. Compared + to SND_SOC_HDAC_HDA, driver's behavior is identical to HD-Audio + legacy solution - including the dynamic resource allocation + based on actual codec capabilities. + config SND_SOC_ICS43432 tristate "ICS43423 and compatible i2s microphones" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 28dc4edfd01f..d32026ae326f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -106,6 +106,7 @@ snd-soc-es8328-spi-objs := es8328-spi.o snd-soc-gtm601-objs := gtm601.o snd-soc-hdac-hdmi-objs := hdac_hdmi.o snd-soc-hdac-hda-objs := hdac_hda.o +snd-soc-hda-codec-objs := hda.o hda-dai.o snd-soc-ics43432-objs := ics43432.o snd-soc-inno-rk3036-objs := inno_rk3036.o snd-soc-isabelle-objs := isabelle.o @@ -458,6 +459,7 @@ obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o obj-$(CONFIG_SND_SOC_HDAC_HDA) += snd-soc-hdac-hda.o +obj-$(CONFIG_SND_SOC_HDA) += snd-soc-hda-codec.o obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o diff --git a/sound/soc/codecs/hda-dai.c b/sound/soc/codecs/hda-dai.c new file mode 100644 index 000000000000..5371ff086261 --- /dev/null +++ b/sound/soc/codecs/hda-dai.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Author: Cezary Rojewski +// + +#include +#include +#include "hda.h" + +static int hda_codec_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + struct hda_pcm_stream *stream_info; + struct hda_codec *codec; + struct hda_pcm *pcm; + int ret; + + codec = dev_to_hda_codec(dai->dev); + stream_info = snd_soc_dai_get_dma_data(dai, substream); + pcm = container_of(stream_info, struct hda_pcm, stream[substream->stream]); + + dev_dbg(dai->dev, "open stream codec: %08x, info: %p, pcm: %p %s substream: %p\n", + codec->core.vendor_id, stream_info, pcm, pcm->name, substream); + + snd_hda_codec_pcm_get(pcm); + + ret = stream_info->ops.open(stream_info, codec, substream); + if (ret < 0) { + dev_err(dai->dev, "codec open failed: %d\n", ret); + snd_hda_codec_pcm_put(pcm); + return ret; + } + + return 0; +} + +static void hda_codec_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + struct hda_pcm_stream *stream_info; + struct hda_codec *codec; + struct hda_pcm *pcm; + int ret; + + codec = dev_to_hda_codec(dai->dev); + stream_info = snd_soc_dai_get_dma_data(dai, substream); + pcm = container_of(stream_info, struct hda_pcm, stream[substream->stream]); + + dev_dbg(dai->dev, "close stream codec: %08x, info: %p, pcm: %p %s substream: %p\n", + codec->core.vendor_id, stream_info, pcm, pcm->name, substream); + + ret = stream_info->ops.close(stream_info, codec, substream); + if (ret < 0) + dev_err(dai->dev, "codec close failed: %d\n", ret); + + snd_hda_codec_pcm_put(pcm); +} + +static int hda_codec_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + struct hda_pcm_stream *stream_info; + struct hda_codec *codec; + + codec = dev_to_hda_codec(dai->dev); + stream_info = snd_soc_dai_get_dma_data(dai, substream); + + snd_hda_codec_cleanup(codec, stream_info, substream); + + return 0; +} + +static int hda_codec_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct hda_pcm_stream *stream_info; + struct hdac_stream *stream; + struct hda_codec *codec; + unsigned int format; + int ret; + + codec = dev_to_hda_codec(dai->dev); + stream = substream->runtime->private_data; + stream_info = snd_soc_dai_get_dma_data(dai, substream); + format = snd_hdac_calc_stream_format(runtime->rate, runtime->channels, runtime->format, + runtime->sample_bits, 0); + + ret = snd_hda_codec_prepare(codec, stream_info, stream->stream_tag, format, substream); + if (ret < 0) { + dev_err(dai->dev, "codec prepare failed: %d\n", ret); + return ret; + } + + return 0; +} + +const struct snd_soc_dai_ops snd_soc_hda_codec_dai_ops = { + .startup = hda_codec_dai_startup, + .shutdown = hda_codec_dai_shutdown, + .hw_free = hda_codec_dai_hw_free, + .prepare = hda_codec_dai_prepare, +}; +EXPORT_SYMBOL_GPL(snd_soc_hda_codec_dai_ops); diff --git a/sound/soc/codecs/hda.c b/sound/soc/codecs/hda.c new file mode 100644 index 000000000000..edcb8bc6806b --- /dev/null +++ b/sound/soc/codecs/hda.c @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Author: Cezary Rojewski +// + +#include +#include +#include +#include +#include +#include +#include "hda.h" + +static int hda_codec_create_dais(struct hda_codec *codec, int pcm_count, + struct snd_soc_dai_driver **drivers) +{ + struct device *dev = &codec->core.dev; + struct snd_soc_dai_driver *drvs; + struct hda_pcm *pcm; + int i; + + drvs = devm_kcalloc(dev, pcm_count, sizeof(*drvs), GFP_KERNEL); + if (!drvs) + return -ENOMEM; + + pcm = list_first_entry(&codec->pcm_list_head, struct hda_pcm, list); + + for (i = 0; i < pcm_count; i++, pcm = list_next_entry(pcm, list)) { + struct snd_soc_pcm_stream *stream; + int dir; + + dev_info(dev, "creating for %s %d\n", pcm->name, i); + drvs[i].id = i; + drvs[i].name = pcm->name; + drvs[i].ops = &snd_soc_hda_codec_dai_ops; + + dir = SNDRV_PCM_STREAM_PLAYBACK; + stream = &drvs[i].playback; + if (!pcm->stream[dir].substreams) { + dev_info(dev, "skipping playback dai for %s\n", pcm->name); + goto capture_dais; + } + + stream->stream_name = + devm_kasprintf(dev, GFP_KERNEL, "%s %s", pcm->name, + snd_pcm_direction_name(dir)); + if (!stream->stream_name) + return -ENOMEM; + stream->channels_min = pcm->stream[dir].channels_min; + stream->channels_max = pcm->stream[dir].channels_max; + stream->rates = pcm->stream[dir].rates; + stream->formats = pcm->stream[dir].formats; + stream->sig_bits = pcm->stream[dir].maxbps; + +capture_dais: + dir = SNDRV_PCM_STREAM_CAPTURE; + stream = &drvs[i].capture; + if (!pcm->stream[dir].substreams) { + dev_info(dev, "skipping capture dai for %s\n", pcm->name); + continue; + } + + stream->stream_name = + devm_kasprintf(dev, GFP_KERNEL, "%s %s", pcm->name, + snd_pcm_direction_name(dir)); + if (!stream->stream_name) + return -ENOMEM; + stream->channels_min = pcm->stream[dir].channels_min; + stream->channels_max = pcm->stream[dir].channels_max; + stream->rates = pcm->stream[dir].rates; + stream->formats = pcm->stream[dir].formats; + stream->sig_bits = pcm->stream[dir].maxbps; + } + + *drivers = drvs; + return 0; +} + +static int hda_codec_register_dais(struct hda_codec *codec, struct snd_soc_component *component) +{ + struct snd_soc_dai_driver *drvs = NULL; + struct snd_soc_dapm_context *dapm; + struct hda_pcm *pcm; + int ret, pcm_count = 0; + + if (list_empty(&codec->pcm_list_head)) + return -EINVAL; + list_for_each_entry(pcm, &codec->pcm_list_head, list) + pcm_count++; + + ret = hda_codec_create_dais(codec, pcm_count, &drvs); + if (ret < 0) + return ret; + + dapm = snd_soc_component_get_dapm(component); + + list_for_each_entry(pcm, &codec->pcm_list_head, list) { + struct snd_soc_dai *dai; + + dai = snd_soc_register_dai(component, drvs, false); + if (!dai) { + dev_err(component->dev, "register dai for %s failed\n", pcm->name); + return -EINVAL; + } + + ret = snd_soc_dapm_new_dai_widgets(dapm, dai); + if (ret < 0) { + dev_err(component->dev, "create widgets failed: %d\n", ret); + snd_soc_unregister_dai(dai); + return ret; + } + + snd_soc_dai_init_dma_data(dai, &pcm->stream[0], &pcm->stream[1]); + drvs++; + } + + return 0; +} + +static void hda_codec_unregister_dais(struct hda_codec *codec, + struct snd_soc_component *component) +{ + struct snd_soc_dai *dai, *save; + struct hda_pcm *pcm; + + for_each_component_dais_safe(component, dai, save) { + list_for_each_entry(pcm, &codec->pcm_list_head, list) { + if (strcmp(dai->driver->name, pcm->name)) + continue; + + if (dai->playback_widget) + snd_soc_dapm_free_widget(dai->playback_widget); + if (dai->capture_widget) + snd_soc_dapm_free_widget(dai->capture_widget); + snd_soc_unregister_dai(dai); + break; + } + } +} + +int hda_codec_probe_complete(struct hda_codec *codec) +{ + struct hdac_device *hdev = &codec->core; + struct hdac_bus *bus = hdev->bus; + int ret; + + ret = snd_hda_codec_build_controls(codec); + if (ret < 0) { + dev_err(&hdev->dev, "unable to create controls %d\n", ret); + goto out; + } + + /* Bus suspended codecs as it does not manage their pm */ + pm_runtime_set_active(&hdev->dev); + /* rpm was forbidden in snd_hda_codec_device_new() */ + snd_hda_codec_set_power_save(codec, 2000); + snd_hda_codec_register(codec); +out: + /* Complement pm_runtime_get_sync(bus) in probe */ + pm_runtime_mark_last_busy(bus->dev); + pm_runtime_put_autosuspend(bus->dev); + + return ret; +} +EXPORT_SYMBOL_GPL(hda_codec_probe_complete); + +/* Expects codec with usage_count=1 and status=suspended */ +static int hda_codec_probe(struct snd_soc_component *component) +{ + struct hda_codec *codec = dev_to_hda_codec(component->dev); + struct hdac_device *hdev = &codec->core; + struct hdac_bus *bus = hdev->bus; + struct hdac_ext_link *hlink; + hda_codec_patch_t patch; + int ret; + +#ifdef CONFIG_PM + WARN_ON(atomic_read(&hdev->dev.power.usage_count) != 1 || + !pm_runtime_status_suspended(&hdev->dev)); +#endif + + hlink = snd_hdac_ext_bus_link_at(bus, hdev->addr); + if (!hlink) { + dev_err(&hdev->dev, "hdac link not found\n"); + return -EIO; + } + + pm_runtime_get_sync(bus->dev); + if (hda_codec_is_display(codec)) + snd_hdac_display_power(bus, hdev->addr, true); + snd_hdac_ext_bus_link_get(bus, hlink); + + ret = snd_hda_codec_device_new(codec->bus, component->card->snd_card, hdev->addr, codec, + false); + if (ret < 0) { + dev_err(&hdev->dev, "create hda codec failed: %d\n", ret); + goto device_new_err; + } + + ret = snd_hda_codec_set_name(codec, codec->preset->name); + if (ret < 0) { + dev_err(&hdev->dev, "name failed %s\n", codec->preset->name); + goto err; + } + + ret = snd_hdac_regmap_init(&codec->core); + if (ret < 0) { + dev_err(&hdev->dev, "regmap init failed\n"); + goto err; + } + + patch = (hda_codec_patch_t)codec->preset->driver_data; + if (!patch) { + dev_err(&hdev->dev, "no patch specified?\n"); + ret = -EINVAL; + goto err; + } + + ret = patch(codec); + if (ret < 0) { + dev_err(&hdev->dev, "patch failed %d\n", ret); + goto err; + } + + /* configure codec for 1:1 PCM:DAI mapping */ + codec->mst_no_extra_pcms = 1; + + ret = snd_hda_codec_parse_pcms(codec); + if (ret < 0) { + dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret); + goto parse_pcms_err; + } + + ret = hda_codec_register_dais(codec, component); + if (ret < 0) { + dev_err(&hdev->dev, "update dais failed: %d\n", ret); + goto parse_pcms_err; + } + + if (!hda_codec_is_display(codec)) { + ret = hda_codec_probe_complete(codec); + if (ret < 0) + goto complete_err; + } + + codec->core.lazy_cache = true; + + return 0; + +complete_err: + hda_codec_unregister_dais(codec, component); +parse_pcms_err: + if (codec->patch_ops.free) + codec->patch_ops.free(codec); +err: + snd_hda_codec_cleanup_for_unbind(codec); +device_new_err: + if (hda_codec_is_display(codec)) + snd_hdac_display_power(bus, hdev->addr, false); + + snd_hdac_ext_bus_link_put(bus, hlink); + + pm_runtime_mark_last_busy(bus->dev); + pm_runtime_put_autosuspend(bus->dev); + return ret; +} + +/* Leaves codec with usage_count=1 and status=suspended */ +static void hda_codec_remove(struct snd_soc_component *component) +{ + struct hda_codec *codec = dev_to_hda_codec(component->dev); + struct hdac_device *hdev = &codec->core; + struct hdac_bus *bus = hdev->bus; + struct hdac_ext_link *hlink; + bool was_registered = codec->registered; + + /* Don't allow any more runtime suspends */ + pm_runtime_forbid(&hdev->dev); + + hda_codec_unregister_dais(codec, component); + + if (codec->patch_ops.free) + codec->patch_ops.free(codec); + + snd_hda_codec_cleanup_for_unbind(codec); + pm_runtime_put_noidle(&hdev->dev); + /* snd_hdac_device_exit() is only called on bus remove */ + pm_runtime_set_suspended(&hdev->dev); + + if (hda_codec_is_display(codec)) + snd_hdac_display_power(bus, hdev->addr, false); + + hlink = snd_hdac_ext_bus_link_at(bus, hdev->addr); + if (hlink) + snd_hdac_ext_bus_link_put(bus, hlink); + /* + * HDMI card's hda_codec_probe_complete() (see late_probe()) may + * not be called due to early error, leaving bus uc unbalanced + */ + if (!was_registered) { + pm_runtime_mark_last_busy(bus->dev); + pm_runtime_put_autosuspend(bus->dev); + } + +#ifdef CONFIG_PM + WARN_ON(atomic_read(&hdev->dev.power.usage_count) != 1 || + !pm_runtime_status_suspended(&hdev->dev)); +#endif +} + +static const struct snd_soc_dapm_route hda_dapm_routes[] = { + {"AIF1TX", NULL, "Codec Input Pin1"}, + {"AIF2TX", NULL, "Codec Input Pin2"}, + {"AIF3TX", NULL, "Codec Input Pin3"}, + + {"Codec Output Pin1", NULL, "AIF1RX"}, + {"Codec Output Pin2", NULL, "AIF2RX"}, + {"Codec Output Pin3", NULL, "AIF3RX"}, +}; + +static const struct snd_soc_dapm_widget hda_dapm_widgets[] = { + /* Audio Interface */ + SND_SOC_DAPM_AIF_IN("AIF1RX", "Analog Codec Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("AIF2RX", "Digital Codec Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("AIF3RX", "Alt Analog Codec Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AIF1TX", "Analog Codec Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AIF2TX", "Digital Codec Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AIF3TX", "Alt Analog Codec Capture", 0, SND_SOC_NOPM, 0, 0), + + /* Input Pins */ + SND_SOC_DAPM_INPUT("Codec Input Pin1"), + SND_SOC_DAPM_INPUT("Codec Input Pin2"), + SND_SOC_DAPM_INPUT("Codec Input Pin3"), + + /* Output Pins */ + SND_SOC_DAPM_OUTPUT("Codec Output Pin1"), + SND_SOC_DAPM_OUTPUT("Codec Output Pin2"), + SND_SOC_DAPM_OUTPUT("Codec Output Pin3"), +}; + +static struct snd_soc_dai_driver card_binder_dai = { + .id = -1, + .name = "codec-probing-DAI", +}; + +static int hda_hdev_attach(struct hdac_device *hdev) +{ + struct hda_codec *codec = dev_to_hda_codec(&hdev->dev); + struct snd_soc_component_driver *comp_drv; + + comp_drv = devm_kzalloc(&hdev->dev, sizeof(*comp_drv), GFP_KERNEL); + if (!comp_drv) + return -ENOMEM; + + /* + * It's save to rely on dev_name() rather than a copy as component + * driver's lifetime is directly tied to hda codec one + */ + comp_drv->name = dev_name(&hdev->dev); + comp_drv->probe = hda_codec_probe; + comp_drv->remove = hda_codec_remove; + comp_drv->idle_bias_on = false; + if (!hda_codec_is_display(codec)) { + comp_drv->dapm_widgets = hda_dapm_widgets; + comp_drv->num_dapm_widgets = ARRAY_SIZE(hda_dapm_widgets); + comp_drv->dapm_routes = hda_dapm_routes; + comp_drv->num_dapm_routes = ARRAY_SIZE(hda_dapm_routes); + } + + return snd_soc_register_component(&hdev->dev, comp_drv, &card_binder_dai, 1); +} + +static int hda_hdev_detach(struct hdac_device *hdev) +{ + struct hda_codec *codec = dev_to_hda_codec(&hdev->dev); + + if (codec->registered) + cancel_delayed_work_sync(&codec->jackpoll_work); + + snd_soc_unregister_component(&hdev->dev); + + return 0; +} + +const struct hdac_ext_bus_ops soc_hda_ext_bus_ops = { + .hdev_attach = hda_hdev_attach, + .hdev_detach = hda_hdev_detach, +}; +EXPORT_SYMBOL_GPL(soc_hda_ext_bus_ops); + +MODULE_DESCRIPTION("HD-Audio codec driver"); +MODULE_AUTHOR("Cezary Rojewski "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/hda.h b/sound/soc/codecs/hda.h new file mode 100644 index 000000000000..78a2be4945b1 --- /dev/null +++ b/sound/soc/codecs/hda.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright(c) 2021-2022 Intel Corporation. All rights reserved. + * + * Author: Cezary Rojewski + */ + +#ifndef SND_SOC_CODECS_HDA_H +#define SND_SOC_CODECS_HDA_H + +#define hda_codec_is_display(codec) \ + ((((codec)->core.vendor_id >> 16) & 0xFFFF) == 0x8086) + +extern const struct snd_soc_dai_ops snd_soc_hda_codec_dai_ops; + +extern const struct hdac_ext_bus_ops soc_hda_ext_bus_ops; +int hda_codec_probe_complete(struct hda_codec *codec); + +#endif -- cgit From 97030a43371ea29d65f332d288eb73e8f7bdb3a9 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:23:52 +0200 Subject: ASoC: Intel: avs: Add HDAudio machine board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Connect AVS driver with ASoC HDAudio codec with help of this machine board. Similarly to its platform and codec components, DAI links and routes are being created dynamically so single board can be used across all HDAudio codec types. Card makes use of "binder" BE DAI Link so HDAudio codec driver can be listed as one of its components. This allows for BE DAIs to be created dynamically, based on HDAudio codec capabilities. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-4-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 3 + sound/soc/intel/avs/Makefile | 3 + sound/soc/intel/avs/boards/Kconfig | 15 ++ sound/soc/intel/avs/boards/Makefile | 5 + sound/soc/intel/avs/boards/hdaudio.c | 294 +++++++++++++++++++++++++++++++++++ 5 files changed, 320 insertions(+) create mode 100644 sound/soc/intel/avs/boards/Kconfig create mode 100644 sound/soc/intel/avs/boards/Makefile create mode 100644 sound/soc/intel/avs/boards/hdaudio.c diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 7c85d1bb9c12..e5107a3ce16a 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -226,5 +226,8 @@ config SND_SOC_INTEL_AVS capabilities. This includes Skylake, Kabylake, Amberlake and Apollolake. +# Machine board drivers +source "sound/soc/intel/avs/boards/Kconfig" + # ASoC codec drivers source "sound/soc/intel/boards/Kconfig" diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile index b6b93ae80304..919212825f21 100644 --- a/sound/soc/intel/avs/Makefile +++ b/sound/soc/intel/avs/Makefile @@ -10,3 +10,6 @@ snd-soc-avs-objs += trace.o CFLAGS_trace.o := -I$(src) obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o + +# Machine support +obj-$(CONFIG_SND_SOC) += boards/ diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig new file mode 100644 index 000000000000..de62c0437f6e --- /dev/null +++ b/sound/soc/intel/avs/boards/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only +menu "Intel AVS Machine drivers" + depends on SND_SOC_INTEL_AVS + +comment "Available DSP configurations" + +config SND_SOC_INTEL_AVS_MACH_HDAUDIO + tristate "HD-Audio generic board" + select SND_SOC_HDA + help + This adds support for AVS with HDAudio codec configuration. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + +endmenu diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile new file mode 100644 index 000000000000..e5281148e5d4 --- /dev/null +++ b/sound/soc/intel/avs/boards/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + +snd-soc-avs-hdaudio-objs := hdaudio.o + +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o diff --git a/sound/soc/intel/avs/boards/hdaudio.c b/sound/soc/intel/avs/boards/hdaudio.c new file mode 100644 index 000000000000..d2fc41d39448 --- /dev/null +++ b/sound/soc/intel/avs/boards/hdaudio.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include +#include +#include +#include "../../../codecs/hda.h" + +static int avs_create_dai_links(struct device *dev, struct hda_codec *codec, int pcm_count, + const char *platform_name, struct snd_soc_dai_link **links) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + struct hda_pcm *pcm; + const char *cname = dev_name(&codec->core.dev); + int i; + + dl = devm_kcalloc(dev, pcm_count, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + pcm = list_first_entry(&codec->pcm_list_head, struct hda_pcm, list); + + for (i = 0; i < pcm_count; i++, pcm = list_next_entry(pcm, list)) { + dl[i].name = devm_kasprintf(dev, GFP_KERNEL, "%s link%d", cname, i); + if (!dl[i].name) + return -ENOMEM; + + dl[i].id = i; + dl[i].nonatomic = 1; + dl[i].no_pcm = 1; + dl[i].dpcm_playback = 1; + dl[i].dpcm_capture = 1; + dl[i].platforms = platform; + dl[i].num_platforms = 1; + + dl[i].codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); + dl[i].cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + if (!dl[i].codecs || !dl[i].cpus) + return -ENOMEM; + + dl[i].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "%s-cpu%d", cname, i); + if (!dl[i].cpus->dai_name) + return -ENOMEM; + + dl[i].codecs->name = devm_kstrdup(dev, cname, GFP_KERNEL); + dl[i].codecs->dai_name = pcm->name; + dl[i].num_codecs = 1; + dl[i].num_cpus = 1; + } + + *links = dl; + return 0; +} + +static int avs_create_dapm_routes(struct device *dev, struct hda_codec *codec, int pcm_count, + struct snd_soc_dapm_route **routes, int *num_routes) +{ + struct snd_soc_dapm_route *dr; + struct hda_pcm *pcm; + const char *cname = dev_name(&codec->core.dev); + int i, n = 0; + + /* at max twice the number of pcms */ + dr = devm_kcalloc(dev, pcm_count * 2, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + pcm = list_first_entry(&codec->pcm_list_head, struct hda_pcm, list); + + for (i = 0; i < pcm_count; i++, pcm = list_next_entry(pcm, list)) { + struct hda_pcm_stream *stream; + int dir; + + dir = SNDRV_PCM_STREAM_PLAYBACK; + stream = &pcm->stream[dir]; + if (!stream->substreams) + goto capture_routes; + + dr[n].sink = devm_kasprintf(dev, GFP_KERNEL, "%s %s", pcm->name, + snd_pcm_direction_name(dir)); + dr[n].source = devm_kasprintf(dev, GFP_KERNEL, "%s-cpu%d Tx", cname, i); + if (!dr[n].sink || !dr[n].source) + return -ENOMEM; + n++; + +capture_routes: + dir = SNDRV_PCM_STREAM_CAPTURE; + stream = &pcm->stream[dir]; + if (!stream->substreams) + continue; + + dr[n].sink = devm_kasprintf(dev, GFP_KERNEL, "%s-cpu%d Rx", cname, i); + dr[n].source = devm_kasprintf(dev, GFP_KERNEL, "%s %s", pcm->name, + snd_pcm_direction_name(dir)); + if (!dr[n].sink || !dr[n].source) + return -ENOMEM; + n++; + } + + *routes = dr; + *num_routes = n; + return 0; +} + +/* Should be aligned with SectionPCM's name from topology */ +#define FEDAI_NAME_PREFIX "HDMI" + +static struct snd_pcm * +avs_card_hdmi_pcm_at(struct snd_soc_card *card, int hdmi_idx) +{ + struct snd_soc_pcm_runtime *rtd; + int dir = SNDRV_PCM_STREAM_PLAYBACK; + + for_each_card_rtds(card, rtd) { + struct snd_pcm *spcm; + int ret, n; + + spcm = rtd->pcm ? rtd->pcm->streams[dir].pcm : NULL; + if (!spcm || !strstr(spcm->id, FEDAI_NAME_PREFIX)) + continue; + + ret = sscanf(spcm->id, FEDAI_NAME_PREFIX "%d", &n); + if (ret != 1) + continue; + if (n == hdmi_idx) + return rtd->pcm; + } + + return NULL; +} + +static int avs_card_late_probe(struct snd_soc_card *card) +{ + struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); + struct hda_codec *codec = mach->pdata; + struct hda_pcm *hpcm; + /* Topology pcm indexing is 1-based */ + int i = 1; + + list_for_each_entry(hpcm, &codec->pcm_list_head, list) { + struct snd_pcm *spcm; + + spcm = avs_card_hdmi_pcm_at(card, i); + if (spcm) { + hpcm->pcm = spcm; + hpcm->device = spcm->device; + dev_info(card->dev, "%s: mapping HDMI converter %d to PCM %d (%p)\n", + __func__, i, hpcm->device, spcm); + } else { + hpcm->pcm = NULL; + hpcm->device = SNDRV_PCM_INVALID_DEVICE; + dev_warn(card->dev, "%s: no PCM in topology for HDMI converter %d\n", + __func__, i); + } + i++; + } + + return hda_codec_probe_complete(codec); +} + +static int avs_probing_link_init(struct snd_soc_pcm_runtime *rtm) +{ + struct snd_soc_dapm_route *routes; + struct snd_soc_acpi_mach *mach; + struct snd_soc_dai_link *links = NULL; + struct snd_soc_card *card = rtm->card; + struct hda_codec *codec; + struct hda_pcm *pcm; + int ret, n, pcm_count = 0; + + mach = dev_get_platdata(card->dev); + codec = mach->pdata; + + if (list_empty(&codec->pcm_list_head)) + return -EINVAL; + list_for_each_entry(pcm, &codec->pcm_list_head, list) + pcm_count++; + + ret = avs_create_dai_links(card->dev, codec, pcm_count, mach->mach_params.platform, &links); + if (ret < 0) { + dev_err(card->dev, "create links failed: %d\n", ret); + return ret; + } + + for (n = 0; n < pcm_count; n++) { + ret = snd_soc_add_pcm_runtime(card, &links[n]); + if (ret < 0) { + dev_err(card->dev, "add links failed: %d\n", ret); + return ret; + } + } + + ret = avs_create_dapm_routes(card->dev, codec, pcm_count, &routes, &n); + if (ret < 0) { + dev_err(card->dev, "create routes failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, routes, n); + if (ret < 0) { + dev_err(card->dev, "add routes failed: %d\n", ret); + return ret; + } + + return 0; +} + +SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); + +static struct snd_soc_dai_link probing_link = { + .name = "probing-LINK", + .id = -1, + .nonatomic = 1, + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .cpus = dummy, + .num_cpus = ARRAY_SIZE(dummy), + .init = avs_probing_link_init, +}; + +static int avs_hdaudio_probe(struct platform_device *pdev) +{ + struct snd_soc_dai_link *binder; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct device *dev = &pdev->dev; + struct hda_codec *codec; + + mach = dev_get_platdata(dev); + codec = mach->pdata; + + /* codec may be unloaded before card's probe() fires */ + if (!device_is_registered(&codec->core.dev)) + return -ENODEV; + + binder = devm_kmemdup(dev, &probing_link, sizeof(probing_link), GFP_KERNEL); + if (!binder) + return -ENOMEM; + + binder->platforms = devm_kzalloc(dev, sizeof(*binder->platforms), GFP_KERNEL); + binder->codecs = devm_kzalloc(dev, sizeof(*binder->codecs), GFP_KERNEL); + if (!binder->platforms || !binder->codecs) + return -ENOMEM; + + binder->codecs->name = devm_kstrdup(dev, dev_name(&codec->core.dev), GFP_KERNEL); + if (!binder->codecs->name) + return -ENOMEM; + + binder->platforms->name = mach->mach_params.platform; + binder->num_platforms = 1; + binder->codecs->dai_name = "codec-probing-DAI"; + binder->num_codecs = 1; + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + card->name = binder->codecs->name; + card->dev = dev; + card->owner = THIS_MODULE; + card->dai_link = binder; + card->num_links = 1; + card->fully_routed = true; + if (hda_codec_is_display(codec)) + card->late_probe = avs_card_late_probe; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_hdaudio_driver = { + .probe = avs_hdaudio_probe, + .driver = { + .name = "avs_hdaudio", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_hdaudio_driver) + +MODULE_DESCRIPTION("Intel HD-Audio machine driver"); +MODULE_AUTHOR("Cezary Rojewski "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_hdaudio"); -- cgit From 6575e5cae7525b07d0b5fbd7d42323363919a867 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:23:53 +0200 Subject: ASoC: Intel: avs: Add DMIC machine board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support AVS-DMIC configuration by implementing board connecting AVS platform component with DMIC codec one. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/Kconfig | 8 ++++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/dmic.c | 93 +++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 sound/soc/intel/avs/boards/dmic.c diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index de62c0437f6e..1d4597fa9814 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -4,6 +4,14 @@ menu "Intel AVS Machine drivers" comment "Available DSP configurations" +config SND_SOC_INTEL_AVS_MACH_DMIC + tristate "DMIC generic board" + select SND_SOC_DMIC + help + This adds support for AVS with Digital Mic array configuration. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + config SND_SOC_INTEL_AVS_MACH_HDAUDIO tristate "HD-Audio generic board" select SND_SOC_HDA diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index e5281148e5d4..2ff35d4d97d8 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only +snd-soc-avs-dmic-objs := dmic.o snd-soc-avs-hdaudio-objs := hdaudio.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o diff --git a/sound/soc/intel/avs/boards/dmic.c b/sound/soc/intel/avs/boards/dmic.c new file mode 100644 index 000000000000..90a921638572 --- /dev/null +++ b/sound/soc/intel/avs/boards/dmic.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include +#include + +SND_SOC_DAILINK_DEF(dmic_pin, DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); +SND_SOC_DAILINK_DEF(dmic_wov_pin, DAILINK_COMP_ARRAY(COMP_CPU("DMIC WoV Pin"))); +SND_SOC_DAILINK_DEF(dmic_codec, DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); +/* Name overridden on probe */ +SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM(""))); + +static struct snd_soc_dai_link card_dai_links[] = { + /* Back ends */ + { + .name = "DMIC", + .id = 0, + .dpcm_capture = 1, + .nonatomic = 1, + .no_pcm = 1, + SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), + }, + { + .name = "DMIC WoV", + .id = 1, + .dpcm_capture = 1, + .nonatomic = 1, + .no_pcm = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(dmic_wov_pin, dmic_codec, platform), + }, +}; + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_MIC("SoC DMIC", NULL), +}; + +static const struct snd_soc_dapm_route card_routes[] = { + {"DMic", NULL, "SoC DMIC"}, + {"DMIC Rx", NULL, "Capture"}, + {"DMIC WoV Rx", NULL, "Capture"}, +}; + +static int avs_dmic_probe(struct platform_device *pdev) +{ + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct device *dev = &pdev->dev; + int ret; + + mach = dev_get_platdata(dev); + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + card->name = "avs_dmic"; + card->dev = dev; + card->owner = THIS_MODULE; + card->dai_link = card_dai_links; + card->num_links = ARRAY_SIZE(card_dai_links); + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = card_routes; + card->num_dapm_routes = ARRAY_SIZE(card_routes); + card->fully_routed = true; + + ret = snd_soc_fixup_dai_links_platform_name(card, mach->mach_params.platform); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_dmic_driver = { + .probe = avs_dmic_probe, + .driver = { + .name = "avs_dmic", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_dmic_driver); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_dmic"); -- cgit From e39acc4cfd9250e7b8ec01897570f3009659c3d6 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:23:54 +0200 Subject: ASoC: Intel: avs: Add I2S-test machine board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow for testing audio streaming over I2S interface through SSP loopback. No actual codec is needed here as board is intended for SSP loopback scenarios only. One playback and one capture endpoint is exposed per SSP port. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-6-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/Kconfig | 6 ++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/i2s_test.c | 180 ++++++++++++++++++++++++++++++++++ 3 files changed, 188 insertions(+) create mode 100644 sound/soc/intel/avs/boards/i2s_test.c diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index 1d4597fa9814..5b89fcb5f07f 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -20,4 +20,10 @@ config SND_SOC_INTEL_AVS_MACH_HDAUDIO Say Y or m if you have such a device. This is a recommended option. If unsure select "N". +config SND_SOC_INTEL_AVS_MACH_I2S_TEST + tristate "I2S test board" + help + This adds support for I2S test-board which can be used to verify + transfer over I2S interface with SSP loopback scenarios. + endmenu diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index 2ff35d4d97d8..fa1a279106be 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -2,6 +2,8 @@ snd-soc-avs-dmic-objs := dmic.o snd-soc-avs-hdaudio-objs := hdaudio.o +snd-soc-avs-i2s-test-objs := i2s_test.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_i2s_TEST) += snd-soc-avs-i2s-test.o diff --git a/sound/soc/intel/avs/boards/i2s_test.c b/sound/soc/intel/avs/boards/i2s_test.c new file mode 100644 index 000000000000..461b651cd331 --- /dev/null +++ b/sound/soc/intel/avs/boards/i2s_test.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include +#include +#include +#include + +static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, + struct snd_soc_dai_link **dai_link) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + + dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); + if (!dl->name || !dl->cpus || !dl->codecs) + return -ENOMEM; + + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "snd-soc-dummy"); + dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, "snd-soc-dummy-dai"); + if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) + return -ENOMEM; + + dl->num_cpus = 1; + dl->num_codecs = 1; + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; + dl->nonatomic = 1; + dl->no_pcm = 1; + dl->dpcm_capture = 1; + dl->dpcm_playback = 1; + + *dai_link = dl; + + return 0; +} + +static int avs_create_dapm_routes(struct device *dev, int ssp_port, + struct snd_soc_dapm_route **routes, int *num_routes) +{ + struct snd_soc_dapm_route *dr; + const int num_dr = 2; + + dr = devm_kcalloc(dev, num_dr, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + dr[0].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%dpb", ssp_port); + dr[0].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[0].sink || !dr[0].source) + return -ENOMEM; + + dr[1].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Rx", ssp_port); + dr[1].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%dcp", ssp_port); + if (!dr[1].sink || !dr[1].source) + return -ENOMEM; + + *routes = dr; + *num_routes = num_dr; + + return 0; +} + +static int avs_create_dapm_widgets(struct device *dev, int ssp_port, + struct snd_soc_dapm_widget **widgets, int *num_widgets) +{ + struct snd_soc_dapm_widget *dw; + const int num_dw = 2; + + dw = devm_kcalloc(dev, num_dw, sizeof(*dw), GFP_KERNEL); + if (!dw) + return -ENOMEM; + + dw[0].id = snd_soc_dapm_hp; + dw[0].reg = SND_SOC_NOPM; + dw[0].name = devm_kasprintf(dev, GFP_KERNEL, "ssp%dpb", ssp_port); + if (!dw[0].name) + return -ENOMEM; + + dw[1].id = snd_soc_dapm_mic; + dw[1].reg = SND_SOC_NOPM; + dw[1].name = devm_kasprintf(dev, GFP_KERNEL, "ssp%dcp", ssp_port); + if (!dw[1].name) + return -ENOMEM; + + *widgets = dw; + *num_widgets = num_dw; + + return 0; +} + +static int avs_i2s_test_probe(struct platform_device *pdev) +{ + struct snd_soc_dapm_widget *widgets; + struct snd_soc_dapm_route *routes; + struct snd_soc_dai_link *dai_link; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct device *dev = &pdev->dev; + const char *pname; + int num_routes, num_widgets; + int ssp_port, ret; + + mach = dev_get_platdata(dev); + pname = mach->mach_params.platform; + ssp_port = __ffs(mach->mach_params.i2s_link_mask); + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + card->name = devm_kasprintf(dev, GFP_KERNEL, "ssp%ld-loopback", ssp_port); + if (!card->name) + return -ENOMEM; + + ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + if (ret) { + dev_err(dev, "Failed to create dai link: %d\n", ret); + return ret; + } + + ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes); + if (ret) { + dev_err(dev, "Failed to create dapm routes: %d\n", ret); + return ret; + } + + ret = avs_create_dapm_widgets(dev, ssp_port, &widgets, &num_widgets); + if (ret) { + dev_err(dev, "Failed to create dapm widgets: %d\n", ret); + return ret; + } + + card->dev = dev; + card->owner = THIS_MODULE; + card->dai_link = dai_link; + card->num_links = 1; + card->dapm_routes = routes; + card->num_dapm_routes = num_routes; + card->dapm_widgets = widgets; + card->num_dapm_widgets = num_widgets; + card->fully_routed = true; + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_i2s_test_driver = { + .probe = avs_i2s_test_probe, + .driver = { + .name = "avs_i2s_test", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_i2s_test_driver); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_i2s_test"); -- cgit From e2a4cbf277c4561d01f1aafa3cfafe46bf3feec7 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:23:55 +0200 Subject: ASoC: Intel: avs: Add rt274 machine board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To support AVS-rt274 configuration add machine board connecting AVS platform component driver with rt274 codec one. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-7-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/Kconfig | 10 ++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/rt274.c | 310 ++++++++++++++++++++++++++++++++++++ 3 files changed, 322 insertions(+) create mode 100644 sound/soc/intel/avs/boards/rt274.c diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index 5b89fcb5f07f..9058919c99a7 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -26,4 +26,14 @@ config SND_SOC_INTEL_AVS_MACH_I2S_TEST This adds support for I2S test-board which can be used to verify transfer over I2S interface with SSP loopback scenarios. +config SND_SOC_INTEL_AVS_MACH_RT274 + tristate "rt274 in I2S mode" + depends on I2C + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_RT274 + help + This adds support for ASoC machine driver with RT274 I2S audio codec. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + endmenu diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index fa1a279106be..e94f04d00ffc 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -3,7 +3,9 @@ snd-soc-avs-dmic-objs := dmic.o snd-soc-avs-hdaudio-objs := hdaudio.o snd-soc-avs-i2s-test-objs := i2s_test.o +snd-soc-avs-rt274-objs := rt274.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_i2s_TEST) += snd-soc-avs-i2s-test.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o diff --git a/sound/soc/intel/avs/boards/rt274.c b/sound/soc/intel/avs/boards/rt274.c new file mode 100644 index 000000000000..afef5a3ca60b --- /dev/null +++ b/sound/soc/intel/avs/boards/rt274.c @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include +#include +#include +#include +#include "../../../codecs/rt274.h" + +#define AVS_RT274_FREQ_OUT 24000000 +#define AVS_RT274_BE_FIXUP_RATE 48000 +#define RT274_CODEC_DAI "rt274-aif1" + +static const struct snd_kcontrol_new card_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Mic Jack"), +}; + +static int +avs_rt274_clock_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *control, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct snd_soc_dai *codec_dai; + int ret; + + codec_dai = snd_soc_card_get_codec_dai(card, RT274_CODEC_DAI); + if (!codec_dai) + return -EINVAL; + + /* Codec needs clock for Jack detection and button press */ + ret = snd_soc_dai_set_sysclk(codec_dai, RT274_SCLK_S_PLL2, AVS_RT274_FREQ_OUT, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, "set codec sysclk failed: %d\n", ret); + return ret; + } + + if (SND_SOC_DAPM_EVENT_ON(event)) { + int ratio = 100; + + snd_soc_dai_set_bclk_ratio(codec_dai, ratio); + + ret = snd_soc_dai_set_pll(codec_dai, 0, RT274_PLL2_S_BCLK, + AVS_RT274_BE_FIXUP_RATE * ratio, AVS_RT274_FREQ_OUT); + if (ret) { + dev_err(codec_dai->dev, "failed to enable PLL2: %d\n", ret); + return ret; + } + } + + return 0; +} + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, avs_rt274_clock_control, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route card_base_routes[] = { + {"Headphone Jack", NULL, "HPO Pin"}, + {"MIC", NULL, "Mic Jack"}, + + {"Headphone Jack", NULL, "Platform Clock"}, + {"MIC", NULL, "Platform Clock"}, +}; + +static struct snd_soc_jack_pin card_headset_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Mic Jack", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static int avs_rt274_codec_init(struct snd_soc_pcm_runtime *runtime) +{ + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); + struct snd_soc_component *component = codec_dai->component; + struct snd_soc_jack_pin *pins; + struct snd_soc_jack *jack; + struct snd_soc_card *card = runtime->card; + int num_pins, ret; + + jack = snd_soc_card_get_drvdata(card); + num_pins = ARRAY_SIZE(card_headset_pins); + + pins = devm_kmemdup(card->dev, card_headset_pins, sizeof(*pins) * num_pins, GFP_KERNEL); + if (!pins) + return -ENOMEM; + + ret = snd_soc_card_jack_new_pins(card, "Headset", SND_JACK_HEADSET, jack, pins, num_pins); + if (ret) + return ret; + + snd_soc_component_set_jack(component, jack, NULL); + + /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0xF, 4, 24); + if (ret < 0) { + dev_err(card->dev, "can't set codec pcm format %d\n", ret); + return ret; + } + + card->dapm.idle_bias_off = true; + + return 0; +} + +static int avs_rt274_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate, *channels; + struct snd_mask *fmt; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + /* The ADSP will convert the FE rate to 48k, stereo */ + rate->min = rate->max = AVS_RT274_BE_FIXUP_RATE; + channels->min = channels->max = 2; + + /* set SSPN to 24 bit */ + snd_mask_none(fmt); + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); + + return 0; +} + +static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, + struct snd_soc_dai_link **dai_link) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + + dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); + if (!dl->name || !dl->cpus || !dl->codecs) + return -ENOMEM; + + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-INT34C2:00"); + dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, "rt274-aif1"); + if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) + return -ENOMEM; + + dl->num_cpus = 1; + dl->num_codecs = 1; + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; + dl->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->init = avs_rt274_codec_init; + dl->be_hw_params_fixup = avs_rt274_be_fixup; + dl->nonatomic = 1; + dl->no_pcm = 1; + dl->dpcm_capture = 1; + dl->dpcm_playback = 1; + + *dai_link = dl; + + return 0; +} + +static int avs_create_dapm_routes(struct device *dev, int ssp_port, + struct snd_soc_dapm_route **routes, int *num_routes) +{ + struct snd_soc_dapm_route *dr; + const int num_base = ARRAY_SIZE(card_base_routes); + const int num_dr = num_base + 2; + int idx; + + dr = devm_kcalloc(dev, num_dr, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + memcpy(dr, card_base_routes, num_base * sizeof(*dr)); + + idx = num_base; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "AIF1 Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + idx++; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Rx", ssp_port); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "AIF1 Capture"); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + *routes = dr; + *num_routes = num_dr; + + return 0; +} + +static int avs_card_set_jack(struct snd_soc_card *card, struct snd_soc_jack *jack) +{ + struct snd_soc_component *component; + + for_each_card_components(card, component) + snd_soc_component_set_jack(component, jack, NULL); + return 0; +} + +static int avs_card_remove(struct snd_soc_card *card) +{ + return avs_card_set_jack(card, NULL); +} + +static int avs_card_suspend_pre(struct snd_soc_card *card) +{ + return avs_card_set_jack(card, NULL); +} + +static int avs_card_resume_post(struct snd_soc_card *card) +{ + struct snd_soc_jack *jack = snd_soc_card_get_drvdata(card); + + return avs_card_set_jack(card, jack); +} + +static int avs_rt274_probe(struct platform_device *pdev) +{ + struct snd_soc_dapm_route *routes; + struct snd_soc_dai_link *dai_link; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct snd_soc_jack *jack; + struct device *dev = &pdev->dev; + const char *pname; + int num_routes, ssp_port, ret; + + mach = dev_get_platdata(dev); + pname = mach->mach_params.platform; + ssp_port = __ffs(mach->mach_params.i2s_link_mask); + + ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + if (ret) { + dev_err(dev, "Failed to create dai link: %d", ret); + return ret; + } + + ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes); + if (ret) { + dev_err(dev, "Failed to create dapm routes: %d", ret); + return ret; + } + + jack = devm_kzalloc(dev, sizeof(*jack), GFP_KERNEL); + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!jack || !card) + return -ENOMEM; + + card->name = "avs_rt274"; + card->dev = dev; + card->owner = THIS_MODULE; + card->remove = avs_card_remove; + card->suspend_pre = avs_card_suspend_pre; + card->resume_post = avs_card_resume_post; + card->dai_link = dai_link; + card->num_links = 1; + card->controls = card_controls; + card->num_controls = ARRAY_SIZE(card_controls); + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = routes; + card->num_dapm_routes = num_routes; + card->fully_routed = true; + snd_soc_card_set_drvdata(card, jack); + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_rt274_driver = { + .probe = avs_rt274_probe, + .driver = { + .name = "avs_rt274", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_rt274_driver); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_rt274"); -- cgit From 1d395ee2e19b33a1008acfc7af186f2851b63d01 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:23:56 +0200 Subject: ASoC: Intel: avs: Add rt286 machine board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To support AVS-rt286 configuration add machine board connecting AVS platform component driver with rt286 codec one. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-8-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/Kconfig | 10 ++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/rt286.c | 281 ++++++++++++++++++++++++++++++++++++ 3 files changed, 293 insertions(+) create mode 100644 sound/soc/intel/avs/boards/rt286.c diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index 9058919c99a7..707e9e96746d 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -36,4 +36,14 @@ config SND_SOC_INTEL_AVS_MACH_RT274 Say Y or m if you have such a device. This is a recommended option. If unsure select "N". +config SND_SOC_INTEL_AVS_MACH_RT286 + tristate "rt286 in I2S mode" + depends on I2C + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_RT286 + help + This adds support for ASoC machine driver with RT286 I2S audio codec. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + endmenu diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index e94f04d00ffc..7ea4ad38c7df 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -4,8 +4,10 @@ snd-soc-avs-dmic-objs := dmic.o snd-soc-avs-hdaudio-objs := hdaudio.o snd-soc-avs-i2s-test-objs := i2s_test.o snd-soc-avs-rt274-objs := rt274.o +snd-soc-avs-rt286-objs := rt286.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_i2s_TEST) += snd-soc-avs-i2s-test.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o diff --git a/sound/soc/intel/avs/boards/rt286.c b/sound/soc/intel/avs/boards/rt286.c new file mode 100644 index 000000000000..e51d4e181274 --- /dev/null +++ b/sound/soc/intel/avs/boards/rt286.c @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include +#include +#include +#include +#include "../../../codecs/rt286.h" + +static const struct snd_kcontrol_new card_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Mic Jack"), + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_soc_dapm_route card_base_routes[] = { + /* HP jack connectors - unknown if we have jack detect */ + {"Headphone Jack", NULL, "HPO Pin"}, + {"MIC1", NULL, "Mic Jack"}, + + {"Speaker", NULL, "SPOR"}, + {"Speaker", NULL, "SPOL"}, +}; + +static struct snd_soc_jack_pin card_headset_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Mic Jack", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static int avs_rt286_codec_init(struct snd_soc_pcm_runtime *runtime) +{ + struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; + struct snd_soc_jack_pin *pins; + struct snd_soc_jack *jack; + struct snd_soc_card *card = runtime->card; + int num_pins, ret; + + jack = snd_soc_card_get_drvdata(card); + num_pins = ARRAY_SIZE(card_headset_pins); + + pins = devm_kmemdup(card->dev, card_headset_pins, sizeof(*pins) * num_pins, GFP_KERNEL); + if (!pins) + return -ENOMEM; + + ret = snd_soc_card_jack_new_pins(card, "Headset", SND_JACK_HEADSET | SND_JACK_BTN_0, jack, + pins, num_pins); + if (ret) + return ret; + + snd_soc_component_set_jack(component, jack, NULL); + + return 0; +} + +static int avs_rt286_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate, *channels; + struct snd_mask *fmt; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + /* The ADSP will convert the FE rate to 48k, stereo */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSP0 to 24 bit */ + snd_mask_none(fmt); + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); + + return 0; +} + +static int +avs_rt286_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *runtime = substream->private_data; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); + int ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000, SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(runtime->dev, "Set codec sysclk failed: %d\n", ret); + + return ret; +} + +static const struct snd_soc_ops avs_rt286_ops = { + .hw_params = avs_rt286_hw_params, +}; + +static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, + struct snd_soc_dai_link **dai_link) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + + dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); + if (!dl->name || !dl->cpus || !dl->codecs) + return -ENOMEM; + + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-INT343A:00"); + dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, "rt286-aif1"); + if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) + return -ENOMEM; + + dl->num_cpus = 1; + dl->num_codecs = 1; + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; + dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->init = avs_rt286_codec_init; + dl->be_hw_params_fixup = avs_rt286_be_fixup; + dl->ops = &avs_rt286_ops; + dl->nonatomic = 1; + dl->no_pcm = 1; + dl->dpcm_capture = 1; + dl->dpcm_playback = 1; + + *dai_link = dl; + + return 0; +} + +static int avs_create_dapm_routes(struct device *dev, int ssp_port, + struct snd_soc_dapm_route **routes, int *num_routes) +{ + struct snd_soc_dapm_route *dr; + const int num_base = ARRAY_SIZE(card_base_routes); + const int num_dr = num_base + 2; + int idx; + + dr = devm_kcalloc(dev, num_dr, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + memcpy(dr, card_base_routes, num_base * sizeof(*dr)); + + idx = num_base; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "AIF1 Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + idx++; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Rx", ssp_port); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "AIF1 Capture"); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + *routes = dr; + *num_routes = num_dr; + + return 0; +} + +static int avs_card_set_jack(struct snd_soc_card *card, struct snd_soc_jack *jack) +{ + struct snd_soc_component *component; + + for_each_card_components(card, component) + snd_soc_component_set_jack(component, jack, NULL); + return 0; +} + +static int avs_card_remove(struct snd_soc_card *card) +{ + return avs_card_set_jack(card, NULL); +} + +static int avs_card_suspend_pre(struct snd_soc_card *card) +{ + return avs_card_set_jack(card, NULL); +} + +static int avs_card_resume_post(struct snd_soc_card *card) +{ + struct snd_soc_jack *jack = snd_soc_card_get_drvdata(card); + + return avs_card_set_jack(card, jack); +} + +static int avs_rt286_probe(struct platform_device *pdev) +{ + struct snd_soc_dapm_route *routes; + struct snd_soc_dai_link *dai_link; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct snd_soc_jack *jack; + struct device *dev = &pdev->dev; + const char *pname; + int num_routes, ssp_port, ret; + + mach = dev_get_platdata(dev); + pname = mach->mach_params.platform; + ssp_port = __ffs(mach->mach_params.i2s_link_mask); + + ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + if (ret) { + dev_err(dev, "Failed to create dai link: %d", ret); + return ret; + } + + ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes); + if (ret) { + dev_err(dev, "Failed to create dapm routes: %d", ret); + return ret; + } + + jack = devm_kzalloc(dev, sizeof(*jack), GFP_KERNEL); + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!jack || !card) + return -ENOMEM; + + card->name = "avs_rt286"; + card->dev = dev; + card->owner = THIS_MODULE; + card->remove = avs_card_remove; + card->suspend_pre = avs_card_suspend_pre; + card->resume_post = avs_card_resume_post; + card->dai_link = dai_link; + card->num_links = 1; + card->controls = card_controls; + card->num_controls = ARRAY_SIZE(card_controls); + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = routes; + card->num_dapm_routes = num_routes; + card->fully_routed = true; + snd_soc_card_set_drvdata(card, jack); + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_rt286_driver = { + .probe = avs_rt286_probe, + .driver = { + .name = "avs_rt286", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_rt286_driver); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_rt286"); -- cgit From 88429ab16df4cd4a1a77d45b90ec95cf62cc22d1 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:23:57 +0200 Subject: ASoC: Intel: avs: Add rt298 machine board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To support AVS-rt298 configuration add machine board connecting AVS platform component driver with rt298 codec one. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-9-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/Kconfig | 10 ++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/rt298.c | 281 ++++++++++++++++++++++++++++++++++++ 3 files changed, 293 insertions(+) create mode 100644 sound/soc/intel/avs/boards/rt298.c diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index 707e9e96746d..b4dc2b02097d 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -46,4 +46,14 @@ config SND_SOC_INTEL_AVS_MACH_RT286 Say Y or m if you have such a device. This is a recommended option. If unsure select "N". +config SND_SOC_INTEL_AVS_MACH_RT298 + tristate "rt298 in I2S mode" + depends on I2C + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_RT298 + help + This adds support for ASoC machine driver with RT298 I2S audio codec. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + endmenu diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index 7ea4ad38c7df..0fd664694c8c 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -5,9 +5,11 @@ snd-soc-avs-hdaudio-objs := hdaudio.o snd-soc-avs-i2s-test-objs := i2s_test.o snd-soc-avs-rt274-objs := rt274.o snd-soc-avs-rt286-objs := rt286.o +snd-soc-avs-rt298-objs := rt298.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_i2s_TEST) += snd-soc-avs-i2s-test.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT298) += snd-soc-avs-rt298.o diff --git a/sound/soc/intel/avs/boards/rt298.c b/sound/soc/intel/avs/boards/rt298.c new file mode 100644 index 000000000000..b28d36872dcb --- /dev/null +++ b/sound/soc/intel/avs/boards/rt298.c @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include +#include +#include +#include +#include "../../../codecs/rt298.h" + +static const struct snd_kcontrol_new card_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Mic Jack"), + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_soc_dapm_route card_base_routes[] = { + /* HP jack connectors - unknown if we have jack detect */ + {"Headphone Jack", NULL, "HPO Pin"}, + {"MIC1", NULL, "Mic Jack"}, + + {"Speaker", NULL, "SPOR"}, + {"Speaker", NULL, "SPOL"}, +}; + +static struct snd_soc_jack_pin card_headset_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Mic Jack", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static int avs_rt298_codec_init(struct snd_soc_pcm_runtime *runtime) +{ + struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; + struct snd_soc_jack_pin *pins; + struct snd_soc_jack *jack; + struct snd_soc_card *card = runtime->card; + int num_pins, ret; + + jack = snd_soc_card_get_drvdata(card); + num_pins = ARRAY_SIZE(card_headset_pins); + + pins = devm_kmemdup(card->dev, card_headset_pins, sizeof(*pins) * num_pins, GFP_KERNEL); + if (!pins) + return -ENOMEM; + + ret = snd_soc_card_jack_new_pins(card, "Headset", SND_JACK_HEADSET | SND_JACK_BTN_0, jack, + pins, num_pins); + if (ret) + return ret; + + snd_soc_component_set_jack(component, jack, NULL); + + return 0; +} + +static int avs_rt298_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate, *channels; + struct snd_mask *fmt; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + /* The ADSP will convert the FE rate to 48k, stereo */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSP0 to 24 bit */ + snd_mask_none(fmt); + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); + + return 0; +} + +static int +avs_rt298_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + int ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, RT298_SCLK_S_PLL, 19200000, SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(rtd->dev, "Set codec sysclk failed: %d\n", ret); + + return ret; +} + +static const struct snd_soc_ops avs_rt298_ops = { + .hw_params = avs_rt298_hw_params, +}; + +static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, + struct snd_soc_dai_link **dai_link) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + + dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); + if (!dl->name || !dl->cpus || !dl->codecs) + return -ENOMEM; + + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-INT343A:00"); + dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, "rt298-aif1"); + if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) + return -ENOMEM; + + dl->num_cpus = 1; + dl->num_codecs = 1; + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; + dl->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->init = avs_rt298_codec_init; + dl->be_hw_params_fixup = avs_rt298_be_fixup; + dl->ops = &avs_rt298_ops; + dl->nonatomic = 1; + dl->no_pcm = 1; + dl->dpcm_capture = 1; + dl->dpcm_playback = 1; + + *dai_link = dl; + + return 0; +} + +static int avs_create_dapm_routes(struct device *dev, int ssp_port, + struct snd_soc_dapm_route **routes, int *num_routes) +{ + struct snd_soc_dapm_route *dr; + const int num_base = ARRAY_SIZE(card_base_routes); + const int num_dr = num_base + 2; + int idx; + + dr = devm_kcalloc(dev, num_dr, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + memcpy(dr, card_base_routes, num_base * sizeof(*dr)); + + idx = num_base; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "AIF1 Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + idx++; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Rx", ssp_port); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "AIF1 Capture"); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + *routes = dr; + *num_routes = num_dr; + + return 0; +} + +static int avs_card_set_jack(struct snd_soc_card *card, struct snd_soc_jack *jack) +{ + struct snd_soc_component *component; + + for_each_card_components(card, component) + snd_soc_component_set_jack(component, jack, NULL); + return 0; +} + +static int avs_card_remove(struct snd_soc_card *card) +{ + return avs_card_set_jack(card, NULL); +} + +static int avs_card_suspend_pre(struct snd_soc_card *card) +{ + return avs_card_set_jack(card, NULL); +} + +static int avs_card_resume_post(struct snd_soc_card *card) +{ + struct snd_soc_jack *jack = snd_soc_card_get_drvdata(card); + + return avs_card_set_jack(card, jack); +} + +static int avs_rt298_probe(struct platform_device *pdev) +{ + struct snd_soc_dapm_route *routes; + struct snd_soc_dai_link *dai_link; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct snd_soc_jack *jack; + struct device *dev = &pdev->dev; + const char *pname; + int num_routes, ssp_port, ret; + + mach = dev_get_platdata(dev); + pname = mach->mach_params.platform; + ssp_port = __ffs(mach->mach_params.i2s_link_mask); + + ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + if (ret) { + dev_err(dev, "Failed to create dai link: %d", ret); + return ret; + } + + ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes); + if (ret) { + dev_err(dev, "Failed to create dapm routes: %d", ret); + return ret; + } + + jack = devm_kzalloc(dev, sizeof(*jack), GFP_KERNEL); + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!jack || !card) + return -ENOMEM; + + card->name = "avs_rt298"; + card->dev = dev; + card->owner = THIS_MODULE; + card->remove = avs_card_remove; + card->suspend_pre = avs_card_suspend_pre; + card->resume_post = avs_card_resume_post; + card->dai_link = dai_link; + card->num_links = 1; + card->controls = card_controls; + card->num_controls = ARRAY_SIZE(card_controls); + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = routes; + card->num_dapm_routes = num_routes; + card->fully_routed = true; + snd_soc_card_set_drvdata(card, jack); + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_rt298_driver = { + .probe = avs_rt298_probe, + .driver = { + .name = "avs_rt298", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_rt298_driver); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_rt298"); -- cgit From 748102786b3ce0bf402c2dc42386cbfaab71ac39 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:23:58 +0200 Subject: ASoC: Intel: avs: Add rt5682 machine board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To support AVS-rt5682 configuration add machine board connecting AVS platform component driver with rt5682 codec one. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-10-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/Kconfig | 10 ++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/rt5682.c | 340 ++++++++++++++++++++++++++++++++++++ 3 files changed, 352 insertions(+) create mode 100644 sound/soc/intel/avs/boards/rt5682.c diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index b4dc2b02097d..767eae57be57 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -56,4 +56,14 @@ config SND_SOC_INTEL_AVS_MACH_RT298 Say Y or m if you have such a device. This is a recommended option. If unsure select "N". +config SND_SOC_INTEL_AVS_MACH_RT5682 + tristate "rt5682 in I2S mode" + depends on I2C + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_RT5682_I2C + help + This adds support for ASoC machine driver with RT5682 I2S audio codec. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + endmenu diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index 0fd664694c8c..fd49bd2a5876 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -6,6 +6,7 @@ snd-soc-avs-i2s-test-objs := i2s_test.o snd-soc-avs-rt274-objs := rt274.o snd-soc-avs-rt286-objs := rt286.o snd-soc-avs-rt298-objs := rt298.o +snd-soc-avs-rt5682-objs := rt5682.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o @@ -13,3 +14,4 @@ obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_i2s_TEST) += snd-soc-avs-i2s-test.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT298) += snd-soc-avs-rt298.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT5682) += snd-soc-avs-rt5682.o diff --git a/sound/soc/intel/avs/boards/rt5682.c b/sound/soc/intel/avs/boards/rt5682.c new file mode 100644 index 000000000000..01f9b9f0c12b --- /dev/null +++ b/sound/soc/intel/avs/boards/rt5682.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../common/soc-intel-quirks.h" +#include "../../../codecs/rt5682.h" + +#define AVS_RT5682_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0)) +#define AVS_RT5682_SSP_CODEC_MASK (GENMASK(2, 0)) +#define AVS_RT5682_MCLK_EN BIT(3) +#define AVS_RT5682_MCLK_24MHZ BIT(4) + +/* Default: MCLK on, MCLK 19.2M, SSP0 */ +static unsigned long avs_rt5682_quirk = AVS_RT5682_MCLK_EN | AVS_RT5682_SSP_CODEC(0); + +static int avs_rt5682_quirk_cb(const struct dmi_system_id *id) +{ + avs_rt5682_quirk = (unsigned long)id->driver_data; + return 1; +} + +static const struct dmi_system_id avs_rt5682_quirk_table[] = { + { + .callback = avs_rt5682_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "WhiskeyLake Client"), + }, + .driver_data = (void *)(AVS_RT5682_MCLK_EN | + AVS_RT5682_MCLK_24MHZ | + AVS_RT5682_SSP_CODEC(1)), + }, + { + .callback = avs_rt5682_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"), + }, + .driver_data = (void *)(AVS_RT5682_MCLK_EN | + AVS_RT5682_SSP_CODEC(0)), + }, + {} +}; + +static const struct snd_kcontrol_new card_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_soc_dapm_route card_base_routes[] = { + /* HP jack connectors - unknown if we have jack detect */ + { "Headphone Jack", NULL, "HPOL" }, + { "Headphone Jack", NULL, "HPOR" }, + + /* other jacks */ + { "IN1P", NULL, "Headset Mic" }, +}; + +static int avs_rt5682_codec_init(struct snd_soc_pcm_runtime *runtime) +{ + struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; + struct snd_soc_jack *jack; + struct snd_soc_card *card = runtime->card; + int ret; + + jack = snd_soc_card_get_drvdata(card); + + /* Need to enable ASRC function for 24MHz mclk rate */ + if ((avs_rt5682_quirk & AVS_RT5682_MCLK_EN) && + (avs_rt5682_quirk & AVS_RT5682_MCLK_24MHZ)) { + rt5682_sel_asrc_clk_src(component, RT5682_DA_STEREO1_FILTER | + RT5682_AD_STEREO1_FILTER, RT5682_CLK_SEL_I2S1_ASRC); + } + + /* + * Headset buttons map to the google Reference headset. + * These can be configured by userspace. + */ + ret = snd_soc_card_jack_new(card, "Headset", SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3, jack); + if (ret) { + dev_err(card->dev, "Headset Jack creation failed: %d\n", ret); + return ret; + } + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + ret = snd_soc_component_set_jack(component, jack, NULL); + if (ret) { + dev_err(card->dev, "Headset Jack call-back failed: %d\n", ret); + return ret; + } + + return 0; +}; + +static int +avs_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); + int clk_id, clk_freq; + int pll_out, ret; + + if (avs_rt5682_quirk & AVS_RT5682_MCLK_EN) { + clk_id = RT5682_PLL1_S_MCLK; + if (avs_rt5682_quirk & AVS_RT5682_MCLK_24MHZ) + clk_freq = 24000000; + else + clk_freq = 19200000; + } else { + clk_id = RT5682_PLL1_S_BCLK1; + clk_freq = params_rate(params) * 50; + } + + pll_out = params_rate(params) * 512; + + ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out); + if (ret < 0) + dev_err(runtime->dev, "snd_soc_dai_set_pll err = %d\n", ret); + + /* Configure sysclk for codec */ + ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1, pll_out, SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(runtime->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); + + /* slot_width should equal or large than data length, set them be the same */ + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2, params_width(params)); + if (ret < 0) { + dev_err(runtime->dev, "set TDM slot err:%d\n", ret); + return ret; + } + + return 0; +} + +static const struct snd_soc_ops avs_rt5682_ops = { + .hw_params = avs_rt5682_hw_params, +}; + +static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, + struct snd_soc_dai_link **dai_link) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + + dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); + if (!dl->name || !dl->cpus || !dl->codecs) + return -ENOMEM; + + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-10EC5682:00"); + dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, "rt5682-aif1"); + if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) + return -ENOMEM; + + dl->num_cpus = 1; + dl->num_codecs = 1; + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; + dl->init = avs_rt5682_codec_init; + dl->ops = &avs_rt5682_ops; + dl->nonatomic = 1; + dl->no_pcm = 1; + dl->dpcm_capture = 1; + dl->dpcm_playback = 1; + + *dai_link = dl; + + return 0; +} + +static int avs_create_dapm_routes(struct device *dev, int ssp_port, + struct snd_soc_dapm_route **routes, int *num_routes) +{ + struct snd_soc_dapm_route *dr; + const int num_base = ARRAY_SIZE(card_base_routes); + const int num_dr = num_base + 2; + int idx; + + dr = devm_kcalloc(dev, num_dr, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + memcpy(dr, card_base_routes, num_base * sizeof(*dr)); + + idx = num_base; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "AIF1 Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + idx++; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Rx", ssp_port); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "AIF1 Capture"); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + *routes = dr; + *num_routes = num_dr; + + return 0; +} + +static int avs_card_set_jack(struct snd_soc_card *card, struct snd_soc_jack *jack) +{ + struct snd_soc_component *component; + + for_each_card_components(card, component) + snd_soc_component_set_jack(component, jack, NULL); + return 0; +} + +static int avs_card_remove(struct snd_soc_card *card) +{ + return avs_card_set_jack(card, NULL); +} + +static int avs_card_suspend_pre(struct snd_soc_card *card) +{ + return avs_card_set_jack(card, NULL); +} + +static int avs_card_resume_post(struct snd_soc_card *card) +{ + struct snd_soc_jack *jack = snd_soc_card_get_drvdata(card); + + return avs_card_set_jack(card, jack); +} + +static int avs_rt5682_probe(struct platform_device *pdev) +{ + struct snd_soc_dapm_route *routes; + struct snd_soc_dai_link *dai_link; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct snd_soc_jack *jack; + struct device *dev = &pdev->dev; + const char *pname; + int num_routes, ssp_port, ret; + + if (pdev->id_entry && pdev->id_entry->driver_data) + avs_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data; + + dmi_check_system(avs_rt5682_quirk_table); + dev_dbg(dev, "avs_rt5682_quirk = %lx\n", avs_rt5682_quirk); + + mach = dev_get_platdata(dev); + pname = mach->mach_params.platform; + ssp_port = __ffs(mach->mach_params.i2s_link_mask); + + ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + if (ret) { + dev_err(dev, "Failed to create dai link: %d", ret); + return ret; + } + + ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes); + if (ret) { + dev_err(dev, "Failed to create dapm routes: %d", ret); + return ret; + } + + jack = devm_kzalloc(dev, sizeof(*jack), GFP_KERNEL); + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!jack || !card) + return -ENOMEM; + + card->name = "avs_rt5682"; + card->dev = dev; + card->owner = THIS_MODULE; + card->remove = avs_card_remove; + card->suspend_pre = avs_card_suspend_pre; + card->resume_post = avs_card_resume_post; + card->dai_link = dai_link; + card->num_links = 1; + card->controls = card_controls; + card->num_controls = ARRAY_SIZE(card_controls); + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = routes; + card->num_dapm_routes = num_routes; + card->fully_routed = true; + snd_soc_card_set_drvdata(card, jack); + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_rt5682_driver = { + .probe = avs_rt5682_probe, + .driver = { + .name = "avs_rt5682", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_rt5682_driver) + +MODULE_AUTHOR("Cezary Rojewski "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_rt5682"); -- cgit From 32ee40b5590081a6b38a55e4ab16b47085f93afe Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:23:59 +0200 Subject: ASoC: Intel: avs: Add nau8825 machine board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To support AVS-nau8825 configuration add machine board connecting AVS platform component driver with nau8825 codec one. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-11-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/Kconfig | 11 ++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/nau8825.c | 353 +++++++++++++++++++++++++++++++++++ 3 files changed, 366 insertions(+) create mode 100644 sound/soc/intel/avs/boards/nau8825.c diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index 767eae57be57..6bf8fa1924a2 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -26,6 +26,17 @@ config SND_SOC_INTEL_AVS_MACH_I2S_TEST This adds support for I2S test-board which can be used to verify transfer over I2S interface with SSP loopback scenarios. +config SND_SOC_INTEL_AVS_MACH_NAU8825 + tristate "nau8825 I2S board" + depends on I2C + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_NAU8825 + help + This adds support for ASoC machine driver with NAU8825 I2S audio codec. + It is meant to be used with AVS driver. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + config SND_SOC_INTEL_AVS_MACH_RT274 tristate "rt274 in I2S mode" depends on I2C diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index fd49bd2a5876..9ac14b269f56 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -3,6 +3,7 @@ snd-soc-avs-dmic-objs := dmic.o snd-soc-avs-hdaudio-objs := hdaudio.o snd-soc-avs-i2s-test-objs := i2s_test.o +snd-soc-avs-nau8825-objs := nau8825.o snd-soc-avs-rt274-objs := rt274.o snd-soc-avs-rt286-objs := rt286.o snd-soc-avs-rt298-objs := rt298.o @@ -11,6 +12,7 @@ snd-soc-avs-rt5682-objs := rt5682.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_i2s_TEST) += snd-soc-avs-i2s-test.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_NAU8825) += snd-soc-avs-nau8825.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT298) += snd-soc-avs-rt298.o diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c new file mode 100644 index 000000000000..f76909e9f990 --- /dev/null +++ b/sound/soc/intel/avs/boards/nau8825.c @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../codecs/nau8825.h" + +#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" + +static int +avs_nau8825_clock_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *control, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct snd_soc_dai *codec_dai; + int ret; + + codec_dai = snd_soc_card_get_codec_dai(card, SKL_NUVOTON_CODEC_DAI); + if (!codec_dai) { + dev_err(card->dev, "Codec dai not found\n"); + return -EINVAL; + } + + if (!SND_SOC_DAPM_EVENT_ON(event)) { + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "set sysclk err = %d\n", ret); + return ret; + } + } + + return 0; +} + +static const struct snd_kcontrol_new card_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, avs_nau8825_clock_control, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route card_base_routes[] = { + { "Headphone Jack", NULL, "HPOL" }, + { "Headphone Jack", NULL, "HPOR" }, + + { "MIC", NULL, "Headset Mic" }, + + { "Headphone Jack", NULL, "Platform Clock" }, + { "Headset Mic", NULL, "Platform Clock" }, +}; + +static struct snd_soc_jack_pin card_headset_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static int avs_nau8825_codec_init(struct snd_soc_pcm_runtime *runtime) +{ + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); + struct snd_soc_component *component = codec_dai->component; + struct snd_soc_jack_pin *pins; + struct snd_soc_jack *jack; + struct snd_soc_card *card = runtime->card; + int num_pins, ret; + + jack = snd_soc_card_get_drvdata(card); + num_pins = ARRAY_SIZE(card_headset_pins); + + pins = devm_kmemdup(card->dev, card_headset_pins, sizeof(*pins) * num_pins, GFP_KERNEL); + if (!pins) + return -ENOMEM; + + /* + * 4 buttons here map to the google Reference headset. + * The use of these buttons can be decided by the user space. + */ + ret = snd_soc_card_jack_new_pins(card, "Headset", SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3, + jack, pins, num_pins); + if (ret) + return ret; + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + //snd_soc_component_set_jack(component, jack, NULL); + // TODO: Fix nau8825 codec to use .set_jack, like everyone else + nau8825_enable_jack_detect(component, jack); + + return 0; +} + +static int +avs_nau8825_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate, *channels; + struct snd_mask *fmt; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + /* The ADSP will convert the FE rate to 48k, stereo */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSP to 24 bit */ + snd_mask_none(fmt); + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); + + return 0; +} + +static int avs_nau8825_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtm = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtm, 0); + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_FS, 0, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, "can't set FS clock %d\n", ret); + break; + } + + ret = snd_soc_dai_set_pll(codec_dai, 0, 0, runtime->rate, runtime->rate * 256); + if (ret < 0) + dev_err(codec_dai->dev, "can't set FLL: %d\n", ret); + break; + + case SNDRV_PCM_TRIGGER_RESUME: + ret = snd_soc_dai_set_pll(codec_dai, 0, 0, runtime->rate, runtime->rate * 256); + if (ret < 0) + dev_err(codec_dai->dev, "can't set FLL: %d\n", ret); + break; + } + + return ret; +} + + +static const struct snd_soc_ops avs_nau8825_ops = { + .trigger = avs_nau8825_trigger, +}; + +static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, + struct snd_soc_dai_link **dai_link) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + + dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); + if (!dl->name || !dl->cpus || !dl->codecs) + return -ENOMEM; + + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-10508825:00"); + dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, SKL_NUVOTON_CODEC_DAI); + if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) + return -ENOMEM; + + dl->num_cpus = 1; + dl->num_codecs = 1; + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; + dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->init = avs_nau8825_codec_init; + dl->be_hw_params_fixup = avs_nau8825_be_fixup; + dl->ops = &avs_nau8825_ops; + dl->nonatomic = 1; + dl->no_pcm = 1; + dl->dpcm_capture = 1; + dl->dpcm_playback = 1; + + *dai_link = dl; + + return 0; +} + +static int avs_create_dapm_routes(struct device *dev, int ssp_port, + struct snd_soc_dapm_route **routes, int *num_routes) +{ + struct snd_soc_dapm_route *dr; + const int num_base = ARRAY_SIZE(card_base_routes); + const int num_dr = num_base + 2; + int idx; + + dr = devm_kcalloc(dev, num_dr, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + memcpy(dr, card_base_routes, num_base * sizeof(*dr)); + + idx = num_base; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + idx++; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Rx", ssp_port); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "Capture"); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + *routes = dr; + *num_routes = num_dr; + + return 0; +} + +static int avs_card_set_jack(struct snd_soc_card *card, struct snd_soc_jack *jack) +{ + struct snd_soc_component *component; + + for_each_card_components(card, component) + snd_soc_component_set_jack(component, jack, NULL); + return 0; +} + +static int avs_card_remove(struct snd_soc_card *card) +{ + return avs_card_set_jack(card, NULL); +} + +static int avs_card_suspend_pre(struct snd_soc_card *card) +{ + return avs_card_set_jack(card, NULL); +} + +static int avs_card_resume_post(struct snd_soc_card *card) +{ + struct snd_soc_dai *codec_dai = snd_soc_card_get_codec_dai(card, SKL_NUVOTON_CODEC_DAI); + struct snd_soc_jack *jack = snd_soc_card_get_drvdata(card); + + if (!codec_dai) { + dev_err(card->dev, "Codec dai not found\n"); + return -EINVAL; + } + + if (codec_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK] && + codec_dai->playback_widget->active) + snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_FS, 0, SND_SOC_CLOCK_IN); + + return avs_card_set_jack(card, jack); +} + +static int avs_nau8825_probe(struct platform_device *pdev) +{ + struct snd_soc_dapm_route *routes; + struct snd_soc_dai_link *dai_link; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct snd_soc_jack *jack; + struct device *dev = &pdev->dev; + const char *pname; + int num_routes, ssp_port, ret; + + mach = dev_get_platdata(dev); + pname = mach->mach_params.platform; + ssp_port = __ffs(mach->mach_params.i2s_link_mask); + + ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + if (ret) { + dev_err(dev, "Failed to create dai link: %d", ret); + return ret; + } + + ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes); + if (ret) { + dev_err(dev, "Failed to create dapm routes: %d", ret); + return ret; + } + + jack = devm_kzalloc(dev, sizeof(*jack), GFP_KERNEL); + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!jack || !card) + return -ENOMEM; + + card->name = "avs_nau8825"; + card->dev = dev; + card->owner = THIS_MODULE; + card->remove = avs_card_remove; + card->suspend_pre = avs_card_suspend_pre; + card->resume_post = avs_card_resume_post; + card->dai_link = dai_link; + card->num_links = 1; + card->controls = card_controls; + card->num_controls = ARRAY_SIZE(card_controls); + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = routes; + card->num_dapm_routes = num_routes; + card->fully_routed = true; + snd_soc_card_set_drvdata(card, jack); + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_nau8825_driver = { + .probe = avs_nau8825_probe, + .driver = { + .name = "avs_nau8825", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_nau8825_driver) + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_nau8825"); -- cgit From 69ea14efe99b533652255b07a9736a9856f50ea5 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:24:00 +0200 Subject: ASoC: Intel: avs: Add ssm4567 machine board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To support AVS-ssm4567 configuration add machine board connecting AVS platform component driver with ssm4567 codec one. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-12-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/Kconfig | 11 ++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/ssm4567.c | 271 +++++++++++++++++++++++++++++++++++ 3 files changed, 284 insertions(+) create mode 100644 sound/soc/intel/avs/boards/ssm4567.c diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index 6bf8fa1924a2..7020e7bf196e 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -77,4 +77,15 @@ config SND_SOC_INTEL_AVS_MACH_RT5682 Say Y or m if you have such a device. This is a recommended option. If unsure select "N". +config SND_SOC_INTEL_AVS_MACH_SSM4567 + tristate "ssm4567 I2S board" + depends on I2C + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_SSM4567 + help + This adds support for ASoC machine driver with SSM4567 I2S audio codec. + It is meant to be used with AVS driver. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + endmenu diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index 9ac14b269f56..ea67fc711d9d 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -8,6 +8,7 @@ snd-soc-avs-rt274-objs := rt274.o snd-soc-avs-rt286-objs := rt286.o snd-soc-avs-rt298-objs := rt298.o snd-soc-avs-rt5682-objs := rt5682.o +snd-soc-avs-ssm4567-objs := ssm4567.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o @@ -17,3 +18,4 @@ obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT298) += snd-soc-avs-rt298.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT5682) += snd-soc-avs-rt5682.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_SSM4567) += snd-soc-avs-ssm4567.o diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c new file mode 100644 index 000000000000..9f84c8ab3447 --- /dev/null +++ b/sound/soc/intel/avs/boards/ssm4567.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include +#include +#include +#include +#include +#include "../../../codecs/nau8825.h" + +#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" +#define SKL_SSM_CODEC_DAI "ssm4567-hifi" + +static struct snd_soc_codec_conf card_codec_conf[] = { + { + .dlc = COMP_CODEC_CONF("i2c-INT343B:00"), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF("i2c-INT343B:01"), + .name_prefix = "Right", + }, +}; + +static const struct snd_kcontrol_new card_controls[] = { + SOC_DAPM_PIN_SWITCH("Left Speaker"), + SOC_DAPM_PIN_SWITCH("Right Speaker"), +}; + +static int +platform_clock_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *control, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct snd_soc_dai *codec_dai; + int ret; + + codec_dai = snd_soc_card_get_codec_dai(card, SKL_NUVOTON_CODEC_DAI); + if (!codec_dai) { + dev_err(card->dev, "Codec dai not found\n"); + return -EINVAL; + } + + if (SND_SOC_DAPM_EVENT_ON(event)) { + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_MCLK, 24000000, + SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(card->dev, "set sysclk err = %d\n", ret); + } else { + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(card->dev, "set sysclk err = %d\n", ret); + } + + return ret; +} + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_SPK("Left Speaker", NULL), + SND_SOC_DAPM_SPK("Right Speaker", NULL), + SND_SOC_DAPM_SPK("DP1", NULL), + SND_SOC_DAPM_SPK("DP2", NULL), + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route card_base_routes[] = { + {"Left Speaker", NULL, "Left OUT"}, + {"Right Speaker", NULL, "Right OUT"}, +}; + +static int avs_ssm4567_codec_init(struct snd_soc_pcm_runtime *runtime) +{ + int ret; + + /* Slot 1 for left */ + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(runtime, 0), 0x01, 0x01, 2, 48); + if (ret < 0) + return ret; + + /* Slot 2 for right */ + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(runtime, 1), 0x02, 0x02, 2, 48); + if (ret < 0) + return ret; + + return 0; +} + +static int +avs_ssm4567_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate, *channels; + struct snd_mask *fmt; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + /* The ADSP will covert the FE rate to 48k, stereo */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSP0 to 24 bit */ + snd_mask_none(fmt); + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); + return 0; +} + +static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, + struct snd_soc_dai_link **dai_link) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + + dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs) * 2, GFP_KERNEL); + if (!dl->name || !dl->cpus || !dl->codecs) + return -ENOMEM; + + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->codecs[0].name = devm_kasprintf(dev, GFP_KERNEL, "i2c-INT343B:00"); + dl->codecs[0].dai_name = devm_kasprintf(dev, GFP_KERNEL, "ssm4567-hifi"); + dl->codecs[1].name = devm_kasprintf(dev, GFP_KERNEL, "i2c-INT343B:01"); + dl->codecs[1].dai_name = devm_kasprintf(dev, GFP_KERNEL, "ssm4567-hifi"); + if (!dl->cpus->dai_name || !dl->codecs[0].name || !dl->codecs[0].dai_name || + !dl->codecs[1].name || !dl->codecs[1].dai_name) + return -ENOMEM; + + dl->num_cpus = 1; + dl->num_codecs = 2; + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; + dl->dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->init = avs_ssm4567_codec_init; + dl->be_hw_params_fixup = avs_ssm4567_be_fixup; + dl->nonatomic = 1; + dl->no_pcm = 1; + dl->dpcm_capture = 1; + dl->dpcm_playback = 1; + dl->ignore_pmdown_time = 1; + + *dai_link = dl; + + return 0; +} + +static int avs_create_dapm_routes(struct device *dev, int ssp_port, + struct snd_soc_dapm_route **routes, int *num_routes) +{ + struct snd_soc_dapm_route *dr; + const int num_base = ARRAY_SIZE(card_base_routes); + const int num_dr = num_base + 4; + int idx; + + dr = devm_kcalloc(dev, num_dr, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + memcpy(dr, card_base_routes, num_base * sizeof(*dr)); + + idx = num_base; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "Left Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + idx++; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "Right Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + idx++; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Rx", ssp_port); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "Left Capture Sense"); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + idx++; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Rx", ssp_port); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "Right Capture Sense"); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + *routes = dr; + *num_routes = num_dr; + + return 0; +} + +static int avs_ssm4567_probe(struct platform_device *pdev) +{ + struct snd_soc_dapm_route *routes; + struct snd_soc_dai_link *dai_link; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct device *dev = &pdev->dev; + const char *pname; + int num_routes, ssp_port, ret; + + mach = dev_get_platdata(dev); + pname = mach->mach_params.platform; + ssp_port = __ffs(mach->mach_params.i2s_link_mask); + + ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + if (ret) { + dev_err(dev, "Failed to create dai link: %d", ret); + return ret; + } + + ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes); + if (ret) { + dev_err(dev, "Failed to create dapm routes: %d", ret); + return ret; + } + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + card->name = "avs_ssm4567-adi"; + card->dev = dev; + card->owner = THIS_MODULE; + card->dai_link = dai_link; + card->num_links = 1; + card->codec_conf = card_codec_conf; + card->num_configs = ARRAY_SIZE(card_codec_conf); + card->controls = card_controls; + card->num_controls = ARRAY_SIZE(card_controls); + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = routes; + card->num_dapm_routes = num_routes; + card->fully_routed = true; + card->disable_route_checks = true; + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_ssm4567_driver = { + .probe = avs_ssm4567_probe, + .driver = { + .name = "avs_ssm4567", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_ssm4567_driver) + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_ssm4567"); -- cgit From 282c8f8de72f95325225d94caef61f3cc96401da Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:24:01 +0200 Subject: ASoC: Intel: avs: Add max98357a machine board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To support AVS-max98357a configuration add machine board connecting AVS platform component driver with max98357a codec one. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-13-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/Kconfig | 10 +++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/max98357a.c | 154 +++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 sound/soc/intel/avs/boards/max98357a.c diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index 7020e7bf196e..28e6691270d9 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -26,6 +26,16 @@ config SND_SOC_INTEL_AVS_MACH_I2S_TEST This adds support for I2S test-board which can be used to verify transfer over I2S interface with SSP loopback scenarios. +config SND_SOC_INTEL_AVS_MACH_MAX98357A + tristate "max98357A I2S board" + depends on I2C + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_MAX98357A + help + This adds support for AVS with MAX98357A I2S codec configuration. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + config SND_SOC_INTEL_AVS_MACH_NAU8825 tristate "nau8825 I2S board" depends on I2C diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index ea67fc711d9d..f7ac1151a8f7 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -3,6 +3,7 @@ snd-soc-avs-dmic-objs := dmic.o snd-soc-avs-hdaudio-objs := hdaudio.o snd-soc-avs-i2s-test-objs := i2s_test.o +snd-soc-avs-max98357a-objs := max98357a.o snd-soc-avs-nau8825-objs := nau8825.o snd-soc-avs-rt274-objs := rt274.o snd-soc-avs-rt286-objs := rt286.o @@ -13,6 +14,7 @@ snd-soc-avs-ssm4567-objs := ssm4567.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_i2s_TEST) += snd-soc-avs-i2s-test.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98357A) += snd-soc-avs-max98357a.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_NAU8825) += snd-soc-avs-nau8825.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o diff --git a/sound/soc/intel/avs/boards/max98357a.c b/sound/soc/intel/avs/boards/max98357a.c new file mode 100644 index 000000000000..921f42caf7e0 --- /dev/null +++ b/sound/soc/intel/avs/boards/max98357a.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include +#include +#include + +static const struct snd_kcontrol_new card_controls[] = { + SOC_DAPM_PIN_SWITCH("Spk"), +}; + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_SPK("Spk", NULL), +}; + +static const struct snd_soc_dapm_route card_base_routes[] = { + { "Spk", NULL, "Speaker" }, +}; + +static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, + struct snd_soc_dai_link **dai_link) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + + dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); + if (!dl->name || !dl->cpus || !dl->codecs) + return -ENOMEM; + + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "MX98357A:00"); + dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, "HiFi"); + if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) + return -ENOMEM; + + dl->num_cpus = 1; + dl->num_codecs = 1; + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; + dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->nonatomic = 1; + dl->no_pcm = 1; + dl->dpcm_playback = 1; + + *dai_link = dl; + + return 0; +} + +static int avs_create_dapm_routes(struct device *dev, int ssp_port, + struct snd_soc_dapm_route **routes, int *num_routes) +{ + struct snd_soc_dapm_route *dr; + const int num_base = ARRAY_SIZE(card_base_routes); + const int num_dr = num_base + 1; + int idx; + + dr = devm_kcalloc(dev, num_dr, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + memcpy(dr, card_base_routes, num_base * sizeof(*dr)); + + idx = num_base; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "HiFi Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + *routes = dr; + *num_routes = num_dr; + + return 0; +} + +static int avs_max98357a_probe(struct platform_device *pdev) +{ + struct snd_soc_dapm_route *routes; + struct snd_soc_dai_link *dai_link; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct device *dev = &pdev->dev; + const char *pname; + int num_routes, ssp_port, ret; + + mach = dev_get_platdata(dev); + pname = mach->mach_params.platform; + ssp_port = __ffs(mach->mach_params.i2s_link_mask); + + ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + if (ret) { + dev_err(dev, "Failed to create dai link: %d", ret); + return ret; + } + + ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes); + if (ret) { + dev_err(dev, "Failed to create dapm routes: %d", ret); + return ret; + } + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + card->name = "avs_max98357a"; + card->dev = dev; + card->owner = THIS_MODULE; + card->dai_link = dai_link; + card->num_links = 1; + card->controls = card_controls; + card->num_controls = ARRAY_SIZE(card_controls); + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = routes; + card->num_dapm_routes = num_routes; + card->fully_routed = true; + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_max98357a_driver = { + .probe = avs_max98357a_probe, + .driver = { + .name = "avs_max98357a", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_max98357a_driver) + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_max98357a"); -- cgit From 223a0a945821b96f4ccd9940ee975499706e1794 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 11 May 2022 18:24:02 +0200 Subject: ASoC: Intel: avs: Add max98373 machine board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To support AVS-max98373 configuration add machine board connecting AVS platform component driver with max98373 codec one. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-14-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/Kconfig | 10 ++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/max98373.c | 239 ++++++++++++++++++++++++++++++++++ 3 files changed, 251 insertions(+) create mode 100644 sound/soc/intel/avs/boards/max98373.c diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index 28e6691270d9..d3be6dc1fc10 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -36,6 +36,16 @@ config SND_SOC_INTEL_AVS_MACH_MAX98357A Say Y or m if you have such a device. This is a recommended option. If unsure select "N". +config SND_SOC_INTEL_AVS_MACH_MAX98373 + tristate "max98373 I2S board" + depends on I2C + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_MAX98373 + help + This adds support for AVS with MAX98373 I2S codec configuration. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + config SND_SOC_INTEL_AVS_MACH_NAU8825 tristate "nau8825 I2S board" depends on I2C diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index f7ac1151a8f7..0bce31e192ce 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -4,6 +4,7 @@ snd-soc-avs-dmic-objs := dmic.o snd-soc-avs-hdaudio-objs := hdaudio.o snd-soc-avs-i2s-test-objs := i2s_test.o snd-soc-avs-max98357a-objs := max98357a.o +snd-soc-avs-max98373-objs := max98373.o snd-soc-avs-nau8825-objs := nau8825.o snd-soc-avs-rt274-objs := rt274.o snd-soc-avs-rt286-objs := rt286.o @@ -15,6 +16,7 @@ obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_i2s_TEST) += snd-soc-avs-i2s-test.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98357A) += snd-soc-avs-max98357a.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_MAX98373) += snd-soc-avs-max98373.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_NAU8825) += snd-soc-avs-nau8825.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT274) += snd-soc-avs-rt274.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_RT286) += snd-soc-avs-rt286.o diff --git a/sound/soc/intel/avs/boards/max98373.c b/sound/soc/intel/avs/boards/max98373.c new file mode 100644 index 000000000000..0fa8f5606385 --- /dev/null +++ b/sound/soc/intel/avs/boards/max98373.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Authors: Cezary Rojewski +// Amadeusz Slawinski +// + +#include +#include +#include +#include +#include +#include + +#define MAX98373_DEV0_NAME "i2c-MX98373:00" +#define MAX98373_DEV1_NAME "i2c-MX98373:01" +#define MAX98373_CODEC_NAME "max98373-aif1" + +static struct snd_soc_codec_conf card_codec_conf[] = { + { + .dlc = COMP_CODEC_CONF(MAX98373_DEV0_NAME), + .name_prefix = "Right", + }, + { + .dlc = COMP_CODEC_CONF(MAX98373_DEV1_NAME), + .name_prefix = "Left", + }, +}; + +static const struct snd_kcontrol_new card_controls[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), +}; + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + +static const struct snd_soc_dapm_route card_base_routes[] = { + { "Left Spk", NULL, "Left BE_OUT" }, + { "Right Spk", NULL, "Right BE_OUT" }, +}; + +static int +avs_max98373_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_params *params) +{ + struct snd_interval *rate, *channels; + struct snd_mask *fmt; + + rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + + /* The ADSP will covert the FE rate to 48k, stereo */ + rate->min = rate->max = 48000; + channels->min = channels->max = 2; + + /* set SSP0 to 16 bit */ + snd_mask_none(fmt); + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); + return 0; +} + +static int avs_max98373_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai; + int ret, i; + + for_each_rtd_codec_dais(runtime, i, codec_dai) { + if (!strcmp(codec_dai->component->name, MAX98373_DEV0_NAME)) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); + if (ret < 0) { + dev_err(runtime->dev, "DEV0 TDM slot err:%d\n", ret); + return ret; + } + } + if (!strcmp(codec_dai->component->name, MAX98373_DEV1_NAME)) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16); + if (ret < 0) { + dev_err(runtime->dev, "DEV1 TDM slot err:%d\n", ret); + return ret; + } + } + } + + return 0; +} + +static const struct snd_soc_ops avs_max98373_ops = { + .hw_params = avs_max98373_hw_params, +}; + +static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, + struct snd_soc_dai_link **dai_link) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + + dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs) * 2, GFP_KERNEL); + if (!dl->name || !dl->cpus || !dl->codecs) + return -ENOMEM; + + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->codecs[0].name = devm_kasprintf(dev, GFP_KERNEL, MAX98373_DEV0_NAME); + dl->codecs[0].dai_name = devm_kasprintf(dev, GFP_KERNEL, MAX98373_CODEC_NAME); + dl->codecs[1].name = devm_kasprintf(dev, GFP_KERNEL, MAX98373_DEV1_NAME); + dl->codecs[1].dai_name = devm_kasprintf(dev, GFP_KERNEL, MAX98373_CODEC_NAME); + if (!dl->cpus->dai_name || !dl->codecs[0].name || !dl->codecs[0].dai_name || + !dl->codecs[1].name || !dl->codecs[1].dai_name) + return -ENOMEM; + + dl->num_cpus = 1; + dl->num_codecs = 2; + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; + dl->dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + dl->be_hw_params_fixup = avs_max98373_be_fixup; + dl->nonatomic = 1; + dl->no_pcm = 1; + dl->dpcm_capture = 1; + dl->dpcm_playback = 1; + dl->ignore_pmdown_time = 1; + dl->ops = &avs_max98373_ops; + + *dai_link = dl; + + return 0; +} + +static int avs_create_dapm_routes(struct device *dev, int ssp_port, + struct snd_soc_dapm_route **routes, int *num_routes) +{ + struct snd_soc_dapm_route *dr; + const int num_base = ARRAY_SIZE(card_base_routes); + const int num_dr = num_base + 2; + int idx; + + dr = devm_kcalloc(dev, num_dr, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + memcpy(dr, card_base_routes, num_base * sizeof(*dr)); + + idx = num_base; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "Left HiFi Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + idx++; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "Right HiFi Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + *routes = dr; + *num_routes = num_dr; + + return 0; +} + +static int avs_max98373_probe(struct platform_device *pdev) +{ + struct snd_soc_dapm_route *routes; + struct snd_soc_dai_link *dai_link; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct device *dev = &pdev->dev; + const char *pname; + int num_routes, ssp_port, ret; + + mach = dev_get_platdata(dev); + pname = mach->mach_params.platform; + ssp_port = __ffs(mach->mach_params.i2s_link_mask); + + ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + if (ret) { + dev_err(dev, "Failed to create dai link: %d", ret); + return ret; + } + + ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes); + if (ret) { + dev_err(dev, "Failed to create dapm routes: %d", ret); + return ret; + } + + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + card->name = "avs_max98373"; + card->dev = dev; + card->owner = THIS_MODULE; + card->dai_link = dai_link; + card->num_links = 1; + card->codec_conf = card_codec_conf; + card->num_configs = ARRAY_SIZE(card_codec_conf); + card->controls = card_controls; + card->num_controls = ARRAY_SIZE(card_controls); + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = routes; + card->num_dapm_routes = num_routes; + card->fully_routed = true; + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_max98373_driver = { + .probe = avs_max98373_probe, + .driver = { + .name = "avs_max98373", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_max98373_driver) + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_max98373"); -- cgit From 6b5b0d6f36dd45e22f1710e8bcd97f28b4ba41f5 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 11 May 2022 18:24:03 +0200 Subject: ASoC: Intel: avs: Add da7219 machine board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To support AVS-da7219 configuration add machine board connecting AVS platform component driver with da7219 codec one. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220511162403.3987658-15-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/Kconfig | 10 ++ sound/soc/intel/avs/boards/Makefile | 2 + sound/soc/intel/avs/boards/da7219.c | 282 ++++++++++++++++++++++++++++++++++++ 3 files changed, 294 insertions(+) create mode 100644 sound/soc/intel/avs/boards/da7219.c diff --git a/sound/soc/intel/avs/boards/Kconfig b/sound/soc/intel/avs/boards/Kconfig index d3be6dc1fc10..4d68e3ef992b 100644 --- a/sound/soc/intel/avs/boards/Kconfig +++ b/sound/soc/intel/avs/boards/Kconfig @@ -4,6 +4,16 @@ menu "Intel AVS Machine drivers" comment "Available DSP configurations" +config SND_SOC_INTEL_AVS_MACH_DA7219 + tristate "da7219 I2S board" + depends on I2C + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_DA7219 + help + This adds support for AVS with DA7219 I2S codec configuration. + Say Y or m if you have such a device. This is a recommended option. + If unsure select "N". + config SND_SOC_INTEL_AVS_MACH_DMIC tristate "DMIC generic board" select SND_SOC_DMIC diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index 0bce31e192ce..25e8c4bb07db 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only +snd-soc-avs-da7219-objs := da7219.o snd-soc-avs-dmic-objs := dmic.o snd-soc-avs-hdaudio-objs := hdaudio.o snd-soc-avs-i2s-test-objs := i2s_test.o @@ -12,6 +13,7 @@ snd-soc-avs-rt298-objs := rt298.o snd-soc-avs-rt5682-objs := rt5682.o snd-soc-avs-ssm4567-objs := ssm4567.o +obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DA7219) += snd-soc-avs-da7219.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_HDAUDIO) += snd-soc-avs-hdaudio.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_i2s_TEST) += snd-soc-avs-i2s-test.o diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c new file mode 100644 index 000000000000..02ae542ad779 --- /dev/null +++ b/sound/soc/intel/avs/boards/da7219.c @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Author: Cezary Rojewski +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../codecs/da7219.h" +#include "../../../codecs/da7219-aad.h" + +#define DA7219_DAI_NAME "da7219-hifi" + +static const struct snd_kcontrol_new card_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static int platform_clock_control(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *k, int event) +{ + struct snd_soc_dapm_context *dapm = w->dapm; + struct snd_soc_card *card = dapm->card; + struct snd_soc_dai *codec_dai; + int ret = 0; + + codec_dai = snd_soc_card_get_codec_dai(card, DA7219_DAI_NAME); + if (!codec_dai) { + dev_err(card->dev, "Codec dai not found. Unable to set/unset codec pll\n"); + return -EIO; + } + + if (SND_SOC_DAPM_EVENT_OFF(event)) { + ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0); + if (ret) + dev_err(card->dev, "failed to stop PLL: %d\n", ret); + } else if (SND_SOC_DAPM_EVENT_ON(event)) { + ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL_SRM, + 0, DA7219_PLL_FREQ_OUT_98304); + if (ret) + dev_err(card->dev, "failed to start PLL: %d\n", ret); + } + + return ret; +} + +static const struct snd_soc_dapm_widget card_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), +}; + +static const struct snd_soc_dapm_route card_base_routes[] = { + /* HP jack connectors - unknown if we have jack detection */ + {"Headphone Jack", NULL, "HPL"}, + {"Headphone Jack", NULL, "HPR"}, + + {"MIC", NULL, "Headset Mic"}, + + { "Headphone Jack", NULL, "Platform Clock" }, + { "Headset Mic", NULL, "Platform Clock" }, +}; + +static int avs_da7219_codec_init(struct snd_soc_pcm_runtime *runtime) +{ + struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; + struct snd_soc_card *card = runtime->card; + struct snd_soc_jack *jack; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); + int clk_freq; + int ret; + + jack = snd_soc_card_get_drvdata(card); + clk_freq = 19200000; + + ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, clk_freq, SND_SOC_CLOCK_IN); + if (ret) { + dev_err(card->dev, "can't set codec sysclk configuration\n"); + return ret; + } + + /* + * Headset buttons map to the google Reference headset. + * These can be configured by userspace. + */ + ret = snd_soc_card_jack_new(card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3 | SND_JACK_LINEOUT, jack); + if (ret) { + dev_err(card->dev, "Headset Jack creation failed: %d\n", ret); + return ret; + } + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + + da7219_aad_jack_det(component, jack); + + return 0; +} + +static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port, + struct snd_soc_dai_link **dai_link) +{ + struct snd_soc_dai_link_component *platform; + struct snd_soc_dai_link *dl; + + dl = devm_kzalloc(dev, sizeof(*dl), GFP_KERNEL); + platform = devm_kzalloc(dev, sizeof(*platform), GFP_KERNEL); + if (!dl || !platform) + return -ENOMEM; + + platform->name = platform_name; + + dl->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_port); + dl->cpus = devm_kzalloc(dev, sizeof(*dl->cpus), GFP_KERNEL); + dl->codecs = devm_kzalloc(dev, sizeof(*dl->codecs), GFP_KERNEL); + if (!dl->name || !dl->cpus || !dl->codecs) + return -ENOMEM; + + dl->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_port); + dl->codecs->name = devm_kasprintf(dev, GFP_KERNEL, "i2c-DLGS7219:00"); + dl->codecs->dai_name = devm_kasprintf(dev, GFP_KERNEL, DA7219_DAI_NAME); + if (!dl->cpus->dai_name || !dl->codecs->name || !dl->codecs->dai_name) + return -ENOMEM; + + dl->num_cpus = 1; + dl->num_codecs = 1; + dl->platforms = platform; + dl->num_platforms = 1; + dl->id = 0; + dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; + dl->init = avs_da7219_codec_init; + dl->nonatomic = 1; + dl->no_pcm = 1; + dl->dpcm_capture = 1; + dl->dpcm_playback = 1; + + *dai_link = dl; + + return 0; +} + +static int avs_create_dapm_routes(struct device *dev, int ssp_port, + struct snd_soc_dapm_route **routes, int *num_routes) +{ + struct snd_soc_dapm_route *dr; + const int num_base = ARRAY_SIZE(card_base_routes); + const int num_dr = num_base + 2; + int idx; + + dr = devm_kcalloc(dev, num_dr, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + memcpy(dr, card_base_routes, num_base * sizeof(*dr)); + + idx = num_base; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "Playback"); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Tx", ssp_port); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + idx++; + dr[idx].sink = devm_kasprintf(dev, GFP_KERNEL, "ssp%d Rx", ssp_port); + dr[idx].source = devm_kasprintf(dev, GFP_KERNEL, "Capture"); + if (!dr[idx].sink || !dr[idx].source) + return -ENOMEM; + + *routes = dr; + *num_routes = num_dr; + + return 0; +} + +static int avs_card_set_jack(struct snd_soc_card *card, struct snd_soc_jack *jack) +{ + struct snd_soc_component *component; + + for_each_card_components(card, component) + snd_soc_component_set_jack(component, jack, NULL); + return 0; +} + +static int avs_card_remove(struct snd_soc_card *card) +{ + return avs_card_set_jack(card, NULL); +} + +static int avs_card_suspend_pre(struct snd_soc_card *card) +{ + return avs_card_set_jack(card, NULL); +} + +static int avs_card_resume_post(struct snd_soc_card *card) +{ + struct snd_soc_jack *jack = snd_soc_card_get_drvdata(card); + + return avs_card_set_jack(card, jack); +} + +static int avs_da7219_probe(struct platform_device *pdev) +{ + struct snd_soc_dapm_route *routes; + struct snd_soc_dai_link *dai_link; + struct snd_soc_acpi_mach *mach; + struct snd_soc_card *card; + struct snd_soc_jack *jack; + struct device *dev = &pdev->dev; + const char *pname; + int num_routes, ssp_port, ret; + + mach = dev_get_platdata(dev); + pname = mach->mach_params.platform; + ssp_port = __ffs(mach->mach_params.i2s_link_mask); + + ret = avs_create_dai_link(dev, pname, ssp_port, &dai_link); + if (ret) { + dev_err(dev, "Failed to create dai link: %d", ret); + return ret; + } + + ret = avs_create_dapm_routes(dev, ssp_port, &routes, &num_routes); + if (ret) { + dev_err(dev, "Failed to create dapm routes: %d", ret); + return ret; + } + + jack = devm_kzalloc(dev, sizeof(*jack), GFP_KERNEL); + card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL); + if (!jack || !card) + return -ENOMEM; + + card->name = "avs_da7219"; + card->dev = dev; + card->owner = THIS_MODULE; + card->remove = avs_card_remove; + card->suspend_pre = avs_card_suspend_pre; + card->resume_post = avs_card_resume_post; + card->dai_link = dai_link; + card->num_links = 1; + card->controls = card_controls; + card->num_controls = ARRAY_SIZE(card_controls); + card->dapm_widgets = card_widgets; + card->num_dapm_widgets = ARRAY_SIZE(card_widgets); + card->dapm_routes = routes; + card->num_dapm_routes = num_routes; + card->fully_routed = true; + snd_soc_card_set_drvdata(card, jack); + + ret = snd_soc_fixup_dai_links_platform_name(card, pname); + if (ret) + return ret; + + return devm_snd_soc_register_card(dev, card); +} + +static struct platform_driver avs_da7219_driver = { + .probe = avs_da7219_probe, + .driver = { + .name = "avs_da7219", + .pm = &snd_soc_pm_ops, + }, +}; + +module_platform_driver(avs_da7219_driver); + +MODULE_AUTHOR("Cezary Rojewski "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:avs_da7219"); -- cgit From 905f3a04e184854555fc248ca4e692fdbf2f2547 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:23 +0100 Subject: ASoC: core: Add set_fmt_new callback that directly specifies provider The original set_fmt callback always passes clock provider/consumer with respect to the CODEC. This made sense when the framework was directly broken down into platforms and CODECs. Now everything is componentised it simplifies things if each side of the link is just told if it is provider or consumer of the clocks. To start this migration add a new callback that can be used to receive a direct specification of clocking. As there are more CODEC drivers than platform drivers, we make the new flags identical to the old CODEC flags meaning CODEC drivers will not require an update. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 7 +++++++ sound/soc/soc-core.c | 3 ++- sound/soc/soc-dai.c | 5 ++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index bbd821d2df9c..9c1d92d5a373 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -124,6 +124,12 @@ struct snd_compr_stream; #define SND_SOC_DAIFMT_CBM_CFS SND_SOC_DAIFMT_CBP_CFC #define SND_SOC_DAIFMT_CBS_CFS SND_SOC_DAIFMT_CBC_CFC +/* when passed to set_fmt directly indicate if the device is provider or consumer */ +#define SND_SOC_DAIFMT_BP_FP SND_SOC_DAIFMT_CBP_CFP +#define SND_SOC_DAIFMT_BC_FP SND_SOC_DAIFMT_CBC_CFP +#define SND_SOC_DAIFMT_BP_FC SND_SOC_DAIFMT_CBP_CFC +#define SND_SOC_DAIFMT_BC_FC SND_SOC_DAIFMT_CBC_CFC + /* Describes the possible PCM format */ #define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT 48 #define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT) @@ -282,6 +288,7 @@ struct snd_soc_dai_ops { * Called by soc_card drivers, normally in their hw_params. */ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); + int (*set_fmt_new)(struct snd_soc_dai *dai, unsigned int fmt); int (*xlate_tdm_slot_mask)(unsigned int slots, unsigned int *tx_mask, unsigned int *rx_mask); int (*set_tdm_slot)(struct snd_soc_dai *dai, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 9574f86dd4de..90f4265bea50 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1235,7 +1235,8 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, for_each_rtd_cpu_dais(rtd, i, cpu_dai) { unsigned int fmt = dai_fmt; - if (snd_soc_component_is_codec(cpu_dai->component)) + if (cpu_dai->driver->ops->set_fmt_new || + snd_soc_component_is_codec(cpu_dai->component)) fmt = inv_dai_fmt; ret = snd_soc_dai_set_fmt(cpu_dai, fmt); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 6078afe335f8..996712f4d9bf 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -209,7 +209,10 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) int ret = -ENOTSUPP; if (dai->driver->ops && - dai->driver->ops->set_fmt) + dai->driver->ops->set_fmt_new) + ret = dai->driver->ops->set_fmt_new(dai, fmt); + else if (dai->driver->ops && + dai->driver->ops->set_fmt) ret = dai->driver->ops->set_fmt(dai, fmt); return soc_dai_ret(dai, ret); -- cgit From ab890e0f83a65624d20b0ca4a7cb6306b8511558 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:24 +0100 Subject: ASoC: amd: vangogh: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update this CPU side driver to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-i2s.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/vangogh/acp5x-i2s.c b/sound/soc/amd/vangogh/acp5x-i2s.c index 59a98f89a669..40fbd0bc77fd 100644 --- a/sound/soc/amd/vangogh/acp5x-i2s.c +++ b/sound/soc/amd/vangogh/acp5x-i2s.c @@ -37,10 +37,10 @@ static int acp5x_i2s_set_fmt(struct snd_soc_dai *cpu_dai, } mode = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; switch (mode) { - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: adata->master_mode = I2S_MASTER_MODE_ENABLE; break; - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: adata->master_mode = I2S_MASTER_MODE_DISABLE; break; } @@ -339,7 +339,7 @@ static int acp5x_i2s_trigger(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops acp5x_i2s_dai_ops = { .hw_params = acp5x_i2s_hwparams, .trigger = acp5x_i2s_trigger, - .set_fmt = acp5x_i2s_set_fmt, + .set_fmt_new = acp5x_i2s_set_fmt, .set_tdm_slot = acp5x_i2s_set_tdm_slot, }; -- cgit From 0fd054a577180cd807992e32c7cd394e54c85903 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:25 +0100 Subject: ASoC: atmel: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-i2s.c | 6 +++--- sound/soc/atmel/atmel_ssc_dai.c | 20 ++++++++++---------- sound/soc/atmel/mchp-i2s-mcc.c | 10 +++++----- sound/soc/atmel/mchp-pdmc.c | 6 +++--- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c index 1934767690b5..c5ce695da586 100644 --- a/sound/soc/atmel/atmel-i2s.c +++ b/sound/soc/atmel/atmel-i2s.c @@ -343,7 +343,7 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream, } switch (dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: /* codec is slave, so cpu is master */ mr |= ATMEL_I2SC_MR_MODE_MASTER; ret = atmel_i2s_get_gck_param(dev, params_rate(params)); @@ -351,7 +351,7 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream, return ret; break; - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: /* codec is master, so cpu is slave */ mr |= ATMEL_I2SC_MR_MODE_SLAVE; dev->gck_param = NULL; @@ -533,7 +533,7 @@ static const struct snd_soc_dai_ops atmel_i2s_dai_ops = { .prepare = atmel_i2s_prepare, .trigger = atmel_i2s_trigger, .hw_params = atmel_i2s_hw_params, - .set_fmt = atmel_i2s_set_dai_fmt, + .set_fmt_new = atmel_i2s_set_dai_fmt, }; static int atmel_i2s_dai_probe(struct snd_soc_dai *dai) diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index c1dea8d62416..da094762dc99 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -210,7 +210,7 @@ static int atmel_ssc_hw_rule_rate(struct snd_pcm_hw_params *params, return frame_size; switch (ssc_p->daifmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBP_CFC: + case SND_SOC_DAIFMT_BC_FP: if ((ssc_p->dir_mask & SSC_DIR_MASK_CAPTURE) && ssc->clk_from_rk_pin) /* Receiver Frame Synchro (i.e. capture) @@ -220,7 +220,7 @@ static int atmel_ssc_hw_rule_rate(struct snd_pcm_hw_params *params, mck_div = 3; break; - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: if ((ssc_p->dir_mask & SSC_DIR_MASK_PLAYBACK) && !ssc->clk_from_rk_pin) /* Transmit Frame Synchro (i.e. playback) @@ -233,7 +233,7 @@ static int atmel_ssc_hw_rule_rate(struct snd_pcm_hw_params *params, } switch (ssc_p->daifmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: r.num = ssc_p->mck_rate / mck_div / frame_size; ret = snd_interval_ratnum(i, 1, &r, &num, &den); @@ -243,8 +243,8 @@ static int atmel_ssc_hw_rule_rate(struct snd_pcm_hw_params *params, } break; - case SND_SOC_DAIFMT_CBP_CFC: - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FP: + case SND_SOC_DAIFMT_BC_FC: t.min = 8000; t.max = ssc_p->mck_rate / mck_div / frame_size; t.openmin = t.openmax = 0; @@ -433,8 +433,8 @@ static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, static int atmel_ssc_cfs(struct atmel_ssc_info *ssc_p) { switch (ssc_p->daifmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBP_CFC: - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BC_FP: + case SND_SOC_DAIFMT_BP_FP: return 1; } return 0; @@ -444,8 +444,8 @@ static int atmel_ssc_cfs(struct atmel_ssc_info *ssc_p) static int atmel_ssc_cbs(struct atmel_ssc_info *ssc_p) { switch (ssc_p->daifmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFP: - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FC: + case SND_SOC_DAIFMT_BP_FP: return 1; } return 0; @@ -835,7 +835,7 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = { .prepare = atmel_ssc_prepare, .trigger = atmel_ssc_trigger, .hw_params = atmel_ssc_hw_params, - .set_fmt = atmel_ssc_set_dai_fmt, + .set_fmt_new = atmel_ssc_set_dai_fmt, .set_clkdiv = atmel_ssc_set_dai_clkdiv, }; diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 6d1227a1d67b..48d434e0c331 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -350,7 +350,7 @@ static int mchp_i2s_mcc_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) return -EINVAL; /* We can't generate only FSYNC */ - if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) == SND_SOC_DAIFMT_CBP_CFC) + if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) == SND_SOC_DAIFMT_BC_FP) return -EINVAL; /* We can only reconfigure the IP when it's stopped */ @@ -547,19 +547,19 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, } switch (dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: /* cpu is BCLK and LRC master */ mra |= MCHP_I2SMCC_MRA_MODE_MASTER; if (dev->sysclk) mra |= MCHP_I2SMCC_MRA_IMCKMODE_GEN; set_divs = 1; break; - case SND_SOC_DAIFMT_CBC_CFP: + case SND_SOC_DAIFMT_BP_FC: /* cpu is BCLK master */ mrb |= MCHP_I2SMCC_MRB_CLKSEL_INT; set_divs = 1; fallthrough; - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: /* cpu is slave */ mra |= MCHP_I2SMCC_MRA_MODE_SLAVE; if (dev->sysclk) @@ -877,7 +877,7 @@ static const struct snd_soc_dai_ops mchp_i2s_mcc_dai_ops = { .trigger = mchp_i2s_mcc_trigger, .hw_params = mchp_i2s_mcc_hw_params, .hw_free = mchp_i2s_mcc_hw_free, - .set_fmt = mchp_i2s_mcc_set_dai_fmt, + .set_fmt_new = mchp_i2s_mcc_set_dai_fmt, .set_tdm_slot = mchp_i2s_mcc_set_dai_tdm_slot, }; diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index a3856c73e221..b3f04fa2f608 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -492,8 +492,8 @@ static int mchp_pdmc_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int fmt_format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; /* IP needs to be bitclock master */ - if (fmt_master != SND_SOC_DAIFMT_CBS_CFS && - fmt_master != SND_SOC_DAIFMT_CBS_CFM) + if (fmt_master != SND_SOC_DAIFMT_BP_FP && + fmt_master != SND_SOC_DAIFMT_BP_FC) return -EINVAL; /* IP supports only PDM interface */ @@ -708,7 +708,7 @@ static int mchp_pdmc_trigger(struct snd_pcm_substream *substream, } static const struct snd_soc_dai_ops mchp_pdmc_dai_ops = { - .set_fmt = mchp_pdmc_set_fmt, + .set_fmt_new = mchp_pdmc_set_fmt, .startup = mchp_pdmc_startup, .shutdown = mchp_pdmc_shutdown, .hw_params = mchp_pdmc_hw_params, -- cgit From fee11f70849b21a244e6e27d281f3858b671bfea Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:26 +0100 Subject: ASoC: au1x: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-5-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/au1x/i2sc.c | 4 ++-- sound/soc/au1x/psc-i2s.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c index 740d4e052e4d..72f16b7fda3e 100644 --- a/sound/soc/au1x/i2sc.c +++ b/sound/soc/au1x/i2sc.c @@ -121,7 +121,7 @@ static int au1xi2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) /* I2S controller only supports provider */ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: /* CODEC consumer */ + case SND_SOC_DAIFMT_BP_FP: /* CODEC consumer */ break; default: goto out; @@ -206,7 +206,7 @@ static const struct snd_soc_dai_ops au1xi2s_dai_ops = { .startup = au1xi2s_startup, .trigger = au1xi2s_trigger, .hw_params = au1xi2s_hw_params, - .set_fmt = au1xi2s_set_fmt, + .set_fmt_new = au1xi2s_set_fmt, }; static struct snd_soc_dai_driver au1xi2s_dai_driver = { diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index b2b8896bb593..d82c1353f2f0 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c @@ -91,10 +91,10 @@ static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, } switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBP_CFP: /* CODEC provider */ + case SND_SOC_DAIFMT_BC_FC: /* CODEC provider */ ct |= PSC_I2SCFG_MS; /* PSC I2S consumer mode */ break; - case SND_SOC_DAIFMT_CBC_CFC: /* CODEC consumer */ + case SND_SOC_DAIFMT_BP_FP: /* CODEC consumer */ ct &= ~PSC_I2SCFG_MS; /* PSC I2S provider mode */ break; default: @@ -266,7 +266,7 @@ static const struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { .startup = au1xpsc_i2s_startup, .trigger = au1xpsc_i2s_trigger, .hw_params = au1xpsc_i2s_hw_params, - .set_fmt = au1xpsc_i2s_set_fmt, + .set_fmt_new = au1xpsc_i2s_set_fmt, }; static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = { -- cgit From 04ea2404468b7885c560c3673f6f2fd368f305a2 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:27 +0100 Subject: ASoC: bcm: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-6-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/bcm/bcm2835-i2s.c | 22 +++++++++++----------- sound/soc/bcm/cygnus-ssp.c | 6 +++--- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index e3fc4bee8cfd..aa7d8e081f89 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -133,8 +133,8 @@ static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) return; switch (provider) { - case SND_SOC_DAIFMT_CBC_CFC: - case SND_SOC_DAIFMT_CBC_CFP: + case SND_SOC_DAIFMT_BP_FP: + case SND_SOC_DAIFMT_BP_FC: clk_prepare_enable(dev->clk); dev->clk_prepared = true; break; @@ -385,12 +385,12 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, /* Check if CPU is bit clock provider */ switch (dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: - case SND_SOC_DAIFMT_CBC_CFP: + case SND_SOC_DAIFMT_BP_FP: + case SND_SOC_DAIFMT_BP_FC: bit_clock_provider = true; break; - case SND_SOC_DAIFMT_CBP_CFC: - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FP: + case SND_SOC_DAIFMT_BC_FC: bit_clock_provider = false; break; default: @@ -399,12 +399,12 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, /* Check if CPU is frame sync provider */ switch (dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: - case SND_SOC_DAIFMT_CBP_CFC: + case SND_SOC_DAIFMT_BP_FP: + case SND_SOC_DAIFMT_BC_FP: frame_sync_provider = true; break; - case SND_SOC_DAIFMT_CBC_CFP: - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BP_FC: + case SND_SOC_DAIFMT_BC_FC: frame_sync_provider = false; break; default: @@ -743,7 +743,7 @@ static const struct snd_soc_dai_ops bcm2835_i2s_dai_ops = { .prepare = bcm2835_i2s_prepare, .trigger = bcm2835_i2s_trigger, .hw_params = bcm2835_i2s_hw_params, - .set_fmt = bcm2835_i2s_set_dai_fmt, + .set_fmt_new = bcm2835_i2s_set_dai_fmt, .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio, .set_tdm_slot = bcm2835_i2s_set_dai_tdm_slot, }; diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c index 9698f4531c90..257f3657bcd6 100644 --- a/sound/soc/bcm/cygnus-ssp.c +++ b/sound/soc/bcm/cygnus-ssp.c @@ -849,11 +849,11 @@ static int cygnus_ssp_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) ssp_newcfg = 0; switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: ssp_newcfg |= BIT(I2S_OUT_CFGX_SLAVE_MODE); aio->is_slave = 1; break; - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: ssp_newcfg &= ~BIT(I2S_OUT_CFGX_SLAVE_MODE); aio->is_slave = 0; break; @@ -1148,7 +1148,7 @@ static const struct snd_soc_dai_ops cygnus_ssp_dai_ops = { .shutdown = cygnus_ssp_shutdown, .trigger = cygnus_ssp_trigger, .hw_params = cygnus_ssp_hw_params, - .set_fmt = cygnus_ssp_set_fmt, + .set_fmt_new = cygnus_ssp_set_fmt, .set_sysclk = cygnus_ssp_set_sysclk, .set_tdm_slot = cygnus_set_dai_tdm_slot, }; -- cgit From 5d6124e58d56818249a6266f56d9c3739e72e1bd Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:28 +0100 Subject: ASoC: ep93xx: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update this CPU side driver to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-7-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/cirrus/ep93xx-i2s.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 2c8cd843d049..2c8b1c76b834 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -246,12 +246,12 @@ static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, } switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: /* CPU is provider */ clk_cfg |= EP93XX_I2S_CLKCFG_MASTER; break; - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: /* Codec is provider */ clk_cfg &= ~EP93XX_I2S_CLKCFG_MASTER; break; @@ -398,7 +398,7 @@ static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { .shutdown = ep93xx_i2s_shutdown, .hw_params = ep93xx_i2s_hw_params, .set_sysclk = ep93xx_i2s_set_sysclk, - .set_fmt = ep93xx_i2s_set_dai_fmt, + .set_fmt_new = ep93xx_i2s_set_dai_fmt, }; #define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) -- cgit From ca0444f1f7b228ae3b8d1a5c0f0d1b4463171f98 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:29 +0100 Subject: ASoC: dwc: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update this CPU side driver to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-8-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/dwc/dwc-i2s.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c index 1edac3e10f34..d3778d2d739d 100644 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -357,20 +357,20 @@ static int dw_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) int ret = 0; switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: if (dev->capability & DW_I2S_SLAVE) ret = 0; else ret = -EINVAL; break; - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: if (dev->capability & DW_I2S_MASTER) ret = 0; else ret = -EINVAL; break; - case SND_SOC_DAIFMT_CBP_CFC: - case SND_SOC_DAIFMT_CBC_CFP: + case SND_SOC_DAIFMT_BC_FP: + case SND_SOC_DAIFMT_BP_FC: ret = -EINVAL; break; default: @@ -387,7 +387,7 @@ static const struct snd_soc_dai_ops dw_i2s_dai_ops = { .hw_params = dw_i2s_hw_params, .prepare = dw_i2s_prepare, .trigger = dw_i2s_trigger, - .set_fmt = dw_i2s_set_fmt, + .set_fmt_new = dw_i2s_set_fmt, }; #ifdef CONFIG_PM -- cgit From 3b14c15a333b8225ea38479e13c0366539d3374a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:30 +0100 Subject: ASoC: fsl: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-9-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_audmix.c | 6 +++--- sound/soc/fsl/fsl_esai.c | 10 +++++----- sound/soc/fsl/fsl_mqs.c | 4 ++-- sound/soc/fsl/fsl_sai.c | 10 +++++----- sound/soc/fsl/fsl_ssi.c | 24 ++++++++++++------------ sound/soc/fsl/imx-audmix.c | 4 ++-- sound/soc/fsl/imx-card.c | 2 +- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 6dbb8c99f626..c580dcb9a4cf 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -259,8 +259,8 @@ static int fsl_audmix_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) /* For playback the AUDMIX is consumer, and for record is provider */ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBP_CFP: - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BC_FC: + case SND_SOC_DAIFMT_BP_FP: break; default: return -EINVAL; @@ -317,7 +317,7 @@ static int fsl_audmix_dai_trigger(struct snd_pcm_substream *substream, int cmd, } static const struct snd_soc_dai_ops fsl_audmix_dai_ops = { - .set_fmt = fsl_audmix_dai_set_fmt, + .set_fmt_new = fsl_audmix_dai_set_fmt, .trigger = fsl_audmix_dai_trigger, }; diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 1a2bdf8e76f0..572bdaee73eb 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -480,16 +480,16 @@ static int fsl_esai_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) /* DAI clock provider masks */ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: esai_priv->consumer_mode = true; break; - case SND_SOC_DAIFMT_CBC_CFP: + case SND_SOC_DAIFMT_BP_FC: xccr |= ESAI_xCCR_xCKD; break; - case SND_SOC_DAIFMT_CBP_CFC: + case SND_SOC_DAIFMT_BC_FP: xccr |= ESAI_xCCR_xFSD; break; - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD; break; default: @@ -790,7 +790,7 @@ static const struct snd_soc_dai_ops fsl_esai_dai_ops = { .trigger = fsl_esai_trigger, .hw_params = fsl_esai_hw_params, .set_sysclk = fsl_esai_set_dai_sysclk, - .set_fmt = fsl_esai_set_dai_fmt, + .set_fmt_new = fsl_esai_set_dai_fmt, .set_tdm_slot = fsl_esai_set_dai_tdm_slot, }; diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c index ceaecbe3a25e..371d441b1dbe 100644 --- a/sound/soc/fsl/fsl_mqs.c +++ b/sound/soc/fsl/fsl_mqs.c @@ -103,7 +103,7 @@ static int fsl_mqs_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) } switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: break; default: return -EINVAL; @@ -152,7 +152,7 @@ static const struct snd_soc_dai_ops fsl_mqs_dai_ops = { .startup = fsl_mqs_startup, .shutdown = fsl_mqs_shutdown, .hw_params = fsl_mqs_hw_params, - .set_fmt = fsl_mqs_set_dai_fmt, + .set_fmt_new = fsl_mqs_set_dai_fmt, }; static struct snd_soc_dai_driver fsl_mqs_dai = { diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index fa950dde5310..3edd302eb5c2 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -292,19 +292,19 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, /* DAI clock provider masks */ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: val_cr2 |= FSL_SAI_CR2_BCD_MSTR; val_cr4 |= FSL_SAI_CR4_FSD_MSTR; sai->is_consumer_mode = false; break; - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: sai->is_consumer_mode = true; break; - case SND_SOC_DAIFMT_CBC_CFP: + case SND_SOC_DAIFMT_BP_FC: val_cr2 |= FSL_SAI_CR2_BCD_MSTR; sai->is_consumer_mode = false; break; - case SND_SOC_DAIFMT_CBP_CFC: + case SND_SOC_DAIFMT_BC_FP: val_cr4 |= FSL_SAI_CR4_FSD_MSTR; sai->is_consumer_mode = true; break; @@ -704,7 +704,7 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { .set_bclk_ratio = fsl_sai_set_dai_bclk_ratio, .set_sysclk = fsl_sai_set_dai_sysclk, - .set_fmt = fsl_sai_set_dai_fmt, + .set_fmt_new = fsl_sai_set_dai_fmt, .set_tdm_slot = fsl_sai_set_dai_tdm_slot, .hw_params = fsl_sai_hw_params, .hw_free = fsl_sai_hw_free, diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 84cb36d9dfea..32e4cf37c202 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -93,7 +93,7 @@ */ #define FSLSSI_AC97_DAIFMT \ (SND_SOC_DAIFMT_AC97 | \ - SND_SOC_DAIFMT_CBM_CFS | \ + SND_SOC_DAIFMT_BC_FP | \ SND_SOC_DAIFMT_NB_NF) #define FSLSSI_SIER_DBG_RX_FLAGS \ @@ -358,13 +358,13 @@ static bool fsl_ssi_is_ac97(struct fsl_ssi *ssi) static bool fsl_ssi_is_i2s_clock_provider(struct fsl_ssi *ssi) { return (ssi->dai_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) == - SND_SOC_DAIFMT_CBC_CFC; + SND_SOC_DAIFMT_BP_FP; } -static bool fsl_ssi_is_i2s_cbp_cfc(struct fsl_ssi *ssi) +static bool fsl_ssi_is_i2s_bc_fp(struct fsl_ssi *ssi) { return (ssi->dai_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) == - SND_SOC_DAIFMT_CBP_CFC; + SND_SOC_DAIFMT_BC_FP; } /** @@ -847,7 +847,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, u8 i2s_net = ssi->i2s_net; /* Normal + Network mode to send 16-bit data in 32-bit frames */ - if (fsl_ssi_is_i2s_cbp_cfc(ssi) && sample_size == 16) + if (fsl_ssi_is_i2s_bc_fp(ssi) && sample_size == 16) i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET; /* Use Normal mode to send mono data at 1st slot of 2 slots */ @@ -920,17 +920,17 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: if (IS_ERR(ssi->baudclk)) { dev_err(ssi->dev, "missing baudclk for master mode\n"); return -EINVAL; } fallthrough; - case SND_SOC_DAIFMT_CBP_CFC: + case SND_SOC_DAIFMT_BC_FP: ssi->i2s_net |= SSI_SCR_I2S_MODE_MASTER; break; - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: ssi->i2s_net |= SSI_SCR_I2S_MODE_SLAVE; break; default: @@ -992,15 +992,15 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt) /* DAI clock provider masks */ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: /* Output bit and frame sync clocks */ strcr |= SSI_STCR_TFDIR | SSI_STCR_TXDIR; scr |= SSI_SCR_SYS_CLK_EN; break; - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: /* Input bit or frame sync clocks */ break; - case SND_SOC_DAIFMT_CBP_CFC: + case SND_SOC_DAIFMT_BC_FP: /* Input bit clock but output frame sync clock */ strcr |= SSI_STCR_TFDIR; break; @@ -1156,7 +1156,7 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { .shutdown = fsl_ssi_shutdown, .hw_params = fsl_ssi_hw_params, .hw_free = fsl_ssi_hw_free, - .set_fmt = fsl_ssi_set_dai_fmt, + .set_fmt_new = fsl_ssi_set_dai_fmt, .set_tdm_slot = fsl_ssi_set_dai_tdm_slot, .trigger = fsl_ssi_trigger, }; diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c index 502fe1b522ab..1292a845c424 100644 --- a/sound/soc/fsl/imx-audmix.c +++ b/sound/soc/fsl/imx-audmix.c @@ -81,7 +81,7 @@ static int imx_audmix_fe_hw_params(struct snd_pcm_substream *substream, int ret, dir; /* For playback the AUDMIX is consumer, and for record is provider */ - fmt |= tx ? SND_SOC_DAIFMT_CBC_CFC : SND_SOC_DAIFMT_CBP_CFP; + fmt |= tx ? SND_SOC_DAIFMT_BP_FP : SND_SOC_DAIFMT_BC_FC; dir = tx ? SND_SOC_CLOCK_OUT : SND_SOC_CLOCK_IN; /* set DAI configuration */ @@ -122,7 +122,7 @@ static int imx_audmix_be_hw_params(struct snd_pcm_substream *substream, return 0; /* For playback the AUDMIX is consumer */ - fmt |= SND_SOC_DAIFMT_CBP_CFP; + fmt |= SND_SOC_DAIFMT_BC_FC; /* set AUDMIX DAI configuration */ ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), fmt); diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index 6f8efd838fcc..1797d777b1b8 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c @@ -317,7 +317,7 @@ static int imx_aif_hw_params(struct snd_pcm_substream *substream, } } - ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + ret = snd_soc_dai_set_fmt(cpu_dai, snd_soc_daifmt_clock_provider_flipped(fmt)); if (ret && ret != -ENOTSUPP) { dev_err(dev, "failed to set cpu dai fmt: %d\n", ret); return ret; -- cgit From 0f362524dd3face4865077a4f7e7e640a95702aa Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:31 +0100 Subject: ASoC: hisilicon: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update this CPU side driver to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-10-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/hisilicon/hi6210-i2s.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/hisilicon/hi6210-i2s.c b/sound/soc/hisilicon/hi6210-i2s.c index a297d4af5099..51f98ae651a6 100644 --- a/sound/soc/hisilicon/hi6210-i2s.c +++ b/sound/soc/hisilicon/hi6210-i2s.c @@ -227,9 +227,9 @@ static int hi6210_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) * We don't actually set the hardware until the hw_params * call, but we need to validate the user input here. */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: + case SND_SOC_DAIFMT_BP_FP: break; default: return -EINVAL; @@ -245,8 +245,8 @@ static int hi6210_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) } i2s->format = fmt; - i2s->master = (i2s->format & SND_SOC_DAIFMT_MASTER_MASK) == - SND_SOC_DAIFMT_CBS_CFS; + i2s->master = (i2s->format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) == + SND_SOC_DAIFMT_BP_FP; return 0; } @@ -375,21 +375,21 @@ static int hi6210_i2s_hw_params(struct snd_pcm_substream *substream, hi6210_write_reg(i2s, HII2S_MUX_TOP_MODULE_CFG, val); - switch (i2s->format & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (i2s->format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: i2s->master = false; val = hi6210_read_reg(i2s, HII2S_I2S_CFG); val |= HII2S_I2S_CFG__S2_MST_SLV; hi6210_write_reg(i2s, HII2S_I2S_CFG, val); break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: i2s->master = true; val = hi6210_read_reg(i2s, HII2S_I2S_CFG); val &= ~HII2S_I2S_CFG__S2_MST_SLV; hi6210_write_reg(i2s, HII2S_I2S_CFG, val); break; default: - WARN_ONCE(1, "Invalid i2s->fmt MASTER_MASK. This shouldn't happen\n"); + WARN_ONCE(1, "Invalid i2s->fmt CLOCK_PROVIDER_MASK. This shouldn't happen\n"); return -EINVAL; } @@ -513,7 +513,7 @@ static int hi6210_i2s_dai_probe(struct snd_soc_dai *dai) static const struct snd_soc_dai_ops hi6210_i2s_dai_ops = { .trigger = hi6210_i2s_trigger, .hw_params = hi6210_i2s_hw_params, - .set_fmt = hi6210_i2s_set_fmt, + .set_fmt_new = hi6210_i2s_set_fmt, .startup = hi6210_i2s_startup, .shutdown = hi6210_i2s_shutdown, }; -- cgit From ed2b384082a678a0c4c8c56deff9e5f46d5e3fca Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:32 +0100 Subject: ASoC: img: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-11-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/img/img-i2s-in.c | 6 +++--- sound/soc/img/img-i2s-out.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c index 09d23b11621c..79e733bc0ae6 100644 --- a/sound/soc/img/img-i2s-in.c +++ b/sound/soc/img/img-i2s-in.c @@ -333,8 +333,8 @@ static int img_i2s_in_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return -EINVAL; } - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: break; default: return -EINVAL; @@ -373,7 +373,7 @@ static int img_i2s_in_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static const struct snd_soc_dai_ops img_i2s_in_dai_ops = { .trigger = img_i2s_in_trigger, .hw_params = img_i2s_in_hw_params, - .set_fmt = img_i2s_in_set_fmt + .set_fmt_new = img_i2s_in_set_fmt }; static int img_i2s_in_dai_probe(struct snd_soc_dai *dai) diff --git a/sound/soc/img/img-i2s-out.c b/sound/soc/img/img-i2s-out.c index 28f48ca1508a..d92539603d6c 100644 --- a/sound/soc/img/img-i2s-out.c +++ b/sound/soc/img/img-i2s-out.c @@ -302,10 +302,10 @@ static int img_i2s_out_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) if (force_clk_active) control_set |= IMG_I2S_OUT_CTL_CLK_EN_MASK; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: control_set |= IMG_I2S_OUT_CTL_MASTER_MASK; break; default: @@ -381,7 +381,7 @@ static int img_i2s_out_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static const struct snd_soc_dai_ops img_i2s_out_dai_ops = { .trigger = img_i2s_out_trigger, .hw_params = img_i2s_out_hw_params, - .set_fmt = img_i2s_out_set_fmt + .set_fmt_new = img_i2s_out_set_fmt }; static int img_i2s_out_dai_probe(struct snd_soc_dai *dai) -- cgit From add9ee8c64c617f561a309cdda50104e9e2c12f6 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:33 +0100 Subject: ASoC: Intel: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-12-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-atom-controls.c | 4 ++-- sound/soc/intel/atom/sst-mfld-platform-pcm.c | 2 +- sound/soc/intel/boards/bytcht_cx2072x.c | 2 +- sound/soc/intel/boards/bytcht_da7213.c | 2 +- sound/soc/intel/boards/bytcht_es8316.c | 2 +- sound/soc/intel/boards/bytcht_nocodec.c | 2 +- sound/soc/intel/boards/bytcr_rt5640.c | 2 +- sound/soc/intel/boards/bytcr_rt5651.c | 2 +- sound/soc/intel/boards/bytcr_wm5102.c | 2 +- sound/soc/intel/boards/cht_bsw_max98090_ti.c | 3 +-- sound/soc/intel/boards/cht_bsw_rt5645.c | 6 +++--- sound/soc/intel/boards/cht_bsw_rt5672.c | 2 +- sound/soc/intel/keembay/kmb_platform.c | 6 +++--- 13 files changed, 18 insertions(+), 19 deletions(-) diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index 335c32732994..406455ddcb96 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c @@ -831,9 +831,9 @@ static int sst_get_ssp_mode(struct snd_soc_dai *dai, unsigned int fmt) dev_dbg(dai->dev, "Enter:%s, format=%x\n", __func__, format); switch (format) { - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: return SSP_MODE_PROVIDER; - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: return SSP_MODE_CONSUMER; default: dev_err(dai->dev, "Invalid ssp protocol: %d\n", format); diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index a56dd48c045f..339d9440c150 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -473,7 +473,7 @@ static const struct snd_soc_dai_ops sst_compr_dai_ops = { static const struct snd_soc_dai_ops sst_be_dai_ops = { .startup = sst_enable_ssp, .hw_params = sst_be_hw_params, - .set_fmt = sst_set_format, + .set_fmt_new = sst_set_format, .set_tdm_slot = sst_platform_set_ssp_slot, .shutdown = sst_disable_ssp, }; diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index 0eed68a11f7e..ae899866863e 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -126,7 +126,7 @@ static int byt_cht_cx2072x_fixup(struct snd_soc_pcm_runtime *rtd, ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC); + SND_SOC_DAIFMT_BP_FP); if (ret < 0) { dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c index eb19bf16afad..a0c8f1d3f8ce 100644 --- a/sound/soc/intel/boards/bytcht_da7213.c +++ b/sound/soc/intel/boards/bytcht_da7213.c @@ -81,7 +81,7 @@ static int codec_fixup(struct snd_soc_pcm_runtime *rtd, ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC); + SND_SOC_DAIFMT_BP_FP); if (ret < 0) { dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index a08507783e44..6432b83f616f 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -265,7 +265,7 @@ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd, ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC + SND_SOC_DAIFMT_BP_FP ); if (ret < 0) { dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); diff --git a/sound/soc/intel/boards/bytcht_nocodec.c b/sound/soc/intel/boards/bytcht_nocodec.c index 115c2bcaabd4..7fc03f2efd35 100644 --- a/sound/soc/intel/boards/bytcht_nocodec.c +++ b/sound/soc/intel/boards/bytcht_nocodec.c @@ -61,7 +61,7 @@ static int codec_fixup(struct snd_soc_pcm_runtime *rtd, ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC); + SND_SOC_DAIFMT_BP_FP); if (ret < 0) { dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index ed9fa1728722..ce1f3eb5f83b 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -1413,7 +1413,7 @@ static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC); + SND_SOC_DAIFMT_BP_FP); if (ret < 0) { dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index d467fcaa48ea..f72a597114bf 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -706,7 +706,7 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd, ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC + SND_SOC_DAIFMT_BP_FP ); if (ret < 0) { diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c index 00384c6fbcaa..fe79f6e5f2bb 100644 --- a/sound/soc/intel/boards/bytcr_wm5102.c +++ b/sound/soc/intel/boards/bytcr_wm5102.c @@ -265,7 +265,7 @@ static int byt_wm5102_codec_fixup(struct snd_soc_pcm_runtime *rtd, ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC); + SND_SOC_DAIFMT_BP_FP); if (ret) { dev_err(rtd->dev, "Error setting format to I2S: %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index a5160f27adea..64eb73525ee3 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -264,8 +264,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } - fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBC_CFC; + fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_BP_FP; ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), fmt); if (ret < 0) { diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index 45c301ea5e00..56ee53e7ed3f 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -362,7 +362,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC + SND_SOC_DAIFMT_BP_FP ); if (ret < 0) { dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); @@ -372,7 +372,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC + SND_SOC_DAIFMT_BC_FC ); if (ret < 0) { dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); @@ -396,7 +396,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0), SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBC_CFC); + SND_SOC_DAIFMT_BC_FC); if (ret < 0) { dev_err(rtd->dev, "can't set format to TDM %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index c80324f34b1b..ca47f6476b07 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -300,7 +300,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC); + SND_SOC_DAIFMT_BP_FP); if (ret < 0) { dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); return ret; diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c index a6fb74ba1c42..a65f03884d9a 100644 --- a/sound/soc/intel/keembay/kmb_platform.c +++ b/sound/soc/intel/keembay/kmb_platform.c @@ -497,11 +497,11 @@ static int kmb_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) int ret; switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: kmb_i2s->clock_provider = false; ret = 0; break; - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: writel(CLOCK_PROVIDER_MODE, kmb_i2s->pss_base + I2S_GEN_CFG_0); ret = clk_prepare_enable(kmb_i2s->clk_i2s); @@ -736,7 +736,7 @@ static const struct snd_soc_dai_ops kmb_dai_ops = { .hw_params = kmb_dai_hw_params, .hw_free = kmb_dai_hw_free, .prepare = kmb_dai_prepare, - .set_fmt = kmb_set_dai_fmt, + .set_fmt_new = kmb_set_dai_fmt, }; static struct snd_soc_dai_driver intel_kmb_hdmi_dai[] = { -- cgit From cbb3a19f090d5a41b822caf9ff2058e1c6bc7ea3 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:34 +0100 Subject: ASoC: js4740-i2s: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update this CPU side driver to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-13-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/jz4740/jz4740-i2s.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 7ad5d9a924d8..2c9dee241778 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -206,18 +206,18 @@ static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) conf &= ~(JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER); - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: conf |= JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER; format |= JZ_AIC_I2S_FMT_ENABLE_SYS_CLK; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_BC_FP: conf |= JZ_AIC_CONF_SYNC_CLK_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_BP_FC: conf |= JZ_AIC_CONF_BIT_CLK_MASTER; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: break; default: return -EINVAL; @@ -433,7 +433,7 @@ static const struct snd_soc_dai_ops jz4740_i2s_dai_ops = { .shutdown = jz4740_i2s_shutdown, .trigger = jz4740_i2s_trigger, .hw_params = jz4740_i2s_hw_params, - .set_fmt = jz4740_i2s_set_fmt, + .set_fmt_new = jz4740_i2s_set_fmt, .set_sysclk = jz4740_i2s_set_sysclk, }; -- cgit From 3af99430f8d948a41556156155b0295dec274d41 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:35 +0100 Subject: ASoC: mediatek: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-14-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-dai-etdm.c | 10 +++++----- sound/soc/mediatek/mt8195/mt8195-dai-pcm.c | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c index c02c10da3600..5f7c9516dfa1 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c @@ -2172,11 +2172,11 @@ static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return -EINVAL; } - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: etdm_data->slave_mode = true; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: etdm_data->slave_mode = false; break; default: @@ -2346,7 +2346,7 @@ static const struct snd_soc_dai_ops mtk_dai_etdm_ops = { .hw_params = mtk_dai_etdm_hw_params, .trigger = mtk_dai_etdm_trigger, .set_sysclk = mtk_dai_etdm_set_sysclk, - .set_fmt = mtk_dai_etdm_set_fmt, + .set_fmt_new = mtk_dai_etdm_set_fmt, .set_tdm_slot = mtk_dai_etdm_set_tdm_slot, }; @@ -2356,7 +2356,7 @@ static const struct snd_soc_dai_ops mtk_dai_hdmitx_dptx_ops = { .hw_params = mtk_dai_hdmitx_dptx_hw_params, .trigger = mtk_dai_hdmitx_dptx_trigger, .set_sysclk = mtk_dai_hdmitx_dptx_set_sysclk, - .set_fmt = mtk_dai_etdm_set_fmt, + .set_fmt_new = mtk_dai_etdm_set_fmt, }; /* dai driver */ diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c index 12644ded83d5..37a8968ac21d 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c @@ -266,11 +266,11 @@ static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return -EINVAL; } - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: pcmif_priv->slave_mode = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: pcmif_priv->slave_mode = 0; break; default: @@ -282,7 +282,7 @@ static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static const struct snd_soc_dai_ops mtk_dai_pcm_ops = { .prepare = mtk_dai_pcm_prepare, - .set_fmt = mtk_dai_pcm_set_fmt, + .set_fmt_new = mtk_dai_pcm_set_fmt, }; /* dai driver */ -- cgit From f60442bf6eab47aa4ab127aab88afdcc29a09a73 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:36 +0100 Subject: ASoC: meson: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-15-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/meson/aiu-encoder-i2s.c | 4 ++-- sound/soc/meson/axg-tdm-interface.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c index 67729de41a73..0ab991230dee 100644 --- a/sound/soc/meson/aiu-encoder-i2s.c +++ b/sound/soc/meson/aiu-encoder-i2s.c @@ -229,7 +229,7 @@ static int aiu_encoder_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int skew; /* Only CPU Master / Codec Slave supported ATM */ - if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) + if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_BP_FP) return -EINVAL; if (inv == SND_SOC_DAIFMT_NB_IF || @@ -323,7 +323,7 @@ static void aiu_encoder_i2s_shutdown(struct snd_pcm_substream *substream, const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops = { .hw_params = aiu_encoder_i2s_hw_params, .hw_free = aiu_encoder_i2s_hw_free, - .set_fmt = aiu_encoder_i2s_set_fmt, + .set_fmt_new = aiu_encoder_i2s_set_fmt, .set_sysclk = aiu_encoder_i2s_set_sysclk, .startup = aiu_encoder_i2s_startup, .shutdown = aiu_encoder_i2s_shutdown, diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index e076ced30025..ffdb12d0e01e 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -119,19 +119,19 @@ static int axg_tdm_iface_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct axg_tdm_iface *iface = snd_soc_dai_get_drvdata(dai); - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: if (!iface->mclk) { dev_err(dai->dev, "cpu clock master: mclk missing\n"); return -ENODEV; } break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: break; - case SND_SOC_DAIFMT_CBS_CFM: - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_BP_FC: + case SND_SOC_DAIFMT_BC_FP: dev_err(dai->dev, "only CBS_CFS and CBM_CFM are supported\n"); fallthrough; default: @@ -326,8 +326,8 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream, if (ret) return ret; - if ((iface->fmt & SND_SOC_DAIFMT_MASTER_MASK) == - SND_SOC_DAIFMT_CBS_CFS) { + if ((iface->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) == + SND_SOC_DAIFMT_BP_FP) { ret = axg_tdm_iface_set_sclk(dai, params); if (ret) return ret; @@ -394,7 +394,7 @@ static int axg_tdm_iface_probe_dai(struct snd_soc_dai *dai) static const struct snd_soc_dai_ops axg_tdm_iface_ops = { .set_sysclk = axg_tdm_iface_set_sysclk, - .set_fmt = axg_tdm_iface_set_fmt, + .set_fmt_new = axg_tdm_iface_set_fmt, .startup = axg_tdm_iface_startup, .hw_params = axg_tdm_iface_hw_params, .prepare = axg_tdm_iface_prepare, -- cgit From f3c0064f1f8e358799c70c7905a09d15c5ec5e5a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:37 +0100 Subject: ASoC: mxs-saif: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update this CPU side driver to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-16-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-saif.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index 7afe1a1acc56..38de46ba1583 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -358,8 +358,8 @@ static int mxs_saif_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) * Saif internally could be slave when working on EXTMASTER mode. * We just hide this to machine driver. */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: if (saif->id == saif->master_id) scr &= ~BM_SAIF_CTRL_SLAVE_MODE; else @@ -642,7 +642,7 @@ static const struct snd_soc_dai_ops mxs_saif_dai_ops = { .prepare = mxs_saif_prepare, .hw_params = mxs_saif_hw_params, .set_sysclk = mxs_saif_set_dai_sysclk, - .set_fmt = mxs_saif_set_dai_fmt, + .set_fmt_new = mxs_saif_set_dai_fmt, }; static struct snd_soc_dai_driver mxs_saif_dai = { -- cgit From 84c5b47c8ce4d5059d5e7539d3b44922cc0390e9 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:38 +0100 Subject: ASoC: pxa: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-17-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/pxa/magician.c | 8 ++++---- sound/soc/pxa/mmp-sspa.c | 8 ++++---- sound/soc/pxa/pxa-ssp.c | 24 ++++++++++++------------ sound/soc/pxa/pxa2xx-i2s.c | 8 ++++---- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index 9433cc927755..b791a2ba5ce5 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -91,13 +91,13 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream, /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_MSB | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_BC_FC); if (ret < 0) return ret; /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBS_CFS); + SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_BP_FP); if (ret < 0) return ret; @@ -129,14 +129,14 @@ static int magician_capture_hw_params(struct snd_pcm_substream *substream, /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); + SND_SOC_DAIFMT_BC_FC); if (ret < 0) return ret; /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); + SND_SOC_DAIFMT_BP_FP); if (ret < 0) return ret; diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 7e39210a0b38..b746e52aaf85 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -171,11 +171,11 @@ static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai, sspa->sp = SSPA_SP_WEN | SSPA_SP_S_RST | SSPA_SP_FFLUSH; sspa->ctrl = 0; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: sspa->sp |= SSPA_SP_MSL; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: break; default: return -EINVAL; @@ -346,7 +346,7 @@ static const struct snd_soc_dai_ops mmp_sspa_dai_ops = { .hw_params = mmp_sspa_hw_params, .set_sysclk = mmp_sspa_set_dai_sysclk, .set_pll = mmp_sspa_set_dai_pll, - .set_fmt = mmp_sspa_set_dai_fmt, + .set_fmt_new = mmp_sspa_set_dai_fmt, }; static struct snd_soc_dai_driver mmp_sspa_dai = { diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 7f13a35e9cc1..52124be1778e 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -372,10 +372,10 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, { struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai); - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_CBM_CFS: - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: + case SND_SOC_DAIFMT_BC_FP: + case SND_SOC_DAIFMT_BP_FP: break; default: return -EINVAL; @@ -432,14 +432,14 @@ static int pxa_ssp_configure_dai_fmt(struct ssp_priv *priv) sscr1 |= SSCR1_RxTresh(8) | SSCR1_TxTresh(7); - switch (priv->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (priv->dai_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR | SSCR1_SCFR; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_BC_FP: sscr1 |= SSCR1_SCLKDIR | SSCR1_SCFR; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: break; default: return -EINVAL; @@ -484,9 +484,9 @@ static int pxa_ssp_configure_dai_fmt(struct ssp_priv *priv) pxa_ssp_write_reg(ssp, SSCR1, sscr1); pxa_ssp_write_reg(ssp, SSPSP, sspsp); - switch (priv->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_CBM_CFS: + switch (priv->dai_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: + case SND_SOC_DAIFMT_BC_FP: scfr = pxa_ssp_read_reg(ssp, SSCR1) | SSCR1_SCFR; pxa_ssp_write_reg(ssp, SSCR1, scfr); @@ -824,7 +824,7 @@ static const struct snd_soc_dai_ops pxa_ssp_dai_ops = { .trigger = pxa_ssp_trigger, .hw_params = pxa_ssp_hw_params, .set_sysclk = pxa_ssp_set_dai_sysclk, - .set_fmt = pxa_ssp_set_dai_fmt, + .set_fmt_new = pxa_ssp_set_dai_fmt, .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, .set_tristate = pxa_ssp_set_dai_tristate, }; diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 746e6ec9198b..9f12fc3615b6 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -129,11 +129,11 @@ static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, break; } - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: pxa_i2s.master = 1; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_BC_FP: pxa_i2s.master = 0; break; default: @@ -333,7 +333,7 @@ static const struct snd_soc_dai_ops pxa_i2s_dai_ops = { .shutdown = pxa2xx_i2s_shutdown, .trigger = pxa2xx_i2s_trigger, .hw_params = pxa2xx_i2s_hw_params, - .set_fmt = pxa2xx_i2s_set_dai_fmt, + .set_fmt_new = pxa2xx_i2s_set_dai_fmt, .set_sysclk = pxa2xx_i2s_set_dai_sysclk, }; -- cgit From 1148e16b335f341f36475b646c692b4a71a1855e Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:39 +0100 Subject: ASoC: qcom: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-18-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/qcom/apq8016_sbc.c | 2 +- sound/soc/qcom/qdsp6/audioreach.c | 4 ++-- sound/soc/qcom/qdsp6/q6afe-dai.c | 2 +- sound/soc/qcom/qdsp6/q6afe.c | 6 +++--- sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 2 +- sound/soc/qcom/sc7180.c | 2 +- sound/soc/qcom/sdm845.c | 6 +++--- sound/soc/qcom/sm8250.c | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index b0a4f7ca2751..e54b8961112f 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -172,7 +172,7 @@ static int msm8916_qdsp6_dai_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); - snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS); + snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_BP_FP); return apq8016_dai_init(rtd, qdsp6_dai_get_lpass_id(cpu_dai)); } diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c index 98c0efa1d0fe..01dac32c50fd 100644 --- a/sound/soc/qcom/qdsp6/audioreach.c +++ b/sound/soc/qcom/qdsp6/audioreach.c @@ -732,10 +732,10 @@ static int audioreach_i2s_set_media_format(struct q6apm_graph *graph, intf_cfg->cfg.sd_line_idx = module->sd_line_idx; switch (cfg->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: intf_cfg->cfg.ws_src = CONFIG_I2S_WS_SRC_INTERNAL; break; - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: /* CPU is slave */ intf_cfg->cfg.ws_src = CONFIG_I2S_WS_SRC_EXTERNAL; break; diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c index 8bb7452b8f18..8f8794cffc1c 100644 --- a/sound/soc/qcom/qdsp6/q6afe-dai.c +++ b/sound/soc/qcom/qdsp6/q6afe-dai.c @@ -648,7 +648,7 @@ static const struct snd_soc_dai_ops q6hdmi_ops = { static const struct snd_soc_dai_ops q6i2s_ops = { .prepare = q6afe_dai_prepare, .hw_params = q6i2s_hw_params, - .set_fmt = q6i2s_set_fmt, + .set_fmt_new = q6i2s_set_fmt, .shutdown = q6afe_dai_shutdown, .set_sysclk = q6afe_mi2s_set_sysclk, }; diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index 625724852a7f..919e326b9462 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -1328,11 +1328,11 @@ int q6afe_i2s_port_prepare(struct q6afe_port *port, struct q6afe_i2s_cfg *cfg) pcfg->i2s_cfg.bit_width = cfg->bit_width; pcfg->i2s_cfg.data_format = AFE_LINEAR_PCM_DATA; - switch (cfg->fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (cfg->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: pcfg->i2s_cfg.ws_src = AFE_PORT_CONFIG_I2S_WS_SRC_INTERNAL; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: /* CPU is slave */ pcfg->i2s_cfg.ws_src = AFE_PORT_CONFIG_I2S_WS_SRC_EXTERNAL; break; diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c index ce9e5646d8f3..82ee52051f83 100644 --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c @@ -207,7 +207,7 @@ static const struct snd_soc_dai_ops q6i2s_ops = { .shutdown = q6apm_lpass_dai_shutdown, .set_channel_map = q6dma_set_channel_map, .hw_params = q6dma_hw_params, - .set_fmt = q6i2s_set_fmt, + .set_fmt_new = q6i2s_set_fmt, }; static const struct snd_soc_component_driver q6apm_lpass_dai_component = { diff --git a/sound/soc/qcom/sc7180.c b/sound/soc/qcom/sc7180.c index efccb5c0b3e0..f5f7c64b23a2 100644 --- a/sound/soc/qcom/sc7180.c +++ b/sound/soc/qcom/sc7180.c @@ -155,7 +155,7 @@ static int sc7180_snd_startup(struct snd_pcm_substream *substream) } snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_CBS_CFS | + SND_SOC_DAIFMT_BC_FC | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S); diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c index 61fda790f375..d8d35563af00 100644 --- a/sound/soc/qcom/sdm845.c +++ b/sound/soc/qcom/sdm845.c @@ -316,8 +316,8 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd) static int sdm845_snd_startup(struct snd_pcm_substream *substream) { - unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; - unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS; + unsigned int fmt = SND_SOC_DAIFMT_BP_FP; + unsigned int codec_dai_fmt = SND_SOC_DAIFMT_BC_FC; struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card); @@ -356,7 +356,7 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream) snd_soc_dai_set_sysclk(cpu_dai, Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT, MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK); - snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS); + snd_soc_dai_set_fmt(cpu_dai, fmt); break; diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c index 6e1184c8b672..ce4a5713386a 100644 --- a/sound/soc/qcom/sm8250.c +++ b/sound/soc/qcom/sm8250.c @@ -96,8 +96,8 @@ static int sm8250_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static int sm8250_snd_startup(struct snd_pcm_substream *substream) { - unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; - unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS; + unsigned int fmt = SND_SOC_DAIFMT_BP_FP; + unsigned int codec_dai_fmt = SND_SOC_DAIFMT_BC_FC; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); -- cgit From 27646d265da1745b2d1d10fec18465631cb1135f Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:40 +0100 Subject: ASoC: rockchip: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Tested-by: Nicolas Frattaroli Link: https://lore.kernel.org/r/20220519154318.2153729-19-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_i2s.c | 8 ++++---- sound/soc/rockchip/rockchip_i2s_tdm.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 4ce5d2579387..0a66c7df323d 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -199,13 +199,13 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, pm_runtime_get_sync(cpu_dai->dev); mask = I2S_CKR_MSS_MASK; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: /* Set source clock in Master mode */ val = I2S_CKR_MSS_MASTER; i2s->is_master_mode = true; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: val = I2S_CKR_MSS_SLAVE; i2s->is_master_mode = false; break; @@ -486,7 +486,7 @@ static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = { .hw_params = rockchip_i2s_hw_params, .set_bclk_ratio = rockchip_i2s_set_bclk_ratio, .set_sysclk = rockchip_i2s_set_sysclk, - .set_fmt = rockchip_i2s_set_fmt, + .set_fmt_new = rockchip_i2s_set_fmt, .trigger = rockchip_i2s_trigger, }; diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c index 98700e75b82a..c90afccdae36 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -411,12 +411,12 @@ static int rockchip_i2s_tdm_set_fmt(struct snd_soc_dai *cpu_dai, } mask = I2S_CKR_MSS_MASK; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: val = I2S_CKR_MSS_MASTER; i2s_tdm->is_master_mode = true; break; - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: val = I2S_CKR_MSS_SLAVE; i2s_tdm->is_master_mode = false; break; @@ -1113,7 +1113,7 @@ static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = { .hw_params = rockchip_i2s_tdm_hw_params, .set_bclk_ratio = rockchip_i2s_tdm_set_bclk_ratio, .set_sysclk = rockchip_i2s_tdm_set_sysclk, - .set_fmt = rockchip_i2s_tdm_set_fmt, + .set_fmt_new = rockchip_i2s_tdm_set_fmt, .set_tdm_slot = rockchip_dai_tdm_slot, .trigger = rockchip_i2s_tdm_trigger, }; -- cgit From 0b491c7c1b2555ef08285fd49a8567f2f9f34ff8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:41 +0100 Subject: ASoC: samsung: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-20-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 8 ++++---- sound/soc/samsung/pcm.c | 6 +++--- sound/soc/samsung/s3c-i2s-v2.c | 8 ++++---- sound/soc/samsung/s3c24xx-i2s.c | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 70c827162be4..9ed275ebd744 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -671,11 +671,11 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return -EINVAL; } - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: tmp |= mod_slave; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: /* * Set default source clock in Master mode, only when the * CLK_I2S_RCLK_SRC clock is not exposed so we ensure any @@ -1107,7 +1107,7 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) static const struct snd_soc_dai_ops samsung_i2s_dai_ops = { .trigger = i2s_trigger, .hw_params = i2s_hw_params, - .set_fmt = i2s_set_fmt, + .set_fmt_new = i2s_set_fmt, .set_clkdiv = i2s_set_clkdiv, .set_sysclk = i2s_set_sysclk, .startup = i2s_startup, diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 4c4dfde0568f..818172d8832d 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -340,8 +340,8 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, goto exit; } - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: /* Nothing to do, Master by default */ break; default: @@ -437,7 +437,7 @@ static const struct snd_soc_dai_ops s3c_pcm_dai_ops = { .set_clkdiv = s3c_pcm_set_clkdiv, .trigger = s3c_pcm_trigger, .hw_params = s3c_pcm_hw_params, - .set_fmt = s3c_pcm_set_fmt, + .set_fmt_new = s3c_pcm_set_fmt, }; static int s3c_pcm_dai_probe(struct snd_soc_dai *dai) diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index de66cc422e6e..9c8a0697849d 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c @@ -252,12 +252,12 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai, iismod = readl(i2s->regs + S3C2412_IISMOD); pr_debug("hw_params r: IISMOD: %x \n", iismod); - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: i2s->master = 0; iismod |= S3C2412_IISMOD_SLAVE; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: i2s->master = 1; iismod &= ~S3C2412_IISMOD_SLAVE; break; @@ -666,7 +666,7 @@ int s3c_i2sv2_register_component(struct device *dev, int id, ops->trigger = s3c2412_i2s_trigger; if (!ops->hw_params) ops->hw_params = s3c_i2sv2_hw_params; - ops->set_fmt = s3c2412_i2s_set_fmt; + ops->set_fmt_new = s3c2412_i2s_set_fmt; ops->set_clkdiv = s3c2412_i2s_set_clkdiv; ops->set_sysclk = s3c_i2sv2_set_sysclk; diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 0f46304eaa4f..6226b3b585e5 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -169,11 +169,11 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); pr_debug("hw_params r: IISMOD: %x \n", iismod); - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_CFC: iismod |= S3C2410_IISMOD_SLAVE; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: iismod &= ~S3C2410_IISMOD_SLAVE; break; default: @@ -394,7 +394,7 @@ static int s3c24xx_i2s_resume(struct snd_soc_component *component) static const struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = { .trigger = s3c24xx_i2s_trigger, .hw_params = s3c24xx_i2s_hw_params, - .set_fmt = s3c24xx_i2s_set_fmt, + .set_fmt_new = s3c24xx_i2s_set_fmt, .set_clkdiv = s3c24xx_i2s_set_clkdiv, .set_sysclk = s3c24xx_i2s_set_sysclk, }; -- cgit From 2d4dd776e902546389f2d7808ece7fd815aa829c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:42 +0100 Subject: ASoC: sh: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Acked-by: Kuninori Morimoto Link: https://lore.kernel.org/r/20220519154318.2153729-21-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 8 ++++---- sound/soc/sh/rcar/core.c | 6 +++--- sound/soc/sh/rz-ssi.c | 4 ++-- sound/soc/sh/ssi.c | 12 ++++++------ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index e9a1eb6bdf66..4058d60b7e93 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1646,10 +1646,10 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) int ret; /* set clock master audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: fsi->clk_master = 1; /* cpu is master */ break; default: @@ -1724,7 +1724,7 @@ static const struct snd_soc_dai_ops fsi_dai_ops = { .startup = fsi_dai_startup, .shutdown = fsi_dai_shutdown, .trigger = fsi_dai_trigger, - .set_fmt = fsi_dai_set_fmt, + .set_fmt_new = fsi_dai_set_fmt, .hw_params = fsi_dai_hw_params, .auto_selectable_formats = &fsi_dai_formats, .num_auto_selectable_formats = 1, diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index eb762ab94d3e..0ac15b74c58a 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -756,10 +756,10 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) /* set clock master for audio interface */ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BC_FC: rdai->clk_master = 0; break; - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: rdai->clk_master = 1; /* cpu is master */ break; default: @@ -1068,7 +1068,7 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { .startup = rsnd_soc_dai_startup, .shutdown = rsnd_soc_dai_shutdown, .trigger = rsnd_soc_dai_trigger, - .set_fmt = rsnd_soc_dai_set_fmt, + .set_fmt_new = rsnd_soc_dai_set_fmt, .set_tdm_slot = rsnd_soc_set_dai_tdm_slot, .prepare = rsnd_soc_dai_prepare, .auto_selectable_formats = rsnd_soc_dai_formats, diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index e392de7a262e..0557d22a089f 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -767,7 +767,7 @@ static int rz_ssi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BP_FP: break; default: dev_err(ssi->dev, "Codec should be clk and frame consumer\n"); @@ -840,7 +840,7 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops rz_ssi_dai_ops = { .trigger = rz_ssi_dai_trigger, - .set_fmt = rz_ssi_dai_set_fmt, + .set_fmt_new = rz_ssi_dai_set_fmt, .hw_params = rz_ssi_dai_hw_params, }; diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c index 15b01bcefca5..95571cbeae29 100644 --- a/sound/soc/sh/ssi.c +++ b/sound/soc/sh/ssi.c @@ -291,16 +291,16 @@ static int ssi_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return -EINVAL; } - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_BP_FC: ssicr |= CR_SCK_MASTER; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_BC_FP: ssicr |= CR_SWS_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: ssicr |= CR_SWS_MASTER | CR_SCK_MASTER; break; default: @@ -336,7 +336,7 @@ static const struct snd_soc_dai_ops ssi_dai_ops = { .hw_params = ssi_hw_params, .set_sysclk = ssi_set_sysclk, .set_clkdiv = ssi_set_clkdiv, - .set_fmt = ssi_set_fmt, + .set_fmt_new = ssi_set_fmt, }; static struct snd_soc_dai_driver sh4_ssi_dai[] = { -- cgit From 0092dac91ec1c404787841bdd9ecbf3404d1a41c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:43 +0100 Subject: ASoC: stm: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-22-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_i2s.c | 10 +++++----- sound/soc/stm/stm32_sai_sub.c | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index ac5dff4d1677..30c04f96ef1d 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -593,16 +593,16 @@ static int stm32_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) } /* DAI clock master masks */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: i2s->ms_flg = I2S_MS_SLAVE; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: i2s->ms_flg = I2S_MS_MASTER; break; default: dev_err(cpu_dai->dev, "Unsupported mode %#x\n", - fmt & SND_SOC_DAIFMT_MASTER_MASK); + fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK); return -EINVAL; } @@ -954,7 +954,7 @@ static const struct regmap_config stm32_h7_i2s_regmap_conf = { static const struct snd_soc_dai_ops stm32_i2s_pcm_dai_ops = { .set_sysclk = stm32_i2s_set_sysclk, - .set_fmt = stm32_i2s_set_dai_fmt, + .set_fmt_new = stm32_i2s_set_dai_fmt, .startup = stm32_i2s_startup, .hw_params = stm32_i2s_hw_params, .trigger = stm32_i2s_trigger, diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index dd636af81c9b..9f169b93fa74 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -719,18 +719,18 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) stm32_sai_sub_reg_up(sai, STM_SAI_FRCR_REGX, frcr_mask, frcr); /* DAI clock master masks */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: /* codec is master */ cr1 |= SAI_XCR1_SLAVE; sai->master = false; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: sai->master = true; break; default: dev_err(cpu_dai->dev, "Unsupported mode %#x\n", - fmt & SND_SOC_DAIFMT_MASTER_MASK); + fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK); return -EINVAL; } @@ -1225,7 +1225,7 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai) static const struct snd_soc_dai_ops stm32_sai_pcm_dai_ops = { .set_sysclk = stm32_sai_set_sysclk, - .set_fmt = stm32_sai_set_dai_fmt, + .set_fmt_new = stm32_sai_set_dai_fmt, .set_tdm_slot = stm32_sai_set_dai_tdm_slot, .startup = stm32_sai_startup, .hw_params = stm32_sai_hw_params, -- cgit From 7cc3965fde74c9c725ed01de4ac35bc7d562d16a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:44 +0100 Subject: ASoC: sunxi: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-23-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 20 ++++++++++---------- sound/soc/sunxi/sun8i-codec.c | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 7047f71629ab..872838d3e0a9 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -702,13 +702,13 @@ static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, SUN4I_I2S_FMT0_FMT_MASK, val); /* DAI clock master masks */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: /* BCLK and LRCLK master */ val = SUN4I_I2S_CTRL_MODE_MASTER; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: /* BCLK and LRCLK slave */ val = SUN4I_I2S_CTRL_MODE_SLAVE; break; @@ -802,13 +802,13 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, SUN8I_I2S_TX_CHAN_OFFSET(offset)); /* DAI clock master masks */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: /* BCLK and LRCLK master */ val = SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: /* BCLK and LRCLK slave */ val = 0; break; @@ -909,13 +909,13 @@ static int sun50i_h6_i2s_set_soc_fmt(const struct sun4i_i2s *i2s, SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset)); /* DAI clock master masks */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: /* BCLK and LRCLK master */ val = SUN8I_I2S_CTRL_BCLK_OUT | SUN8I_I2S_CTRL_LRCK_OUT; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: /* BCLK and LRCLK slave */ val = 0; break; @@ -1081,7 +1081,7 @@ static int sun4i_i2s_set_tdm_slot(struct snd_soc_dai *dai, static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = { .hw_params = sun4i_i2s_hw_params, - .set_fmt = sun4i_i2s_set_fmt, + .set_fmt_new = sun4i_i2s_set_fmt, .set_sysclk = sun4i_i2s_set_sysclk, .set_tdm_slot = sun4i_i2s_set_tdm_slot, .trigger = sun4i_i2s_trigger, diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 0bea2162f68d..6e9ef948d662 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -286,11 +286,11 @@ static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) u32 dsp_format, format, invert, value; /* clock masters */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */ + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: /* Codec slave, DAI master */ value = 0x1; break; - case SND_SOC_DAIFMT_CBM_CFM: /* Codec Master, DAI slave */ + case SND_SOC_DAIFMT_BC_FC: /* Codec Master, DAI slave */ value = 0x0; break; default: @@ -630,7 +630,7 @@ done: } static const struct snd_soc_dai_ops sun8i_codec_dai_ops = { - .set_fmt = sun8i_codec_set_fmt, + .set_fmt_new = sun8i_codec_set_fmt, .set_tdm_slot = sun8i_codec_set_tdm_slot, .startup = sun8i_codec_startup, .hw_params = sun8i_codec_hw_params, -- cgit From d92ad6633fa77f9496840b77c8effeaa13ac78dc Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:45 +0100 Subject: ASoC: tegra: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-24-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 8 ++++---- sound/soc/tegra/tegra210_i2s.c | 8 ++++---- sound/soc/tegra/tegra30_i2s.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 27365a877e47..9abb0e3536d8 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -95,11 +95,11 @@ static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, } mask |= TEGRA20_I2S_CTRL_MASTER_ENABLE; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: val |= TEGRA20_I2S_CTRL_MASTER_ENABLE; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: break; default: return -EINVAL; @@ -311,7 +311,7 @@ static int tegra20_i2s_startup(struct snd_pcm_substream *substream, } static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = { - .set_fmt = tegra20_i2s_set_fmt, + .set_fmt_new = tegra20_i2s_set_fmt, .hw_params = tegra20_i2s_hw_params, .trigger = tegra20_i2s_trigger, .startup = tegra20_i2s_startup, diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c index 9552bbb939dd..a304948ee393 100644 --- a/sound/soc/tegra/tegra210_i2s.c +++ b/sound/soc/tegra/tegra210_i2s.c @@ -214,11 +214,11 @@ static int tegra210_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int mask, val; mask = I2S_CTRL_MASTER_EN_MASK; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: val = 0; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: val = I2S_CTRL_MASTER_EN; break; default: @@ -678,7 +678,7 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream, } static const struct snd_soc_dai_ops tegra210_i2s_dai_ops = { - .set_fmt = tegra210_i2s_set_fmt, + .set_fmt_new = tegra210_i2s_set_fmt, .hw_params = tegra210_i2s_hw_params, .set_bclk_ratio = tegra210_i2s_set_dai_bclk_ratio, .set_tdm_slot = tegra210_i2s_set_tdm_slot, diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 084a533bf4f2..a4ea5221de6b 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -87,11 +87,11 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, } mask |= TEGRA30_I2S_CTRL_MASTER_ENABLE; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: val |= TEGRA30_I2S_CTRL_MASTER_ENABLE; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: break; default: return -EINVAL; @@ -304,7 +304,7 @@ static int tegra30_i2s_probe(struct snd_soc_dai *dai) } static const struct snd_soc_dai_ops tegra30_i2s_dai_ops = { - .set_fmt = tegra30_i2s_set_fmt, + .set_fmt_new = tegra30_i2s_set_fmt, .hw_params = tegra30_i2s_hw_params, .trigger = tegra30_i2s_trigger, .set_tdm_slot = tegra30_i2s_set_tdm, -- cgit From d444c8d246a62392c0d249b1030c3ca271d47649 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:46 +0100 Subject: ASoC: test-component: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update this CPU side driver to use the new direct callback. Signed-off-by: Charles Keepax Acked-by: Kuninori Morimoto Link: https://lore.kernel.org/r/20220519154318.2153729-25-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/generic/test-component.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c index 5da4725d9e16..3a992a6eba9b 100644 --- a/sound/soc/generic/test-component.c +++ b/sound/soc/generic/test-component.c @@ -66,7 +66,7 @@ static int test_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; unsigned int clock = fmt & SND_SOC_DAIFMT_CLOCK_MASK; unsigned int inv = fmt & SND_SOC_DAIFMT_INV_MASK; - unsigned int master = fmt & SND_SOC_DAIFMT_MASTER_MASK; + unsigned int master = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; char *str; dev_info(dai->dev, "name : %s", dai->name); @@ -105,16 +105,16 @@ static int test_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) str = "unknown"; switch (master) { - case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_BP_FP: str = "clk provider, frame provider"; break; - case SND_SOC_DAIFMT_CBC_CFP: + case SND_SOC_DAIFMT_BC_FP: str = "clk consumer, frame provider"; break; - case SND_SOC_DAIFMT_CBP_CFC: + case SND_SOC_DAIFMT_BP_FC: str = "clk provider, frame consumer"; break; - case SND_SOC_DAIFMT_CBC_CFC: + case SND_SOC_DAIFMT_BC_FC: str = "clk consumer, frame consumer"; break; } @@ -192,10 +192,10 @@ static int test_dai_bespoke_trigger(struct snd_pcm_substream *substream, static u64 test_dai_formats = /* * Select below from Sound Card, not auto - * SND_SOC_POSSIBLE_DAIFMT_CBP_CFP - * SND_SOC_POSSIBLE_DAIFMT_CBC_CFP - * SND_SOC_POSSIBLE_DAIFMT_CBP_CFC - * SND_SOC_POSSIBLE_DAIFMT_CBC_CFC + * SND_SOC_POSSIBLE_DAIFMT_BP_FP + * SND_SOC_POSSIBLE_DAIFMT_BC_FP + * SND_SOC_POSSIBLE_DAIFMT_BP_FC + * SND_SOC_POSSIBLE_DAIFMT_BC_FC */ SND_SOC_POSSIBLE_DAIFMT_I2S | SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | @@ -210,7 +210,7 @@ static u64 test_dai_formats = SND_SOC_POSSIBLE_DAIFMT_IB_IF; static const struct snd_soc_dai_ops test_ops = { - .set_fmt = test_dai_set_fmt, + .set_fmt_new = test_dai_set_fmt, .startup = test_dai_startup, .shutdown = test_dai_shutdown, .auto_selectable_formats = &test_dai_formats, @@ -221,7 +221,7 @@ static const struct snd_soc_dai_ops test_verbose_ops = { .set_sysclk = test_dai_set_sysclk, .set_pll = test_dai_set_pll, .set_clkdiv = test_dai_set_clkdiv, - .set_fmt = test_dai_set_fmt, + .set_fmt_new = test_dai_set_fmt, .mute_stream = test_dai_mute_stream, .startup = test_dai_startup, .shutdown = test_dai_shutdown, -- cgit From 563ff63dc9fbb8ef4b8f145a53c84a5489bbd789 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:47 +0100 Subject: ASoC: ti: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update these CPU side drivers to use the new direct callback. Signed-off-by: Charles Keepax Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20220519154318.2153729-26-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 34 +++++++++++++++++----------------- sound/soc/ti/davinci-mcasp.c | 12 ++++++------ sound/soc/ti/omap-mcbsp.c | 14 +++++++------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index 0363a088d2e0..c7368d529668 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -230,15 +230,15 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, dev->fmt = fmt; /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: /* cpu is master */ pcr = DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_BC_FP: pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM; /* * Selection of the clock input pin that is the @@ -260,7 +260,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, } break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: /* codec is master */ pcr = 0; break; @@ -395,12 +395,12 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); } - master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; + master = dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; fmt = params_format(params); mcbsp_word_length = asp_word_length[fmt]; switch (master) { - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: freq = clk_get_rate(dev->clk); srgr = DAVINCI_MCBSP_SRGR_FSGM | DAVINCI_MCBSP_SRGR_CLKSM; @@ -426,7 +426,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, clk_div &= 0xFF; srgr |= clk_div; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_BC_FP: srgr = DAVINCI_MCBSP_SRGR_FSGM; clk_div = dev->clk_div - 1; srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1); @@ -434,7 +434,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, clk_div &= 0xFF; srgr |= clk_div; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: /* Clock and frame sync given from external sources */ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); srgr = DAVINCI_MCBSP_SRGR_FSGM; @@ -473,15 +473,15 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, fmt = double_fmt[fmt]; } switch (master) { - case SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_BP_FP: + case SND_SOC_DAIFMT_BP_FC: rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(0); xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(0); rcr |= DAVINCI_MCBSP_RCR_RPHASE; xcr |= DAVINCI_MCBSP_XCR_XPHASE; break; - case SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_BC_FC: + case SND_SOC_DAIFMT_BC_FP: rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1); xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1); break; @@ -492,13 +492,13 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, mcbsp_word_length = asp_word_length[fmt]; switch (master) { - case SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_BP_FP: + case SND_SOC_DAIFMT_BP_FC: rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0); xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0); break; - case SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_BC_FC: + case SND_SOC_DAIFMT_BC_FP: rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1); xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1); break; @@ -606,7 +606,7 @@ static const struct snd_soc_dai_ops davinci_i2s_dai_ops = { .prepare = davinci_i2s_prepare, .trigger = davinci_i2s_trigger, .hw_params = davinci_i2s_hw_params, - .set_fmt = davinci_i2s_set_dai_fmt, + .set_fmt_new = davinci_i2s_set_dai_fmt, .set_clkdiv = davinci_i2s_dai_set_clkdiv, }; diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 377be2e2b6ee..961bac696365 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -492,8 +492,8 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, FSRDLY(data_delay), FSRDLY(3)); - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: /* codec is clock and frame slave */ mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE); @@ -510,7 +510,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp->bclk_master = 1; break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_BP_FC: /* codec is clock slave and frame master */ mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE); @@ -527,7 +527,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp->bclk_master = 1; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_BC_FP: /* codec is clock master and frame slave */ mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE); @@ -544,7 +544,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, mcasp->bclk_master = 0; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: /* codec is clock and frame master */ mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); mcasp_clr_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, AFSXE); @@ -1620,7 +1620,7 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { .trigger = davinci_mcasp_trigger, .delay = davinci_mcasp_delay, .hw_params = davinci_mcasp_hw_params, - .set_fmt = davinci_mcasp_set_dai_fmt, + .set_fmt_new = davinci_mcasp_set_dai_fmt, .set_clkdiv = davinci_mcasp_set_clkdiv, .set_sysclk = davinci_mcasp_set_sysclk, .set_tdm_slot = davinci_mcasp_set_tdm_slot, diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index 4479d74f0a45..5bfb56d4ff84 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -1036,8 +1036,8 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, /* In McBSP master modes, FRAME (i.e. sample rate) is generated * by _counting_ BCLKs. Calculate frame size in BCLKs */ - master = mcbsp->fmt & SND_SOC_DAIFMT_MASTER_MASK; - if (master == SND_SOC_DAIFMT_CBS_CFS) { + master = mcbsp->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; + if (master == SND_SOC_DAIFMT_BP_FP) { div = mcbsp->clk_div ? mcbsp->clk_div : 1; framesize = (mcbsp->in_freq / div) / params_rate(params); @@ -1136,20 +1136,20 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, return -EINVAL; } - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BP_FP: /* McBSP master. Set FS and bit clocks as outputs */ regs->pcr0 |= FSXM | FSRM | CLKXM | CLKRM; /* Sample rate generator drives the FS */ regs->srgr2 |= FSGM; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_BC_FP: /* McBSP slave. FS clock as output */ regs->srgr2 |= FSGM; regs->pcr0 |= FSXM | FSRM; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_BC_FC: /* McBSP slave */ break; default: @@ -1271,7 +1271,7 @@ static const struct snd_soc_dai_ops mcbsp_dai_ops = { .trigger = omap_mcbsp_dai_trigger, .delay = omap_mcbsp_dai_delay, .hw_params = omap_mcbsp_dai_hw_params, - .set_fmt = omap_mcbsp_dai_set_dai_fmt, + .set_fmt_new = omap_mcbsp_dai_set_dai_fmt, .set_clkdiv = omap_mcbsp_dai_set_clkdiv, .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, }; -- cgit From ce3467c78478e33927aea9043bf20f46fa4d5688 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:48 +0100 Subject: ASoC: ux500: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update this CPU side driver to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-27-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/ux500/ux500_msp_dai.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 21052378a32e..cd6c4bdf5041 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -191,8 +191,8 @@ static int setup_clocking(struct snd_soc_dai *dai, return -EINVAL; } - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: dev_dbg(dai->dev, "%s: Codec is master.\n", __func__); msp_config->iodelay = 0x20; @@ -204,7 +204,7 @@ static int setup_clocking(struct snd_soc_dai *dai, break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_BP_FP: dev_dbg(dai->dev, "%s: Codec is slave.\n", __func__); msp_config->tx_clk_sel = TX_CLK_SEL_SRG; @@ -328,15 +328,15 @@ static int setup_msp_config(struct snd_pcm_substream *substream, dev_dbg(dai->dev, "%s: rate: %u, channels: %d.\n", __func__, runtime->rate, runtime->channels); switch (fmt & - (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) { - case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: + (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK)) { + case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BP_FP: dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__); msp_config->default_protdesc = 1; msp_config->protocol = MSP_I2S_PROTOCOL; break; - case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BC_FC: dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__); msp_config->data_size = MSP_DATA_BITS_16; @@ -348,10 +348,10 @@ static int setup_msp_config(struct snd_pcm_substream *substream, break; - case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BP_FP: + case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BC_FC: + case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_BP_FP: + case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_BC_FC: dev_dbg(dai->dev, "%s: PCM format.\n", __func__); msp_config->data_size = MSP_DATA_BITS_16; @@ -477,7 +477,7 @@ static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream, } /* Set OPP-level */ - if ((drvdata->fmt & SND_SOC_DAIFMT_MASTER_MASK) && + if ((drvdata->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) && (drvdata->msp->f_bitclk > 19200000)) { /* If the bit-clock is higher than 19.2MHz, Vape should be * run in 100% OPP. Only when bit-clock is used (MSP master) @@ -544,13 +544,13 @@ static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *dai, dev_dbg(dai->dev, "%s: MSP %d: Enter.\n", __func__, dai->id); switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK | - SND_SOC_DAIFMT_MASTER_MASK)) { - case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: + SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK)) { + case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BP_FP: + case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BC_FC: + case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_BP_FP: + case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_BC_FC: + case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BP_FP: + case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BC_FC: break; default: @@ -707,7 +707,7 @@ static int ux500_msp_dai_probe(struct snd_soc_dai *dai) static const struct snd_soc_dai_ops ux500_msp_dai_ops[] = { { .set_sysclk = ux500_msp_dai_set_dai_sysclk, - .set_fmt = ux500_msp_dai_set_dai_fmt, + .set_fmt_new = ux500_msp_dai_set_dai_fmt, .set_tdm_slot = ux500_msp_dai_set_tdm_slot, .startup = ux500_msp_dai_startup, .shutdown = ux500_msp_dai_shutdown, -- cgit From e945206a0a448ac81dde0609578508368946f7a6 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:49 +0100 Subject: ASoC: xtensa: Update to use set_fmt_new callback As part of updating the core to directly tell drivers if they are clock provider or consumer update this CPU side driver to use the new direct callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-28-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/xtensa/xtfpga-i2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c index aeb4b2c4d1d3..72935f491901 100644 --- a/sound/soc/xtensa/xtfpga-i2s.c +++ b/sound/soc/xtensa/xtfpga-i2s.c @@ -339,7 +339,7 @@ static int xtfpga_i2s_set_fmt(struct snd_soc_dai *cpu_dai, { if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) return -EINVAL; - if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) + if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_BP_FP) return -EINVAL; if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S) return -EINVAL; @@ -487,7 +487,7 @@ static const struct snd_soc_component_driver xtfpga_i2s_component = { static const struct snd_soc_dai_ops xtfpga_i2s_dai_ops = { .startup = xtfpga_i2s_startup, .hw_params = xtfpga_i2s_hw_params, - .set_fmt = xtfpga_i2s_set_fmt, + .set_fmt_new = xtfpga_i2s_set_fmt, }; static struct snd_soc_dai_driver xtfpga_i2s_dai[] = { -- cgit From 6c076273a326cc5b5162451aacf7b7744bb03c66 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:50 +0100 Subject: ASoC: core: Always send the CPU DAI a direct clock specifier All CPU drivers are now updated to accept a direct indication of whether they are clock provider or consumer, rather than being told if the CODEC is clock provider. As such update the core to always pass this direct indication rather than only if the new set_fmt_new callback is defined. Note this makes no difference to the CODEC side of the DAI link as it was already being directly told if it was clock provider under the old system. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-29-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 90f4265bea50..227540851ded 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1214,7 +1214,6 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, { struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; - unsigned int inv_dai_fmt; unsigned int i; int ret; @@ -1227,19 +1226,11 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, return ret; } - /* - * Flip the polarity for the "CPU" end of a CODEC<->CODEC link - */ - inv_dai_fmt = snd_soc_daifmt_clock_provider_flipped(dai_fmt); + /* Flip the polarity for the "CPU" end of link */ + dai_fmt = snd_soc_daifmt_clock_provider_flipped(dai_fmt); for_each_rtd_cpu_dais(rtd, i, cpu_dai) { - unsigned int fmt = dai_fmt; - - if (cpu_dai->driver->ops->set_fmt_new || - snd_soc_component_is_codec(cpu_dai->component)) - fmt = inv_dai_fmt; - - ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt); if (ret != 0 && ret != -ENOTSUPP) return ret; } -- cgit From 346f47e784cd48b456f267a66e0daf1ef10d21b3 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:51 +0100 Subject: ASoC: amd: vangogh: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-30-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/amd/vangogh/acp5x-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/vangogh/acp5x-i2s.c b/sound/soc/amd/vangogh/acp5x-i2s.c index 40fbd0bc77fd..72c8c68e5933 100644 --- a/sound/soc/amd/vangogh/acp5x-i2s.c +++ b/sound/soc/amd/vangogh/acp5x-i2s.c @@ -339,7 +339,7 @@ static int acp5x_i2s_trigger(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops acp5x_i2s_dai_ops = { .hw_params = acp5x_i2s_hwparams, .trigger = acp5x_i2s_trigger, - .set_fmt_new = acp5x_i2s_set_fmt, + .set_fmt = acp5x_i2s_set_fmt, .set_tdm_slot = acp5x_i2s_set_tdm_slot, }; -- cgit From a839a53b9dc70f94032a671ee019599884612d4a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:52 +0100 Subject: ASoC: atmel: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-31-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-i2s.c | 2 +- sound/soc/atmel/atmel_ssc_dai.c | 2 +- sound/soc/atmel/mchp-i2s-mcc.c | 2 +- sound/soc/atmel/mchp-pdmc.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c index c5ce695da586..ba56d6ac7e57 100644 --- a/sound/soc/atmel/atmel-i2s.c +++ b/sound/soc/atmel/atmel-i2s.c @@ -533,7 +533,7 @@ static const struct snd_soc_dai_ops atmel_i2s_dai_ops = { .prepare = atmel_i2s_prepare, .trigger = atmel_i2s_trigger, .hw_params = atmel_i2s_hw_params, - .set_fmt_new = atmel_i2s_set_dai_fmt, + .set_fmt = atmel_i2s_set_dai_fmt, }; static int atmel_i2s_dai_probe(struct snd_soc_dai *dai) diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index da094762dc99..c92905e343e7 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -835,7 +835,7 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = { .prepare = atmel_ssc_prepare, .trigger = atmel_ssc_trigger, .hw_params = atmel_ssc_hw_params, - .set_fmt_new = atmel_ssc_set_dai_fmt, + .set_fmt = atmel_ssc_set_dai_fmt, .set_clkdiv = atmel_ssc_set_dai_clkdiv, }; diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 48d434e0c331..269eab56b6dd 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -877,7 +877,7 @@ static const struct snd_soc_dai_ops mchp_i2s_mcc_dai_ops = { .trigger = mchp_i2s_mcc_trigger, .hw_params = mchp_i2s_mcc_hw_params, .hw_free = mchp_i2s_mcc_hw_free, - .set_fmt_new = mchp_i2s_mcc_set_dai_fmt, + .set_fmt = mchp_i2s_mcc_set_dai_fmt, .set_tdm_slot = mchp_i2s_mcc_set_dai_tdm_slot, }; diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index b3f04fa2f608..b9f637059448 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -708,7 +708,7 @@ static int mchp_pdmc_trigger(struct snd_pcm_substream *substream, } static const struct snd_soc_dai_ops mchp_pdmc_dai_ops = { - .set_fmt_new = mchp_pdmc_set_fmt, + .set_fmt = mchp_pdmc_set_fmt, .startup = mchp_pdmc_startup, .shutdown = mchp_pdmc_shutdown, .hw_params = mchp_pdmc_hw_params, -- cgit From 2c73f5fd20a845fcb48173578b7c83dbcbacdeda Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:53 +0100 Subject: ASoC: au1x: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-32-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/au1x/i2sc.c | 2 +- sound/soc/au1x/psc-i2s.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c index 72f16b7fda3e..45bb7851e75d 100644 --- a/sound/soc/au1x/i2sc.c +++ b/sound/soc/au1x/i2sc.c @@ -206,7 +206,7 @@ static const struct snd_soc_dai_ops au1xi2s_dai_ops = { .startup = au1xi2s_startup, .trigger = au1xi2s_trigger, .hw_params = au1xi2s_hw_params, - .set_fmt_new = au1xi2s_set_fmt, + .set_fmt = au1xi2s_set_fmt, }; static struct snd_soc_dai_driver au1xi2s_dai_driver = { diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index d82c1353f2f0..530a072d7427 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c @@ -266,7 +266,7 @@ static const struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { .startup = au1xpsc_i2s_startup, .trigger = au1xpsc_i2s_trigger, .hw_params = au1xpsc_i2s_hw_params, - .set_fmt_new = au1xpsc_i2s_set_fmt, + .set_fmt = au1xpsc_i2s_set_fmt, }; static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = { -- cgit From 1a267dd98c246237be00587b6e71f969bf75f10d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:54 +0100 Subject: ASoC: bcm: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-33-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/bcm/bcm2835-i2s.c | 2 +- sound/soc/bcm/cygnus-ssp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index aa7d8e081f89..e39c8d9f4099 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -743,7 +743,7 @@ static const struct snd_soc_dai_ops bcm2835_i2s_dai_ops = { .prepare = bcm2835_i2s_prepare, .trigger = bcm2835_i2s_trigger, .hw_params = bcm2835_i2s_hw_params, - .set_fmt_new = bcm2835_i2s_set_dai_fmt, + .set_fmt = bcm2835_i2s_set_dai_fmt, .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio, .set_tdm_slot = bcm2835_i2s_set_dai_tdm_slot, }; diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c index 257f3657bcd6..4bfa2d715ff4 100644 --- a/sound/soc/bcm/cygnus-ssp.c +++ b/sound/soc/bcm/cygnus-ssp.c @@ -1148,7 +1148,7 @@ static const struct snd_soc_dai_ops cygnus_ssp_dai_ops = { .shutdown = cygnus_ssp_shutdown, .trigger = cygnus_ssp_trigger, .hw_params = cygnus_ssp_hw_params, - .set_fmt_new = cygnus_ssp_set_fmt, + .set_fmt = cygnus_ssp_set_fmt, .set_sysclk = cygnus_ssp_set_sysclk, .set_tdm_slot = cygnus_set_dai_tdm_slot, }; -- cgit From 324a4db8de05290237793dc3d7da887846ae90c1 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:55 +0100 Subject: ASoC: ep93xx: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-34-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/cirrus/ep93xx-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 2c8b1c76b834..47959794353a 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -398,7 +398,7 @@ static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = { .shutdown = ep93xx_i2s_shutdown, .hw_params = ep93xx_i2s_hw_params, .set_sysclk = ep93xx_i2s_set_sysclk, - .set_fmt_new = ep93xx_i2s_set_dai_fmt, + .set_fmt = ep93xx_i2s_set_dai_fmt, }; #define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) -- cgit From 765fb623a2cd925c550370f73efe2137c52a1b25 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:56 +0100 Subject: ASoC: dwc: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-35-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/dwc/dwc-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c index d3778d2d739d..e794e020052e 100644 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -387,7 +387,7 @@ static const struct snd_soc_dai_ops dw_i2s_dai_ops = { .hw_params = dw_i2s_hw_params, .prepare = dw_i2s_prepare, .trigger = dw_i2s_trigger, - .set_fmt_new = dw_i2s_set_fmt, + .set_fmt = dw_i2s_set_fmt, }; #ifdef CONFIG_PM -- cgit From 00778276cf4c611882219ab7aba9664c48981f1a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:57 +0100 Subject: ASoC: fsl: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-36-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_audmix.c | 2 +- sound/soc/fsl/fsl_esai.c | 2 +- sound/soc/fsl/fsl_mqs.c | 2 +- sound/soc/fsl/fsl_sai.c | 2 +- sound/soc/fsl/fsl_ssi.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index c580dcb9a4cf..43857b7a81c9 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -317,7 +317,7 @@ static int fsl_audmix_dai_trigger(struct snd_pcm_substream *substream, int cmd, } static const struct snd_soc_dai_ops fsl_audmix_dai_ops = { - .set_fmt_new = fsl_audmix_dai_set_fmt, + .set_fmt = fsl_audmix_dai_set_fmt, .trigger = fsl_audmix_dai_trigger, }; diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 572bdaee73eb..75f7807df29a 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -790,7 +790,7 @@ static const struct snd_soc_dai_ops fsl_esai_dai_ops = { .trigger = fsl_esai_trigger, .hw_params = fsl_esai_hw_params, .set_sysclk = fsl_esai_set_dai_sysclk, - .set_fmt_new = fsl_esai_set_dai_fmt, + .set_fmt = fsl_esai_set_dai_fmt, .set_tdm_slot = fsl_esai_set_dai_tdm_slot, }; diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c index 371d441b1dbe..fc539a139250 100644 --- a/sound/soc/fsl/fsl_mqs.c +++ b/sound/soc/fsl/fsl_mqs.c @@ -152,7 +152,7 @@ static const struct snd_soc_dai_ops fsl_mqs_dai_ops = { .startup = fsl_mqs_startup, .shutdown = fsl_mqs_shutdown, .hw_params = fsl_mqs_hw_params, - .set_fmt_new = fsl_mqs_set_dai_fmt, + .set_fmt = fsl_mqs_set_dai_fmt, }; static struct snd_soc_dai_driver fsl_mqs_dai = { diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 3edd302eb5c2..f67d8527876e 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -704,7 +704,7 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = { .set_bclk_ratio = fsl_sai_set_dai_bclk_ratio, .set_sysclk = fsl_sai_set_dai_sysclk, - .set_fmt_new = fsl_sai_set_dai_fmt, + .set_fmt = fsl_sai_set_dai_fmt, .set_tdm_slot = fsl_sai_set_dai_tdm_slot, .hw_params = fsl_sai_hw_params, .hw_free = fsl_sai_hw_free, diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 32e4cf37c202..7dd0c48cd9ae 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1156,7 +1156,7 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { .shutdown = fsl_ssi_shutdown, .hw_params = fsl_ssi_hw_params, .hw_free = fsl_ssi_hw_free, - .set_fmt_new = fsl_ssi_set_dai_fmt, + .set_fmt = fsl_ssi_set_dai_fmt, .set_tdm_slot = fsl_ssi_set_dai_tdm_slot, .trigger = fsl_ssi_trigger, }; -- cgit From b9a7972818b84a15d46505df7808fd86c3fba5bb Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:58 +0100 Subject: ASoC: hisilicon: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-37-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/hisilicon/hi6210-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/hisilicon/hi6210-i2s.c b/sound/soc/hisilicon/hi6210-i2s.c index 51f98ae651a6..689ae13f34f5 100644 --- a/sound/soc/hisilicon/hi6210-i2s.c +++ b/sound/soc/hisilicon/hi6210-i2s.c @@ -513,7 +513,7 @@ static int hi6210_i2s_dai_probe(struct snd_soc_dai *dai) static const struct snd_soc_dai_ops hi6210_i2s_dai_ops = { .trigger = hi6210_i2s_trigger, .hw_params = hi6210_i2s_hw_params, - .set_fmt_new = hi6210_i2s_set_fmt, + .set_fmt = hi6210_i2s_set_fmt, .startup = hi6210_i2s_startup, .shutdown = hi6210_i2s_shutdown, }; -- cgit From 1830a30ec4cf1642a429e80dbbeb86aa7825c71a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:42:59 +0100 Subject: ASoC: img: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-38-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/img/img-i2s-in.c | 2 +- sound/soc/img/img-i2s-out.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c index 79e733bc0ae6..97cab6d95b16 100644 --- a/sound/soc/img/img-i2s-in.c +++ b/sound/soc/img/img-i2s-in.c @@ -373,7 +373,7 @@ static int img_i2s_in_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static const struct snd_soc_dai_ops img_i2s_in_dai_ops = { .trigger = img_i2s_in_trigger, .hw_params = img_i2s_in_hw_params, - .set_fmt_new = img_i2s_in_set_fmt + .set_fmt = img_i2s_in_set_fmt }; static int img_i2s_in_dai_probe(struct snd_soc_dai *dai) diff --git a/sound/soc/img/img-i2s-out.c b/sound/soc/img/img-i2s-out.c index d92539603d6c..9ec6fc528e2b 100644 --- a/sound/soc/img/img-i2s-out.c +++ b/sound/soc/img/img-i2s-out.c @@ -381,7 +381,7 @@ static int img_i2s_out_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static const struct snd_soc_dai_ops img_i2s_out_dai_ops = { .trigger = img_i2s_out_trigger, .hw_params = img_i2s_out_hw_params, - .set_fmt_new = img_i2s_out_set_fmt + .set_fmt = img_i2s_out_set_fmt }; static int img_i2s_out_dai_probe(struct snd_soc_dai *dai) -- cgit From c14a6ce9848571cf67faff206b02e212bec82761 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:00 +0100 Subject: ASoC: Intel: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-39-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-mfld-platform-pcm.c | 2 +- sound/soc/intel/keembay/kmb_platform.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 339d9440c150..a56dd48c045f 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -473,7 +473,7 @@ static const struct snd_soc_dai_ops sst_compr_dai_ops = { static const struct snd_soc_dai_ops sst_be_dai_ops = { .startup = sst_enable_ssp, .hw_params = sst_be_hw_params, - .set_fmt_new = sst_set_format, + .set_fmt = sst_set_format, .set_tdm_slot = sst_platform_set_ssp_slot, .shutdown = sst_disable_ssp, }; diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c index a65f03884d9a..d10881fedc8b 100644 --- a/sound/soc/intel/keembay/kmb_platform.c +++ b/sound/soc/intel/keembay/kmb_platform.c @@ -736,7 +736,7 @@ static const struct snd_soc_dai_ops kmb_dai_ops = { .hw_params = kmb_dai_hw_params, .hw_free = kmb_dai_hw_free, .prepare = kmb_dai_prepare, - .set_fmt_new = kmb_set_dai_fmt, + .set_fmt = kmb_set_dai_fmt, }; static struct snd_soc_dai_driver intel_kmb_hdmi_dai[] = { -- cgit From 1724cc38e7685ad8b01413acd70a4a731fc105ae Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:01 +0100 Subject: ASoC: jz4740-i2s: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-40-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/jz4740/jz4740-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 2c9dee241778..446c5e061564 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -433,7 +433,7 @@ static const struct snd_soc_dai_ops jz4740_i2s_dai_ops = { .shutdown = jz4740_i2s_shutdown, .trigger = jz4740_i2s_trigger, .hw_params = jz4740_i2s_hw_params, - .set_fmt_new = jz4740_i2s_set_fmt, + .set_fmt = jz4740_i2s_set_fmt, .set_sysclk = jz4740_i2s_set_sysclk, }; -- cgit From 00ca2d152ef0fa9f4beb2a590e176499440de8fe Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:02 +0100 Subject: ASoC: mediatek: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-41-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-dai-etdm.c | 4 ++-- sound/soc/mediatek/mt8195/mt8195-dai-pcm.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c index 5f7c9516dfa1..c2e268054773 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c @@ -2346,7 +2346,7 @@ static const struct snd_soc_dai_ops mtk_dai_etdm_ops = { .hw_params = mtk_dai_etdm_hw_params, .trigger = mtk_dai_etdm_trigger, .set_sysclk = mtk_dai_etdm_set_sysclk, - .set_fmt_new = mtk_dai_etdm_set_fmt, + .set_fmt = mtk_dai_etdm_set_fmt, .set_tdm_slot = mtk_dai_etdm_set_tdm_slot, }; @@ -2356,7 +2356,7 @@ static const struct snd_soc_dai_ops mtk_dai_hdmitx_dptx_ops = { .hw_params = mtk_dai_hdmitx_dptx_hw_params, .trigger = mtk_dai_hdmitx_dptx_trigger, .set_sysclk = mtk_dai_hdmitx_dptx_set_sysclk, - .set_fmt_new = mtk_dai_etdm_set_fmt, + .set_fmt = mtk_dai_etdm_set_fmt, }; /* dai driver */ diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c index 37a8968ac21d..caceb0deb467 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c @@ -282,7 +282,7 @@ static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static const struct snd_soc_dai_ops mtk_dai_pcm_ops = { .prepare = mtk_dai_pcm_prepare, - .set_fmt_new = mtk_dai_pcm_set_fmt, + .set_fmt = mtk_dai_pcm_set_fmt, }; /* dai driver */ -- cgit From eee6b5b9f3af0e906085022713ef41e56d03eca8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:03 +0100 Subject: ASoC: meson: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-42-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/meson/aiu-encoder-i2s.c | 2 +- sound/soc/meson/axg-tdm-interface.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c index 0ab991230dee..a0dd914c8ed1 100644 --- a/sound/soc/meson/aiu-encoder-i2s.c +++ b/sound/soc/meson/aiu-encoder-i2s.c @@ -323,7 +323,7 @@ static void aiu_encoder_i2s_shutdown(struct snd_pcm_substream *substream, const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops = { .hw_params = aiu_encoder_i2s_hw_params, .hw_free = aiu_encoder_i2s_hw_free, - .set_fmt_new = aiu_encoder_i2s_set_fmt, + .set_fmt = aiu_encoder_i2s_set_fmt, .set_sysclk = aiu_encoder_i2s_set_sysclk, .startup = aiu_encoder_i2s_startup, .shutdown = aiu_encoder_i2s_shutdown, diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index ffdb12d0e01e..c040c83637e0 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -394,7 +394,7 @@ static int axg_tdm_iface_probe_dai(struct snd_soc_dai *dai) static const struct snd_soc_dai_ops axg_tdm_iface_ops = { .set_sysclk = axg_tdm_iface_set_sysclk, - .set_fmt_new = axg_tdm_iface_set_fmt, + .set_fmt = axg_tdm_iface_set_fmt, .startup = axg_tdm_iface_startup, .hw_params = axg_tdm_iface_hw_params, .prepare = axg_tdm_iface_prepare, -- cgit From 1a805faeb4915496671cd24bd2a75cc97a85dfc8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:04 +0100 Subject: ASoC: mxs-saif: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-43-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-saif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index 38de46ba1583..467b0f2ce0bb 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -642,7 +642,7 @@ static const struct snd_soc_dai_ops mxs_saif_dai_ops = { .prepare = mxs_saif_prepare, .hw_params = mxs_saif_hw_params, .set_sysclk = mxs_saif_set_dai_sysclk, - .set_fmt_new = mxs_saif_set_dai_fmt, + .set_fmt = mxs_saif_set_dai_fmt, }; static struct snd_soc_dai_driver mxs_saif_dai = { -- cgit From 8e2cc2b241bc0bb905231f301e6dfc80dc79f8a8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:05 +0100 Subject: ASoC: pxa: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-44-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 2 +- sound/soc/pxa/pxa-ssp.c | 2 +- sound/soc/pxa/pxa2xx-i2s.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index b746e52aaf85..382e9d8608a3 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -346,7 +346,7 @@ static const struct snd_soc_dai_ops mmp_sspa_dai_ops = { .hw_params = mmp_sspa_hw_params, .set_sysclk = mmp_sspa_set_dai_sysclk, .set_pll = mmp_sspa_set_dai_pll, - .set_fmt_new = mmp_sspa_set_dai_fmt, + .set_fmt = mmp_sspa_set_dai_fmt, }; static struct snd_soc_dai_driver mmp_sspa_dai = { diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 52124be1778e..0f504a9f4983 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -824,7 +824,7 @@ static const struct snd_soc_dai_ops pxa_ssp_dai_ops = { .trigger = pxa_ssp_trigger, .hw_params = pxa_ssp_hw_params, .set_sysclk = pxa_ssp_set_dai_sysclk, - .set_fmt_new = pxa_ssp_set_dai_fmt, + .set_fmt = pxa_ssp_set_dai_fmt, .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, .set_tristate = pxa_ssp_set_dai_tristate, }; diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 9f12fc3615b6..ffcf44e4dc8c 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -333,7 +333,7 @@ static const struct snd_soc_dai_ops pxa_i2s_dai_ops = { .shutdown = pxa2xx_i2s_shutdown, .trigger = pxa2xx_i2s_trigger, .hw_params = pxa2xx_i2s_hw_params, - .set_fmt_new = pxa2xx_i2s_set_dai_fmt, + .set_fmt = pxa2xx_i2s_set_dai_fmt, .set_sysclk = pxa2xx_i2s_set_dai_sysclk, }; -- cgit From f1bd2fae856384f9377ca3faed0583d929002640 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:06 +0100 Subject: ASoC: qcom: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-45-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6afe-dai.c | 2 +- sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c index 8f8794cffc1c..8bb7452b8f18 100644 --- a/sound/soc/qcom/qdsp6/q6afe-dai.c +++ b/sound/soc/qcom/qdsp6/q6afe-dai.c @@ -648,7 +648,7 @@ static const struct snd_soc_dai_ops q6hdmi_ops = { static const struct snd_soc_dai_ops q6i2s_ops = { .prepare = q6afe_dai_prepare, .hw_params = q6i2s_hw_params, - .set_fmt_new = q6i2s_set_fmt, + .set_fmt = q6i2s_set_fmt, .shutdown = q6afe_dai_shutdown, .set_sysclk = q6afe_mi2s_set_sysclk, }; diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c index 82ee52051f83..ce9e5646d8f3 100644 --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c @@ -207,7 +207,7 @@ static const struct snd_soc_dai_ops q6i2s_ops = { .shutdown = q6apm_lpass_dai_shutdown, .set_channel_map = q6dma_set_channel_map, .hw_params = q6dma_hw_params, - .set_fmt_new = q6i2s_set_fmt, + .set_fmt = q6i2s_set_fmt, }; static const struct snd_soc_component_driver q6apm_lpass_dai_component = { -- cgit From 059f16bc0e02164617312435c31dffdc419f113f Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:07 +0100 Subject: ASoC: rockchip: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-46-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rockchip_i2s.c | 2 +- sound/soc/rockchip/rockchip_i2s_tdm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 0a66c7df323d..47a3971a9ce1 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -486,7 +486,7 @@ static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = { .hw_params = rockchip_i2s_hw_params, .set_bclk_ratio = rockchip_i2s_set_bclk_ratio, .set_sysclk = rockchip_i2s_set_sysclk, - .set_fmt_new = rockchip_i2s_set_fmt, + .set_fmt = rockchip_i2s_set_fmt, .trigger = rockchip_i2s_trigger, }; diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c index c90afccdae36..48b3ecfa58b4 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -1113,7 +1113,7 @@ static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = { .hw_params = rockchip_i2s_tdm_hw_params, .set_bclk_ratio = rockchip_i2s_tdm_set_bclk_ratio, .set_sysclk = rockchip_i2s_tdm_set_sysclk, - .set_fmt_new = rockchip_i2s_tdm_set_fmt, + .set_fmt = rockchip_i2s_tdm_set_fmt, .set_tdm_slot = rockchip_dai_tdm_slot, .trigger = rockchip_i2s_tdm_trigger, }; -- cgit From b99d00c724bcf395558cb3028e823bd8f554fee6 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:08 +0100 Subject: ASoC: samsung: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220519154318.2153729-47-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 2 +- sound/soc/samsung/pcm.c | 2 +- sound/soc/samsung/s3c-i2s-v2.c | 2 +- sound/soc/samsung/s3c24xx-i2s.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 9ed275ebd744..fdd9561c6a9f 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1107,7 +1107,7 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) static const struct snd_soc_dai_ops samsung_i2s_dai_ops = { .trigger = i2s_trigger, .hw_params = i2s_hw_params, - .set_fmt_new = i2s_set_fmt, + .set_fmt = i2s_set_fmt, .set_clkdiv = i2s_set_clkdiv, .set_sysclk = i2s_set_sysclk, .startup = i2s_startup, diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 818172d8832d..c2eb3534bfcc 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -437,7 +437,7 @@ static const struct snd_soc_dai_ops s3c_pcm_dai_ops = { .set_clkdiv = s3c_pcm_set_clkdiv, .trigger = s3c_pcm_trigger, .hw_params = s3c_pcm_hw_params, - .set_fmt_new = s3c_pcm_set_fmt, + .set_fmt = s3c_pcm_set_fmt, }; static int s3c_pcm_dai_probe(struct snd_soc_dai *dai) diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index 9c8a0697849d..1bec72246ed0 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c @@ -666,7 +666,7 @@ int s3c_i2sv2_register_component(struct device *dev, int id, ops->trigger = s3c2412_i2s_trigger; if (!ops->hw_params) ops->hw_params = s3c_i2sv2_hw_params; - ops->set_fmt_new = s3c2412_i2s_set_fmt; + ops->set_fmt = s3c2412_i2s_set_fmt; ops->set_clkdiv = s3c2412_i2s_set_clkdiv; ops->set_sysclk = s3c_i2sv2_set_sysclk; diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 6226b3b585e5..4082ad7cbcc1 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c @@ -394,7 +394,7 @@ static int s3c24xx_i2s_resume(struct snd_soc_component *component) static const struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = { .trigger = s3c24xx_i2s_trigger, .hw_params = s3c24xx_i2s_hw_params, - .set_fmt_new = s3c24xx_i2s_set_fmt, + .set_fmt = s3c24xx_i2s_set_fmt, .set_clkdiv = s3c24xx_i2s_set_clkdiv, .set_sysclk = s3c24xx_i2s_set_sysclk, }; -- cgit From adced68031f96642272fae4e8c36d45d13797306 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:09 +0100 Subject: ASoC: sh: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-48-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/sh/fsi.c | 2 +- sound/soc/sh/rcar/core.c | 2 +- sound/soc/sh/rz-ssi.c | 2 +- sound/soc/sh/ssi.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 4058d60b7e93..f3edc2e3d9d7 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1724,7 +1724,7 @@ static const struct snd_soc_dai_ops fsi_dai_ops = { .startup = fsi_dai_startup, .shutdown = fsi_dai_shutdown, .trigger = fsi_dai_trigger, - .set_fmt_new = fsi_dai_set_fmt, + .set_fmt = fsi_dai_set_fmt, .hw_params = fsi_dai_hw_params, .auto_selectable_formats = &fsi_dai_formats, .num_auto_selectable_formats = 1, diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 0ac15b74c58a..a4180dc5a59b 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1068,7 +1068,7 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { .startup = rsnd_soc_dai_startup, .shutdown = rsnd_soc_dai_shutdown, .trigger = rsnd_soc_dai_trigger, - .set_fmt_new = rsnd_soc_dai_set_fmt, + .set_fmt = rsnd_soc_dai_set_fmt, .set_tdm_slot = rsnd_soc_set_dai_tdm_slot, .prepare = rsnd_soc_dai_prepare, .auto_selectable_formats = rsnd_soc_dai_formats, diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index 0557d22a089f..beaf1a8d6da1 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -840,7 +840,7 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream, static const struct snd_soc_dai_ops rz_ssi_dai_ops = { .trigger = rz_ssi_dai_trigger, - .set_fmt_new = rz_ssi_dai_set_fmt, + .set_fmt = rz_ssi_dai_set_fmt, .hw_params = rz_ssi_dai_hw_params, }; diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c index 95571cbeae29..bf7a3c69920a 100644 --- a/sound/soc/sh/ssi.c +++ b/sound/soc/sh/ssi.c @@ -336,7 +336,7 @@ static const struct snd_soc_dai_ops ssi_dai_ops = { .hw_params = ssi_hw_params, .set_sysclk = ssi_set_sysclk, .set_clkdiv = ssi_set_clkdiv, - .set_fmt_new = ssi_set_fmt, + .set_fmt = ssi_set_fmt, }; static struct snd_soc_dai_driver sh4_ssi_dai[] = { -- cgit From 02ba0d9680feee645a321d65012f38d0a368b559 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:10 +0100 Subject: ASoC: stm: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-49-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_i2s.c | 2 +- sound/soc/stm/stm32_sai_sub.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 30c04f96ef1d..32d885f84a92 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -954,7 +954,7 @@ static const struct regmap_config stm32_h7_i2s_regmap_conf = { static const struct snd_soc_dai_ops stm32_i2s_pcm_dai_ops = { .set_sysclk = stm32_i2s_set_sysclk, - .set_fmt_new = stm32_i2s_set_dai_fmt, + .set_fmt = stm32_i2s_set_dai_fmt, .startup = stm32_i2s_startup, .hw_params = stm32_i2s_hw_params, .trigger = stm32_i2s_trigger, diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 9f169b93fa74..e09221b5f1f3 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1225,7 +1225,7 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai) static const struct snd_soc_dai_ops stm32_sai_pcm_dai_ops = { .set_sysclk = stm32_sai_set_sysclk, - .set_fmt_new = stm32_sai_set_dai_fmt, + .set_fmt = stm32_sai_set_dai_fmt, .set_tdm_slot = stm32_sai_set_dai_tdm_slot, .startup = stm32_sai_startup, .hw_params = stm32_sai_hw_params, -- cgit From 15011b2388d020a6cdb323539fc69c31b04d9f21 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:11 +0100 Subject: ASoC: sunxi: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-50-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 2 +- sound/soc/sunxi/sun8i-codec.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 872838d3e0a9..f58aa6406a87 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -1081,7 +1081,7 @@ static int sun4i_i2s_set_tdm_slot(struct snd_soc_dai *dai, static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = { .hw_params = sun4i_i2s_hw_params, - .set_fmt_new = sun4i_i2s_set_fmt, + .set_fmt = sun4i_i2s_set_fmt, .set_sysclk = sun4i_i2s_set_sysclk, .set_tdm_slot = sun4i_i2s_set_tdm_slot, .trigger = sun4i_i2s_trigger, diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 6e9ef948d662..90d74a2d53f3 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -630,7 +630,7 @@ done: } static const struct snd_soc_dai_ops sun8i_codec_dai_ops = { - .set_fmt_new = sun8i_codec_set_fmt, + .set_fmt = sun8i_codec_set_fmt, .set_tdm_slot = sun8i_codec_set_tdm_slot, .startup = sun8i_codec_startup, .hw_params = sun8i_codec_hw_params, -- cgit From 475f2af6a2ff33e828900601a162e324b9986f9a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:12 +0100 Subject: ASoC: tegra: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-51-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 2 +- sound/soc/tegra/tegra210_i2s.c | 2 +- sound/soc/tegra/tegra30_i2s.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 9abb0e3536d8..2e1a726602f0 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -311,7 +311,7 @@ static int tegra20_i2s_startup(struct snd_pcm_substream *substream, } static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = { - .set_fmt_new = tegra20_i2s_set_fmt, + .set_fmt = tegra20_i2s_set_fmt, .hw_params = tegra20_i2s_hw_params, .trigger = tegra20_i2s_trigger, .startup = tegra20_i2s_startup, diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c index a304948ee393..a28945895466 100644 --- a/sound/soc/tegra/tegra210_i2s.c +++ b/sound/soc/tegra/tegra210_i2s.c @@ -678,7 +678,7 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream, } static const struct snd_soc_dai_ops tegra210_i2s_dai_ops = { - .set_fmt_new = tegra210_i2s_set_fmt, + .set_fmt = tegra210_i2s_set_fmt, .hw_params = tegra210_i2s_hw_params, .set_bclk_ratio = tegra210_i2s_set_dai_bclk_ratio, .set_tdm_slot = tegra210_i2s_set_tdm_slot, diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index a4ea5221de6b..3aa157c82ae2 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -304,7 +304,7 @@ static int tegra30_i2s_probe(struct snd_soc_dai *dai) } static const struct snd_soc_dai_ops tegra30_i2s_dai_ops = { - .set_fmt_new = tegra30_i2s_set_fmt, + .set_fmt = tegra30_i2s_set_fmt, .hw_params = tegra30_i2s_hw_params, .trigger = tegra30_i2s_trigger, .set_tdm_slot = tegra30_i2s_set_tdm, -- cgit From 408c122ef9de99220f7919594ab8af98194a19e8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:13 +0100 Subject: ASoC: test-component: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-52-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/generic/test-component.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c index 3a992a6eba9b..d28712fabe3f 100644 --- a/sound/soc/generic/test-component.c +++ b/sound/soc/generic/test-component.c @@ -210,7 +210,7 @@ static u64 test_dai_formats = SND_SOC_POSSIBLE_DAIFMT_IB_IF; static const struct snd_soc_dai_ops test_ops = { - .set_fmt_new = test_dai_set_fmt, + .set_fmt = test_dai_set_fmt, .startup = test_dai_startup, .shutdown = test_dai_shutdown, .auto_selectable_formats = &test_dai_formats, @@ -221,7 +221,7 @@ static const struct snd_soc_dai_ops test_verbose_ops = { .set_sysclk = test_dai_set_sysclk, .set_pll = test_dai_set_pll, .set_clkdiv = test_dai_set_clkdiv, - .set_fmt_new = test_dai_set_fmt, + .set_fmt = test_dai_set_fmt, .mute_stream = test_dai_mute_stream, .startup = test_dai_startup, .shutdown = test_dai_shutdown, -- cgit From 9ff1836023ae19013c01f230e6a091fad6835213 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:14 +0100 Subject: ASoC: ti: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20220519154318.2153729-53-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 2 +- sound/soc/ti/davinci-mcasp.c | 2 +- sound/soc/ti/omap-mcbsp.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index c7368d529668..fe572b720b09 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -606,7 +606,7 @@ static const struct snd_soc_dai_ops davinci_i2s_dai_ops = { .prepare = davinci_i2s_prepare, .trigger = davinci_i2s_trigger, .hw_params = davinci_i2s_hw_params, - .set_fmt_new = davinci_i2s_set_dai_fmt, + .set_fmt = davinci_i2s_set_dai_fmt, .set_clkdiv = davinci_i2s_dai_set_clkdiv, }; diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 961bac696365..e2aab4729f3a 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -1620,7 +1620,7 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = { .trigger = davinci_mcasp_trigger, .delay = davinci_mcasp_delay, .hw_params = davinci_mcasp_hw_params, - .set_fmt_new = davinci_mcasp_set_dai_fmt, + .set_fmt = davinci_mcasp_set_dai_fmt, .set_clkdiv = davinci_mcasp_set_clkdiv, .set_sysclk = davinci_mcasp_set_sysclk, .set_tdm_slot = davinci_mcasp_set_tdm_slot, diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index 5bfb56d4ff84..58d8e200a7b9 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -1271,7 +1271,7 @@ static const struct snd_soc_dai_ops mcbsp_dai_ops = { .trigger = omap_mcbsp_dai_trigger, .delay = omap_mcbsp_dai_delay, .hw_params = omap_mcbsp_dai_hw_params, - .set_fmt_new = omap_mcbsp_dai_set_dai_fmt, + .set_fmt = omap_mcbsp_dai_set_dai_fmt, .set_clkdiv = omap_mcbsp_dai_set_clkdiv, .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, }; -- cgit From e24ba1a21e244e7174e75ca0c4020beaff0ad369 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:15 +0100 Subject: ASoC: ux500: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-54-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/ux500/ux500_msp_dai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index cd6c4bdf5041..851c3b8473fd 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -707,7 +707,7 @@ static int ux500_msp_dai_probe(struct snd_soc_dai *dai) static const struct snd_soc_dai_ops ux500_msp_dai_ops[] = { { .set_sysclk = ux500_msp_dai_set_dai_sysclk, - .set_fmt_new = ux500_msp_dai_set_dai_fmt, + .set_fmt = ux500_msp_dai_set_dai_fmt, .set_tdm_slot = ux500_msp_dai_set_tdm_slot, .startup = ux500_msp_dai_startup, .shutdown = ux500_msp_dai_shutdown, -- cgit From 58e23e21d18532aaa404e1db87ec92762e1fecd5 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:16 +0100 Subject: ASoC: xtensa: Rename set_fmt_new back to set_fmt Now the core has been migrated across to the new direct clock specification we can move the drivers back to the normal set_fmt callback. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-55-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/xtensa/xtfpga-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/xtensa/xtfpga-i2s.c b/sound/soc/xtensa/xtfpga-i2s.c index 72935f491901..8bd121546032 100644 --- a/sound/soc/xtensa/xtfpga-i2s.c +++ b/sound/soc/xtensa/xtfpga-i2s.c @@ -487,7 +487,7 @@ static const struct snd_soc_component_driver xtfpga_i2s_component = { static const struct snd_soc_dai_ops xtfpga_i2s_dai_ops = { .startup = xtfpga_i2s_startup, .hw_params = xtfpga_i2s_hw_params, - .set_fmt_new = xtfpga_i2s_set_fmt, + .set_fmt = xtfpga_i2s_set_fmt, }; static struct snd_soc_dai_driver xtfpga_i2s_dai[] = { -- cgit From 19423951a4b5c4f0ca107d6a4bed23f3f63718ca Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:17 +0100 Subject: ASoC: soc-dai: Remove set_fmt_new callback Now the behaviour of the core and all drivers is updated to the new direct clock specification the temporary set_fmt_new callback can be completely removed. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-56-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc-dai.h | 1 - sound/soc/soc-dai.c | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 9c1d92d5a373..ea7509672086 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -288,7 +288,6 @@ struct snd_soc_dai_ops { * Called by soc_card drivers, normally in their hw_params. */ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); - int (*set_fmt_new)(struct snd_soc_dai *dai, unsigned int fmt); int (*xlate_tdm_slot_mask)(unsigned int slots, unsigned int *tx_mask, unsigned int *rx_mask); int (*set_tdm_slot)(struct snd_soc_dai *dai, diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 996712f4d9bf..d530e8c2b77b 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -208,11 +208,7 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { int ret = -ENOTSUPP; - if (dai->driver->ops && - dai->driver->ops->set_fmt_new) - ret = dai->driver->ops->set_fmt_new(dai, fmt); - else if (dai->driver->ops && - dai->driver->ops->set_fmt) + if (dai->driver->ops && dai->driver->ops->set_fmt) ret = dai->driver->ops->set_fmt(dai, fmt); return soc_dai_ret(dai, ret); -- cgit From 28086d05ada6d03daa886aad0e469854b811311c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 19 May 2022 16:43:18 +0100 Subject: ASoC: simple-card-utils: Move snd_soc_component_is_codec to be local The helper function snd_soc_component_is_codec is based off the presence of the non_legacy_dai_naming flag. This isn't super robust as CPU side components may also specify this flag, and indeed the kernel already contains a couple that do. After componentisation there isn't really a totally robust solution to identifying what is a CODEC driver, without introducing a flag specifically for that purpose, and really the desirable direction to move in is that the distinction doesn't matter. This patch does two things to try to mitigate these problems. Firstly, now that all the other users of the helper function have been removed, it makes the helper function local to the driver rather, than being part of the core. This should help to discourage any new code from being created that depends on the CODEC driver distinction. Secondly, it updates the helper function itself to use the endianness flag rather than the non_legacy_dai_naming flag. The endianness flag is definitely invalid on a CPU side component, so it a more reliable indicator that the device is definitely a CODEC. The vast majority of buses require the CODEC to set the endianness flag, so the number of corner cases should be fairly minimal. It is worth noting that CODECs sending audio over SPI, or built into the CPU CODECs are potential corner cases, however the hope is that in most cases those types of devices do not consitute a simple audio card. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220519154318.2153729-57-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 5 ----- sound/soc/generic/simple-card-utils.c | 7 ++++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 5a764c3099d3..5c4cfa70b018 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -348,11 +348,6 @@ static inline int snd_soc_component_cache_sync( return regcache_sync(component->regmap); } -static inline int snd_soc_component_is_codec(struct snd_soc_component *component) -{ - return component->driver->non_legacy_dai_naming; -} - void snd_soc_component_set_aux(struct snd_soc_component *component, struct snd_soc_aux_dev *aux); int snd_soc_component_init(struct snd_soc_component *component); diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 539d7f081bd7..50a982708933 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -513,6 +513,11 @@ static int asoc_simple_init_dai(struct snd_soc_dai *dai, return 0; } +static inline int asoc_simple_component_is_codec(struct snd_soc_component *component) +{ + return component->driver->endianness; +} + static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd, struct simple_dai_props *dai_props) { @@ -524,7 +529,7 @@ static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd, /* Only Codecs */ for_each_rtd_components(rtd, i, component) { - if (!snd_soc_component_is_codec(component)) + if (!asoc_simple_component_is_codec(component)) return 0; } -- cgit From 60391d788a221f1866492a71929483790b772676 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 3 Jun 2022 16:05:10 +0200 Subject: ASoC: ak4642: Drop no-op remove function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A remove callback that just returns 0 is equivalent to no callback at all as can be seen in i2c_device_remove(). So simplify accordingly. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20220603140513.131142-2-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/ak4613.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index 55e773f92122..648208d40d06 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -919,18 +919,12 @@ static int ak4613_i2c_probe(struct i2c_client *i2c) &ak4613_dai, 1); } -static int ak4613_i2c_remove(struct i2c_client *client) -{ - return 0; -} - static struct i2c_driver ak4613_i2c_driver = { .driver = { .name = "ak4613-codec", .of_match_table = ak4613_of_match, }, .probe_new = ak4613_i2c_probe, - .remove = ak4613_i2c_remove, .id_table = ak4613_i2c_id, }; -- cgit From 8a291eebeb633316edad2e80537a3c7df83ee8dc Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 3 Jun 2022 16:05:11 +0200 Subject: ASoC: da7219: Drop no-op remove function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A remove callback that just returns 0 is equivalent to no callback at all as can be seen in i2c_device_remove(). So simplify accordingly. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20220603140513.131142-3-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/da7219.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 7fdef38ed8cd..c18f76f370fc 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -2693,11 +2693,6 @@ static int da7219_i2c_probe(struct i2c_client *i2c) return ret; } -static int da7219_i2c_remove(struct i2c_client *client) -{ - return 0; -} - static const struct i2c_device_id da7219_i2c_id[] = { { "da7219", }, { } @@ -2711,7 +2706,6 @@ static struct i2c_driver da7219_i2c_driver = { .acpi_match_table = ACPI_PTR(da7219_acpi_match), }, .probe_new = da7219_i2c_probe, - .remove = da7219_i2c_remove, .id_table = da7219_i2c_id, }; -- cgit From 3cce931a5e4487f7339be559e2ea032478be021a Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 3 Jun 2022 16:05:12 +0200 Subject: ASoC: lm49453: Drop no-op remove function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A remove callback that just returns 0 is equivalent to no callback at all as can be seen in i2c_device_remove(). So simplify accordingly. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20220603140513.131142-4-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/lm49453.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index bd0078e4499b..c4900ada8618 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -1442,11 +1442,6 @@ static int lm49453_i2c_probe(struct i2c_client *i2c) return ret; } -static int lm49453_i2c_remove(struct i2c_client *client) -{ - return 0; -} - static const struct i2c_device_id lm49453_i2c_id[] = { { "lm49453", 0 }, { } @@ -1458,7 +1453,6 @@ static struct i2c_driver lm49453_i2c_driver = { .name = "lm49453", }, .probe_new = lm49453_i2c_probe, - .remove = lm49453_i2c_remove, .id_table = lm49453_i2c_id, }; -- cgit From fb68cb963bb78380166a98beea593d20b956e4c3 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 3 Jun 2022 16:05:13 +0200 Subject: ASoC: da732x: Drop no-op remove function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A remove callback that just returns 0 is equivalent to no callback at all as can be seen in i2c_device_remove(). So simplify accordingly. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20220603140513.131142-5-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/da732x.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index f14cddf23f42..3f1cfee10df3 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1546,11 +1546,6 @@ err: return ret; } -static int da732x_i2c_remove(struct i2c_client *client) -{ - return 0; -} - static const struct i2c_device_id da732x_i2c_id[] = { { "da7320", 0}, { } @@ -1562,7 +1557,6 @@ static struct i2c_driver da732x_i2c_driver = { .name = "da7320", }, .probe_new = da732x_i2c_probe, - .remove = da732x_i2c_remove, .id_table = da732x_i2c_id, }; -- cgit From 94e0bc317ad241c022a6bb311b3a28b4d51ea8b6 Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Wed, 25 May 2022 14:16:30 +0100 Subject: ASoC: cs35l41: Move cs35l41 exit hibernate function into shared code CS35L41 HDA Driver will support hibernation using DSP firmware, move the exit hibernate function into shared code so this can be reused. Acked-by: Charles Keepax Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov Link: https://lore.kernel.org/r/20220525131638.5512-10-vitalyr@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/cs35l41.h | 1 + sound/soc/codecs/cs35l41-lib.c | 60 +++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/cs35l41.c | 61 +----------------------------------------- 3 files changed, 62 insertions(+), 60 deletions(-) diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h index 8972fa697622..7759f2e14d96 100644 --- a/include/sound/cs35l41.h +++ b/include/sound/cs35l41.h @@ -881,6 +881,7 @@ void cs35l41_configure_cs_dsp(struct device *dev, struct regmap *reg, struct cs_ int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap, enum cs35l41_cspl_mbox_cmd cmd); int cs35l41_write_fs_errata(struct device *dev, struct regmap *regmap); +int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap); int cs35l41_init_boost(struct device *dev, struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg); bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type); diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c index 6d3070ea9e06..cc5366c8bdd6 100644 --- a/sound/soc/codecs/cs35l41-lib.c +++ b/sound/soc/codecs/cs35l41-lib.c @@ -1321,6 +1321,66 @@ int cs35l41_write_fs_errata(struct device *dev, struct regmap *regmap) } EXPORT_SYMBOL_GPL(cs35l41_write_fs_errata); +static void cs35l41_wait_for_pwrmgt_sts(struct device *dev, struct regmap *regmap) +{ + const int pwrmgt_retries = 10; + unsigned int sts; + int i, ret; + + for (i = 0; i < pwrmgt_retries; i++) { + ret = regmap_read(regmap, CS35L41_PWRMGT_STS, &sts); + if (ret) + dev_err(dev, "Failed to read PWRMGT_STS: %d\n", ret); + else if (!(sts & CS35L41_WR_PEND_STS_MASK)) + return; + + udelay(20); + } + + dev_err(dev, "Timed out reading PWRMGT_STS\n"); +} + +int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap) +{ + const int wake_retries = 20; + const int sleep_retries = 5; + int ret, i, j; + + for (i = 0; i < sleep_retries; i++) { + dev_dbg(dev, "Exit hibernate\n"); + + for (j = 0; j < wake_retries; j++) { + ret = cs35l41_set_cspl_mbox_cmd(dev, regmap, + CSPL_MBOX_CMD_OUT_OF_HIBERNATE); + if (!ret) + break; + + usleep_range(100, 200); + } + + if (j < wake_retries) { + dev_dbg(dev, "Wake success at cycle: %d\n", j); + return 0; + } + + dev_err(dev, "Wake failed, re-enter hibernate: %d\n", ret); + + cs35l41_wait_for_pwrmgt_sts(dev, regmap); + regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0088); + + cs35l41_wait_for_pwrmgt_sts(dev, regmap); + regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0188); + + cs35l41_wait_for_pwrmgt_sts(dev, regmap); + regmap_write(regmap, CS35L41_PWRMGT_CTL, 0x3); + } + + dev_err(dev, "Timed out waking device\n"); + + return -ETIMEDOUT; +} +EXPORT_SYMBOL_GPL(cs35l41_exit_hibernate); + MODULE_DESCRIPTION("CS35L41 library"); MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, "); MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, "); diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index 3e68a07a3c8e..be7d02517739 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -1351,65 +1351,6 @@ static int __maybe_unused cs35l41_runtime_suspend(struct device *dev) return 0; } -static void cs35l41_wait_for_pwrmgt_sts(struct cs35l41_private *cs35l41) -{ - const int pwrmgt_retries = 10; - unsigned int sts; - int i, ret; - - for (i = 0; i < pwrmgt_retries; i++) { - ret = regmap_read(cs35l41->regmap, CS35L41_PWRMGT_STS, &sts); - if (ret) - dev_err(cs35l41->dev, "Failed to read PWRMGT_STS: %d\n", ret); - else if (!(sts & CS35L41_WR_PEND_STS_MASK)) - return; - - udelay(20); - } - - dev_err(cs35l41->dev, "Timed out reading PWRMGT_STS\n"); -} - -static int cs35l41_exit_hibernate(struct cs35l41_private *cs35l41) -{ - const int wake_retries = 20; - const int sleep_retries = 5; - int ret, i, j; - - for (i = 0; i < sleep_retries; i++) { - dev_dbg(cs35l41->dev, "Exit hibernate\n"); - - for (j = 0; j < wake_retries; j++) { - ret = cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, - CSPL_MBOX_CMD_OUT_OF_HIBERNATE); - if (!ret) - break; - - usleep_range(100, 200); - } - - if (j < wake_retries) { - dev_dbg(cs35l41->dev, "Wake success at cycle: %d\n", j); - return 0; - } - - dev_err(cs35l41->dev, "Wake failed, re-enter hibernate: %d\n", ret); - - cs35l41_wait_for_pwrmgt_sts(cs35l41); - regmap_write(cs35l41->regmap, CS35L41_WAKESRC_CTL, 0x0088); - - cs35l41_wait_for_pwrmgt_sts(cs35l41); - regmap_write(cs35l41->regmap, CS35L41_WAKESRC_CTL, 0x0188); - - cs35l41_wait_for_pwrmgt_sts(cs35l41); - regmap_write(cs35l41->regmap, CS35L41_PWRMGT_CTL, 0x3); - } - - dev_err(cs35l41->dev, "Timed out waking device\n"); - - return -ETIMEDOUT; -} - static int __maybe_unused cs35l41_runtime_resume(struct device *dev) { struct cs35l41_private *cs35l41 = dev_get_drvdata(dev); @@ -1422,7 +1363,7 @@ static int __maybe_unused cs35l41_runtime_resume(struct device *dev) regcache_cache_only(cs35l41->regmap, false); - ret = cs35l41_exit_hibernate(cs35l41); + ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap); if (ret) return ret; -- cgit From e341efc308e5374ded6b471f9e1ec01450bcc93e Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Wed, 25 May 2022 14:16:32 +0100 Subject: ASoC: cs35l41: Add common cs35l41 enter hibernate function Since the CS35L41 HDA driver also support hibernation, it makes sense to move code from the ASoC driver to enter hibernation into common code. Since HDA must support laptops which do not support hibernation due to lack of external boost GPIO it is necessary to ensure the function returns an error when an unsupported boost type is in use. Acked-by: Charles Keepax Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov Link: https://lore.kernel.org/r/20220525131638.5512-12-vitalyr@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/cs35l41.h | 2 ++ sound/soc/codecs/cs35l41-lib.c | 19 +++++++++++++++++++ sound/soc/codecs/cs35l41.c | 10 +--------- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h index 7759f2e14d96..a66ef37184fd 100644 --- a/include/sound/cs35l41.h +++ b/include/sound/cs35l41.h @@ -881,6 +881,8 @@ void cs35l41_configure_cs_dsp(struct device *dev, struct regmap *reg, struct cs_ int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap, enum cs35l41_cspl_mbox_cmd cmd); int cs35l41_write_fs_errata(struct device *dev, struct regmap *regmap); +int cs35l41_enter_hibernate(struct device *dev, struct regmap *regmap, + enum cs35l41_boost_type b_type); int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap); int cs35l41_init_boost(struct device *dev, struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg); diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c index cc5366c8bdd6..10b754481ca2 100644 --- a/sound/soc/codecs/cs35l41-lib.c +++ b/sound/soc/codecs/cs35l41-lib.c @@ -1321,6 +1321,25 @@ int cs35l41_write_fs_errata(struct device *dev, struct regmap *regmap) } EXPORT_SYMBOL_GPL(cs35l41_write_fs_errata); +int cs35l41_enter_hibernate(struct device *dev, struct regmap *regmap, + enum cs35l41_boost_type b_type) +{ + if (!cs35l41_safe_reset(regmap, b_type)) { + dev_dbg(dev, "System does not support Suspend\n"); + return -EINVAL; + } + + dev_dbg(dev, "Enter hibernate\n"); + regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0088); + regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0188); + + // Don't wait for ACK since bus activity would wake the device + regmap_write(regmap, CS35L41_DSP_VIRT1_MBOX_1, CSPL_MBOX_CMD_HIBERNATE); + + return 0; +} +EXPORT_SYMBOL_GPL(cs35l41_enter_hibernate); + static void cs35l41_wait_for_pwrmgt_sts(struct device *dev, struct regmap *regmap) { const int pwrmgt_retries = 10; diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index be7d02517739..a115ea35b92d 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -1335,15 +1335,7 @@ static int __maybe_unused cs35l41_runtime_suspend(struct device *dev) if (!cs35l41->dsp.preloaded || !cs35l41->dsp.cs_dsp.running) return 0; - dev_dbg(cs35l41->dev, "Enter hibernate\n"); - - cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type); - regmap_write(cs35l41->regmap, CS35L41_WAKESRC_CTL, 0x0088); - regmap_write(cs35l41->regmap, CS35L41_WAKESRC_CTL, 0x0188); - - // Don't wait for ACK since bus activity would wake the device - regmap_write(cs35l41->regmap, CS35L41_DSP_VIRT1_MBOX_1, - CSPL_MBOX_CMD_HIBERNATE); + cs35l41_enter_hibernate(dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type); regcache_cache_only(cs35l41->regmap, true); regcache_mark_dirty(cs35l41->regmap); -- cgit From 97076475e2fdf471348b9ce73215cdbceeb4390f Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Wed, 25 May 2022 14:16:31 +0100 Subject: ASoC: cs35l41: Do not print error when waking from hibernation When waking from hibernation, it is possible for the function which sends the wake command to fail initially, but after a retry it will succeed. There is no need to print an error if the initial attempts fail. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20220525131638.5512-11-vitalyr@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l41-lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c index 10b754481ca2..0c7d1c791279 100644 --- a/sound/soc/codecs/cs35l41-lib.c +++ b/sound/soc/codecs/cs35l41-lib.c @@ -1302,7 +1302,8 @@ int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap, return 0; } - dev_err(dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts); + if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE) + dev_err(dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts); return -ENOMSG; } -- cgit From 0439eb4d94e0fc17c6dd3829fabd88c11773381d Mon Sep 17 00:00:00 2001 From: V sujith kumar Reddy Date: Tue, 31 May 2022 17:38:11 +0530 Subject: ASoC: amd: acp: Add support for nau8825 and max98360 card We have new platform with nau8825 as a primary codec and max98360 as an amp codec. Add machine struct to register sof audio based sound card on such Chrome machine. Signed-off-by: V sujith kumar Reddy Reviewed-by: Akihiko Odaki Link: https://lore.kernel.org/r/20220531120813.47116-2-Vsujithkumar.Reddy@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp-config.c | 21 +++++ sound/soc/amd/acp/Kconfig | 1 + sound/soc/amd/acp/acp-mach-common.c | 166 ++++++++++++++++++++++++++++++++++-- sound/soc/amd/acp/acp-mach.h | 3 + sound/soc/amd/acp/acp-sof-mach.c | 15 ++++ sound/soc/amd/mach-config.h | 1 + 6 files changed, 201 insertions(+), 6 deletions(-) diff --git a/sound/soc/amd/acp-config.c b/sound/soc/amd/acp-config.c index 5cbc82eca4c9..3b9f851bf50d 100644 --- a/sound/soc/amd/acp-config.c +++ b/sound/soc/amd/acp-config.c @@ -130,4 +130,25 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[] = { }; EXPORT_SYMBOL(snd_soc_acpi_amd_sof_machines); +struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[] = { + { + .id = "AMDI1019", + .drv_name = "rmb-dsp", + .pdata = &acp_quirk_data, + .fw_filename = "sof-rmb.ri", + .sof_tplg_filename = "sof-acp-rmb.tplg", + }, + { + .id = "10508825", + .drv_name = "nau8825-max", + .pdata = &acp_quirk_data, + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_max, + .fw_filename = "sof-rmb.ri", + .sof_tplg_filename = "sof-rmb-nau8825-max98360.tplg", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_rmb_sof_machines); + MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig index 9dae2719084c..7e56d2644105 100644 --- a/sound/soc/amd/acp/Kconfig +++ b/sound/soc/amd/acp/Kconfig @@ -49,6 +49,7 @@ config SND_SOC_AMD_MACH_COMMON select SND_SOC_RT1019 select SND_SOC_MAX98357A select SND_SOC_RT5682S + select SND_SOC_NAU8825 help This option enables common Machine driver module for ACP. diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index 6ae454bf60af..a03b396d96bb 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -24,6 +24,7 @@ #include "../../codecs/rt5682.h" #include "../../codecs/rt1019.h" #include "../../codecs/rt5682s.h" +#include "../../codecs/nau8825.h" #include "acp-mach.h" #define PCO_PLAT_CLK 48000000 @@ -175,7 +176,8 @@ static void acp_card_shutdown(struct snd_pcm_substream *substream) struct snd_soc_card *card = rtd->card; struct acp_card_drvdata *drvdata = card->drvdata; - clk_disable_unprepare(drvdata->wclk); + if (!drvdata->soc_mclk) + clk_disable_unprepare(drvdata->wclk); } static const struct snd_soc_ops acp_card_rt5682_ops = { @@ -363,7 +365,7 @@ static int acp_card_amp_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp_card_drvdata *drvdata = card->drvdata; - int ret; + int ret = 0; runtime->hw.channels_max = DUAL_CHANNEL; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, @@ -371,10 +373,13 @@ static int acp_card_amp_startup(struct snd_pcm_substream *substream) snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); - ret = acp_clk_enable(drvdata); - if (ret < 0) - dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret); - + if (!drvdata->soc_mclk) { + ret = acp_clk_enable(drvdata); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret); + return ret; + } + } return ret; } @@ -409,6 +414,104 @@ static const struct snd_soc_ops acp_card_maxim_ops = { .shutdown = acp_card_shutdown, }; +/* Declare nau8825 codec components */ +SND_SOC_DAILINK_DEF(nau8825, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", "nau8825-hifi"))); + +static const struct snd_soc_dapm_route nau8825_map[] = { + { "Headphone Jack", NULL, "HPOL" }, + { "Headphone Jack", NULL, "HPOR" }, +}; + +static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct acp_card_drvdata *drvdata = card->drvdata; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; + unsigned int fmt; + int ret; + + dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); + + if (drvdata->hs_codec_id != NAU8825) + return -EINVAL; + + if (drvdata->soc_mclk) + fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + else + fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); + return ret; + } + ret = snd_soc_card_jack_new(card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_LINEOUT | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &pco_jack); + if (ret) { + dev_err(card->dev, "HP jack creation failed %d\n", ret); + return ret; + } + + snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + ret = snd_soc_component_set_jack(component, &pco_jack, NULL); + if (ret) { + dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); + return ret; + } + + return snd_soc_dapm_add_routes(&rtd->card->dapm, nau8825_map, ARRAY_SIZE(nau8825_map)); +} + +static int acp_nau8825_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + int ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_FS, + (48000 * 256), SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); + + ret = snd_soc_dai_set_pll(codec_dai, 0, 0, params_rate(params), + params_rate(params) * 256); + if (ret < 0) { + dev_err(rtd->dev, "can't set FLL: %d\n", ret); + return ret; + } + + return ret; +} + +static int acp_nau8825_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + runtime->hw.channels_max = 2; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + + runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); + return 0; +} + +static const struct snd_soc_ops acp_card_nau8825_ops = { + .startup = acp_nau8825_startup, + .hw_params = acp_nau8825_hw_params, +}; + /* Declare DMIC codec components */ SND_SOC_DAILINK_DEF(dmic_codec, DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); @@ -437,6 +540,8 @@ SND_SOC_DAILINK_DEF(i2s_sp, DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp"))); SND_SOC_DAILINK_DEF(sof_sp, DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp"))); +SND_SOC_DAILINK_DEF(sof_hs, + DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs"))); SND_SOC_DAILINK_DEF(sof_dmic, DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic"))); SND_SOC_DAILINK_DEF(pdm_dmic, @@ -491,6 +596,31 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) i++; } + if (drv_data->hs_cpu_id == I2S_HS) { + links[i].name = "acp-headset-codec"; + links[i].id = HEADSET_BE_ID; + links[i].cpus = sof_hs; + links[i].num_cpus = ARRAY_SIZE(sof_hs); + links[i].platforms = sof_component; + links[i].num_platforms = ARRAY_SIZE(sof_component); + links[i].dpcm_playback = 1; + links[i].dpcm_capture = 1; + links[i].nonatomic = true; + links[i].no_pcm = 1; + if (!drv_data->hs_codec_id) { + /* Use dummy codec if codec id not specified */ + links[i].codecs = dummy_codec; + links[i].num_codecs = ARRAY_SIZE(dummy_codec); + } + if (drv_data->hs_codec_id == NAU8825) { + links[i].codecs = nau8825; + links[i].num_codecs = ARRAY_SIZE(nau8825); + links[i].init = acp_card_nau8825_init; + links[i].ops = &acp_card_nau8825_ops; + } + i++; + } + if (drv_data->amp_cpu_id == I2S_SP) { links[i].name = "acp-amp-codec"; links[i].id = AMP_BE_ID; @@ -523,6 +653,30 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) i++; } + if (drv_data->amp_cpu_id == I2S_HS) { + links[i].name = "acp-amp-codec"; + links[i].id = AMP_BE_ID; + links[i].cpus = sof_hs; + links[i].num_cpus = ARRAY_SIZE(sof_hs); + links[i].platforms = sof_component; + links[i].num_platforms = ARRAY_SIZE(sof_component); + links[i].dpcm_playback = 1; + links[i].nonatomic = true; + links[i].no_pcm = 1; + if (!drv_data->amp_codec_id) { + /* Use dummy codec if codec id not specified */ + links[i].codecs = dummy_codec; + links[i].num_codecs = ARRAY_SIZE(dummy_codec); + } + if (drv_data->amp_codec_id == MAX98360A) { + links[i].codecs = max98360a; + links[i].num_codecs = ARRAY_SIZE(max98360a); + links[i].ops = &acp_card_maxim_ops; + links[i].init = acp_card_maxim_init; + } + i++; + } + if (drv_data->dmic_cpu_id == DMIC) { links[i].name = "acp-dmic-codec"; links[i].id = DMIC_BE_ID; diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h index 5dc47cfbff10..c95ee1c52eb1 100644 --- a/sound/soc/amd/acp/acp-mach.h +++ b/sound/soc/amd/acp/acp-mach.h @@ -26,6 +26,7 @@ enum be_id { enum cpu_endpoints { NONE = 0, + I2S_HS, I2S_SP, I2S_BT, DMIC, @@ -37,6 +38,7 @@ enum codec_endpoints { RT1019, MAX98360A, RT5682S, + NAU8825, }; struct acp_card_drvdata { @@ -49,6 +51,7 @@ struct acp_card_drvdata { unsigned int dai_fmt; struct clk *wclk; struct clk *bclk; + bool soc_mclk; }; int acp_sofdsp_dai_links_create(struct snd_soc_card *card); diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c index d1531cdab110..adbae809f2aa 100644 --- a/sound/soc/amd/acp/acp-sof-mach.c +++ b/sound/soc/amd/acp/acp-sof-mach.c @@ -56,6 +56,16 @@ static struct acp_card_drvdata sof_rt5682s_max_data = { .dmic_codec_id = DMIC, }; +static struct acp_card_drvdata sof_nau8825_data = { + .hs_cpu_id = I2S_HS, + .amp_cpu_id = I2S_HS, + .dmic_cpu_id = DMIC, + .hs_codec_id = NAU8825, + .amp_codec_id = MAX98360A, + .dmic_codec_id = DMIC, + .soc_mclk = true, +}; + static const struct snd_kcontrol_new acp_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headset Mic"), @@ -124,6 +134,10 @@ static const struct platform_device_id board_ids[] = { .name = "rt5682s-rt1019", .driver_data = (kernel_ulong_t)&sof_rt5682s_rt1019_data }, + { + .name = "nau8825-max", + .driver_data = (kernel_ulong_t)&sof_nau8825_data + }, { } }; static struct platform_driver acp_asoc_audio = { @@ -143,4 +157,5 @@ MODULE_ALIAS("platform:rt5682-rt1019"); MODULE_ALIAS("platform:rt5682-max"); MODULE_ALIAS("platform:rt5682s-max"); MODULE_ALIAS("platform:rt5682s-rt1019"); +MODULE_ALIAS("platform:nau8825-max"); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/amd/mach-config.h b/sound/soc/amd/mach-config.h index 0a54567a2841..7b4c625da40d 100644 --- a/sound/soc/amd/mach-config.h +++ b/sound/soc/amd/mach-config.h @@ -19,6 +19,7 @@ #define ACP_PCI_DEV_ID 0x15E2 extern struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[]; struct config_entry { u32 flags; -- cgit From 4dc6737cfe882765d914fcb88b5eaa14551ffddd Mon Sep 17 00:00:00 2001 From: V sujith kumar Reddy Date: Tue, 31 May 2022 17:38:12 +0530 Subject: ASoC: amd: acp: Add support for rt5682s and rt1019 card with hs instance We have new platform with rt5682s as a primary codec and rt1019 as an amp codec. Add machine struct to register sof audio based sound card on such Chrome machine. Here we are configuring as a soc mclk master and codec slave. Signed-off-by: V sujith kumar Reddy Link: https://lore.kernel.org/r/20220531120813.47116-3-Vsujithkumar.Reddy@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp-config.c | 9 +++++ sound/soc/amd/acp/acp-mach-common.c | 67 +++++++++++++++++++++++++++++++------ sound/soc/amd/acp/acp-sof-mach.c | 15 +++++++++ 3 files changed, 81 insertions(+), 10 deletions(-) diff --git a/sound/soc/amd/acp-config.c b/sound/soc/amd/acp-config.c index 3b9f851bf50d..0932473b6394 100644 --- a/sound/soc/amd/acp-config.c +++ b/sound/soc/amd/acp-config.c @@ -147,6 +147,15 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[] = { .fw_filename = "sof-rmb.ri", .sof_tplg_filename = "sof-rmb-nau8825-max98360.tplg", }, + { + .id = "RTL5682", + .drv_name = "rt5682s-hs-rt1019", + .pdata = &acp_quirk_data, + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &_rt1019, + .fw_filename = "sof-rmb.ri", + .sof_tplg_filename = "sof-rmb-rt5682s-rt1019.tplg", + }, {}, }; EXPORT_SYMBOL(snd_soc_acpi_amd_rmb_sof_machines); diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index a03b396d96bb..7530cab24bc8 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -149,9 +149,14 @@ static int acp_card_hs_startup(struct snd_pcm_substream *substream) struct acp_card_drvdata *drvdata = card->drvdata; struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; + unsigned int fmt; - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBP_CFP); + if (drvdata->soc_mclk) + fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + else + fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + + ret = snd_soc_dai_set_fmt(codec_dai, fmt); if (ret < 0) { dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); return ret; @@ -162,10 +167,13 @@ static int acp_card_hs_startup(struct snd_pcm_substream *substream) &constraints_channels); snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); - - ret = acp_clk_enable(drvdata); - if (ret < 0) - dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret); + if (!drvdata->soc_mclk) { + ret = acp_clk_enable(drvdata); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret); + return ret; + } + } return ret; } @@ -201,6 +209,7 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd) struct acp_card_drvdata *drvdata = card->drvdata; struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_component *component = codec_dai->component; + unsigned int fmt; int ret; dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); @@ -208,8 +217,12 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd) if (drvdata->hs_codec_id != RT5682S) return -EINVAL; - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF - | SND_SOC_DAIFMT_CBP_CFP); + if (drvdata->soc_mclk) + fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC; + else + fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP; + + ret = snd_soc_dai_set_fmt(codec_dai, fmt); if (ret < 0) { dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); return ret; @@ -236,8 +249,10 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd) return ret; } - drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk"); - drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk"); + if (!drvdata->soc_mclk) { + drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk"); + drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk"); + } ret = snd_soc_card_jack_new(card, "Headset Jack", SND_JACK_HEADSET | SND_JACK_LINEOUT | @@ -298,6 +313,9 @@ static const struct snd_soc_ops acp_card_dmic_ops = { SND_SOC_DAILINK_DEF(rt1019, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:00", "rt1019-aif"), COMP_CODEC("i2c-10EC1019:01", "rt1019-aif"))); +SND_SOC_DAILINK_DEF(rt1019_1, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:02", "rt1019-aif"), + COMP_CODEC("i2c-10EC1019:01", "rt1019-aif"))); static const struct snd_soc_dapm_route rt1019_map_lr[] = { { "Left Spk", NULL, "Left SPO" }, @@ -315,6 +333,17 @@ static struct snd_soc_codec_conf rt1019_conf[] = { }, }; +static struct snd_soc_codec_conf rt1019_1_conf[] = { + { + .dlc = COMP_CODEC_CONF("i2c-10EC1019:02"), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"), + .name_prefix = "Right", + }, +}; + static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; @@ -618,6 +647,12 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) links[i].init = acp_card_nau8825_init; links[i].ops = &acp_card_nau8825_ops; } + if (drv_data->hs_codec_id == RT5682S) { + links[i].codecs = rt5682s; + links[i].num_codecs = ARRAY_SIZE(rt5682s); + links[i].init = acp_card_rt5682s_init; + links[i].ops = &acp_card_rt5682s_ops; + } i++; } @@ -674,6 +709,18 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card) links[i].ops = &acp_card_maxim_ops; links[i].init = acp_card_maxim_init; } + if (drv_data->amp_codec_id == RT1019) { + links[i].codecs = rt1019; + links[i].num_codecs = ARRAY_SIZE(rt1019); + links[i].ops = &acp_card_rt1019_ops; + links[i].init = acp_card_rt1019_init; + card->codec_conf = rt1019_conf; + card->num_configs = ARRAY_SIZE(rt1019_conf); + links[i].codecs = rt1019_1; + links[i].num_codecs = ARRAY_SIZE(rt1019_1); + card->codec_conf = rt1019_1_conf; + card->num_configs = ARRAY_SIZE(rt1019_1_conf); + } i++; } diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c index adbae809f2aa..f19f064a7527 100644 --- a/sound/soc/amd/acp/acp-sof-mach.c +++ b/sound/soc/amd/acp/acp-sof-mach.c @@ -66,6 +66,16 @@ static struct acp_card_drvdata sof_nau8825_data = { .soc_mclk = true, }; +static struct acp_card_drvdata sof_rt5682s_hs_rt1019_data = { + .hs_cpu_id = I2S_HS, + .amp_cpu_id = I2S_HS, + .dmic_cpu_id = DMIC, + .hs_codec_id = RT5682S, + .amp_codec_id = RT1019, + .dmic_codec_id = DMIC, + .soc_mclk = true, +}; + static const struct snd_kcontrol_new acp_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headset Mic"), @@ -138,6 +148,10 @@ static const struct platform_device_id board_ids[] = { .name = "nau8825-max", .driver_data = (kernel_ulong_t)&sof_nau8825_data }, + { + .name = "rt5682s-hs-rt1019", + .driver_data = (kernel_ulong_t)&sof_rt5682s_hs_rt1019_data + }, { } }; static struct platform_driver acp_asoc_audio = { @@ -158,4 +172,5 @@ MODULE_ALIAS("platform:rt5682-max"); MODULE_ALIAS("platform:rt5682s-max"); MODULE_ALIAS("platform:rt5682s-rt1019"); MODULE_ALIAS("platform:nau8825-max"); +MODULE_ALIAS("platform:rt5682s-hs-rt1019"); MODULE_LICENSE("GPL v2"); -- cgit From 8dc51d009fad7aba0575e0eb4b684d25c0f01f37 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:05:29 +0200 Subject: ASoC: ssm2518: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the ssm2518 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602130531.3552275-2-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/ssm2518.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index 83acbdbb8e0d..012f209e76e9 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -409,8 +409,8 @@ static int ssm2518_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) bool invert_fclk; int ret; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; -- cgit From 0160e8835fab4d4a15abefe7509d0397890c0ffd Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:05:30 +0200 Subject: ASoC: ssm2602: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the ssm2602 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602130531.3552275-3-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/ssm2602.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 7964e922b07f..1821854ca0f3 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -411,11 +411,11 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int iface = 0; /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: iface |= 0x0040; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; -- cgit From 627a18149250e13409079ffb6936e472c3766f44 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:05:31 +0200 Subject: ASoC: ssm4567: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the ssm4567 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602130531.3552275-4-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/ssm4567.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c index 08ced09ef001..b47321c597d0 100644 --- a/sound/soc/codecs/ssm4567.c +++ b/sound/soc/codecs/ssm4567.c @@ -278,8 +278,8 @@ static int ssm4567_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) unsigned int ctrl1 = 0; bool invert_fclk; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; -- cgit From 0511e2ac4e848ceac14b3ac4b476f0e26b48ddb2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:04 -0500 Subject: ASoC: cs35l45: typo in argument definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck warning: sound/soc/codecs/cs35l45-tables.c:36:49: style:inconclusive: Function 'cs35l45_apply_patch' argument 1 names different: declaration 'cs43l45' definition 'cs35l45'. [funcArgNamesDifferent] Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l45.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h index 4e266d19cd1c..8f98cbbf6209 100644 --- a/sound/soc/codecs/cs35l45.h +++ b/sound/soc/codecs/cs35l45.h @@ -209,7 +209,7 @@ struct cs35l45_private { extern const struct dev_pm_ops cs35l45_pm_ops; extern const struct regmap_config cs35l45_i2c_regmap; extern const struct regmap_config cs35l45_spi_regmap; -int cs35l45_apply_patch(struct cs35l45_private *cs43l45); +int cs35l45_apply_patch(struct cs35l45_private *cs35l45); unsigned int cs35l45_get_clk_freq_id(unsigned int freq); int cs35l45_probe(struct cs35l45_private *cs35l45); int cs35l45_remove(struct cs35l45_private *cs35l45); -- cgit From 94f8f2068ed0e3a5e367029f64ed76e6e65d5eb3 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:05 -0500 Subject: ASoC: cs42l42: remove redundant test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck warning: sound/soc/codecs/cs42l42.c:1704:28: style: The statement 'if (cs42l42->plug_state!=CS42L42_TS_TRANS) cs42l42->plug_state=CS42L42_TS_TRANS' is logically equivalent to 'cs42l42->plug_state=CS42L42_TS_TRANS'. [duplicateConditionalAssign] if (cs42l42->plug_state != CS42L42_TS_TRANS) ^ sound/soc/codecs/cs42l42.c:1705:25: note: Assignment 'cs42l42->plug_state=CS42L42_TS_TRANS' cs42l42->plug_state = CS42L42_TS_TRANS; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 4fade2388797..6ca74c0d46ea 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -1701,8 +1701,7 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data) break; default: - if (cs42l42->plug_state != CS42L42_TS_TRANS) - cs42l42->plug_state = CS42L42_TS_TRANS; + cs42l42->plug_state = CS42L42_TS_TRANS; } } -- cgit From cac24a360a6b948ffb75c3d7ccc819064300454c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:06 -0500 Subject: ASoC: wcd-mbhc-v2: remove useless initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck warning: sound/soc/codecs/wcd-mbhc-v2.c:1309:17: style: Variable 'clamp_state' is assigned a value that is never used. [unreadVariable] u8 clamp_state = 0; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd-mbhc-v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index c53c2ef33e1a..31009283e7d4 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -1306,7 +1306,7 @@ exit: static irqreturn_t wcd_mbhc_adc_hs_ins_irq(int irq, void *data) { struct wcd_mbhc *mbhc = data; - u8 clamp_state = 0; + u8 clamp_state; u8 clamp_retry = WCD_MBHC_FAKE_INS_RETRY; /* -- cgit From 0016361dfcc93a70850c6909fb76f15305dda5ae Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:07 -0500 Subject: ASoC: wcd9335: remove redundant tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck warning: sound/soc/codecs/wcd9335.c:1810:23: style: Condition 'tx_port>=4' is always true [knownConditionTrueFalse] } else if ((tx_port >= 4) && (tx_port < 8)) { ^ sound/soc/codecs/wcd9335.c:1806:15: note: Assuming that condition 'tx_port<4' is not redundant if (tx_port < 4) { ^ sound/soc/codecs/wcd9335.c:1810:23: note: Condition 'tx_port>=4' is always true } else if ((tx_port >= 4) && (tx_port < 8)) { ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 617a36a89dfe..e1b693048084 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -1807,11 +1807,11 @@ static int wcd9335_set_decimator_rate(struct snd_soc_dai *dai, tx_port_reg = WCD9335_CDC_IF_ROUTER_TX_MUX_CFG0; shift = (tx_port << 1); shift_val = 0x03; - } else if ((tx_port >= 4) && (tx_port < 8)) { + } else if (tx_port < 8) { tx_port_reg = WCD9335_CDC_IF_ROUTER_TX_MUX_CFG1; shift = ((tx_port - 4) << 1); shift_val = 0x03; - } else if ((tx_port >= 8) && (tx_port < 11)) { + } else if (tx_port < 11) { tx_port_reg = WCD9335_CDC_IF_ROUTER_TX_MUX_CFG2; shift = ((tx_port - 8) << 1); shift_val = 0x03; -- cgit From fb6ed937aaa0703bcdacfe013897d583a6eba365 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:08 -0500 Subject: ASoC: Intel: atom: sst: remove useless initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck reports an invalid null pointer dereference but there's indeed no need to initialize a loop variable. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst/sst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/atom/sst/sst.c b/sound/soc/intel/atom/sst/sst.c index 3a42d68c0247..160b50f479fb 100644 --- a/sound/soc/intel/atom/sst/sst.c +++ b/sound/soc/intel/atom/sst/sst.c @@ -114,7 +114,7 @@ static irqreturn_t intel_sst_interrupt_mrfld(int irq, void *context) static irqreturn_t intel_sst_irq_thread_mrfld(int irq, void *context) { struct intel_sst_drv *drv = (struct intel_sst_drv *) context; - struct ipc_post *__msg, *msg = NULL; + struct ipc_post *__msg, *msg; unsigned long irq_flags; spin_lock_irqsave(&drv->rx_msg_lock, irq_flags); -- cgit From d8af541139fa135a250c5ae743bfec3b49e97c3a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:09 -0500 Subject: ASoC: Intel: atom: sst_ipc: remove redundant test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck warning: sound/soc/intel/atom/sst/sst_ipc.c:344:30: style: Condition 'drv_id' is always true [knownConditionTrueFalse] if (msg_high.part.result && drv_id && !msg_high.part.large) { ^ sound/soc/intel/atom/sst/sst_ipc.c:337:13: note: Assuming that condition 'drv_id==0' is not redundant if (drv_id == SST_ASYNC_DRV_ID) { ^ sound/soc/intel/atom/sst/sst_ipc.c:344:30: note: Condition 'drv_id' is always true if (msg_high.part.result && drv_id && !msg_high.part.large) { ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst/sst_ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/atom/sst/sst_ipc.c b/sound/soc/intel/atom/sst/sst_ipc.c index 4e8382097e61..78ea67c7a128 100644 --- a/sound/soc/intel/atom/sst/sst_ipc.c +++ b/sound/soc/intel/atom/sst/sst_ipc.c @@ -341,7 +341,7 @@ void sst_process_reply_mrfld(struct intel_sst_drv *sst_drv_ctx, } /* FW sent short error response for an IPC */ - if (msg_high.part.result && drv_id && !msg_high.part.large) { + if (msg_high.part.result && !msg_high.part.large) { /* 32-bit FW error code in msg_low */ dev_err(sst_drv_ctx->dev, "FW sent error response 0x%x", msg_low); sst_wake_up_block(sst_drv_ctx, msg_high.part.result, -- cgit From a140785b701d286374ea1b26762f333e4f5e9ee3 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:10 -0500 Subject: ASoC: Intel: atom: sst_ipc: remove useless initializations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck throws invalid NULL dereference warnings but there's indeed no need to initialize a loop variable or initialize to NULL before allocating memory. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst/sst_ipc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/atom/sst/sst_ipc.c b/sound/soc/intel/atom/sst/sst_ipc.c index 78ea67c7a128..4e039c7173d8 100644 --- a/sound/soc/intel/atom/sst/sst_ipc.c +++ b/sound/soc/intel/atom/sst/sst_ipc.c @@ -28,7 +28,7 @@ struct sst_block *sst_create_block(struct intel_sst_drv *ctx, u32 msg_id, u32 drv_id) { - struct sst_block *msg = NULL; + struct sst_block *msg; dev_dbg(ctx->dev, "Enter\n"); msg = kzalloc(sizeof(*msg), GFP_KERNEL); @@ -63,7 +63,7 @@ struct sst_block *sst_create_block(struct intel_sst_drv *ctx, int sst_wake_up_block(struct intel_sst_drv *ctx, int result, u32 drv_id, u32 ipc, void *data, u32 size) { - struct sst_block *block = NULL; + struct sst_block *block; dev_dbg(ctx->dev, "Enter\n"); @@ -91,7 +91,7 @@ int sst_wake_up_block(struct intel_sst_drv *ctx, int result, int sst_free_block(struct intel_sst_drv *ctx, struct sst_block *freed) { - struct sst_block *block = NULL, *__block; + struct sst_block *block, *__block; dev_dbg(ctx->dev, "Enter\n"); spin_lock_bh(&ctx->block_lock); -- cgit From f6cd55a19f3f46e3d36b1121f844956128c60b6a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:11 -0500 Subject: ASoC: Intel: atom: controls: remove useless initializations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck complains about invalid NULL dereferences but there's indeed no need to initialize loop variables or before allocating memory. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-atom-controls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index 335c32732994..34d63252debf 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c @@ -1328,7 +1328,7 @@ int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute) { struct sst_data *drv = snd_soc_dai_get_drvdata(dai); struct snd_soc_dapm_widget *w; - struct snd_soc_dapm_path *p = NULL; + struct snd_soc_dapm_path *p; dev_dbg(dai->dev, "enter, dai-name=%s dir=%d\n", dai->name, stream); @@ -1392,7 +1392,7 @@ int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute) static int sst_fill_module_list(struct snd_kcontrol *kctl, struct snd_soc_dapm_widget *w, int type) { - struct sst_module *module = NULL; + struct sst_module *module; struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); struct sst_ids *ids = w->priv; int ret = 0; -- cgit From 9972773c26125242b467f0062c1fee874c87ae68 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:12 -0500 Subject: ASoC: Intel: boards: reset acpi_chan_package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck complains about possible tests of uninitialized 'aif_value' members. This isn't really possible but static analysis cannot know what ACPICA does, so make sure the acpi_chan_package structure is reset prior to use to make the warning go away. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 2 +- sound/soc/intel/boards/bytcr_rt5651.c | 2 +- sound/soc/intel/boards/cht_bsw_rt5645.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index ed9fa1728722..2371927fe836 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -1636,7 +1636,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) * with the codec driver/pdata are non-existent */ - struct acpi_chan_package chan_package; + struct acpi_chan_package chan_package = { 0 }; /* format specified: 2 64-bit integers */ struct acpi_buffer format = {sizeof("NN"), "NN"}; diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index d467fcaa48ea..03a52b1069a9 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -952,7 +952,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) * with the codec driver/pdata are non-existent */ - struct acpi_chan_package chan_package; + struct acpi_chan_package chan_package = { 0 }; /* format specified: 2 64-bit integers */ struct acpi_buffer format = {sizeof("NN"), "NN"}; diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index 45c301ea5e00..453281326c83 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -603,7 +603,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) * with the codec driver/pdata are non-existent */ - struct acpi_chan_package chan_package; + struct acpi_chan_package chan_package = { 0 }; /* format specified: 2 64-bit integers */ struct acpi_buffer format = {sizeof("NN"), "NN"}; -- cgit From f057852fd351741d1efaadc48aa59ea49c79a087 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:13 -0500 Subject: ASoC: Intel: sof_pcm512x: remove unnecessary init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck complains about an invalid NULL dereference but indeed there is no need to initialize a loop variable. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_pcm512x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c index 6815204e58d5..d4c67d5340a9 100644 --- a/sound/soc/intel/boards/sof_pcm512x.c +++ b/sound/soc/intel/boards/sof_pcm512x.c @@ -419,7 +419,7 @@ static int sof_audio_probe(struct platform_device *pdev) static int sof_pcm512x_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct snd_soc_component *component = NULL; + struct snd_soc_component *component; for_each_card_components(card, component) { if (!strcmp(component->name, pcm512x_component[0].name)) { -- cgit From 9e9fb5d3f387788d50f5eae4c01ff60429691e71 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:14 -0500 Subject: ASoC: mediatek: mt8195: simplify error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck warnings: sound/soc/mediatek/mt8195/mt8195-afe-clk.c:311:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/mediatek/mt8195/mt8195-afe-clk.c:297:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/mediatek/mt8195/mt8195-afe-clk.c:311:9: note: Returning identical expression 'ret' return ret; ^ sound/soc/mediatek/mt8195/mt8195-afe-clk.c:341:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/mediatek/mt8195/mt8195-afe-clk.c:338:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/mediatek/mt8195/mt8195-afe-clk.c:341:9: note: Returning identical expression 'ret' return ret; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-afe-clk.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c index efd5cc364a35..2ee3872c83c3 100644 --- a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c @@ -284,7 +284,7 @@ static int mt8195_afe_enable_apll_tuner(struct mtk_base_afe *afe, { struct mt8195_afe_tuner_cfg *cfg = mt8195_afe_found_apll_tuner(id); unsigned long flags; - int ret = 0; + int ret; if (!cfg) return -EINVAL; @@ -308,7 +308,7 @@ static int mt8195_afe_enable_apll_tuner(struct mtk_base_afe *afe, spin_unlock_irqrestore(&cfg->ctrl_lock, flags); - return ret; + return 0; } static int mt8195_afe_disable_apll_tuner(struct mtk_base_afe *afe, @@ -316,7 +316,7 @@ static int mt8195_afe_disable_apll_tuner(struct mtk_base_afe *afe, { struct mt8195_afe_tuner_cfg *cfg = mt8195_afe_found_apll_tuner(id); unsigned long flags; - int ret = 0; + int ret; if (!cfg) return -EINVAL; @@ -338,7 +338,7 @@ static int mt8195_afe_disable_apll_tuner(struct mtk_base_afe *afe, if (ret) return ret; - return ret; + return 0; } int mt8195_afe_get_mclk_source_clk_id(int sel) -- cgit From 015d9ab7805fb1b3766d1dc487ed34dbc03bd4da Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:15 -0500 Subject: ASoC: qcom: q6dsp: q6adm: remove useless initializations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck complains about invalid NULL dereferences but there's indeed no need to initialize loop variables. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6adm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c index 72c5719f1d25..22b408c3794e 100644 --- a/sound/soc/qcom/qdsp6/q6adm.c +++ b/sound/soc/qcom/qdsp6/q6adm.c @@ -90,7 +90,7 @@ struct q6adm_session_map_node_v5 { static struct q6copp *q6adm_find_copp(struct q6adm *adm, int port_idx, int copp_idx) { - struct q6copp *c = NULL; + struct q6copp *c; struct q6copp *ret = NULL; unsigned long flags; @@ -299,7 +299,7 @@ static struct q6copp *q6adm_find_matching_copp(struct q6adm *adm, int channel_mode, int bit_width, int app_type) { - struct q6copp *c = NULL; + struct q6copp *c; struct q6copp *ret = NULL; unsigned long flags; -- cgit From 7518be0cc120d7617a8985787196cd5776b93688 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:16 -0500 Subject: ASoC: qcom: q6dsp: remove spurious space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck warning: sound/soc/qcom/qdsp6/q6adm.c:183:14: warning:inconclusive: Found suspicious oper ator '*' [constStatement] } __packed * open = data->payload; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6adm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/qdsp6/q6adm.c b/sound/soc/qcom/qdsp6/q6adm.c index 22b408c3794e..01f383888b62 100644 --- a/sound/soc/qcom/qdsp6/q6adm.c +++ b/sound/soc/qcom/qdsp6/q6adm.c @@ -180,7 +180,7 @@ static int q6adm_callback(struct apr_device *adev, struct apr_resp_pkt *data) u32 status; u16 copp_id; u16 reserved; - } __packed * open = data->payload; + } __packed *open = data->payload; copp = q6adm_find_copp(adm, port_idx, copp_idx); if (!copp) -- cgit From 59a6cc5c5d64ca20461fec46e450e0639b1e6410 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:17 -0500 Subject: ASoC: rockchip: simplify error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck warning: sound/soc/rockchip/rk3288_hdmi_analog.c:256:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/rockchip/rk3288_hdmi_analog.c:252:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/rockchip/rk3288_hdmi_analog.c:256:9: note: Returning identical expression 'ret' return ret; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/rockchip/rk3288_hdmi_analog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/rockchip/rk3288_hdmi_analog.c b/sound/soc/rockchip/rk3288_hdmi_analog.c index bcdeddeba80c..0c6bd9a019db 100644 --- a/sound/soc/rockchip/rk3288_hdmi_analog.c +++ b/sound/soc/rockchip/rk3288_hdmi_analog.c @@ -169,7 +169,7 @@ static struct snd_soc_card snd_soc_card_rk = { static int snd_rk_mc_probe(struct platform_device *pdev) { - int ret = 0; + int ret; struct snd_soc_card *card = &snd_soc_card_rk; struct device_node *np = pdev->dev.of_node; struct rk_drvdata *machine; @@ -253,7 +253,7 @@ static int snd_rk_mc_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, ret, "Soc register card failed\n"); - return ret; + return 0; } static const struct of_device_id rockchip_sound_of_match[] = { -- cgit From 0c57064e3fdba9bb76086b9a6e318eb0cef24b69 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:18 -0500 Subject: ASoC: samsung: snow: simplify error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck warning: sound/soc/samsung/snow.c:219:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/samsung/snow.c:215:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/samsung/snow.c:219:9: note: Returning identical expression 'ret' return ret; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/samsung/snow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 02372109c251..da342da03880 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -216,7 +216,7 @@ static int snow_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, ret, "snd_soc_register_card failed\n"); - return ret; + return 0; } static int snow_remove(struct platform_device *pdev) -- cgit From 7188b28f6686af0bc4aa1f96d720de782769a0a9 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 20 May 2022 16:17:19 -0500 Subject: ASoC: meson: remove useless initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cppcheck complains about invalid NULL dereferences but there's indeed no need to initialize a loop variable. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220520211719.607543-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/meson/meson-codec-glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/meson/meson-codec-glue.c b/sound/soc/meson/meson-codec-glue.c index 2870cfad813a..80c5ed196961 100644 --- a/sound/soc/meson/meson-codec-glue.c +++ b/sound/soc/meson/meson-codec-glue.c @@ -13,7 +13,7 @@ static struct snd_soc_dapm_widget * meson_codec_glue_get_input(struct snd_soc_dapm_widget *w) { - struct snd_soc_dapm_path *p = NULL; + struct snd_soc_dapm_path *p; struct snd_soc_dapm_widget *in; snd_soc_dapm_widget_for_each_source_path(w, p) { -- cgit From 0a034d93ee929a9ea89f3fa5f1d8492435b9ee6e Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Fri, 3 Jun 2022 17:10:43 +0400 Subject: ASoC: cros_ec_codec: Fix refcount leak in cros_ec_codec_platform_probe of_parse_phandle() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Add missing of_node_put() to avoid refcount leak. Fixes: b6bc07d4360d ("ASoC: cros_ec_codec: support WoV") Signed-off-by: Miaoqian Lin Reviewed-by: Tzung-Bi Shih Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220603131043.38907-1-linmq006@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/cros_ec_codec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c index 8b0a9c788a26..11e7b3f6d410 100644 --- a/sound/soc/codecs/cros_ec_codec.c +++ b/sound/soc/codecs/cros_ec_codec.c @@ -995,6 +995,7 @@ static int cros_ec_codec_platform_probe(struct platform_device *pdev) dev_dbg(dev, "ap_shm_phys_addr=%#llx len=%#x\n", priv->ap_shm_phys_addr, priv->ap_shm_len); } + of_node_put(node); } #endif -- cgit From 3e2649c5e8643bea0867bb1dd970fedadb0eb7f3 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Fri, 3 Jun 2022 17:06:39 +0400 Subject: ASoC: samsung: Fix error handling in aries_audio_probe of_get_child_by_name() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. This function is missing of_node_put(cpu) in the error path. Fix this by goto out label. of_node_put() will check NULL pointer. Fixes: 7a3a7671fa6c ("ASoC: samsung: Add driver for Aries boards") Signed-off-by: Miaoqian Lin Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220603130640.37624-1-linmq006@gmail.com Signed-off-by: Mark Brown --- sound/soc/samsung/aries_wm8994.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/aries_wm8994.c b/sound/soc/samsung/aries_wm8994.c index bb0cf4244e00..edee02d7f100 100644 --- a/sound/soc/samsung/aries_wm8994.c +++ b/sound/soc/samsung/aries_wm8994.c @@ -628,8 +628,10 @@ static int aries_audio_probe(struct platform_device *pdev) return -EINVAL; codec = of_get_child_by_name(dev->of_node, "codec"); - if (!codec) - return -EINVAL; + if (!codec) { + ret = -EINVAL; + goto out; + } for_each_card_prelinks(card, i, dai_link) { dai_link->codecs->of_node = of_parse_phandle(codec, -- cgit From 8466579b63cc9aa957b7b4f273087512f989d2a1 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 28 May 2022 09:59:22 +0200 Subject: ASoC: ux500: Remove some leftover from the "Replace GPLv2 boilerplate/reference with SPDX" rules The "Replace GPLv2 boilerplate/reference with SPDX" has left some empty "License terms" paragraphs. Remove them as well. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/84d94977c57deee9e85249f18394ebf8d72497bc.1653724723.git.christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/ux500/mop500.c | 2 -- sound/soc/ux500/mop500_ab8500.c | 2 -- sound/soc/ux500/mop500_ab8500.h | 2 -- sound/soc/ux500/ux500_msp_dai.c | 2 -- sound/soc/ux500/ux500_msp_dai.h | 2 -- sound/soc/ux500/ux500_msp_i2s.c | 2 -- sound/soc/ux500/ux500_msp_i2s.h | 2 -- sound/soc/ux500/ux500_pcm.c | 2 -- sound/soc/ux500/ux500_pcm.h | 2 -- 9 files changed, 18 deletions(-) diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 4f41bb0ab2b0..fdd55d772b8e 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -4,8 +4,6 @@ * * Author: Ola Lilja (ola.o.lilja@stericsson.com) * for ST-Ericsson. - * - * License terms: */ #include diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c index 1ea1729984a9..e5e73a2bd9fe 100644 --- a/sound/soc/ux500/mop500_ab8500.c +++ b/sound/soc/ux500/mop500_ab8500.c @@ -5,8 +5,6 @@ * Author: Ola Lilja , * Kristoffer Karlsson * for ST-Ericsson. - * - * License terms: */ #include diff --git a/sound/soc/ux500/mop500_ab8500.h b/sound/soc/ux500/mop500_ab8500.h index 087ef246d87d..98de80a9cc4f 100644 --- a/sound/soc/ux500/mop500_ab8500.h +++ b/sound/soc/ux500/mop500_ab8500.h @@ -4,8 +4,6 @@ * * Author: Ola Lilja * for ST-Ericsson. - * - * License terms: */ #ifndef MOP500_AB8500_H diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 21052378a32e..56532b62faf3 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -5,8 +5,6 @@ * Author: Ola Lilja , * Roger Nilsson * for ST-Ericsson. - * - * License terms: */ #include diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h index fcd4b26f5d2d..30bf70838196 100644 --- a/sound/soc/ux500/ux500_msp_dai.h +++ b/sound/soc/ux500/ux500_msp_dai.h @@ -5,8 +5,6 @@ * Author: Ola Lilja , * Roger Nilsson * for ST-Ericsson. - * - * License terms: */ #ifndef UX500_msp_dai_H diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index fd0b88bb7921..d113411a19f8 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -6,8 +6,6 @@ * Roger Nilsson , * Sandeep Kaushik * for ST-Ericsson. - * - * License terms: */ #include diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h index 756b3973af9a..d45b5e2831cc 100644 --- a/sound/soc/ux500/ux500_msp_i2s.h +++ b/sound/soc/ux500/ux500_msp_i2s.h @@ -4,8 +4,6 @@ * * Author: Ola Lilja , * for ST-Ericsson. - * - * License terms: */ diff --git a/sound/soc/ux500/ux500_pcm.c b/sound/soc/ux500/ux500_pcm.c index 18191084b8b8..d3802e5ef196 100644 --- a/sound/soc/ux500/ux500_pcm.c +++ b/sound/soc/ux500/ux500_pcm.c @@ -5,8 +5,6 @@ * Author: Ola Lilja , * Roger Nilsson * for ST-Ericsson. - * - * License terms: */ #include diff --git a/sound/soc/ux500/ux500_pcm.h b/sound/soc/ux500/ux500_pcm.h index ff3ef7223db6..bd4348ebf9a1 100644 --- a/sound/soc/ux500/ux500_pcm.h +++ b/sound/soc/ux500/ux500_pcm.h @@ -5,8 +5,6 @@ * Author: Ola Lilja , * Roger Nilsson * for ST-Ericsson. - * - * License terms: */ #ifndef UX500_PCM_H #define UX500_PCM_H -- cgit From 2f4a8171da06609bb6a063630ed546ee3d93dad7 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 25 May 2022 22:05:43 -0300 Subject: ASoC: imx-audmux: Silence a clang warning Change the of_device_get_match_data() cast to (uintptr_t) to silence the following clang warning: sound/soc/fsl/imx-audmux.c:301:16: warning: cast to smaller integer type 'enum imx_audmux_type' from 'const void *' [-Wvoid-pointer-to-enum-cast] Reported-by: kernel test robot Fixes: 6a8b8b582db1 ("ASoC: imx-audmux: Remove unused .id_table") Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20220526010543.1164793-1-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index dfa05d40b276..a8e5e0f57faf 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -298,7 +298,7 @@ static int imx_audmux_probe(struct platform_device *pdev) audmux_clk = NULL; } - audmux_type = (enum imx_audmux_type)of_device_get_match_data(&pdev->dev); + audmux_type = (uintptr_t)of_device_get_match_data(&pdev->dev); switch (audmux_type) { case IMX31_AUDMUX: -- cgit From b521e85eefa384a5c31984b1a7e0d71b762c9663 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 28 May 2022 10:00:53 +0200 Subject: ASoC: ab8500: Remove some leftover from the "Replace GPLv2 boilerplate/reference with SPDX" rules The "Replace GPLv2 boilerplate/reference with SPDX" has left some empty "License terms" paragraphs. Remove them as well. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/28c0833d4a11f8f75f385e5aad93c23721b06c7e.1653724847.git.christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/codecs/ab8500-codec.c | 2 -- sound/soc/codecs/ab8500-codec.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index aefafb0b7b97..cbd4a92cb06c 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -12,8 +12,6 @@ * Mikko Sarmanne , * Jarmo K. Kuronen , * for ST-Ericsson. - * - * License terms: */ #include diff --git a/sound/soc/codecs/ab8500-codec.h b/sound/soc/codecs/ab8500-codec.h index 0ac87d0446c2..2a6f6409f1f8 100644 --- a/sound/soc/codecs/ab8500-codec.h +++ b/sound/soc/codecs/ab8500-codec.h @@ -11,8 +11,6 @@ * Mikko J. Lehto , * Mikko Sarmanne , * for ST-Ericsson. - * - * License terms: */ #ifndef AB8500_CODEC_REGISTERS_H -- cgit From b661a848a50c0cc3e0b79795c74469d7b50ff4ac Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:11:29 +0200 Subject: ASoC: amd: acp: fix typo in comment Spelling mistake (triple letters) in comment. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20220521111145.81697-79-Julia.Lawall@inria.fr Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-pdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c index 424c6e0bb9d6..7a0b26a30051 100644 --- a/sound/soc/amd/acp/acp-pdm.c +++ b/sound/soc/amd/acp/acp-pdm.c @@ -174,7 +174,7 @@ static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream, struct acp_dev_data *adata = dev_get_drvdata(dev); u32 ext_int_ctrl; - /* Disable DMIC interrrupts */ + /* Disable DMIC interrupts */ ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL); ext_int_ctrl |= ~PDM_DMA_INTR_MASK; writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL); -- cgit From 99b5c107506c728b8a7d25742cf13f6c9c89d6ea Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 11:29:20 +0200 Subject: ASoC: ops: Clarify snd_soc_info_volsw_sx() Currently snd_soc_info_volsw_sx() is implemented indirectly, wrapping snd_soc_info_volsw() and modifying the values it sets up rather than directly setting up the values reported to userspace. This makes it much harder to follow what the intended behaviour of these controls is. Let's rewrite the function to be self contained with a clarifying comment at the top in an effort to help maintainability. Signed-off-by: Mark Brown Reviewed-by: Charles Keepax Tested-by: Charles Keepax Link: https://lore.kernel.org/r/20220602092921.3302713-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index e693070f51fe..8c0e669fe92d 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -203,7 +203,8 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw); * Callback to provide information about a single mixer control, or a double * mixer control that spans 2 registers of the SX TLV type. SX TLV controls * have a range that represents both positive and negative values either side - * of zero but without a sign bit. + * of zero but without a sign bit. min is the minimum register value, max is + * the number of steps. * * Returns 0 for success. */ @@ -212,12 +213,21 @@ int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol, { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; + int max; - snd_soc_info_volsw(kcontrol, uinfo); - /* Max represents the number of levels in an SX control not the - * maximum value, so add the minimum value back on - */ - uinfo->value.integer.max += mc->min; + if (mc->platform_max) + max = mc->platform_max; + else + max = mc->max; + + if (max == 1 && !strstr(kcontrol->id.name, " Volume")) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + else + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + + uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = max; return 0; } -- cgit From f53f50ee21d46094a8c48970e95e38a4deaa128e Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Wed, 1 Jun 2022 11:23:40 +0200 Subject: ASoC: fsl_sai: use local device pointer Use a local variable to dereference the device pointer once and use the local variable in further calls. No functional changes. Signed-off-by: Marco Felsch Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/20220601092342.3328644-1-m.felsch@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 53 +++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index fa950dde5310..a7637d602f3c 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1004,6 +1004,7 @@ static int fsl_sai_runtime_resume(struct device *dev); static int fsl_sai_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; struct fsl_sai *sai; struct regmap *gpr; struct resource *res; @@ -1012,12 +1013,12 @@ static int fsl_sai_probe(struct platform_device *pdev) int irq, ret, i; int index; - sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL); + sai = devm_kzalloc(dev, sizeof(*sai), GFP_KERNEL); if (!sai) return -ENOMEM; sai->pdev = pdev; - sai->soc_data = of_device_get_match_data(&pdev->dev); + sai->soc_data = of_device_get_match_data(dev); sai->is_lsb_first = of_property_read_bool(np, "lsb-first"); @@ -1032,18 +1033,18 @@ static int fsl_sai_probe(struct platform_device *pdev) ARRAY_SIZE(fsl_sai_reg_defaults_ofs8); } - sai->regmap = devm_regmap_init_mmio(&pdev->dev, base, &fsl_sai_regmap_config); + sai->regmap = devm_regmap_init_mmio(dev, base, &fsl_sai_regmap_config); if (IS_ERR(sai->regmap)) { - dev_err(&pdev->dev, "regmap init failed\n"); + dev_err(dev, "regmap init failed\n"); return PTR_ERR(sai->regmap); } - sai->bus_clk = devm_clk_get(&pdev->dev, "bus"); + sai->bus_clk = devm_clk_get(dev, "bus"); /* Compatible with old DTB cases */ if (IS_ERR(sai->bus_clk) && PTR_ERR(sai->bus_clk) != -EPROBE_DEFER) - sai->bus_clk = devm_clk_get(&pdev->dev, "sai"); + sai->bus_clk = devm_clk_get(dev, "sai"); if (IS_ERR(sai->bus_clk)) { - dev_err(&pdev->dev, "failed to get bus clock: %ld\n", + dev_err(dev, "failed to get bus clock: %ld\n", PTR_ERR(sai->bus_clk)); /* -EPROBE_DEFER */ return PTR_ERR(sai->bus_clk); @@ -1051,9 +1052,9 @@ static int fsl_sai_probe(struct platform_device *pdev) for (i = 1; i < FSL_SAI_MCLK_MAX; i++) { sprintf(tmp, "mclk%d", i); - sai->mclk_clk[i] = devm_clk_get(&pdev->dev, tmp); + sai->mclk_clk[i] = devm_clk_get(dev, tmp); if (IS_ERR(sai->mclk_clk[i])) { - dev_err(&pdev->dev, "failed to get mclk%d clock: %ld\n", + dev_err(dev, "failed to get mclk%d clock: %ld\n", i + 1, PTR_ERR(sai->mclk_clk[i])); sai->mclk_clk[i] = NULL; } @@ -1068,10 +1069,10 @@ static int fsl_sai_probe(struct platform_device *pdev) if (irq < 0) return irq; - ret = devm_request_irq(&pdev->dev, irq, fsl_sai_isr, IRQF_SHARED, + ret = devm_request_irq(dev, irq, fsl_sai_isr, IRQF_SHARED, np->name, sai); if (ret) { - dev_err(&pdev->dev, "failed to claim irq %u\n", irq); + dev_err(dev, "failed to claim irq %u\n", irq); return ret; } @@ -1088,7 +1089,7 @@ static int fsl_sai_probe(struct platform_device *pdev) if (of_find_property(np, "fsl,sai-synchronous-rx", NULL) && of_find_property(np, "fsl,sai-asynchronous", NULL)) { /* error out if both synchronous and asynchronous are present */ - dev_err(&pdev->dev, "invalid binding for synchronous mode\n"); + dev_err(dev, "invalid binding for synchronous mode\n"); return -EINVAL; } @@ -1109,7 +1110,7 @@ static int fsl_sai_probe(struct platform_device *pdev) of_device_is_compatible(np, "fsl,imx6ul-sai")) { gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr"); if (IS_ERR(gpr)) { - dev_err(&pdev->dev, "cannot find iomuxc registers\n"); + dev_err(dev, "cannot find iomuxc registers\n"); return PTR_ERR(gpr); } @@ -1127,23 +1128,23 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; platform_set_drvdata(pdev, sai); - pm_runtime_enable(&pdev->dev); - if (!pm_runtime_enabled(&pdev->dev)) { - ret = fsl_sai_runtime_resume(&pdev->dev); + pm_runtime_enable(dev); + if (!pm_runtime_enabled(dev)) { + ret = fsl_sai_runtime_resume(dev); if (ret) goto err_pm_disable; } - ret = pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_get_sync(dev); if (ret < 0) { - pm_runtime_put_noidle(&pdev->dev); + pm_runtime_put_noidle(dev); goto err_pm_get_sync; } /* Get sai version */ - ret = fsl_sai_check_version(&pdev->dev); + ret = fsl_sai_check_version(dev); if (ret < 0) - dev_warn(&pdev->dev, "Error reading SAI version: %d\n", ret); + dev_warn(dev, "Error reading SAI version: %d\n", ret); /* Select MCLK direction */ if (of_find_property(np, "fsl,sai-mclk-direction-output", NULL) && @@ -1152,7 +1153,7 @@ static int fsl_sai_probe(struct platform_device *pdev) FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN); } - ret = pm_runtime_put_sync(&pdev->dev); + ret = pm_runtime_put_sync(dev); if (ret < 0) goto err_pm_get_sync; @@ -1165,12 +1166,12 @@ static int fsl_sai_probe(struct platform_device *pdev) if (ret) goto err_pm_get_sync; } else { - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); + ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0); if (ret) goto err_pm_get_sync; } - ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, + ret = devm_snd_soc_register_component(dev, &fsl_component, &sai->cpu_dai_drv, 1); if (ret) goto err_pm_get_sync; @@ -1178,10 +1179,10 @@ static int fsl_sai_probe(struct platform_device *pdev) return ret; err_pm_get_sync: - if (!pm_runtime_status_suspended(&pdev->dev)) - fsl_sai_runtime_suspend(&pdev->dev); + if (!pm_runtime_status_suspended(dev)) + fsl_sai_runtime_suspend(dev); err_pm_disable: - pm_runtime_disable(&pdev->dev); + pm_runtime_disable(dev); return ret; } -- cgit From 22205521770ee740f64a3ec90301f50e34738cfd Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Wed, 1 Jun 2022 11:23:42 +0200 Subject: ASoC: fsl_sai: add error message in case of missing imx-pcm-dma support If the imx-pcm-dma is required we need to have the module enabled. For all NXP/FSL sound cards using the ASoC architecture this is the case but in case of using the simple-audio-card sound card this isn't the case. In such case the driver probe fails silently and the card isn't available. It took a while to find the missing Kconfig. Make this easier for others by printing a error if this the module isn't available but required by the HW. Signed-off-by: Marco Felsch Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/20220601092342.3328644-3-m.felsch@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index a7637d602f3c..b65c9c7cf54a 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -1163,8 +1163,11 @@ static int fsl_sai_probe(struct platform_device *pdev) */ if (sai->soc_data->use_imx_pcm) { ret = imx_pcm_dma_init(pdev); - if (ret) + if (ret) { + if (!IS_ENABLED(CONFIG_SND_SOC_IMX_PCM_DMA)) + dev_err(dev, "Error: You must enable the imx-pcm-dma support!\n"); goto err_pm_get_sync; + } } else { ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0); if (ret) -- cgit From ae4f11c1ed2d67192fdf3d89db719ee439827c11 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Thu, 2 Jun 2022 07:41:42 +0400 Subject: ASoC: mediatek: mt8173: Fix refcount leak in mt8173_rt5650_rt5676_dev_probe of_parse_phandle() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Fix missing of_node_put() in error paths. Fixes: 94319ba10eca ("ASoC: mediatek: Use platform_of_node for machine drivers") Signed-off-by: Miaoqian Lin Link: https://lore.kernel.org/r/20220602034144.60159-1-linmq006@gmail.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c index 70bf312e855f..8794720cea3a 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5676.c @@ -256,14 +256,16 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) if (!mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); - return -EINVAL; + ret = -EINVAL; + goto put_node; } mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node = of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1); if (!mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); - return -EINVAL; + ret = -EINVAL; + goto put_node; } mt8173_rt5650_rt5676_codec_conf[0].dlc.of_node = mt8173_rt5650_rt5676_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node; @@ -276,13 +278,15 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) if (!mt8173_rt5650_rt5676_dais[DAI_LINK_HDMI_I2S].codecs->of_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); - return -EINVAL; + ret = -EINVAL; + goto put_node; } card->dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, card); +put_node: of_node_put(platform_node); return ret; } -- cgit From aa7407f807b250eca7697e5fe9a699bc6c2fab71 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 5 Jun 2022 09:31:23 -0700 Subject: ASoC: max98390: use linux/gpio/consumer.h to fix build Change the header file to fix build errors in max98390.c: ../sound/soc/codecs/max98390.c: In function 'max98390_i2c_probe': ../sound/soc/codecs/max98390.c:1076:22: error: implicit declaration of function 'devm_gpiod_get_optional'; did you mean 'devm_regulator_get_optional'? [-Werror=implicit-function-declaration] 1076 | reset_gpio = devm_gpiod_get_optional(&i2c->dev, ../sound/soc/codecs/max98390.c:1077:55: error: 'GPIOD_OUT_HIGH' undeclared (first use in this function); did you mean 'GPIOF_INIT_HIGH'? 1077 | "reset", GPIOD_OUT_HIGH); ../sound/soc/codecs/max98390.c:1077:55: note: each undeclared identifier is reported only once for each function it appears in ../sound/soc/codecs/max98390.c:1083:17: error: implicit declaration of function 'gpiod_set_value_cansleep'; did you mean 'gpio_set_value_cansleep'? [-Werror=implicit-function-declaration] 1083 | gpiod_set_value_cansleep(reset_gpio, 0); Fixes: 397ff0249606 ("ASoC: max98390: Add reset gpio control") Signed-off-by: Randy Dunlap Reported-by: kernel test robot Cc: Steve Lee Cc: Mark Brown Cc: Liam Girdwood Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: alsa-devel@alsa-project.org Link: https://lore.kernel.org/r/20220605163123.23537-1-rdunlap@infradead.org Signed-off-by: Mark Brown --- sound/soc/codecs/max98390.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c index 2a6b1648c884..d83f81d9ff4e 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include -- cgit From ef6c320942a2f057204702d769d507186fd7f0b7 Mon Sep 17 00:00:00 2001 From: Alexander Martinz Date: Thu, 2 Jun 2022 18:45:03 +0200 Subject: ASoC: codecs: tfa989x: Add support for tfa9890 The initialization sequence is taken from the version provided by the supplier [1]. This allows speakers using the TFA9890 amplifier to work, which are used by various mobile phones such as the SHIFT6mq. [1]: https://source.codeaurora.org/external/mas/tfa98xx/tree/src/tfa_init.c?id=d2cd12931fbc48df988b62931fb9960d4e9dc05d#n1827 Signed-off-by: Alexander Martinz Reviewed-by: Stephan Gerhold Link: https://lore.kernel.org/r/20220602164504.261361-1-amartinz@shiftphones.com Signed-off-by: Mark Brown --- sound/soc/codecs/tfa989x.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/sound/soc/codecs/tfa989x.c b/sound/soc/codecs/tfa989x.c index dc86852752c5..8ab2656de750 100644 --- a/sound/soc/codecs/tfa989x.c +++ b/sound/soc/codecs/tfa989x.c @@ -40,12 +40,14 @@ #define TFA989X_I2S_SEL_REG 0x0a #define TFA989X_I2S_SEL_REG_SPKR_MSK GENMASK(10, 9) /* speaker impedance */ #define TFA989X_I2S_SEL_REG_DCFG_MSK GENMASK(14, 11) /* DCDC compensation */ +#define TFA989X_HIDE_UNHIDE_KEY 0x40 #define TFA989X_PWM_CONTROL 0x41 #define TFA989X_CURRENTSENSE1 0x46 #define TFA989X_CURRENTSENSE2 0x47 #define TFA989X_CURRENTSENSE3 0x48 #define TFA989X_CURRENTSENSE4 0x49 +#define TFA9890_REVISION 0x80 #define TFA9895_REVISION 0x12 #define TFA9897_REVISION 0x97 @@ -188,6 +190,33 @@ static struct snd_soc_dai_driver tfa989x_dai = { .ops = &tfa989x_dai_ops, }; +static int tfa9890_init(struct regmap *regmap) +{ + int ret; + + /* unhide keys to allow updating them */ + ret = regmap_write(regmap, TFA989X_HIDE_UNHIDE_KEY, 0x5a6b); + if (ret) + return ret; + + /* update PLL registers */ + ret = regmap_set_bits(regmap, 0x59, 0x3); + if (ret) + return ret; + + /* hide keys again */ + ret = regmap_write(regmap, TFA989X_HIDE_UNHIDE_KEY, 0x0000); + if (ret) + return ret; + + return regmap_write(regmap, TFA989X_CURRENTSENSE2, 0x7BE1); +} + +static const struct tfa989x_rev tfa9890_rev = { + .rev = TFA9890_REVISION, + .init = tfa9890_init, +}; + static const struct reg_sequence tfa9895_reg_init[] = { /* some other registers must be set for optimal amplifier behaviour */ { TFA989X_BAT_PROT, 0x13ab }, @@ -376,6 +405,7 @@ static int tfa989x_i2c_probe(struct i2c_client *i2c) } static const struct of_device_id tfa989x_of_match[] = { + { .compatible = "nxp,tfa9890", .data = &tfa9890_rev }, { .compatible = "nxp,tfa9895", .data = &tfa9895_rev }, { .compatible = "nxp,tfa9897", .data = &tfa9897_rev }, { } -- cgit From d0da7c8668dc19df157d927a67721ca00e29ff2b Mon Sep 17 00:00:00 2001 From: Alexander Martinz Date: Thu, 2 Jun 2022 18:45:04 +0200 Subject: ASoC: dt-bindings: nxp,tfa989x: Add tfa9890 support Document TFA9890 binding for tfa989x. Signed-off-by: Alexander Martinz Reviewed-by: Stephan Gerhold Acked-by: Rob Herring Link: https://lore.kernel.org/r/20220602164504.261361-2-amartinz@shiftphones.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml b/Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml index b9b1dba40856..7f2e68ff6d34 100644 --- a/Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml +++ b/Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml @@ -15,6 +15,7 @@ allOf: properties: compatible: enum: + - nxp,tfa9890 - nxp,tfa9895 - nxp,tfa9897 -- cgit From 6398b004cfcce38626f3ba6fa5853177a3501aae Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 20 May 2022 11:06:00 +0800 Subject: ASoC: fsl_asrc_dma: enable dual fifo for ASRC P2P The SSI and SPDIF has dual fifos, enhance P2P for these case with using the sdma_peripheral_config struct Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1653015960-15474-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc_dma.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index 5038faf035cb..aaf7993935b7 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -129,6 +129,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, struct snd_pcm_hw_params *params) { enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + enum sdma_peripheral_type be_peripheral_type = IMX_DMATYPE_SSI; struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL; @@ -139,6 +140,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, struct snd_soc_component *component_be = NULL; struct fsl_asrc *asrc = pair->asrc; struct dma_slave_config config_fe, config_be; + struct sdma_peripheral_config audio_config; enum asrc_pair_index index = pair->index; struct device *dev = component->dev; struct device_node *of_dma_node; @@ -221,6 +223,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, /* Get DMA request of Back-End */ tmp_data = tmp_chan->private; pair->dma_data.dma_request = tmp_data->dma_request; + be_peripheral_type = tmp_data->peripheral_type; if (!be_chan) dma_release_channel(tmp_chan); @@ -268,6 +271,17 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, config_be.dst_addr_width = buswidth; config_be.dst_maxburst = dma_params_be->maxburst; + memset(&audio_config, 0, sizeof(audio_config)); + config_be.peripheral_config = &audio_config; + config_be.peripheral_size = sizeof(audio_config); + + if (tx && (be_peripheral_type == IMX_DMATYPE_SSI_DUAL || + be_peripheral_type == IMX_DMATYPE_SPDIF)) + audio_config.n_fifos_dst = 2; + if (!tx && (be_peripheral_type == IMX_DMATYPE_SSI_DUAL || + be_peripheral_type == IMX_DMATYPE_SPDIF)) + audio_config.n_fifos_src = 2; + if (tx) { config_be.src_addr = asrc->paddr + asrc->get_fifo_addr(OUT, index); config_be.dst_addr = dma_params_be->addr; -- cgit From ff31753fcb061b90bd8c356d5b27a6eb5f8ade15 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 30 May 2022 04:28:44 +0000 Subject: ASoC: simple-card-utils: rename asoc_simple_init_dai_link_params() to asoc_simple_init_for_codec2codec() commit 95cfc0a0aaf5752071 ("ASoC: simple-card: Add support for codec2codec DAI links") added the function asoc_simple_init_dai_link_params() to initialize dai_link "params". It is very straight naming, but difficult to noticed that it is for Codec2Codec support. Handling Codec2Codec is one of very tricky part on ALSA SoC, thus it is very important to clarify it. This patch renames the function name. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o7zflk3n.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card-utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 539d7f081bd7..fa080f166345 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -513,7 +513,7 @@ static int asoc_simple_init_dai(struct snd_soc_dai *dai, return 0; } -static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd, +static int asoc_simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd, struct simple_dai_props *dai_props) { struct snd_soc_dai_link *dai_link = rtd->dai_link; @@ -575,7 +575,7 @@ int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd) return ret; } - ret = asoc_simple_init_dai_link_params(rtd, props); + ret = asoc_simple_init_for_codec2codec(rtd, props); if (ret < 0) return ret; -- cgit From 3ae190edc5f6f64f296f8dd15f4b511f529ab402 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Jun 2022 12:35:30 +0200 Subject: ASoC: nau8822: Don't reconfigure PLL to the same values When we configure the PLL record the input and output frequency, then if we get asked to configure the same values again just skip reprogramming the hardware. This makes things a bit easier to use for machine drivers since it means they don't need to keep track of if they've programmed the PLL so much. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220603103530.3844527-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/nau8822.c | 7 +++++++ sound/soc/codecs/nau8822.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c index 08f6c56dc387..f4f68b549e1a 100644 --- a/sound/soc/codecs/nau8822.c +++ b/sound/soc/codecs/nau8822.c @@ -726,6 +726,10 @@ static int nau8822_set_pll(struct snd_soc_dai *dai, int pll_id, int source, struct nau8822_pll *pll_param = &nau8822->pll; int ret, fs; + if (freq_in == pll_param->freq_in && + freq_out == pll_param->freq_out) + return 0; + fs = freq_out / 256; ret = nau8822_calc_pll(freq_in, fs, pll_param); @@ -762,6 +766,9 @@ static int nau8822_set_pll(struct snd_soc_dai *dai, int pll_id, int source, snd_soc_component_update_bits(component, NAU8822_REG_POWER_MANAGEMENT_1, NAU8822_PLL_EN_MASK, NAU8822_PLL_ON); + pll_param->freq_in = freq_in; + pll_param->freq_out = freq_out; + return 0; } diff --git a/sound/soc/codecs/nau8822.h b/sound/soc/codecs/nau8822.h index b45d42c15de6..547ec057f853 100644 --- a/sound/soc/codecs/nau8822.h +++ b/sound/soc/codecs/nau8822.h @@ -198,6 +198,8 @@ struct nau8822_pll { int mclk_scaler; int pll_frac; int pll_int; + int freq_in; + int freq_out; }; /* Codec Private Data */ -- cgit From 84965cc60e643db7049eb75bb9a6cc5cd66ee3d8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 20 May 2022 19:33:49 +0200 Subject: ASoC: cs35l45: Make cs35l45_remove() return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cs35l45_remove() always returns zero. Make it return no value which makes it easier to see in the callers that there is no error to handle. Also the return value of i2c driver remove callbacks is ignored anyway. This prepares making i2c remove callbacks return void, too. Signed-off-by: Uwe Kleine-König Acked-by: Charles Keepax Reviewed-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20220520173349.774366-1-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l45-i2c.c | 4 +++- sound/soc/codecs/cs35l45.c | 4 +--- sound/soc/codecs/cs35l45.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/cs35l45-i2c.c b/sound/soc/codecs/cs35l45-i2c.c index 38a4dbc9e9fe..06c2ddffb9c5 100644 --- a/sound/soc/codecs/cs35l45-i2c.c +++ b/sound/soc/codecs/cs35l45-i2c.c @@ -40,7 +40,9 @@ static int cs35l45_i2c_remove(struct i2c_client *client) { struct cs35l45_private *cs35l45 = i2c_get_clientdata(client); - return cs35l45_remove(cs35l45); + cs35l45_remove(cs35l45); + + return 0; } static const struct of_device_id cs35l45_of_match[] = { diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c index 2367c1a4c10e..c94edfce4b72 100644 --- a/sound/soc/codecs/cs35l45.c +++ b/sound/soc/codecs/cs35l45.c @@ -665,7 +665,7 @@ err: } EXPORT_SYMBOL_NS_GPL(cs35l45_probe, SND_SOC_CS35L45); -int cs35l45_remove(struct cs35l45_private *cs35l45) +void cs35l45_remove(struct cs35l45_private *cs35l45) { pm_runtime_disable(cs35l45->dev); @@ -673,8 +673,6 @@ int cs35l45_remove(struct cs35l45_private *cs35l45) regulator_disable(cs35l45->vdd_a); /* VDD_BATT must be the last to power-off */ regulator_disable(cs35l45->vdd_batt); - - return 0; } EXPORT_SYMBOL_NS_GPL(cs35l45_remove, SND_SOC_CS35L45); diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h index 4e266d19cd1c..680891bcfce9 100644 --- a/sound/soc/codecs/cs35l45.h +++ b/sound/soc/codecs/cs35l45.h @@ -212,6 +212,6 @@ extern const struct regmap_config cs35l45_spi_regmap; int cs35l45_apply_patch(struct cs35l45_private *cs43l45); unsigned int cs35l45_get_clk_freq_id(unsigned int freq); int cs35l45_probe(struct cs35l45_private *cs35l45); -int cs35l45_remove(struct cs35l45_private *cs35l45); +void cs35l45_remove(struct cs35l45_private *cs35l45); #endif /* CS35L45_H */ -- cgit From 9c3148dec7d2d40ef727b8789d3e9410ad6d4a1f Mon Sep 17 00:00:00 2001 From: zhangqilong Date: Thu, 2 Jun 2022 15:20:24 +0800 Subject: ASoC: fsl_xcvr:Fix unbalanced pm_runtime_enable in fsl_xcvr_probe a) Add missing pm_runtime_disable() when probe error out. It could avoid pm_runtime implementation complains when removing and probing again the driver. b) Add remove for missing pm_runtime_disable(). Fix:c590fa80b3928 ("ASoC: fsl_xcvr: register platform component before registering cpu dai") Signed-off-by: Zhang Qilong Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/20220602072024.33236-1-zhangqilong3@huawei.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_xcvr.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index d0556c79fdb1..55e640cba87d 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -1228,6 +1228,7 @@ static int fsl_xcvr_probe(struct platform_device *pdev) */ ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0); if (ret) { + pm_runtime_disable(dev); dev_err(dev, "failed to pcm register\n"); return ret; } @@ -1235,6 +1236,7 @@ static int fsl_xcvr_probe(struct platform_device *pdev) ret = devm_snd_soc_register_component(dev, &fsl_xcvr_comp, &fsl_xcvr_dai, 1); if (ret) { + pm_runtime_disable(dev); dev_err(dev, "failed to register component %s\n", fsl_xcvr_comp.name); } @@ -1242,6 +1244,12 @@ static int fsl_xcvr_probe(struct platform_device *pdev) return ret; } +static int fsl_xcvr_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + return 0; +} + static __maybe_unused int fsl_xcvr_runtime_suspend(struct device *dev) { struct fsl_xcvr *xcvr = dev_get_drvdata(dev); @@ -1370,6 +1378,7 @@ static struct platform_driver fsl_xcvr_driver = { .pm = &fsl_xcvr_pm_ops, .of_match_table = fsl_xcvr_dt_ids, }, + .remove = fsl_xcvr_remove, }; module_platform_driver(fsl_xcvr_driver); -- cgit From bf1ebcddcb19a1b6d6d8b75b75626197a5a76d4f Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Wed, 25 May 2022 21:50:23 +0800 Subject: ASoC: stm32: sai: Remove useless define STM_SAI_IS_SUB_B(x) and STM_SAI_BLOCK_NAME(x) are not being used, so remove them. Signed-off-by: Tang Bin Acked-by: Olivier Moysan Link: https://lore.kernel.org/r/20220525135023.6792-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai_sub.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index dd636af81c9b..4296fcb245c9 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -45,8 +45,6 @@ #define STM_SAI_B_ID 0x1 #define STM_SAI_IS_SUB_A(x) ((x)->id == STM_SAI_A_ID) -#define STM_SAI_IS_SUB_B(x) ((x)->id == STM_SAI_B_ID) -#define STM_SAI_BLOCK_NAME(x) (((x)->id == STM_SAI_A_ID) ? "A" : "B") #define SAI_SYNC_NONE 0x0 #define SAI_SYNC_INTERNAL 0x1 -- cgit From fef94875a72bc63ba60d2e12421d7f49d31523f0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 12:18:33 +0200 Subject: ASoC: ops: Remove unneeded delay.h inclusion The ops code does not do any sleeps or delays so does not need delay.h. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602101833.3481641-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 8c0e669fe92d..2d5910b6ca54 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include -- cgit From 32882881078bd8f8fae47ff69c102d9e691f5bb9 Mon Sep 17 00:00:00 2001 From: Srinivasa Rao Mandadapu Date: Wed, 18 May 2022 18:12:35 +0530 Subject: ASoC: qcom: soundwire: Add support for controlling audio CGCR from HLOS Add support for controlling soundwire audio CGCR interface using clock framework to make hclk ungating with software. As per new hardware changes, software has to always ungate hclk if soundwire is operational and keep it running. This requirement is for latest LPASS chipsets for RX, TX and WSA path to work. Signed-off-by: Srinivasa Rao Mandadapu Link: https://lore.kernel.org/r/1652877755-25120-1-git-send-email-quic_srivasam@quicinc.com Signed-off-by: Mark Brown --- drivers/soundwire/qcom.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 22b706350ead..a3fccf051e07 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -142,6 +143,7 @@ struct qcom_swrm_ctrl { struct device *dev; struct regmap *regmap; void __iomem *mmio; + struct reset_control *audio_cgcr; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs; #endif @@ -656,6 +658,8 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl) val = FIELD_PREP(SWRM_MCP_FRAME_CTRL_BANK_ROW_CTRL_BMSK, ctrl->rows_index); val |= FIELD_PREP(SWRM_MCP_FRAME_CTRL_BANK_COL_CTRL_BMSK, ctrl->cols_index); + reset_control_reset(ctrl->audio_cgcr); + ctrl->reg_write(ctrl, SWRM_MCP_FRAME_CTRL_BANK_ADDR(0), val); /* Enable Auto enumeration */ @@ -1332,6 +1336,10 @@ static int qcom_swrm_probe(struct platform_device *pdev) ctrl->bus.compute_params = &qcom_swrm_compute_params; ctrl->bus.clk_stop_timeout = 300; + ctrl->audio_cgcr = devm_reset_control_get_exclusive(dev, "swr_audio_cgcr"); + if (IS_ERR(ctrl->audio_cgcr)) + dev_err(dev, "Failed to get audio_cgcr reset required for soundwire-v1.6.0\n"); + ret = qcom_swrm_get_port_config(ctrl); if (ret) goto err_clk; @@ -1485,6 +1493,8 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev) qcom_swrm_get_device_status(ctrl); sdw_handle_slave_status(&ctrl->bus, ctrl->status); } else { + reset_control_reset(ctrl->audio_cgcr); + ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START); ctrl->reg_write(ctrl, SWRM_INTERRUPT_CLEAR, SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET); -- cgit From 4f8ed19593872b710f27bbc3b7a9ce03310efc57 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:10:58 +0200 Subject: ASoC: tfa9879: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tfa9879 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Acked-by: Peter Rosin Link: https://lore.kernel.org/r/20220602131058.3552621-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tfa9879.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tfa9879.c b/sound/soc/codecs/tfa9879.c index 3d8e8c2276f0..41a9b1b76e62 100644 --- a/sound/soc/codecs/tfa9879.c +++ b/sound/soc/codecs/tfa9879.c @@ -111,8 +111,8 @@ static int tfa9879_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) int i2s_set; int sck_pol; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; -- cgit From 7472eb8d7dd12b6b9b1a4f4527719cc9c7f5965f Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Fri, 3 Jun 2022 12:34:15 +0400 Subject: ASoC: mt6797-mt6351: Fix refcount leak in mt6797_mt6351_dev_probe of_parse_phandle() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Add missing of_node_put() to avoid refcount leak. Fixes: f0ab0bf250da ("ASoC: add mt6797-mt6351 driver and config option") Signed-off-by: Miaoqian Lin Link: https://lore.kernel.org/r/20220603083417.9011-1-linmq006@gmail.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt6797/mt6797-mt6351.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mt6797/mt6797-mt6351.c b/sound/soc/mediatek/mt6797/mt6797-mt6351.c index 496f32bcfb5e..d2f6213a6bfc 100644 --- a/sound/soc/mediatek/mt6797/mt6797-mt6351.c +++ b/sound/soc/mediatek/mt6797/mt6797-mt6351.c @@ -217,7 +217,8 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev) if (!codec_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); - return -EINVAL; + ret = -EINVAL; + goto put_platform_node; } for_each_card_prelinks(card, i, dai_link) { if (dai_link->codecs->name) @@ -230,6 +231,9 @@ static int mt6797_mt6351_dev_probe(struct platform_device *pdev) dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", __func__, ret); + of_node_put(codec_node); +put_platform_node: + of_node_put(platform_node); return ret; } -- cgit From 82fa8f581a954ddeec1602bed9f8b4a09d100e6e Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Tue, 31 May 2022 17:47:12 +0800 Subject: ASoC: codecs: da7210: add check for i2c_add_driver As i2c_add_driver could return error if fails, it should be better to check the return value. However, if the CONFIG_I2C and CONFIG_SPI_MASTER are both true, the return value of i2c_add_driver will be covered by spi_register_driver. Therefore, it is necessary to add check and return error if fails. Fixes: aa0e25caafb7 ("ASoC: da7210: Add support for spi regmap") Signed-off-by: Jiasheng Jiang Link: https://lore.kernel.org/r/20220531094712.2376759-1-jiasheng@iscas.ac.cn Signed-off-by: Mark Brown --- sound/soc/codecs/da7210.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 3fa3042e4424..76a21976ccdd 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -1335,6 +1335,8 @@ static int __init da7210_modinit(void) int ret = 0; #if IS_ENABLED(CONFIG_I2C) ret = i2c_add_driver(&da7210_i2c_driver); + if (ret) + return ret; #endif #if defined(CONFIG_SPI_MASTER) ret = spi_register_driver(&da7210_spi_driver); -- cgit From 12ba5ceb4a08d5ea776d3eaf83c0cee63fafe952 Mon Sep 17 00:00:00 2001 From: Minghao Chi Date: Thu, 2 Jun 2022 07:18:09 +0000 Subject: ASoC: mediatek: remove unnecessary check of clk_disable_unprepare Because clk_disable_unprepare already checked NULL clock parameter, so the additional checks are unnecessary, just remove them. Reported-by: Zeal Robot Signed-off-by: Minghao Chi Link: https://lore.kernel.org/r/20220602071809.278134-1-chi.minghao@zte.com.cn Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index 31494930433f..dcaeeeb8aac7 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -286,10 +286,8 @@ static int mt8173_afe_dais_set_clks(struct mtk_base_afe *afe, static void mt8173_afe_dais_disable_clks(struct mtk_base_afe *afe, struct clk *m_ck, struct clk *b_ck) { - if (m_ck) - clk_disable_unprepare(m_ck); - if (b_ck) - clk_disable_unprepare(b_ck); + clk_disable_unprepare(m_ck); + clk_disable_unprepare(b_ck); } static int mt8173_afe_i2s_startup(struct snd_pcm_substream *substream, -- cgit From 8366d8ca0f7805be6cffe1e242822565aed509ae Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 14:58:12 +0200 Subject: ASoC: max9860: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the max9860 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Acked-by: Peter Rosin Link: https://lore.kernel.org/r/20220602125812.3551947-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/max9860.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c index 82f20a8e27ad..a1d0179e12c7 100644 --- a/sound/soc/codecs/max9860.c +++ b/sound/soc/codecs/max9860.c @@ -448,9 +448,9 @@ static int max9860_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct snd_soc_component *component = dai->component; struct max9860_priv *max9860 = snd_soc_component_get_drvdata(component); - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_CBC_CFC: max9860->fmt = fmt; return 0; -- cgit From 063c915502b914a5a621458c763dfc28286f7606 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 25 May 2022 13:23:41 +0800 Subject: ASoC: fsl_mqs: simplify the code with adding fsl_mqs_soc_data Add soc specific data struct fsl_mqs_soc_data, move the definition of control register, each function bits to it, then the code can be simplified. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1653456221-21613-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_mqs.c | 119 +++++++++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 48 deletions(-) diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c index ceaecbe3a25e..8a8d727319d6 100644 --- a/sound/soc/fsl/fsl_mqs.c +++ b/sound/soc/fsl/fsl_mqs.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -29,15 +30,41 @@ #define MQS_CLK_DIV_MASK (0xFF << 0) #define MQS_CLK_DIV_SHIFT (0) +/** + * struct fsl_mqs_soc_data - soc specific data + * + * @use_gpr: control register is in General Purpose Register group + * @ctrl_off: control register offset + * @en_mask: enable bit mask + * @en_shift: enable bit shift + * @rst_mask: reset bit mask + * @rst_shift: reset bit shift + * @osr_mask: oversample bit mask + * @osr_shift: oversample bit shift + * @div_mask: clock divider mask + * @div_shift: clock divider bit shift + */ +struct fsl_mqs_soc_data { + bool use_gpr; + int ctrl_off; + int en_mask; + int en_shift; + int rst_mask; + int rst_shift; + int osr_mask; + int osr_shift; + int div_mask; + int div_shift; +}; + /* codec private data */ struct fsl_mqs { struct regmap *regmap; struct clk *mclk; struct clk *ipg; + const struct fsl_mqs_soc_data *soc; - unsigned int reg_iomuxc_gpr2; unsigned int reg_mqs_ctrl; - bool use_gpr; }; #define FSL_MQS_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) @@ -65,19 +92,11 @@ static int fsl_mqs_hw_params(struct snd_pcm_substream *substream, res = mclk_rate % (32 * lrclk * 2 * 8); if (res == 0 && div > 0 && div <= 256) { - if (mqs_priv->use_gpr) { - regmap_update_bits(mqs_priv->regmap, IOMUXC_GPR2, - IMX6SX_GPR2_MQS_CLK_DIV_MASK, - (div - 1) << IMX6SX_GPR2_MQS_CLK_DIV_SHIFT); - regmap_update_bits(mqs_priv->regmap, IOMUXC_GPR2, - IMX6SX_GPR2_MQS_OVERSAMPLE_MASK, 0); - } else { - regmap_update_bits(mqs_priv->regmap, REG_MQS_CTRL, - MQS_CLK_DIV_MASK, - (div - 1) << MQS_CLK_DIV_SHIFT); - regmap_update_bits(mqs_priv->regmap, REG_MQS_CTRL, - MQS_OVERSAMPLE_MASK, 0); - } + regmap_update_bits(mqs_priv->regmap, mqs_priv->soc->ctrl_off, + mqs_priv->soc->div_mask, + (div - 1) << mqs_priv->soc->div_shift); + regmap_update_bits(mqs_priv->regmap, mqs_priv->soc->ctrl_off, + mqs_priv->soc->osr_mask, 0); } else { dev_err(component->dev, "can't get proper divider\n"); } @@ -118,14 +137,9 @@ static int fsl_mqs_startup(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct fsl_mqs *mqs_priv = snd_soc_component_get_drvdata(component); - if (mqs_priv->use_gpr) - regmap_update_bits(mqs_priv->regmap, IOMUXC_GPR2, - IMX6SX_GPR2_MQS_EN_MASK, - 1 << IMX6SX_GPR2_MQS_EN_SHIFT); - else - regmap_update_bits(mqs_priv->regmap, REG_MQS_CTRL, - MQS_EN_MASK, - 1 << MQS_EN_SHIFT); + regmap_update_bits(mqs_priv->regmap, mqs_priv->soc->ctrl_off, + mqs_priv->soc->en_mask, + 1 << mqs_priv->soc->en_shift); return 0; } @@ -135,12 +149,8 @@ static void fsl_mqs_shutdown(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct fsl_mqs *mqs_priv = snd_soc_component_get_drvdata(component); - if (mqs_priv->use_gpr) - regmap_update_bits(mqs_priv->regmap, IOMUXC_GPR2, - IMX6SX_GPR2_MQS_EN_MASK, 0); - else - regmap_update_bits(mqs_priv->regmap, REG_MQS_CTRL, - MQS_EN_MASK, 0); + regmap_update_bits(mqs_priv->regmap, mqs_priv->soc->ctrl_off, + mqs_priv->soc->en_mask, 0); } static const struct snd_soc_component_driver soc_codec_fsl_mqs = { @@ -191,12 +201,9 @@ static int fsl_mqs_probe(struct platform_device *pdev) * But in i.MX8QM/i.MX8QXP the control register is moved * to its own domain. */ - if (of_device_is_compatible(np, "fsl,imx8qm-mqs")) - mqs_priv->use_gpr = false; - else - mqs_priv->use_gpr = true; + mqs_priv->soc = of_device_get_match_data(&pdev->dev); - if (mqs_priv->use_gpr) { + if (mqs_priv->soc->use_gpr) { gpr_np = of_parse_phandle(np, "gpr", 0); if (!gpr_np) { dev_err(&pdev->dev, "failed to get gpr node by phandle\n"); @@ -280,12 +287,7 @@ static int fsl_mqs_runtime_resume(struct device *dev) return ret; } - if (mqs_priv->use_gpr) - regmap_write(mqs_priv->regmap, IOMUXC_GPR2, - mqs_priv->reg_iomuxc_gpr2); - else - regmap_write(mqs_priv->regmap, REG_MQS_CTRL, - mqs_priv->reg_mqs_ctrl); + regmap_write(mqs_priv->regmap, mqs_priv->soc->ctrl_off, mqs_priv->reg_mqs_ctrl); return 0; } @@ -293,12 +295,7 @@ static int fsl_mqs_runtime_suspend(struct device *dev) { struct fsl_mqs *mqs_priv = dev_get_drvdata(dev); - if (mqs_priv->use_gpr) - regmap_read(mqs_priv->regmap, IOMUXC_GPR2, - &mqs_priv->reg_iomuxc_gpr2); - else - regmap_read(mqs_priv->regmap, REG_MQS_CTRL, - &mqs_priv->reg_mqs_ctrl); + regmap_read(mqs_priv->regmap, mqs_priv->soc->ctrl_off, &mqs_priv->reg_mqs_ctrl); clk_disable_unprepare(mqs_priv->mclk); clk_disable_unprepare(mqs_priv->ipg); @@ -315,9 +312,35 @@ static const struct dev_pm_ops fsl_mqs_pm_ops = { pm_runtime_force_resume) }; +static const struct fsl_mqs_soc_data fsl_mqs_imx8qm_data = { + .use_gpr = false, + .ctrl_off = REG_MQS_CTRL, + .en_mask = MQS_EN_MASK, + .en_shift = MQS_EN_SHIFT, + .rst_mask = MQS_SW_RST_MASK, + .rst_shift = MQS_SW_RST_SHIFT, + .osr_mask = MQS_OVERSAMPLE_MASK, + .osr_shift = MQS_OVERSAMPLE_SHIFT, + .div_mask = MQS_CLK_DIV_MASK, + .div_shift = MQS_CLK_DIV_SHIFT, +}; + +static const struct fsl_mqs_soc_data fsl_mqs_imx6sx_data = { + .use_gpr = true, + .ctrl_off = IOMUXC_GPR2, + .en_mask = IMX6SX_GPR2_MQS_EN_MASK, + .en_shift = IMX6SX_GPR2_MQS_EN_SHIFT, + .rst_mask = IMX6SX_GPR2_MQS_SW_RST_MASK, + .rst_shift = IMX6SX_GPR2_MQS_SW_RST_SHIFT, + .osr_mask = IMX6SX_GPR2_MQS_OVERSAMPLE_MASK, + .osr_shift = IMX6SX_GPR2_MQS_OVERSAMPLE_SHIFT, + .div_mask = IMX6SX_GPR2_MQS_CLK_DIV_MASK, + .div_shift = IMX6SX_GPR2_MQS_CLK_DIV_SHIFT, +}; + static const struct of_device_id fsl_mqs_dt_ids[] = { - { .compatible = "fsl,imx8qm-mqs", }, - { .compatible = "fsl,imx6sx-mqs", }, + { .compatible = "fsl,imx8qm-mqs", .data = &fsl_mqs_imx8qm_data }, + { .compatible = "fsl,imx6sx-mqs", .data = &fsl_mqs_imx6sx_data }, {} }; MODULE_DEVICE_TABLE(of, fsl_mqs_dt_ids); -- cgit From 2685d5046962f018b1a155b3eef316562414638b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:11:26 +0200 Subject: ASoC: stm32: dfsdm: fix typo in comment Spelling mistake (triple letters) in comment. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20220521111145.81697-76-Julia.Lawall@inria.fr Signed-off-by: Mark Brown --- sound/soc/stm/stm32_adfsdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index 6ee714542b84..122805160e70 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -296,7 +296,7 @@ static int stm32_adfsdm_pcm_new(struct snd_soc_component *component, static int stm32_adfsdm_dummy_cb(const void *data, void *private) { /* - * This dummmy callback is requested by iio_channel_get_all_cb() API, + * This dummy callback is requested by iio_channel_get_all_cb() API, * but the stm32_dfsdm_get_buff_cb() API is used instead, to optimize * DMA transfers. */ -- cgit From ac8a2ea48001a4c336fbaaa977642d5ad79cdbd8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 3 Jun 2022 13:50:03 +0200 Subject: ASoC: wm_adsp: Fix event generation for wm_adsp_fw_put() Currently wm_adsp_fw_put() returns 0 rather than 1 when updating the value of the control, meaning that no event is generated to userspace. Fix this by setting the default return value to 1, the code already exits early with a return value of 0 if the value is unchanged. Signed-off-by: Mark Brown Reviewed-by: Richard Fitzgerald Link: https://lore.kernel.org/r/20220603115003.3865834-1-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 7973a75cac05..6d7fd88243aa 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -333,7 +333,7 @@ int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct wm_adsp *dsp = snd_soc_component_get_drvdata(component); - int ret = 0; + int ret = 1; if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw) return 0; -- cgit From 3929ead38d61abe6c5302adce1d490f5c041d4b3 Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Mon, 30 May 2022 12:01:50 +0800 Subject: ASoC: nau8822: Add operation for internal PLL off and on We tried to enable the audio on an imx6sx EVB with the codec nau8822, after setting the internal PLL fractional parameters, the audio still couldn't work and the there was no sdma irq at all. After checking with the section "8.1.1 Phase Locked Loop (PLL) Design Example" of "NAU88C22 Datasheet Rev 0.6", we found we need to turn off the PLL before programming fractional parameters and turn on the PLL after programming. After this change, the audio driver could record and play sound and the sdma's irq is triggered when playing or recording. Cc: David Lin Cc: John Hsu Cc: Seven Li Signed-off-by: Hui Wang Link: https://lore.kernel.org/r/20220530040151.95221-2-hui.wang@canonical.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8822.c | 4 ++++ sound/soc/codecs/nau8822.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c index 66bbd8f4f1ad..08f6c56dc387 100644 --- a/sound/soc/codecs/nau8822.c +++ b/sound/soc/codecs/nau8822.c @@ -740,6 +740,8 @@ static int nau8822_set_pll(struct snd_soc_dai *dai, int pll_id, int source, pll_param->pll_int, pll_param->pll_frac, pll_param->mclk_scaler, pll_param->pre_factor); + snd_soc_component_update_bits(component, + NAU8822_REG_POWER_MANAGEMENT_1, NAU8822_PLL_EN_MASK, NAU8822_PLL_OFF); snd_soc_component_update_bits(component, NAU8822_REG_PLL_N, NAU8822_PLLMCLK_DIV2 | NAU8822_PLLN_MASK, (pll_param->pre_factor ? NAU8822_PLLMCLK_DIV2 : 0) | @@ -757,6 +759,8 @@ static int nau8822_set_pll(struct snd_soc_dai *dai, int pll_id, int source, pll_param->mclk_scaler << NAU8822_MCLKSEL_SFT); snd_soc_component_update_bits(component, NAU8822_REG_CLOCKING, NAU8822_CLKM_MASK, NAU8822_CLKM_PLL); + snd_soc_component_update_bits(component, + NAU8822_REG_POWER_MANAGEMENT_1, NAU8822_PLL_EN_MASK, NAU8822_PLL_ON); return 0; } diff --git a/sound/soc/codecs/nau8822.h b/sound/soc/codecs/nau8822.h index 489191ff187e..b45d42c15de6 100644 --- a/sound/soc/codecs/nau8822.h +++ b/sound/soc/codecs/nau8822.h @@ -90,6 +90,9 @@ #define NAU8822_REFIMP_3K 0x3 #define NAU8822_IOBUF_EN (0x1 << 2) #define NAU8822_ABIAS_EN (0x1 << 3) +#define NAU8822_PLL_EN_MASK (0x1 << 5) +#define NAU8822_PLL_ON (0x1 << 5) +#define NAU8822_PLL_OFF (0x0 << 5) /* NAU8822_REG_AUDIO_INTERFACE (0x4) */ #define NAU8822_AIFMT_MASK (0x3 << 3) -- cgit From dd58365d43efccd87dbfc8f93eb3e61b9b4d64f8 Mon Sep 17 00:00:00 2001 From: Srinivasa Rao Mandadapu Date: Fri, 27 May 2022 19:40:08 +0530 Subject: ASoC: qcom: lpass-platform: Update VMA access permissions in mmap callback Replace page protection permissions from noncashed to writecombine, in lpass codec DMA path mmp callabck, to support 64 bit chromeOS. Avoid SIGBUS error in userspace caused by noncached permissions in 64 bit chromeOS. Signed-off-by: Srinivasa Rao Mandadapu Link: https://lore.kernel.org/r/1653660608-27245-1-git-send-email-quic_srivasam@quicinc.com Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index f03a7ae49d50..b41ab7a321ae 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -898,7 +898,7 @@ static int lpass_platform_cdc_dma_mmap(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; unsigned long size, offset; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); size = vma->vm_end - vma->vm_start; offset = vma->vm_pgoff << PAGE_SHIFT; return io_remap_pfn_range(vma, vma->vm_start, -- cgit From 33dbf3fc6942b53920296395bb4c81fb3cc5ebfd Mon Sep 17 00:00:00 2001 From: xliu Date: Thu, 2 Jun 2022 13:19:22 +0800 Subject: ASoC: Intel: cirrus-common: fix incorrect channel mapping The default mapping of ASPRX1 (DAC source) is slot 0. Change the slot mapping of right amplifiers (WR and TR) to slot 1 to receive right channel data. Also update the ACPI instance ID mapping according to HW configuration. Signed-off-by: xliu Signed-off-by: Brent Lu Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220602051922.1232457-1-brent.lu@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_cirrus_common.c | 40 +++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_cirrus_common.c b/sound/soc/intel/boards/sof_cirrus_common.c index e71d74ec1b0b..f4192df962d6 100644 --- a/sound/soc/intel/boards/sof_cirrus_common.c +++ b/sound/soc/intel/boards/sof_cirrus_common.c @@ -54,22 +54,29 @@ static struct snd_soc_dai_link_component cs35l41_components[] = { }, }; +/* + * Mapping between ACPI instance id and speaker position. + * + * Four speakers: + * 0: Tweeter left, 1: Woofer left + * 2: Tweeter right, 3: Woofer right + */ static struct snd_soc_codec_conf cs35l41_codec_conf[] = { { .dlc = COMP_CODEC_CONF(CS35L41_DEV0_NAME), - .name_prefix = "WL", + .name_prefix = "TL", }, { .dlc = COMP_CODEC_CONF(CS35L41_DEV1_NAME), - .name_prefix = "WR", + .name_prefix = "WL", }, { .dlc = COMP_CODEC_CONF(CS35L41_DEV2_NAME), - .name_prefix = "TL", + .name_prefix = "TR", }, { .dlc = COMP_CODEC_CONF(CS35L41_DEV3_NAME), - .name_prefix = "TR", + .name_prefix = "WR", }, }; @@ -101,6 +108,21 @@ static int cs35l41_init(struct snd_soc_pcm_runtime *rtd) return ret; } +/* + * Channel map: + * + * TL/WL: ASPRX1 on slot 0, ASPRX2 on slot 1 (default) + * TR/WR: ASPRX1 on slot 1, ASPRX2 on slot 0 + */ +static const struct { + unsigned int rx[2]; +} cs35l41_channel_map[] = { + {.rx = {0, 1}}, /* TL */ + {.rx = {0, 1}}, /* WL */ + {.rx = {1, 0}}, /* TR */ + {.rx = {1, 0}}, /* WR */ +}; + static int cs35l41_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -134,6 +156,16 @@ static int cs35l41_hw_params(struct snd_pcm_substream *substream, ret); return ret; } + + /* setup channel map */ + ret = snd_soc_dai_set_channel_map(codec_dai, 0, NULL, + ARRAY_SIZE(cs35l41_channel_map[i].rx), + (unsigned int *)cs35l41_channel_map[i].rx); + if (ret < 0) { + dev_err(codec_dai->dev, "fail to set channel map, ret %d\n", + ret); + return ret; + } } return 0; -- cgit From 07c2307ce8b420e351e0635c690397ad7a9fab77 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 2 Jun 2022 17:21:14 +0100 Subject: ASoC: cs42l52: Fix TLV scales for mixer controls The datasheet specifies the range of the mixer volumes as between -51.5dB and 12dB with a 0.5dB step. Update the TLVs for this. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220602162119.3393857-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l52.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 9b182b585be4..02c25399cf8a 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -137,7 +137,7 @@ static DECLARE_TLV_DB_SCALE(mic_tlv, 1600, 100, 0); static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0); -static DECLARE_TLV_DB_SCALE(mix_tlv, -50, 50, 0); +static DECLARE_TLV_DB_SCALE(mix_tlv, -5150, 50, 0); static DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0); @@ -364,7 +364,7 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = { CS42L52_ADCB_VOL, 0, 0xA0, 0x78, ipd_tlv), SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL, - 0, 0x19, 0x7F, ipd_tlv), + 0, 0x19, 0x7F, mix_tlv), SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0), -- cgit From e9dad4de223ee5a4bd5e8b11931a2af8558da0bc Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 2 Jun 2022 17:21:15 +0100 Subject: ASoC: cs35l36: Update digital volume TLV The digital volume TLV specifies the step as 0.25dB but the actual step of the control is 0.125dB. Update the TLV to correct this. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220602162119.3393857-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l36.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c index 920190daa4d1..dfe85dc2cd20 100644 --- a/sound/soc/codecs/cs35l36.c +++ b/sound/soc/codecs/cs35l36.c @@ -444,7 +444,8 @@ static bool cs35l36_volatile_reg(struct device *dev, unsigned int reg) } } -static DECLARE_TLV_DB_SCALE(dig_vol_tlv, -10200, 25, 0); +static const DECLARE_TLV_DB_RANGE(dig_vol_tlv, 0, 912, + TLV_DB_MINMAX_ITEM(-10200, 1200)); static DECLARE_TLV_DB_SCALE(amp_gain_tlv, 0, 1, 1); static const char * const cs35l36_pcm_sftramp_text[] = { -- cgit From 5a7f6cdd402e3da891d2768f1da1f3ea1664a2a2 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 2 Jun 2022 17:21:16 +0100 Subject: ASoC: cs53l30: Correct number of volume levels on SX controls This driver specified the maximum value rather than the number of volume levels on the SX controls, this is incorrect, so correct them. Reported-by: David Rhodes Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220602162119.3393857-4-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs53l30.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index 703545273900..360ca2ffd506 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -348,22 +348,22 @@ static const struct snd_kcontrol_new cs53l30_snd_controls[] = { SOC_ENUM("ADC2 NG Delay", adc2_ng_delay_enum), SOC_SINGLE_SX_TLV("ADC1A PGA Volume", - CS53L30_ADC1A_AFE_CTL, 0, 0x34, 0x18, pga_tlv), + CS53L30_ADC1A_AFE_CTL, 0, 0x34, 0x24, pga_tlv), SOC_SINGLE_SX_TLV("ADC1B PGA Volume", - CS53L30_ADC1B_AFE_CTL, 0, 0x34, 0x18, pga_tlv), + CS53L30_ADC1B_AFE_CTL, 0, 0x34, 0x24, pga_tlv), SOC_SINGLE_SX_TLV("ADC2A PGA Volume", - CS53L30_ADC2A_AFE_CTL, 0, 0x34, 0x18, pga_tlv), + CS53L30_ADC2A_AFE_CTL, 0, 0x34, 0x24, pga_tlv), SOC_SINGLE_SX_TLV("ADC2B PGA Volume", - CS53L30_ADC2B_AFE_CTL, 0, 0x34, 0x18, pga_tlv), + CS53L30_ADC2B_AFE_CTL, 0, 0x34, 0x24, pga_tlv), SOC_SINGLE_SX_TLV("ADC1A Digital Volume", - CS53L30_ADC1A_DIG_VOL, 0, 0xA0, 0x0C, dig_tlv), + CS53L30_ADC1A_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv), SOC_SINGLE_SX_TLV("ADC1B Digital Volume", - CS53L30_ADC1B_DIG_VOL, 0, 0xA0, 0x0C, dig_tlv), + CS53L30_ADC1B_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv), SOC_SINGLE_SX_TLV("ADC2A Digital Volume", - CS53L30_ADC2A_DIG_VOL, 0, 0xA0, 0x0C, dig_tlv), + CS53L30_ADC2A_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv), SOC_SINGLE_SX_TLV("ADC2B Digital Volume", - CS53L30_ADC2B_DIG_VOL, 0, 0xA0, 0x0C, dig_tlv), + CS53L30_ADC2B_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv), }; static const struct snd_soc_dapm_widget cs53l30_dapm_widgets[] = { -- cgit From cd6c0895b9d30b47d22293b9cddab3a8366e4a76 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 2 Jun 2022 17:21:17 +0100 Subject: ASoC: cs42l52: Correct TLV for Bypass Volume The Bypass Volume is accidentally using a -6dB minimum TLV rather than the correct -60dB minimum. Add a new TLV to correct this. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220602162119.3393857-5-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l52.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 02c25399cf8a..10e696406a71 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -137,6 +137,8 @@ static DECLARE_TLV_DB_SCALE(mic_tlv, 1600, 100, 0); static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0); +static DECLARE_TLV_DB_SCALE(pass_tlv, -6000, 50, 0); + static DECLARE_TLV_DB_SCALE(mix_tlv, -5150, 50, 0); static DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0); @@ -351,7 +353,7 @@ static const struct snd_kcontrol_new cs42l52_snd_controls[] = { CS42L52_SPKB_VOL, 0, 0x40, 0xC0, hl_tlv), SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL, - CS42L52_PASSTHRUB_VOL, 0, 0x88, 0x90, pga_tlv), + CS42L52_PASSTHRUB_VOL, 0, 0x88, 0x90, pass_tlv), SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0), -- cgit From 0c9495ee315e13cce3e3eb588efdcb107b566aab Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 2 Jun 2022 17:21:18 +0100 Subject: ASoC: cs42l56: Correct typo in minimum level for SX volume controls A couple of the SX volume controls specify 0x84 as the lowest volume value, however the correct value from the datasheet is 0x44. The datasheet don't include spaces in the value it displays as binary so this was almost certainly just a typo reading 1000100. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220602162119.3393857-6-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l56.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index dc23007336c5..510c94265b1f 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -391,9 +391,9 @@ static const struct snd_kcontrol_new cs42l56_snd_controls[] = { SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1), SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME, - CS42L56_HPB_VOLUME, 0, 0x84, 0x48, hl_tlv), + CS42L56_HPB_VOLUME, 0, 0x44, 0x48, hl_tlv), SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME, - CS42L56_LOB_VOLUME, 0, 0x84, 0x48, hl_tlv), + CS42L56_LOB_VOLUME, 0, 0x44, 0x48, hl_tlv), SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL, 0, 0x00, 1, tone_tlv), -- cgit From 513abe2460de2feaa56a66270efda5fa7a788459 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 2 Jun 2022 17:21:19 +0100 Subject: ASoC: cs42l51: Correct minimum value for SX volume control The minimum value for the PGA Volume is given as 0x1A, however the values from there to 0x19 are all the same volume and this is not represented in the TLV structure. The number of volumes given is correct so this leads to all the volumes being shifted. Move the minimum value up to 0x19 to fix this. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20220602162119.3393857-7-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l51.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index aff618513c75..0e933181b5db 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -143,7 +143,7 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = { 0, 0xA0, 96, adc_att_tlv), SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L51_ALC_PGA_CTL, CS42L51_ALC_PGB_CTL, - 0, 0x1A, 30, pga_tlv), + 0, 0x19, 30, pga_tlv), SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0), SOC_SINGLE("Auto-Mute Switch", CS42L51_DAC_CTL, 2, 1, 0), SOC_SINGLE("Soft Ramp Switch", CS42L51_DAC_CTL, 1, 1, 0), -- cgit From eff8f2aeaf0c1b529d918c9f9569577dff600dc5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:52:57 +0200 Subject: ASoC: cx2072x: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the cx2072x driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-2-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/cx2072x.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index b35debb5818d..b6667e8a6099 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -710,22 +710,19 @@ static int cx2072x_config_i2spcm(struct cx2072x_priv *cx2072x) regdbt2.ulval = 0xac; - /* set master/slave */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: reg2.r.tx_master = 1; reg3.r.rx_master = 1; - dev_dbg(dev, "Sets Master mode\n"); break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: reg2.r.tx_master = 0; reg3.r.rx_master = 0; - dev_dbg(dev, "Sets Slave mode\n"); break; default: - dev_err(dev, "Unsupported DAI master mode\n"); + dev_err(dev, "Unsupported DAI clocking mode\n"); return -EINVAL; } @@ -1009,9 +1006,9 @@ static int cx2072x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) dev_dbg(dev, "set_dai_fmt- %08x\n", fmt); /* set master/slave */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: + case SND_SOC_DAIFMT_CBC_CFC: break; default: -- cgit From 573a9a37b6fcef6dc3977ca11a671f82b1c1b606 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:52:58 +0200 Subject: ASoC: max98090: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the max98090 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-3-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/max98090.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 576277a82d41..72471cdb2229 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -1591,9 +1591,9 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, cdata->fmt = fmt; regval = 0; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* Set to slave mode PLL - MAS mode off */ + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: + /* Set to consumer mode PLL - MAS mode off */ snd_soc_component_write(component, M98090_REG_CLOCK_RATIO_NI_MSB, 0x00); snd_soc_component_write(component, @@ -1602,8 +1602,8 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, M98090_USE_M1_MASK, 0); max98090->master = false; break; - case SND_SOC_DAIFMT_CBM_CFM: - /* Set to master mode */ + case SND_SOC_DAIFMT_CBP_CFP: + /* Set to provider mode */ if (max98090->tdm_slots == 4) { /* TDM */ regval |= M98090_MAS_MASK | @@ -1619,8 +1619,6 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai, } max98090->master = true; break; - case SND_SOC_DAIFMT_CBS_CFM: - case SND_SOC_DAIFMT_CBM_CFS: default: dev_err(component->dev, "DAI clock mode unsupported"); return -EINVAL; -- cgit From cd0df1706d181bf103d0f02e6c008c2386772eb1 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:52:59 +0200 Subject: ASoC: rk3328: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the rk3328 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-4-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/rk3328_codec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c index 86b679cf7aef..1d523bfd9d84 100644 --- a/sound/soc/codecs/rk3328_codec.c +++ b/sound/soc/codecs/rk3328_codec.c @@ -69,11 +69,11 @@ static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) snd_soc_component_get_drvdata(dai->component); unsigned int val; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: val = PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: val = PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER; break; default: -- cgit From ef08b481ae78eb89672bdf67ed306a43065253b3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:00 +0200 Subject: ASoC: sta32x: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the sta32x driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-5-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/sta32x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 8585cbef4c9b..17e5077f26b0 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -601,8 +601,8 @@ static int sta32x_set_dai_fmt(struct snd_soc_dai *codec_dai, struct sta32x_priv *sta32x = snd_soc_component_get_drvdata(component); u8 confb = 0; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; -- cgit From def5b3774a48ed06e69b56af8317cb563bbd9ceb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:01 +0200 Subject: ASoC: sta350: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the sta350 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-6-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/sta350.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index 9189fb3648f7..b2d15d20fe63 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -630,8 +630,8 @@ static int sta350_set_dai_fmt(struct snd_soc_dai *codec_dai, struct sta350_priv *sta350 = snd_soc_component_get_drvdata(component); unsigned int confb = 0; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: break; default: return -EINVAL; -- cgit From d7e98b570e801375130ed4796bcbb35a39669d44 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:02 +0200 Subject: ASoC: sti-sas: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the sti-sas driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-7-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/sti-sas.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c index 3be4940e3c77..10a6a112f4b4 100644 --- a/sound/soc/codecs/sti-sas.c +++ b/sound/soc/codecs/sti-sas.c @@ -199,10 +199,10 @@ static int stih407_sas_dac_mute(struct snd_soc_dai *dai, int mute, int stream) static int sti_sas_spdif_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { - if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { + if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_CBC_CFC) { dev_err(dai->component->dev, - "%s: ERROR: Unsupporter master mask 0x%x\n", - __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK); + "%s: ERROR: Unsupported clocking mask 0x%x\n", + __func__, fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK); return -EINVAL; } -- cgit From 6b486af2ab946cbcad5c95f8daa1f4a8a53f25c5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:03 +0200 Subject: ASoC: tas2552: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tas2552 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-8-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas2552.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index b5c9c61ff5a8..c98a9332dcc0 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -347,17 +347,17 @@ static int tas2552_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct tas2552_data *tas2552 = dev_get_drvdata(component->dev); u8 serial_format; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: serial_format = 0x00; break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: serial_format = TAS2552_WCLKDIR; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: serial_format = TAS2552_BCLKDIR; break; - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBP_CFP: serial_format = (TAS2552_BCLKDIR | TAS2552_WCLKDIR); break; default: -- cgit From f8a4018c826fde6137425bbdbe524d5973feb173 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:04 +0200 Subject: ASoC: tas2770: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tas2770 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-9-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas2770.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index c1dbd978d550..f6037a148cb6 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -340,11 +340,11 @@ static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0; int ret; - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: break; default: - dev_err(tas2770->dev, "ASI format master is not found\n"); + dev_err(tas2770->dev, "ASI invalid DAI clocking\n"); return -EINVAL; } -- cgit From 7c5c399fb97e3f7a88d1b154f610cab4d9253955 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:05 +0200 Subject: ASoC: tas5086: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tas5086 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-10-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas5086.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index 5c0df3cd4832..05b57bb1aea0 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -318,7 +318,7 @@ static int tas5086_set_dai_fmt(struct snd_soc_dai *codec_dai, struct tas5086_private *priv = snd_soc_component_get_drvdata(component); /* The TAS5086 can only be slave to all clocks */ - if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { + if ((format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_CBC_CFC) { dev_err(component->dev, "Invalid clocking mode\n"); return -EINVAL; } -- cgit From 9f6654c3162a4e64265c62bea433550fce4beffd Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:06 +0200 Subject: ASoC: tas5720: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tas5720 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-11-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas5720.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c index 17034abef568..2ee06a95f3e4 100644 --- a/sound/soc/codecs/tas5720.c +++ b/sound/soc/codecs/tas5720.c @@ -89,8 +89,8 @@ static int tas5720_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) u8 serial_format; int ret; - if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { - dev_vdbg(component->dev, "DAI Format master is not found\n"); + if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_CBC_CFC) { + dev_vdbg(component->dev, "DAI clocking invalid\n"); return -EINVAL; } -- cgit From f025fcc466cc03fa4f5ae245b6848629b846edff Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:07 +0200 Subject: ASoC: tas6424: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tas6424 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-12-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas6424.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/tas6424.c b/sound/soc/codecs/tas6424.c index 22b53856e691..9c9a6ec4d977 100644 --- a/sound/soc/codecs/tas6424.c +++ b/sound/soc/codecs/tas6424.c @@ -160,11 +160,11 @@ static int tas6424_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) dev_dbg(component->dev, "%s() fmt=0x%0x\n", __func__, fmt); /* clock masters */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: break; default: - dev_err(component->dev, "Invalid DAI master/slave interface\n"); + dev_err(component->dev, "Invalid DAI clocking\n"); return -EINVAL; } -- cgit From 5fc4ed4bda465fb826bea7c6a7b15657154787ce Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:08 +0200 Subject: ASoC: uda1334: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the uda1334 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-13-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/uda1334.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/uda1334.c b/sound/soc/codecs/uda1334.c index 8670a2a05a56..9d5ed34e5420 100644 --- a/sound/soc/codecs/uda1334.c +++ b/sound/soc/codecs/uda1334.c @@ -169,7 +169,7 @@ static int uda1334_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int uda1334_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { fmt &= (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_INV_MASK | - SND_SOC_DAIFMT_MASTER_MASK); + SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK); if (fmt != (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC)) { -- cgit From ad60ff09801fa1841dcdcf1f6ad1fa0e09ad0693 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:09 +0200 Subject: ASoC: tlv320adc3xxx: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tlv320aic3xxx driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-14-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adc3xxx.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/tlv320adc3xxx.c b/sound/soc/codecs/tlv320adc3xxx.c index 82532ad00c3c..748998e48af9 100644 --- a/sound/soc/codecs/tlv320adc3xxx.c +++ b/sound/soc/codecs/tlv320adc3xxx.c @@ -1252,8 +1252,7 @@ static int adc3xxx_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) int master = 0; int ret; - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { case SND_SOC_DAIFMT_CBP_CFP: master = 1; clkdir = ADC3XXX_BCLK_MASTER | ADC3XXX_WCLK_MASTER; -- cgit From 10649fa392c9abb6e9b258f7af9577596339fbe2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:10 +0200 Subject: ASoC: tlv320adcx140: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tlv320adcx140 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-15-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320adcx140.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index b55f0b836932..de5b184a701e 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -713,16 +713,14 @@ static int adcx140_set_dai_fmt(struct snd_soc_dai *codec_dai, bool inverted_bclk = false; /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: iface_reg2 |= ADCX140_BCLK_FSYNC_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; - case SND_SOC_DAIFMT_CBS_CFM: - case SND_SOC_DAIFMT_CBM_CFS: default: - dev_err(component->dev, "Invalid DAI master/slave interface\n"); + dev_err(component->dev, "Invalid DAI clock provider\n"); return -EINVAL; } -- cgit From b9ff35c7afc6ae1bddca3f84fb23a3d903a62a23 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:11 +0200 Subject: ASoC: tlv320aic23: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tlv320aic23 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Reported-by: kernel test robot Link: https://lore.kernel.org/r/20220602135316.3554400-16-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic23.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 2400093e2c99..c86ca793a2b6 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -429,12 +429,11 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, iface_reg = snd_soc_component_read(component, TLV320AIC23_DIGT_FMT) & (~0x03); - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: iface_reg |= TLV320AIC23_MS_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: iface_reg &= ~TLV320AIC23_MS_MASTER; break; default: -- cgit From 8d322f170b09989f47614c1a663371647f03176f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:12 +0200 Subject: ASoC: tlv320aic26: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tlv320aic26 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Reported-by: kernel test robot Link: https://lore.kernel.org/r/20220602135316.3554400-17-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic26.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 077415a57225..f85f8061639f 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -32,7 +32,7 @@ struct aic26 { struct spi_device *spi; struct regmap *regmap; struct snd_soc_component *component; - int master; + int clock_provider; int datfm; int mclk; @@ -117,8 +117,8 @@ static int aic26_hw_params(struct snd_pcm_substream *substream, reg = dval << 2; snd_soc_component_write(component, AIC26_REG_PLL_PROG2, reg); - /* Audio Control 3 (master mode, fsref rate) */ - if (aic26->master) + /* Audio Control 3 (clock provider mode, fsref rate) */ + if (aic26->clock_provider) reg = 0x0800; if (fsref == 48000) reg = 0x2000; @@ -178,10 +178,9 @@ static int aic26_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) dev_dbg(&aic26->spi->dev, "aic26_set_fmt(dai=%p, fmt==%i)\n", codec_dai, fmt); - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: aic26->master = 1; break; - case SND_SOC_DAIFMT_CBS_CFS: aic26->master = 0; break; + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: aic26->clock_provider = 1; break; + case SND_SOC_DAIFMT_CBC_CFC: aic26->clock_provider = 0; break; default: dev_dbg(&aic26->spi->dev, "bad master\n"); return -EINVAL; } @@ -363,7 +362,7 @@ static int aic26_spi_probe(struct spi_device *spi) /* Initialize the driver data */ aic26->spi = spi; dev_set_drvdata(&spi->dev, aic26); - aic26->master = 1; + aic26->clock_provider = 1; ret = devm_snd_soc_register_component(&spi->dev, &aic26_soc_component_dev, &aic26_dai, 1); -- cgit From 2fd8298aed2228b8c6b94edf820121da25b3f5e2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:13 +0200 Subject: ASoC: tlv320aic31xx: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tlv320aic31xx driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-18-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic31xx.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index b2e59581c17a..aacee2367992 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -1033,8 +1033,8 @@ static int aic31xx_clock_master_routes(struct snd_soc_component *component, struct aic31xx_priv *aic31xx = snd_soc_component_get_drvdata(component); int ret; - fmt &= SND_SOC_DAIFMT_MASTER_MASK; - if (fmt == SND_SOC_DAIFMT_CBS_CFS && + fmt &= SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; + if (fmt == SND_SOC_DAIFMT_CBC_CFC && aic31xx->master_dapm_route_applied) { /* * Remove the DAPM route(s) for codec clock master modes, @@ -1051,7 +1051,7 @@ static int aic31xx_clock_master_routes(struct snd_soc_component *component, return ret; aic31xx->master_dapm_route_applied = false; - } else if (fmt != SND_SOC_DAIFMT_CBS_CFS && + } else if (fmt != SND_SOC_DAIFMT_CBC_CFC && !aic31xx->master_dapm_route_applied) { /* * Add the needed DAPM route(s) for codec clock master modes, @@ -1083,21 +1083,20 @@ static int aic31xx_set_dai_fmt(struct snd_soc_dai *codec_dai, dev_dbg(component->dev, "## %s: fmt = 0x%x\n", __func__, fmt); - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: iface_reg1 |= AIC31XX_BCLK_MASTER | AIC31XX_WCLK_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: iface_reg1 |= AIC31XX_WCLK_MASTER; break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: iface_reg1 |= AIC31XX_BCLK_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: - dev_err(component->dev, "Invalid DAI master/slave interface\n"); + dev_err(component->dev, "Invalid DAI clock provider\n"); return -EINVAL; } -- cgit From 0cc5a137f7a3ba6fec069d8d222020f0927a18ef Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:14 +0200 Subject: ASoC: tlv320aic32x4: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tlv320aic32x4 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-19-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 8f42fd7bc053..a8e6adf62ac8 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -615,15 +615,14 @@ static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) u8 iface_reg_2 = 0; u8 iface_reg_3 = 0; - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: iface_reg_1 |= AIC32X4_BCLKMASTER | AIC32X4_WCLKMASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: break; default: - printk(KERN_ERR "aic32x4: invalid DAI master/slave interface\n"); + printk(KERN_ERR "aic32x4: invalid clock provider\n"); return -EINVAL; } -- cgit From 83a5f86903fbaf9c47c13975eb6f2fbd16d7f865 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:15 +0200 Subject: ASoC: tlv320aic33: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tlv320aic33 driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-20-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index d53037b1509d..610e41bbf388 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1253,22 +1253,21 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, iface_areg = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLA) & 0x3f; iface_breg = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLB) & 0x3f; - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: aic3x->master = 1; iface_areg |= BIT_CLK_MASTER | WORD_CLK_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBC_CFC: aic3x->master = 0; iface_areg &= ~(BIT_CLK_MASTER | WORD_CLK_MASTER); break; - case SND_SOC_DAIFMT_CBM_CFS: + case SND_SOC_DAIFMT_CBP_CFC: aic3x->master = 1; iface_areg |= BIT_CLK_MASTER; iface_areg &= ~WORD_CLK_MASTER; break; - case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBC_CFP: aic3x->master = 1; iface_areg |= WORD_CLK_MASTER; iface_areg &= ~BIT_CLK_MASTER; -- cgit From 894bf75bb1f6c274cdd877879d9215abd6ed4b1b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 2 Jun 2022 15:53:16 +0200 Subject: ASoC: tlv320dac3x: Use modern ASoC DAI format terminology As part of moving to remove the old style defines for the bus clocks update the tlv320dac3x driver to use more modern terminology for clocking. Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220602135316.3554400-21-broonie@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320dac33.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 66f1d1cd6cf0..371026eb8f41 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -1317,16 +1317,14 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai, aictrl_a = dac33_read_reg_cache(component, DAC33_SER_AUDIOIF_CTRL_A); aictrl_b = dac33_read_reg_cache(component, DAC33_SER_AUDIOIF_CTRL_B); - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - /* Codec Master */ + + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: aictrl_a |= (DAC33_MSBCLK | DAC33_MSWCLK); break; - case SND_SOC_DAIFMT_CBS_CFS: - /* Codec Slave */ + case SND_SOC_DAIFMT_CBC_CFC: if (dac33->fifo_mode) { - dev_err(component->dev, "FIFO mode requires master mode\n"); + dev_err(component->dev, "FIFO mode requires provider mode\n"); return -EINVAL; } else aictrl_a &= ~(DAC33_MSBCLK | DAC33_MSWCLK); -- cgit From e059da384ffdc93778e69a5f212c2ac7357ec09a Mon Sep 17 00:00:00 2001 From: Wesley Cheng Date: Thu, 2 Jun 2022 19:14:32 -0700 Subject: dt-bindings: Update QCOM USB subsystem maintainer information Update devicetree binding files with the proper maintainer, and updated contact email. Signed-off-by: Wesley Cheng Acked-by: Krzysztof Kozlowski Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220603021432.13365-1-quic_wcheng@quicinc.com --- Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml | 2 +- Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml | 2 +- Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml | 2 +- .../devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml | 2 +- Documentation/devicetree/bindings/usb/qcom,dwc3.yaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml index 60dc27834e1d..b078009ed509 100644 --- a/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,qmp-usb3-dp-phy.yaml @@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#" title: Qualcomm QMP USB3 DP PHY controller maintainers: - - Manu Gautam + - Wesley Cheng properties: compatible: diff --git a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml index 0ab3dad3f121..d68ab49345b8 100644 --- a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml @@ -8,7 +8,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#" title: Qualcomm QUSB2 phy controller maintainers: - - Manu Gautam + - Wesley Cheng description: QUSB2 controller supports LS/FS/HS usb connectivity on Qualcomm chipsets. diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml b/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml index 1ce251de0855..7a0e6a9854da 100644 --- a/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml +++ b/Documentation/devicetree/bindings/phy/qcom,usb-snps-femto-v2.yaml @@ -7,7 +7,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#" title: Qualcomm Synopsys Femto High-Speed USB PHY V2 maintainers: - - Wesley Cheng + - Wesley Cheng description: | Qualcomm High-Speed USB PHY diff --git a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml index 12ed98c28aaa..dbe78cd4adba 100644 --- a/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml +++ b/Documentation/devicetree/bindings/regulator/qcom,usb-vbus-regulator.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: The Qualcomm PMIC VBUS output regulator driver maintainers: - - Wesley Cheng + - Wesley Cheng description: | This regulator driver controls the VBUS output by the Qualcomm PMIC. This diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml index e336fe2e03cc..749e1963ddbb 100644 --- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm SuperSpeed DWC3 USB SoC controller maintainers: - - Manu Gautam + - Wesley Cheng properties: compatible: -- cgit From 0a884eadc428b9e7070d86e8b22c278bdb52a422 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 1 Jun 2022 15:52:22 +0200 Subject: dt-bindings: vendor-prefixes: document deprecated Atheros Two old boards use "atheros" prefix instead of already documented "qca". Document it as deprecated to fix warnings like: at91-gatwick.dtb: atheros@0: 'atheros,board-id' does not match any of the regexes Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220601135222.205035-1-krzysztof.kozlowski@linaro.org --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 6bb20b4554d7..0496773a3c4d 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -143,6 +143,9 @@ patternProperties: description: ASPEED Technology Inc. "^asus,.*": description: AsusTek Computer Inc. + "^atheros,.*": + description: Qualcomm Atheros, Inc. (deprecated, use qca) + deprecated: true "^atlas,.*": description: Atlas Scientific LLC "^atmel,.*": -- cgit From cce65bb2c36dd32d7bb413636b89a80d85b94196 Mon Sep 17 00:00:00 2001 From: Krishna Manikandan Date: Thu, 2 Jun 2022 16:19:58 +0530 Subject: dt-bindings: msm: update maintainers list with proper id Use quic id instead of codeaurora id in maintainers list for display devicetree bindings. Signed-off-by: Krishna Manikandan Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/1654166998-14907-1-git-send-email-quic_mkrishn@quicinc.com --- Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml | 2 +- Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml | 2 +- Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml | 2 +- Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml | 2 +- Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml | 2 +- Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml | 2 +- Documentation/devicetree/bindings/display/msm/dsi-phy-20nm.yaml | 2 +- Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml | 2 +- Documentation/devicetree/bindings/display/msm/dsi-phy-common.yaml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml index b41991eaa454..d3c3e4b07897 100644 --- a/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml +++ b/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Display DPU dt properties for SC7180 target maintainers: - - Krishna Manikandan + - Krishna Manikandan description: | Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml index 6e417d06fc79..f427eec3d3a4 100644 --- a/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml +++ b/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Display DPU dt properties for SC7280 maintainers: - - Krishna Manikandan + - Krishna Manikandan description: | Device tree bindings for MSM Mobile Display Subsystem (MDSS) that encapsulates diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml index 1a42491efdbc..2bb8896beffc 100644 --- a/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml +++ b/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Display DPU dt properties for SDM845 target maintainers: - - Krishna Manikandan + - Krishna Manikandan description: | Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml index 7095ec3c890d..880bfe930830 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Display DSI controller maintainers: - - Krishna Manikandan + - Krishna Manikandan allOf: - $ref: "../dsi-controller.yaml#" diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml index 2d5a766d028f..716f921e3532 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Display DSI 10nm PHY maintainers: - - Krishna Manikandan + - Krishna Manikandan allOf: - $ref: dsi-phy-common.yaml# diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml index 81dbee4803c0..1342d74ecfe0 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Display DSI 14nm PHY maintainers: - - Krishna Manikandan + - Krishna Manikandan allOf: - $ref: dsi-phy-common.yaml# diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-20nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-20nm.yaml index b8de785ce815..9c1f9140c731 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-phy-20nm.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-20nm.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Display DSI 20nm PHY maintainers: - - Krishna Manikandan + - Krishna Manikandan allOf: - $ref: dsi-phy-common.yaml# diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml index 69eecaa64b18..3d8540a06fe2 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm Display DSI 28nm PHY maintainers: - - Krishna Manikandan + - Krishna Manikandan allOf: - $ref: dsi-phy-common.yaml# diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-common.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-common.yaml index 502bdda90235..76d40f7933dd 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-phy-common.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-common.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Description of Qualcomm Display DSI PHY common dt properties maintainers: - - Krishna Manikandan + - Krishna Manikandan description: | This defines the DSI PHY dt properties which are common for all -- cgit From 216d1a8013433bacb2001d492a467e3a58db91bc Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 3 Jun 2022 17:57:23 +0200 Subject: dt-bindings: update Luca Ceresoli's e-mail address My Bootlin address is preferred from now on. Signed-off-by: Luca Ceresoli Signed-off-by: Luca Ceresoli Acked-by: Rob Herring Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220603155727.1232061-2-luca@lucaceresoli.net --- Documentation/devicetree/bindings/clock/idt,versaclock5.yaml | 2 +- Documentation/devicetree/bindings/mfd/maxim,max77714.yaml | 2 +- Documentation/devicetree/bindings/power/supply/maxim,max77976.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml b/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml index be66f1e8b547..7c331bfbe370 100644 --- a/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml +++ b/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml @@ -45,7 +45,7 @@ description: | The case where SH and SP are both 1 is likely not very interesting. maintainers: - - Luca Ceresoli + - Luca Ceresoli properties: compatible: diff --git a/Documentation/devicetree/bindings/mfd/maxim,max77714.yaml b/Documentation/devicetree/bindings/mfd/maxim,max77714.yaml index 74a6867d3c82..edac14af101e 100644 --- a/Documentation/devicetree/bindings/mfd/maxim,max77714.yaml +++ b/Documentation/devicetree/bindings/mfd/maxim,max77714.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: MAX77714 PMIC with GPIO, RTC and watchdog from Maxim Integrated. maintainers: - - Luca Ceresoli + - Luca Ceresoli description: | MAX77714 is a Power Management IC with 4 buck regulators, 9 diff --git a/Documentation/devicetree/bindings/power/supply/maxim,max77976.yaml b/Documentation/devicetree/bindings/power/supply/maxim,max77976.yaml index 675b9b26d233..f23dcc50793e 100644 --- a/Documentation/devicetree/bindings/power/supply/maxim,max77976.yaml +++ b/Documentation/devicetree/bindings/power/supply/maxim,max77976.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Maxim Integrated MAX77976 Battery charger maintainers: - - Luca Ceresoli + - Luca Ceresoli description: | The Maxim MAX77976 is a 19Vin / 5.5A, 1-Cell Li+ battery charger -- cgit From fa1f57421e0b1c57843902c89728f823abc32f02 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Thu, 2 Jun 2022 22:23:49 +0300 Subject: xen/virtio: Enable restricted memory access using Xen grant mappings In order to support virtio in Xen guests add a config option XEN_VIRTIO enabling the user to specify whether in all Xen guests virtio should be able to access memory via Xen grant mappings only on the host side. Also set PLATFORM_VIRTIO_RESTRICTED_MEM_ACCESS feature from the guest initialization code on Arm and x86 if CONFIG_XEN_VIRTIO is enabled. Signed-off-by: Juergen Gross Signed-off-by: Oleksandr Tyshchenko Reviewed-by: Stefano Stabellini Reviewed-by: Boris Ostrovsky Link: https://lore.kernel.org/r/1654197833-25362-5-git-send-email-olekstysh@gmail.com Signed-off-by: Juergen Gross --- arch/arm/xen/enlighten.c | 2 ++ arch/x86/xen/enlighten_hvm.c | 2 ++ arch/x86/xen/enlighten_pv.c | 2 ++ drivers/xen/Kconfig | 11 +++++++++++ include/xen/xen.h | 8 ++++++++ 5 files changed, 25 insertions(+) diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 07eb69f9e7df..1f9c3ba32833 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -443,6 +443,8 @@ static int __init xen_guest_init(void) if (!xen_domain()) return 0; + xen_set_restricted_virtio_memory_access(); + if (!acpi_disabled) xen_acpi_guest_init(); else diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c index 517a9d8d8f94..8b71b1dd7639 100644 --- a/arch/x86/xen/enlighten_hvm.c +++ b/arch/x86/xen/enlighten_hvm.c @@ -195,6 +195,8 @@ static void __init xen_hvm_guest_init(void) if (xen_pv_domain()) return; + xen_set_restricted_virtio_memory_access(); + init_hvm_pv_info(); reserve_shared_info(); diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index f33a4421e7cd..e3297b15701c 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -109,6 +109,8 @@ static DEFINE_PER_CPU(struct tls_descs, shadow_tls_desc); static void __init xen_pv_init_platform(void) { + xen_set_restricted_virtio_memory_access(); + populate_extra_pte(fix_to_virt(FIX_PARAVIRT_BOOTMAP)); set_fixmap(FIX_PARAVIRT_BOOTMAP, xen_start_info->shared_info); diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 313a9127fd5c..a7bd8ce7a1d2 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -339,4 +339,15 @@ config XEN_GRANT_DMA_OPS bool select DMA_OPS +config XEN_VIRTIO + bool "Xen virtio support" + depends on VIRTIO + select XEN_GRANT_DMA_OPS + help + Enable virtio support for running as Xen guest. Depending on the + guest type this will require special support on the backend side + (qemu or kernel, depending on the virtio device types used). + + If in doubt, say n. + endmenu diff --git a/include/xen/xen.h b/include/xen/xen.h index a99bab817523..0780a81e140d 100644 --- a/include/xen/xen.h +++ b/include/xen/xen.h @@ -52,6 +52,14 @@ bool xen_biovec_phys_mergeable(const struct bio_vec *vec1, extern u64 xen_saved_max_mem_size; #endif +#include + +static inline void xen_set_restricted_virtio_memory_access(void) +{ + if (IS_ENABLED(CONFIG_XEN_VIRTIO) && xen_domain()) + platform_set(PLATFORM_VIRTIO_RESTRICTED_MEM_ACCESS); +} + #ifdef CONFIG_XEN_UNPOPULATED_ALLOC int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages); void xen_free_unpopulated_pages(unsigned int nr_pages, struct page **pages); -- cgit From add413a1d966d8458571a2571881903d234a9f8e Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshchenko Date: Thu, 2 Jun 2022 22:23:50 +0300 Subject: dt-bindings: Add xen,grant-dma IOMMU description for xen-grant DMA ops The main purpose of this binding is to communicate Xen specific information using generic IOMMU device tree bindings (which is a good fit here) rather than introducing a custom property. Introduce Xen specific IOMMU for the virtualized device (e.g. virtio) to be used by Xen grant DMA-mapping layer in the subsequent commit. The reference to Xen specific IOMMU node using "iommus" property indicates that Xen grant mappings need to be enabled for the device, and it specifies the ID of the domain where the corresponding backend resides. The domid (domain ID) is used as an argument to the Xen grant mapping APIs. This is needed for the option to restrict memory access using Xen grant mappings to work which primary goal is to enable using virtio devices in Xen guests. Signed-off-by: Oleksandr Tyshchenko Reviewed-by: Stefano Stabellini Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1654197833-25362-6-git-send-email-olekstysh@gmail.com Signed-off-by: Juergen Gross --- .../devicetree/bindings/iommu/xen,grant-dma.yaml | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Documentation/devicetree/bindings/iommu/xen,grant-dma.yaml diff --git a/Documentation/devicetree/bindings/iommu/xen,grant-dma.yaml b/Documentation/devicetree/bindings/iommu/xen,grant-dma.yaml new file mode 100644 index 000000000000..be1539d234f9 --- /dev/null +++ b/Documentation/devicetree/bindings/iommu/xen,grant-dma.yaml @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iommu/xen,grant-dma.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xen specific IOMMU for virtualized devices (e.g. virtio) + +maintainers: + - Stefano Stabellini + +description: + The Xen IOMMU represents the Xen grant table interface. Grant mappings + are to be used with devices connected to the Xen IOMMU using the "iommus" + property, which also specifies the ID of the backend domain. + The binding is required to restrict memory access using Xen grant mappings. + +properties: + compatible: + const: xen,grant-dma + + '#iommu-cells': + const: 1 + description: + The single cell is the domid (domain ID) of the domain where the backend + is running. + +required: + - compatible + - "#iommu-cells" + +additionalProperties: false + +examples: + - | + iommu { + compatible = "xen,grant-dma"; + #iommu-cells = <1>; + }; -- cgit From 1ca55d50e50c74747a7b8846dac306fbe5ac4cf5 Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshchenko Date: Thu, 2 Jun 2022 22:23:51 +0300 Subject: xen/grant-dma-iommu: Introduce stub IOMMU driver In order to reuse generic IOMMU device tree bindings by Xen grant DMA-mapping layer we need to add this stub driver from a fw_devlink perspective (grant-dma-ops cannot be converted into the proper IOMMU driver). Otherwise, just reusing IOMMU bindings (without having a corresponding driver) leads to the deferred probe timeout afterwards, because the IOMMU device never becomes available. This stub driver does nothing except registering empty iommu_ops, the upper layer "of_iommu" will treat this as NO_IOMMU condition and won't return -EPROBE_DEFER. As this driver is quite different from the most hardware IOMMU implementations and only needed in Xen guests, place it in drivers/xen directory. The subsequent commit will make use of it. Signed-off-by: Oleksandr Tyshchenko Reviewed-by: Stefano Stabellini Link: https://lore.kernel.org/r/1654197833-25362-7-git-send-email-olekstysh@gmail.com Signed-off-by: Juergen Gross --- drivers/xen/Kconfig | 4 +++ drivers/xen/Makefile | 1 + drivers/xen/grant-dma-iommu.c | 78 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 drivers/xen/grant-dma-iommu.c diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index a7bd8ce7a1d2..35d20d90390b 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -335,6 +335,10 @@ config XEN_UNPOPULATED_ALLOC having to balloon out RAM regions in order to obtain physical memory space to create such mappings. +config XEN_GRANT_DMA_IOMMU + bool + select IOMMU_API + config XEN_GRANT_DMA_OPS bool select DMA_OPS diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 1a23cb0dc188..c0503f1c7d5b 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -40,3 +40,4 @@ xen-privcmd-y := privcmd.o privcmd-buf.o obj-$(CONFIG_XEN_FRONT_PGDIR_SHBUF) += xen-front-pgdir-shbuf.o obj-$(CONFIG_XEN_UNPOPULATED_ALLOC) += unpopulated-alloc.o obj-$(CONFIG_XEN_GRANT_DMA_OPS) += grant-dma-ops.o +obj-$(CONFIG_XEN_GRANT_DMA_IOMMU) += grant-dma-iommu.o diff --git a/drivers/xen/grant-dma-iommu.c b/drivers/xen/grant-dma-iommu.c new file mode 100644 index 000000000000..16b8bc0c0b33 --- /dev/null +++ b/drivers/xen/grant-dma-iommu.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Stub IOMMU driver which does nothing. + * The main purpose of it being present is to reuse generic IOMMU device tree + * bindings by Xen grant DMA-mapping layer. + * + * Copyright (C) 2022 EPAM Systems Inc. + */ + +#include +#include +#include + +struct grant_dma_iommu_device { + struct device *dev; + struct iommu_device iommu; +}; + +/* Nothing is really needed here */ +static const struct iommu_ops grant_dma_iommu_ops; + +static const struct of_device_id grant_dma_iommu_of_match[] = { + { .compatible = "xen,grant-dma" }, + { }, +}; + +static int grant_dma_iommu_probe(struct platform_device *pdev) +{ + struct grant_dma_iommu_device *mmu; + int ret; + + mmu = devm_kzalloc(&pdev->dev, sizeof(*mmu), GFP_KERNEL); + if (!mmu) + return -ENOMEM; + + mmu->dev = &pdev->dev; + + ret = iommu_device_register(&mmu->iommu, &grant_dma_iommu_ops, &pdev->dev); + if (ret) + return ret; + + platform_set_drvdata(pdev, mmu); + + return 0; +} + +static int grant_dma_iommu_remove(struct platform_device *pdev) +{ + struct grant_dma_iommu_device *mmu = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + iommu_device_unregister(&mmu->iommu); + + return 0; +} + +static struct platform_driver grant_dma_iommu_driver = { + .driver = { + .name = "grant-dma-iommu", + .of_match_table = grant_dma_iommu_of_match, + }, + .probe = grant_dma_iommu_probe, + .remove = grant_dma_iommu_remove, +}; + +static int __init grant_dma_iommu_init(void) +{ + struct device_node *iommu_np; + + iommu_np = of_find_matching_node(NULL, grant_dma_iommu_of_match); + if (!iommu_np) + return 0; + + of_node_put(iommu_np); + + return platform_driver_register(&grant_dma_iommu_driver); +} +subsys_initcall(grant_dma_iommu_init); -- cgit From 625ab90ecdf7770bda7ae21c4d5c938aa9b43bb4 Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshchenko Date: Thu, 2 Jun 2022 22:23:52 +0300 Subject: xen/grant-dma-ops: Retrieve the ID of backend's domain for DT devices Use the presence of "iommus" property pointed to the IOMMU node with recently introduced "xen,grant-dma" compatible as a clear indicator of enabling Xen grant mappings scheme for that device and read the ID of Xen domain where the corresponding backend is running. The domid (domain ID) is used as an argument to the Xen grant mapping APIs. To avoid the deferred probe timeout which takes place after reusing generic IOMMU device tree bindings (because the IOMMU device never becomes available) enable recently introduced stub IOMMU driver by selecting XEN_GRANT_DMA_IOMMU. Also introduce xen_is_grant_dma_device() to check whether xen-grant DMA ops need to be set for a passed device. Remove the hardcoded domid 0 in xen_grant_setup_dma_ops(). Signed-off-by: Oleksandr Tyshchenko Reviewed-by: Stefano Stabellini Link: https://lore.kernel.org/r/1654197833-25362-8-git-send-email-olekstysh@gmail.com Signed-off-by: Juergen Gross --- drivers/xen/Kconfig | 1 + drivers/xen/grant-dma-ops.c | 48 ++++++++++++++++++++++++++++++++++++++------- include/xen/xen-ops.h | 5 +++++ 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 35d20d90390b..bfd5f4f706bc 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -347,6 +347,7 @@ config XEN_VIRTIO bool "Xen virtio support" depends on VIRTIO select XEN_GRANT_DMA_OPS + select XEN_GRANT_DMA_IOMMU if OF help Enable virtio support for running as Xen guest. Depending on the guest type this will require special support on the backend side diff --git a/drivers/xen/grant-dma-ops.c b/drivers/xen/grant-dma-ops.c index aaff35cda517..fc0142484001 100644 --- a/drivers/xen/grant-dma-ops.c +++ b/drivers/xen/grant-dma-ops.c @@ -56,11 +56,6 @@ static struct xen_grant_dma_data *find_xen_grant_dma_data(struct device *dev) * Such a DMA address is formed by using the grant reference as a frame * number and setting the highest address bit (this bit is for the backend * to be able to distinguish it from e.g. a mmio address). - * - * Note that for now we hard wire dom0 to be the backend domain. In order - * to support any domain as backend we'd need to add a way to communicate - * the domid of this backend, e.g. via Xenstore, via the PCI-device's - * config space or DT/ACPI. */ static void *xen_grant_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp, @@ -276,9 +271,26 @@ static const struct dma_map_ops xen_grant_dma_ops = { .dma_supported = xen_grant_dma_supported, }; +bool xen_is_grant_dma_device(struct device *dev) +{ + struct device_node *iommu_np; + bool has_iommu; + + /* XXX Handle only DT devices for now */ + if (!dev->of_node) + return false; + + iommu_np = of_parse_phandle(dev->of_node, "iommus", 0); + has_iommu = iommu_np && of_device_is_compatible(iommu_np, "xen,grant-dma"); + of_node_put(iommu_np); + + return has_iommu; +} + void xen_grant_setup_dma_ops(struct device *dev) { struct xen_grant_dma_data *data; + struct of_phandle_args iommu_spec; data = find_xen_grant_dma_data(dev); if (data) { @@ -286,12 +298,34 @@ void xen_grant_setup_dma_ops(struct device *dev) return; } + /* XXX ACPI device unsupported for now */ + if (!dev->of_node) + goto err; + + if (of_parse_phandle_with_args(dev->of_node, "iommus", "#iommu-cells", + 0, &iommu_spec)) { + dev_err(dev, "Cannot parse iommus property\n"); + goto err; + } + + if (!of_device_is_compatible(iommu_spec.np, "xen,grant-dma") || + iommu_spec.args_count != 1) { + dev_err(dev, "Incompatible IOMMU node\n"); + of_node_put(iommu_spec.np); + goto err; + } + + of_node_put(iommu_spec.np); + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) goto err; - /* XXX The dom0 is hardcoded as the backend domain for now */ - data->backend_domid = 0; + /* + * The endpoint ID here means the ID of the domain where the corresponding + * backend is running + */ + data->backend_domid = iommu_spec.args[0]; if (xa_err(xa_store(&xen_grant_dma_devices, (unsigned long)dev, data, GFP_KERNEL))) { diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index afd586d717a4..80546960f8b7 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h @@ -216,10 +216,15 @@ static inline void xen_preemptible_hcall_end(void) { } #ifdef CONFIG_XEN_GRANT_DMA_OPS void xen_grant_setup_dma_ops(struct device *dev); +bool xen_is_grant_dma_device(struct device *dev); #else static inline void xen_grant_setup_dma_ops(struct device *dev) { } +static inline bool xen_is_grant_dma_device(struct device *dev) +{ + return false; +} #endif /* CONFIG_XEN_GRANT_DMA_OPS */ #endif /* INCLUDE_XEN_OPS_H */ -- cgit From fea981610c25173e6e5d63ccd4fce49739663ab0 Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshchenko Date: Thu, 2 Jun 2022 22:23:53 +0300 Subject: arm/xen: Assign xen-grant DMA ops for xen-grant DMA devices By assigning xen-grant DMA ops we will restrict memory access for passed device using Xen grant mappings. This is needed for using any virtualized device (e.g. virtio) in Xen guests in a safe manner. Please note, for the virtio devices the XEN_VIRTIO config should be enabled (it forces ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS). Signed-off-by: Oleksandr Tyshchenko Reviewed-by: Stefano Stabellini Link: https://lore.kernel.org/r/1654197833-25362-9-git-send-email-olekstysh@gmail.com Signed-off-by: Juergen Gross --- include/xen/arm/xen-ops.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/xen/arm/xen-ops.h b/include/xen/arm/xen-ops.h index 288deb1c3ac9..b0766a660338 100644 --- a/include/xen/arm/xen-ops.h +++ b/include/xen/arm/xen-ops.h @@ -3,11 +3,14 @@ #define _ASM_ARM_XEN_OPS_H #include +#include static inline void xen_setup_dma_ops(struct device *dev) { #ifdef CONFIG_XEN - if (xen_swiotlb_detect()) + if (xen_is_grant_dma_device(dev)) + xen_grant_setup_dma_ops(dev); + else if (xen_swiotlb_detect()) dev->dma_ops = &xen_swiotlb_dma_ops; #endif } -- cgit From 612c4695e312c753a8b06f6b052cea3d8338e3c3 Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Mon, 23 May 2022 21:28:39 +0800 Subject: ASoC: mediatek: mt6366: support for mt6366 codec Mt6366 is a new version of mt6358, and they are same about audio part. So we can reuse the driver of mt6358 that add a new compatible string inside of the mt6358 driver. Signed-off-by: Jiaxin Yu Link: https://lore.kernel.org/r/20220523132858.22166-2-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6358.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index 60b209efe52d..93f35e8d26fc 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -2479,6 +2479,7 @@ static int mt6358_platform_driver_probe(struct platform_device *pdev) static const struct of_device_id mt6358_of_match[] = { {.compatible = "mediatek,mt6358-sound",}, + {.compatible = "mediatek,mt6366-sound",}, {} }; MODULE_DEVICE_TABLE(of, mt6358_of_match); -- cgit From 58949aa35c0f74a98b03864817354d85f452a51c Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Mon, 23 May 2022 21:28:41 +0800 Subject: ASoC: mediatek: mt8186: support audsys clock control Add mt8186 audio cg control. Audio clock gates are registered to CCF for reference count and clock parent management. Signed-off-by: Jiaxin Yu Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220523132858.22166-4-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-audsys-clk.c | 150 ++++++++++++++++++++++++ sound/soc/mediatek/mt8186/mt8186-audsys-clk.h | 15 +++ sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h | 45 +++++++ 3 files changed, 210 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-audsys-clk.c create mode 100644 sound/soc/mediatek/mt8186/mt8186-audsys-clk.h create mode 100644 sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h diff --git a/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c new file mode 100644 index 000000000000..578969ca91c8 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt8186-audsys-clk.h -- Mediatek 8186 audsys clock control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include +#include +#include "mt8186-afe-common.h" +#include "mt8186-audsys-clk.h" +#include "mt8186-audsys-clkid.h" +#include "mt8186-reg.h" + +struct afe_gate { + int id; + const char *name; + const char *parent_name; + int reg; + u8 bit; + const struct clk_ops *ops; + unsigned long flags; + u8 cg_flags; +}; + +#define GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit, _flags, _cgflags) {\ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .reg = _reg, \ + .bit = _bit, \ + .flags = _flags, \ + .cg_flags = _cgflags, \ + } + +#define GATE_AFE(_id, _name, _parent, _reg, _bit) \ + GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit, \ + CLK_SET_RATE_PARENT, CLK_GATE_SET_TO_DISABLE) + +#define GATE_AUD0(_id, _name, _parent, _bit) \ + GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON0, _bit) + +#define GATE_AUD1(_id, _name, _parent, _bit) \ + GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON1, _bit) + +#define GATE_AUD2(_id, _name, _parent, _bit) \ + GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON2, _bit) + +static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = { + /* AUD0 */ + GATE_AUD0(CLK_AUD_AFE, "aud_afe_clk", "top_audio", 2), + GATE_AUD0(CLK_AUD_22M, "aud_apll22m_clk", "top_aud_engen1", 8), + GATE_AUD0(CLK_AUD_24M, "aud_apll24m_clk", "top_aud_engen2", 9), + GATE_AUD0(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner_clk", "top_aud_engen2", 18), + GATE_AUD0(CLK_AUD_APLL_TUNER, "aud_apll_tuner_clk", "top_aud_engen1", 19), + GATE_AUD0(CLK_AUD_TDM, "aud_tdm_clk", "top_aud_1", 20), + GATE_AUD0(CLK_AUD_ADC, "aud_adc_clk", "top_audio", 24), + GATE_AUD0(CLK_AUD_DAC, "aud_dac_clk", "top_audio", 25), + GATE_AUD0(CLK_AUD_DAC_PREDIS, "aud_dac_predis_clk", "top_audio", 26), + GATE_AUD0(CLK_AUD_TML, "aud_tml_clk", "top_audio", 27), + GATE_AUD0(CLK_AUD_NLE, "aud_nle_clk", "top_audio", 28), + + /* AUD1 */ + GATE_AUD1(CLK_AUD_I2S1_BCLK, "aud_i2s1_bclk", "top_audio", 4), + GATE_AUD1(CLK_AUD_I2S2_BCLK, "aud_i2s2_bclk", "top_audio", 5), + GATE_AUD1(CLK_AUD_I2S3_BCLK, "aud_i2s3_bclk", "top_audio", 6), + GATE_AUD1(CLK_AUD_I2S4_BCLK, "aud_i2s4_bclk", "top_audio", 7), + GATE_AUD1(CLK_AUD_CONNSYS_I2S_ASRC, "aud_connsys_i2s_asrc", "top_audio", 12), + GATE_AUD1(CLK_AUD_GENERAL1_ASRC, "aud_general1_asrc", "top_audio", 13), + GATE_AUD1(CLK_AUD_GENERAL2_ASRC, "aud_general2_asrc", "top_audio", 14), + GATE_AUD1(CLK_AUD_DAC_HIRES, "aud_dac_hires_clk", "top_audio_h", 15), + GATE_AUD1(CLK_AUD_ADC_HIRES, "aud_adc_hires_clk", "top_audio_h", 16), + GATE_AUD1(CLK_AUD_ADC_HIRES_TML, "aud_adc_hires_tml", "top_audio_h", 17), + GATE_AUD1(CLK_AUD_ADDA6_ADC, "aud_adda6_adc", "top_audio", 20), + GATE_AUD1(CLK_AUD_ADDA6_ADC_HIRES, "aud_adda6_adc_hires", "top_audio_h", 21), + GATE_AUD1(CLK_AUD_3RD_DAC, "aud_3rd_dac", "top_audio", 28), + GATE_AUD1(CLK_AUD_3RD_DAC_PREDIS, "aud_3rd_dac_predis", "top_audio", 29), + GATE_AUD1(CLK_AUD_3RD_DAC_TML, "aud_3rd_dac_tml", "top_audio", 30), + GATE_AUD1(CLK_AUD_3RD_DAC_HIRES, "aud_3rd_dac_hires", "top_audio_h", 31), + + /* AUD2 */ + GATE_AUD2(CLK_AUD_ETDM_IN1_BCLK, "aud_etdm_in1_bclk", "top_audio", 23), + GATE_AUD2(CLK_AUD_ETDM_OUT1_BCLK, "aud_etdm_out1_bclk", "top_audio", 24), +}; + +int mt8186_audsys_clk_register(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct clk *clk; + struct clk_lookup *cl; + int i; + + afe_priv->lookup = devm_kcalloc(afe->dev, CLK_AUD_NR_CLK, + sizeof(*afe_priv->lookup), + GFP_KERNEL); + + if (!afe_priv->lookup) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(aud_clks); i++) { + const struct afe_gate *gate = &aud_clks[i]; + + clk = clk_register_gate(afe->dev, gate->name, gate->parent_name, + gate->flags, afe->base_addr + gate->reg, + gate->bit, gate->cg_flags, NULL); + + if (IS_ERR(clk)) { + dev_err(afe->dev, "Failed to register clk %s: %ld\n", + gate->name, PTR_ERR(clk)); + continue; + } + + /* add clk_lookup for devm_clk_get(SND_SOC_DAPM_CLOCK_SUPPLY) */ + cl = kzalloc(sizeof(*cl), GFP_KERNEL); + if (!cl) + return -ENOMEM; + + cl->clk = clk; + cl->con_id = gate->name; + cl->dev_id = dev_name(afe->dev); + clkdev_add(cl); + + afe_priv->lookup[i] = cl; + } + + return 0; +} + +void mt8186_audsys_clk_unregister(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct clk *clk; + struct clk_lookup *cl; + int i; + + if (!afe_priv) + return; + + for (i = 0; i < CLK_AUD_NR_CLK; i++) { + cl = afe_priv->lookup[i]; + if (!cl) + continue; + + clk = cl->clk; + clk_unregister_gate(clk); + + clkdev_drop(cl); + } +} diff --git a/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h new file mode 100644 index 000000000000..b8d6a06e11e8 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * mt8186-audsys-clk.h -- Mediatek 8186 audsys clock definition + * + * Copyright (c) 2022 MediaTek Inc. + * Author: Trevor Wu + */ + +#ifndef _MT8186_AUDSYS_CLK_H_ +#define _MT8186_AUDSYS_CLK_H_ + +int mt8186_audsys_clk_register(struct mtk_base_afe *afe); +void mt8186_audsys_clk_unregister(struct mtk_base_afe *afe); + +#endif diff --git a/sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h b/sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h new file mode 100644 index 000000000000..3ce5937c1823 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * mt8186-audsys-clkid.h -- Mediatek 8186 audsys clock id definition + * + * Copyright (c) 2022 MediaTek Inc. + * Author: Jiaxin Yu + */ + +#ifndef _MT8186_AUDSYS_CLKID_H_ +#define _MT8186_AUDSYS_CLKID_H_ + +enum{ + CLK_AUD_AFE, + CLK_AUD_22M, + CLK_AUD_24M, + CLK_AUD_APLL2_TUNER, + CLK_AUD_APLL_TUNER, + CLK_AUD_TDM, + CLK_AUD_ADC, + CLK_AUD_DAC, + CLK_AUD_DAC_PREDIS, + CLK_AUD_TML, + CLK_AUD_NLE, + CLK_AUD_I2S1_BCLK, + CLK_AUD_I2S2_BCLK, + CLK_AUD_I2S3_BCLK, + CLK_AUD_I2S4_BCLK, + CLK_AUD_CONNSYS_I2S_ASRC, + CLK_AUD_GENERAL1_ASRC, + CLK_AUD_GENERAL2_ASRC, + CLK_AUD_DAC_HIRES, + CLK_AUD_ADC_HIRES, + CLK_AUD_ADC_HIRES_TML, + CLK_AUD_ADDA6_ADC, + CLK_AUD_ADDA6_ADC_HIRES, + CLK_AUD_3RD_DAC, + CLK_AUD_3RD_DAC_PREDIS, + CLK_AUD_3RD_DAC_TML, + CLK_AUD_3RD_DAC_HIRES, + CLK_AUD_ETDM_IN1_BCLK, + CLK_AUD_ETDM_OUT1_BCLK, + CLK_AUD_NR_CLK, +}; + +#endif -- cgit From b65c466220b336f5044c1be75ebc771d087ee7ca Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Mon, 23 May 2022 21:28:42 +0800 Subject: ASoC: mediatek: mt8186: support adda in platform driver Add mt8186 adda dai driver. Signed-off-by: Jiaxin Yu Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220523132858.22166-5-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-dai-adda.c | 873 ++++++++++++++++++++++++++++ 1 file changed, 873 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-adda.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c new file mode 100644 index 000000000000..c66861fd197d --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c @@ -0,0 +1,873 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI ADDA Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include +#include "mt8186-afe-clk.h" +#include "mt8186-afe-common.h" +#include "mt8186-afe-gpio.h" +#include "mt8186-interconnection.h" + +enum { + UL_IIR_SW = 0, + UL_IIR_5HZ, + UL_IIR_10HZ, + UL_IIR_25HZ, + UL_IIR_50HZ, + UL_IIR_75HZ, +}; + +enum { + AUDIO_SDM_LEVEL_MUTE = 0, + AUDIO_SDM_LEVEL_NORMAL = 0x1d, + /* if you change level normal */ + /* you need to change formula of hp impedance and dc trim too */ +}; + +enum { + AUDIO_SDM_2ND = 0, + AUDIO_SDM_3RD, +}; + +enum { + DELAY_DATA_MISO1 = 0, + DELAY_DATA_MISO2, +}; + +enum { + MTK_AFE_ADDA_DL_RATE_8K = 0, + MTK_AFE_ADDA_DL_RATE_11K = 1, + MTK_AFE_ADDA_DL_RATE_12K = 2, + MTK_AFE_ADDA_DL_RATE_16K = 3, + MTK_AFE_ADDA_DL_RATE_22K = 4, + MTK_AFE_ADDA_DL_RATE_24K = 5, + MTK_AFE_ADDA_DL_RATE_32K = 6, + MTK_AFE_ADDA_DL_RATE_44K = 7, + MTK_AFE_ADDA_DL_RATE_48K = 8, + MTK_AFE_ADDA_DL_RATE_96K = 9, + MTK_AFE_ADDA_DL_RATE_192K = 10, +}; + +enum { + MTK_AFE_ADDA_UL_RATE_8K = 0, + MTK_AFE_ADDA_UL_RATE_16K = 1, + MTK_AFE_ADDA_UL_RATE_32K = 2, + MTK_AFE_ADDA_UL_RATE_48K = 3, + MTK_AFE_ADDA_UL_RATE_96K = 4, + MTK_AFE_ADDA_UL_RATE_192K = 5, + MTK_AFE_ADDA_UL_RATE_48K_HD = 6, +}; + +#define SDM_AUTO_RESET_THRESHOLD 0x190000 + +struct mtk_afe_adda_priv { + int dl_rate; + int ul_rate; +}; + +static struct mtk_afe_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe, + const char *name) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id; + + if (strncmp(name, "aud_dac_hires_clk", 7) == 0 || + strncmp(name, "aud_adc_hires_clk", 7) == 0) + dai_id = MT8186_DAI_ADDA; + else + return NULL; + + return afe_priv->dai_priv[dai_id]; +} + +static unsigned int adda_dl_rate_transform(struct mtk_base_afe *afe, + unsigned int rate) +{ + switch (rate) { + case 8000: + return MTK_AFE_ADDA_DL_RATE_8K; + case 11025: + return MTK_AFE_ADDA_DL_RATE_11K; + case 12000: + return MTK_AFE_ADDA_DL_RATE_12K; + case 16000: + return MTK_AFE_ADDA_DL_RATE_16K; + case 22050: + return MTK_AFE_ADDA_DL_RATE_22K; + case 24000: + return MTK_AFE_ADDA_DL_RATE_24K; + case 32000: + return MTK_AFE_ADDA_DL_RATE_32K; + case 44100: + return MTK_AFE_ADDA_DL_RATE_44K; + case 48000: + return MTK_AFE_ADDA_DL_RATE_48K; + case 96000: + return MTK_AFE_ADDA_DL_RATE_96K; + case 192000: + return MTK_AFE_ADDA_DL_RATE_192K; + default: + dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", + __func__, rate); + } + + return MTK_AFE_ADDA_DL_RATE_48K; +} + +static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe, + unsigned int rate) +{ + switch (rate) { + case 8000: + return MTK_AFE_ADDA_UL_RATE_8K; + case 16000: + return MTK_AFE_ADDA_UL_RATE_16K; + case 32000: + return MTK_AFE_ADDA_UL_RATE_32K; + case 48000: + return MTK_AFE_ADDA_UL_RATE_48K; + case 96000: + return MTK_AFE_ADDA_UL_RATE_96K; + case 192000: + return MTK_AFE_ADDA_UL_RATE_192K; + default: + dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", + __func__, rate); + } + + return MTK_AFE_ADDA_UL_RATE_48K; +} + +/* dai component */ +static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN3, I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN3, I_DL12_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN3, I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN3, I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN3_1, I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN3_1, I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN3_1, I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN3_1, I_DL8_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN3, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN3, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN3, + I_GAIN1_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN3, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1 Switch", AFE_CONN3, + I_PCM_2_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN3_1, + I_SRC_1_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_2_OUT_CH1 Switch", AFE_CONN3_1, + I_SRC_2_OUT_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_adda_dl_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN4, I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN4, I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN4, I_DL12_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN4, I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN4, I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN4, I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN4, I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN4_1, I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN4_1, I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN4_1, I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN4_1, I_DL8_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN4, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN4, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN4, + I_GAIN1_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN4, + I_PCM_1_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2 Switch", AFE_CONN4, + I_PCM_2_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN4_1, + I_SRC_1_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_2_OUT_CH2 Switch", AFE_CONN4_1, + I_SRC_2_OUT_CH2, 1, 0), +}; + +enum { + SUPPLY_SEQ_ADDA_AFE_ON, + SUPPLY_SEQ_ADDA_DL_ON, + SUPPLY_SEQ_ADDA_AUD_PAD_TOP, + SUPPLY_SEQ_ADDA_MTKAIF_CFG, + SUPPLY_SEQ_ADDA_FIFO, + SUPPLY_SEQ_ADDA_AP_DMIC, + SUPPLY_SEQ_ADDA_UL_ON, +}; + +static int mtk_adda_ul_src_dmic(struct mtk_base_afe *afe, int id) +{ + unsigned int reg; + + switch (id) { + case MT8186_DAI_ADDA: + case MT8186_DAI_AP_DMIC: + reg = AFE_ADDA_UL_SRC_CON0; + break; + default: + return -EINVAL; + } + + /* dmic mode, 3.25M*/ + regmap_update_bits(afe->regmap, reg, + DIGMIC_3P25M_1P625M_SEL_MASK_SFT, 0); + regmap_update_bits(afe->regmap, reg, + DMIC_LOW_POWER_CTL_MASK_SFT, 0); + + /* turn on dmic, ch1, ch2 */ + regmap_update_bits(afe->regmap, reg, + UL_SDM_3_LEVEL_MASK_SFT, + BIT(UL_SDM_3_LEVEL_SFT)); + regmap_update_bits(afe->regmap, reg, + UL_MODE_3P25M_CH1_CTL_MASK_SFT, + BIT(UL_MODE_3P25M_CH1_CTL_SFT)); + regmap_update_bits(afe->regmap, reg, + UL_MODE_3P25M_CH2_CTL_MASK_SFT, + BIT(UL_MODE_3P25M_CH2_CTL_SFT)); + + return 0; +} + +static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int mtkaif_dmic = afe_priv->mtkaif_dmic; + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x, mtkaif_dmic %d\n", + __func__, w->name, event, mtkaif_dmic); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_ADDA, 1); + + /* update setting to dmic */ + if (mtkaif_dmic) { + /* mtkaif_rxif_data_mode = 1, dmic */ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0, + 0x1, 0x1); + + /* dmic mode, 3.25M*/ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0, + MTKAIF_RXIF_VOICE_MODE_MASK_SFT, + 0x0); + mtk_adda_ul_src_dmic(afe, MT8186_DAI_ADDA); + } + break; + case SND_SOC_DAPM_POST_PMD: + /* should delayed 1/fs(smallest is 8k) = 125us before afe off */ + usleep_range(125, 135); + mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_ADDA, 1); + + /* reset dmic */ + afe_priv->mtkaif_dmic = 0; + break; + default: + break; + } + + return 0; +} + +static int mtk_adda_pad_top_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2_CLK_P2) + regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x39); + else if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2) + regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x31); + else + regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x31); + break; + default: + break; + } + + return 0; +} + +static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int delay_data; + int delay_cycle; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2_CLK_P2) { + /* set protocol 2 */ + regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0x10000); + /* mtkaif_rxif_clkinv_adc inverse */ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_CFG0, + MTKAIF_RXIF_CLKINV_ADC_MASK_SFT, + BIT(MTKAIF_RXIF_CLKINV_ADC_SFT)); + + if (strcmp(w->name, "ADDA_MTKAIF_CFG") == 0) { + if (afe_priv->mtkaif_chosen_phase[0] < 0 && + afe_priv->mtkaif_chosen_phase[1] < 0) { + dev_err(afe->dev, + "%s(), calib fail mtkaif_chosen_phase[0/1]:%d/%d\n", + __func__, + afe_priv->mtkaif_chosen_phase[0], + afe_priv->mtkaif_chosen_phase[1]); + break; + } + + if (afe_priv->mtkaif_chosen_phase[0] < 0 || + afe_priv->mtkaif_chosen_phase[1] < 0) { + dev_err(afe->dev, + "%s(), skip dealy setting mtkaif_chosen_phase[0/1]:%d/%d\n", + __func__, + afe_priv->mtkaif_chosen_phase[0], + afe_priv->mtkaif_chosen_phase[1]); + break; + } + } + + /* set delay for ch12 */ + if (afe_priv->mtkaif_phase_cycle[0] >= + afe_priv->mtkaif_phase_cycle[1]) { + delay_data = DELAY_DATA_MISO1; + delay_cycle = afe_priv->mtkaif_phase_cycle[0] - + afe_priv->mtkaif_phase_cycle[1]; + } else { + delay_data = DELAY_DATA_MISO2; + delay_cycle = afe_priv->mtkaif_phase_cycle[1] - + afe_priv->mtkaif_phase_cycle[0]; + } + + regmap_update_bits(afe->regmap, + AFE_ADDA_MTKAIF_RX_CFG2, + MTKAIF_RXIF_DELAY_DATA_MASK_SFT, + delay_data << + MTKAIF_RXIF_DELAY_DATA_SFT); + + regmap_update_bits(afe->regmap, + AFE_ADDA_MTKAIF_RX_CFG2, + MTKAIF_RXIF_DELAY_CYCLE_MASK_SFT, + delay_cycle << + MTKAIF_RXIF_DELAY_CYCLE_SFT); + + } else if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2) { + regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0x10000); + } else { + regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0); + } + + break; + default: + break; + } + + return 0; +} + +static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_ADDA, 0); + break; + case SND_SOC_DAPM_POST_PMD: + /* should delayed 1/fs(smallest is 8k) = 125us before afe off */ + usleep_range(125, 135); + mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_ADDA, 0); + break; + default: + break; + } + + return 0; +} + +static int mt8186_adda_dmic_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + ucontrol->value.integer.value[0] = afe_priv->mtkaif_dmic; + + return 0; +} + +static int mt8186_adda_dmic_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dmic_on; + + dmic_on = ucontrol->value.integer.value[0]; + + dev_dbg(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n", + __func__, kcontrol->id.name, dmic_on); + + if (afe_priv->mtkaif_dmic == dmic_on) + return 0; + + afe_priv->mtkaif_dmic = dmic_on; + + return 1; +} + +static const struct snd_kcontrol_new mtk_adda_controls[] = { + SOC_SINGLE("ADDA_DL_GAIN", AFE_ADDA_DL_SRC2_CON1, + DL_2_GAIN_CTL_PRE_SFT, DL_2_GAIN_CTL_PRE_MASK, 0), + SOC_SINGLE_BOOL_EXT("MTKAIF_DMIC Switch", 0, + mt8186_adda_dmic_get, mt8186_adda_dmic_set), +}; + +/* ADDA UL MUX */ +enum { + ADDA_UL_MUX_MTKAIF = 0, + ADDA_UL_MUX_AP_DMIC, + ADDA_UL_MUX_MASK = 0x1, +}; + +static const char * const adda_ul_mux_map[] = { + "MTKAIF", "AP_DMIC" +}; + +static int adda_ul_map_value[] = { + ADDA_UL_MUX_MTKAIF, + ADDA_UL_MUX_AP_DMIC, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(adda_ul_mux_map_enum, + SND_SOC_NOPM, + 0, + ADDA_UL_MUX_MASK, + adda_ul_mux_map, + adda_ul_map_value); + +static const struct snd_kcontrol_new adda_ul_mux_control = + SOC_DAPM_ENUM("ADDA_UL_MUX Select", adda_ul_mux_map_enum); + +static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = { + /* inter-connections */ + SND_SOC_DAPM_MIXER("ADDA_DL_CH1", SND_SOC_NOPM, 0, 0, + mtk_adda_dl_ch1_mix, + ARRAY_SIZE(mtk_adda_dl_ch1_mix)), + SND_SOC_DAPM_MIXER("ADDA_DL_CH2", SND_SOC_NOPM, 0, 0, + mtk_adda_dl_ch2_mix, + ARRAY_SIZE(mtk_adda_dl_ch2_mix)), + + SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON, + AFE_ADDA_UL_DL_CON0, ADDA_AFE_ON_SFT, 0, + NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON, + AFE_ADDA_DL_SRC2_CON0, + DL_2_SRC_ON_CTL_PRE_SFT, 0, + mtk_adda_dl_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON, + AFE_ADDA_UL_SRC_CON0, + UL_SRC_ON_CTL_SFT, 0, + mtk_adda_ul_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("AUD_PAD_TOP", SUPPLY_SEQ_ADDA_AUD_PAD_TOP, + 0, 0, 0, + mtk_adda_pad_top_event, + SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_SUPPLY_S("ADDA_MTKAIF_CFG", SUPPLY_SEQ_ADDA_MTKAIF_CFG, + SND_SOC_NOPM, 0, 0, + mtk_adda_mtkaif_cfg_event, + SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_SUPPLY_S("AP_DMIC_EN", SUPPLY_SEQ_ADDA_AP_DMIC, + AFE_ADDA_UL_SRC_CON0, + UL_AP_DMIC_ON_SFT, 0, + NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("ADDA_FIFO", SUPPLY_SEQ_ADDA_FIFO, + AFE_ADDA_UL_DL_CON0, + AFE_ADDA_FIFO_AUTO_RST_SFT, 1, + NULL, 0), + + SND_SOC_DAPM_MUX("ADDA_UL_Mux", SND_SOC_NOPM, 0, 0, + &adda_ul_mux_control), + + SND_SOC_DAPM_INPUT("AP_DMIC_INPUT"), + + /* clock */ + SND_SOC_DAPM_CLOCK_SUPPLY("top_mux_audio_h"), + + SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_clk"), + SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_hires_clk"), + SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_predis_clk"), + + SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_clk"), + SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_hires_clk"), +}; + +#define HIRES_THRESHOLD 48000 +static int mtk_afe_dac_hires_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = source; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_adda_priv *adda_priv; + + adda_priv = get_adda_priv_by_name(afe, w->name); + + if (!adda_priv) { + dev_err(afe->dev, "%s(), adda_priv == NULL", __func__); + return 0; + } + + return (adda_priv->dl_rate > HIRES_THRESHOLD) ? 1 : 0; +} + +static int mtk_afe_adc_hires_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = source; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_adda_priv *adda_priv; + + adda_priv = get_adda_priv_by_name(afe, w->name); + + if (!adda_priv) { + dev_err(afe->dev, "%s(), adda_priv == NULL", __func__); + return 0; + } + + return (adda_priv->ul_rate > HIRES_THRESHOLD) ? 1 : 0; +} + +static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = { + /* playback */ + {"ADDA_DL_CH1", "DL1_CH1 Switch", "DL1"}, + {"ADDA_DL_CH2", "DL1_CH1 Switch", "DL1"}, + {"ADDA_DL_CH2", "DL1_CH2 Switch", "DL1"}, + + {"ADDA_DL_CH1", "DL12_CH1 Switch", "DL12"}, + {"ADDA_DL_CH2", "DL12_CH2 Switch", "DL12"}, + + {"ADDA_DL_CH1", "DL6_CH1 Switch", "DL6"}, + {"ADDA_DL_CH2", "DL6_CH2 Switch", "DL6"}, + + {"ADDA_DL_CH1", "DL8_CH1 Switch", "DL8"}, + {"ADDA_DL_CH2", "DL8_CH2 Switch", "DL8"}, + + {"ADDA_DL_CH1", "DL2_CH1 Switch", "DL2"}, + {"ADDA_DL_CH2", "DL2_CH1 Switch", "DL2"}, + {"ADDA_DL_CH2", "DL2_CH2 Switch", "DL2"}, + + {"ADDA_DL_CH1", "DL3_CH1 Switch", "DL3"}, + {"ADDA_DL_CH2", "DL3_CH1 Switch", "DL3"}, + {"ADDA_DL_CH2", "DL3_CH2 Switch", "DL3"}, + + {"ADDA_DL_CH1", "DL4_CH1 Switch", "DL4"}, + {"ADDA_DL_CH2", "DL4_CH2 Switch", "DL4"}, + + {"ADDA_DL_CH1", "DL5_CH1 Switch", "DL5"}, + {"ADDA_DL_CH2", "DL5_CH2 Switch", "DL5"}, + + {"ADDA Playback", NULL, "ADDA_DL_CH1"}, + {"ADDA Playback", NULL, "ADDA_DL_CH2"}, + + {"ADDA Playback", NULL, "ADDA Enable"}, + {"ADDA Playback", NULL, "ADDA Playback Enable"}, + + /* capture */ + {"ADDA_UL_Mux", "MTKAIF", "ADDA Capture"}, + {"ADDA_UL_Mux", "AP_DMIC", "AP DMIC Capture"}, + + {"ADDA Capture", NULL, "ADDA Enable"}, + {"ADDA Capture", NULL, "ADDA Capture Enable"}, + {"ADDA Capture", NULL, "AUD_PAD_TOP"}, + {"ADDA Capture", NULL, "ADDA_MTKAIF_CFG"}, + + {"AP DMIC Capture", NULL, "ADDA Enable"}, + {"AP DMIC Capture", NULL, "ADDA Capture Enable"}, + {"AP DMIC Capture", NULL, "ADDA_FIFO"}, + {"AP DMIC Capture", NULL, "AP_DMIC_EN"}, + + {"AP DMIC Capture", NULL, "AP_DMIC_INPUT"}, + + /* clk */ + {"ADDA Playback", NULL, "aud_dac_clk"}, + {"ADDA Playback", NULL, "aud_dac_predis_clk"}, + {"ADDA Playback", NULL, "aud_dac_hires_clk", mtk_afe_dac_hires_connect}, + + {"ADDA Capture Enable", NULL, "aud_adc_clk"}, + {"ADDA Capture Enable", NULL, "aud_adc_hires_clk", + mtk_afe_adc_hires_connect}, + + /* hires source from apll1 */ + {"top_mux_audio_h", NULL, APLL2_W_NAME}, + + {"aud_dac_hires_clk", NULL, "top_mux_audio_h"}, + {"aud_adc_hires_clk", NULL, "top_mux_audio_h"}, +}; + +/* dai ops */ +static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + unsigned int rate = params_rate(params); + int id = dai->id; + struct mtk_afe_adda_priv *adda_priv = afe_priv->dai_priv[id]; + + dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n", + __func__, id, substream->stream, rate); + + if (!adda_priv) { + dev_err(afe->dev, "%s(), adda_priv == NULL", __func__); + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + unsigned int dl_src2_con0; + unsigned int dl_src2_con1; + + adda_priv->dl_rate = rate; + + /* set sampling rate */ + dl_src2_con0 = adda_dl_rate_transform(afe, rate) << + DL_2_INPUT_MODE_CTL_SFT; + + /* set output mode, UP_SAMPLING_RATE_X8 */ + dl_src2_con0 |= (0x3 << DL_2_OUTPUT_SEL_CTL_SFT); + + /* turn off mute function */ + dl_src2_con0 |= BIT(DL_2_MUTE_CH2_OFF_CTL_PRE_SFT); + dl_src2_con0 |= BIT(DL_2_MUTE_CH1_OFF_CTL_PRE_SFT); + + /* set voice input data if input sample rate is 8k or 16k */ + if (rate == 8000 || rate == 16000) + dl_src2_con0 |= BIT(DL_2_VOICE_MODE_CTL_PRE_SFT); + + /* SA suggest apply -0.3db to audio/speech path */ + dl_src2_con1 = MTK_AFE_ADDA_DL_GAIN_NORMAL << + DL_2_GAIN_CTL_PRE_SFT; + + /* turn on down-link gain */ + dl_src2_con0 |= BIT(DL_2_GAIN_ON_CTL_PRE_SFT); + + if (id == MT8186_DAI_ADDA) { + /* clean predistortion */ + regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON0, 0); + regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON1, 0); + + regmap_write(afe->regmap, + AFE_ADDA_DL_SRC2_CON0, dl_src2_con0); + regmap_write(afe->regmap, + AFE_ADDA_DL_SRC2_CON1, dl_src2_con1); + + /* set sdm gain */ + regmap_update_bits(afe->regmap, + AFE_ADDA_DL_SDM_DCCOMP_CON, + ATTGAIN_CTL_MASK_SFT, + AUDIO_SDM_LEVEL_NORMAL << + ATTGAIN_CTL_SFT); + + /* Use new 2nd sdm */ + regmap_update_bits(afe->regmap, + AFE_ADDA_DL_SDM_DITHER_CON, + AFE_DL_SDM_DITHER_64TAP_EN_MASK_SFT, + BIT(AFE_DL_SDM_DITHER_64TAP_EN_SFT)); + regmap_update_bits(afe->regmap, + AFE_ADDA_DL_SDM_AUTO_RESET_CON, + AFE_DL_USE_NEW_2ND_SDM_MASK_SFT, + BIT(AFE_DL_USE_NEW_2ND_SDM_SFT)); + regmap_update_bits(afe->regmap, + AFE_ADDA_DL_SDM_DCCOMP_CON, + USE_3RD_SDM_MASK_SFT, + AUDIO_SDM_2ND << USE_3RD_SDM_SFT); + + /* sdm auto reset */ + regmap_write(afe->regmap, + AFE_ADDA_DL_SDM_AUTO_RESET_CON, + SDM_AUTO_RESET_THRESHOLD); + regmap_update_bits(afe->regmap, + AFE_ADDA_DL_SDM_AUTO_RESET_CON, + SDM_AUTO_RESET_TEST_ON_MASK_SFT, + BIT(SDM_AUTO_RESET_TEST_ON_SFT)); + } + } else { + unsigned int ul_src_con0 = 0; + unsigned int voice_mode = adda_ul_rate_transform(afe, rate); + + adda_priv->ul_rate = rate; + ul_src_con0 |= (voice_mode << 17) & (0x7 << 17); + + /* enable iir */ + ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) & + UL_IIR_ON_TMP_CTL_MASK_SFT; + ul_src_con0 |= (UL_IIR_SW << UL_IIRMODE_CTL_SFT) & + UL_IIRMODE_CTL_MASK_SFT; + switch (id) { + case MT8186_DAI_ADDA: + case MT8186_DAI_AP_DMIC: + /* 35Hz @ 48k */ + regmap_write(afe->regmap, + AFE_ADDA_IIR_COEF_02_01, 0); + regmap_write(afe->regmap, + AFE_ADDA_IIR_COEF_04_03, 0x3fb8); + regmap_write(afe->regmap, + AFE_ADDA_IIR_COEF_06_05, 0x3fb80000); + regmap_write(afe->regmap, + AFE_ADDA_IIR_COEF_08_07, 0x3fb80000); + regmap_write(afe->regmap, + AFE_ADDA_IIR_COEF_10_09, 0xc048); + + regmap_write(afe->regmap, + AFE_ADDA_UL_SRC_CON0, ul_src_con0); + + /* Using Internal ADC */ + regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, BIT(0), 0); + + /* mtkaif_rxif_data_mode = 0, amic */ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0, BIT(0), 0); + break; + default: + break; + } + + /* ap dmic */ + switch (id) { + case MT8186_DAI_AP_DMIC: + mtk_adda_ul_src_dmic(afe, id); + break; + default: + break; + } + } + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_adda_ops = { + .hw_params = mtk_dai_adda_hw_params, +}; + +/* dai driver */ +#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 |\ + SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_adda_driver[] = { + { + .name = "ADDA", + .id = MT8186_DAI_ADDA, + .playback = { + .stream_name = "ADDA Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_PLAYBACK_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .capture = { + .stream_name = "ADDA Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_CAPTURE_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, + { + .name = "AP_DMIC", + .id = MT8186_DAI_AP_DMIC, + .capture = { + .stream_name = "AP DMIC Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_CAPTURE_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, +}; + +int mt8186_dai_adda_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_adda_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver); + + dai->controls = mtk_adda_controls; + dai->num_controls = ARRAY_SIZE(mtk_adda_controls); + dai->dapm_widgets = mtk_dai_adda_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets); + dai->dapm_routes = mtk_dai_adda_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes); + + /* set dai priv */ + ret = mt8186_dai_set_priv(afe, MT8186_DAI_ADDA, + sizeof(struct mtk_afe_adda_priv), NULL); + if (ret) + return ret; + + /* ap dmic priv share with adda */ + afe_priv->dai_priv[MT8186_DAI_AP_DMIC] = + afe_priv->dai_priv[MT8186_DAI_ADDA]; + + return 0; +} -- cgit From 55cac93d271166a2aa431d453bf31fdcb19bd5e6 Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Mon, 23 May 2022 21:28:43 +0800 Subject: ASoC: mediatek: mt8186: support hostless in platform driver Add mt8186 hostless dai driver. Signed-off-by: Jiaxin Yu Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220523132858.22166-6-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-dai-hostless.c | 298 ++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-hostless.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-hostless.c b/sound/soc/mediatek/mt8186/mt8186-dai-hostless.c new file mode 100644 index 000000000000..bf0d83840cf4 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-hostless.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI Hostless Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include "mt8186-afe-common.h" + +static const struct snd_pcm_hardware mt8186_hostless_hardware = { + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID), + .period_bytes_min = 256, + .period_bytes_max = 4 * 48 * 1024, + .periods_min = 2, + .periods_max = 256, + .buffer_bytes_max = 4 * 48 * 1024, + .fifo_size = 0, +}; + +/* dai component */ +static const struct snd_soc_dapm_route mtk_dai_hostless_routes[] = { + /* Hostless ADDA Loopback */ + {"ADDA_DL_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, + {"ADDA_DL_CH1", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, + {"ADDA_DL_CH2", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, + {"ADDA_DL_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, + {"I2S1_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, + {"I2S1_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, + {"I2S3_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, + {"I2S3_CH1", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, + {"I2S3_CH2", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, + {"I2S3_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, + {"Hostless LPBK UL", NULL, "ADDA_UL_Mux"}, + + /* Hostelss FM */ + /* connsys_i2s to hw gain 1*/ + {"Hostless FM UL", NULL, "Connsys I2S"}, + + {"HW_GAIN1_IN_CH1", "CONNSYS_I2S_CH1 Switch", "Hostless FM DL"}, + {"HW_GAIN1_IN_CH2", "CONNSYS_I2S_CH2 Switch", "Hostless FM DL"}, + /* hw gain to adda dl */ + {"Hostless FM UL", NULL, "HW Gain 1 Out"}, + + {"ADDA_DL_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"}, + {"ADDA_DL_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"}, + /* hw gain to i2s3 */ + {"I2S3_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"}, + {"I2S3_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"}, + /* hw gain to i2s1 */ + {"I2S1_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"}, + {"I2S1_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"}, + + /* Hostless_SRC */ + {"ADDA_DL_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"}, + {"ADDA_DL_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"}, + {"I2S1_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"}, + {"I2S1_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"}, + {"I2S3_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"}, + {"I2S3_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"}, + {"Hostless_SRC_1_UL", NULL, "HW_SRC_1_Out"}, + + /* Hostless_SRC_bargein */ + {"HW_SRC_1_IN_CH1", "I2S0_CH1 Switch", "Hostless_SRC_Bargein_DL"}, + {"HW_SRC_1_IN_CH2", "I2S0_CH2 Switch", "Hostless_SRC_Bargein_DL"}, + {"Hostless_SRC_Bargein_UL", NULL, "I2S0"}, + + /* Hostless AAudio */ + {"Hostless HW Gain AAudio In", NULL, "HW Gain 2 In"}, + {"Hostless SRC AAudio UL", NULL, "HW Gain 2 Out"}, + {"HW_SRC_2_IN_CH1", "HW_GAIN2_OUT_CH1 Switch", "Hostless SRC AAudio DL"}, + {"HW_SRC_2_IN_CH2", "HW_GAIN2_OUT_CH2 Switch", "Hostless SRC AAudio DL"}, +}; + +/* dai ops */ +static int mtk_dai_hostless_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + snd_soc_set_runtime_hwparams(substream, &mt8186_hostless_hardware); + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n"); + return ret; + } + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_hostless_ops = { + .startup = mtk_dai_hostless_startup, +}; + +/* dai driver */ +#define MTK_HOSTLESS_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_HOSTLESS_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_hostless_driver[] = { + { + .name = "Hostless LPBK DAI", + .id = MT8186_DAI_HOSTLESS_LPBK, + .playback = { + .stream_name = "Hostless LPBK DL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .capture = { + .stream_name = "Hostless LPBK UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless FM DAI", + .id = MT8186_DAI_HOSTLESS_FM, + .playback = { + .stream_name = "Hostless FM DL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .capture = { + .stream_name = "Hostless FM UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless_SRC_1_DAI", + .id = MT8186_DAI_HOSTLESS_SRC_1, + .playback = { + .stream_name = "Hostless_SRC_1_DL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .capture = { + .stream_name = "Hostless_SRC_1_UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless_SRC_Bargein_DAI", + .id = MT8186_DAI_HOSTLESS_SRC_BARGEIN, + .playback = { + .stream_name = "Hostless_SRC_Bargein_DL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .capture = { + .stream_name = "Hostless_SRC_Bargein_UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + /* BE dai */ + { + .name = "Hostless_UL1 DAI", + .id = MT8186_DAI_HOSTLESS_UL1, + .capture = { + .stream_name = "Hostless_UL1 UL", + .channels_min = 1, + .channels_max = 4, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless_UL2 DAI", + .id = MT8186_DAI_HOSTLESS_UL2, + .capture = { + .stream_name = "Hostless_UL2 UL", + .channels_min = 1, + .channels_max = 4, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless_UL3 DAI", + .id = MT8186_DAI_HOSTLESS_UL3, + .capture = { + .stream_name = "Hostless_UL3 UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless_UL5 DAI", + .id = MT8186_DAI_HOSTLESS_UL5, + .capture = { + .stream_name = "Hostless_UL5 UL", + .channels_min = 1, + .channels_max = 12, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless_UL6 DAI", + .id = MT8186_DAI_HOSTLESS_UL6, + .capture = { + .stream_name = "Hostless_UL6 UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless HW Gain AAudio DAI", + .id = MT8186_DAI_HOSTLESS_HW_GAIN_AAUDIO, + .capture = { + .stream_name = "Hostless HW Gain AAudio In", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless SRC AAudio DAI", + .id = MT8186_DAI_HOSTLESS_SRC_AAUDIO, + .playback = { + .stream_name = "Hostless SRC AAudio DL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .capture = { + .stream_name = "Hostless SRC AAudio UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, +}; + +int mt8186_dai_hostless_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_hostless_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_hostless_driver); + + dai->dapm_routes = mtk_dai_hostless_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_hostless_routes); + + return 0; +} -- cgit From 2567ccae9105cbc881828f2ea09954c1b5fd975d Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Mon, 23 May 2022 21:28:44 +0800 Subject: ASoC: mediatek: mt8186: support hw gain in platform driver Add mt8186 hw gain dai driver. Signed-off-by: Jiaxin Yu Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220523132858.22166-7-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c | 236 +++++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c b/sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c new file mode 100644 index 000000000000..33edd6cbde12 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI HW Gain Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include "mt8186-afe-common.h" +#include "mt8186-interconnection.h" + +#define HW_GAIN_1_EN_W_NAME "HW GAIN 1 Enable" +#define HW_GAIN_2_EN_W_NAME "HW GAIN 2 Enable" + +/* dai component */ +static const struct snd_kcontrol_new mtk_hw_gain1_in_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH1 Switch", AFE_CONN13_1, + I_CONNSYS_I2S_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_gain1_in_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH2 Switch", AFE_CONN14_1, + I_CONNSYS_I2S_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_gain2_in_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN15, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_gain2_in_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN16, + I_ADDA_UL_CH2, 1, 0), +}; + +static int mtk_hw_gain_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + unsigned int gain_cur; + unsigned int gain_con1; + + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (strcmp(w->name, HW_GAIN_1_EN_W_NAME) == 0) { + gain_cur = AFE_GAIN1_CUR; + gain_con1 = AFE_GAIN1_CON1; + } else { + gain_cur = AFE_GAIN2_CUR; + gain_con1 = AFE_GAIN2_CON1; + } + + /* let hw gain ramp up, set cur gain to 0 */ + regmap_update_bits(afe->regmap, gain_cur, AFE_GAIN1_CUR_MASK_SFT, 0); + + /* set target gain to 0 */ + regmap_update_bits(afe->regmap, gain_con1, GAIN1_TARGET_MASK_SFT, 0); + break; + default: + break; + } + + return 0; +} + +static const struct snd_soc_dapm_widget mtk_dai_hw_gain_widgets[] = { + /* inter-connections */ + SND_SOC_DAPM_MIXER("HW_GAIN1_IN_CH1", SND_SOC_NOPM, 0, 0, + mtk_hw_gain1_in_ch1_mix, + ARRAY_SIZE(mtk_hw_gain1_in_ch1_mix)), + SND_SOC_DAPM_MIXER("HW_GAIN1_IN_CH2", SND_SOC_NOPM, 0, 0, + mtk_hw_gain1_in_ch2_mix, + ARRAY_SIZE(mtk_hw_gain1_in_ch2_mix)), + SND_SOC_DAPM_MIXER("HW_GAIN2_IN_CH1", SND_SOC_NOPM, 0, 0, + mtk_hw_gain2_in_ch1_mix, + ARRAY_SIZE(mtk_hw_gain2_in_ch1_mix)), + SND_SOC_DAPM_MIXER("HW_GAIN2_IN_CH2", SND_SOC_NOPM, 0, 0, + mtk_hw_gain2_in_ch2_mix, + ARRAY_SIZE(mtk_hw_gain2_in_ch2_mix)), + + SND_SOC_DAPM_SUPPLY(HW_GAIN_1_EN_W_NAME, + AFE_GAIN1_CON0, GAIN1_ON_SFT, 0, + mtk_hw_gain_event, + SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_SUPPLY(HW_GAIN_2_EN_W_NAME, + AFE_GAIN2_CON0, GAIN2_ON_SFT, 0, + mtk_hw_gain_event, + SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_INPUT("HW Gain 1 Out Endpoint"), + SND_SOC_DAPM_INPUT("HW Gain 2 Out Endpoint"), + SND_SOC_DAPM_OUTPUT("HW Gain 1 In Endpoint"), +}; + +static const struct snd_soc_dapm_route mtk_dai_hw_gain_routes[] = { + {"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH1"}, + {"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH2"}, + {"HW Gain 2 In", NULL, "HW_GAIN2_IN_CH1"}, + {"HW Gain 2 In", NULL, "HW_GAIN2_IN_CH2"}, + + {"HW Gain 1 In", NULL, HW_GAIN_1_EN_W_NAME}, + {"HW Gain 1 Out", NULL, HW_GAIN_1_EN_W_NAME}, + {"HW Gain 2 In", NULL, HW_GAIN_2_EN_W_NAME}, + {"HW Gain 2 Out", NULL, HW_GAIN_2_EN_W_NAME}, + + {"HW Gain 1 In Endpoint", NULL, "HW Gain 1 In"}, + {"HW Gain 1 Out", NULL, "HW Gain 1 Out Endpoint"}, + {"HW Gain 2 Out", NULL, "HW Gain 2 Out Endpoint"}, +}; + +static const struct snd_kcontrol_new mtk_hw_gain_controls[] = { + SOC_SINGLE("HW Gain 1 Volume", AFE_GAIN1_CON1, + GAIN1_TARGET_SFT, GAIN1_TARGET_MASK, 0), + SOC_SINGLE("HW Gain 2 Volume", AFE_GAIN2_CON1, + GAIN2_TARGET_SFT, GAIN2_TARGET_MASK, 0), +}; + +/* dai ops */ +static int mtk_dai_gain_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + unsigned int rate = params_rate(params); + unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, dai->id); + + dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n", + __func__, dai->id, substream->stream, rate); + + /* rate */ + regmap_update_bits(afe->regmap, + dai->id == MT8186_DAI_HW_GAIN_1 ? + AFE_GAIN1_CON0 : AFE_GAIN2_CON0, + GAIN1_MODE_MASK_SFT, + rate_reg << GAIN1_MODE_SFT); + + /* sample per step */ + regmap_update_bits(afe->regmap, + dai->id == MT8186_DAI_HW_GAIN_1 ? + AFE_GAIN1_CON0 : AFE_GAIN2_CON0, + GAIN1_SAMPLE_PER_STEP_MASK_SFT, + (dai->id == MT8186_DAI_HW_GAIN_1 ? 0x40 : 0x0) << + GAIN1_SAMPLE_PER_STEP_SFT); + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_gain_ops = { + .hw_params = mtk_dai_gain_hw_params, +}; + +/* dai driver */ +#define MTK_HW_GAIN_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_HW_GAIN_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_gain_driver[] = { + { + .name = "HW Gain 1", + .id = MT8186_DAI_HW_GAIN_1, + .playback = { + .stream_name = "HW Gain 1 In", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HW_GAIN_RATES, + .formats = MTK_HW_GAIN_FORMATS, + }, + .capture = { + .stream_name = "HW Gain 1 Out", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HW_GAIN_RATES, + .formats = MTK_HW_GAIN_FORMATS, + }, + .ops = &mtk_dai_gain_ops, + .symmetric_rate = 1, + .symmetric_channels = 1, + .symmetric_sample_bits = 1, + }, + { + .name = "HW Gain 2", + .id = MT8186_DAI_HW_GAIN_2, + .playback = { + .stream_name = "HW Gain 2 In", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HW_GAIN_RATES, + .formats = MTK_HW_GAIN_FORMATS, + }, + .capture = { + .stream_name = "HW Gain 2 Out", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HW_GAIN_RATES, + .formats = MTK_HW_GAIN_FORMATS, + }, + .ops = &mtk_dai_gain_ops, + .symmetric_rate = 1, + .symmetric_channels = 1, + .symmetric_sample_bits = 1, + }, +}; + +int mt8186_dai_hw_gain_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_gain_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_gain_driver); + + dai->controls = mtk_hw_gain_controls; + dai->num_controls = ARRAY_SIZE(mtk_hw_gain_controls); + dai->dapm_widgets = mtk_dai_hw_gain_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_hw_gain_widgets); + dai->dapm_routes = mtk_dai_hw_gain_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_hw_gain_routes); + return 0; +} -- cgit From 2907d261276e09bd84fdc8bad35930a046a99d4d Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Mon, 23 May 2022 21:28:45 +0800 Subject: ASoC: mediatek: mt8186: support i2s in platform driver Add mt8186 i2s dai driver. Signed-off-by: Jiaxin Yu Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220523132858.22166-8-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-dai-i2s.c | 1286 ++++++++++++++++++++++++++++ 1 file changed, 1286 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-i2s.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c b/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c new file mode 100644 index 000000000000..5c1290b950e8 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c @@ -0,0 +1,1286 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI I2S Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include +#include +#include "mt8186-afe-clk.h" +#include "mt8186-afe-common.h" +#include "mt8186-afe-gpio.h" +#include "mt8186-interconnection.h" + +enum { + I2S_FMT_EIAJ = 0, + I2S_FMT_I2S = 1, +}; + +enum { + I2S_WLEN_16_BIT = 0, + I2S_WLEN_32_BIT = 1, +}; + +enum { + I2S_HD_NORMAL = 0, + I2S_HD_LOW_JITTER = 1, +}; + +enum { + I2S1_SEL_O28_O29 = 0, + I2S1_SEL_O03_O04 = 1, +}; + +enum { + I2S_IN_PAD_CONNSYS = 0, + I2S_IN_PAD_IO_MUX = 1, +}; + +struct mtk_afe_i2s_priv { + int id; + int rate; /* for determine which apll to use */ + int low_jitter_en; + int master; /* only i2s0 has slave mode*/ + + const char *share_property_name; + int share_i2s_id; + + int mclk_id; + int mclk_rate; + int mclk_apll; +}; + +static unsigned int get_i2s_wlen(snd_pcm_format_t format) +{ + return snd_pcm_format_physical_width(format) <= 16 ? + I2S_WLEN_16_BIT : I2S_WLEN_32_BIT; +} + +#define MTK_AFE_I2S0_KCONTROL_NAME "I2S0_HD_Mux" +#define MTK_AFE_I2S1_KCONTROL_NAME "I2S1_HD_Mux" +#define MTK_AFE_I2S2_KCONTROL_NAME "I2S2_HD_Mux" +#define MTK_AFE_I2S3_KCONTROL_NAME "I2S3_HD_Mux" +#define MTK_AFE_I2S0_SRC_KCONTROL_NAME "I2S0_SRC_Mux" + +#define I2S0_HD_EN_W_NAME "I2S0_HD_EN" +#define I2S1_HD_EN_W_NAME "I2S1_HD_EN" +#define I2S2_HD_EN_W_NAME "I2S2_HD_EN" +#define I2S3_HD_EN_W_NAME "I2S3_HD_EN" + +#define I2S0_MCLK_EN_W_NAME "I2S0_MCLK_EN" +#define I2S1_MCLK_EN_W_NAME "I2S1_MCLK_EN" +#define I2S2_MCLK_EN_W_NAME "I2S2_MCLK_EN" +#define I2S3_MCLK_EN_W_NAME "I2S3_MCLK_EN" + +static int get_i2s_id_by_name(struct mtk_base_afe *afe, + const char *name) +{ + if (strncmp(name, "I2S0", 4) == 0) + return MT8186_DAI_I2S_0; + else if (strncmp(name, "I2S1", 4) == 0) + return MT8186_DAI_I2S_1; + else if (strncmp(name, "I2S2", 4) == 0) + return MT8186_DAI_I2S_2; + else if (strncmp(name, "I2S3", 4) == 0) + return MT8186_DAI_I2S_3; + + return -EINVAL; +} + +static struct mtk_afe_i2s_priv *get_i2s_priv_by_name(struct mtk_base_afe *afe, + const char *name) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_i2s_id_by_name(afe, name); + + if (dai_id < 0) + return NULL; + + return afe_priv->dai_priv[dai_id]; +} + +/* low jitter control */ +static const char * const mt8186_i2s_hd_str[] = { + "Normal", "Low_Jitter" +}; + +static const struct soc_enum mt8186_i2s_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_i2s_hd_str), + mt8186_i2s_hd_str), +}; + +static int mt8186_i2s_hd_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return -EINVAL; + } + + ucontrol->value.integer.value[0] = i2s_priv->low_jitter_en; + + return 0; +} + +static int mt8186_i2s_hd_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int hd_en; + + if (ucontrol->value.enumerated.item[0] >= e->items) + return -EINVAL; + + hd_en = ucontrol->value.integer.value[0]; + + dev_dbg(afe->dev, "%s(), kcontrol name %s, hd_en %d\n", + __func__, kcontrol->id.name, hd_en); + + i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return -EINVAL; + } + + if (i2s_priv->low_jitter_en == hd_en) + return 0; + + i2s_priv->low_jitter_en = hd_en; + + return 1; +} + +static const struct snd_kcontrol_new mtk_dai_i2s_controls[] = { + SOC_ENUM_EXT(MTK_AFE_I2S0_KCONTROL_NAME, mt8186_i2s_enum[0], + mt8186_i2s_hd_get, mt8186_i2s_hd_set), + SOC_ENUM_EXT(MTK_AFE_I2S1_KCONTROL_NAME, mt8186_i2s_enum[0], + mt8186_i2s_hd_get, mt8186_i2s_hd_set), + SOC_ENUM_EXT(MTK_AFE_I2S2_KCONTROL_NAME, mt8186_i2s_enum[0], + mt8186_i2s_hd_get, mt8186_i2s_hd_set), + SOC_ENUM_EXT(MTK_AFE_I2S3_KCONTROL_NAME, mt8186_i2s_enum[0], + mt8186_i2s_hd_get, mt8186_i2s_hd_set), +}; + +/* dai component */ +/* i2s virtual mux to output widget */ +static const char * const i2s_mux_map[] = { + "Normal", "Dummy_Widget", +}; + +static int i2s_mux_map_value[] = { + 0, 1, +}; + +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s_mux_map_enum, + SND_SOC_NOPM, + 0, + 1, + i2s_mux_map, + i2s_mux_map_value); + +static const struct snd_kcontrol_new i2s0_in_mux_control = + SOC_DAPM_ENUM("I2S0 In Select", i2s_mux_map_enum); + +static const struct snd_kcontrol_new i2s1_out_mux_control = + SOC_DAPM_ENUM("I2S1 Out Select", i2s_mux_map_enum); + +static const struct snd_kcontrol_new i2s2_in_mux_control = + SOC_DAPM_ENUM("I2S2 In Select", i2s_mux_map_enum); + +static const struct snd_kcontrol_new i2s3_out_mux_control = + SOC_DAPM_ENUM("I2S3 Out Select", i2s_mux_map_enum); + +/* i2s in lpbk */ +static const char * const i2s_lpbk_mux_map[] = { + "Normal", "Lpbk", +}; + +static int i2s_lpbk_mux_map_value[] = { + 0, 1, +}; + +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s0_lpbk_mux_map_enum, + AFE_I2S_CON, + I2S_LOOPBACK_SFT, + 1, + i2s_lpbk_mux_map, + i2s_lpbk_mux_map_value); + +static const struct snd_kcontrol_new i2s0_lpbk_mux_control = + SOC_DAPM_ENUM("I2S Lpbk Select", i2s0_lpbk_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s2_lpbk_mux_map_enum, + AFE_I2S_CON2, + I2S3_LOOPBACK_SFT, + 1, + i2s_lpbk_mux_map, + i2s_lpbk_mux_map_value); + +static const struct snd_kcontrol_new i2s2_lpbk_mux_control = + SOC_DAPM_ENUM("I2S Lpbk Select", i2s2_lpbk_mux_map_enum); + +/* interconnection */ +static const struct snd_kcontrol_new mtk_i2s3_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN0, + I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN0, + I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN0, + I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN0, + I_DL12_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN0, + I_DL12_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN0_1, + I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN0_1, + I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN0_1, + I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN0_1, + I_DL8_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN0, + I_GAIN1_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN0, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN0_1, + I_SRC_1_OUT_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2s3_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN1, + I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN1, + I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN1, + I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN1, + I_DL12_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN1, + I_DL12_CH4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN1_1, + I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN1_1, + I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN1_1, + I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN1_1, + I_DL8_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN1, + I_GAIN1_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN1, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN1, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN1, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN1, + I_PCM_1_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2 Switch", AFE_CONN1, + I_PCM_2_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN1_1, + I_SRC_1_OUT_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2s1_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN28, + I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN28, + I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN28, + I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN28, + I_DL12_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN28, + I_DL12_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN28_1, + I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN28_1, + I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN28_1, + I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN28_1, + I_DL8_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN28, + I_GAIN1_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN28, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN28, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN28_1, + I_SRC_1_OUT_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2s1_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN29, + I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN29, + I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN29, + I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN29, + I_DL12_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN29, + I_DL12_CH4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN29_1, + I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN29_1, + I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN29_1, + I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN29_1, + I_DL8_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN29, + I_GAIN1_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN29, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN29, + I_PCM_1_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2 Switch", AFE_CONN29, + I_PCM_2_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN29_1, + I_SRC_1_OUT_CH2, 1, 0), +}; + +enum { + SUPPLY_SEQ_APLL, + SUPPLY_SEQ_I2S_MCLK_EN, + SUPPLY_SEQ_I2S_HD_EN, + SUPPLY_SEQ_I2S_EN, +}; + +static int mtk_i2s_en_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + i2s_priv = get_i2s_priv_by_name(afe, w->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return -EINVAL; + } + + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_afe_gpio_request(afe->dev, true, i2s_priv->id, 0); + break; + case SND_SOC_DAPM_POST_PMD: + mt8186_afe_gpio_request(afe->dev, false, i2s_priv->id, 0); + break; + default: + break; + } + + return 0; +} + +static int mtk_apll_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (strcmp(w->name, APLL1_W_NAME) == 0) + mt8186_apll1_enable(afe); + else + mt8186_apll2_enable(afe); + break; + case SND_SOC_DAPM_POST_PMD: + if (strcmp(w->name, APLL1_W_NAME) == 0) + mt8186_apll1_disable(afe); + else + mt8186_apll2_disable(afe); + break; + default: + break; + } + + return 0; +} + +static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + i2s_priv = get_i2s_priv_by_name(afe, w->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_mck_enable(afe, i2s_priv->mclk_id, i2s_priv->mclk_rate); + break; + case SND_SOC_DAPM_POST_PMD: + i2s_priv->mclk_rate = 0; + mt8186_mck_disable(afe, i2s_priv->mclk_id); + break; + default: + break; + } + + return 0; +} + +static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = { + SND_SOC_DAPM_INPUT("CONNSYS"), + + SND_SOC_DAPM_MIXER("I2S1_CH1", SND_SOC_NOPM, 0, 0, + mtk_i2s1_ch1_mix, + ARRAY_SIZE(mtk_i2s1_ch1_mix)), + SND_SOC_DAPM_MIXER("I2S1_CH2", SND_SOC_NOPM, 0, 0, + mtk_i2s1_ch2_mix, + ARRAY_SIZE(mtk_i2s1_ch2_mix)), + + SND_SOC_DAPM_MIXER("I2S3_CH1", SND_SOC_NOPM, 0, 0, + mtk_i2s3_ch1_mix, + ARRAY_SIZE(mtk_i2s3_ch1_mix)), + SND_SOC_DAPM_MIXER("I2S3_CH2", SND_SOC_NOPM, 0, 0, + mtk_i2s3_ch2_mix, + ARRAY_SIZE(mtk_i2s3_ch2_mix)), + + /* i2s en*/ + SND_SOC_DAPM_SUPPLY_S("I2S0_EN", SUPPLY_SEQ_I2S_EN, + AFE_I2S_CON, I2S_EN_SFT, 0, + mtk_i2s_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("I2S1_EN", SUPPLY_SEQ_I2S_EN, + AFE_I2S_CON1, I2S_EN_SFT, 0, + mtk_i2s_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("I2S2_EN", SUPPLY_SEQ_I2S_EN, + AFE_I2S_CON2, I2S_EN_SFT, 0, + mtk_i2s_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("I2S3_EN", SUPPLY_SEQ_I2S_EN, + AFE_I2S_CON3, I2S_EN_SFT, 0, + mtk_i2s_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + /* i2s hd en */ + SND_SOC_DAPM_SUPPLY_S(I2S0_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN, + AFE_I2S_CON, I2S1_HD_EN_SFT, 0, NULL, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2S1_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN, + AFE_I2S_CON1, I2S2_HD_EN_SFT, 0, NULL, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2S2_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN, + AFE_I2S_CON2, I2S3_HD_EN_SFT, 0, NULL, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2S3_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN, + AFE_I2S_CON3, I2S4_HD_EN_SFT, 0, NULL, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* i2s mclk en */ + SND_SOC_DAPM_SUPPLY_S(I2S0_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2S1_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2S2_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2S3_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* apll */ + SND_SOC_DAPM_SUPPLY_S(APLL1_W_NAME, SUPPLY_SEQ_APLL, + SND_SOC_NOPM, 0, 0, + mtk_apll_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(APLL2_W_NAME, SUPPLY_SEQ_APLL, + SND_SOC_NOPM, 0, 0, + mtk_apll_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* allow i2s on without codec on */ + SND_SOC_DAPM_OUTPUT("I2S_DUMMY_OUT"), + SND_SOC_DAPM_MUX("I2S1_Out_Mux", + SND_SOC_NOPM, 0, 0, &i2s1_out_mux_control), + SND_SOC_DAPM_MUX("I2S3_Out_Mux", + SND_SOC_NOPM, 0, 0, &i2s3_out_mux_control), + SND_SOC_DAPM_INPUT("I2S_DUMMY_IN"), + SND_SOC_DAPM_MUX("I2S0_In_Mux", + SND_SOC_NOPM, 0, 0, &i2s0_in_mux_control), + SND_SOC_DAPM_MUX("I2S2_In_Mux", + SND_SOC_NOPM, 0, 0, &i2s2_in_mux_control), + + /* i2s in lpbk */ + SND_SOC_DAPM_MUX("I2S0_Lpbk_Mux", + SND_SOC_NOPM, 0, 0, &i2s0_lpbk_mux_control), + SND_SOC_DAPM_MUX("I2S2_Lpbk_Mux", + SND_SOC_NOPM, 0, 0, &i2s2_lpbk_mux_control), +}; + +static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + i2s_priv = get_i2s_priv_by_name(afe, sink->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return 0; + } + + if (i2s_priv->share_i2s_id < 0) + return 0; + + return i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name); +} + +static int mtk_afe_i2s_hd_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + i2s_priv = get_i2s_priv_by_name(afe, sink->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return 0; + } + + if (get_i2s_id_by_name(afe, sink->name) == + get_i2s_id_by_name(afe, source->name)) + return i2s_priv->low_jitter_en; + + /* check if share i2s need hd en */ + if (i2s_priv->share_i2s_id < 0) + return 0; + + if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name)) + return i2s_priv->low_jitter_en; + + return 0; +} + +static int mtk_afe_i2s_apll_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + int cur_apll; + int i2s_need_apll; + + i2s_priv = get_i2s_priv_by_name(afe, w->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return 0; + } + + /* which apll */ + cur_apll = mt8186_get_apll_by_name(afe, source->name); + + /* choose APLL from i2s rate */ + i2s_need_apll = mt8186_get_apll_by_rate(afe, i2s_priv->rate); + + return (i2s_need_apll == cur_apll) ? 1 : 0; +} + +static int mtk_afe_i2s_mclk_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + i2s_priv = get_i2s_priv_by_name(afe, sink->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return 0; + } + + if (get_i2s_id_by_name(afe, sink->name) == + get_i2s_id_by_name(afe, source->name)) + return (i2s_priv->mclk_rate > 0) ? 1 : 0; + + /* check if share i2s need mclk */ + if (i2s_priv->share_i2s_id < 0) + return 0; + + if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name)) + return (i2s_priv->mclk_rate > 0) ? 1 : 0; + + return 0; +} + +static int mtk_afe_mclk_apll_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + int cur_apll; + + i2s_priv = get_i2s_priv_by_name(afe, w->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return 0; + } + + /* which apll */ + cur_apll = mt8186_get_apll_by_name(afe, source->name); + + return (i2s_priv->mclk_apll == cur_apll) ? 1 : 0; +} + +static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = { + {"Connsys I2S", NULL, "CONNSYS"}, + + /* i2s0 */ + {"I2S0", NULL, "I2S0_EN"}, + {"I2S0", NULL, "I2S1_EN", mtk_afe_i2s_share_connect}, + {"I2S0", NULL, "I2S2_EN", mtk_afe_i2s_share_connect}, + {"I2S0", NULL, "I2S3_EN", mtk_afe_i2s_share_connect}, + + {"I2S0", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S0", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S0", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S0", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {I2S0_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {I2S0_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2S0", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S0", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S0", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S0", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2S0_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2S0_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + + /* i2s1 */ + {"I2S1_CH1", "DL1_CH1 Switch", "DL1"}, + {"I2S1_CH2", "DL1_CH2 Switch", "DL1"}, + + {"I2S1_CH1", "DL2_CH1 Switch", "DL2"}, + {"I2S1_CH2", "DL2_CH2 Switch", "DL2"}, + + {"I2S1_CH1", "DL3_CH1 Switch", "DL3"}, + {"I2S1_CH2", "DL3_CH2 Switch", "DL3"}, + + {"I2S1_CH1", "DL12_CH1 Switch", "DL12"}, + {"I2S1_CH2", "DL12_CH2 Switch", "DL12"}, + + {"I2S1_CH1", "DL12_CH3 Switch", "DL12"}, + {"I2S1_CH2", "DL12_CH4 Switch", "DL12"}, + + {"I2S1_CH1", "DL6_CH1 Switch", "DL6"}, + {"I2S1_CH2", "DL6_CH2 Switch", "DL6"}, + + {"I2S1_CH1", "DL4_CH1 Switch", "DL4"}, + {"I2S1_CH2", "DL4_CH2 Switch", "DL4"}, + + {"I2S1_CH1", "DL5_CH1 Switch", "DL5"}, + {"I2S1_CH2", "DL5_CH2 Switch", "DL5"}, + + {"I2S1_CH1", "DL8_CH1 Switch", "DL8"}, + {"I2S1_CH2", "DL8_CH2 Switch", "DL8"}, + + {"I2S1", NULL, "I2S1_CH1"}, + {"I2S1", NULL, "I2S1_CH2"}, + + {"I2S1", NULL, "I2S0_EN", mtk_afe_i2s_share_connect}, + {"I2S1", NULL, "I2S1_EN"}, + {"I2S1", NULL, "I2S2_EN", mtk_afe_i2s_share_connect}, + {"I2S1", NULL, "I2S3_EN", mtk_afe_i2s_share_connect}, + + {"I2S1", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S1", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S1", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S1", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {I2S1_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {I2S1_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2S1", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S1", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S1", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S1", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2S1_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2S1_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + + /* i2s2 */ + {"I2S2", NULL, "I2S0_EN", mtk_afe_i2s_share_connect}, + {"I2S2", NULL, "I2S1_EN", mtk_afe_i2s_share_connect}, + {"I2S2", NULL, "I2S2_EN"}, + {"I2S2", NULL, "I2S3_EN", mtk_afe_i2s_share_connect}, + + {"I2S2", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S2", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S2", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S2", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {I2S2_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {I2S2_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2S2", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S2", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S2", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S2", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2S2_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2S2_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + + /* i2s3 */ + {"I2S3_CH1", "DL1_CH1 Switch", "DL1"}, + {"I2S3_CH2", "DL1_CH2 Switch", "DL1"}, + + {"I2S3_CH1", "DL2_CH1 Switch", "DL2"}, + {"I2S3_CH2", "DL2_CH2 Switch", "DL2"}, + + {"I2S3_CH1", "DL3_CH1 Switch", "DL3"}, + {"I2S3_CH2", "DL3_CH2 Switch", "DL3"}, + + {"I2S3_CH1", "DL12_CH1 Switch", "DL12"}, + {"I2S3_CH2", "DL12_CH2 Switch", "DL12"}, + + {"I2S3_CH1", "DL12_CH3 Switch", "DL12"}, + {"I2S3_CH2", "DL12_CH4 Switch", "DL12"}, + + {"I2S3_CH1", "DL6_CH1 Switch", "DL6"}, + {"I2S3_CH2", "DL6_CH2 Switch", "DL6"}, + + {"I2S3_CH1", "DL4_CH1 Switch", "DL4"}, + {"I2S3_CH2", "DL4_CH2 Switch", "DL4"}, + + {"I2S3_CH1", "DL5_CH1 Switch", "DL5"}, + {"I2S3_CH2", "DL5_CH2 Switch", "DL5"}, + + {"I2S3_CH1", "DL8_CH1 Switch", "DL8"}, + {"I2S3_CH2", "DL8_CH2 Switch", "DL8"}, + + {"I2S3", NULL, "I2S3_CH1"}, + {"I2S3", NULL, "I2S3_CH2"}, + + {"I2S3", NULL, "I2S0_EN", mtk_afe_i2s_share_connect}, + {"I2S3", NULL, "I2S1_EN", mtk_afe_i2s_share_connect}, + {"I2S3", NULL, "I2S2_EN", mtk_afe_i2s_share_connect}, + {"I2S3", NULL, "I2S3_EN"}, + + {"I2S3", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S3", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S3", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S3", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {I2S3_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {I2S3_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2S3", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S3", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S3", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S3", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2S3_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2S3_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + + /* allow i2s on without codec on */ + {"I2S0", NULL, "I2S0_In_Mux"}, + {"I2S0_In_Mux", "Dummy_Widget", "I2S_DUMMY_IN"}, + + {"I2S1_Out_Mux", "Dummy_Widget", "I2S1"}, + {"I2S_DUMMY_OUT", NULL, "I2S1_Out_Mux"}, + + {"I2S2", NULL, "I2S2_In_Mux"}, + {"I2S2_In_Mux", "Dummy_Widget", "I2S_DUMMY_IN"}, + + {"I2S3_Out_Mux", "Dummy_Widget", "I2S3"}, + {"I2S_DUMMY_OUT", NULL, "I2S3_Out_Mux"}, + + /* i2s in lpbk */ + {"I2S0_Lpbk_Mux", "Lpbk", "I2S3"}, + {"I2S2_Lpbk_Mux", "Lpbk", "I2S1"}, + {"I2S0", NULL, "I2S0_Lpbk_Mux"}, + {"I2S2", NULL, "I2S2_Lpbk_Mux"}, +}; + +/* dai ops */ +static int mtk_dai_connsys_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + unsigned int rate = params_rate(params); + unsigned int rate_reg = mt8186_rate_transform(afe->dev, + rate, dai->id); + unsigned int i2s_con = 0; + + dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n", + __func__, dai->id, substream->stream, rate); + + /* non-inverse, i2s mode, slave, 16bits, from connsys */ + i2s_con |= 0 << INV_PAD_CTRL_SFT; + i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT; + i2s_con |= 1 << I2S_SRC_SFT; + i2s_con |= get_i2s_wlen(SNDRV_PCM_FORMAT_S16_LE) << I2S_WLEN_SFT; + i2s_con |= 0 << I2SIN_PAD_SEL_SFT; + regmap_write(afe->regmap, AFE_CONNSYS_I2S_CON, i2s_con); + + /* use asrc */ + regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON, + I2S_BYPSRC_MASK_SFT, 0); + + /* slave mode, set i2s for asrc */ + regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON, + I2S_MODE_MASK_SFT, rate_reg << I2S_MODE_SFT); + + if (rate == 44100) + regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x1b9000); + else if (rate == 32000) + regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x140000); + else + regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x1e0000); + + /* Calibration setting */ + regmap_write(afe->regmap, AFE_ASRC_2CH_CON4, 0x140000); + regmap_write(afe->regmap, AFE_ASRC_2CH_CON9, 0x36000); + regmap_write(afe->regmap, AFE_ASRC_2CH_CON10, 0x2fc00); + regmap_write(afe->regmap, AFE_ASRC_2CH_CON6, 0x7ef4); + regmap_write(afe->regmap, AFE_ASRC_2CH_CON5, 0xff5986); + + /* 0:Stereo 1:Mono */ + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2, + CHSET_IS_MONO_MASK_SFT, 0); + + return 0; +} + +static int mtk_dai_connsys_i2s_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + dev_dbg(afe->dev, "%s(), cmd %d, stream %d\n", + __func__, cmd, substream->stream); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + /* i2s enable */ + regmap_update_bits(afe->regmap, + AFE_CONNSYS_I2S_CON, + I2S_EN_MASK_SFT, + BIT(I2S_EN_SFT)); + + /* calibrator enable */ + regmap_update_bits(afe->regmap, + AFE_ASRC_2CH_CON5, + CALI_EN_MASK_SFT, + BIT(CALI_EN_SFT)); + + /* asrc enable */ + regmap_update_bits(afe->regmap, + AFE_ASRC_2CH_CON0, + CON0_CHSET_STR_CLR_MASK_SFT, + BIT(CON0_CHSET_STR_CLR_SFT)); + regmap_update_bits(afe->regmap, + AFE_ASRC_2CH_CON0, + CON0_ASM_ON_MASK_SFT, + BIT(CON0_ASM_ON_SFT)); + + afe_priv->dai_on[dai->id] = true; + return 0; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0, + CON0_ASM_ON_MASK_SFT, 0); + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5, + CALI_EN_MASK_SFT, 0); + + /* i2s disable */ + regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON, + I2S_EN_MASK_SFT, 0); + + /* bypass asrc */ + regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON, + I2S_BYPSRC_MASK_SFT, BIT(I2S_BYPSRC_SFT)); + + afe_priv->dai_on[dai->id] = false; + return 0; + default: + return -EINVAL; + } + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_connsys_i2s_ops = { + .hw_params = mtk_dai_connsys_i2s_hw_params, + .trigger = mtk_dai_connsys_i2s_trigger, +}; + +/* i2s */ +static int mtk_dai_i2s_config(struct mtk_base_afe *afe, + struct snd_pcm_hw_params *params, + int i2s_id) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[i2s_id]; + + unsigned int rate = params_rate(params); + unsigned int rate_reg = mt8186_rate_transform(afe->dev, + rate, i2s_id); + snd_pcm_format_t format = params_format(params); + unsigned int i2s_con = 0; + int ret; + + dev_dbg(afe->dev, "%s(), id %d, rate %d, format %d\n", + __func__, i2s_id, rate, format); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return -EINVAL; + } + + i2s_priv->rate = rate; + + switch (i2s_id) { + case MT8186_DAI_I2S_0: + i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT; + i2s_con |= rate_reg << I2S_OUT_MODE_SFT; + i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT; + i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT; + regmap_update_bits(afe->regmap, AFE_I2S_CON, + 0xffffeffa, i2s_con); + break; + case MT8186_DAI_I2S_1: + i2s_con = I2S1_SEL_O28_O29 << I2S2_SEL_O03_O04_SFT; + i2s_con |= rate_reg << I2S2_OUT_MODE_SFT; + i2s_con |= I2S_FMT_I2S << I2S2_FMT_SFT; + i2s_con |= get_i2s_wlen(format) << I2S2_WLEN_SFT; + regmap_update_bits(afe->regmap, AFE_I2S_CON1, + 0xffffeffa, i2s_con); + break; + case MT8186_DAI_I2S_2: + i2s_con = 8 << I2S3_UPDATE_WORD_SFT; + i2s_con |= rate_reg << I2S3_OUT_MODE_SFT; + i2s_con |= I2S_FMT_I2S << I2S3_FMT_SFT; + i2s_con |= get_i2s_wlen(format) << I2S3_WLEN_SFT; + regmap_update_bits(afe->regmap, AFE_I2S_CON2, + 0xffffeffa, i2s_con); + break; + case MT8186_DAI_I2S_3: + i2s_con = rate_reg << I2S4_OUT_MODE_SFT; + i2s_con |= I2S_FMT_I2S << I2S4_FMT_SFT; + i2s_con |= get_i2s_wlen(format) << I2S4_WLEN_SFT; + regmap_update_bits(afe->regmap, AFE_I2S_CON3, + 0xffffeffa, i2s_con); + break; + default: + dev_err(afe->dev, "%s(), id %d not support\n", + __func__, i2s_id); + return -EINVAL; + } + + /* set share i2s */ + if (i2s_priv && i2s_priv->share_i2s_id >= 0) { + ret = mtk_dai_i2s_config(afe, params, i2s_priv->share_i2s_id); + if (ret) + return ret; + } + + return 0; +} + +static int mtk_dai_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + + return mtk_dai_i2s_config(afe, params, dai->id); +} + +static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[dai->id]; + int apll; + int apll_rate; + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return -EINVAL; + } + + if (dir != SND_SOC_CLOCK_OUT) { + dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__); + return -EINVAL; + } + + dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq); + + apll = mt8186_get_apll_by_rate(afe, freq); + apll_rate = mt8186_get_apll_rate(afe, apll); + + if (freq > apll_rate) { + dev_err(afe->dev, "%s(), freq > apll rate", __func__); + return -EINVAL; + } + + if (apll_rate % freq != 0) { + dev_err(afe->dev, "%s(), APLL cannot generate freq Hz", __func__); + return -EINVAL; + } + + i2s_priv->mclk_rate = freq; + i2s_priv->mclk_apll = apll; + + if (i2s_priv->share_i2s_id > 0) { + struct mtk_afe_i2s_priv *share_i2s_priv; + + share_i2s_priv = afe_priv->dai_priv[i2s_priv->share_i2s_id]; + if (!share_i2s_priv) { + dev_err(afe->dev, "%s(), share_i2s_priv == NULL", __func__); + return -EINVAL; + } + + share_i2s_priv->mclk_rate = i2s_priv->mclk_rate; + share_i2s_priv->mclk_apll = i2s_priv->mclk_apll; + } + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_i2s_ops = { + .hw_params = mtk_dai_i2s_hw_params, + .set_sysclk = mtk_dai_i2s_set_sysclk, +}; + +/* dai driver */ +#define MTK_CONNSYS_I2S_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) + +#define MTK_I2S_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = { + { + .name = "CONNSYS_I2S", + .id = MT8186_DAI_CONNSYS_I2S, + .capture = { + .stream_name = "Connsys I2S", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_CONNSYS_I2S_RATES, + .formats = MTK_I2S_FORMATS, + }, + .ops = &mtk_dai_connsys_i2s_ops, + }, + { + .name = "I2S0", + .id = MT8186_DAI_I2S_0, + .capture = { + .stream_name = "I2S0", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_I2S_RATES, + .formats = MTK_I2S_FORMATS, + }, + .ops = &mtk_dai_i2s_ops, + }, + { + .name = "I2S1", + .id = MT8186_DAI_I2S_1, + .playback = { + .stream_name = "I2S1", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_I2S_RATES, + .formats = MTK_I2S_FORMATS, + }, + .ops = &mtk_dai_i2s_ops, + }, + { + .name = "I2S2", + .id = MT8186_DAI_I2S_2, + .capture = { + .stream_name = "I2S2", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_I2S_RATES, + .formats = MTK_I2S_FORMATS, + }, + .ops = &mtk_dai_i2s_ops, + }, + { + .name = "I2S3", + .id = MT8186_DAI_I2S_3, + .playback = { + .stream_name = "I2S3", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_I2S_RATES, + .formats = MTK_I2S_FORMATS, + }, + .ops = &mtk_dai_i2s_ops, + } +}; + +/* this enum is merely for mtk_afe_i2s_priv declare */ +enum { + DAI_I2S0 = 0, + DAI_I2S1, + DAI_I2S2, + DAI_I2S3, + DAI_I2S_NUM, +}; + +static const struct mtk_afe_i2s_priv mt8186_i2s_priv[DAI_I2S_NUM] = { + [DAI_I2S0] = { + .id = MT8186_DAI_I2S_0, + .mclk_id = MT8186_I2S0_MCK, + .share_property_name = "i2s0-share", + .share_i2s_id = -1, + }, + [DAI_I2S1] = { + .id = MT8186_DAI_I2S_1, + .mclk_id = MT8186_I2S1_MCK, + .share_property_name = "i2s1-share", + .share_i2s_id = -1, + }, + [DAI_I2S2] = { + .id = MT8186_DAI_I2S_2, + .mclk_id = MT8186_I2S2_MCK, + .share_property_name = "i2s2-share", + .share_i2s_id = -1, + }, + [DAI_I2S3] = { + .id = MT8186_DAI_I2S_3, + /* clock gate naming is hf_faud_i2s4_m_ck*/ + .mclk_id = MT8186_I2S4_MCK, + .share_property_name = "i2s3-share", + .share_i2s_id = -1, + } +}; + +static int mt8186_dai_i2s_get_share(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + const struct device_node *of_node = afe->dev->of_node; + const char *of_str; + const char *property_name; + struct mtk_afe_i2s_priv *i2s_priv; + int i; + + for (i = 0; i < DAI_I2S_NUM; i++) { + i2s_priv = afe_priv->dai_priv[mt8186_i2s_priv[i].id]; + property_name = mt8186_i2s_priv[i].share_property_name; + if (of_property_read_string(of_node, property_name, &of_str)) + continue; + i2s_priv->share_i2s_id = get_i2s_id_by_name(afe, of_str); + } + + return 0; +} + +static int mt8186_dai_i2s_set_priv(struct mtk_base_afe *afe) +{ + int i; + int ret; + + for (i = 0; i < DAI_I2S_NUM; i++) { + ret = mt8186_dai_set_priv(afe, mt8186_i2s_priv[i].id, + sizeof(struct mtk_afe_i2s_priv), + &mt8186_i2s_priv[i]); + if (ret) + return ret; + } + + return 0; +} + +int mt8186_dai_i2s_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + int ret; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_i2s_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver); + + dai->controls = mtk_dai_i2s_controls; + dai->num_controls = ARRAY_SIZE(mtk_dai_i2s_controls); + dai->dapm_widgets = mtk_dai_i2s_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets); + dai->dapm_routes = mtk_dai_i2s_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes); + + /* set all dai i2s private data */ + ret = mt8186_dai_i2s_set_priv(afe); + if (ret) + return ret; + + /* parse share i2s */ + ret = mt8186_dai_i2s_get_share(afe); + if (ret) + return ret; + + return 0; +} -- cgit From 920508f9fe2fc90f19916d74f4c23088030d32e0 Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Mon, 23 May 2022 21:28:46 +0800 Subject: ASoC: mediatek: mt8186: support pcm in platform driver Add mt8186 pcm dai driver. Signed-off-by: Jiaxin Yu Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20220523132858.22166-9-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-dai-pcm.c | 423 +++++++++++++++++++++++++++++ 1 file changed, 423 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-pcm.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c b/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c new file mode 100644 index 000000000000..0b0032ecfe6d --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c @@ -0,0 +1,423 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI I2S Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include +#include "mt8186-afe-common.h" +#include "mt8186-afe-gpio.h" +#include "mt8186-interconnection.h" + +struct mtk_afe_pcm_priv { + unsigned int id; + unsigned int fmt; + unsigned int bck_invert; + unsigned int lck_invert; +}; + +enum aud_tx_lch_rpt { + AUD_TX_LCH_RPT_NO_REPEAT = 0, + AUD_TX_LCH_RPT_REPEAT = 1 +}; + +enum aud_vbt_16k_mode { + AUD_VBT_16K_MODE_DISABLE = 0, + AUD_VBT_16K_MODE_ENABLE = 1 +}; + +enum aud_ext_modem { + AUD_EXT_MODEM_SELECT_INTERNAL = 0, + AUD_EXT_MODEM_SELECT_EXTERNAL = 1 +}; + +enum aud_pcm_sync_type { + /* bck sync length = 1 */ + AUD_PCM_ONE_BCK_CYCLE_SYNC = 0, + /* bck sync length = PCM_INTF_CON1[9:13] */ + AUD_PCM_EXTENDED_BCK_CYCLE_SYNC = 1 +}; + +enum aud_bt_mode { + AUD_BT_MODE_DUAL_MIC_ON_TX = 0, + AUD_BT_MODE_SINGLE_MIC_ON_TX = 1 +}; + +enum aud_pcm_afifo_src { + /* slave mode & external modem uses different crystal */ + AUD_PCM_AFIFO_ASRC = 0, + /* slave mode & external modem uses the same crystal */ + AUD_PCM_AFIFO_AFIFO = 1 +}; + +enum aud_pcm_clock_source { + AUD_PCM_CLOCK_MASTER_MODE = 0, + AUD_PCM_CLOCK_SLAVE_MODE = 1 +}; + +enum aud_pcm_wlen { + AUD_PCM_WLEN_PCM_32_BCK_CYCLES = 0, + AUD_PCM_WLEN_PCM_64_BCK_CYCLES = 1 +}; + +enum aud_pcm_24bit { + AUD_PCM_24BIT_PCM_16_BITS = 0, + AUD_PCM_24BIT_PCM_24_BITS = 1 +}; + +enum aud_pcm_mode { + AUD_PCM_MODE_PCM_MODE_8K = 0, + AUD_PCM_MODE_PCM_MODE_16K = 1, + AUD_PCM_MODE_PCM_MODE_32K = 2, + AUD_PCM_MODE_PCM_MODE_48K = 3, +}; + +enum aud_pcm_fmt { + AUD_PCM_FMT_I2S = 0, + AUD_PCM_FMT_EIAJ = 1, + AUD_PCM_FMT_PCM_MODE_A = 2, + AUD_PCM_FMT_PCM_MODE_B = 3 +}; + +enum aud_bclk_out_inv { + AUD_BCLK_OUT_INV_NO_INVERSE = 0, + AUD_BCLK_OUT_INV_INVERSE = 1 +}; + +enum aud_lrclk_out_inv { + AUD_LRCLK_OUT_INV_NO_INVERSE = 0, + AUD_LRCLK_OUT_INV_INVERSE = 1 +}; + +enum aud_pcm_en { + AUD_PCM_EN_DISABLE = 0, + AUD_PCM_EN_ENABLE = 1 +}; + +/* dai component */ +static const struct snd_kcontrol_new mtk_pcm_1_playback_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN7, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN7, + I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN7_1, + I_DL4_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_pcm_1_playback_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN8, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN8, + I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN8_1, + I_DL4_CH2, 1, 0), +}; + +static int mtk_pcm_en_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_PCM, 0); + break; + case SND_SOC_DAPM_POST_PMD: + mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_PCM, 0); + break; + } + + return 0; +} + +/* pcm in/out lpbk */ +static const char * const pcm_lpbk_mux_map[] = { + "Normal", "Lpbk", +}; + +static int pcm_lpbk_mux_map_value[] = { + 0, 1, +}; + +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(pcm_in_lpbk_mux_map_enum, + PCM_INTF_CON1, + PCM_I2S_PCM_LOOPBACK_SFT, + 1, + pcm_lpbk_mux_map, + pcm_lpbk_mux_map_value); + +static const struct snd_kcontrol_new pcm_in_lpbk_mux_control = + SOC_DAPM_ENUM("PCM In Lpbk Select", pcm_in_lpbk_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(pcm_out_lpbk_mux_map_enum, + PCM_INTF_CON1, + PCM_I2S_PCM_LOOPBACK_SFT, + 1, + pcm_lpbk_mux_map, + pcm_lpbk_mux_map_value); + +static const struct snd_kcontrol_new pcm_out_lpbk_mux_control = + SOC_DAPM_ENUM("PCM Out Lpbk Select", pcm_out_lpbk_mux_map_enum); + +static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = { + /* inter-connections */ + SND_SOC_DAPM_MIXER("PCM_1_PB_CH1", SND_SOC_NOPM, 0, 0, + mtk_pcm_1_playback_ch1_mix, + ARRAY_SIZE(mtk_pcm_1_playback_ch1_mix)), + SND_SOC_DAPM_MIXER("PCM_1_PB_CH2", SND_SOC_NOPM, 0, 0, + mtk_pcm_1_playback_ch2_mix, + ARRAY_SIZE(mtk_pcm_1_playback_ch2_mix)), + + SND_SOC_DAPM_SUPPLY("PCM_1_EN", + PCM_INTF_CON1, PCM_EN_SFT, 0, + mtk_pcm_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* pcm in lpbk */ + SND_SOC_DAPM_MUX("PCM_In_Lpbk_Mux", + SND_SOC_NOPM, 0, 0, &pcm_in_lpbk_mux_control), + + /* pcm out lpbk */ + SND_SOC_DAPM_MUX("PCM_Out_Lpbk_Mux", + SND_SOC_NOPM, 0, 0, &pcm_out_lpbk_mux_control), +}; + +static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = { + {"PCM 1 Playback", NULL, "PCM_1_PB_CH1"}, + {"PCM 1 Playback", NULL, "PCM_1_PB_CH2"}, + + {"PCM 1 Playback", NULL, "PCM_1_EN"}, + {"PCM 1 Capture", NULL, "PCM_1_EN"}, + + {"PCM_1_PB_CH1", "DL2_CH1 Switch", "DL2"}, + {"PCM_1_PB_CH2", "DL2_CH2 Switch", "DL2"}, + + {"PCM_1_PB_CH1", "DL4_CH1 Switch", "DL4"}, + {"PCM_1_PB_CH2", "DL4_CH2 Switch", "DL4"}, + + /* pcm out lpbk */ + {"PCM_Out_Lpbk_Mux", "Lpbk", "PCM 1 Playback"}, + {"I2S0", NULL, "PCM_Out_Lpbk_Mux"}, + + /* pcm in lpbk */ + {"PCM_In_Lpbk_Mux", "Lpbk", "PCM 1 Capture"}, + {"I2S3", NULL, "PCM_In_Lpbk_Mux"}, +}; + +/* dai ops */ +static int mtk_dai_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int pcm_id = dai->id; + struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[pcm_id]; + unsigned int rate = params_rate(params); + unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, dai->id); + snd_pcm_format_t format = params_format(params); + unsigned int data_width = + snd_pcm_format_width(format); + unsigned int wlen_width = + snd_pcm_format_physical_width(format); + unsigned int pcm_con = 0; + + dev_dbg(afe->dev, "%s(), id %d, stream %d, widget active p %d, c %d\n", + __func__, dai->id, substream->stream, dai->playback_widget->active, + dai->capture_widget->active); + dev_dbg(afe->dev, "%s(), rate %d, rate_reg %d, data_width %d, wlen_width %d\n", + __func__, rate, rate_reg, data_width, wlen_width); + + if (dai->playback_widget->active || dai->capture_widget->active) + return 0; + + switch (dai->id) { + case MT8186_DAI_PCM: + pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT << PCM_TX_LCH_RPT_SFT; + pcm_con |= AUD_VBT_16K_MODE_DISABLE << PCM_VBT_16K_MODE_SFT; + pcm_con |= AUD_EXT_MODEM_SELECT_EXTERNAL << PCM_EXT_MODEM_SFT; + pcm_con |= AUD_PCM_ONE_BCK_CYCLE_SYNC << PCM_SYNC_TYPE_SFT; + pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM_BT_MODE_SFT; + pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM_BYP_ASRC_SFT; + pcm_con |= AUD_PCM_CLOCK_MASTER_MODE << PCM_SLAVE_SFT; + pcm_con |= 0 << PCM_SYNC_LENGTH_SFT; + + /* sampling rate */ + pcm_con |= rate_reg << PCM_MODE_SFT; + + /* format */ + pcm_con |= pcm_priv->fmt << PCM_FMT_SFT; + + /* 24bit data width */ + if (data_width > 16) + pcm_con |= AUD_PCM_24BIT_PCM_24_BITS << PCM_24BIT_SFT; + else + pcm_con |= AUD_PCM_24BIT_PCM_16_BITS << PCM_24BIT_SFT; + + /* wlen width*/ + if (wlen_width > 16) + pcm_con |= AUD_PCM_WLEN_PCM_64_BCK_CYCLES << PCM_WLEN_SFT; + else + pcm_con |= AUD_PCM_WLEN_PCM_32_BCK_CYCLES << PCM_WLEN_SFT; + + /* clock invert */ + pcm_con |= pcm_priv->lck_invert << PCM_SYNC_OUT_INV_SFT; + pcm_con |= pcm_priv->bck_invert << PCM_BCLK_OUT_INV_SFT; + + regmap_update_bits(afe->regmap, PCM_INTF_CON1, 0xfffffffe, pcm_con); + break; + default: + dev_err(afe->dev, "%s(), id %d not support\n", __func__, dai->id); + return -EINVAL; + } + + return 0; +} + +static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[dai->id]; + + if (!pcm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + /* DAI mode*/ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + pcm_priv->fmt = AUD_PCM_FMT_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + pcm_priv->fmt = AUD_PCM_FMT_EIAJ; + break; + case SND_SOC_DAIFMT_DSP_A: + pcm_priv->fmt = AUD_PCM_FMT_PCM_MODE_A; + break; + case SND_SOC_DAIFMT_DSP_B: + pcm_priv->fmt = AUD_PCM_FMT_PCM_MODE_B; + break; + default: + pcm_priv->fmt = AUD_PCM_FMT_I2S; + } + + /* DAI clock inversion*/ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE; + pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE; + break; + case SND_SOC_DAIFMT_NB_IF: + pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE; + pcm_priv->lck_invert = AUD_BCLK_OUT_INV_INVERSE; + break; + case SND_SOC_DAIFMT_IB_NF: + pcm_priv->bck_invert = AUD_BCLK_OUT_INV_INVERSE; + pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE; + break; + case SND_SOC_DAIFMT_IB_IF: + pcm_priv->bck_invert = AUD_BCLK_OUT_INV_INVERSE; + pcm_priv->lck_invert = AUD_BCLK_OUT_INV_INVERSE; + break; + default: + pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE; + pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE; + break; + } + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_pcm_ops = { + .hw_params = mtk_dai_pcm_hw_params, + .set_fmt = mtk_dai_pcm_set_fmt, +}; + +/* dai driver */ +#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 |\ + SNDRV_PCM_RATE_48000) + +#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = { + { + .name = "PCM 1", + .id = MT8186_DAI_PCM, + .playback = { + .stream_name = "PCM 1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .capture = { + .stream_name = "PCM 1 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mtk_dai_pcm_ops, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, + }, +}; + +static struct mtk_afe_pcm_priv *init_pcm_priv_data(struct mtk_base_afe *afe) +{ + struct mtk_afe_pcm_priv *pcm_priv; + + pcm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_pcm_priv), + GFP_KERNEL); + if (!pcm_priv) + return NULL; + + pcm_priv->id = MT8186_DAI_PCM; + pcm_priv->fmt = AUD_PCM_FMT_I2S; + pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE; + pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE; + + return pcm_priv; +} + +int mt8186_dai_pcm_register(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_pcm_priv *pcm_priv; + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_pcm_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver); + + dai->dapm_widgets = mtk_dai_pcm_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets); + dai->dapm_routes = mtk_dai_pcm_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes); + + pcm_priv = init_pcm_priv_data(afe); + if (!pcm_priv) + return -ENOMEM; + + afe_priv->dai_priv[MT8186_DAI_PCM] = pcm_priv; + + return 0; +} -- cgit From e118015db7bd0dad1744221d0fe18333ebf9c622 Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Mon, 23 May 2022 21:28:47 +0800 Subject: ASoC: mediatek: mt8186: support src in platform driver Add mt8186 src dai driver Signed-off-by: Jiaxin Yu Link: https://lore.kernel.org/r/20220523132858.22166-10-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-dai-src.c | 695 +++++++++++++++++++++++++++++ 1 file changed, 695 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-src.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-src.c b/sound/soc/mediatek/mt8186/mt8186-dai-src.c new file mode 100644 index 000000000000..67989ffd67ca --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-src.c @@ -0,0 +1,695 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI SRC Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include "mt8186-afe-common.h" +#include "mt8186-interconnection.h" + +struct mtk_afe_src_priv { + int dl_rate; + int ul_rate; +}; + +static const unsigned int src_iir_coeff_32_to_16[] = { + 0x0dbae6, 0xff9b0a, 0x0dbae6, 0x05e488, 0xe072b9, 0x000002, + 0x0dbae6, 0x000f3b, 0x0dbae6, 0x06a537, 0xe17d79, 0x000002, + 0x0dbae6, 0x01246a, 0x0dbae6, 0x087261, 0xe306be, 0x000002, + 0x0dbae6, 0x03437d, 0x0dbae6, 0x0bc16f, 0xe57c87, 0x000002, + 0x0dbae6, 0x072981, 0x0dbae6, 0x111dd3, 0xe94f2a, 0x000002, + 0x0dbae6, 0x0dc4a6, 0x0dbae6, 0x188611, 0xee85a0, 0x000002, + 0x0dbae6, 0x168b9a, 0x0dbae6, 0x200e8f, 0xf3ccf1, 0x000002, + 0x000000, 0x1b75cb, 0x1b75cb, 0x2374a2, 0x000000, 0x000001 +}; + +static const unsigned int src_iir_coeff_44_to_16[] = { + 0x09ae28, 0xf7d97d, 0x09ae28, 0x212a3d, 0xe0ac3a, 0x000002, + 0x09ae28, 0xf8525a, 0x09ae28, 0x216d72, 0xe234be, 0x000002, + 0x09ae28, 0xf980f5, 0x09ae28, 0x22a057, 0xe45a81, 0x000002, + 0x09ae28, 0xfc0a08, 0x09ae28, 0x24d3bd, 0xe7752d, 0x000002, + 0x09ae28, 0x016162, 0x09ae28, 0x27da01, 0xeb6ea8, 0x000002, + 0x09ae28, 0x0b67df, 0x09ae28, 0x2aca4a, 0xef34c4, 0x000002, + 0x000000, 0x135c50, 0x135c50, 0x2c1079, 0x000000, 0x000001 +}; + +static const unsigned int src_iir_coeff_44_to_32[] = { + 0x096966, 0x0c4d35, 0x096966, 0xedee81, 0xf05070, 0x000003, + 0x12d2cc, 0x193910, 0x12d2cc, 0xddbf4f, 0xe21e1d, 0x000002, + 0x12d2cc, 0x1a9e60, 0x12d2cc, 0xe18916, 0xe470fd, 0x000002, + 0x12d2cc, 0x1d06e0, 0x12d2cc, 0xe8a4a6, 0xe87b24, 0x000002, + 0x12d2cc, 0x207578, 0x12d2cc, 0xf4fe62, 0xef5917, 0x000002, + 0x12d2cc, 0x24055f, 0x12d2cc, 0x05ee2b, 0xf8b502, 0x000002, + 0x000000, 0x25a599, 0x25a599, 0x0fabe2, 0x000000, 0x000001 +}; + +static const unsigned int src_iir_coeff_48_to_16[] = { + 0x0296a4, 0xfd69dd, 0x0296a4, 0x209439, 0xe01ff9, 0x000002, + 0x0f4ff3, 0xf0d6d4, 0x0f4ff3, 0x209bc9, 0xe076c3, 0x000002, + 0x0e8490, 0xf1fe63, 0x0e8490, 0x20cfd6, 0xe12124, 0x000002, + 0x14852f, 0xed794a, 0x14852f, 0x21503d, 0xe28b32, 0x000002, + 0x136222, 0xf17677, 0x136222, 0x225be1, 0xe56964, 0x000002, + 0x0a8d85, 0xfc4a97, 0x0a8d85, 0x24310c, 0xea6952, 0x000002, + 0x05eff5, 0x043455, 0x05eff5, 0x4ced8f, 0xe134d6, 0x000001, + 0x000000, 0x3aebe6, 0x3aebe6, 0x04f3b0, 0x000000, 0x000004 +}; + +static const unsigned int src_iir_coeff_48_to_32[] = { + 0x10c1b8, 0x10a7df, 0x10c1b8, 0xe7514e, 0xe0b41f, 0x000002, + 0x10c1b8, 0x116257, 0x10c1b8, 0xe9402f, 0xe25aaa, 0x000002, + 0x10c1b8, 0x130c89, 0x10c1b8, 0xed3cc3, 0xe4dddb, 0x000002, + 0x10c1b8, 0x1600dd, 0x10c1b8, 0xf48000, 0xe90c55, 0x000002, + 0x10c1b8, 0x1a672e, 0x10c1b8, 0x00494c, 0xefa807, 0x000002, + 0x10c1b8, 0x1f38e6, 0x10c1b8, 0x0ee076, 0xf7c5f3, 0x000002, + 0x000000, 0x218370, 0x218370, 0x168b40, 0x000000, 0x000001 +}; + +static const unsigned int src_iir_coeff_48_to_44[] = { + 0x0bf71c, 0x170f3f, 0x0bf71c, 0xe3a4c8, 0xf096cb, 0x000003, + 0x0bf71c, 0x17395e, 0x0bf71c, 0xe58085, 0xf210c8, 0x000003, + 0x0bf71c, 0x1782bd, 0x0bf71c, 0xe95ef6, 0xf4c899, 0x000003, + 0x0bf71c, 0x17cd97, 0x0bf71c, 0xf1608a, 0xfa3b18, 0x000003, + 0x000000, 0x2fdc6f, 0x2fdc6f, 0xf15663, 0x000000, 0x000001 +}; + +static const unsigned int src_iir_coeff_96_to_16[] = { + 0x0805a1, 0xf21ae3, 0x0805a1, 0x3840bb, 0xe02a2e, 0x000002, + 0x0d5dd8, 0xe8f259, 0x0d5dd8, 0x1c0af6, 0xf04700, 0x000003, + 0x0bb422, 0xec08d9, 0x0bb422, 0x1bfccc, 0xf09216, 0x000003, + 0x08fde6, 0xf108be, 0x08fde6, 0x1bf096, 0xf10ae0, 0x000003, + 0x0ae311, 0xeeeda3, 0x0ae311, 0x37c646, 0xe385f5, 0x000002, + 0x044089, 0xfa7242, 0x044089, 0x37a785, 0xe56526, 0x000002, + 0x00c75c, 0xffb947, 0x00c75c, 0x378ba3, 0xe72c5f, 0x000002, + 0x000000, 0x0ef76e, 0x0ef76e, 0x377fda, 0x000000, 0x000001, +}; + +static const unsigned int src_iir_coeff_96_to_44[] = { + 0x08b543, 0xfd80f4, 0x08b543, 0x0e2332, 0xe06ed0, 0x000002, + 0x1b6038, 0xf90e7e, 0x1b6038, 0x0ec1ac, 0xe16f66, 0x000002, + 0x188478, 0xfbb921, 0x188478, 0x105859, 0xe2e596, 0x000002, + 0x13eff3, 0xffa707, 0x13eff3, 0x13455c, 0xe533b7, 0x000002, + 0x0dc239, 0x03d458, 0x0dc239, 0x17f120, 0xe8b617, 0x000002, + 0x0745f1, 0x05d790, 0x0745f1, 0x1e3d75, 0xed5f18, 0x000002, + 0x05641f, 0x085e2b, 0x05641f, 0x48efd0, 0xe3e9c8, 0x000001, + 0x000000, 0x28f632, 0x28f632, 0x273905, 0x000000, 0x000001, +}; + +static unsigned int mtk_get_src_freq_mode(struct mtk_base_afe *afe, int rate) +{ + switch (rate) { + case 8000: + return 0x50000; + case 11025: + return 0x6e400; + case 12000: + return 0x78000; + case 16000: + return 0xa0000; + case 22050: + return 0xdc800; + case 24000: + return 0xf0000; + case 32000: + return 0x140000; + case 44100: + return 0x1b9000; + case 48000: + return 0x1e0000; + case 88200: + return 0x372000; + case 96000: + return 0x3c0000; + case 176400: + return 0x6e4000; + case 192000: + return 0x780000; + default: + dev_err(afe->dev, "%s(), rate %d invalid!!!\n", + __func__, rate); + return 0; + } +} + +static const unsigned int *get_iir_coeff(unsigned int rate_in, + unsigned int rate_out, + unsigned int *param_num) +{ + if (rate_in == 32000 && rate_out == 16000) { + *param_num = ARRAY_SIZE(src_iir_coeff_32_to_16); + return src_iir_coeff_32_to_16; + } else if (rate_in == 44100 && rate_out == 16000) { + *param_num = ARRAY_SIZE(src_iir_coeff_44_to_16); + return src_iir_coeff_44_to_16; + } else if (rate_in == 44100 && rate_out == 32000) { + *param_num = ARRAY_SIZE(src_iir_coeff_44_to_32); + return src_iir_coeff_44_to_32; + } else if ((rate_in == 48000 && rate_out == 16000) || + (rate_in == 96000 && rate_out == 32000)) { + *param_num = ARRAY_SIZE(src_iir_coeff_48_to_16); + return src_iir_coeff_48_to_16; + } else if (rate_in == 48000 && rate_out == 32000) { + *param_num = ARRAY_SIZE(src_iir_coeff_48_to_32); + return src_iir_coeff_48_to_32; + } else if (rate_in == 48000 && rate_out == 44100) { + *param_num = ARRAY_SIZE(src_iir_coeff_48_to_44); + return src_iir_coeff_48_to_44; + } else if (rate_in == 96000 && rate_out == 16000) { + *param_num = ARRAY_SIZE(src_iir_coeff_96_to_16); + return src_iir_coeff_96_to_16; + } else if ((rate_in == 96000 && rate_out == 44100) || + (rate_in == 48000 && rate_out == 22050)) { + *param_num = ARRAY_SIZE(src_iir_coeff_96_to_44); + return src_iir_coeff_96_to_44; + } + + *param_num = 0; + return NULL; +} + +static int mtk_set_src_1_param(struct mtk_base_afe *afe, int id) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id]; + unsigned int iir_coeff_num; + unsigned int iir_stage; + int rate_in = src_priv->dl_rate; + int rate_out = src_priv->ul_rate; + unsigned int out_freq_mode = mtk_get_src_freq_mode(afe, rate_out); + unsigned int in_freq_mode = mtk_get_src_freq_mode(afe, rate_in); + + /* set out freq mode */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON3, + G_SRC_ASM_FREQ_4_MASK_SFT, + out_freq_mode << G_SRC_ASM_FREQ_4_SFT); + + /* set in freq mode */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON4, + G_SRC_ASM_FREQ_5_MASK_SFT, + in_freq_mode << G_SRC_ASM_FREQ_5_SFT); + + regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON5, 0x3f5986); + regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON5, 0x3f5987); + regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON6, 0x1fbd); + regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2, 0); + + /* set iir if in_rate > out_rate */ + if (rate_in > rate_out) { + int i; + const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out, + &iir_coeff_num); + + if (iir_coeff_num == 0 || !iir_coeff) { + dev_err(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n", + __func__, iir_coeff_num, iir_coeff); + return -EINVAL; + } + + /* COEFF_SRAM_CTRL */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0, + G_SRC_COEFF_SRAM_CTRL_MASK_SFT, + BIT(G_SRC_COEFF_SRAM_CTRL_SFT)); + /* Clear coeff history to r/w coeff from the first position */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON13, + G_SRC_COEFF_SRAM_ADR_MASK_SFT, 0); + /* Write SRC coeff, should not read the reg during write */ + for (i = 0; i < iir_coeff_num; i++) + regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON12, + iir_coeff[i]); + /* disable sram access */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0, + G_SRC_COEFF_SRAM_CTRL_MASK_SFT, 0); + /* CHSET_IIR_STAGE */ + iir_stage = (iir_coeff_num / 6) - 1; + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2, + G_SRC_CHSET_IIR_STAGE_MASK_SFT, + iir_stage << G_SRC_CHSET_IIR_STAGE_SFT); + /* CHSET_IIR_EN */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2, + G_SRC_CHSET_IIR_EN_MASK_SFT, + BIT(G_SRC_CHSET_IIR_EN_SFT)); + } else { + /* CHSET_IIR_EN off */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2, + G_SRC_CHSET_IIR_EN_MASK_SFT, 0); + } + + return 0; +} + +static int mtk_set_src_2_param(struct mtk_base_afe *afe, int id) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id]; + unsigned int iir_coeff_num; + unsigned int iir_stage; + int rate_in = src_priv->dl_rate; + int rate_out = src_priv->ul_rate; + unsigned int out_freq_mode = mtk_get_src_freq_mode(afe, rate_out); + unsigned int in_freq_mode = mtk_get_src_freq_mode(afe, rate_in); + + /* set out freq mode */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON3, + G_SRC_ASM_FREQ_4_MASK_SFT, + out_freq_mode << G_SRC_ASM_FREQ_4_SFT); + + /* set in freq mode */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON4, + G_SRC_ASM_FREQ_5_MASK_SFT, + in_freq_mode << G_SRC_ASM_FREQ_5_SFT); + + regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON5, 0x3f5986); + regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON5, 0x3f5987); + regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON6, 0x1fbd); + regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2, 0); + + /* set iir if in_rate > out_rate */ + if (rate_in > rate_out) { + int i; + const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out, + &iir_coeff_num); + + if (iir_coeff_num == 0 || !iir_coeff) { + dev_err(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n", + __func__, iir_coeff_num, iir_coeff); + return -EINVAL; + } + + /* COEFF_SRAM_CTRL */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0, + G_SRC_COEFF_SRAM_CTRL_MASK_SFT, + BIT(G_SRC_COEFF_SRAM_CTRL_SFT)); + /* Clear coeff history to r/w coeff from the first position */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON13, + G_SRC_COEFF_SRAM_ADR_MASK_SFT, 0); + /* Write SRC coeff, should not read the reg during write */ + for (i = 0; i < iir_coeff_num; i++) + regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON12, + iir_coeff[i]); + /* disable sram access */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0, + G_SRC_COEFF_SRAM_CTRL_MASK_SFT, 0); + /* CHSET_IIR_STAGE */ + iir_stage = (iir_coeff_num / 6) - 1; + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2, + G_SRC_CHSET_IIR_STAGE_MASK_SFT, + iir_stage << G_SRC_CHSET_IIR_STAGE_SFT); + /* CHSET_IIR_EN */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2, + G_SRC_CHSET_IIR_EN_MASK_SFT, + BIT(G_SRC_CHSET_IIR_EN_SFT)); + } else { + /* CHSET_IIR_EN off */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2, + G_SRC_CHSET_IIR_EN_MASK_SFT, 0); + } + + return 0; +} + +#define HW_SRC_1_EN_W_NAME "HW_SRC_1_Enable" +#define HW_SRC_2_EN_W_NAME "HW_SRC_2_Enable" + +static int mtk_hw_src_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int id; + struct mtk_afe_src_priv *src_priv; + unsigned int reg; + + if (strcmp(w->name, HW_SRC_1_EN_W_NAME) == 0) + id = MT8186_DAI_SRC_1; + else + id = MT8186_DAI_SRC_2; + + src_priv = afe_priv->dai_priv[id]; + + dev_dbg(afe->dev, + "%s(), name %s, event 0x%x, id %d, src_priv %p, dl_rate %d, ul_rate %d\n", + __func__, w->name, event, id, src_priv, + src_priv->dl_rate, src_priv->ul_rate); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (id == MT8186_DAI_SRC_1) + mtk_set_src_1_param(afe, id); + else + mtk_set_src_2_param(afe, id); + break; + case SND_SOC_DAPM_POST_PMU: + reg = (id == MT8186_DAI_SRC_1) ? + AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0; + /* ASM_ON */ + regmap_update_bits(afe->regmap, reg, + G_SRC_ASM_ON_MASK_SFT, + BIT(G_SRC_ASM_ON_SFT)); + /* CHSET_ON */ + regmap_update_bits(afe->regmap, reg, + G_SRC_CHSET_ON_MASK_SFT, + BIT(G_SRC_CHSET_ON_SFT)); + /* CHSET_STR_CLR */ + regmap_update_bits(afe->regmap, reg, + G_SRC_CHSET_STR_CLR_MASK_SFT, + BIT(G_SRC_CHSET_STR_CLR_SFT)); + break; + case SND_SOC_DAPM_PRE_PMD: + reg = (id == MT8186_DAI_SRC_1) ? + AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0; + /* ASM_OFF */ + regmap_update_bits(afe->regmap, reg, G_SRC_ASM_ON_MASK_SFT, 0); + /* CHSET_OFF */ + regmap_update_bits(afe->regmap, reg, G_SRC_CHSET_ON_MASK_SFT, 0); + /* CHSET_STR_CLR */ + regmap_update_bits(afe->regmap, reg, G_SRC_CHSET_STR_CLR_MASK_SFT, 0); + break; + default: + break; + } + + return 0; +} + +/* dai component */ +static const struct snd_kcontrol_new mtk_hw_src_1_in_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN40, + I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN40, + I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN40, + I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN40_1, + I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN40_1, + I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN40, + I_I2S0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN40_1, + I_DL5_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_src_1_in_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN41, + I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN41, + I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN41, + I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN41_1, + I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN41_1, + I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN41, + I_I2S0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN41_1, + I_DL5_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_src_2_in_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN42, + I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN42, + I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN42, + I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN42, + I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN42_1, + I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN42_1, + I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH1 Switch", AFE_CONN42, + I_GAIN2_OUT_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_src_2_in_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN43, + I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN43, + I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN43, + I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN43, + I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN43_1, + I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN43_1, + I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH2 Switch", AFE_CONN43, + I_GAIN2_OUT_CH2, 1, 0), +}; + +static const struct snd_soc_dapm_widget mtk_dai_src_widgets[] = { + /* inter-connections */ + SND_SOC_DAPM_MIXER("HW_SRC_1_IN_CH1", SND_SOC_NOPM, 0, 0, + mtk_hw_src_1_in_ch1_mix, + ARRAY_SIZE(mtk_hw_src_1_in_ch1_mix)), + SND_SOC_DAPM_MIXER("HW_SRC_1_IN_CH2", SND_SOC_NOPM, 0, 0, + mtk_hw_src_1_in_ch2_mix, + ARRAY_SIZE(mtk_hw_src_1_in_ch2_mix)), + SND_SOC_DAPM_MIXER("HW_SRC_2_IN_CH1", SND_SOC_NOPM, 0, 0, + mtk_hw_src_2_in_ch1_mix, + ARRAY_SIZE(mtk_hw_src_2_in_ch1_mix)), + SND_SOC_DAPM_MIXER("HW_SRC_2_IN_CH2", SND_SOC_NOPM, 0, 0, + mtk_hw_src_2_in_ch2_mix, + ARRAY_SIZE(mtk_hw_src_2_in_ch2_mix)), + + SND_SOC_DAPM_SUPPLY(HW_SRC_1_EN_W_NAME, + GENERAL_ASRC_EN_ON, GENERAL1_ASRC_EN_ON_SFT, 0, + mtk_hw_src_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_SUPPLY(HW_SRC_2_EN_W_NAME, + GENERAL_ASRC_EN_ON, GENERAL2_ASRC_EN_ON_SFT, 0, + mtk_hw_src_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_INPUT("HW SRC 1 Out Endpoint"), + SND_SOC_DAPM_INPUT("HW SRC 2 Out Endpoint"), + SND_SOC_DAPM_OUTPUT("HW SRC 1 In Endpoint"), + SND_SOC_DAPM_OUTPUT("HW SRC 2 In Endpoint"), +}; + +static int mtk_afe_src_en_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = source; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_src_priv *src_priv; + + if (strcmp(w->name, HW_SRC_1_EN_W_NAME) == 0) + src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_1]; + else + src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_2]; + + dev_dbg(afe->dev, + "%s(), source %s, sink %s, dl_rate %d, ul_rate %d\n", + __func__, source->name, sink->name, + src_priv->dl_rate, src_priv->ul_rate); + + return (src_priv->dl_rate > 0 && src_priv->ul_rate > 0) ? 1 : 0; +} + +static const struct snd_soc_dapm_route mtk_dai_src_routes[] = { + {"HW_SRC_1_IN_CH1", "DL1_CH1 Switch", "DL1"}, + {"HW_SRC_1_IN_CH2", "DL1_CH2 Switch", "DL1"}, + {"HW_SRC_2_IN_CH1", "DL1_CH1 Switch", "DL1"}, + {"HW_SRC_2_IN_CH2", "DL1_CH2 Switch", "DL1"}, + {"HW_SRC_1_IN_CH1", "DL2_CH1 Switch", "DL2"}, + {"HW_SRC_1_IN_CH2", "DL2_CH2 Switch", "DL2"}, + {"HW_SRC_2_IN_CH1", "DL2_CH1 Switch", "DL2"}, + {"HW_SRC_2_IN_CH2", "DL2_CH2 Switch", "DL2"}, + {"HW_SRC_1_IN_CH1", "DL3_CH1 Switch", "DL3"}, + {"HW_SRC_1_IN_CH2", "DL3_CH2 Switch", "DL3"}, + {"HW_SRC_2_IN_CH1", "DL3_CH1 Switch", "DL3"}, + {"HW_SRC_2_IN_CH2", "DL3_CH2 Switch", "DL3"}, + {"HW_SRC_1_IN_CH1", "DL6_CH1 Switch", "DL6"}, + {"HW_SRC_1_IN_CH2", "DL6_CH2 Switch", "DL6"}, + {"HW_SRC_2_IN_CH1", "DL6_CH1 Switch", "DL6"}, + {"HW_SRC_2_IN_CH2", "DL6_CH2 Switch", "DL6"}, + {"HW_SRC_1_IN_CH1", "DL5_CH1 Switch", "DL5"}, + {"HW_SRC_1_IN_CH2", "DL5_CH2 Switch", "DL5"}, + {"HW_SRC_2_IN_CH1", "DL5_CH1 Switch", "DL5"}, + {"HW_SRC_2_IN_CH2", "DL5_CH2 Switch", "DL5"}, + {"HW_SRC_1_IN_CH1", "DL4_CH1 Switch", "DL4"}, + {"HW_SRC_1_IN_CH2", "DL4_CH2 Switch", "DL4"}, + {"HW_SRC_2_IN_CH1", "DL4_CH1 Switch", "DL4"}, + {"HW_SRC_2_IN_CH2", "DL4_CH2 Switch", "DL4"}, + + {"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH1"}, + {"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH2"}, + + {"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH1"}, + {"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH2"}, + + {"HW_SRC_1_In", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect}, + {"HW_SRC_1_Out", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect}, + {"HW_SRC_2_In", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect}, + {"HW_SRC_2_Out", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect}, + + {"HW SRC 1 In Endpoint", NULL, "HW_SRC_1_In"}, + {"HW SRC 2 In Endpoint", NULL, "HW_SRC_2_In"}, + {"HW_SRC_1_Out", NULL, "HW SRC 1 Out Endpoint"}, + {"HW_SRC_2_Out", NULL, "HW SRC 2 Out Endpoint"}, +}; + +/* dai ops */ +static int mtk_dai_src_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int id = dai->id; + struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id]; + unsigned int sft, mask; + unsigned int rate = params_rate(params); + unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, id); + + dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n", + __func__, id, substream->stream, rate); + + /* rate */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + src_priv->dl_rate = rate; + if (id == MT8186_DAI_SRC_1) { + sft = GENERAL1_ASRCIN_MODE_SFT; + mask = GENERAL1_ASRCIN_MODE_MASK; + } else { + sft = GENERAL2_ASRCIN_MODE_SFT; + mask = GENERAL2_ASRCIN_MODE_MASK; + } + } else { + src_priv->ul_rate = rate; + if (id == MT8186_DAI_SRC_1) { + sft = GENERAL1_ASRCOUT_MODE_SFT; + mask = GENERAL1_ASRCOUT_MODE_MASK; + } else { + sft = GENERAL2_ASRCOUT_MODE_SFT; + mask = GENERAL2_ASRCOUT_MODE_MASK; + } + } + + regmap_update_bits(afe->regmap, GENERAL_ASRC_MODE, mask << sft, rate_reg << sft); + + return 0; +} + +static int mtk_dai_src_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int id = dai->id; + struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id]; + + dev_dbg(afe->dev, "%s(), id %d, stream %d\n", + __func__, id, substream->stream); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + src_priv->dl_rate = 0; + else + src_priv->ul_rate = 0; + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_src_ops = { + .hw_params = mtk_dai_src_hw_params, + .hw_free = mtk_dai_src_hw_free, +}; + +/* dai driver */ +#define MTK_SRC_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_SRC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_src_driver[] = { + { + .name = "HW_SRC_1", + .id = MT8186_DAI_SRC_1, + .playback = { + .stream_name = "HW_SRC_1_In", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_SRC_RATES, + .formats = MTK_SRC_FORMATS, + }, + .capture = { + .stream_name = "HW_SRC_1_Out", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_SRC_RATES, + .formats = MTK_SRC_FORMATS, + }, + .ops = &mtk_dai_src_ops, + }, + { + .name = "HW_SRC_2", + .id = MT8186_DAI_SRC_2, + .playback = { + .stream_name = "HW_SRC_2_In", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_SRC_RATES, + .formats = MTK_SRC_FORMATS, + }, + .capture = { + .stream_name = "HW_SRC_2_Out", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_SRC_RATES, + .formats = MTK_SRC_FORMATS, + }, + .ops = &mtk_dai_src_ops, + }, +}; + +int mt8186_dai_src_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + int ret; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_src_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_src_driver); + + dai->dapm_widgets = mtk_dai_src_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_src_widgets); + dai->dapm_routes = mtk_dai_src_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_src_routes); + + /* set dai priv */ + ret = mt8186_dai_set_priv(afe, MT8186_DAI_SRC_1, + sizeof(struct mtk_afe_src_priv), NULL); + if (ret) + return ret; + + ret = mt8186_dai_set_priv(afe, MT8186_DAI_SRC_2, + sizeof(struct mtk_afe_src_priv), NULL); + if (ret) + return ret; + + return 0; +} -- cgit From ae92dcbee8b6a6f63198a2a6fea0fc9f6a0fe07b Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Mon, 23 May 2022 21:28:48 +0800 Subject: ASoC: mediatek: mt8186: support tdm in platform driver Add mt8186 tdm dai driver. Signed-off-by: Jiaxin Yu Link: https://lore.kernel.org/r/20220523132858.22166-11-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-dai-tdm.c | 698 +++++++++++++++++++++++++++++ 1 file changed, 698 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-tdm.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c new file mode 100644 index 000000000000..dfff209b60da --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c @@ -0,0 +1,698 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI TDM Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include + +#include "mt8186-afe-clk.h" +#include "mt8186-afe-common.h" +#include "mt8186-afe-gpio.h" +#include "mt8186-interconnection.h" + +#define TDM_HD_EN_W_NAME "TDM_HD_EN" +#define TDM_MCLK_EN_W_NAME "TDM_MCLK_EN" +#define MTK_AFE_TDM_KCONTROL_NAME "TDM_HD_Mux" + +struct mtk_afe_tdm_priv { + unsigned int id; + unsigned int rate; /* for determine which apll to use */ + unsigned int bck_invert; + unsigned int lck_invert; + unsigned int lrck_width; + unsigned int mclk_id; + unsigned int mclk_multiple; /* according to sample rate */ + unsigned int mclk_rate; + unsigned int mclk_apll; + unsigned int tdm_mode; + unsigned int data_mode; + unsigned int slave_mode; + unsigned int low_jitter_en; +}; + +enum { + TDM_IN_I2S = 0, + TDM_IN_LJ = 1, + TDM_IN_RJ = 2, + TDM_IN_DSP_A = 4, + TDM_IN_DSP_B = 5, +}; + +enum { + TDM_DATA_ONE_PIN = 0, + TDM_DATA_MULTI_PIN, +}; + +enum { + TDM_BCK_NON_INV = 0, + TDM_BCK_INV = 1, +}; + +enum { + TDM_LCK_NON_INV = 0, + TDM_LCK_INV = 1, +}; + +static unsigned int get_tdm_lrck_width(snd_pcm_format_t format, + unsigned int mode) +{ + if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B) + return 0; + + return snd_pcm_format_physical_width(format) - 1; +} + +static unsigned int get_tdm_ch_fixup(unsigned int channels) +{ + if (channels > 4) + return 8; + else if (channels > 2) + return 4; + + return 2; +} + +static unsigned int get_tdm_ch_per_sdata(unsigned int mode, + unsigned int channels) +{ + if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B) + return get_tdm_ch_fixup(channels); + + return 2; +} + +enum { + SUPPLY_SEQ_APLL, + SUPPLY_SEQ_TDM_MCK_EN, + SUPPLY_SEQ_TDM_HD_EN, + SUPPLY_SEQ_TDM_EN, +}; + +static int get_tdm_id_by_name(const char *name) +{ + return MT8186_DAI_TDM_IN; +} + +static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_afe_gpio_request(afe->dev, true, tdm_priv->id, 0); + break; + case SND_SOC_DAPM_POST_PMD: + mt8186_afe_gpio_request(afe->dev, false, tdm_priv->id, 0); + break; + default: + break; + } + + return 0; +} + +static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n", + __func__, w->name, event, dai_id); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate); + break; + case SND_SOC_DAPM_POST_PMD: + tdm_priv->mclk_rate = 0; + mt8186_mck_disable(afe, tdm_priv->mclk_id); + break; + default: + break; + } + + return 0; +} + +/* dai component */ +/* tdm virtual mux to output widget */ +static const char * const tdm_mux_map[] = { + "Normal", "Dummy_Widget", +}; + +static int tdm_mux_map_value[] = { + 0, 1, +}; + +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(tdm_mux_map_enum, + SND_SOC_NOPM, + 0, + 1, + tdm_mux_map, + tdm_mux_map_value); + +static const struct snd_kcontrol_new tdm_in_mux_control = + SOC_DAPM_ENUM("TDM In Select", tdm_mux_map_enum); + +static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = { + SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"), + + SND_SOC_DAPM_SUPPLY_S("TDM_EN", SUPPLY_SEQ_TDM_EN, + ETDM_IN1_CON0, ETDM_IN1_CON0_REG_ETDM_IN_EN_SFT, + 0, mtk_tdm_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + /* tdm hd en */ + SND_SOC_DAPM_SUPPLY_S(TDM_HD_EN_W_NAME, SUPPLY_SEQ_TDM_HD_EN, + ETDM_IN1_CON2, ETDM_IN1_CON2_REG_CLOCK_SOURCE_SEL_SFT, + 0, NULL, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S(TDM_MCLK_EN_W_NAME, SUPPLY_SEQ_TDM_MCK_EN, + SND_SOC_NOPM, 0, 0, + mtk_tdm_mck_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_INPUT("TDM_DUMMY_IN"), + + SND_SOC_DAPM_MUX("TDM_In_Mux", + SND_SOC_NOPM, 0, 0, &tdm_in_mux_control), +}; + +static int mtk_afe_tdm_mclk_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return 0; + } + + return (tdm_priv->mclk_rate > 0) ? 1 : 0; +} + +static int mtk_afe_tdm_mclk_apll_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + int cur_apll; + + /* which apll */ + cur_apll = mt8186_get_apll_by_name(afe, source->name); + + return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0; +} + +static int mtk_afe_tdm_hd_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return 0; + } + + return tdm_priv->low_jitter_en; +} + +static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + int cur_apll; + int tdm_need_apll; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return 0; + } + + /* which apll */ + cur_apll = mt8186_get_apll_by_name(afe, source->name); + + /* choose APLL from tdm rate */ + tdm_need_apll = mt8186_get_apll_by_rate(afe, tdm_priv->rate); + + return (tdm_need_apll == cur_apll) ? 1 : 0; +} + +/* low jitter control */ +static const char * const mt8186_tdm_hd_str[] = { + "Normal", "Low_Jitter" +}; + +static const struct soc_enum mt8186_tdm_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_tdm_hd_str), + mt8186_tdm_hd_str), +}; + +static int mt8186_tdm_hd_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(kcontrol->id.name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + ucontrol->value.integer.value[0] = tdm_priv->low_jitter_en; + + return 0; +} + +static int mt8186_tdm_hd_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(kcontrol->id.name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int hd_en; + + if (ucontrol->value.enumerated.item[0] >= e->items) + return -EINVAL; + + hd_en = ucontrol->value.integer.value[0]; + + dev_dbg(afe->dev, "%s(), kcontrol name %s, hd_en %d\n", + __func__, kcontrol->id.name, hd_en); + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + if (tdm_priv->low_jitter_en == hd_en) + return 0; + + tdm_priv->low_jitter_en = hd_en; + + return 1; +} + +static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = { + SOC_ENUM_EXT(MTK_AFE_TDM_KCONTROL_NAME, mt8186_tdm_enum[0], + mt8186_tdm_hd_get, mt8186_tdm_hd_set), +}; + +static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = { + {"TDM IN", NULL, "aud_tdm_clk"}, + {"TDM IN", NULL, "TDM_EN"}, + {"TDM IN", NULL, TDM_HD_EN_W_NAME, mtk_afe_tdm_hd_connect}, + {TDM_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect}, + {TDM_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect}, + + {"TDM IN", NULL, TDM_MCLK_EN_W_NAME, mtk_afe_tdm_mclk_connect}, + {TDM_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_mclk_apll_connect}, + {TDM_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_mclk_apll_connect}, + + /* allow tdm on without codec on */ + {"TDM IN", NULL, "TDM_In_Mux"}, + {"TDM_In_Mux", "Dummy_Widget", "TDM_DUMMY_IN"}, +}; + +/* dai ops */ +static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe, + struct mtk_afe_tdm_priv *tdm_priv, + int freq) +{ + int apll; + int apll_rate; + + apll = mt8186_get_apll_by_rate(afe, freq); + apll_rate = mt8186_get_apll_rate(afe, apll); + + if (!freq || freq > apll_rate) { + dev_err(afe->dev, + "%s(), freq(%d Hz) invalid\n", __func__, freq); + return -EINVAL; + } + + if (apll_rate % freq != 0) { + dev_err(afe->dev, + "%s(), APLL cannot generate %d Hz", __func__, freq); + return -EINVAL; + } + + tdm_priv->mclk_rate = freq; + tdm_priv->mclk_apll = apll; + + return 0; +} + +static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int tdm_id = dai->id; + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id]; + unsigned int tdm_mode = tdm_priv->tdm_mode; + unsigned int data_mode = tdm_priv->data_mode; + unsigned int rate = params_rate(params); + unsigned int channels = params_channels(params); + snd_pcm_format_t format = params_format(params); + unsigned int bit_width = + snd_pcm_format_physical_width(format); + unsigned int tdm_channels = (data_mode == TDM_DATA_ONE_PIN) ? + get_tdm_ch_per_sdata(tdm_mode, channels) : 2; + unsigned int lrck_width = + get_tdm_lrck_width(format, tdm_mode); + unsigned int tdm_con = 0; + bool slave_mode = tdm_priv->slave_mode; + bool lrck_inv = tdm_priv->lck_invert; + bool bck_inv = tdm_priv->bck_invert; + unsigned int tran_rate; + unsigned int tran_relatch_rate; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + tdm_priv->rate = rate; + + tran_rate = mt8186_rate_transform(afe->dev, rate, dai->id); + tran_relatch_rate = mt8186_tdm_relatch_rate_transform(afe->dev, rate); + + /* calculate mclk_rate, if not set explicitly */ + if (!tdm_priv->mclk_rate) { + tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple; + mtk_dai_tdm_cal_mclk(afe, + tdm_priv, + tdm_priv->mclk_rate); + } + + /* ETDM_IN1_CON0 */ + tdm_con |= slave_mode << ETDM_IN1_CON0_REG_SLAVE_MODE_SFT; + tdm_con |= tdm_mode << ETDM_IN1_CON0_REG_FMT_SFT; + tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_BIT_LENGTH_SFT; + tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_WORD_LENGTH_SFT; + tdm_con |= (tdm_channels - 1) << ETDM_IN1_CON0_REG_CH_NUM_SFT; + /* need to disable sync mode otherwise this may cause latch data error */ + tdm_con |= 0 << ETDM_IN1_CON0_REG_SYNC_MODE_SFT; + /* relatch 1x en clock fix to h26m */ + tdm_con |= 0 << ETDM_IN1_CON0_REG_RELATCH_1X_EN_SEL_DOMAIN_SFT; + regmap_update_bits(afe->regmap, ETDM_IN1_CON0, ETDM_IN_CON0_CTRL_MASK, tdm_con); + + /* ETDM_IN1_CON1 */ + tdm_con = 0; + tdm_con |= 0 << ETDM_IN1_CON1_REG_LRCK_AUTO_MODE_SFT; + tdm_con |= 1 << ETDM_IN1_CON1_PINMUX_MCLK_CTRL_OE_SFT; + tdm_con |= (lrck_width - 1) << ETDM_IN1_CON1_REG_LRCK_WIDTH_SFT; + regmap_update_bits(afe->regmap, ETDM_IN1_CON1, ETDM_IN_CON1_CTRL_MASK, tdm_con); + + /* ETDM_IN1_CON3 */ + tdm_con = 0; + tdm_con = ETDM_IN_CON3_FS(tran_rate); + regmap_update_bits(afe->regmap, ETDM_IN1_CON3, ETDM_IN_CON3_CTRL_MASK, tdm_con); + + /* ETDM_IN1_CON4 */ + tdm_con = 0; + tdm_con = ETDM_IN_CON4_FS(tran_relatch_rate); + if (slave_mode) { + if (lrck_inv) + tdm_con |= ETDM_IN_CON4_CON0_SLAVE_LRCK_INV; + if (bck_inv) + tdm_con |= ETDM_IN_CON4_CON0_SLAVE_BCK_INV; + } else { + if (lrck_inv) + tdm_con |= ETDM_IN_CON4_CON0_MASTER_LRCK_INV; + if (bck_inv) + tdm_con |= ETDM_IN_CON4_CON0_MASTER_BCK_INV; + } + regmap_update_bits(afe->regmap, ETDM_IN1_CON4, ETDM_IN_CON4_CTRL_MASK, tdm_con); + + /* ETDM_IN1_CON2 */ + tdm_con = 0; + if (data_mode == TDM_DATA_MULTI_PIN) { + tdm_con |= ETDM_IN_CON2_MULTI_IP_2CH_MODE; + tdm_con |= ETDM_IN_CON2_MULTI_IP_CH(channels); + } + regmap_update_bits(afe->regmap, ETDM_IN1_CON2, ETDM_IN_CON2_CTRL_MASK, tdm_con); + + /* ETDM_IN1_CON8 */ + tdm_con = 0; + if (slave_mode) { + tdm_con |= 1 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT; + tdm_con |= 0 << ETDM_IN1_CON8_REG_AFIFO_CLOCK_DOMAIN_SEL_SFT; + tdm_con |= ETDM_IN_CON8_FS(tran_relatch_rate); + } else { + tdm_con |= 0 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT; + } + regmap_update_bits(afe->regmap, ETDM_IN1_CON8, ETDM_IN_CON8_CTRL_MASK, tdm_con); + + return 0; +} + +static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + if (dir != SND_SOC_CLOCK_IN) { + dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__); + return -EINVAL; + } + + dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq); + + return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq); +} + +static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + /* DAI mode*/ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + tdm_priv->tdm_mode = TDM_IN_I2S; + tdm_priv->data_mode = TDM_DATA_MULTI_PIN; + break; + case SND_SOC_DAIFMT_LEFT_J: + tdm_priv->tdm_mode = TDM_IN_LJ; + tdm_priv->data_mode = TDM_DATA_MULTI_PIN; + break; + case SND_SOC_DAIFMT_RIGHT_J: + tdm_priv->tdm_mode = TDM_IN_RJ; + tdm_priv->data_mode = TDM_DATA_MULTI_PIN; + break; + case SND_SOC_DAIFMT_DSP_A: + tdm_priv->tdm_mode = TDM_IN_DSP_A; + tdm_priv->data_mode = TDM_DATA_ONE_PIN; + break; + case SND_SOC_DAIFMT_DSP_B: + tdm_priv->tdm_mode = TDM_IN_DSP_B; + tdm_priv->data_mode = TDM_DATA_ONE_PIN; + break; + default: + dev_err(afe->dev, "%s(), invalid DAIFMT_FORMAT_MASK", __func__); + return -EINVAL; + } + + /* DAI clock inversion*/ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + tdm_priv->bck_invert = TDM_BCK_NON_INV; + tdm_priv->lck_invert = TDM_LCK_NON_INV; + break; + case SND_SOC_DAIFMT_NB_IF: + tdm_priv->bck_invert = TDM_BCK_NON_INV; + tdm_priv->lck_invert = TDM_LCK_INV; + break; + case SND_SOC_DAIFMT_IB_NF: + tdm_priv->bck_invert = TDM_BCK_INV; + tdm_priv->lck_invert = TDM_LCK_NON_INV; + break; + case SND_SOC_DAIFMT_IB_IF: + tdm_priv->bck_invert = TDM_BCK_INV; + tdm_priv->lck_invert = TDM_LCK_INV; + break; + default: + dev_err(afe->dev, "%s(), invalid DAIFMT_INV_MASK", __func__); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: + tdm_priv->slave_mode = false; + break; + case SND_SOC_DAIFMT_CBC_CFC: + tdm_priv->slave_mode = true; + break; + default: + dev_err(afe->dev, "%s(), invalid DAIFMT_CLOCK_PROVIDER_MASK", + __func__); + return -EINVAL; + } + + return 0; +} + +static int mtk_dai_tdm_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, + unsigned int rx_mask, + int slots, + int slot_width) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id]; + + dev_dbg(dai->dev, "%s %d slot_width %d\n", __func__, dai->id, slot_width); + + tdm_priv->lrck_width = slot_width; + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_tdm_ops = { + .hw_params = mtk_dai_tdm_hw_params, + .set_sysclk = mtk_dai_tdm_set_sysclk, + .set_fmt = mtk_dai_tdm_set_fmt, + .set_tdm_slot = mtk_dai_tdm_set_tdm_slot, +}; + +/* dai driver */ +#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = { + { + .name = "TDM IN", + .id = MT8186_DAI_TDM_IN, + .capture = { + .stream_name = "TDM IN", + .channels_min = 2, + .channels_max = 8, + .rates = MTK_TDM_RATES, + .formats = MTK_TDM_FORMATS, + }, + .ops = &mtk_dai_tdm_ops, + }, +}; + +static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe) +{ + struct mtk_afe_tdm_priv *tdm_priv; + + tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv), + GFP_KERNEL); + if (!tdm_priv) + return NULL; + + tdm_priv->mclk_multiple = 512; + tdm_priv->mclk_id = MT8186_TDM_MCK; + tdm_priv->id = MT8186_DAI_TDM_IN; + + return tdm_priv; +} + +int mt8186_dai_tdm_register(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_tdm_priv *tdm_priv; + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_tdm_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver); + + dai->controls = mtk_dai_tdm_controls; + dai->num_controls = ARRAY_SIZE(mtk_dai_tdm_controls); + dai->dapm_widgets = mtk_dai_tdm_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets); + dai->dapm_routes = mtk_dai_tdm_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes); + + tdm_priv = init_tdm_priv_data(afe); + if (!tdm_priv) + return -ENOMEM; + + afe_priv->dai_priv[MT8186_DAI_TDM_IN] = tdm_priv; + + return 0; +} -- cgit From 55b423d5623ccd6785429431c2cf5f3e073b73ba Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Mon, 23 May 2022 21:28:49 +0800 Subject: ASoC: mediatek: mt8186: support audio clock control in platform driver Add audio clock control with CCF interface. Signed-off-by: Jiaxin Yu Link: https://lore.kernel.org/r/20220523132858.22166-12-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-afe-clk.c | 651 +++++++++++++++++++++++++++++ sound/soc/mediatek/mt8186/mt8186-afe-clk.h | 106 +++++ 2 files changed, 757 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.c create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.h diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c new file mode 100644 index 000000000000..0275f66ddc18 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c @@ -0,0 +1,651 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt8186-afe-clk.c -- Mediatek 8186 afe clock ctrl +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include +#include + +#include "mt8186-afe-common.h" +#include "mt8186-afe-clk.h" +#include "mt8186-audsys-clk.h" + +static DEFINE_MUTEX(mutex_request_dram); + +static const char *aud_clks[CLK_NUM] = { + [CLK_AFE] = "aud_afe_clk", + [CLK_DAC] = "aud_dac_clk", + [CLK_DAC_PREDIS] = "aud_dac_predis_clk", + [CLK_ADC] = "aud_adc_clk", + [CLK_TML] = "aud_tml_clk", + [CLK_APLL22M] = "aud_apll22m_clk", + [CLK_APLL24M] = "aud_apll24m_clk", + [CLK_APLL1_TUNER] = "aud_apll_tuner_clk", + [CLK_APLL2_TUNER] = "aud_apll2_tuner_clk", + [CLK_TDM] = "aud_tdm_clk", + [CLK_NLE] = "aud_nle_clk", + [CLK_DAC_HIRES] = "aud_dac_hires_clk", + [CLK_ADC_HIRES] = "aud_adc_hires_clk", + [CLK_I2S1_BCLK] = "aud_i2s1_bclk", + [CLK_I2S2_BCLK] = "aud_i2s2_bclk", + [CLK_I2S3_BCLK] = "aud_i2s3_bclk", + [CLK_I2S4_BCLK] = "aud_i2s4_bclk", + [CLK_CONNSYS_I2S_ASRC] = "aud_connsys_i2s_asrc", + [CLK_GENERAL1_ASRC] = "aud_general1_asrc", + [CLK_GENERAL2_ASRC] = "aud_general2_asrc", + [CLK_ADC_HIRES_TML] = "aud_adc_hires_tml", + [CLK_ADDA6_ADC] = "aud_adda6_adc", + [CLK_ADDA6_ADC_HIRES] = "aud_adda6_adc_hires", + [CLK_3RD_DAC] = "aud_3rd_dac", + [CLK_3RD_DAC_PREDIS] = "aud_3rd_dac_predis", + [CLK_3RD_DAC_TML] = "aud_3rd_dac_tml", + [CLK_3RD_DAC_HIRES] = "aud_3rd_dac_hires", + [CLK_ETDM_IN1_BCLK] = "aud_etdm_in1_bclk", + [CLK_ETDM_OUT1_BCLK] = "aud_etdm_out1_bclk", + [CLK_INFRA_SYS_AUDIO] = "aud_infra_clk", + [CLK_INFRA_AUDIO_26M] = "mtkaif_26m_clk", + [CLK_MUX_AUDIO] = "top_mux_audio", + [CLK_MUX_AUDIOINTBUS] = "top_mux_audio_int", + [CLK_TOP_MAINPLL_D2_D4] = "top_mainpll_d2_d4", + [CLK_TOP_MUX_AUD_1] = "top_mux_aud_1", + [CLK_TOP_APLL1_CK] = "top_apll1_ck", + [CLK_TOP_MUX_AUD_2] = "top_mux_aud_2", + [CLK_TOP_APLL2_CK] = "top_apll2_ck", + [CLK_TOP_MUX_AUD_ENG1] = "top_mux_aud_eng1", + [CLK_TOP_APLL1_D8] = "top_apll1_d8", + [CLK_TOP_MUX_AUD_ENG2] = "top_mux_aud_eng2", + [CLK_TOP_APLL2_D8] = "top_apll2_d8", + [CLK_TOP_MUX_AUDIO_H] = "top_mux_audio_h", + [CLK_TOP_I2S0_M_SEL] = "top_i2s0_m_sel", + [CLK_TOP_I2S1_M_SEL] = "top_i2s1_m_sel", + [CLK_TOP_I2S2_M_SEL] = "top_i2s2_m_sel", + [CLK_TOP_I2S4_M_SEL] = "top_i2s4_m_sel", + [CLK_TOP_TDM_M_SEL] = "top_tdm_m_sel", + [CLK_TOP_APLL12_DIV0] = "top_apll12_div0", + [CLK_TOP_APLL12_DIV1] = "top_apll12_div1", + [CLK_TOP_APLL12_DIV2] = "top_apll12_div2", + [CLK_TOP_APLL12_DIV4] = "top_apll12_div4", + [CLK_TOP_APLL12_DIV_TDM] = "top_apll12_div_tdm", + [CLK_CLK26M] = "top_clk26m_clk", +}; + +int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe, + int clk_id) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIOINTBUS], + afe_priv->clk[clk_id]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_MUX_AUDIOINTBUS], + aud_clks[clk_id], ret); + return ret; + } + + return 0; +} + +static int apll1_mux_setting(struct mtk_base_afe *afe, bool enable) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + if (enable) { + ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_1]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_1], ret); + return ret; + } + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1], + afe_priv->clk[CLK_TOP_APLL1_CK]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_1], + aud_clks[CLK_TOP_APLL1_CK], ret); + return ret; + } + + /* 180.6336 / 8 = 22.5792MHz */ + ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1], ret); + return ret; + } + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1], + afe_priv->clk[CLK_TOP_APLL1_D8]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1], + aud_clks[CLK_TOP_APLL1_D8], ret); + return ret; + } + } else { + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1], + afe_priv->clk[CLK_CLK26M]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1], + aud_clks[CLK_CLK26M], ret); + return ret; + } + clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]); + + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1], + afe_priv->clk[CLK_CLK26M]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_1], + aud_clks[CLK_CLK26M], ret); + return ret; + } + clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_1]); + } + + return 0; +} + +static int apll2_mux_setting(struct mtk_base_afe *afe, bool enable) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + if (enable) { + ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_2]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_2], ret); + return ret; + } + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2], + afe_priv->clk[CLK_TOP_APLL2_CK]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_2], + aud_clks[CLK_TOP_APLL2_CK], ret); + return ret; + } + + /* 196.608 / 8 = 24.576MHz */ + ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2], ret); + return ret; + } + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2], + afe_priv->clk[CLK_TOP_APLL2_D8]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2], + aud_clks[CLK_TOP_APLL2_D8], ret); + return ret; + } + } else { + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2], + afe_priv->clk[CLK_CLK26M]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2], + aud_clks[CLK_CLK26M], ret); + return ret; + } + clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]); + + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2], + afe_priv->clk[CLK_CLK26M]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_2], + aud_clks[CLK_CLK26M], ret); + return ret; + } + clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_2]); + } + + return 0; +} + +int mt8186_afe_enable_cgs(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret = 0; + int i; + + for (i = CLK_I2S1_BCLK; i <= CLK_ETDM_OUT1_BCLK; i++) { + ret = clk_prepare_enable(afe_priv->clk[i]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[i], ret); + return ret; + } + } + + return 0; +} + +void mt8186_afe_disable_cgs(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int i; + + for (i = CLK_I2S1_BCLK; i <= CLK_ETDM_OUT1_BCLK; i++) + clk_disable_unprepare(afe_priv->clk[i]); +} + +int mt8186_afe_enable_clock(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret = 0; + + ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUDIO]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_INFRA_SYS_AUDIO], ret); + goto clk_infra_sys_audio_err; + } + + ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_AUDIO_26M]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_INFRA_AUDIO_26M], ret); + goto clk_infra_audio_26m_err; + } + + ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIO]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_MUX_AUDIO], ret); + goto clk_mux_audio_err; + } + ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIO], + afe_priv->clk[CLK_CLK26M]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_MUX_AUDIO], + aud_clks[CLK_CLK26M], ret); + goto clk_mux_audio_err; + } + + ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret); + goto clk_mux_audio_intbus_err; + } + ret = mt8186_set_audio_int_bus_parent(afe, + CLK_TOP_MAINPLL_D2_D4); + if (ret) + goto clk_mux_audio_intbus_parent_err; + + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUDIO_H], + afe_priv->clk[CLK_TOP_APLL2_CK]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUDIO_H], + aud_clks[CLK_TOP_APLL2_CK], ret); + goto clk_mux_audio_h_parent_err; + } + + ret = clk_prepare_enable(afe_priv->clk[CLK_AFE]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_AFE], ret); + goto clk_afe_err; + } + + return 0; + +clk_afe_err: + clk_disable_unprepare(afe_priv->clk[CLK_AFE]); +clk_mux_audio_h_parent_err: +clk_mux_audio_intbus_parent_err: + mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M); +clk_mux_audio_intbus_err: + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); +clk_mux_audio_err: + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]); +clk_infra_sys_audio_err: + clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]); +clk_infra_audio_26m_err: + clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]); + + return ret; +} + +void mt8186_afe_disable_clock(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + clk_disable_unprepare(afe_priv->clk[CLK_AFE]); + mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M); + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]); + clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]); + clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]); +} + +int mt8186_afe_suspend_clock(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + /* set audio int bus to 26M */ + ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + if (ret) { + dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret); + goto clk_mux_audio_intbus_err; + } + ret = mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M); + if (ret) + goto clk_mux_audio_intbus_parent_err; + + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + + return 0; + +clk_mux_audio_intbus_parent_err: + mt8186_set_audio_int_bus_parent(afe, CLK_TOP_MAINPLL_D2_D4); +clk_mux_audio_intbus_err: + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + return ret; +} + +int mt8186_afe_resume_clock(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + /* set audio int bus to normal working clock */ + ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + if (ret) { + dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret); + goto clk_mux_audio_intbus_err; + } + ret = mt8186_set_audio_int_bus_parent(afe, + CLK_TOP_MAINPLL_D2_D4); + if (ret) + goto clk_mux_audio_intbus_parent_err; + + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + + return 0; + +clk_mux_audio_intbus_parent_err: + mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M); +clk_mux_audio_intbus_err: + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + return ret; +} + +int mt8186_apll1_enable(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + /* setting for APLL */ + apll1_mux_setting(afe, true); + + ret = clk_prepare_enable(afe_priv->clk[CLK_APLL22M]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_APLL22M], ret); + goto err_clk_apll22m; + } + + ret = clk_prepare_enable(afe_priv->clk[CLK_APLL1_TUNER]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_APLL1_TUNER], ret); + goto err_clk_apll1_tuner; + } + + regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0xfff7, 0x832); + regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x1); + + regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE, + AFE_22M_ON_MASK_SFT, BIT(AFE_22M_ON_SFT)); + + return 0; + +err_clk_apll1_tuner: + clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]); +err_clk_apll22m: + clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]); + + return ret; +} + +void mt8186_apll1_disable(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE, + AFE_22M_ON_MASK_SFT, 0); + + regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0); + + clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]); + clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]); + + apll1_mux_setting(afe, false); +} + +int mt8186_apll2_enable(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + /* setting for APLL */ + apll2_mux_setting(afe, true); + + ret = clk_prepare_enable(afe_priv->clk[CLK_APLL24M]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_APLL24M], ret); + goto err_clk_apll24m; + } + + ret = clk_prepare_enable(afe_priv->clk[CLK_APLL2_TUNER]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_APLL2_TUNER], ret); + goto err_clk_apll2_tuner; + } + + regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0xfff7, 0x634); + regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x1); + + regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE, + AFE_24M_ON_MASK_SFT, BIT(AFE_24M_ON_SFT)); + + return 0; + +err_clk_apll2_tuner: + clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]); +err_clk_apll24m: + clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]); + + return ret; +} + +void mt8186_apll2_disable(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE, + AFE_24M_ON_MASK_SFT, 0); + + regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0); + + clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]); + clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]); + + apll2_mux_setting(afe, false); +} + +int mt8186_get_apll_rate(struct mtk_base_afe *afe, int apll) +{ + return (apll == MT8186_APLL1) ? 180633600 : 196608000; +} + +int mt8186_get_apll_by_rate(struct mtk_base_afe *afe, int rate) +{ + return ((rate % 8000) == 0) ? MT8186_APLL2 : MT8186_APLL1; +} + +int mt8186_get_apll_by_name(struct mtk_base_afe *afe, const char *name) +{ + if (strcmp(name, APLL1_W_NAME) == 0) + return MT8186_APLL1; + + return MT8186_APLL2; +} + +/* mck */ +struct mt8186_mck_div { + u32 m_sel_id; + u32 div_clk_id; +}; + +static const struct mt8186_mck_div mck_div[MT8186_MCK_NUM] = { + [MT8186_I2S0_MCK] = { + .m_sel_id = CLK_TOP_I2S0_M_SEL, + .div_clk_id = CLK_TOP_APLL12_DIV0, + }, + [MT8186_I2S1_MCK] = { + .m_sel_id = CLK_TOP_I2S1_M_SEL, + .div_clk_id = CLK_TOP_APLL12_DIV1, + }, + [MT8186_I2S2_MCK] = { + .m_sel_id = CLK_TOP_I2S2_M_SEL, + .div_clk_id = CLK_TOP_APLL12_DIV2, + }, + [MT8186_I2S4_MCK] = { + .m_sel_id = CLK_TOP_I2S4_M_SEL, + .div_clk_id = CLK_TOP_APLL12_DIV4, + }, + [MT8186_TDM_MCK] = { + .m_sel_id = CLK_TOP_TDM_M_SEL, + .div_clk_id = CLK_TOP_APLL12_DIV_TDM, + }, +}; + +int mt8186_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int apll = mt8186_get_apll_by_rate(afe, rate); + int apll_clk_id = apll == MT8186_APLL1 ? + CLK_TOP_MUX_AUD_1 : CLK_TOP_MUX_AUD_2; + int m_sel_id = mck_div[mck_id].m_sel_id; + int div_clk_id = mck_div[mck_id].div_clk_id; + int ret; + + /* select apll */ + if (m_sel_id >= 0) { + ret = clk_prepare_enable(afe_priv->clk[m_sel_id]); + if (ret) { + dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n", + __func__, aud_clks[m_sel_id], ret); + return ret; + } + ret = clk_set_parent(afe_priv->clk[m_sel_id], + afe_priv->clk[apll_clk_id]); + if (ret) { + dev_err(afe->dev, "%s(), clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[m_sel_id], + aud_clks[apll_clk_id], ret); + return ret; + } + } + + /* enable div, set rate */ + ret = clk_prepare_enable(afe_priv->clk[div_clk_id]); + if (ret) { + dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n", + __func__, aud_clks[div_clk_id], ret); + return ret; + } + ret = clk_set_rate(afe_priv->clk[div_clk_id], rate); + if (ret) { + dev_err(afe->dev, "%s(), clk_set_rate %s, rate %d, fail %d\n", + __func__, aud_clks[div_clk_id], rate, ret); + return ret; + } + + return 0; +} + +void mt8186_mck_disable(struct mtk_base_afe *afe, int mck_id) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int m_sel_id = mck_div[mck_id].m_sel_id; + int div_clk_id = mck_div[mck_id].div_clk_id; + + clk_disable_unprepare(afe_priv->clk[div_clk_id]); + if (m_sel_id >= 0) + clk_disable_unprepare(afe_priv->clk[m_sel_id]); +} + +int mt8186_init_clock(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct device_node *of_node = afe->dev->of_node; + int i = 0; + + mt8186_audsys_clk_register(afe); + + afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM, sizeof(*afe_priv->clk), + GFP_KERNEL); + if (!afe_priv->clk) + return -ENOMEM; + + for (i = 0; i < CLK_NUM; i++) { + afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]); + if (IS_ERR(afe_priv->clk[i])) { + dev_err(afe->dev, "%s devm_clk_get %s fail, ret %ld\n", + __func__, + aud_clks[i], PTR_ERR(afe_priv->clk[i])); + afe_priv->clk[i] = NULL; + } + } + + afe_priv->apmixedsys = syscon_regmap_lookup_by_phandle(of_node, + "mediatek,apmixedsys"); + if (IS_ERR(afe_priv->apmixedsys)) { + dev_err(afe->dev, "%s() Cannot find apmixedsys controller: %ld\n", + __func__, PTR_ERR(afe_priv->apmixedsys)); + return PTR_ERR(afe_priv->apmixedsys); + } + + afe_priv->topckgen = syscon_regmap_lookup_by_phandle(of_node, + "mediatek,topckgen"); + if (IS_ERR(afe_priv->topckgen)) { + dev_err(afe->dev, "%s() Cannot find topckgen controller: %ld\n", + __func__, PTR_ERR(afe_priv->topckgen)); + return PTR_ERR(afe_priv->topckgen); + } + + afe_priv->infracfg = syscon_regmap_lookup_by_phandle(of_node, + "mediatek,infracfg"); + if (IS_ERR(afe_priv->infracfg)) { + dev_err(afe->dev, "%s() Cannot find infracfg: %ld\n", + __func__, PTR_ERR(afe_priv->infracfg)); + return PTR_ERR(afe_priv->infracfg); + } + + return 0; +} + +void mt8186_deinit_clock(struct mtk_base_afe *afe) +{ + mt8186_audsys_clk_unregister(afe); +} diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.h b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h new file mode 100644 index 000000000000..c539557d7c78 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * mt8186-afe-clk.h -- Mediatek 8186 afe clock ctrl definition + * + * Copyright (c) 2022 MediaTek Inc. + * Author: Jiaxin Yu + */ + +#ifndef _MT8186_AFE_CLOCK_CTRL_H_ +#define _MT8186_AFE_CLOCK_CTRL_H_ + +#define PERI_BUS_DCM_CTRL 0x74 + +/* APLL */ +#define APLL1_W_NAME "APLL1" +#define APLL2_W_NAME "APLL2" +enum { + MT8186_APLL1 = 0, + MT8186_APLL2, +}; + +enum { + CLK_AFE = 0, + CLK_DAC, + CLK_DAC_PREDIS, + CLK_ADC, + CLK_TML, + CLK_APLL22M, + CLK_APLL24M, + CLK_APLL1_TUNER, + CLK_APLL2_TUNER, + CLK_TDM, + CLK_NLE, + CLK_DAC_HIRES, + CLK_ADC_HIRES, + CLK_I2S1_BCLK, + CLK_I2S2_BCLK, + CLK_I2S3_BCLK, + CLK_I2S4_BCLK, + CLK_CONNSYS_I2S_ASRC, + CLK_GENERAL1_ASRC, + CLK_GENERAL2_ASRC, + CLK_ADC_HIRES_TML, + CLK_ADDA6_ADC, + CLK_ADDA6_ADC_HIRES, + CLK_3RD_DAC, + CLK_3RD_DAC_PREDIS, + CLK_3RD_DAC_TML, + CLK_3RD_DAC_HIRES, + CLK_ETDM_IN1_BCLK, + CLK_ETDM_OUT1_BCLK, + CLK_INFRA_SYS_AUDIO, + CLK_INFRA_AUDIO_26M, + CLK_MUX_AUDIO, + CLK_MUX_AUDIOINTBUS, + CLK_TOP_MAINPLL_D2_D4, + /* apll related mux */ + CLK_TOP_MUX_AUD_1, + CLK_TOP_APLL1_CK, + CLK_TOP_MUX_AUD_2, + CLK_TOP_APLL2_CK, + CLK_TOP_MUX_AUD_ENG1, + CLK_TOP_APLL1_D8, + CLK_TOP_MUX_AUD_ENG2, + CLK_TOP_APLL2_D8, + CLK_TOP_MUX_AUDIO_H, + CLK_TOP_I2S0_M_SEL, + CLK_TOP_I2S1_M_SEL, + CLK_TOP_I2S2_M_SEL, + CLK_TOP_I2S4_M_SEL, + CLK_TOP_TDM_M_SEL, + CLK_TOP_APLL12_DIV0, + CLK_TOP_APLL12_DIV1, + CLK_TOP_APLL12_DIV2, + CLK_TOP_APLL12_DIV4, + CLK_TOP_APLL12_DIV_TDM, + CLK_CLK26M, + CLK_NUM +}; + +struct mtk_base_afe; +int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe, int clk_id); +int mt8186_init_clock(struct mtk_base_afe *afe); +void mt8186_deinit_clock(struct mtk_base_afe *afe); +int mt8186_afe_enable_cgs(struct mtk_base_afe *afe); +void mt8186_afe_disable_cgs(struct mtk_base_afe *afe); +int mt8186_afe_enable_clock(struct mtk_base_afe *afe); +void mt8186_afe_disable_clock(struct mtk_base_afe *afe); +int mt8186_afe_suspend_clock(struct mtk_base_afe *afe); +int mt8186_afe_resume_clock(struct mtk_base_afe *afe); + +int mt8186_apll1_enable(struct mtk_base_afe *afe); +void mt8186_apll1_disable(struct mtk_base_afe *afe); + +int mt8186_apll2_enable(struct mtk_base_afe *afe); +void mt8186_apll2_disable(struct mtk_base_afe *afe); + +int mt8186_get_apll_rate(struct mtk_base_afe *afe, int apll); +int mt8186_get_apll_by_rate(struct mtk_base_afe *afe, int rate); +int mt8186_get_apll_by_name(struct mtk_base_afe *afe, const char *name); + +/* these will be replaced by using CCF */ +int mt8186_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate); +void mt8186_mck_disable(struct mtk_base_afe *afe, int mck_id); + +#endif -- cgit From cfa9a966f12a91a269e50f1c3237c006ffe2ee9a Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Mon, 23 May 2022 21:28:50 +0800 Subject: ASoC: mediatek: mt8186: support gpio control in platform driver Add gpio control for all audio interface separately. Signed-off-by: Jiaxin Yu Link: https://lore.kernel.org/r/20220523132858.22166-13-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-afe-gpio.c | 244 ++++++++++++++++++++++++++++ sound/soc/mediatek/mt8186/mt8186-afe-gpio.h | 19 +++ 2 files changed, 263 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-gpio.c create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-gpio.h diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c new file mode 100644 index 000000000000..5ba28095b7da --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt8186-afe-gpio.c -- Mediatek 8186 afe gpio ctrl +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include + +#include "mt8186-afe-common.h" +#include "mt8186-afe-gpio.h" + +struct pinctrl *aud_pinctrl; + +enum mt8186_afe_gpio { + MT8186_AFE_GPIO_CLK_MOSI_OFF, + MT8186_AFE_GPIO_CLK_MOSI_ON, + MT8186_AFE_GPIO_CLK_MISO_OFF, + MT8186_AFE_GPIO_CLK_MISO_ON, + MT8186_AFE_GPIO_DAT_MISO_OFF, + MT8186_AFE_GPIO_DAT_MISO_ON, + MT8186_AFE_GPIO_DAT_MOSI_OFF, + MT8186_AFE_GPIO_DAT_MOSI_ON, + MT8186_AFE_GPIO_I2S0_OFF, + MT8186_AFE_GPIO_I2S0_ON, + MT8186_AFE_GPIO_I2S1_OFF, + MT8186_AFE_GPIO_I2S1_ON, + MT8186_AFE_GPIO_I2S2_OFF, + MT8186_AFE_GPIO_I2S2_ON, + MT8186_AFE_GPIO_I2S3_OFF, + MT8186_AFE_GPIO_I2S3_ON, + MT8186_AFE_GPIO_TDM_OFF, + MT8186_AFE_GPIO_TDM_ON, + MT8186_AFE_GPIO_PCM_OFF, + MT8186_AFE_GPIO_PCM_ON, + MT8186_AFE_GPIO_GPIO_NUM +}; + +struct audio_gpio_attr { + const char *name; + bool gpio_prepare; + struct pinctrl_state *gpioctrl; +}; + +static struct audio_gpio_attr aud_gpios[MT8186_AFE_GPIO_GPIO_NUM] = { + [MT8186_AFE_GPIO_CLK_MOSI_OFF] = {"aud_clk_mosi_off", false, NULL}, + [MT8186_AFE_GPIO_CLK_MOSI_ON] = {"aud_clk_mosi_on", false, NULL}, + [MT8186_AFE_GPIO_CLK_MISO_OFF] = {"aud_clk_miso_off", false, NULL}, + [MT8186_AFE_GPIO_CLK_MISO_ON] = {"aud_clk_miso_on", false, NULL}, + [MT8186_AFE_GPIO_DAT_MISO_OFF] = {"aud_dat_miso_off", false, NULL}, + [MT8186_AFE_GPIO_DAT_MISO_ON] = {"aud_dat_miso_on", false, NULL}, + [MT8186_AFE_GPIO_DAT_MOSI_OFF] = {"aud_dat_mosi_off", false, NULL}, + [MT8186_AFE_GPIO_DAT_MOSI_ON] = {"aud_dat_mosi_on", false, NULL}, + [MT8186_AFE_GPIO_I2S0_OFF] = {"aud_gpio_i2s0_off", false, NULL}, + [MT8186_AFE_GPIO_I2S0_ON] = {"aud_gpio_i2s0_on", false, NULL}, + [MT8186_AFE_GPIO_I2S1_OFF] = {"aud_gpio_i2s1_off", false, NULL}, + [MT8186_AFE_GPIO_I2S1_ON] = {"aud_gpio_i2s1_on", false, NULL}, + [MT8186_AFE_GPIO_I2S2_OFF] = {"aud_gpio_i2s2_off", false, NULL}, + [MT8186_AFE_GPIO_I2S2_ON] = {"aud_gpio_i2s2_on", false, NULL}, + [MT8186_AFE_GPIO_I2S3_OFF] = {"aud_gpio_i2s3_off", false, NULL}, + [MT8186_AFE_GPIO_I2S3_ON] = {"aud_gpio_i2s3_on", false, NULL}, + [MT8186_AFE_GPIO_TDM_OFF] = {"aud_gpio_tdm_off", false, NULL}, + [MT8186_AFE_GPIO_TDM_ON] = {"aud_gpio_tdm_on", false, NULL}, + [MT8186_AFE_GPIO_PCM_OFF] = {"aud_gpio_pcm_off", false, NULL}, + [MT8186_AFE_GPIO_PCM_ON] = {"aud_gpio_pcm_on", false, NULL}, +}; + +static DEFINE_MUTEX(gpio_request_mutex); + +int mt8186_afe_gpio_init(struct device *dev) +{ + int i, j, ret; + + aud_pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(aud_pinctrl)) { + ret = PTR_ERR(aud_pinctrl); + dev_err(dev, "%s(), ret %d, cannot get aud_pinctrl!\n", + __func__, ret); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(aud_gpios); i++) { + aud_gpios[i].gpioctrl = pinctrl_lookup_state(aud_pinctrl, + aud_gpios[i].name); + if (IS_ERR(aud_gpios[i].gpioctrl)) { + ret = PTR_ERR(aud_gpios[i].gpioctrl); + dev_info(dev, "%s(), pinctrl_lookup_state %s fail, ret %d\n", + __func__, aud_gpios[i].name, ret); + } else { + aud_gpios[i].gpio_prepare = true; + } + } + + /* gpio status init */ + for (i = MT8186_DAI_ADDA; i <= MT8186_DAI_TDM_IN; i++) { + for (j = 0; j <= 1; j++) + mt8186_afe_gpio_request(dev, false, i, j); + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt8186_afe_gpio_init); + +static int mt8186_afe_gpio_select(struct device *dev, + enum mt8186_afe_gpio type) +{ + int ret = 0; + + if (type < 0 || type >= MT8186_AFE_GPIO_GPIO_NUM) { + dev_err(dev, "%s(), error, invalid gpio type %d\n", + __func__, type); + return -EINVAL; + } + + if (!aud_gpios[type].gpio_prepare) { + dev_err(dev, "%s(), error, gpio type %d not prepared\n", + __func__, type); + return -EIO; + } + + ret = pinctrl_select_state(aud_pinctrl, + aud_gpios[type].gpioctrl); + if (ret) { + dev_err(dev, "%s(), error, can not set gpio type %d\n", + __func__, type); + return ret; + } + + return 0; +} + +static int mt8186_afe_gpio_adda_dl(struct device *dev, bool enable) +{ + int ret; + + if (enable) { + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_ON); + if (ret) { + dev_err(dev, "%s(), MOSI CLK ON slect fail!\n", __func__); + return ret; + } + + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_ON); + if (ret) { + dev_err(dev, "%s(), MOSI DAT ON slect fail!\n", __func__); + return ret; + } + } else { + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_OFF); + if (ret) { + dev_err(dev, "%s(), MOSI DAT OFF slect fail!\n", __func__); + return ret; + } + + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_OFF); + if (ret) { + dev_err(dev, "%s(), MOSI CLK ON slect fail!\n", __func__); + return ret; + } + } + + return 0; +} + +static int mt8186_afe_gpio_adda_ul(struct device *dev, bool enable) +{ + int ret; + + if (enable) { + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_ON); + if (ret) { + dev_err(dev, "%s(), MISO CLK ON slect fail!\n", __func__); + return ret; + } + + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_ON); + if (ret) { + dev_err(dev, "%s(), MISO DAT ON slect fail!\n", __func__); + return ret; + } + } else { + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_OFF); + if (ret) { + dev_err(dev, "%s(), MISO DAT OFF slect fail!\n", __func__); + return ret; + } + + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_OFF); + if (ret) { + dev_err(dev, "%s(), MISO CLK OFF slect fail!\n", __func__); + return ret; + } + } + + return 0; +} + +int mt8186_afe_gpio_request(struct device *dev, bool enable, + int dai, int uplink) +{ + enum mt8186_afe_gpio sel; + int ret = -EINVAL; + + mutex_lock(&gpio_request_mutex); + + switch (dai) { + case MT8186_DAI_ADDA: + if (uplink) + ret = mt8186_afe_gpio_adda_ul(dev, enable); + else + ret = mt8186_afe_gpio_adda_dl(dev, enable); + goto unlock; + case MT8186_DAI_I2S_0: + sel = enable ? MT8186_AFE_GPIO_I2S0_ON : MT8186_AFE_GPIO_I2S0_OFF; + break; + case MT8186_DAI_I2S_1: + sel = enable ? MT8186_AFE_GPIO_I2S1_ON : MT8186_AFE_GPIO_I2S1_OFF; + break; + case MT8186_DAI_I2S_2: + sel = enable ? MT8186_AFE_GPIO_I2S2_ON : MT8186_AFE_GPIO_I2S2_OFF; + break; + case MT8186_DAI_I2S_3: + sel = enable ? MT8186_AFE_GPIO_I2S3_ON : MT8186_AFE_GPIO_I2S3_OFF; + break; + case MT8186_DAI_TDM_IN: + sel = enable ? MT8186_AFE_GPIO_TDM_ON : MT8186_AFE_GPIO_TDM_OFF; + break; + case MT8186_DAI_PCM: + sel = enable ? MT8186_AFE_GPIO_PCM_ON : MT8186_AFE_GPIO_PCM_OFF; + break; + default: + mutex_unlock(&gpio_request_mutex); + dev_err(dev, "%s(), invalid dai %d\n", __func__, dai); + goto unlock; + } + + ret = mt8186_afe_gpio_select(dev, sel); + +unlock: + mutex_unlock(&gpio_request_mutex); + + return ret; +} diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h new file mode 100644 index 000000000000..1ddc27838eb1 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * mt6833-afe-gpio.h -- Mediatek 6833 afe gpio ctrl definition + * + * Copyright (c) 2022 MediaTek Inc. + * Author: Jiaxin Yu + */ + +#ifndef _MT8186_AFE_GPIO_H_ +#define _MT8186_AFE_GPIO_H_ + +struct mtk_base_afe; + +int mt8186_afe_gpio_init(struct device *dev); + +int mt8186_afe_gpio_request(struct device *dev, bool enable, + int dai, int uplink); + +#endif -- cgit From 80d8cad2e9ce21517d50c7084c12a59d38a778f7 Mon Sep 17 00:00:00 2001 From: Jiaxin Yu Date: Mon, 23 May 2022 21:28:51 +0800 Subject: ASoC: mediatek: mt8186: add misc driver and register definitions Add mt8186 platform misc driver and data tables/register definitions files. Signed-off-by: Jiaxin Yu Link: https://lore.kernel.org/r/20220523132858.22166-14-jiaxin.yu@mediatek.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-interconnection.h | 69 + sound/soc/mediatek/mt8186/mt8186-misc-control.c | 252 ++ sound/soc/mediatek/mt8186/mt8186-reg.h | 2913 ++++++++++++++++++++ 3 files changed, 3234 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-interconnection.h create mode 100644 sound/soc/mediatek/mt8186/mt8186-misc-control.c create mode 100644 sound/soc/mediatek/mt8186/mt8186-reg.h diff --git a/sound/soc/mediatek/mt8186/mt8186-interconnection.h b/sound/soc/mediatek/mt8186/mt8186-interconnection.h new file mode 100644 index 000000000000..5b188d93ebd3 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-interconnection.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Mediatek MT8186 audio driver interconnection definition + * + * Copyright (c) 2022 MediaTek Inc. + * Author: Jiaxin Yu + */ + +#ifndef _MT8186_INTERCONNECTION_H_ +#define _MT8186_INTERCONNECTION_H_ + +/* in port define */ +#define I_I2S0_CH1 0 +#define I_I2S0_CH2 1 +#define I_ADDA_UL_CH1 3 +#define I_ADDA_UL_CH2 4 +#define I_DL1_CH1 5 +#define I_DL1_CH2 6 +#define I_DL2_CH1 7 +#define I_DL2_CH2 8 +#define I_PCM_1_CAP_CH1 9 +#define I_GAIN1_OUT_CH1 10 +#define I_GAIN1_OUT_CH2 11 +#define I_GAIN2_OUT_CH1 12 +#define I_GAIN2_OUT_CH2 13 +#define I_PCM_2_CAP_CH1 14 +#define I_ADDA_UL_CH3 17 +#define I_ADDA_UL_CH4 18 +#define I_DL12_CH1 19 +#define I_DL12_CH2 20 +#define I_DL12_CH3 5 +#define I_DL12_CH4 6 +#define I_PCM_2_CAP_CH2 21 +#define I_PCM_1_CAP_CH2 22 +#define I_DL3_CH1 23 +#define I_DL3_CH2 24 +#define I_I2S2_CH1 25 +#define I_I2S2_CH2 26 +#define I_I2S2_CH3 27 +#define I_I2S2_CH4 28 + +/* in port define >= 32 */ +#define I_32_OFFSET 32 +#define I_CONNSYS_I2S_CH1 (34 - I_32_OFFSET) +#define I_CONNSYS_I2S_CH2 (35 - I_32_OFFSET) +#define I_SRC_1_OUT_CH1 (36 - I_32_OFFSET) +#define I_SRC_1_OUT_CH2 (37 - I_32_OFFSET) +#define I_SRC_2_OUT_CH1 (38 - I_32_OFFSET) +#define I_SRC_2_OUT_CH2 (39 - I_32_OFFSET) +#define I_DL4_CH1 (40 - I_32_OFFSET) +#define I_DL4_CH2 (41 - I_32_OFFSET) +#define I_DL5_CH1 (42 - I_32_OFFSET) +#define I_DL5_CH2 (43 - I_32_OFFSET) +#define I_DL6_CH1 (44 - I_32_OFFSET) +#define I_DL6_CH2 (45 - I_32_OFFSET) +#define I_DL7_CH1 (46 - I_32_OFFSET) +#define I_DL7_CH2 (47 - I_32_OFFSET) +#define I_DL8_CH1 (48 - I_32_OFFSET) +#define I_DL8_CH2 (49 - I_32_OFFSET) +#define I_TDM_IN_CH1 (56 - I_32_OFFSET) +#define I_TDM_IN_CH2 (57 - I_32_OFFSET) +#define I_TDM_IN_CH3 (58 - I_32_OFFSET) +#define I_TDM_IN_CH4 (59 - I_32_OFFSET) +#define I_TDM_IN_CH5 (60 - I_32_OFFSET) +#define I_TDM_IN_CH6 (61 - I_32_OFFSET) +#define I_TDM_IN_CH7 (62 - I_32_OFFSET) +#define I_TDM_IN_CH8 (63 - I_32_OFFSET) + +#endif diff --git a/sound/soc/mediatek/mt8186/mt8186-misc-control.c b/sound/soc/mediatek/mt8186/mt8186-misc-control.c new file mode 100644 index 000000000000..2317de8c44c0 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-misc-control.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio Misc Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include +#include +#include +#include + +#include "../common/mtk-afe-fe-dai.h" +#include "../common/mtk-afe-platform-driver.h" +#include "mt8186-afe-common.h" + +static const char * const mt8186_sgen_mode_str[] = { + "I0I1", "I2", "I3I4", "I5I6", + "I7I8", "I9I22", "I10I11", "I12I13", + "I14I21", "I15I16", "I17I18", "I19I20", + "I23I24", "I25I26", "I27I28", "I33", + "I34I35", "I36I37", "I38I39", "I40I41", + "I42I43", "I44I45", "I46I47", "I48I49", + "I56I57", "I58I59", "I60I61", "I62I63", + "O0O1", "O2", "O3O4", "O5O6", + "O7O8", "O9O10", "O11", "O12", + "O13O14", "O15O16", "O17O18", "O19O20", + "O21O22", "O23O24", "O25", "O28O29", + "O34", "O35", "O32O33", "O36O37", + "O38O39", "O30O31", "O40O41", "O42O43", + "O44O45", "O46O47", "O48O49", "O50O51", + "O58O59", "O60O61", "O62O63", "O64O65", + "O66O67", "O68O69", "O26O27", "OFF", +}; + +static const int mt8186_sgen_mode_idx[] = { + 0, 2, 4, 6, + 8, 22, 10, 12, + 14, -1, 18, 20, + 24, 26, 28, 33, + 34, 36, 38, 40, + 42, 44, 46, 48, + 56, 58, 60, 62, + 128, 130, 132, 134, + 135, 138, 139, 140, + 142, 144, 166, 148, + 150, 152, 153, 156, + 162, 163, 160, 164, + 166, -1, 168, 170, + 172, 174, 176, 178, + 186, 188, 190, 192, + 194, 196, -1, -1, +}; + +static const char * const mt8186_sgen_rate_str[] = { + "8K", "11K", "12K", "16K", + "22K", "24K", "32K", "44K", + "48K", "88k", "96k", "176k", + "192k" +}; + +static const int mt8186_sgen_rate_idx[] = { + 0, 1, 2, 4, + 5, 6, 8, 9, + 10, 11, 12, 13, + 14 +}; + +/* this order must match reg bit amp_div_ch1/2 */ +static const char * const mt8186_sgen_amp_str[] = { + "1/128", "1/64", "1/32", "1/16", "1/8", "1/4", "1/2", "1" }; + +static int mt8186_sgen_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + ucontrol->value.integer.value[0] = afe_priv->sgen_mode; + + return 0; +} + +static int mt8186_sgen_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int mode; + int mode_idx; + + if (ucontrol->value.enumerated.item[0] >= e->items) + return -EINVAL; + + mode = ucontrol->value.integer.value[0]; + mode_idx = mt8186_sgen_mode_idx[mode]; + + dev_dbg(afe->dev, "%s(), mode %d, mode_idx %d\n", + __func__, mode, mode_idx); + + if (mode == afe_priv->sgen_mode) + return 0; + + if (mode_idx >= 0) { + regmap_update_bits(afe->regmap, AFE_SINEGEN_CON2, + INNER_LOOP_BACK_MODE_MASK_SFT, + mode_idx << INNER_LOOP_BACK_MODE_SFT); + regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0, + DAC_EN_MASK_SFT, BIT(DAC_EN_SFT)); + } else { + /* disable sgen */ + regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0, + DAC_EN_MASK_SFT, 0); + regmap_update_bits(afe->regmap, AFE_SINEGEN_CON2, + INNER_LOOP_BACK_MODE_MASK_SFT, + 0x3f << INNER_LOOP_BACK_MODE_SFT); + } + + afe_priv->sgen_mode = mode; + + return 1; +} + +static int mt8186_sgen_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + ucontrol->value.integer.value[0] = afe_priv->sgen_rate; + + return 0; +} + +static int mt8186_sgen_rate_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int rate; + + if (ucontrol->value.enumerated.item[0] >= e->items) + return -EINVAL; + + rate = ucontrol->value.integer.value[0]; + + dev_dbg(afe->dev, "%s(), rate %d\n", __func__, rate); + + if (rate == afe_priv->sgen_rate) + return 0; + + regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0, + SINE_MODE_CH1_MASK_SFT, + mt8186_sgen_rate_idx[rate] << SINE_MODE_CH1_SFT); + + regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0, + SINE_MODE_CH2_MASK_SFT, + mt8186_sgen_rate_idx[rate] << SINE_MODE_CH2_SFT); + + afe_priv->sgen_rate = rate; + + return 1; +} + +static int mt8186_sgen_amplitude_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + ucontrol->value.integer.value[0] = afe_priv->sgen_amplitude; + return 0; +} + +static int mt8186_sgen_amplitude_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int amplitude; + + if (ucontrol->value.enumerated.item[0] >= e->items) + return -EINVAL; + + amplitude = ucontrol->value.integer.value[0]; + if (amplitude > AMP_DIV_CH1_MASK) { + dev_err(afe->dev, "%s(), amplitude %d invalid\n", + __func__, amplitude); + return -EINVAL; + } + + dev_dbg(afe->dev, "%s(), amplitude %d\n", __func__, amplitude); + + if (amplitude == afe_priv->sgen_amplitude) + return 0; + + regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0, + AMP_DIV_CH1_MASK_SFT, + amplitude << AMP_DIV_CH1_SFT); + regmap_update_bits(afe->regmap, AFE_SINEGEN_CON0, + AMP_DIV_CH2_MASK_SFT, + amplitude << AMP_DIV_CH2_SFT); + + afe_priv->sgen_amplitude = amplitude; + + return 1; +} + +static const struct soc_enum mt8186_afe_sgen_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_sgen_mode_str), + mt8186_sgen_mode_str), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_sgen_rate_str), + mt8186_sgen_rate_str), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_sgen_amp_str), + mt8186_sgen_amp_str), +}; + +static const struct snd_kcontrol_new mt8186_afe_sgen_controls[] = { + SOC_ENUM_EXT("Audio_SineGen_Switch", mt8186_afe_sgen_enum[0], + mt8186_sgen_get, mt8186_sgen_set), + SOC_ENUM_EXT("Audio_SineGen_SampleRate", mt8186_afe_sgen_enum[1], + mt8186_sgen_rate_get, mt8186_sgen_rate_set), + SOC_ENUM_EXT("Audio_SineGen_Amplitude", mt8186_afe_sgen_enum[2], + mt8186_sgen_amplitude_get, mt8186_sgen_amplitude_set), + SOC_SINGLE("Audio_SineGen_Mute_Ch1", AFE_SINEGEN_CON0, + MUTE_SW_CH1_MASK_SFT, MUTE_SW_CH1_MASK, 0), + SOC_SINGLE("Audio_SineGen_Mute_Ch2", AFE_SINEGEN_CON0, + MUTE_SW_CH2_MASK_SFT, MUTE_SW_CH2_MASK, 0), + SOC_SINGLE("Audio_SineGen_Freq_Div_Ch1", AFE_SINEGEN_CON0, + FREQ_DIV_CH1_SFT, FREQ_DIV_CH1_MASK, 0), + SOC_SINGLE("Audio_SineGen_Freq_Div_Ch2", AFE_SINEGEN_CON0, + FREQ_DIV_CH2_SFT, FREQ_DIV_CH2_MASK, 0), +}; + +int mt8186_add_misc_control(struct snd_soc_component *component) +{ + snd_soc_add_component_controls(component, + mt8186_afe_sgen_controls, + ARRAY_SIZE(mt8186_afe_sgen_controls)); + + return 0; +} diff --git a/sound/soc/mediatek/mt8186/mt8186-reg.h b/sound/soc/mediatek/mt8186/mt8186-reg.h new file mode 100644 index 000000000000..53c3eb7283d8 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-reg.h @@ -0,0 +1,2913 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * mt8186-reg.h -- Mediatek 8186 audio driver reg definition + * + * Copyright (c) 2022 MediaTek Inc. + * Author: Jiaxin Yu + */ + +#ifndef _MT8186_REG_H_ +#define _MT8186_REG_H_ + +/* reg bit enum */ +enum { + MT8186_MEMIF_PBUF_SIZE_32_BYTES, + MT8186_MEMIF_PBUF_SIZE_64_BYTES, + MT8186_MEMIF_PBUF_SIZE_128_BYTES, + MT8186_MEMIF_PBUF_SIZE_256_BYTES, + MT8186_MEMIF_PBUF_SIZE_NUM, +}; + +/***************************************************************************** + * R E G I S T E R D E F I N I T I O N + *****************************************************************************/ +/* AUDIO_TOP_CON0 */ +#define RESERVED_SFT 31 +#define RESERVED_MASK_SFT BIT(31) +#define AHB_IDLE_EN_INT_SFT 30 +#define AHB_IDLE_EN_INT_MASK_SFT BIT(30) +#define AHB_IDLE_EN_EXT_SFT 29 +#define AHB_IDLE_EN_EXT_MASK_SFT BIT(29) +#define PDN_NLE_SFT 28 +#define PDN_NLE_MASK_SFT BIT(28) +#define PDN_TML_SFT 27 +#define PDN_TML_MASK_SFT BIT(27) +#define PDN_DAC_PREDIS_SFT 26 +#define PDN_DAC_PREDIS_MASK_SFT BIT(26) +#define PDN_DAC_SFT 25 +#define PDN_DAC_MASK_SFT BIT(25) +#define PDN_ADC_SFT 24 +#define PDN_ADC_MASK_SFT BIT(24) +#define PDN_TDM_CK_SFT 20 +#define PDN_TDM_CK_MASK_SFT BIT(20) +#define PDN_APLL_TUNER_SFT 19 +#define PDN_APLL_TUNER_MASK_SFT BIT(19) +#define PDN_APLL2_TUNER_SFT 18 +#define PDN_APLL2_TUNER_MASK_SFT BIT(18) +#define APB3_SEL_SFT 14 +#define APB3_SEL_MASK_SFT BIT(14) +#define APB_R2T_SFT 13 +#define APB_R2T_MASK_SFT BIT(13) +#define APB_W2T_SFT 12 +#define APB_W2T_MASK_SFT BIT(12) +#define PDN_24M_SFT 9 +#define PDN_24M_MASK_SFT BIT(9) +#define PDN_22M_SFT 8 +#define PDN_22M_MASK_SFT BIT(8) +#define PDN_AFE_SFT 2 +#define PDN_AFE_MASK_SFT BIT(2) + +/* AUDIO_TOP_CON1 */ +#define PDN_3RD_DAC_HIRES_SFT 31 +#define PDN_3RD_DAC_HIRES_MASK_SFT BIT(31) +#define PDN_3RD_DAC_TML_SFT 30 +#define PDN_3RD_DAC_TML_MASK_SFT BIT(30) +#define PDN_3RD_DAC_PREDIS_SFT 29 +#define PDN_3RD_DAC_PREDIS_MASK_SFT BIT(29) +#define PDN_3RD_DAC_SFT 28 +#define PDN_3RD_DAC_MASK_SFT BIT(28) +#define I2S_SOFT_RST5_SFT 22 +#define I2S_SOFT_RST5_MASK_SFT BIT(22) +#define PDN_ADDA6_ADC_HIRES_SFT 21 +#define PDN_ADDA6_ADC_HIRES_MASK_SFT BIT(21) +#define PDN_ADDA6_ADC_SFT 20 +#define PDN_ADDA6_ADC_MASK_SFT BIT(20) +#define PDN_ADC_HIRES_TML_SFT 17 +#define PDN_ADC_HIRES_TML_MASK_SFT BIT(17) +#define PDN_ADC_HIRES_SFT 16 +#define PDN_ADC_HIRES_MASK_SFT BIT(16) +#define PDN_DAC_HIRES_SFT 15 +#define PDN_DAC_HIRES_MASK_SFT BIT(15) +#define PDN_GENERAL2_ASRC_SFT 14 +#define PDN_GENERAL2_ASRC_MASK_SFT BIT(14) +#define PDN_GENERAL1_ASRC_SFT 13 +#define PDN_GENERAL1_ASRC_MASK_SFT BIT(13) +#define PDN_CONNSYS_I2S_ASRC_SFT 12 +#define PDN_CONNSYS_I2S_ASRC_MASK_SFT BIT(12) +#define I2S4_BCLK_SW_CG_SFT 7 +#define I2S4_BCLK_SW_CG_MASK_SFT BIT(7) +#define I2S3_BCLK_SW_CG_SFT 6 +#define I2S3_BCLK_SW_CG_MASK_SFT BIT(6) +#define I2S2_BCLK_SW_CG_SFT 5 +#define I2S2_BCLK_SW_CG_MASK_SFT BIT(5) +#define I2S1_BCLK_SW_CG_SFT 4 +#define I2S1_BCLK_SW_CG_MASK_SFT BIT(4) +#define I2S_SOFT_RST2_SFT 2 +#define I2S_SOFT_RST2_MASK_SFT BIT(2) +#define I2S_SOFT_RST_SFT 1 +#define I2S_SOFT_RST_MASK_SFT BIT(1) + +/* AUDIO_TOP_CON3 */ +#define BUSY_SFT 31 +#define BUSY_MASK_SFT BIT(31) +#define OS_DISABLE_SFT 30 +#define OS_DISABLE_MASK_SFT BIT(30) +#define CG_DISABLE_SFT 29 +#define CG_DISABLE_MASK_SFT BIT(29) +#define CLEAR_FLAG_SFT 0 +#define CLEAR_FLAG_MASK_SFT BIT(0) + +/* AFE_DAC_CON0 */ +#define VUL12_ON_SFT 31 +#define VUL12_ON_MASK_SFT BIT(31) +#define MOD_DAI_ON_SFT 30 +#define MOD_DAI_ON_MASK_SFT BIT(30) +#define DAI_ON_SFT 29 +#define DAI_ON_MASK_SFT BIT(29) +#define DAI2_ON_SFT 28 +#define DAI2_ON_MASK_SFT BIT(28) +#define VUL6_ON_SFT 23 +#define VUL6_ON_MASK_SFT BIT(23) +#define VUL5_ON_SFT 22 +#define VUL5_ON_MASK_SFT BIT(22) +#define VUL4_ON_SFT 21 +#define VUL4_ON_MASK_SFT BIT(21) +#define VUL3_ON_SFT 20 +#define VUL3_ON_MASK_SFT BIT(20) +#define VUL2_ON_SFT 19 +#define VUL2_ON_MASK_SFT BIT(19) +#define VUL_ON_SFT 18 +#define VUL_ON_MASK_SFT BIT(18) +#define AWB2_ON_SFT 17 +#define AWB2_ON_MASK_SFT BIT(17) +#define AWB_ON_SFT 16 +#define AWB_ON_MASK_SFT BIT(16) +#define DL12_ON_SFT 15 +#define DL12_ON_MASK_SFT BIT(15) +#define DL8_ON_SFT 11 +#define DL8_ON_MASK_SFT BIT(11) +#define DL7_ON_SFT 10 +#define DL7_ON_MASK_SFT BIT(10) +#define DL6_ON_SFT 9 +#define DL6_ON_MASK_SFT BIT(9) +#define DL5_ON_SFT 8 +#define DL5_ON_MASK_SFT BIT(8) +#define DL4_ON_SFT 7 +#define DL4_ON_MASK_SFT BIT(7) +#define DL3_ON_SFT 6 +#define DL3_ON_MASK_SFT BIT(6) +#define DL2_ON_SFT 5 +#define DL2_ON_MASK_SFT BIT(5) +#define DL1_ON_SFT 4 +#define DL1_ON_MASK_SFT BIT(4) +#define AUDIO_AFE_ON_SFT 0 +#define AUDIO_AFE_ON_MASK_SFT BIT(0) + +/* AFE_DAC_MON */ +#define AFE_ON_RETM_SFT 0 +#define AFE_ON_RETM_MASK_SFT BIT(0) + +/* AFE_I2S_CON */ +#define BCK_NEG_EG_LATCH_SFT 30 +#define BCK_NEG_EG_LATCH_MASK_SFT BIT(30) +#define BCK_INV_SFT 29 +#define BCK_INV_MASK_SFT BIT(29) +#define I2SIN_PAD_SEL_SFT 28 +#define I2SIN_PAD_SEL_MASK_SFT BIT(28) +#define I2S_LOOPBACK_SFT 20 +#define I2S_LOOPBACK_MASK_SFT BIT(20) +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_SFT 17 +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_MASK_SFT BIT(17) +#define I2S1_HD_EN_SFT 12 +#define I2S1_HD_EN_MASK_SFT BIT(12) +#define I2S_OUT_MODE_SFT 8 +#define I2S_OUT_MODE_MASK_SFT GENMASK(11, 8) +#define INV_PAD_CTRL_SFT 7 +#define INV_PAD_CTRL_MASK_SFT BIT(7) +#define I2S_BYPSRC_SFT 6 +#define I2S_BYPSRC_MASK_SFT BIT(6) +#define INV_LRCK_SFT 5 +#define INV_LRCK_MASK_SFT BIT(5) +#define I2S_FMT_SFT 3 +#define I2S_FMT_MASK_SFT BIT(3) +#define I2S_SRC_SFT 2 +#define I2S_SRC_MASK_SFT BIT(2) +#define I2S_WLEN_SFT 1 +#define I2S_WLEN_MASK_SFT BIT(1) +#define I2S_EN_SFT 0 +#define I2S_EN_MASK_SFT BIT(0) + +/* AFE_I2S_CON1 */ +#define I2S2_LR_SWAP_SFT 31 +#define I2S2_LR_SWAP_MASK_SFT BIT(31) +#define I2S2_SEL_O19_O20_SFT 18 +#define I2S2_SEL_O19_O20_MASK_SFT BIT(18) +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_SFT 17 +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_MASK_SFT BIT(17) +#define I2S2_SEL_O03_O04_SFT 16 +#define I2S2_SEL_O03_O04_MASK_SFT BIT(16) +#define I2S2_HD_EN_SFT 12 +#define I2S2_HD_EN_MASK_SFT BIT(12) +#define I2S2_OUT_MODE_SFT 8 +#define I2S2_OUT_MODE_MASK_SFT GENMASK(11, 8) +#define INV_LRCK_SFT 5 +#define INV_LRCK_MASK_SFT BIT(5) +#define I2S2_FMT_SFT 3 +#define I2S2_FMT_MASK_SFT BIT(3) +#define I2S2_WLEN_SFT 1 +#define I2S2_WLEN_MASK_SFT BIT(1) +#define I2S2_EN_SFT 0 +#define I2S2_EN_MASK_SFT BIT(0) + +/* AFE_I2S_CON2 */ +#define I2S3_LR_SWAP_SFT 31 +#define I2S3_LR_SWAP_MASK_SFT BIT(31) +#define I2S3_UPDATE_WORD_SFT 24 +#define I2S3_UPDATE_WORD_MASK_SFT GENMASK(28, 24) +#define I2S3_BCK_INV_SFT 23 +#define I2S3_BCK_INV_MASK_SFT BIT(23) +#define I2S3_FPGA_BIT_TEST_SFT 22 +#define I2S3_FPGA_BIT_TEST_MASK_SFT BIT(22) +#define I2S3_FPGA_BIT_SFT 21 +#define I2S3_FPGA_BIT_MASK_SFT BIT(21) +#define I2S3_LOOPBACK_SFT 20 +#define I2S3_LOOPBACK_MASK_SFT BIT(20) +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_SFT 17 +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_MASK_SFT BIT(17) +#define I2S3_HD_EN_SFT 12 +#define I2S3_HD_EN_MASK_SFT BIT(12) +#define I2S3_OUT_MODE_SFT 8 +#define I2S3_OUT_MODE_MASK_SFT GENMASK(11, 8) +#define I2S3_FMT_SFT 3 +#define I2S3_FMT_MASK_SFT BIT(3) +#define I2S3_WLEN_SFT 1 +#define I2S3_WLEN_MASK_SFT BIT(1) +#define I2S3_EN_SFT 0 +#define I2S3_EN_MASK_SFT BIT(0) + +/* AFE_I2S_CON3 */ +#define I2S4_LR_SWAP_SFT 31 +#define I2S4_LR_SWAP_MASK_SFT BIT(31) +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_SFT 17 +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_MASK_SFT BIT(17) +#define I2S4_HD_EN_SFT 12 +#define I2S4_HD_EN_MASK_SFT BIT(12) +#define I2S4_OUT_MODE_SFT 8 +#define I2S4_OUT_MODE_MASK_SFT GENMASK(11, 8) +#define INV_LRCK_SFT 5 +#define INV_LRCK_MASK_SFT BIT(5) +#define I2S4_FMT_SFT 3 +#define I2S4_FMT_MASK_SFT BIT(3) +#define I2S4_WLEN_SFT 1 +#define I2S4_WLEN_MASK_SFT BIT(1) +#define I2S4_EN_SFT 0 +#define I2S4_EN_MASK_SFT BIT(0) + +/* AFE_I2S_CON4 */ +#define I2S_LOOPBACK_SFT 20 +#define I2S_LOOPBACK_MASK 0x1 +#define I2S_LOOPBACK_MASK_SFT BIT(20) +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_SFT 17 +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_MASK 0x1 +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_MASK_SFT BIT(17) +#define INV_LRCK_SFT 5 +#define INV_LRCK_MASK 0x1 +#define INV_LRCK_MASK_SFT BIT(5) + +/* AFE_CONNSYS_I2S_CON */ +#define BCK_NEG_EG_LATCH_SFT 30 +#define BCK_NEG_EG_LATCH_MASK_SFT BIT(30) +#define BCK_INV_SFT 29 +#define BCK_INV_MASK_SFT BIT(29) +#define I2SIN_PAD_SEL_SFT 28 +#define I2SIN_PAD_SEL_MASK_SFT BIT(28) +#define I2S_LOOPBACK_SFT 20 +#define I2S_LOOPBACK_MASK_SFT BIT(20) +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_SFT 17 +#define I2S_ONOFF_NOT_RESET_CK_ENABLE_MASK_SFT BIT(17) +#define I2S_MODE_SFT 8 +#define I2S_MODE_MASK_SFT GENMASK(11, 8) +#define INV_PAD_CTRL_SFT 7 +#define INV_PAD_CTRL_MASK_SFT BIT(7) +#define I2S_BYPSRC_SFT 6 +#define I2S_BYPSRC_MASK_SFT BIT(6) +#define INV_LRCK_SFT 5 +#define INV_LRCK_MASK_SFT BIT(5) +#define I2S_FMT_SFT 3 +#define I2S_FMT_MASK_SFT BIT(3) +#define I2S_SRC_SFT 2 +#define I2S_SRC_MASK_SFT BIT(2) +#define I2S_WLEN_SFT 1 +#define I2S_WLEN_MASK_SFT BIT(1) +#define I2S_EN_SFT 0 +#define I2S_EN_MASK_SFT BIT(0) + +/* AFE_ASRC_2CH_CON2 */ +#define CHSET_O16BIT_SFT 19 +#define CHSET_O16BIT_MASK_SFT BIT(19) +#define CHSET_CLR_IIR_HISTORY_SFT 17 +#define CHSET_CLR_IIR_HISTORY_MASK_SFT BIT(17) +#define CHSET_IS_MONO_SFT 16 +#define CHSET_IS_MONO_MASK_SFT BIT(16) +#define CHSET_IIR_EN_SFT 11 +#define CHSET_IIR_EN_MASK_SFT BIT(11) +#define CHSET_IIR_STAGE_SFT 8 +#define CHSET_IIR_STAGE_MASK_SFT GENMASK(10, 8) +#define CHSET_STR_CLR_SFT 5 +#define CHSET_STR_CLR_MASK_SFT BIT(5) +#define CHSET_ON_SFT 2 +#define CHSET_ON_MASK_SFT BIT(2) +#define COEFF_SRAM_CTRL_SFT 1 +#define COEFF_SRAM_CTRL_MASK_SFT BIT(1) +#define ASM_ON_SFT 0 +#define ASM_ON_MASK_SFT BIT(0) + +/* AFE_GAIN1_CON0 */ +#define GAIN1_SAMPLE_PER_STEP_SFT 8 +#define GAIN1_SAMPLE_PER_STEP_MASK_SFT GENMASK(15, 8) +#define GAIN1_MODE_SFT 4 +#define GAIN1_MODE_MASK_SFT GENMASK(7, 4) +#define GAIN1_ON_SFT 0 +#define GAIN1_ON_MASK_SFT BIT(0) + +/* AFE_GAIN1_CON1 */ +#define GAIN1_TARGET_SFT 0 +#define GAIN1_TARGET_MASK 0xfffffff +#define GAIN1_TARGET_MASK_SFT GENMASK(27, 0) + +/* AFE_GAIN2_CON0 */ +#define GAIN2_SAMPLE_PER_STEP_SFT 8 +#define GAIN2_SAMPLE_PER_STEP_MASK_SFT GENMASK(15, 8) +#define GAIN2_MODE_SFT 4 +#define GAIN2_MODE_MASK_SFT GENMASK(7, 4) +#define GAIN2_ON_SFT 0 +#define GAIN2_ON_MASK_SFT BIT(0) + +/* AFE_GAIN2_CON1 */ +#define GAIN2_TARGET_SFT 0 +#define GAIN2_TARGET_MASK 0xfffffff +#define GAIN2_TARGET_MASK_SFT GENMASK(27, 0) + +/* AFE_GAIN1_CUR */ +#define AFE_GAIN1_CUR_SFT 0 +#define AFE_GAIN1_CUR_MASK_SFT GENMASK(27, 0) + +/* AFE_GAIN2_CUR */ +#define AFE_GAIN2_CUR_SFT 0 +#define AFE_GAIN2_CUR_MASK_SFT GENMASK(27, 0) + +/* PCM_INTF_CON1 */ +#define PCM_FIX_VALUE_SEL_SFT 31 +#define PCM_FIX_VALUE_SEL_MASK_SFT BIT(31) +#define PCM_BUFFER_LOOPBACK_SFT 30 +#define PCM_BUFFER_LOOPBACK_MASK_SFT BIT(30) +#define PCM_PARALLEL_LOOPBACK_SFT 29 +#define PCM_PARALLEL_LOOPBACK_MASK_SFT BIT(29) +#define PCM_SERIAL_LOOPBACK_SFT 28 +#define PCM_SERIAL_LOOPBACK_MASK_SFT BIT(28) +#define PCM_DAI_PCM_LOOPBACK_SFT 27 +#define PCM_DAI_PCM_LOOPBACK_MASK_SFT BIT(27) +#define PCM_I2S_PCM_LOOPBACK_SFT 26 +#define PCM_I2S_PCM_LOOPBACK_MASK_SFT BIT(26) +#define PCM_SYNC_DELSEL_SFT 25 +#define PCM_SYNC_DELSEL_MASK_SFT BIT(25) +#define PCM_TX_LR_SWAP_SFT 24 +#define PCM_TX_LR_SWAP_MASK_SFT BIT(24) +#define PCM_SYNC_OUT_INV_SFT 23 +#define PCM_SYNC_OUT_INV_MASK_SFT BIT(23) +#define PCM_BCLK_OUT_INV_SFT 22 +#define PCM_BCLK_OUT_INV_MASK_SFT BIT(22) +#define PCM_SYNC_IN_INV_SFT 21 +#define PCM_SYNC_IN_INV_MASK_SFT BIT(21) +#define PCM_BCLK_IN_INV_SFT 20 +#define PCM_BCLK_IN_INV_MASK_SFT BIT(20) +#define PCM_TX_LCH_RPT_SFT 19 +#define PCM_TX_LCH_RPT_MASK_SFT BIT(19) +#define PCM_VBT_16K_MODE_SFT 18 +#define PCM_VBT_16K_MODE_MASK_SFT BIT(18) +#define PCM_EXT_MODEM_SFT 17 +#define PCM_EXT_MODEM_MASK_SFT BIT(17) +#define PCM_24BIT_SFT 16 +#define PCM_24BIT_MASK_SFT BIT(16) +#define PCM_WLEN_SFT 14 +#define PCM_WLEN_MASK_SFT GENMASK(15, 14) +#define PCM_SYNC_LENGTH_SFT 9 +#define PCM_SYNC_LENGTH_MASK_SFT GENMASK(13, 9) +#define PCM_SYNC_TYPE_SFT 8 +#define PCM_SYNC_TYPE_MASK_SFT BIT(8) +#define PCM_BT_MODE_SFT 7 +#define PCM_BT_MODE_MASK_SFT BIT(7) +#define PCM_BYP_ASRC_SFT 6 +#define PCM_BYP_ASRC_MASK_SFT BIT(6) +#define PCM_SLAVE_SFT 5 +#define PCM_SLAVE_MASK_SFT BIT(5) +#define PCM_MODE_SFT 3 +#define PCM_MODE_MASK_SFT GENMASK(4, 3) +#define PCM_FMT_SFT 1 +#define PCM_FMT_MASK_SFT GENMASK(2, 1) +#define PCM_EN_SFT 0 +#define PCM_EN_MASK_SFT BIT(0) + +/* PCM_INTF_CON2 */ +#define PCM1_TX_FIFO_OV_SFT 31 +#define PCM1_TX_FIFO_OV_MASK_SFT BIT(31) +#define PCM1_RX_FIFO_OV_SFT 30 +#define PCM1_RX_FIFO_OV_MASK_SFT BIT(30) +#define PCM2_TX_FIFO_OV_SFT 29 +#define PCM2_TX_FIFO_OV_MASK_SFT BIT(29) +#define PCM2_RX_FIFO_OV_SFT 28 +#define PCM2_RX_FIFO_OV_MASK_SFT BIT(28) +#define PCM1_SYNC_GLITCH_SFT 27 +#define PCM1_SYNC_GLITCH_MASK_SFT BIT(27) +#define PCM2_SYNC_GLITCH_SFT 26 +#define PCM2_SYNC_GLITCH_MASK_SFT BIT(26) +#define TX3_RCH_DBG_MODE_SFT 17 +#define TX3_RCH_DBG_MODE_MASK_SFT BIT(17) +#define PCM1_PCM2_LOOPBACK_SFT 16 +#define PCM1_PCM2_LOOPBACK_MASK_SFT BIT(16) +#define DAI_PCM_LOOPBACK_CH_SFT 14 +#define DAI_PCM_LOOPBACK_CH_MASK_SFT GENMASK(15, 14) +#define I2S_PCM_LOOPBACK_CH_SFT 12 +#define I2S_PCM_LOOPBACK_CH_MASK_SFT GENMASK(13, 12) +#define TX_FIX_VALUE_SFT 0 +#define TX_FIX_VALUE_MASK_SFT GENMASK(7, 0) + +/* PCM2_INTF_CON */ +#define PCM2_TX_FIX_VALUE_SFT 24 +#define PCM2_TX_FIX_VALUE_MASK_SFT GENMASK(31, 24) +#define PCM2_FIX_VALUE_SEL_SFT 23 +#define PCM2_FIX_VALUE_SEL_MASK_SFT BIT(23) +#define PCM2_BUFFER_LOOPBACK_SFT 22 +#define PCM2_BUFFER_LOOPBACK_MASK_SFT BIT(22) +#define PCM2_PARALLEL_LOOPBACK_SFT 21 +#define PCM2_PARALLEL_LOOPBACK_MASK_SFT BIT(21) +#define PCM2_SERIAL_LOOPBACK_SFT 20 +#define PCM2_SERIAL_LOOPBACK_MASK_SFT BIT(20) +#define PCM2_DAI_PCM_LOOPBACK_SFT 19 +#define PCM2_DAI_PCM_LOOPBACK_MASK_SFT BIT(19) +#define PCM2_I2S_PCM_LOOPBACK_SFT 18 +#define PCM2_I2S_PCM_LOOPBACK_MASK_SFT BIT(18) +#define PCM2_SYNC_DELSEL_SFT 17 +#define PCM2_SYNC_DELSEL_MASK_SFT BIT(17) +#define PCM2_TX_LR_SWAP_SFT 16 +#define PCM2_TX_LR_SWAP_MASK_SFT BIT(16) +#define PCM2_SYNC_IN_INV_SFT 15 +#define PCM2_SYNC_IN_INV_MASK_SFT BIT(15) +#define PCM2_BCLK_IN_INV_SFT 14 +#define PCM2_BCLK_IN_INV_MASK_SFT BIT(14) +#define PCM2_TX_LCH_RPT_SFT 13 +#define PCM2_TX_LCH_RPT_MASK_SFT BIT(13) +#define PCM2_VBT_16K_MODE_SFT 12 +#define PCM2_VBT_16K_MODE_MASK_SFT BIT(12) +#define PCM2_LOOPBACK_CH_SEL_SFT 10 +#define PCM2_LOOPBACK_CH_SEL_MASK_SFT GENMASK(11, 10) +#define PCM2_TX2_BT_MODE_SFT 8 +#define PCM2_TX2_BT_MODE_MASK_SFT BIT(8) +#define PCM2_BT_MODE_SFT 7 +#define PCM2_BT_MODE_MASK_SFT BIT(7) +#define PCM2_AFIFO_SFT 6 +#define PCM2_AFIFO_MASK_SFT BIT(6) +#define PCM2_WLEN_SFT 5 +#define PCM2_WLEN_MASK_SFT BIT(5) +#define PCM2_MODE_SFT 3 +#define PCM2_MODE_MASK_SFT GENMASK(4, 3) +#define PCM2_FMT_SFT 1 +#define PCM2_FMT_MASK_SFT GENMASK(2, 1) +#define PCM2_EN_SFT 0 +#define PCM2_EN_MASK_SFT BIT(0) + +// AFE_CM1_CON +#define CHANNEL_MERGE0_DEBUG_MODE_SFT (31) +#define CHANNEL_MERGE0_DEBUG_MODE_MASK_SFT BIT(31) +#define VUL3_BYPASS_CM_SFT (30) +#define VUL3_BYPASS_CM_MASK (0x1) +#define VUL3_BYPASS_CM_MASK_SFT BIT(30) +#define CM1_DEBUG_MODE_SEL_SFT (29) +#define CM1_DEBUG_MODE_SEL_MASK_SFT BIT(29) +#define CHANNEL_MERGE0_UPDATE_CNT_SFT (16) +#define CHANNEL_MERGE0_UPDATE_CNT_MASK_SFT GENMASK(28, 16) +#define CM1_FS_SELECT_SFT (8) +#define CM1_FS_SELECT_MASK_SFT GENMASK(12, 8) +#define CHANNEL_MERGE0_CHNUM_SFT (3) +#define CHANNEL_MERGE0_CHNUM_MASK_SFT GENMASK(7, 3) +#define CHANNEL_MERGE0_BYTE_SWAP_SFT (1) +#define CHANNEL_MERGE0_BYTE_SWAP_MASK_SFT BIT(1) +#define CHANNEL_MERGE0_EN_SFT (0) +#define CHANNEL_MERGE0_EN_MASK_SFT BIT(0) + +/* AFE_ADDA_MTKAIF_CFG0 */ +#define MTKAIF_RXIF_CLKINV_ADC_SFT 31 +#define MTKAIF_RXIF_CLKINV_ADC_MASK_SFT BIT(31) +#define MTKAIF_RXIF_BYPASS_SRC_SFT 17 +#define MTKAIF_RXIF_BYPASS_SRC_MASK_SFT BIT(17) +#define MTKAIF_RXIF_PROTOCOL2_SFT 16 +#define MTKAIF_RXIF_PROTOCOL2_MASK_SFT BIT(16) +#define MTKAIF_TXIF_BYPASS_SRC_SFT 5 +#define MTKAIF_TXIF_BYPASS_SRC_MASK_SFT BIT(5) +#define MTKAIF_TXIF_PROTOCOL2_SFT 4 +#define MTKAIF_TXIF_PROTOCOL2_MASK_SFT BIT(4) +#define MTKAIF_TXIF_8TO5_SFT 2 +#define MTKAIF_TXIF_8TO5_MASK_SFT BIT(2) +#define MTKAIF_RXIF_8TO5_SFT 1 +#define MTKAIF_RXIF_8TO5_MASK_SFT BIT(1) +#define MTKAIF_IF_LOOPBACK1_SFT 0 +#define MTKAIF_IF_LOOPBACK1_MASK_SFT BIT(0) + +/* AFE_ADDA_MTKAIF_RX_CFG2 */ +#define MTKAIF_RXIF_DETECT_ON_PROTOCOL2_SFT 16 +#define MTKAIF_RXIF_DETECT_ON_PROTOCOL2_MASK_SFT BIT(16) +#define MTKAIF_RXIF_DELAY_CYCLE_SFT 12 +#define MTKAIF_RXIF_DELAY_CYCLE_MASK_SFT GENMASK(15, 12) +#define MTKAIF_RXIF_DELAY_DATA_SFT 8 +#define MTKAIF_RXIF_DELAY_DATA_MASK 0x1 +#define MTKAIF_RXIF_DELAY_DATA_MASK_SFT BIT(8) +#define MTKAIF_RXIF_FIFO_RSP_PROTOCOL2_SFT 4 +#define MTKAIF_RXIF_FIFO_RSP_PROTOCOL2_MASK_SFT GENMASK(6, 4) + +/* AFE_ADDA_DL_SRC2_CON0 */ +#define DL_2_INPUT_MODE_CTL_SFT 28 +#define DL_2_INPUT_MODE_CTL_MASK_SFT GENMASK(31, 28) +#define DL_2_CH1_SATURATION_EN_CTL_SFT 27 +#define DL_2_CH1_SATURATION_EN_CTL_MASK_SFT BIT(27) +#define DL_2_CH2_SATURATION_EN_CTL_SFT 26 +#define DL_2_CH2_SATURATION_EN_CTL_MASK_SFT BIT(26) +#define DL_2_OUTPUT_SEL_CTL_SFT 24 +#define DL_2_OUTPUT_SEL_CTL_MASK_SFT GENMASK(25, 24) +#define DL_2_FADEIN_0START_EN_SFT 16 +#define DL_2_FADEIN_0START_EN_MASK_SFT GENMASK(17, 16) +#define DL_DISABLE_HW_CG_CTL_SFT 15 +#define DL_DISABLE_HW_CG_CTL_MASK_SFT BIT(15) +#define C_DATA_EN_SEL_CTL_PRE_SFT 14 +#define C_DATA_EN_SEL_CTL_PRE_MASK_SFT BIT(14) +#define DL_2_SIDE_TONE_ON_CTL_PRE_SFT 13 +#define DL_2_SIDE_TONE_ON_CTL_PRE_MASK_SFT BIT(13) +#define DL_2_MUTE_CH1_OFF_CTL_PRE_SFT 12 +#define DL_2_MUTE_CH1_OFF_CTL_PRE_MASK_SFT BIT(12) +#define DL_2_MUTE_CH2_OFF_CTL_PRE_SFT 11 +#define DL_2_MUTE_CH2_OFF_CTL_PRE_MASK_SFT BIT(11) +#define DL2_ARAMPSP_CTL_PRE_SFT 9 +#define DL2_ARAMPSP_CTL_PRE_MASK_SFT GENMASK(10, 9) +#define DL_2_IIRMODE_CTL_PRE_SFT 6 +#define DL_2_IIRMODE_CTL_PRE_MASK_SFT GENMASK(8, 6) +#define DL_2_VOICE_MODE_CTL_PRE_SFT 5 +#define DL_2_VOICE_MODE_CTL_PRE_MASK_SFT BIT(5) +#define D2_2_MUTE_CH1_ON_CTL_PRE_SFT 4 +#define D2_2_MUTE_CH1_ON_CTL_PRE_MASK_SFT BIT(4) +#define D2_2_MUTE_CH2_ON_CTL_PRE_SFT 3 +#define D2_2_MUTE_CH2_ON_CTL_PRE_MASK_SFT BIT(3) +#define DL_2_IIR_ON_CTL_PRE_SFT 2 +#define DL_2_IIR_ON_CTL_PRE_MASK_SFT BIT(2) +#define DL_2_GAIN_ON_CTL_PRE_SFT 1 +#define DL_2_GAIN_ON_CTL_PRE_MASK_SFT BIT(1) +#define DL_2_SRC_ON_CTL_PRE_SFT 0 +#define DL_2_SRC_ON_CTL_PRE_MASK_SFT BIT(0) + +/* AFE_ADDA_DL_SRC2_CON1 */ +#define DL_2_GAIN_CTL_PRE_SFT 16 +#define DL_2_GAIN_CTL_PRE_MASK 0xffff +#define DL_2_GAIN_CTL_PRE_MASK_SFT GENMASK(31, 16) +#define DL_2_GAIN_MODE_CTL_SFT 0 +#define DL_2_GAIN_MODE_CTL_MASK_SFT BIT(0) + +/* AFE_ADDA_UL_SRC_CON0 */ +#define ULCF_CFG_EN_CTL_SFT 31 +#define ULCF_CFG_EN_CTL_MASK_SFT BIT(31) +#define UL_DMIC_PHASE_SEL_CH1_SFT 27 +#define UL_DMIC_PHASE_SEL_CH1_MASK_SFT GENMASK(29, 27) +#define UL_DMIC_PHASE_SEL_CH2_SFT 24 +#define UL_DMIC_PHASE_SEL_CH2_MASK_SFT GENMASK(26, 24) +#define UL_MODE_3P25M_CH2_CTL_SFT 22 +#define UL_MODE_3P25M_CH2_CTL_MASK_SFT BIT(22) +#define UL_MODE_3P25M_CH1_CTL_SFT 21 +#define UL_MODE_3P25M_CH1_CTL_MASK_SFT BIT(21) +#define UL_VOICE_MODE_CH1_CH2_CTL_SFT 17 +#define UL_VOICE_MODE_CH1_CH2_CTL_MASK_SFT GENMASK(19, 17) +#define UL_AP_DMIC_ON_SFT 16 +#define UL_AP_DMIC_ON_MASK_SFT BIT(16) +#define DMIC_LOW_POWER_CTL_SFT 14 +#define DMIC_LOW_POWER_CTL_MASK_SFT GENMASK(15, 14) +#define UL_DISABLE_HW_CG_CTL_SFT 12 +#define UL_DISABLE_HW_CG_CTL_MASK_SFT BIT(12) +#define UL_IIR_ON_TMP_CTL_SFT 10 +#define UL_IIR_ON_TMP_CTL_MASK_SFT BIT(10) +#define UL_IIRMODE_CTL_SFT 7 +#define UL_IIRMODE_CTL_MASK_SFT GENMASK(9, 7) +#define DIGMIC_4P33M_SEL_SFT 6 +#define DIGMIC_4P33M_SEL_MASK_SFT BIT(6) +#define DIGMIC_3P25M_1P625M_SEL_SFT 5 +#define DIGMIC_3P25M_1P625M_SEL_MASK_SFT BIT(5) +#define UL_LOOP_BACK_MODE_SFT 2 +#define UL_LOOP_BACK_MODE_MASK_SFT BIT(2) +#define UL_SDM_3_LEVEL_SFT 1 +#define UL_SDM_3_LEVEL_MASK_SFT BIT(1) +#define UL_SRC_ON_CTL_SFT 0 +#define UL_SRC_ON_CTL_MASK_SFT BIT(0) + +/* AFE_ADDA_UL_SRC_CON1 */ +#define C_DAC_EN_CTL_SFT 27 +#define C_DAC_EN_CTL_MASK_SFT BIT(27) +#define C_MUTE_SW_CTL_SFT 26 +#define C_MUTE_SW_CTL_MASK_SFT BIT(26) +#define ASDM_SRC_SEL_CTL_SFT 25 +#define ASDM_SRC_SEL_CTL_MASK_SFT BIT(25) +#define C_AMP_DIV_CH2_CTL_SFT 21 +#define C_AMP_DIV_CH2_CTL_MASK_SFT GENMASK(23, 21) +#define C_FREQ_DIV_CH2_CTL_SFT 16 +#define C_FREQ_DIV_CH2_CTL_MASK_SFT GENMASK(20, 16) +#define C_SINE_MODE_CH2_CTL_SFT 12 +#define C_SINE_MODE_CH2_CTL_MASK_SFT GENMASK(15, 12) +#define C_AMP_DIV_CH1_CTL_SFT 9 +#define C_AMP_DIV_CH1_CTL_MASK_SFT GENMASK(11, 9) +#define C_FREQ_DIV_CH1_CTL_SFT 4 +#define C_FREQ_DIV_CH1_CTL_MASK_SFT GENMASK(8, 4) +#define C_SINE_MODE_CH1_CTL_SFT 0 +#define C_SINE_MODE_CH1_CTL_MASK_SFT GENMASK(3, 0) + +/* AFE_ADDA_TOP_CON0 */ +#define C_LOOP_BACK_MODE_CTL_SFT 12 +#define C_LOOP_BACK_MODE_CTL_MASK_SFT GENMASK(15, 12) +#define ADDA_UL_GAIN_MODE_SFT 8 +#define ADDA_UL_GAIN_MODE_MASK_SFT GENMASK(9, 8) +#define C_EXT_ADC_CTL_SFT 0 +#define C_EXT_ADC_CTL_MASK_SFT BIT(0) + +/* AFE_ADDA_UL_DL_CON0 */ +#define AFE_ADDA_UL_LR_SWAP_SFT 31 +#define AFE_ADDA_UL_LR_SWAP_MASK_SFT BIT(31) +#define AFE_ADDA_CKDIV_RST_SFT 30 +#define AFE_ADDA_CKDIV_RST_MASK_SFT BIT(30) +#define AFE_ADDA_FIFO_AUTO_RST_SFT 29 +#define AFE_ADDA_FIFO_AUTO_RST_MASK_SFT BIT(29) +#define AFE_ADDA_UL_FIFO_DIGMIC_TESTIN_SFT 21 +#define AFE_ADDA_UL_FIFO_DIGMIC_TESTIN_MASK_SFT GENMASK(22, 21) +#define AFE_ADDA_UL_FIFO_DIGMIC_WDATA_TESTEN_SFT 20 +#define AFE_ADDA_UL_FIFO_DIGMIC_WDATA_TESTEN_MASK_SFT BIT(20) +#define AFE_ADDA6_UL_LR_SWAP_SFT 15 +#define AFE_ADDA6_UL_LR_SWAP_MASK_SFT BIT(15) +#define AFE_ADDA6_CKDIV_RST_SFT 14 +#define AFE_ADDA6_CKDIV_RST_MASK_SFT BIT(14) +#define AFE_ADDA6_FIFO_AUTO_RST_SFT 13 +#define AFE_ADDA6_FIFO_AUTO_RST_MASK_SFT BIT(13) +#define AFE_ADDA6_UL_FIFO_DIGMIC_TESTIN_SFT 5 +#define AFE_ADDA6_UL_FIFO_DIGMIC_TESTIN_MASK_SFT GENMASK(6, 5) +#define AFE_ADDA6_UL_FIFO_DIGMIC_WDATA_TESTEN_SFT 4 +#define AFE_ADDA6_UL_FIFO_DIGMIC_WDATA_TESTEN_MASK_SFT BIT(4) +#define ADDA_AFE_ON_SFT 0 +#define ADDA_AFE_ON_MASK_SFT BIT(0) + +/* AFE_SIDETONE_CON0 */ +#define R_RDY_SFT 30 +#define R_RDY_MASK_SFT BIT(30) +#define W_RDY_SFT 29 +#define W_RDY_MASK_SFT BIT(29) +#define R_W_EN_SFT 25 +#define R_W_EN_MASK_SFT BIT(25) +#define R_W_SEL_SFT 24 +#define R_W_SEL_MASK_SFT BIT(24) +#define SEL_CH2_SFT 23 +#define SEL_CH2_MASK_SFT BIT(23) +#define SIDE_TONE_COEFFICIENT_ADDR_SFT 16 +#define SIDE_TONE_COEFFICIENT_ADDR_MASK_SFT GENMASK(20, 16) +#define SIDE_TONE_COEFFICIENT_SFT 0 +#define SIDE_TONE_COEFFICIENT_MASK_SFT GENMASK(15, 0) + +/* AFE_SIDETONE_COEFF */ +#define SIDE_TONE_COEFF_SFT 0 +#define SIDE_TONE_COEFF_MASK_SFT GENMASK(15, 0) + +/* AFE_SIDETONE_CON1 */ +#define STF_BYPASS_MODE_SFT 31 +#define STF_BYPASS_MODE_MASK_SFT BIT(31) +#define STF_BYPASS_MODE_O28_O29_SFT 30 +#define STF_BYPASS_MODE_O28_O29_MASK_SFT BIT(30) +#define STF_BYPASS_MODE_I2S4_SFT 29 +#define STF_BYPASS_MODE_I2S4_MASK_SFT BIT(29) +#define STF_BYPASS_MODE_DL3_SFT 27 +#define STF_BYPASS_MODE_DL3_MASK_SFT BIT(27) +#define STF_BYPASS_MODE_I2S7_SFT 26 +#define STF_BYPASS_MODE_I2S7_MASK_SFT BIT(26) +#define STF_BYPASS_MODE_I2S9_SFT 25 +#define STF_BYPASS_MODE_I2S9_MASK_SFT BIT(25) +#define STF_O19O20_OUT_EN_SEL_SFT 13 +#define STF_O19O20_OUT_EN_SEL_MASK_SFT BIT(13) +#define STF_SOURCE_FROM_O19O20_SFT 12 +#define STF_SOURCE_FROM_O19O20_MASK_SFT BIT(12) +#define SIDE_TONE_ON_SFT 8 +#define SIDE_TONE_ON_MASK_SFT BIT(8) +#define SIDE_TONE_HALF_TAP_NUM_SFT 0 +#define SIDE_TONE_HALF_TAP_NUM_MASK_SFT GENMASK(5, 0) + +/* AFE_SIDETONE_GAIN */ +#define POSITIVE_GAIN_SFT 16 +#define POSITIVE_GAIN_MASK_SFT GENMASK(18, 16) +#define SIDE_TONE_GAIN_SFT 0 +#define SIDE_TONE_GAIN_MASK_SFT GENMASK(15, 0) + +/* AFE_ADDA_DL_SDM_DCCOMP_CON */ +#define USE_3RD_SDM_SFT 28 +#define USE_3RD_SDM_MASK_SFT BIT(28) +#define DL_FIFO_START_POINT_SFT 24 +#define DL_FIFO_START_POINT_MASK_SFT GENMASK(26, 24) +#define DL_FIFO_SWAP_SFT 20 +#define DL_FIFO_SWAP_MASK_SFT BIT(20) +#define C_AUDSDM1ORDSELECT_CTL_SFT 19 +#define C_AUDSDM1ORDSELECT_CTL_MASK_SFT BIT(19) +#define C_SDM7BITSEL_CTL_SFT 18 +#define C_SDM7BITSEL_CTL_MASK_SFT BIT(18) +#define GAIN_AT_SDM_RST_PRE_CTL_SFT 15 +#define GAIN_AT_SDM_RST_PRE_CTL_MASK_SFT BIT(15) +#define DL_DCM_AUTO_IDLE_EN_SFT 14 +#define DL_DCM_AUTO_IDLE_EN_MASK_SFT BIT(14) +#define AFE_DL_SRC_DCM_EN_SFT 13 +#define AFE_DL_SRC_DCM_EN_MASK_SFT BIT(13) +#define AFE_DL_POST_SRC_DCM_EN_SFT 12 +#define AFE_DL_POST_SRC_DCM_EN_MASK_SFT BIT(12) +#define AUD_SDM_MONO_SFT 9 +#define AUD_SDM_MONO_MASK_SFT BIT(9) +#define AUD_DC_COMP_EN_SFT 8 +#define AUD_DC_COMP_EN_MASK_SFT BIT(8) +#define ATTGAIN_CTL_SFT 0 +#define ATTGAIN_CTL_MASK_SFT GENMASK(5, 0) + +/* AFE_SINEGEN_CON0 */ +#define DAC_EN_SFT 26 +#define DAC_EN_MASK 0x1 +#define DAC_EN_MASK_SFT BIT(26) +#define MUTE_SW_CH2_SFT 25 +#define MUTE_SW_CH2_MASK 0x1 +#define MUTE_SW_CH2_MASK_SFT BIT(25) +#define MUTE_SW_CH1_SFT 24 +#define MUTE_SW_CH1_MASK 0x1 +#define MUTE_SW_CH1_MASK_SFT BIT(24) +#define SINE_MODE_CH2_SFT 20 +#define SINE_MODE_CH2_MASK 0xf +#define SINE_MODE_CH2_MASK_SFT GENMASK(23, 20) +#define AMP_DIV_CH2_SFT 17 +#define AMP_DIV_CH2_MASK 0x7 +#define AMP_DIV_CH2_MASK_SFT GENMASK(19, 17) +#define FREQ_DIV_CH2_SFT 12 +#define FREQ_DIV_CH2_MASK 0x1f +#define FREQ_DIV_CH2_MASK_SFT GENMASK(16, 12) +#define SINE_MODE_CH1_SFT 8 +#define SINE_MODE_CH1_MASK 0xf +#define SINE_MODE_CH1_MASK_SFT GENMASK(11, 8) +#define AMP_DIV_CH1_SFT 5 +#define AMP_DIV_CH1_MASK 0x7 +#define AMP_DIV_CH1_MASK_SFT GENMASK(7, 5) +#define FREQ_DIV_CH1_SFT 0 +#define FREQ_DIV_CH1_MASK 0x1f +#define FREQ_DIV_CH1_MASK_SFT GENMASK(4, 0) + +/* AFE_SINEGEN_CON2 */ +#define INNER_LOOP_BACK_MODE_SFT 0 +#define INNER_LOOP_BACK_MODE_MASK_SFT GENMASK(7, 0) + +/* AFE_HD_ENGEN_ENABLE */ +#define AFE_24M_ON_SFT 1 +#define AFE_24M_ON_MASK_SFT BIT(1) +#define AFE_22M_ON_SFT 0 +#define AFE_22M_ON_MASK_SFT BIT(0) + +/* AFE_ADDA_DL_NLE_FIFO_MON */ +#define DL_NLE_FIFO_WBIN_SFT 8 +#define DL_NLE_FIFO_WBIN_MASK_SFT GENMASK(11, 8) +#define DL_NLE_FIFO_RBIN_SFT 4 +#define DL_NLE_FIFO_RBIN_MASK_SFT GENMASK(7, 4) +#define DL_NLE_FIFO_RDACTIVE_SFT 3 +#define DL_NLE_FIFO_RDACTIVE_MASK_SFT BIT(3) +#define DL_NLE_FIFO_STARTRD_SFT 2 +#define DL_NLE_FIFO_STARTRD_MASK_SFT BIT(2) +#define DL_NLE_FIFO_RD_EMPTY_SFT 1 +#define DL_NLE_FIFO_RD_EMPTY_MASK_SFT BIT(1) +#define DL_NLE_FIFO_WR_FULL_SFT 0 +#define DL_NLE_FIFO_WR_FULL_MASK_SFT BIT(0) + +/* AFE_DL1_CON0 */ +#define DL1_MODE_SFT 24 +#define DL1_MODE_MASK 0xf +#define DL1_MODE_MASK_SFT GENMASK(27, 24) +#define DL1_MINLEN_SFT 20 +#define DL1_MINLEN_MASK 0xf +#define DL1_MINLEN_MASK_SFT GENMASK(23, 20) +#define DL1_MAXLEN_SFT 16 +#define DL1_MAXLEN_MASK 0xf +#define DL1_MAXLEN_MASK_SFT GENMASK(19, 16) +#define DL1_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL1_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL1_SW_CLEAR_BUF_EMPTY_MASK_SFT BIT(15) +#define DL1_PBUF_SIZE_SFT 12 +#define DL1_PBUF_SIZE_MASK 0x3 +#define DL1_PBUF_SIZE_MASK_SFT GENMASK(13, 12) +#define DL1_MONO_SFT 8 +#define DL1_MONO_MASK 0x1 +#define DL1_MONO_MASK_SFT BIT(8) +#define DL1_NORMAL_MODE_SFT 5 +#define DL1_NORMAL_MODE_MASK 0x1 +#define DL1_NORMAL_MODE_MASK_SFT BIT(5) +#define DL1_HALIGN_SFT 4 +#define DL1_HALIGN_MASK 0x1 +#define DL1_HALIGN_MASK_SFT BIT(4) +#define DL1_HD_MODE_SFT 0 +#define DL1_HD_MODE_MASK 0x3 +#define DL1_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_DL2_CON0 */ +#define DL2_MODE_SFT 24 +#define DL2_MODE_MASK 0xf +#define DL2_MODE_MASK_SFT GENMASK(27, 24) +#define DL2_MINLEN_SFT 20 +#define DL2_MINLEN_MASK 0xf +#define DL2_MINLEN_MASK_SFT GENMASK(23, 20) +#define DL2_MAXLEN_SFT 16 +#define DL2_MAXLEN_MASK 0xf +#define DL2_MAXLEN_MASK_SFT GENMASK(19, 16) +#define DL2_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL2_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL2_SW_CLEAR_BUF_EMPTY_MASK_SFT BIT(15) +#define DL2_PBUF_SIZE_SFT 12 +#define DL2_PBUF_SIZE_MASK 0x3 +#define DL2_PBUF_SIZE_MASK_SFT GENMASK(13, 12) +#define DL2_MONO_SFT 8 +#define DL2_MONO_MASK 0x1 +#define DL2_MONO_MASK_SFT BIT(8) +#define DL2_NORMAL_MODE_SFT 5 +#define DL2_NORMAL_MODE_MASK 0x1 +#define DL2_NORMAL_MODE_MASK_SFT BIT(5) +#define DL2_HALIGN_SFT 4 +#define DL2_HALIGN_MASK 0x1 +#define DL2_HALIGN_MASK_SFT BIT(4) +#define DL2_HD_MODE_SFT 0 +#define DL2_HD_MODE_MASK 0x3 +#define DL2_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_DL3_CON0 */ +#define DL3_MODE_SFT 24 +#define DL3_MODE_MASK 0xf +#define DL3_MODE_MASK_SFT GENMASK(27, 24) +#define DL3_MINLEN_SFT 20 +#define DL3_MINLEN_MASK 0xf +#define DL3_MINLEN_MASK_SFT GENMASK(23, 20) +#define DL3_MAXLEN_SFT 16 +#define DL3_MAXLEN_MASK 0xf +#define DL3_MAXLEN_MASK_SFT GENMASK(19, 16) +#define DL3_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL3_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL3_SW_CLEAR_BUF_EMPTY_MASK_SFT BIT(15) +#define DL3_PBUF_SIZE_SFT 12 +#define DL3_PBUF_SIZE_MASK 0x3 +#define DL3_PBUF_SIZE_MASK_SFT GENMASK(13, 12) +#define DL3_MONO_SFT 8 +#define DL3_MONO_MASK 0x1 +#define DL3_MONO_MASK_SFT BIT(8) +#define DL3_NORMAL_MODE_SFT 5 +#define DL3_NORMAL_MODE_MASK 0x1 +#define DL3_NORMAL_MODE_MASK_SFT BIT(5) +#define DL3_HALIGN_SFT 4 +#define DL3_HALIGN_MASK 0x1 +#define DL3_HALIGN_MASK_SFT BIT(4) +#define DL3_HD_MODE_SFT 0 +#define DL3_HD_MODE_MASK 0x3 +#define DL3_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_DL4_CON0 */ +#define DL4_MODE_SFT 24 +#define DL4_MODE_MASK 0xf +#define DL4_MODE_MASK_SFT GENMASK(27, 24) +#define DL4_MINLEN_SFT 20 +#define DL4_MINLEN_MASK 0xf +#define DL4_MINLEN_MASK_SFT GENMASK(23, 20) +#define DL4_MAXLEN_SFT 16 +#define DL4_MAXLEN_MASK 0xf +#define DL4_MAXLEN_MASK_SFT GENMASK(19, 16) +#define DL4_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL4_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL4_SW_CLEAR_BUF_EMPTY_MASK_SFT BIT(15) +#define DL4_PBUF_SIZE_SFT 12 +#define DL4_PBUF_SIZE_MASK 0x3 +#define DL4_PBUF_SIZE_MASK_SFT GENMASK(13, 12) +#define DL4_MONO_SFT 8 +#define DL4_MONO_MASK 0x1 +#define DL4_MONO_MASK_SFT BIT(8) +#define DL4_NORMAL_MODE_SFT 5 +#define DL4_NORMAL_MODE_MASK 0x1 +#define DL4_NORMAL_MODE_MASK_SFT BIT(5) +#define DL4_HALIGN_SFT 4 +#define DL4_HALIGN_MASK 0x1 +#define DL4_HALIGN_MASK_SFT BIT(4) +#define DL4_HD_MODE_SFT 0 +#define DL4_HD_MODE_MASK 0x3 +#define DL4_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_DL5_CON0 */ +#define DL5_MODE_SFT 24 +#define DL5_MODE_MASK 0xf +#define DL5_MODE_MASK_SFT GENMASK(27, 24) +#define DL5_MINLEN_SFT 20 +#define DL5_MINLEN_MASK 0xf +#define DL5_MINLEN_MASK_SFT GENMASK(23, 20) +#define DL5_MAXLEN_SFT 16 +#define DL5_MAXLEN_MASK 0xf +#define DL5_MAXLEN_MASK_SFT GENMASK(19, 16) +#define DL5_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL5_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL5_SW_CLEAR_BUF_EMPTY_MASK_SFT BIT(15) +#define DL5_PBUF_SIZE_SFT 12 +#define DL5_PBUF_SIZE_MASK 0x3 +#define DL5_PBUF_SIZE_MASK_SFT GENMASK(13, 12) +#define DL5_MONO_SFT 8 +#define DL5_MONO_MASK 0x1 +#define DL5_MONO_MASK_SFT BIT(8) +#define DL5_NORMAL_MODE_SFT 5 +#define DL5_NORMAL_MODE_MASK 0x1 +#define DL5_NORMAL_MODE_MASK_SFT BIT(5) +#define DL5_HALIGN_SFT 4 +#define DL5_HALIGN_MASK 0x1 +#define DL5_HALIGN_MASK_SFT BIT(4) +#define DL5_HD_MODE_SFT 0 +#define DL5_HD_MODE_MASK 0x3 +#define DL5_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_DL6_CON0 */ +#define DL6_MODE_SFT 24 +#define DL6_MODE_MASK 0xf +#define DL6_MODE_MASK_SFT GENMASK(27, 24) +#define DL6_MINLEN_SFT 20 +#define DL6_MINLEN_MASK 0xf +#define DL6_MINLEN_MASK_SFT GENMASK(23, 20) +#define DL6_MAXLEN_SFT 16 +#define DL6_MAXLEN_MASK 0xf +#define DL6_MAXLEN_MASK_SFT GENMASK(19, 16) +#define DL6_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL6_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL6_SW_CLEAR_BUF_EMPTY_MASK_SFT BIT(15) +#define DL6_PBUF_SIZE_SFT 12 +#define DL6_PBUF_SIZE_MASK 0x3 +#define DL6_PBUF_SIZE_MASK_SFT GENMASK(13, 12) +#define DL6_MONO_SFT 8 +#define DL6_MONO_MASK 0x1 +#define DL6_MONO_MASK_SFT BIT(8) +#define DL6_NORMAL_MODE_SFT 5 +#define DL6_NORMAL_MODE_MASK 0x1 +#define DL6_NORMAL_MODE_MASK_SFT BIT(5) +#define DL6_HALIGN_SFT 4 +#define DL6_HALIGN_MASK 0x1 +#define DL6_HALIGN_MASK_SFT BIT(4) +#define DL6_HD_MODE_SFT 0 +#define DL6_HD_MODE_MASK 0x3 +#define DL6_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_DL7_CON0 */ +#define DL7_MODE_SFT 24 +#define DL7_MODE_MASK 0xf +#define DL7_MODE_MASK_SFT GENMASK(27, 24) +#define DL7_MINLEN_SFT 20 +#define DL7_MINLEN_MASK 0xf +#define DL7_MINLEN_MASK_SFT GENMASK(23, 20) +#define DL7_MAXLEN_SFT 16 +#define DL7_MAXLEN_MASK 0xf +#define DL7_MAXLEN_MASK_SFT GENMASK(19, 16) +#define DL7_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL7_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL7_SW_CLEAR_BUF_EMPTY_MASK_SFT BIT(15) +#define DL7_PBUF_SIZE_SFT 12 +#define DL7_PBUF_SIZE_MASK 0x3 +#define DL7_PBUF_SIZE_MASK_SFT GENMASK(13, 12) +#define DL7_MONO_SFT 8 +#define DL7_MONO_MASK 0x1 +#define DL7_MONO_MASK_SFT BIT(8) +#define DL7_NORMAL_MODE_SFT 5 +#define DL7_NORMAL_MODE_MASK 0x1 +#define DL7_NORMAL_MODE_MASK_SFT BIT(5) +#define DL7_HALIGN_SFT 4 +#define DL7_HALIGN_MASK 0x1 +#define DL7_HALIGN_MASK_SFT BIT(4) +#define DL7_HD_MODE_SFT 0 +#define DL7_HD_MODE_MASK 0x3 +#define DL7_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_DL8_CON0 */ +#define DL8_MODE_SFT 24 +#define DL8_MODE_MASK 0xf +#define DL8_MODE_MASK_SFT GENMASK(27, 24) +#define DL8_MINLEN_SFT 20 +#define DL8_MINLEN_MASK 0xf +#define DL8_MINLEN_MASK_SFT GENMASK(23, 20) +#define DL8_MAXLEN_SFT 16 +#define DL8_MAXLEN_MASK 0xf +#define DL8_MAXLEN_MASK_SFT GENMASK(19, 16) +#define DL8_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL8_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL8_SW_CLEAR_BUF_EMPTY_MASK_SFT BIT(15) +#define DL8_PBUF_SIZE_SFT 12 +#define DL8_PBUF_SIZE_MASK 0x3 +#define DL8_PBUF_SIZE_MASK_SFT GENMASK(13, 12) +#define DL8_MONO_SFT 8 +#define DL8_MONO_MASK 0x1 +#define DL8_MONO_MASK_SFT BIT(8) +#define DL8_NORMAL_MODE_SFT 5 +#define DL8_NORMAL_MODE_MASK 0x1 +#define DL8_NORMAL_MODE_MASK_SFT BIT(5) +#define DL8_HALIGN_SFT 4 +#define DL8_HALIGN_MASK 0x1 +#define DL8_HALIGN_MASK_SFT BIT(4) +#define DL8_HD_MODE_SFT 0 +#define DL8_HD_MODE_MASK 0x3 +#define DL8_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_DL12_CON0 */ +#define DL12_MODE_SFT 24 +#define DL12_MODE_MASK 0xf +#define DL12_MODE_MASK_SFT GENMASK(27, 24) +#define DL12_MINLEN_SFT 20 +#define DL12_MINLEN_MASK 0xf +#define DL12_MINLEN_MASK_SFT GENMASK(23, 20) +#define DL12_MAXLEN_SFT 16 +#define DL12_MAXLEN_MASK 0xf +#define DL12_MAXLEN_MASK_SFT GENMASK(19, 16) +#define DL12_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL12_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL12_SW_CLEAR_BUF_EMPTY_MASK_SFT BIT(15) +#define DL12_PBUF_SIZE_SFT 12 +#define DL12_PBUF_SIZE_MASK 0x3 +#define DL12_PBUF_SIZE_MASK_SFT GENMASK(13, 12) +#define DL12_4CH_EN_SFT 11 +#define DL12_4CH_EN_MASK 0x1 +#define DL12_4CH_EN_MASK_SFT BIT(11) +#define DL12_MONO_SFT 8 +#define DL12_MONO_MASK 0x1 +#define DL12_MONO_MASK_SFT BIT(8) +#define DL12_NORMAL_MODE_SFT 5 +#define DL12_NORMAL_MODE_MASK 0x1 +#define DL12_NORMAL_MODE_MASK_SFT BIT(5) +#define DL12_HALIGN_SFT 4 +#define DL12_HALIGN_MASK 0x1 +#define DL12_HALIGN_MASK_SFT BIT(4) +#define DL12_HD_MODE_SFT 0 +#define DL12_HD_MODE_MASK 0x3 +#define DL12_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_AWB_CON0 */ +#define AWB_MODE_SFT 24 +#define AWB_MODE_MASK 0xf +#define AWB_MODE_MASK_SFT GENMASK(27, 24) +#define AWB_SW_CLEAR_BUF_FULL_SFT 15 +#define AWB_SW_CLEAR_BUF_FULL_MASK 0x1 +#define AWB_SW_CLEAR_BUF_FULL_MASK_SFT BIT(15) +#define AWB_R_MONO_SFT 9 +#define AWB_R_MONO_MASK 0x1 +#define AWB_R_MONO_MASK_SFT BIT(9) +#define AWB_MONO_SFT 8 +#define AWB_MONO_MASK 0x1 +#define AWB_MONO_MASK_SFT BIT(8) +#define AWB_WR_SIGN_SFT 6 +#define AWB_WR_SIGN_MASK 0x1 +#define AWB_WR_SIGN_MASK_SFT BIT(6) +#define AWB_NORMAL_MODE_SFT 5 +#define AWB_NORMAL_MODE_MASK 0x1 +#define AWB_NORMAL_MODE_MASK_SFT BIT(5) +#define AWB_HALIGN_SFT 4 +#define AWB_HALIGN_MASK 0x1 +#define AWB_HALIGN_MASK_SFT BIT(4) +#define AWB_HD_MODE_SFT 0 +#define AWB_HD_MODE_MASK 0x3 +#define AWB_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_AWB2_CON0 */ +#define AWB2_MODE_SFT 24 +#define AWB2_MODE_MASK 0xf +#define AWB2_MODE_MASK_SFT GENMASK(27, 24) +#define AWB2_SW_CLEAR_BUF_FULL_SFT 15 +#define AWB2_SW_CLEAR_BUF_FULL_MASK 0x1 +#define AWB2_SW_CLEAR_BUF_FULL_MASK_SFT BIT(15) +#define AWB2_R_MONO_SFT 9 +#define AWB2_R_MONO_MASK 0x1 +#define AWB2_R_MONO_MASK_SFT BIT(9) +#define AWB2_MONO_SFT 8 +#define AWB2_MONO_MASK 0x1 +#define AWB2_MONO_MASK_SFT BIT(8) +#define AWB2_WR_SIGN_SFT 6 +#define AWB2_WR_SIGN_MASK 0x1 +#define AWB2_WR_SIGN_MASK_SFT BIT(6) +#define AWB2_NORMAL_MODE_SFT 5 +#define AWB2_NORMAL_MODE_MASK 0x1 +#define AWB2_NORMAL_MODE_MASK_SFT BIT(5) +#define AWB2_HALIGN_SFT 4 +#define AWB2_HALIGN_MASK 0x1 +#define AWB2_HALIGN_MASK_SFT BIT(4) +#define AWB2_HD_MODE_SFT 0 +#define AWB2_HD_MODE_MASK 0x3 +#define AWB2_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_VUL_CON0 */ +#define VUL_MODE_SFT 24 +#define VUL_MODE_MASK 0xf +#define VUL_MODE_MASK_SFT GENMASK(27, 24) +#define VUL_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL_SW_CLEAR_BUF_FULL_MASK_SFT BIT(15) +#define VUL_R_MONO_SFT 9 +#define VUL_R_MONO_MASK 0x1 +#define VUL_R_MONO_MASK_SFT BIT(9) +#define VUL_MONO_SFT 8 +#define VUL_MONO_MASK 0x1 +#define VUL_MONO_MASK_SFT BIT(8) +#define VUL_WR_SIGN_SFT 6 +#define VUL_WR_SIGN_MASK 0x1 +#define VUL_WR_SIGN_MASK_SFT BIT(6) +#define VUL_NORMAL_MODE_SFT 5 +#define VUL_NORMAL_MODE_MASK 0x1 +#define VUL_NORMAL_MODE_MASK_SFT BIT(5) +#define VUL_HALIGN_SFT 4 +#define VUL_HALIGN_MASK 0x1 +#define VUL_HALIGN_MASK_SFT BIT(4) +#define VUL_HD_MODE_SFT 0 +#define VUL_HD_MODE_MASK 0x3 +#define VUL_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_VUL12_CON0 */ +#define VUL12_MODE_SFT 24 +#define VUL12_MODE_MASK 0xf +#define VUL12_MODE_MASK_SFT GENMASK(27, 24) +#define VUL12_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL12_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL12_SW_CLEAR_BUF_FULL_MASK_SFT BIT(15) +#define VUL12_4CH_EN_SFT 11 +#define VUL12_4CH_EN_MASK 0x1 +#define VUL12_4CH_EN_MASK_SFT BIT(11) +#define VUL12_R_MONO_SFT 9 +#define VUL12_R_MONO_MASK 0x1 +#define VUL12_R_MONO_MASK_SFT BIT(9) +#define VUL12_MONO_SFT 8 +#define VUL12_MONO_MASK 0x1 +#define VUL12_MONO_MASK_SFT BIT(8) +#define VUL12_WR_SIGN_SFT 6 +#define VUL12_WR_SIGN_MASK 0x1 +#define VUL12_WR_SIGN_MASK_SFT BIT(6) +#define VUL12_NORMAL_MODE_SFT 5 +#define VUL12_NORMAL_MODE_MASK 0x1 +#define VUL12_NORMAL_MODE_MASK_SFT BIT(5) +#define VUL12_HALIGN_SFT 4 +#define VUL12_HALIGN_MASK 0x1 +#define VUL12_HALIGN_MASK_SFT BIT(4) +#define VUL12_HD_MODE_SFT 0 +#define VUL12_HD_MODE_MASK 0x3 +#define VUL12_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_VUL2_CON0 */ +#define VUL2_MODE_SFT 24 +#define VUL2_MODE_MASK 0xf +#define VUL2_MODE_MASK_SFT GENMASK(27, 24) +#define VUL2_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL2_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL2_SW_CLEAR_BUF_FULL_MASK_SFT BIT(15) +#define VUL2_R_MONO_SFT 9 +#define VUL2_R_MONO_MASK 0x1 +#define VUL2_R_MONO_MASK_SFT BIT(9) +#define VUL2_MONO_SFT 8 +#define VUL2_MONO_MASK 0x1 +#define VUL2_MONO_MASK_SFT BIT(8) +#define VUL2_WR_SIGN_SFT 6 +#define VUL2_WR_SIGN_MASK 0x1 +#define VUL2_WR_SIGN_MASK_SFT BIT(6) +#define VUL2_NORMAL_MODE_SFT 5 +#define VUL2_NORMAL_MODE_MASK 0x1 +#define VUL2_NORMAL_MODE_MASK_SFT BIT(5) +#define VUL2_HALIGN_SFT 4 +#define VUL2_HALIGN_MASK 0x1 +#define VUL2_HALIGN_MASK_SFT BIT(4) +#define VUL2_HD_MODE_SFT 0 +#define VUL2_HD_MODE_MASK 0x3 +#define VUL2_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_VUL3_CON0 */ +#define VUL3_MODE_SFT 24 +#define VUL3_MODE_MASK 0xf +#define VUL3_MODE_MASK_SFT GENMASK(27, 24) +#define VUL3_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL3_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL3_SW_CLEAR_BUF_FULL_MASK_SFT BIT(15) +#define VUL3_R_MONO_SFT 9 +#define VUL3_R_MONO_MASK 0x1 +#define VUL3_R_MONO_MASK_SFT BIT(9) +#define VUL3_MONO_SFT 8 +#define VUL3_MONO_MASK 0x1 +#define VUL3_MONO_MASK_SFT BIT(8) +#define VUL3_WR_SIGN_SFT 6 +#define VUL3_WR_SIGN_MASK 0x1 +#define VUL3_WR_SIGN_MASK_SFT BIT(6) +#define VUL3_NORMAL_MODE_SFT 5 +#define VUL3_NORMAL_MODE_MASK 0x1 +#define VUL3_NORMAL_MODE_MASK_SFT BIT(5) +#define VUL3_HALIGN_SFT 4 +#define VUL3_HALIGN_MASK 0x1 +#define VUL3_HALIGN_MASK_SFT BIT(4) +#define VUL3_HD_MODE_SFT 0 +#define VUL3_HD_MODE_MASK 0x3 +#define VUL3_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_VUL4_CON0 */ +#define VUL4_MODE_SFT 24 +#define VUL4_MODE_MASK 0xf +#define VUL4_MODE_MASK_SFT GENMASK(27, 24) +#define VUL4_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL4_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL4_SW_CLEAR_BUF_FULL_MASK_SFT BIT(15) +#define VUL4_R_MONO_SFT 9 +#define VUL4_R_MONO_MASK 0x1 +#define VUL4_R_MONO_MASK_SFT BIT(9) +#define VUL4_MONO_SFT 8 +#define VUL4_MONO_MASK 0x1 +#define VUL4_MONO_MASK_SFT BIT(8) +#define VUL4_WR_SIGN_SFT 6 +#define VUL4_WR_SIGN_MASK 0x1 +#define VUL4_WR_SIGN_MASK_SFT BIT(6) +#define VUL4_NORMAL_MODE_SFT 5 +#define VUL4_NORMAL_MODE_MASK 0x1 +#define VUL4_NORMAL_MODE_MASK_SFT BIT(5) +#define VUL4_HALIGN_SFT 4 +#define VUL4_HALIGN_MASK 0x1 +#define VUL4_HALIGN_MASK_SFT BIT(4) +#define VUL4_HD_MODE_SFT 0 +#define VUL4_HD_MODE_MASK 0x3 +#define VUL4_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_VUL5_CON0 */ +#define VUL5_MODE_SFT 24 +#define VUL5_MODE_MASK 0xf +#define VUL5_MODE_MASK_SFT GENMASK(27, 24) +#define VUL5_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL5_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL5_SW_CLEAR_BUF_FULL_MASK_SFT BIT(15) +#define VUL5_R_MONO_SFT 9 +#define VUL5_R_MONO_MASK 0x1 +#define VUL5_R_MONO_MASK_SFT BIT(9) +#define VUL5_MONO_SFT 8 +#define VUL5_MONO_MASK 0x1 +#define VUL5_MONO_MASK_SFT BIT(8) +#define VUL5_WR_SIGN_SFT 6 +#define VUL5_WR_SIGN_MASK 0x1 +#define VUL5_WR_SIGN_MASK_SFT BIT(6) +#define VUL5_NORMAL_MODE_SFT 5 +#define VUL5_NORMAL_MODE_MASK 0x1 +#define VUL5_NORMAL_MODE_MASK_SFT BIT(5) +#define VUL5_HALIGN_SFT 4 +#define VUL5_HALIGN_MASK 0x1 +#define VUL5_HALIGN_MASK_SFT BIT(4) +#define VUL5_HD_MODE_SFT 0 +#define VUL5_HD_MODE_MASK 0x3 +#define VUL5_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_VUL6_CON0 */ +#define VUL6_MODE_SFT 24 +#define VUL6_MODE_MASK 0xf +#define VUL6_MODE_MASK_SFT GENMASK(27, 24) +#define VUL6_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL6_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL6_SW_CLEAR_BUF_FULL_MASK_SFT BIT(15) +#define VUL6_R_MONO_SFT 9 +#define VUL6_R_MONO_MASK 0x1 +#define VUL6_R_MONO_MASK_SFT BIT(9) +#define VUL6_MONO_SFT 8 +#define VUL6_MONO_MASK 0x1 +#define VUL6_MONO_MASK_SFT BIT(8) +#define VUL6_WR_SIGN_SFT 6 +#define VUL6_WR_SIGN_MASK 0x1 +#define VUL6_WR_SIGN_MASK_SFT BIT(6) +#define VUL6_NORMAL_MODE_SFT 5 +#define VUL6_NORMAL_MODE_MASK 0x1 +#define VUL6_NORMAL_MODE_MASK_SFT BIT(5) +#define VUL6_HALIGN_SFT 4 +#define VUL6_HALIGN_MASK 0x1 +#define VUL6_HALIGN_MASK_SFT BIT(4) +#define VUL6_HD_MODE_SFT 0 +#define VUL6_HD_MODE_MASK 0x3 +#define VUL6_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_DAI_CON0 */ +#define DAI_MODE_SFT 24 +#define DAI_MODE_MASK 0x3 +#define DAI_MODE_MASK_SFT GENMASK(25, 24) +#define DAI_SW_CLEAR_BUF_FULL_SFT 15 +#define DAI_SW_CLEAR_BUF_FULL_MASK 0x1 +#define DAI_SW_CLEAR_BUF_FULL_MASK_SFT BIT(15) +#define DAI_DUPLICATE_WR_SFT 10 +#define DAI_DUPLICATE_WR_MASK 0x1 +#define DAI_DUPLICATE_WR_MASK_SFT BIT(10) +#define DAI_MONO_SFT 8 +#define DAI_MONO_MASK 0x1 +#define DAI_MONO_MASK_SFT BIT(8) +#define DAI_WR_SIGN_SFT 6 +#define DAI_WR_SIGN_MASK 0x1 +#define DAI_WR_SIGN_MASK_SFT BIT(6) +#define DAI_NORMAL_MODE_SFT 5 +#define DAI_NORMAL_MODE_MASK 0x1 +#define DAI_NORMAL_MODE_MASK_SFT BIT(5) +#define DAI_HALIGN_SFT 4 +#define DAI_HALIGN_MASK 0x1 +#define DAI_HALIGN_MASK_SFT BIT(4) +#define DAI_HD_MODE_SFT 0 +#define DAI_HD_MODE_MASK 0x3 +#define DAI_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_MOD_DAI_CON0 */ +#define MOD_DAI_MODE_SFT 24 +#define MOD_DAI_MODE_MASK 0x3 +#define MOD_DAI_MODE_MASK_SFT GENMASK(25, 24) +#define MOD_DAI_SW_CLEAR_BUF_FULL_SFT 15 +#define MOD_DAI_SW_CLEAR_BUF_FULL_MASK 0x1 +#define MOD_DAI_SW_CLEAR_BUF_FULL_MASK_SFT BIT(15) +#define MOD_DAI_DUPLICATE_WR_SFT 10 +#define MOD_DAI_DUPLICATE_WR_MASK 0x1 +#define MOD_DAI_DUPLICATE_WR_MASK_SFT BIT(10) +#define MOD_DAI_MONO_SFT 8 +#define MOD_DAI_MONO_MASK 0x1 +#define MOD_DAI_MONO_MASK_SFT BIT(8) +#define MOD_DAI_WR_SIGN_SFT 6 +#define MOD_DAI_WR_SIGN_MASK 0x1 +#define MOD_DAI_WR_SIGN_MASK_SFT BIT(6) +#define MOD_DAI_NORMAL_MODE_SFT 5 +#define MOD_DAI_NORMAL_MODE_MASK 0x1 +#define MOD_DAI_NORMAL_MODE_MASK_SFT BIT(5) +#define MOD_DAI_HALIGN_SFT 4 +#define MOD_DAI_HALIGN_MASK 0x1 +#define MOD_DAI_HALIGN_MASK_SFT BIT(4) +#define MOD_DAI_HD_MODE_SFT 0 +#define MOD_DAI_HD_MODE_MASK 0x3 +#define MOD_DAI_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_DAI2_CON0 */ +#define DAI2_MODE_SFT 24 +#define DAI2_MODE_MASK 0xf +#define DAI2_MODE_MASK_SFT GENMASK(27, 24) +#define DAI2_SW_CLEAR_BUF_FULL_SFT 15 +#define DAI2_SW_CLEAR_BUF_FULL_MASK 0x1 +#define DAI2_SW_CLEAR_BUF_FULL_MASK_SFT BIT(15) +#define DAI2_DUPLICATE_WR_SFT 10 +#define DAI2_DUPLICATE_WR_MASK 0x1 +#define DAI2_DUPLICATE_WR_MASK_SFT BIT(10) +#define DAI2_MONO_SFT 8 +#define DAI2_MONO_MASK 0x1 +#define DAI2_MONO_MASK_SFT BIT(8) +#define DAI2_WR_SIGN_SFT 6 +#define DAI2_WR_SIGN_MASK 0x1 +#define DAI2_WR_SIGN_MASK_SFT BIT(6) +#define DAI2_NORMAL_MODE_SFT 5 +#define DAI2_NORMAL_MODE_MASK 0x1 +#define DAI2_NORMAL_MODE_MASK_SFT BIT(5) +#define DAI2_HALIGN_SFT 4 +#define DAI2_HALIGN_MASK 0x1 +#define DAI2_HALIGN_MASK_SFT BIT(4) +#define DAI2_HD_MODE_SFT 0 +#define DAI2_HD_MODE_MASK 0x3 +#define DAI2_HD_MODE_MASK_SFT GENMASK(1, 0) + +/* AFE_MEMIF_CON0 */ +#define CPU_COMPACT_MODE_SFT 2 +#define CPU_COMPACT_MODE_MASK_SFT BIT(2) +#define CPU_HD_ALIGN_SFT 1 +#define CPU_HD_ALIGN_MASK_SFT BIT(1) +#define SYSRAM_SIGN_SFT 0 +#define SYSRAM_SIGN_MASK_SFT BIT(0) + +/* AFE_IRQ_MCU_CON0 */ +#define IRQ31_MCU_ON_SFT 31 +#define IRQ31_MCU_ON_MASK 0x1 +#define IRQ31_MCU_ON_MASK_SFT BIT(31) +#define IRQ26_MCU_ON_SFT 26 +#define IRQ26_MCU_ON_MASK 0x1 +#define IRQ26_MCU_ON_MASK_SFT BIT(26) +#define IRQ25_MCU_ON_SFT 25 +#define IRQ25_MCU_ON_MASK 0x1 +#define IRQ25_MCU_ON_MASK_SFT BIT(25) +#define IRQ24_MCU_ON_SFT 24 +#define IRQ24_MCU_ON_MASK 0x1 +#define IRQ24_MCU_ON_MASK_SFT BIT(24) +#define IRQ23_MCU_ON_SFT 23 +#define IRQ23_MCU_ON_MASK 0x1 +#define IRQ23_MCU_ON_MASK_SFT BIT(23) +#define IRQ22_MCU_ON_SFT 22 +#define IRQ22_MCU_ON_MASK 0x1 +#define IRQ22_MCU_ON_MASK_SFT BIT(22) +#define IRQ21_MCU_ON_SFT 21 +#define IRQ21_MCU_ON_MASK 0x1 +#define IRQ21_MCU_ON_MASK_SFT BIT(21) +#define IRQ20_MCU_ON_SFT 20 +#define IRQ20_MCU_ON_MASK 0x1 +#define IRQ20_MCU_ON_MASK_SFT BIT(20) +#define IRQ19_MCU_ON_SFT 19 +#define IRQ19_MCU_ON_MASK 0x1 +#define IRQ19_MCU_ON_MASK_SFT BIT(19) +#define IRQ18_MCU_ON_SFT 18 +#define IRQ18_MCU_ON_MASK 0x1 +#define IRQ18_MCU_ON_MASK_SFT BIT(18) +#define IRQ17_MCU_ON_SFT 17 +#define IRQ17_MCU_ON_MASK 0x1 +#define IRQ17_MCU_ON_MASK_SFT BIT(17) +#define IRQ16_MCU_ON_SFT 16 +#define IRQ16_MCU_ON_MASK 0x1 +#define IRQ16_MCU_ON_MASK_SFT BIT(16) +#define IRQ15_MCU_ON_SFT 15 +#define IRQ15_MCU_ON_MASK 0x1 +#define IRQ15_MCU_ON_MASK_SFT BIT(15) +#define IRQ14_MCU_ON_SFT 14 +#define IRQ14_MCU_ON_MASK 0x1 +#define IRQ14_MCU_ON_MASK_SFT BIT(14) +#define IRQ13_MCU_ON_SFT 13 +#define IRQ13_MCU_ON_MASK 0x1 +#define IRQ13_MCU_ON_MASK_SFT BIT(13) +#define IRQ12_MCU_ON_SFT 12 +#define IRQ12_MCU_ON_MASK 0x1 +#define IRQ12_MCU_ON_MASK_SFT BIT(12) +#define IRQ11_MCU_ON_SFT 11 +#define IRQ11_MCU_ON_MASK 0x1 +#define IRQ11_MCU_ON_MASK_SFT BIT(11) +#define IRQ10_MCU_ON_SFT 10 +#define IRQ10_MCU_ON_MASK 0x1 +#define IRQ10_MCU_ON_MASK_SFT BIT(10) +#define IRQ9_MCU_ON_SFT 9 +#define IRQ9_MCU_ON_MASK 0x1 +#define IRQ9_MCU_ON_MASK_SFT BIT(9) +#define IRQ8_MCU_ON_SFT 8 +#define IRQ8_MCU_ON_MASK 0x1 +#define IRQ8_MCU_ON_MASK_SFT BIT(8) +#define IRQ7_MCU_ON_SFT 7 +#define IRQ7_MCU_ON_MASK 0x1 +#define IRQ7_MCU_ON_MASK_SFT BIT(7) +#define IRQ6_MCU_ON_SFT 6 +#define IRQ6_MCU_ON_MASK 0x1 +#define IRQ6_MCU_ON_MASK_SFT BIT(6) +#define IRQ5_MCU_ON_SFT 5 +#define IRQ5_MCU_ON_MASK 0x1 +#define IRQ5_MCU_ON_MASK_SFT BIT(5) +#define IRQ4_MCU_ON_SFT 4 +#define IRQ4_MCU_ON_MASK 0x1 +#define IRQ4_MCU_ON_MASK_SFT BIT(4) +#define IRQ3_MCU_ON_SFT 3 +#define IRQ3_MCU_ON_MASK 0x1 +#define IRQ3_MCU_ON_MASK_SFT BIT(3) +#define IRQ2_MCU_ON_SFT 2 +#define IRQ2_MCU_ON_MASK 0x1 +#define IRQ2_MCU_ON_MASK_SFT BIT(2) +#define IRQ1_MCU_ON_SFT 1 +#define IRQ1_MCU_ON_MASK 0x1 +#define IRQ1_MCU_ON_MASK_SFT BIT(1) +#define IRQ0_MCU_ON_SFT 0 +#define IRQ0_MCU_ON_MASK 0x1 +#define IRQ0_MCU_ON_MASK_SFT BIT(0) + +/* AFE_IRQ_MCU_CON1 */ +#define IRQ7_MCU_MODE_SFT 28 +#define IRQ7_MCU_MODE_MASK 0xf +#define IRQ7_MCU_MODE_MASK_SFT GENMASK(31, 28) +#define IRQ6_MCU_MODE_SFT 24 +#define IRQ6_MCU_MODE_MASK 0xf +#define IRQ6_MCU_MODE_MASK_SFT GENMASK(27, 24) +#define IRQ5_MCU_MODE_SFT 20 +#define IRQ5_MCU_MODE_MASK 0xf +#define IRQ5_MCU_MODE_MASK_SFT GENMASK(23, 20) +#define IRQ4_MCU_MODE_SFT 16 +#define IRQ4_MCU_MODE_MASK 0xf +#define IRQ4_MCU_MODE_MASK_SFT GENMASK(19, 16) +#define IRQ3_MCU_MODE_SFT 12 +#define IRQ3_MCU_MODE_MASK 0xf +#define IRQ3_MCU_MODE_MASK_SFT GENMASK(15, 12) +#define IRQ2_MCU_MODE_SFT 8 +#define IRQ2_MCU_MODE_MASK 0xf +#define IRQ2_MCU_MODE_MASK_SFT GENMASK(11, 8) +#define IRQ1_MCU_MODE_SFT 4 +#define IRQ1_MCU_MODE_MASK 0xf +#define IRQ1_MCU_MODE_MASK_SFT GENMASK(7, 4) +#define IRQ0_MCU_MODE_SFT 0 +#define IRQ0_MCU_MODE_MASK 0xf +#define IRQ0_MCU_MODE_MASK_SFT GENMASK(3, 0) + +/* AFE_IRQ_MCU_CON2 */ +#define IRQ15_MCU_MODE_SFT 28 +#define IRQ15_MCU_MODE_MASK 0xf +#define IRQ15_MCU_MODE_MASK_SFT GENMASK(31, 28) +#define IRQ14_MCU_MODE_SFT 24 +#define IRQ14_MCU_MODE_MASK 0xf +#define IRQ14_MCU_MODE_MASK_SFT GENMASK(27, 24) +#define IRQ13_MCU_MODE_SFT 20 +#define IRQ13_MCU_MODE_MASK 0xf +#define IRQ13_MCU_MODE_MASK_SFT GENMASK(23, 20) +#define IRQ12_MCU_MODE_SFT 16 +#define IRQ12_MCU_MODE_MASK 0xf +#define IRQ12_MCU_MODE_MASK_SFT GENMASK(19, 16) +#define IRQ11_MCU_MODE_SFT 12 +#define IRQ11_MCU_MODE_MASK 0xf +#define IRQ11_MCU_MODE_MASK_SFT GENMASK(15, 12) +#define IRQ10_MCU_MODE_SFT 8 +#define IRQ10_MCU_MODE_MASK 0xf +#define IRQ10_MCU_MODE_MASK_SFT GENMASK(11, 8) +#define IRQ9_MCU_MODE_SFT 4 +#define IRQ9_MCU_MODE_MASK 0xf +#define IRQ9_MCU_MODE_MASK_SFT GENMASK(7, 4) +#define IRQ8_MCU_MODE_SFT 0 +#define IRQ8_MCU_MODE_MASK 0xf +#define IRQ8_MCU_MODE_MASK_SFT GENMASK(3, 0) + +/* AFE_IRQ_MCU_CON3 */ +#define IRQ23_MCU_MODE_SFT 28 +#define IRQ23_MCU_MODE_MASK 0xf +#define IRQ23_MCU_MODE_MASK_SFT GENMASK(31, 28) +#define IRQ22_MCU_MODE_SFT 24 +#define IRQ22_MCU_MODE_MASK 0xf +#define IRQ22_MCU_MODE_MASK_SFT GENMASK(27, 24) +#define IRQ21_MCU_MODE_SFT 20 +#define IRQ21_MCU_MODE_MASK 0xf +#define IRQ21_MCU_MODE_MASK_SFT GENMASK(23, 20) +#define IRQ20_MCU_MODE_SFT 16 +#define IRQ20_MCU_MODE_MASK 0xf +#define IRQ20_MCU_MODE_MASK_SFT GENMASK(19, 16) +#define IRQ19_MCU_MODE_SFT 12 +#define IRQ19_MCU_MODE_MASK 0xf +#define IRQ19_MCU_MODE_MASK_SFT GENMASK(15, 12) +#define IRQ18_MCU_MODE_SFT 8 +#define IRQ18_MCU_MODE_MASK 0xf +#define IRQ18_MCU_MODE_MASK_SFT GENMASK(11, 8) +#define IRQ17_MCU_MODE_SFT 4 +#define IRQ17_MCU_MODE_MASK 0xf +#define IRQ17_MCU_MODE_MASK_SFT GENMASK(7, 4) +#define IRQ16_MCU_MODE_SFT 0 +#define IRQ16_MCU_MODE_MASK 0xf +#define IRQ16_MCU_MODE_MASK_SFT GENMASK(3, 0) + +/* AFE_IRQ_MCU_CON4 */ +#define IRQ26_MCU_MODE_SFT 8 +#define IRQ26_MCU_MODE_MASK 0xf +#define IRQ26_MCU_MODE_MASK_SFT GENMASK(11, 8) +#define IRQ25_MCU_MODE_SFT 4 +#define IRQ25_MCU_MODE_MASK 0xf +#define IRQ25_MCU_MODE_MASK_SFT GENMASK(7, 4) +#define IRQ24_MCU_MODE_SFT 0 +#define IRQ24_MCU_MODE_MASK 0xf +#define IRQ24_MCU_MODE_MASK_SFT GENMASK(3, 0) + +/* AFE_IRQ_MCU_CLR */ +#define IRQ31_MCU_CLR_SFT 31 +#define IRQ31_MCU_CLR_MASK_SFT BIT(31) +#define IRQ26_MCU_CLR_SFT 26 +#define IRQ26_MCU_CLR_MASK_SFT BIT(26) +#define IRQ25_MCU_CLR_SFT 25 +#define IRQ25_MCU_CLR_MASK_SFT BIT(25) +#define IRQ24_MCU_CLR_SFT 24 +#define IRQ24_MCU_CLR_MASK_SFT BIT(24) +#define IRQ23_MCU_CLR_SFT 23 +#define IRQ23_MCU_CLR_MASK_SFT BIT(23) +#define IRQ22_MCU_CLR_SFT 22 +#define IRQ22_MCU_CLR_MASK_SFT BIT(22) +#define IRQ21_MCU_CLR_SFT 21 +#define IRQ21_MCU_CLR_MASK_SFT BIT(21) +#define IRQ20_MCU_CLR_SFT 20 +#define IRQ20_MCU_CLR_MASK_SFT BIT(20) +#define IRQ19_MCU_CLR_SFT 19 +#define IRQ19_MCU_CLR_MASK_SFT BIT(19) +#define IRQ18_MCU_CLR_SFT 18 +#define IRQ18_MCU_CLR_MASK_SFT BIT(18) +#define IRQ17_MCU_CLR_SFT 17 +#define IRQ17_MCU_CLR_MASK_SFT BIT(17) +#define IRQ16_MCU_CLR_SFT 16 +#define IRQ16_MCU_CLR_MASK_SFT BIT(16) +#define IRQ15_MCU_CLR_SFT 15 +#define IRQ15_MCU_CLR_MASK_SFT BIT(15) +#define IRQ14_MCU_CLR_SFT 14 +#define IRQ14_MCU_CLR_MASK_SFT BIT(14) +#define IRQ13_MCU_CLR_SFT 13 +#define IRQ13_MCU_CLR_MASK_SFT BIT(13) +#define IRQ12_MCU_CLR_SFT 12 +#define IRQ12_MCU_CLR_MASK_SFT BIT(12) +#define IRQ11_MCU_CLR_SFT 11 +#define IRQ11_MCU_CLR_MASK_SFT BIT(11) +#define IRQ10_MCU_CLR_SFT 10 +#define IRQ10_MCU_CLR_MASK_SFT BIT(10) +#define IRQ9_MCU_CLR_SFT 9 +#define IRQ9_MCU_CLR_MASK_SFT BIT(9) +#define IRQ8_MCU_CLR_SFT 8 +#define IRQ8_MCU_CLR_MASK_SFT BIT(8) +#define IRQ7_MCU_CLR_SFT 7 +#define IRQ7_MCU_CLR_MASK_SFT BIT(7) +#define IRQ6_MCU_CLR_SFT 6 +#define IRQ6_MCU_CLR_MASK_SFT BIT(6) +#define IRQ5_MCU_CLR_SFT 5 +#define IRQ5_MCU_CLR_MASK_SFT BIT(5) +#define IRQ4_MCU_CLR_SFT 4 +#define IRQ4_MCU_CLR_MASK_SFT BIT(4) +#define IRQ3_MCU_CLR_SFT 3 +#define IRQ3_MCU_CLR_MASK_SFT BIT(3) +#define IRQ2_MCU_CLR_SFT 2 +#define IRQ2_MCU_CLR_MASK_SFT BIT(2) +#define IRQ1_MCU_CLR_SFT 1 +#define IRQ1_MCU_CLR_MASK_SFT BIT(1) +#define IRQ0_MCU_CLR_SFT 0 +#define IRQ0_MCU_CLR_MASK_SFT BIT(0) + +/* AFE_IRQ_MCU_EN */ +#define IRQ31_MCU_EN_SFT 31 +#define IRQ30_MCU_EN_SFT 30 +#define IRQ29_MCU_EN_SFT 29 +#define IRQ28_MCU_EN_SFT 28 +#define IRQ27_MCU_EN_SFT 27 +#define IRQ26_MCU_EN_SFT 26 +#define IRQ25_MCU_EN_SFT 25 +#define IRQ24_MCU_EN_SFT 24 +#define IRQ23_MCU_EN_SFT 23 +#define IRQ22_MCU_EN_SFT 22 +#define IRQ21_MCU_EN_SFT 21 +#define IRQ20_MCU_EN_SFT 20 +#define IRQ19_MCU_EN_SFT 19 +#define IRQ18_MCU_EN_SFT 18 +#define IRQ17_MCU_EN_SFT 17 +#define IRQ16_MCU_EN_SFT 16 +#define IRQ15_MCU_EN_SFT 15 +#define IRQ14_MCU_EN_SFT 14 +#define IRQ13_MCU_EN_SFT 13 +#define IRQ12_MCU_EN_SFT 12 +#define IRQ11_MCU_EN_SFT 11 +#define IRQ10_MCU_EN_SFT 10 +#define IRQ9_MCU_EN_SFT 9 +#define IRQ8_MCU_EN_SFT 8 +#define IRQ7_MCU_EN_SFT 7 +#define IRQ6_MCU_EN_SFT 6 +#define IRQ5_MCU_EN_SFT 5 +#define IRQ4_MCU_EN_SFT 4 +#define IRQ3_MCU_EN_SFT 3 +#define IRQ2_MCU_EN_SFT 2 +#define IRQ1_MCU_EN_SFT 1 +#define IRQ0_MCU_EN_SFT 0 + +/* AFE_IRQ_MCU_SCP_EN */ +#define IRQ31_MCU_SCP_EN_SFT 31 +#define IRQ30_MCU_SCP_EN_SFT 30 +#define IRQ29_MCU_SCP_EN_SFT 29 +#define IRQ28_MCU_SCP_EN_SFT 28 +#define IRQ27_MCU_SCP_EN_SFT 27 +#define IRQ26_MCU_SCP_EN_SFT 26 +#define IRQ25_MCU_SCP_EN_SFT 25 +#define IRQ24_MCU_SCP_EN_SFT 24 +#define IRQ23_MCU_SCP_EN_SFT 23 +#define IRQ22_MCU_SCP_EN_SFT 22 +#define IRQ21_MCU_SCP_EN_SFT 21 +#define IRQ20_MCU_SCP_EN_SFT 20 +#define IRQ19_MCU_SCP_EN_SFT 19 +#define IRQ18_MCU_SCP_EN_SFT 18 +#define IRQ17_MCU_SCP_EN_SFT 17 +#define IRQ16_MCU_SCP_EN_SFT 16 +#define IRQ15_MCU_SCP_EN_SFT 15 +#define IRQ14_MCU_SCP_EN_SFT 14 +#define IRQ13_MCU_SCP_EN_SFT 13 +#define IRQ12_MCU_SCP_EN_SFT 12 +#define IRQ11_MCU_SCP_EN_SFT 11 +#define IRQ10_MCU_SCP_EN_SFT 10 +#define IRQ9_MCU_SCP_EN_SFT 9 +#define IRQ8_MCU_SCP_EN_SFT 8 +#define IRQ7_MCU_SCP_EN_SFT 7 +#define IRQ6_MCU_SCP_EN_SFT 6 +#define IRQ5_MCU_SCP_EN_SFT 5 +#define IRQ4_MCU_SCP_EN_SFT 4 +#define IRQ3_MCU_SCP_EN_SFT 3 +#define IRQ2_MCU_SCP_EN_SFT 2 +#define IRQ1_MCU_SCP_EN_SFT 1 +#define IRQ0_MCU_SCP_EN_SFT 0 + +/* AFE_IRQ_MCU_DSP_EN */ +#define IRQ31_MCU_DSP_EN_SFT 31 +#define IRQ30_MCU_DSP_EN_SFT 30 +#define IRQ29_MCU_DSP_EN_SFT 29 +#define IRQ28_MCU_DSP_EN_SFT 28 +#define IRQ27_MCU_DSP_EN_SFT 27 +#define IRQ26_MCU_DSP_EN_SFT 26 +#define IRQ25_MCU_DSP_EN_SFT 25 +#define IRQ24_MCU_DSP_EN_SFT 24 +#define IRQ23_MCU_DSP_EN_SFT 23 +#define IRQ22_MCU_DSP_EN_SFT 22 +#define IRQ21_MCU_DSP_EN_SFT 21 +#define IRQ20_MCU_DSP_EN_SFT 20 +#define IRQ19_MCU_DSP_EN_SFT 19 +#define IRQ18_MCU_DSP_EN_SFT 18 +#define IRQ17_MCU_DSP_EN_SFT 17 +#define IRQ16_MCU_DSP_EN_SFT 16 +#define IRQ15_MCU_DSP_EN_SFT 15 +#define IRQ14_MCU_DSP_EN_SFT 14 +#define IRQ13_MCU_DSP_EN_SFT 13 +#define IRQ12_MCU_DSP_EN_SFT 12 +#define IRQ11_MCU_DSP_EN_SFT 11 +#define IRQ10_MCU_DSP_EN_SFT 10 +#define IRQ9_MCU_DSP_EN_SFT 9 +#define IRQ8_MCU_DSP_EN_SFT 8 +#define IRQ7_MCU_DSP_EN_SFT 7 +#define IRQ6_MCU_DSP_EN_SFT 6 +#define IRQ5_MCU_DSP_EN_SFT 5 +#define IRQ4_MCU_DSP_EN_SFT 4 +#define IRQ3_MCU_DSP_EN_SFT 3 +#define IRQ2_MCU_DSP_EN_SFT 2 +#define IRQ1_MCU_DSP_EN_SFT 1 +#define IRQ0_MCU_DSP_EN_SFT 0 + +/* AFE_AUD_PAD_TOP */ +#define AUD_PAD_TOP_MON_SFT 15 +#define AUD_PAD_TOP_MON_MASK_SFT GENMASK(31, 15) +#define AUD_PAD_TOP_FIFO_RSP_SFT 4 +#define AUD_PAD_TOP_FIFO_RSP_MASK_SFT GENMASK(7, 4) +#define RG_RX_PROTOCOL2_SFT 3 +#define RG_RX_PROTOCOL2_MASK_SFT BIT(3) +#define RESERVDED_01_SFT 1 +#define RESERVDED_01_MASK_SFT GENMASK(2, 1) +#define RG_RX_FIFO_ON_SFT 0 +#define RG_RX_FIFO_ON_MASK_SFT BIT(0) + +/* AFE_ADDA_MTKAIF_SYNCWORD_CFG */ +#define RG_ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE_SFT 23 +#define RG_ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE_MASK_SFT BIT(23) + +/* AFE_ADDA_MTKAIF_RX_CFG0 */ +#define MTKAIF_RXIF_VOICE_MODE_SFT 20 +#define MTKAIF_RXIF_VOICE_MODE_MASK_SFT GENMASK(23, 20) +#define MTKAIF_RXIF_DETECT_ON_SFT 16 +#define MTKAIF_RXIF_DETECT_ON_MASK_SFT BIT(16) +#define MTKAIF_RXIF_DATA_BIT_SFT 8 +#define MTKAIF_RXIF_DATA_BIT_MASK_SFT GENMASK(10, 8) +#define MTKAIF_RXIF_FIFO_RSP_SFT 4 +#define MTKAIF_RXIF_FIFO_RSP_MASK_SFT GENMASK(6, 4) +#define MTKAIF_RXIF_DATA_MODE_SFT 0 +#define MTKAIF_RXIF_DATA_MODE_MASK_SFT BIT(0) + +/* GENERAL_ASRC_MODE */ +#define GENERAL2_ASRCOUT_MODE_SFT 12 +#define GENERAL2_ASRCOUT_MODE_MASK 0xf +#define GENERAL2_ASRCOUT_MODE_MASK_SFT GENMASK(15, 12) +#define GENERAL2_ASRCIN_MODE_SFT 8 +#define GENERAL2_ASRCIN_MODE_MASK 0xf +#define GENERAL2_ASRCIN_MODE_MASK_SFT GENMASK(11, 8) +#define GENERAL1_ASRCOUT_MODE_SFT 4 +#define GENERAL1_ASRCOUT_MODE_MASK 0xf +#define GENERAL1_ASRCOUT_MODE_MASK_SFT GENMASK(7, 4) +#define GENERAL1_ASRCIN_MODE_SFT 0 +#define GENERAL1_ASRCIN_MODE_MASK 0xf +#define GENERAL1_ASRCIN_MODE_MASK_SFT GENMASK(3, 0) + +/* GENERAL_ASRC_EN_ON */ +#define GENERAL2_ASRC_EN_ON_SFT 1 +#define GENERAL2_ASRC_EN_ON_MASK_SFT BIT(1) +#define GENERAL1_ASRC_EN_ON_SFT 0 +#define GENERAL1_ASRC_EN_ON_MASK_SFT BIT(0) + +/* AFE_GENERAL1_ASRC_2CH_CON0 */ +#define G_SRC_CHSET_STR_CLR_SFT 4 +#define G_SRC_CHSET_STR_CLR_MASK_SFT BIT(4) +#define G_SRC_CHSET_ON_SFT 2 +#define G_SRC_CHSET_ON_MASK_SFT BIT(2) +#define G_SRC_COEFF_SRAM_CTRL_SFT 1 +#define G_SRC_COEFF_SRAM_CTRL_MASK_SFT BIT(1) +#define G_SRC_ASM_ON_SFT 0 +#define G_SRC_ASM_ON_MASK_SFT BIT(0) + +/* AFE_GENERAL1_ASRC_2CH_CON3 */ +#define G_SRC_ASM_FREQ_4_SFT 0 +#define G_SRC_ASM_FREQ_4_MASK_SFT GENMASK(23, 0) + +/* AFE_GENERAL1_ASRC_2CH_CON4 */ +#define G_SRC_ASM_FREQ_5_SFT 0 +#define G_SRC_ASM_FREQ_5_MASK_SFT GENMASK(23, 0) + +/* AFE_GENERAL1_ASRC_2CH_CON13 */ +#define G_SRC_COEFF_SRAM_ADR_SFT 0 +#define G_SRC_COEFF_SRAM_ADR_MASK_SFT GENMASK(5, 0) + +/* AFE_GENERAL1_ASRC_2CH_CON2 */ +#define G_SRC_CHSET_O16BIT_SFT 19 +#define G_SRC_CHSET_O16BIT_MASK_SFT BIT(19) +#define G_SRC_CHSET_CLR_IIR_HISTORY_SFT 17 +#define G_SRC_CHSET_CLR_IIR_HISTORY_MASK_SFT BIT(17) +#define G_SRC_CHSET_IS_MONO_SFT 16 +#define G_SRC_CHSET_IS_MONO_MASK_SFT BIT(16) +#define G_SRC_CHSET_IIR_EN_SFT 11 +#define G_SRC_CHSET_IIR_EN_MASK_SFT BIT(11) +#define G_SRC_CHSET_IIR_STAGE_SFT 8 +#define G_SRC_CHSET_IIR_STAGE_MASK_SFT GENMASK(10, 8) +#define G_SRC_CHSET_STR_CLR_RU_SFT 5 +#define G_SRC_CHSET_STR_CLR_RU_MASK_SFT BIT(5) +#define G_SRC_CHSET_ON_SFT 2 +#define G_SRC_CHSET_ON_MASK_SFT BIT(2) +#define G_SRC_COEFF_SRAM_CTRL_SFT 1 +#define G_SRC_COEFF_SRAM_CTRL_MASK_SFT BIT(1) +#define G_SRC_ASM_ON_SFT 0 +#define G_SRC_ASM_ON_MASK_SFT BIT(0) + +/* AFE_ADDA_DL_SDM_DITHER_CON */ +#define AFE_DL_SDM_DITHER_64TAP_EN_SFT 20 +#define AFE_DL_SDM_DITHER_64TAP_EN_MASK_SFT BIT(20) +#define AFE_DL_SDM_DITHER_EN_SFT 16 +#define AFE_DL_SDM_DITHER_EN_MASK_SFT BIT(16) +#define AFE_DL_SDM_DITHER_GAIN_SFT 0 +#define AFE_DL_SDM_DITHER_GAIN_MASK_SFT GENMASK(7, 0) + +/* AFE_ADDA_DL_SDM_AUTO_RESET_CON */ +#define SDM_AUTO_RESET_TEST_ON_SFT 31 +#define SDM_AUTO_RESET_TEST_ON_MASK_SFT BIT(31) +#define AFE_DL_USE_NEW_2ND_SDM_SFT 28 +#define AFE_DL_USE_NEW_2ND_SDM_MASK_SFT BIT(28) +#define SDM_AUTO_RESET_COUNT_TH_SFT 0 +#define SDM_AUTO_RESET_COUNT_TH_MASK_SFT GENMASK(23, 0) + +/* AFE_ASRC_2CH_CON0 */ +#define CON0_CHSET_STR_CLR_SFT 4 +#define CON0_CHSET_STR_CLR_MASK_SFT BIT(4) +#define CON0_ASM_ON_SFT 0 +#define CON0_ASM_ON_MASK_SFT BIT(0) + +/* AFE_ASRC_2CH_CON5 */ +#define CALI_EN_SFT 0 +#define CALI_EN_MASK_SFT BIT(0) + +/* FPGA_CFG4 */ +#define IRQ_COUNTER_SFT 3 +#define IRQ_COUNTER_MASK_SFT GENMASK(31, 3) +#define IRQ_CLK_COUNTER_CLEAN_SFT 2 +#define IRQ_CLK_COUNTER_CLEAN_MASK_SFT BIT(2) +#define IRQ_CLK_COUNTER_PAUSE_SFT 1 +#define IRQ_CLK_COUNTER_PAUSE_MASK_SFT BIT(1) +#define IRQ_CLK_COUNTER_ON_SFT 0 +#define IRQ_CLK_COUNTER_ON_MASK_SFT BIT(0) + +/* FPGA_CFG5 */ +#define WR_MSTR_ON_SFT 16 +#define WR_MSTR_ON_MASK_SFT GENMASK(28, 16) +#define WR_AG_SEL_SFT 0 +#define WR_AG_SEL_MASK_SFT GENMASK(12, 0) + +/* FPGA_CFG6 */ +#define WR_MSTR_REQ_REAL_SFT 16 +#define WR_MSTR_REQ_REAL_MASK_SFT GENMASK(28, 16) +#define WR_MSTR_REQ_IN_SFT 0 +#define WR_MSTR_REQ_IN_MASK_SFT GENMASK(12, 0) + +/* FPGA_CFG7 */ +#define MEM1_WDATA_MON0_SFT 0 +#define MEM1_WDATA_MON0_MASK_SFT GENMASK(31, 0) + +/* FPGA_CFG8 */ +#define MEM1_WDATA_MON1_SFT 0 +#define MEM1_WDATA_MON1_MASK_SFT GENMASK(31, 0) + +/* FPGA_CFG9 */ +#define MEM_WE_SFT 31 +#define MEM_WE_MASK_SFT BIT(31) +#define AFE_HREADY_SFT 30 +#define AFE_HREADY_MASK_SFT BIT(30) +#define MEM_WR_REQ_SFT 29 +#define MEM_WR_REQ_MASK_SFT BIT(29) +#define WR_AG_REG_MON_SFT 16 +#define WR_AG_REG_MON_MASK_SFT GENMASK(28, 16) +#define HCLK_CK_SFT 15 +#define HCLK_CK_MASK_SFT BIT(15) +#define MEM_RD_REQ_SFT 14 +#define MEM_RD_REQ_MASK_SFT BIT(14) +#define RD_AG_REQ_MON_SFT 0 +#define RD_AG_REQ_MON_MASK_SFT GENMASK(13, 0) + +/* FPGA_CFG10 */ +#define MEM_BYTE_0_SFT 0 +#define MEM_BYTE_0_MASK_SFT GENMASK(31, 0) + +/* FPGA_CFG11 */ +#define MEM_BYTE_1_SFT 0 +#define MEM_BYTE_1_MASK_SFT GENMASK(31, 0) + +/* FPGA_CFG12 */ +#define RDATA_CNT_SFT 30 +#define RDATA_CNT_MASK_SFT GENMASK(31, 30) +#define MS2_HREADY_SFT 29 +#define MS2_HREADY_MASK_SFT BIT(29) +#define MS1_HREADY_SFT 28 +#define MS1_HREADY_MASK_SFT BIT(28) +#define AG_SEL_SFT 0 +#define AG_SEL_MASK_SFT GENMASK(25, 0) + +/* FPGA_CFG13 */ +#define AFE_ST_SFT 27 +#define AFE_ST_MASK_SFT GENMASK(31, 27) +#define AG_IN_SERVICE_SFT 0 +#define AG_IN_SERVICE_MASK_SFT GENMASK(25, 0) + +/* ETDM_IN1_CON0 */ +#define ETDM_IN1_CON0_REG_ETDM_IN_EN_SFT 0 +#define ETDM_IN1_CON0_REG_ETDM_IN_EN_MASK_SFT BIT(0) +#define ETDM_IN1_CON0_REG_SYNC_MODE_SFT 1 +#define ETDM_IN1_CON0_REG_SYNC_MODE_MASK_SFT BIT(1) +#define ETDM_IN1_CON0_REG_LSB_FIRST_SFT 3 +#define ETDM_IN1_CON0_REG_LSB_FIRST_MASK_SFT BIT(3) +#define ETDM_IN1_CON0_REG_SOFT_RST_SFT 4 +#define ETDM_IN1_CON0_REG_SOFT_RST_MASK_SFT BIT(4) +#define ETDM_IN1_CON0_REG_SLAVE_MODE_SFT 5 +#define ETDM_IN1_CON0_REG_SLAVE_MODE_MASK_SFT BIT(5) +#define ETDM_IN1_CON0_REG_FMT_SFT 6 +#define ETDM_IN1_CON0_REG_FMT_MASK_SFT GENMASK(8, 6) +#define ETDM_IN1_CON0_REG_LRCK_EDGE_SEL_SFT 10 +#define ETDM_IN1_CON0_REG_LRCK_EDGE_SEL_MASK_SFT BIT(10) +#define ETDM_IN1_CON0_REG_BIT_LENGTH_SFT 11 +#define ETDM_IN1_CON0_REG_BIT_LENGTH_MASK_SFT GENMASK(15, 11) +#define ETDM_IN1_CON0_REG_WORD_LENGTH_SFT 16 +#define ETDM_IN1_CON0_REG_WORD_LENGTH_MASK_SFT GENMASK(20, 16) +#define ETDM_IN1_CON0_REG_CH_NUM_SFT 23 +#define ETDM_IN1_CON0_REG_CH_NUM_MASK_SFT GENMASK(27, 23) +#define ETDM_IN1_CON0_REG_RELATCH_1X_EN_SEL_DOMAIN_SFT 28 +#define ETDM_IN1_CON0_REG_RELATCH_1X_EN_SEL_DOMAIN_MASK_SFT GENMASK(31, 28) +#define ETDM_IN1_CON0_REG_VALID_TOGETHER_SFT 31 +#define ETDM_IN1_CON0_REG_VALID_TOGETHER_MASK_SFT BIT(31) +#define ETDM_IN_CON0_CTRL_MASK 0x1f9ff9e2 + +/* ETDM_IN1_CON1 */ +#define ETDM_IN1_CON1_REG_INITIAL_COUNT_SFT 0 +#define ETDM_IN1_CON1_REG_INITIAL_COUNT_MASK_SFT GENMASK(4, 0) +#define ETDM_IN1_CON1_REG_INITIAL_POINT_SFT 5 +#define ETDM_IN1_CON1_REG_INITIAL_POINT_MASK_SFT GENMASK(9, 5) +#define ETDM_IN1_CON1_REG_LRCK_AUTO_OFF_SFT 10 +#define ETDM_IN1_CON1_REG_LRCK_AUTO_OFF_MASK_SFT BIT(10) +#define ETDM_IN1_CON1_REG_BCK_AUTO_OFF_SFT 11 +#define ETDM_IN1_CON1_REG_BCK_AUTO_OFF_MASK_SFT BIT(11) +#define ETDM_IN1_CON1_REG_INITIAL_LRCK_SFT 13 +#define ETDM_IN1_CON1_REG_INITIAL_LRCK_MASK_SFT BIT(13) +#define ETDM_IN1_CON1_REG_LRCK_RESET_SFT 15 +#define ETDM_IN1_CON1_REG_LRCK_RESET_MASK_SFT BIT(15) +#define ETDM_IN1_CON1_PINMUX_MCLK_CTRL_OE_SFT 16 +#define ETDM_IN1_CON1_PINMUX_MCLK_CTRL_OE_MASK_SFT BIT(16) +#define ETDM_IN1_CON1_REG_OUTPUT_CR_EN_SFT 18 +#define ETDM_IN1_CON1_REG_OUTPUT_CR_EN_MASK_SFT BIT(18) +#define ETDM_IN1_CON1_REG_LR_ALIGN_SFT 19 +#define ETDM_IN1_CON1_REG_LR_ALIGN_MASK_SFT BIT(19) +#define ETDM_IN1_CON1_REG_LRCK_WIDTH_SFT 20 +#define ETDM_IN1_CON1_REG_LRCK_WIDTH_MASK_SFT GENMASK(29, 20) +#define ETDM_IN1_CON1_REG_DIRECT_INPUT_MASTER_BCK_SFT 30 +#define ETDM_IN1_CON1_REG_DIRECT_INPUT_MASTER_BCK_MASK_SFT BIT(30) +#define ETDM_IN1_CON1_REG_LRCK_AUTO_MODE_SFT 31 +#define ETDM_IN1_CON1_REG_LRCK_AUTO_MODE_MASK_SFT BIT(31) +#define ETDM_IN_CON1_CTRL_MASK 0xbff10000 + +/* ETDM_IN1_CON2 */ +#define ETDM_IN1_CON2_REG_UPDATE_POINT_SFT 0 +#define ETDM_IN1_CON2_REG_UPDATE_POINT_MASK_SFT GENMASK(4, 0) +#define ETDM_IN1_CON2_REG_UPDATE_GAP_SFT 5 +#define ETDM_IN1_CON2_REG_UPDATE_GAP_MASK_SFT GENMASK(9, 5) +#define ETDM_IN1_CON2_REG_CLOCK_SOURCE_SEL_SFT 10 +#define ETDM_IN1_CON2_REG_CLOCK_SOURCE_SEL_MASK_SFT GENMASK(12, 10) +#define ETDM_IN1_CON2_REG_AGENT_USE_ETDM_BCK_SFT 13 +#define ETDM_IN1_CON2_REG_AGENT_USE_ETDM_BCK_MASK_SFT BIT(13) +#define ETDM_IN1_CON2_REG_CK_EN_SEL_AUTO_SFT 14 +#define ETDM_IN1_CON2_REG_CK_EN_SEL_AUTO_MASK_SFT BIT(14) +#define ETDM_IN1_CON2_REG_MULTI_IP_ONE_DATA_CH_NUM_SFT 15 +#define ETDM_IN1_CON2_REG_MULTI_IP_ONE_DATA_CH_NUM_MASK_SFT GENMASK(19, 15) +#define ETDM_IN1_CON2_REG_MASK_AUTO_SFT 20 +#define ETDM_IN1_CON2_REG_MASK_AUTO_MASK_SFT BIT(20) +#define ETDM_IN1_CON2_REG_MASK_NUM_SFT 21 +#define ETDM_IN1_CON2_REG_MASK_NUM_MASK_SFT GENMASK(25, 21) +#define ETDM_IN1_CON2_REG_UPDATE_POINT_AUTO_SFT 26 +#define ETDM_IN1_CON2_REG_UPDATE_POINT_AUTO_MASK_SFT BIT(26) +#define ETDM_IN1_CON2_REG_SDATA_DELAY_0P5T_EN_SFT 27 +#define ETDM_IN1_CON2_REG_SDATA_DELAY_0P5T_EN_MASK_SFT BIT(27) +#define ETDM_IN1_CON2_REG_SDATA_DELAY_BCK_INV_SFT 28 +#define ETDM_IN1_CON2_REG_SDATA_DELAY_BCK_INV_MASK_SFT BIT(28) +#define ETDM_IN1_CON2_REG_LRCK_DELAY_0P5T_EN_SFT 29 +#define ETDM_IN1_CON2_REG_LRCK_DELAY_0P5T_EN_MASK_SFT BIT(29) +#define ETDM_IN1_CON2_REG_LRCK_DELAY_BCK_INV_SFT 30 +#define ETDM_IN1_CON2_REG_LRCK_DELAY_BCK_INV_MASK_SFT BIT(30) +#define ETDM_IN1_CON2_REG_MULTI_IP_MODE_SFT 31 +#define ETDM_IN1_CON2_REG_MULTI_IP_MODE_MASK_SFT BIT(31) +#define ETDM_IN_CON2_CTRL_MASK 0x800f8000 +#define ETDM_IN_CON2_MULTI_IP_CH(x) (((x) - 1) << 15) +#define ETDM_IN_CON2_MULTI_IP_2CH_MODE BIT(31) + +/* ETDM_IN1_CON3 */ +#define ETDM_IN1_CON3_REG_DISABLE_OUT_0_SFT 0 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_0_MASK_SFT BIT(0) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_1_SFT 1 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_1_MASK_SFT BIT(1) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_2_SFT 2 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_2_MASK_SFT BIT(2) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_3_SFT 3 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_3_MASK_SFT BIT(3) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_4_SFT 4 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_4_MASK_SFT BIT(4) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_5_SFT 5 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_5_MASK_SFT BIT(5) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_6_SFT 6 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_6_MASK_SFT BIT(6) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_7_SFT 7 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_7_MASK_SFT BIT(7) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_8_SFT 8 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_8_MASK_SFT BIT(8) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_9_SFT 9 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_9_MASK_SFT BIT(9) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_10_SFT 10 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_10_MASK_SFT BIT(10) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_11_SFT 11 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_11_MASK_SFT BIT(11) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_12_SFT 12 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_12_MASK_SFT BIT(12) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_13_SFT 13 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_13_MASK_SFT BIT(13) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_14_SFT 14 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_14_MASK_SFT BIT(14) +#define ETDM_IN1_CON3_REG_DISABLE_OUT_15_SFT 15 +#define ETDM_IN1_CON3_REG_DISABLE_OUT_15_MASK_SFT BIT(15) +#define ETDM_IN1_CON3_REG_RJ_DATA_RIGHT_ALIGN_SFT 16 +#define ETDM_IN1_CON3_REG_RJ_DATA_RIGHT_ALIGN_MASK_SFT BIT(16) +#define ETDM_IN1_CON3_REG_MONITOR_SEL_SFT 17 +#define ETDM_IN1_CON3_REG_MONITOR_SEL_MASK_SFT GENMASK(18, 17) +#define ETDM_IN1_CON3_REG_CNT_UPPER_LIMIT_SFT 19 +#define ETDM_IN1_CON3_REG_CNT_UPPER_LIMIT_MASK_SFT GENMASK(24, 19) +#define ETDM_IN1_CON3_REG_COMPACT_SAMPLE_END_DIS_SFT 25 +#define ETDM_IN1_CON3_REG_COMPACT_SAMPLE_END_DIS_MASK_SFT BIT(25) +#define ETDM_IN1_CON3_REG_FS_TIMING_SEL_SFT 26 +#define ETDM_IN1_CON3_REG_FS_TIMING_SEL_MASK_SFT GENMASK(30, 26) +#define ETDM_IN1_CON3_REG_SAMPLE_END_MODE_SFT 31 +#define ETDM_IN1_CON3_REG_SAMPLE_END_MODE_MASK_SFT BIT(31) +#define ETDM_IN_CON3_CTRL_MASK (0x7c000000) +#define ETDM_IN_CON3_FS(x) (((x) & 0x1f) << 26) + +/* ETDM_IN1_CON4 */ +#define ETDM_IN1_CON4_REG_DSD_MODE_SFT 0 +#define ETDM_IN1_CON4_REG_DSD_MODE_MASK_SFT GENMASK(5, 0) +#define ETDM_IN1_CON4_REG_DSD_REPACK_AUTO_MODE_SFT 8 +#define ETDM_IN1_CON4_REG_DSD_REPACK_AUTO_MODE_MASK_SFT BIT(8) +#define ETDM_IN1_CON4_REG_REPACK_WORD_LENGTH_SFT 9 +#define ETDM_IN1_CON4_REG_REPACK_WORD_LENGTH_MASK_SFT GENMASK(10, 9) +#define ETDM_IN1_CON4_REG_ASYNC_RESET_SFT 11 +#define ETDM_IN1_CON4_REG_ASYNC_RESET_MASK_SFT BIT(11) +#define ETDM_IN1_CON4_REG_DSD_CHNUM_SFT 12 +#define ETDM_IN1_CON4_REG_DSD_CHNUM_MASK_SFT GENMASK(15, 12) +#define ETDM_IN1_CON4_REG_SLAVE_BCK_INV_SFT 16 +#define ETDM_IN1_CON4_REG_SLAVE_BCK_INV_MASK_SFT BIT(16) +#define ETDM_IN1_CON4_REG_SLAVE_LRCK_INV_SFT 17 +#define ETDM_IN1_CON4_REG_SLAVE_LRCK_INV_MASK_SFT BIT(17) +#define ETDM_IN1_CON4_REG_MASTER_BCK_INV_SFT 18 +#define ETDM_IN1_CON4_REG_MASTER_BCK_INV_MASK_SFT BIT(18) +#define ETDM_IN1_CON4_REG_MASTER_LRCK_INV_SFT 19 +#define ETDM_IN1_CON4_REG_MASTER_LRCK_INV_MASK_SFT BIT(19) +#define ETDM_IN1_CON4_REG_RELATCH_1X_EN_SEL_SFT 20 +#define ETDM_IN1_CON4_REG_RELATCH_1X_EN_SEL_MASK_SFT GENMASK(24, 20) +#define ETDM_IN1_CON4_REG_SAMPLE_END_POINT_SFT 25 +#define ETDM_IN1_CON4_REG_SAMPLE_END_POINT_MASK_SFT GENMASK(29, 25) +#define ETDM_IN1_CON4_REG_WAIT_LAST_SAMPLE_SFT 30 +#define ETDM_IN1_CON4_REG_WAIT_LAST_SAMPLE_MASK_SFT BIT(30) +#define ETDM_IN1_CON4_REG_MASTER_BCK_FORCE_ON_SFT 31 +#define ETDM_IN1_CON4_REG_MASTER_BCK_FORCE_ON_MASK_SFT BIT(31) +#define ETDM_IN_CON4_CTRL_MASK 0x1ff0000 +#define ETDM_IN_CON4_FS(x) (((x) & 0x1f) << 20) +#define ETDM_IN_CON4_CON0_MASTER_LRCK_INV BIT(19) +#define ETDM_IN_CON4_CON0_MASTER_BCK_INV BIT(18) +#define ETDM_IN_CON4_CON0_SLAVE_LRCK_INV BIT(17) +#define ETDM_IN_CON4_CON0_SLAVE_BCK_INV BIT(16) + +/* ETDM_IN1_CON5 */ +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_0_SFT 0 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_0_MASK_SFT BIT(0) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_1_SFT 1 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_1_MASK_SFT BIT(1) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_2_SFT 2 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_2_MASK_SFT BIT(2) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_3_SFT 3 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_3_MASK_SFT BIT(3) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_4_SFT 4 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_4_MASK_SFT BIT(4) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_5_SFT 5 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_5_MASK_SFT BIT(5) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_6_SFT 6 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_6_MASK_SFT BIT(6) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_7_SFT 7 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_7_MASK_SFT BIT(7) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_8_SFT 8 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_8_MASK_SFT BIT(8) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_9_SFT 9 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_9_MASK_SFT BIT(9) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_10_SFT 10 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_10_MASK_SFT BIT(10) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_11_SFT 11 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_11_MASK_SFT BIT(11) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_12_SFT 12 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_12_MASK_SFT BIT(12) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_13_SFT 13 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_13_MASK_SFT BIT(13) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_14_SFT 14 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_14_MASK_SFT BIT(14) +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_15_SFT 15 +#define ETDM_IN1_CON5_REG_ODD_FLAG_EN_15_MASK_SFT BIT(15) +#define ETDM_IN1_CON5_REG_LR_SWAP_0_SFT 16 +#define ETDM_IN1_CON5_REG_LR_SWAP_0_MASK_SFT BIT(16) +#define ETDM_IN1_CON5_REG_LR_SWAP_1_SFT 17 +#define ETDM_IN1_CON5_REG_LR_SWAP_1_MASK_SFT BIT(17) +#define ETDM_IN1_CON5_REG_LR_SWAP_2_SFT 18 +#define ETDM_IN1_CON5_REG_LR_SWAP_2_MASK_SFT BIT(18) +#define ETDM_IN1_CON5_REG_LR_SWAP_3_SFT 19 +#define ETDM_IN1_CON5_REG_LR_SWAP_3_MASK_SFT BIT(19) +#define ETDM_IN1_CON5_REG_LR_SWAP_4_SFT 20 +#define ETDM_IN1_CON5_REG_LR_SWAP_4_MASK_SFT BIT(20) +#define ETDM_IN1_CON5_REG_LR_SWAP_5_SFT 21 +#define ETDM_IN1_CON5_REG_LR_SWAP_5_MASK_SFT BIT(21) +#define ETDM_IN1_CON5_REG_LR_SWAP_6_SFT 22 +#define ETDM_IN1_CON5_REG_LR_SWAP_6_MASK_SFT BIT(22) +#define ETDM_IN1_CON5_REG_LR_SWAP_7_SFT 23 +#define ETDM_IN1_CON5_REG_LR_SWAP_7_MASK_SFT BIT(23) +#define ETDM_IN1_CON5_REG_LR_SWAP_8_SFT 24 +#define ETDM_IN1_CON5_REG_LR_SWAP_8_MASK_SFT BIT(24) +#define ETDM_IN1_CON5_REG_LR_SWAP_9_SFT 25 +#define ETDM_IN1_CON5_REG_LR_SWAP_9_MASK_SFT BIT(25) +#define ETDM_IN1_CON5_REG_LR_SWAP_10_SFT 26 +#define ETDM_IN1_CON5_REG_LR_SWAP_10_MASK_SFT BIT(26) +#define ETDM_IN1_CON5_REG_LR_SWAP_11_SFT 27 +#define ETDM_IN1_CON5_REG_LR_SWAP_11_MASK_SFT BIT(27) +#define ETDM_IN1_CON5_REG_LR_SWAP_12_SFT 28 +#define ETDM_IN1_CON5_REG_LR_SWAP_12_MASK_SFT BIT(28) +#define ETDM_IN1_CON5_REG_LR_SWAP_13_SFT 29 +#define ETDM_IN1_CON5_REG_LR_SWAP_13_MASK_SFT BIT(29) +#define ETDM_IN1_CON5_REG_LR_SWAP_14_SFT 30 +#define ETDM_IN1_CON5_REG_LR_SWAP_14_MASK_SFT BIT(30) +#define ETDM_IN1_CON5_REG_LR_SWAP_15_SFT 31 +#define ETDM_IN1_CON5_REG_LR_SWAP_15_MASK_SFT BIT(31) + +/* ETDM_IN1_CON6 */ +#define ETDM_IN1_CON6_LCH_DATA_REG_SFT 0 +#define ETDM_IN1_CON6_LCH_DATA_REG_MASK_SFT GENMASK(31, 0) + +/* ETDM_IN1_CON7 */ +#define ETDM_IN1_CON7_RCH_DATA_REG_SFT 0 +#define ETDM_IN1_CON7_RCH_DATA_REG_MASK_SFT GENMASK(31, 0) + +/* ETDM_IN1_CON8 */ +#define ETDM_IN1_CON8_REG_AFIFO_THRESHOLD_SFT 29 +#define ETDM_IN1_CON8_REG_AFIFO_THRESHOLD_MASK_SFT GENMASK(30, 29) +#define ETDM_IN1_CON8_REG_CK_EN_SEL_MANUAL_SFT 16 +#define ETDM_IN1_CON8_REG_CK_EN_SEL_MANUAL_MASK_SFT GENMASK(25, 16) +#define ETDM_IN1_CON8_REG_AFIFO_SW_RESET_SFT 15 +#define ETDM_IN1_CON8_REG_AFIFO_SW_RESET_MASK_SFT BIT(15) +#define ETDM_IN1_CON8_REG_AFIFO_RESET_SEL_SFT 14 +#define ETDM_IN1_CON8_REG_AFIFO_RESET_SEL_MASK_SFT BIT(14) +#define ETDM_IN1_CON8_REG_AFIFO_AUTO_RESET_DIS_SFT 9 +#define ETDM_IN1_CON8_REG_AFIFO_AUTO_RESET_DIS_MASK_SFT BIT(9) +#define ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT 8 +#define ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_MASK_SFT BIT(8) +#define ETDM_IN1_CON8_REG_AFIFO_CLOCK_DOMAIN_SEL_SFT 5 +#define ETDM_IN1_CON8_REG_AFIFO_CLOCK_DOMAIN_SEL_MASK_SFT GENMASK(7, 5) +#define ETDM_IN1_CON8_REG_AFIFO_MODE_SFT 0 +#define ETDM_IN1_CON8_REG_AFIFO_MODE_MASK_SFT GENMASK(4, 0) +#define ETDM_IN_CON8_FS(x) (((x) & 0x1f) << 0) +#define ETDM_IN_CON8_CTRL_MASK 0x13f + +#define AUDIO_TOP_CON0 0x0000 +#define AUDIO_TOP_CON1 0x0004 +#define AUDIO_TOP_CON2 0x0008 +#define AUDIO_TOP_CON3 0x000c +#define AFE_DAC_CON0 0x0010 +#define AFE_I2S_CON 0x0018 +#define AFE_CONN0 0x0020 +#define AFE_CONN1 0x0024 +#define AFE_CONN2 0x0028 +#define AFE_CONN3 0x002c +#define AFE_CONN4 0x0030 +#define AFE_I2S_CON1 0x0034 +#define AFE_I2S_CON2 0x0038 +#define AFE_I2S_CON3 0x0040 +#define AFE_CONN5 0x0044 +#define AFE_CONN_24BIT 0x0048 +#define AFE_DL1_CON0 0x004c +#define AFE_DL1_BASE_MSB 0x0050 +#define AFE_DL1_BASE 0x0054 +#define AFE_DL1_CUR_MSB 0x0058 +#define AFE_DL1_CUR 0x005c +#define AFE_DL1_END_MSB 0x0060 +#define AFE_DL1_END 0x0064 +#define AFE_DL2_CON0 0x0068 +#define AFE_DL2_BASE_MSB 0x006c +#define AFE_DL2_BASE 0x0070 +#define AFE_DL2_CUR_MSB 0x0074 +#define AFE_DL2_CUR 0x0078 +#define AFE_DL2_END_MSB 0x007c +#define AFE_DL2_END 0x0080 +#define AFE_DL3_CON0 0x0084 +#define AFE_DL3_BASE_MSB 0x0088 +#define AFE_DL3_BASE 0x008c +#define AFE_DL3_CUR_MSB 0x0090 +#define AFE_DL3_CUR 0x0094 +#define AFE_DL3_END_MSB 0x0098 +#define AFE_DL3_END 0x009c +#define AFE_CONN6 0x00bc +#define AFE_DL4_CON0 0x00cc +#define AFE_DL4_BASE_MSB 0x00d0 +#define AFE_DL4_BASE 0x00d4 +#define AFE_DL4_CUR_MSB 0x00d8 +#define AFE_DL4_CUR 0x00dc +#define AFE_DL4_END_MSB 0x00e0 +#define AFE_DL4_END 0x00e4 +#define AFE_DL12_CON0 0x00e8 +#define AFE_DL12_BASE_MSB 0x00ec +#define AFE_DL12_BASE 0x00f0 +#define AFE_DL12_CUR_MSB 0x00f4 +#define AFE_DL12_CUR 0x00f8 +#define AFE_DL12_END_MSB 0x00fc +#define AFE_DL12_END 0x0100 +#define AFE_ADDA_DL_SRC2_CON0 0x0108 +#define AFE_ADDA_DL_SRC2_CON1 0x010c +#define AFE_ADDA_UL_SRC_CON0 0x0114 +#define AFE_ADDA_UL_SRC_CON1 0x0118 +#define AFE_ADDA_TOP_CON0 0x0120 +#define AFE_ADDA_UL_DL_CON0 0x0124 +#define AFE_ADDA_SRC_DEBUG 0x012c +#define AFE_ADDA_SRC_DEBUG_MON0 0x0130 +#define AFE_ADDA_SRC_DEBUG_MON1 0x0134 +#define AFE_ADDA_UL_SRC_MON0 0x0148 +#define AFE_ADDA_UL_SRC_MON1 0x014c +#define AFE_SECURE_CON0 0x0150 +#define AFE_SRAM_BOUND 0x0154 +#define AFE_SECURE_CON1 0x0158 +#define AFE_SECURE_CONN0 0x015c +#define AFE_VUL_CON0 0x0170 +#define AFE_VUL_BASE_MSB 0x0174 +#define AFE_VUL_BASE 0x0178 +#define AFE_VUL_CUR_MSB 0x017c +#define AFE_VUL_CUR 0x0180 +#define AFE_VUL_END_MSB 0x0184 +#define AFE_VUL_END 0x0188 +#define AFE_SIDETONE_DEBUG 0x01d0 +#define AFE_SIDETONE_MON 0x01d4 +#define AFE_SINEGEN_CON2 0x01dc +#define AFE_SIDETONE_CON0 0x01e0 +#define AFE_SIDETONE_COEFF 0x01e4 +#define AFE_SIDETONE_CON1 0x01e8 +#define AFE_SIDETONE_GAIN 0x01ec +#define AFE_SINEGEN_CON0 0x01f0 +#define AFE_TOP_CON0 0x0200 +#define AFE_VUL2_CON0 0x020c +#define AFE_VUL2_BASE_MSB 0x0210 +#define AFE_VUL2_BASE 0x0214 +#define AFE_VUL2_CUR_MSB 0x0218 +#define AFE_VUL2_CUR 0x021c +#define AFE_VUL2_END_MSB 0x0220 +#define AFE_VUL2_END 0x0224 +#define AFE_VUL3_CON0 0x0228 +#define AFE_VUL3_BASE_MSB 0x022c +#define AFE_VUL3_BASE 0x0230 +#define AFE_VUL3_CUR_MSB 0x0234 +#define AFE_VUL3_CUR 0x0238 +#define AFE_VUL3_END_MSB 0x023c +#define AFE_VUL3_END 0x0240 +#define AFE_BUSY 0x0244 +#define AFE_BUS_CFG 0x0250 +#define AFE_ADDA_PREDIS_CON0 0x0260 +#define AFE_ADDA_PREDIS_CON1 0x0264 +#define AFE_I2S_MON 0x027c +#define AFE_ADDA_IIR_COEF_02_01 0x0290 +#define AFE_ADDA_IIR_COEF_04_03 0x0294 +#define AFE_ADDA_IIR_COEF_06_05 0x0298 +#define AFE_ADDA_IIR_COEF_08_07 0x029c +#define AFE_ADDA_IIR_COEF_10_09 0x02a0 +#define AFE_IRQ_MCU_CON1 0x02e4 +#define AFE_IRQ_MCU_CON2 0x02e8 +#define AFE_DAC_MON 0x02ec +#define AFE_IRQ_MCU_CON3 0x02f0 +#define AFE_IRQ_MCU_CON4 0x02f4 +#define AFE_IRQ_MCU_CNT0 0x0300 +#define AFE_IRQ_MCU_CNT6 0x0304 +#define AFE_IRQ_MCU_CNT8 0x0308 +#define AFE_IRQ_MCU_DSP2_EN 0x030c +#define AFE_IRQ0_MCU_CNT_MON 0x0310 +#define AFE_IRQ6_MCU_CNT_MON 0x0314 +#define AFE_VUL4_CON0 0x0358 +#define AFE_VUL4_BASE_MSB 0x035c +#define AFE_VUL4_BASE 0x0360 +#define AFE_VUL4_CUR_MSB 0x0364 +#define AFE_VUL4_CUR 0x0368 +#define AFE_VUL4_END_MSB 0x036c +#define AFE_VUL4_END 0x0370 +#define AFE_VUL12_CON0 0x0374 +#define AFE_VUL12_BASE_MSB 0x0378 +#define AFE_VUL12_BASE 0x037c +#define AFE_VUL12_CUR_MSB 0x0380 +#define AFE_VUL12_CUR 0x0384 +#define AFE_VUL12_END_MSB 0x0388 +#define AFE_VUL12_END 0x038c +#define AFE_IRQ3_MCU_CNT_MON 0x0398 +#define AFE_IRQ4_MCU_CNT_MON 0x039c +#define AFE_IRQ_MCU_CON0 0x03a0 +#define AFE_IRQ_MCU_STATUS 0x03a4 +#define AFE_IRQ_MCU_CLR 0x03a8 +#define AFE_IRQ_MCU_CNT1 0x03ac +#define AFE_IRQ_MCU_CNT2 0x03b0 +#define AFE_IRQ_MCU_EN 0x03b4 +#define AFE_IRQ_MCU_MON2 0x03b8 +#define AFE_IRQ_MCU_CNT5 0x03bc +#define AFE_IRQ1_MCU_CNT_MON 0x03c0 +#define AFE_IRQ2_MCU_CNT_MON 0x03c4 +#define AFE_IRQ5_MCU_CNT_MON 0x03cc +#define AFE_IRQ_MCU_DSP_EN 0x03d0 +#define AFE_IRQ_MCU_SCP_EN 0x03d4 +#define AFE_IRQ_MCU_CNT7 0x03dc +#define AFE_IRQ7_MCU_CNT_MON 0x03e0 +#define AFE_IRQ_MCU_CNT3 0x03e4 +#define AFE_IRQ_MCU_CNT4 0x03e8 +#define AFE_IRQ_MCU_CNT11 0x03ec +#define AFE_APLL1_TUNER_CFG 0x03f0 +#define AFE_APLL2_TUNER_CFG 0x03f4 +#define AFE_IRQ_MCU_MISS_CLR 0x03f8 +#define AFE_CONN33 0x0408 +#define AFE_IRQ_MCU_CNT12 0x040c +#define AFE_GAIN1_CON0 0x0410 +#define AFE_GAIN1_CON1 0x0414 +#define AFE_GAIN1_CON2 0x0418 +#define AFE_GAIN1_CON3 0x041c +#define AFE_CONN7 0x0420 +#define AFE_GAIN1_CUR 0x0424 +#define AFE_GAIN2_CON0 0x0428 +#define AFE_GAIN2_CON1 0x042c +#define AFE_GAIN2_CON2 0x0430 +#define AFE_GAIN2_CON3 0x0434 +#define AFE_CONN8 0x0438 +#define AFE_GAIN2_CUR 0x043c +#define AFE_CONN9 0x0440 +#define AFE_CONN10 0x0444 +#define AFE_CONN11 0x0448 +#define AFE_CONN12 0x044c +#define AFE_CONN13 0x0450 +#define AFE_CONN14 0x0454 +#define AFE_CONN15 0x0458 +#define AFE_CONN16 0x045c +#define AFE_CONN17 0x0460 +#define AFE_CONN18 0x0464 +#define AFE_CONN19 0x0468 +#define AFE_CONN20 0x046c +#define AFE_CONN21 0x0470 +#define AFE_CONN22 0x0474 +#define AFE_CONN23 0x0478 +#define AFE_CONN24 0x047c +#define AFE_CONN_RS 0x0494 +#define AFE_CONN_DI 0x0498 +#define AFE_CONN25 0x04b0 +#define AFE_CONN26 0x04b4 +#define AFE_CONN27 0x04b8 +#define AFE_CONN28 0x04bc +#define AFE_CONN29 0x04c0 +#define AFE_CONN30 0x04c4 +#define AFE_CONN31 0x04c8 +#define AFE_CONN32 0x04cc +#define AFE_SRAM_DELSEL_CON1 0x04f4 +#define AFE_CONN56 0x0500 +#define AFE_CONN57 0x0504 +#define AFE_CONN58 0x0508 +#define AFE_CONN59 0x050c +#define AFE_CONN56_1 0x0510 +#define AFE_CONN57_1 0x0514 +#define AFE_CONN58_1 0x0518 +#define AFE_CONN59_1 0x051c +#define PCM_INTF_CON1 0x0530 +#define PCM_INTF_CON2 0x0538 +#define PCM2_INTF_CON 0x053c +#define AFE_CM1_CON 0x0550 +#define AFE_CONN34 0x0580 +#define FPGA_CFG0 0x05b0 +#define FPGA_CFG1 0x05b4 +#define FPGA_CFG2 0x05c0 +#define FPGA_CFG3 0x05c4 +#define AUDIO_TOP_DBG_CON 0x05c8 +#define AUDIO_TOP_DBG_MON0 0x05cc +#define AUDIO_TOP_DBG_MON1 0x05d0 +#define AFE_IRQ8_MCU_CNT_MON 0x05e4 +#define AFE_IRQ11_MCU_CNT_MON 0x05e8 +#define AFE_IRQ12_MCU_CNT_MON 0x05ec +#define AFE_IRQ_MCU_CNT9 0x0600 +#define AFE_IRQ_MCU_CNT10 0x0604 +#define AFE_IRQ_MCU_CNT13 0x0608 +#define AFE_IRQ_MCU_CNT14 0x060c +#define AFE_IRQ_MCU_CNT15 0x0610 +#define AFE_IRQ_MCU_CNT16 0x0614 +#define AFE_IRQ_MCU_CNT17 0x0618 +#define AFE_IRQ_MCU_CNT18 0x061c +#define AFE_IRQ_MCU_CNT19 0x0620 +#define AFE_IRQ_MCU_CNT20 0x0624 +#define AFE_IRQ_MCU_CNT21 0x0628 +#define AFE_IRQ_MCU_CNT22 0x062c +#define AFE_IRQ_MCU_CNT23 0x0630 +#define AFE_IRQ_MCU_CNT24 0x0634 +#define AFE_IRQ_MCU_CNT25 0x0638 +#define AFE_IRQ_MCU_CNT26 0x063c +#define AFE_IRQ9_MCU_CNT_MON 0x0660 +#define AFE_IRQ10_MCU_CNT_MON 0x0664 +#define AFE_IRQ13_MCU_CNT_MON 0x0668 +#define AFE_IRQ14_MCU_CNT_MON 0x066c +#define AFE_IRQ15_MCU_CNT_MON 0x0670 +#define AFE_IRQ16_MCU_CNT_MON 0x0674 +#define AFE_IRQ17_MCU_CNT_MON 0x0678 +#define AFE_IRQ18_MCU_CNT_MON 0x067c +#define AFE_IRQ19_MCU_CNT_MON 0x0680 +#define AFE_IRQ20_MCU_CNT_MON 0x0684 +#define AFE_IRQ21_MCU_CNT_MON 0x0688 +#define AFE_IRQ22_MCU_CNT_MON 0x068c +#define AFE_IRQ23_MCU_CNT_MON 0x0690 +#define AFE_IRQ24_MCU_CNT_MON 0x0694 +#define AFE_IRQ25_MCU_CNT_MON 0x0698 +#define AFE_IRQ26_MCU_CNT_MON 0x069c +#define AFE_IRQ31_MCU_CNT_MON 0x06a0 +#define AFE_GENERAL_REG0 0x0800 +#define AFE_GENERAL_REG1 0x0804 +#define AFE_GENERAL_REG2 0x0808 +#define AFE_GENERAL_REG3 0x080c +#define AFE_GENERAL_REG4 0x0810 +#define AFE_GENERAL_REG5 0x0814 +#define AFE_GENERAL_REG6 0x0818 +#define AFE_GENERAL_REG7 0x081c +#define AFE_GENERAL_REG8 0x0820 +#define AFE_GENERAL_REG9 0x0824 +#define AFE_GENERAL_REG10 0x0828 +#define AFE_GENERAL_REG11 0x082c +#define AFE_GENERAL_REG12 0x0830 +#define AFE_GENERAL_REG13 0x0834 +#define AFE_GENERAL_REG14 0x0838 +#define AFE_GENERAL_REG15 0x083c +#define AFE_CBIP_CFG0 0x0840 +#define AFE_CBIP_MON0 0x0844 +#define AFE_CBIP_SLV_MUX_MON0 0x0848 +#define AFE_CBIP_SLV_DECODER_MON0 0x084c +#define AFE_ADDA6_MTKAIF_MON0 0x0854 +#define AFE_ADDA6_MTKAIF_MON1 0x0858 +#define AFE_AWB_CON0 0x085c +#define AFE_AWB_BASE_MSB 0x0860 +#define AFE_AWB_BASE 0x0864 +#define AFE_AWB_CUR_MSB 0x0868 +#define AFE_AWB_CUR 0x086c +#define AFE_AWB_END_MSB 0x0870 +#define AFE_AWB_END 0x0874 +#define AFE_AWB2_CON0 0x0878 +#define AFE_AWB2_BASE_MSB 0x087c +#define AFE_AWB2_BASE 0x0880 +#define AFE_AWB2_CUR_MSB 0x0884 +#define AFE_AWB2_CUR 0x0888 +#define AFE_AWB2_END_MSB 0x088c +#define AFE_AWB2_END 0x0890 +#define AFE_DAI_CON0 0x0894 +#define AFE_DAI_BASE_MSB 0x0898 +#define AFE_DAI_BASE 0x089c +#define AFE_DAI_CUR_MSB 0x08a0 +#define AFE_DAI_CUR 0x08a4 +#define AFE_DAI_END_MSB 0x08a8 +#define AFE_DAI_END 0x08ac +#define AFE_DAI2_CON0 0x08b0 +#define AFE_DAI2_BASE_MSB 0x08b4 +#define AFE_DAI2_BASE 0x08b8 +#define AFE_DAI2_CUR_MSB 0x08bc +#define AFE_DAI2_CUR 0x08c0 +#define AFE_DAI2_END_MSB 0x08c4 +#define AFE_DAI2_END 0x08c8 +#define AFE_MEMIF_CON0 0x08cc +#define AFE_CONN0_1 0x0900 +#define AFE_CONN1_1 0x0904 +#define AFE_CONN2_1 0x0908 +#define AFE_CONN3_1 0x090c +#define AFE_CONN4_1 0x0910 +#define AFE_CONN5_1 0x0914 +#define AFE_CONN6_1 0x0918 +#define AFE_CONN7_1 0x091c +#define AFE_CONN8_1 0x0920 +#define AFE_CONN9_1 0x0924 +#define AFE_CONN10_1 0x0928 +#define AFE_CONN11_1 0x092c +#define AFE_CONN12_1 0x0930 +#define AFE_CONN13_1 0x0934 +#define AFE_CONN14_1 0x0938 +#define AFE_CONN15_1 0x093c +#define AFE_CONN16_1 0x0940 +#define AFE_CONN17_1 0x0944 +#define AFE_CONN18_1 0x0948 +#define AFE_CONN19_1 0x094c +#define AFE_CONN20_1 0x0950 +#define AFE_CONN21_1 0x0954 +#define AFE_CONN22_1 0x0958 +#define AFE_CONN23_1 0x095c +#define AFE_CONN24_1 0x0960 +#define AFE_CONN25_1 0x0964 +#define AFE_CONN26_1 0x0968 +#define AFE_CONN27_1 0x096c +#define AFE_CONN28_1 0x0970 +#define AFE_CONN29_1 0x0974 +#define AFE_CONN30_1 0x0978 +#define AFE_CONN31_1 0x097c +#define AFE_CONN32_1 0x0980 +#define AFE_CONN33_1 0x0984 +#define AFE_CONN34_1 0x0988 +#define AFE_CONN_RS_1 0x098c +#define AFE_CONN_DI_1 0x0990 +#define AFE_CONN_24BIT_1 0x0994 +#define AFE_CONN_REG 0x0998 +#define AFE_CONN35 0x09a0 +#define AFE_CONN36 0x09a4 +#define AFE_CONN37 0x09a8 +#define AFE_CONN38 0x09ac +#define AFE_CONN35_1 0x09b0 +#define AFE_CONN36_1 0x09b4 +#define AFE_CONN37_1 0x09b8 +#define AFE_CONN38_1 0x09bc +#define AFE_CONN39 0x09c0 +#define AFE_CONN40 0x09c4 +#define AFE_CONN41 0x09c8 +#define AFE_CONN42 0x09cc +#define AFE_CONN39_1 0x09e0 +#define AFE_CONN40_1 0x09e4 +#define AFE_CONN41_1 0x09e8 +#define AFE_CONN42_1 0x09ec +#define AFE_I2S_CON4 0x09f8 +#define AFE_CONN60 0x0a64 +#define AFE_CONN61 0x0a68 +#define AFE_CONN62 0x0a6c +#define AFE_CONN63 0x0a70 +#define AFE_CONN64 0x0a74 +#define AFE_CONN65 0x0a78 +#define AFE_CONN66 0x0a7c +#define AFE_ADDA6_TOP_CON0 0x0a80 +#define AFE_ADDA6_UL_SRC_CON0 0x0a84 +#define AFE_ADDA6_UL_SRC_CON1 0x0a88 +#define AFE_ADDA6_SRC_DEBUG 0x0a8c +#define AFE_ADDA6_SRC_DEBUG_MON0 0x0a90 +#define AFE_ADDA6_ULCF_CFG_02_01 0x0aa0 +#define AFE_ADDA6_ULCF_CFG_04_03 0x0aa4 +#define AFE_ADDA6_ULCF_CFG_06_05 0x0aa8 +#define AFE_ADDA6_ULCF_CFG_08_07 0x0aac +#define AFE_ADDA6_ULCF_CFG_10_09 0x0ab0 +#define AFE_ADDA6_ULCF_CFG_12_11 0x0ab4 +#define AFE_ADDA6_ULCF_CFG_14_13 0x0ab8 +#define AFE_ADDA6_ULCF_CFG_16_15 0x0abc +#define AFE_ADDA6_ULCF_CFG_18_17 0x0ac0 +#define AFE_ADDA6_ULCF_CFG_20_19 0x0ac4 +#define AFE_ADDA6_ULCF_CFG_22_21 0x0ac8 +#define AFE_ADDA6_ULCF_CFG_24_23 0x0acc +#define AFE_ADDA6_ULCF_CFG_26_25 0x0ad0 +#define AFE_ADDA6_ULCF_CFG_28_27 0x0ad4 +#define AFE_ADDA6_ULCF_CFG_30_29 0x0ad8 +#define AFE_ADD6A_UL_SRC_MON0 0x0ae4 +#define AFE_ADDA6_UL_SRC_MON1 0x0ae8 +#define AFE_CONN43 0x0af8 +#define AFE_CONN43_1 0x0afc +#define AFE_MOD_DAI_CON0 0x0b00 +#define AFE_MOD_DAI_BASE_MSB 0x0b04 +#define AFE_MOD_DAI_BASE 0x0b08 +#define AFE_MOD_DAI_CUR_MSB 0x0b0c +#define AFE_MOD_DAI_CUR 0x0b10 +#define AFE_MOD_DAI_END_MSB 0x0b14 +#define AFE_MOD_DAI_END 0x0b18 +#define AFE_AWB_RCH_MON 0x0b70 +#define AFE_AWB_LCH_MON 0x0b74 +#define AFE_VUL_RCH_MON 0x0b78 +#define AFE_VUL_LCH_MON 0x0b7c +#define AFE_VUL12_RCH_MON 0x0b80 +#define AFE_VUL12_LCH_MON 0x0b84 +#define AFE_VUL2_RCH_MON 0x0b88 +#define AFE_VUL2_LCH_MON 0x0b8c +#define AFE_DAI_DATA_MON 0x0b90 +#define AFE_MOD_DAI_DATA_MON 0x0b94 +#define AFE_DAI2_DATA_MON 0x0b98 +#define AFE_AWB2_RCH_MON 0x0b9c +#define AFE_AWB2_LCH_MON 0x0ba0 +#define AFE_VUL3_RCH_MON 0x0ba4 +#define AFE_VUL3_LCH_MON 0x0ba8 +#define AFE_VUL4_RCH_MON 0x0bac +#define AFE_VUL4_LCH_MON 0x0bb0 +#define AFE_VUL5_RCH_MON 0x0bb4 +#define AFE_VUL5_LCH_MON 0x0bb8 +#define AFE_VUL6_RCH_MON 0x0bbc +#define AFE_VUL6_LCH_MON 0x0bc0 +#define AFE_DL1_RCH_MON 0x0bc4 +#define AFE_DL1_LCH_MON 0x0bc8 +#define AFE_DL2_RCH_MON 0x0bcc +#define AFE_DL2_LCH_MON 0x0bd0 +#define AFE_DL12_RCH1_MON 0x0bd4 +#define AFE_DL12_LCH1_MON 0x0bd8 +#define AFE_DL12_RCH2_MON 0x0bdc +#define AFE_DL12_LCH2_MON 0x0be0 +#define AFE_DL3_RCH_MON 0x0be4 +#define AFE_DL3_LCH_MON 0x0be8 +#define AFE_DL4_RCH_MON 0x0bec +#define AFE_DL4_LCH_MON 0x0bf0 +#define AFE_DL5_RCH_MON 0x0bf4 +#define AFE_DL5_LCH_MON 0x0bf8 +#define AFE_DL6_RCH_MON 0x0bfc +#define AFE_DL6_LCH_MON 0x0c00 +#define AFE_DL7_RCH_MON 0x0c04 +#define AFE_DL7_LCH_MON 0x0c08 +#define AFE_DL8_RCH_MON 0x0c0c +#define AFE_DL8_LCH_MON 0x0c10 +#define AFE_VUL5_CON0 0x0c14 +#define AFE_VUL5_BASE_MSB 0x0c18 +#define AFE_VUL5_BASE 0x0c1c +#define AFE_VUL5_CUR_MSB 0x0c20 +#define AFE_VUL5_CUR 0x0c24 +#define AFE_VUL5_END_MSB 0x0c28 +#define AFE_VUL5_END 0x0c2c +#define AFE_VUL6_CON0 0x0c30 +#define AFE_VUL6_BASE_MSB 0x0c34 +#define AFE_VUL6_BASE 0x0c38 +#define AFE_VUL6_CUR_MSB 0x0c3c +#define AFE_VUL6_CUR 0x0c40 +#define AFE_VUL6_END_MSB 0x0c44 +#define AFE_VUL6_END 0x0c48 +#define AFE_ADDA_DL_SDM_DCCOMP_CON 0x0c50 +#define AFE_ADDA_DL_SDM_TEST 0x0c54 +#define AFE_ADDA_DL_DC_COMP_CFG0 0x0c58 +#define AFE_ADDA_DL_DC_COMP_CFG1 0x0c5c +#define AFE_ADDA_DL_SDM_FIFO_MON 0x0c60 +#define AFE_ADDA_DL_SRC_LCH_MON 0x0c64 +#define AFE_ADDA_DL_SRC_RCH_MON 0x0c68 +#define AFE_ADDA_DL_SDM_OUT_MON 0x0c6c +#define AFE_ADDA_DL_SDM_DITHER_CON 0x0c70 +#define AFE_ADDA_DL_SDM_AUTO_RESET_CON 0x0c74 +#define AFE_CONNSYS_I2S_CON 0x0c78 +#define AFE_CONNSYS_I2S_MON 0x0c7c +#define AFE_ASRC_2CH_CON0 0x0c80 +#define AFE_ASRC_2CH_CON1 0x0c84 +#define AFE_ASRC_2CH_CON2 0x0c88 +#define AFE_ASRC_2CH_CON3 0x0c8c +#define AFE_ASRC_2CH_CON4 0x0c90 +#define AFE_ASRC_2CH_CON5 0x0c94 +#define AFE_ASRC_2CH_CON6 0x0c98 +#define AFE_ASRC_2CH_CON7 0x0c9c +#define AFE_ASRC_2CH_CON8 0x0ca0 +#define AFE_ASRC_2CH_CON9 0x0ca4 +#define AFE_ASRC_2CH_CON10 0x0ca8 +#define AFE_ASRC_2CH_CON12 0x0cb0 +#define AFE_ASRC_2CH_CON13 0x0cb4 +#define AFE_ADDA6_IIR_COEF_02_01 0x0ce0 +#define AFE_ADDA6_IIR_COEF_04_03 0x0ce4 +#define AFE_ADDA6_IIR_COEF_06_05 0x0ce8 +#define AFE_ADDA6_IIR_COEF_08_07 0x0cec +#define AFE_ADDA6_IIR_COEF_10_09 0x0cf0 +#define AFE_CONN67 0x0cf4 +#define AFE_CONN68 0x0cf8 +#define AFE_CONN69 0x0cfc +#define AFE_SE_PROT_SIDEBAND 0x0d38 +#define AFE_SE_DOMAIN_SIDEBAND0 0x0d3c +#define AFE_ADDA_PREDIS_CON2 0x0d40 +#define AFE_ADDA_PREDIS_CON3 0x0d44 +#define AFE_SE_DOMAIN_SIDEBAND1 0x0d54 +#define AFE_SE_DOMAIN_SIDEBAND2 0x0d58 +#define AFE_SE_DOMAIN_SIDEBAND3 0x0d5c +#define AFE_CONN44 0x0d70 +#define AFE_CONN45 0x0d74 +#define AFE_CONN46 0x0d78 +#define AFE_CONN47 0x0d7c +#define AFE_CONN44_1 0x0d80 +#define AFE_CONN45_1 0x0d84 +#define AFE_CONN46_1 0x0d88 +#define AFE_CONN47_1 0x0d8c +#define AFE_HD_ENGEN_ENABLE 0x0dd0 +#define AFE_ADDA_DL_NLE_FIFO_MON 0x0dfc +#define AFE_ADDA_MTKAIF_CFG0 0x0e00 +#define AFE_CONN67_1 0x0e04 +#define AFE_CONN68_1 0x0e08 +#define AFE_CONN69_1 0x0e0c +#define AFE_ADDA_MTKAIF_SYNCWORD_CFG 0x0e14 +#define AFE_ADDA_MTKAIF_RX_CFG0 0x0e20 +#define AFE_ADDA_MTKAIF_RX_CFG1 0x0e24 +#define AFE_ADDA_MTKAIF_RX_CFG2 0x0e28 +#define AFE_ADDA_MTKAIF_MON0 0x0e34 +#define AFE_ADDA_MTKAIF_MON1 0x0e38 +#define AFE_AUD_PAD_TOP 0x0e40 +#define AFE_DL_NLE_R_CFG0 0x0e44 +#define AFE_DL_NLE_R_CFG1 0x0e48 +#define AFE_DL_NLE_L_CFG0 0x0e4c +#define AFE_DL_NLE_L_CFG1 0x0e50 +#define AFE_DL_NLE_R_MON0 0x0e54 +#define AFE_DL_NLE_R_MON1 0x0e58 +#define AFE_DL_NLE_R_MON2 0x0e5c +#define AFE_DL_NLE_L_MON0 0x0e60 +#define AFE_DL_NLE_L_MON1 0x0e64 +#define AFE_DL_NLE_L_MON2 0x0e68 +#define AFE_DL_NLE_GAIN_CFG0 0x0e6c +#define AFE_ADDA6_MTKAIF_CFG0 0x0e70 +#define AFE_ADDA6_MTKAIF_RX_CFG0 0x0e74 +#define AFE_ADDA6_MTKAIF_RX_CFG1 0x0e78 +#define AFE_ADDA6_MTKAIF_RX_CFG2 0x0e7c +#define AFE_GENERAL1_ASRC_2CH_CON0 0x0e80 +#define AFE_GENERAL1_ASRC_2CH_CON1 0x0e84 +#define AFE_GENERAL1_ASRC_2CH_CON2 0x0e88 +#define AFE_GENERAL1_ASRC_2CH_CON3 0x0e8c +#define AFE_GENERAL1_ASRC_2CH_CON4 0x0e90 +#define AFE_GENERAL1_ASRC_2CH_CON5 0x0e94 +#define AFE_GENERAL1_ASRC_2CH_CON6 0x0e98 +#define AFE_GENERAL1_ASRC_2CH_CON7 0x0e9c +#define AFE_GENERAL1_ASRC_2CH_CON8 0x0ea0 +#define AFE_GENERAL1_ASRC_2CH_CON9 0x0ea4 +#define AFE_GENERAL1_ASRC_2CH_CON10 0x0ea8 +#define AFE_GENERAL1_ASRC_2CH_CON12 0x0eb0 +#define AFE_GENERAL1_ASRC_2CH_CON13 0x0eb4 +#define GENERAL_ASRC_MODE 0x0eb8 +#define GENERAL_ASRC_EN_ON 0x0ebc +#define AFE_CONN48 0x0ec0 +#define AFE_CONN49 0x0ec4 +#define AFE_CONN50 0x0ec8 +#define AFE_CONN51 0x0ecc +#define AFE_CONN52 0x0ed0 +#define AFE_CONN53 0x0ed4 +#define AFE_CONN54 0x0ed8 +#define AFE_CONN55 0x0edc +#define AFE_CONN48_1 0x0ee0 +#define AFE_CONN49_1 0x0ee4 +#define AFE_CONN50_1 0x0ee8 +#define AFE_CONN51_1 0x0eec +#define AFE_CONN52_1 0x0ef0 +#define AFE_CONN53_1 0x0ef4 +#define AFE_CONN54_1 0x0ef8 +#define AFE_CONN55_1 0x0efc +#define AFE_GENERAL2_ASRC_2CH_CON0 0x0f00 +#define AFE_GENERAL2_ASRC_2CH_CON1 0x0f04 +#define AFE_GENERAL2_ASRC_2CH_CON2 0x0f08 +#define AFE_GENERAL2_ASRC_2CH_CON3 0x0f0c +#define AFE_GENERAL2_ASRC_2CH_CON4 0x0f10 +#define AFE_GENERAL2_ASRC_2CH_CON5 0x0f14 +#define AFE_GENERAL2_ASRC_2CH_CON6 0x0f18 +#define AFE_GENERAL2_ASRC_2CH_CON7 0x0f1c +#define AFE_GENERAL2_ASRC_2CH_CON8 0x0f20 +#define AFE_GENERAL2_ASRC_2CH_CON9 0x0f24 +#define AFE_GENERAL2_ASRC_2CH_CON10 0x0f28 +#define AFE_GENERAL2_ASRC_2CH_CON12 0x0f30 +#define AFE_GENERAL2_ASRC_2CH_CON13 0x0f34 +#define AFE_DL5_CON0 0x0f4c +#define AFE_DL5_BASE_MSB 0x0f50 +#define AFE_DL5_BASE 0x0f54 +#define AFE_DL5_CUR_MSB 0x0f58 +#define AFE_DL5_CUR 0x0f5c +#define AFE_DL5_END_MSB 0x0f60 +#define AFE_DL5_END 0x0f64 +#define AFE_DL6_CON0 0x0f68 +#define AFE_DL6_BASE_MSB 0x0f6c +#define AFE_DL6_BASE 0x0f70 +#define AFE_DL6_CUR_MSB 0x0f74 +#define AFE_DL6_CUR 0x0f78 +#define AFE_DL6_END_MSB 0x0f7c +#define AFE_DL6_END 0x0f80 +#define AFE_DL7_CON0 0x0f84 +#define AFE_DL7_BASE_MSB 0x0f88 +#define AFE_DL7_BASE 0x0f8c +#define AFE_DL7_CUR_MSB 0x0f90 +#define AFE_DL7_CUR 0x0f94 +#define AFE_DL7_END_MSB 0x0f98 +#define AFE_DL7_END 0x0f9c +#define AFE_DL8_CON0 0x0fa0 +#define AFE_DL8_BASE_MSB 0x0fa4 +#define AFE_DL8_BASE 0x0fa8 +#define AFE_DL8_CUR_MSB 0x0fac +#define AFE_DL8_CUR 0x0fb0 +#define AFE_DL8_END_MSB 0x0fb4 +#define AFE_DL8_END 0x0fb8 +#define AFE_SE_SECURE_CON 0x1004 +#define AFE_PROT_SIDEBAND_MON 0x1008 +#define AFE_DOMAIN_SIDEBAND0_MON 0x100c +#define AFE_DOMAIN_SIDEBAND1_MON 0x1010 +#define AFE_DOMAIN_SIDEBAND2_MON 0x1014 +#define AFE_DOMAIN_SIDEBAND3_MON 0x1018 +#define AFE_SECURE_MASK_CONN0 0x1020 +#define AFE_SECURE_MASK_CONN1 0x1024 +#define AFE_SECURE_MASK_CONN2 0x1028 +#define AFE_SECURE_MASK_CONN3 0x102c +#define AFE_SECURE_MASK_CONN4 0x1030 +#define AFE_SECURE_MASK_CONN5 0x1034 +#define AFE_SECURE_MASK_CONN6 0x1038 +#define AFE_SECURE_MASK_CONN7 0x103c +#define AFE_SECURE_MASK_CONN8 0x1040 +#define AFE_SECURE_MASK_CONN9 0x1044 +#define AFE_SECURE_MASK_CONN10 0x1048 +#define AFE_SECURE_MASK_CONN11 0x104c +#define AFE_SECURE_MASK_CONN12 0x1050 +#define AFE_SECURE_MASK_CONN13 0x1054 +#define AFE_SECURE_MASK_CONN14 0x1058 +#define AFE_SECURE_MASK_CONN15 0x105c +#define AFE_SECURE_MASK_CONN16 0x1060 +#define AFE_SECURE_MASK_CONN17 0x1064 +#define AFE_SECURE_MASK_CONN18 0x1068 +#define AFE_SECURE_MASK_CONN19 0x106c +#define AFE_SECURE_MASK_CONN20 0x1070 +#define AFE_SECURE_MASK_CONN21 0x1074 +#define AFE_SECURE_MASK_CONN22 0x1078 +#define AFE_SECURE_MASK_CONN23 0x107c +#define AFE_SECURE_MASK_CONN24 0x1080 +#define AFE_SECURE_MASK_CONN25 0x1084 +#define AFE_SECURE_MASK_CONN26 0x1088 +#define AFE_SECURE_MASK_CONN27 0x108c +#define AFE_SECURE_MASK_CONN28 0x1090 +#define AFE_SECURE_MASK_CONN29 0x1094 +#define AFE_SECURE_MASK_CONN30 0x1098 +#define AFE_SECURE_MASK_CONN31 0x109c +#define AFE_SECURE_MASK_CONN32 0x10a0 +#define AFE_SECURE_MASK_CONN33 0x10a4 +#define AFE_SECURE_MASK_CONN34 0x10a8 +#define AFE_SECURE_MASK_CONN35 0x10ac +#define AFE_SECURE_MASK_CONN36 0x10b0 +#define AFE_SECURE_MASK_CONN37 0x10b4 +#define AFE_SECURE_MASK_CONN38 0x10b8 +#define AFE_SECURE_MASK_CONN39 0x10bc +#define AFE_SECURE_MASK_CONN40 0x10c0 +#define AFE_SECURE_MASK_CONN41 0x10c4 +#define AFE_SECURE_MASK_CONN42 0x10c8 +#define AFE_SECURE_MASK_CONN43 0x10cc +#define AFE_SECURE_MASK_CONN44 0x10d0 +#define AFE_SECURE_MASK_CONN45 0x10d4 +#define AFE_SECURE_MASK_CONN46 0x10d8 +#define AFE_SECURE_MASK_CONN47 0x10dc +#define AFE_SECURE_MASK_CONN48 0x10e0 +#define AFE_SECURE_MASK_CONN49 0x10e4 +#define AFE_SECURE_MASK_CONN50 0x10e8 +#define AFE_SECURE_MASK_CONN51 0x10ec +#define AFE_SECURE_MASK_CONN52 0x10f0 +#define AFE_SECURE_MASK_CONN53 0x10f4 +#define AFE_SECURE_MASK_CONN54 0x10f8 +#define AFE_SECURE_MASK_CONN55 0x10fc +#define AFE_SECURE_MASK_CONN56 0x1100 +#define AFE_SECURE_MASK_CONN57 0x1104 +#define AFE_SECURE_MASK_CONN0_1 0x1108 +#define AFE_SECURE_MASK_CONN1_1 0x110c +#define AFE_SECURE_MASK_CONN2_1 0x1110 +#define AFE_SECURE_MASK_CONN3_1 0x1114 +#define AFE_SECURE_MASK_CONN4_1 0x1118 +#define AFE_SECURE_MASK_CONN5_1 0x111c +#define AFE_SECURE_MASK_CONN6_1 0x1120 +#define AFE_SECURE_MASK_CONN7_1 0x1124 +#define AFE_SECURE_MASK_CONN8_1 0x1128 +#define AFE_SECURE_MASK_CONN9_1 0x112c +#define AFE_SECURE_MASK_CONN10_1 0x1130 +#define AFE_SECURE_MASK_CONN11_1 0x1134 +#define AFE_SECURE_MASK_CONN12_1 0x1138 +#define AFE_SECURE_MASK_CONN13_1 0x113c +#define AFE_SECURE_MASK_CONN14_1 0x1140 +#define AFE_SECURE_MASK_CONN15_1 0x1144 +#define AFE_SECURE_MASK_CONN16_1 0x1148 +#define AFE_SECURE_MASK_CONN17_1 0x114c +#define AFE_SECURE_MASK_CONN18_1 0x1150 +#define AFE_SECURE_MASK_CONN19_1 0x1154 +#define AFE_SECURE_MASK_CONN20_1 0x1158 +#define AFE_SECURE_MASK_CONN21_1 0x115c +#define AFE_SECURE_MASK_CONN22_1 0x1160 +#define AFE_SECURE_MASK_CONN23_1 0x1164 +#define AFE_SECURE_MASK_CONN24_1 0x1168 +#define AFE_SECURE_MASK_CONN25_1 0x116c +#define AFE_SECURE_MASK_CONN26_1 0x1170 +#define AFE_SECURE_MASK_CONN27_1 0x1174 +#define AFE_SECURE_MASK_CONN28_1 0x1178 +#define AFE_SECURE_MASK_CONN29_1 0x117c +#define AFE_SECURE_MASK_CONN30_1 0x1180 +#define AFE_SECURE_MASK_CONN31_1 0x1184 +#define AFE_SECURE_MASK_CONN32_1 0x1188 +#define AFE_SECURE_MASK_CONN33_1 0x118c +#define AFE_SECURE_MASK_CONN34_1 0x1190 +#define AFE_SECURE_MASK_CONN35_1 0x1194 +#define AFE_SECURE_MASK_CONN36_1 0x1198 +#define AFE_SECURE_MASK_CONN37_1 0x119c +#define AFE_SECURE_MASK_CONN38_1 0x11a0 +#define AFE_SECURE_MASK_CONN39_1 0x11a4 +#define AFE_SECURE_MASK_CONN40_1 0x11a8 +#define AFE_SECURE_MASK_CONN41_1 0x11ac +#define AFE_SECURE_MASK_CONN42_1 0x11b0 +#define AFE_SECURE_MASK_CONN43_1 0x11b4 +#define AFE_SECURE_MASK_CONN44_1 0x11b8 +#define AFE_SECURE_MASK_CONN45_1 0x11bc +#define AFE_SECURE_MASK_CONN46_1 0x11c0 +#define AFE_SECURE_MASK_CONN47_1 0x11c4 +#define AFE_SECURE_MASK_CONN48_1 0x11c8 +#define AFE_SECURE_MASK_CONN49_1 0x11cc +#define AFE_SECURE_MASK_CONN50_1 0x11d0 +#define AFE_SECURE_MASK_CONN51_1 0x11d4 +#define AFE_SECURE_MASK_CONN52_1 0x11d8 +#define AFE_SECURE_MASK_CONN53_1 0x11dc +#define AFE_SECURE_MASK_CONN54_1 0x11e0 +#define AFE_SECURE_MASK_CONN55_1 0x11e4 +#define AFE_SECURE_MASK_CONN56_1 0x11e8 +#define AFE_CONN60_1 0x11f0 +#define AFE_CONN61_1 0x11f4 +#define AFE_CONN62_1 0x11f8 +#define AFE_CONN63_1 0x11fc +#define AFE_CONN64_1 0x1220 +#define AFE_CONN65_1 0x1224 +#define AFE_CONN66_1 0x1228 +#define FPGA_CFG4 0x1230 +#define FPGA_CFG5 0x1234 +#define FPGA_CFG6 0x1238 +#define FPGA_CFG7 0x123c +#define FPGA_CFG8 0x1240 +#define FPGA_CFG9 0x1244 +#define FPGA_CFG10 0x1248 +#define FPGA_CFG11 0x124c +#define FPGA_CFG12 0x1250 +#define FPGA_CFG13 0x1254 +#define ETDM_IN1_CON0 0x1430 +#define ETDM_IN1_CON1 0x1434 +#define ETDM_IN1_CON2 0x1438 +#define ETDM_IN1_CON3 0x143c +#define ETDM_IN1_CON4 0x1440 +#define ETDM_IN1_CON5 0x1444 +#define ETDM_IN1_CON6 0x1448 +#define ETDM_IN1_CON7 0x144c +#define ETDM_IN1_CON8 0x1450 +#define ETDM_OUT1_CON0 0x1454 +#define ETDM_OUT1_CON1 0x1458 +#define ETDM_OUT1_CON2 0x145c +#define ETDM_OUT1_CON3 0x1460 +#define ETDM_OUT1_CON4 0x1464 +#define ETDM_OUT1_CON5 0x1468 +#define ETDM_OUT1_CON6 0x146c +#define ETDM_OUT1_CON7 0x1470 +#define ETDM_OUT1_CON8 0x1474 +#define ETDM_IN1_MON 0x1478 +#define ETDM_OUT1_MON 0x147c +#define ETDM_0_3_COWORK_CON0 0x18b0 +#define ETDM_0_3_COWORK_CON1 0x18b4 +#define ETDM_0_3_COWORK_CON3 0x18bc + +#define AFE_MAX_REGISTER ETDM_0_3_COWORK_CON3 + +#define AFE_IRQ_STATUS_BITS 0x87FFFFFF +#define AFE_IRQ_CNT_SHIFT 0 +#define AFE_IRQ_CNT_MASK 0x3ffff +#endif -- cgit From c271cc9febaaa1bcbc0842d1ee30466aa6148ea8 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 5 Jun 2022 13:40:06 +0200 Subject: netfilter: nf_tables: release new hooks on unsupported flowtable flags Release the list of new hooks that are pending to be registered in case that unsupported flowtable flags are provided. Fixes: 78d9f48f7f44 ("netfilter: nf_tables: add devices to existing flowtable") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 2faa77cd2fe2..252796a99f5e 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -7433,11 +7433,15 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh, if (nla[NFTA_FLOWTABLE_FLAGS]) { flags = ntohl(nla_get_be32(nla[NFTA_FLOWTABLE_FLAGS])); - if (flags & ~NFT_FLOWTABLE_MASK) - return -EOPNOTSUPP; + if (flags & ~NFT_FLOWTABLE_MASK) { + err = -EOPNOTSUPP; + goto err_flowtable_update_hook; + } if ((flowtable->data.flags & NFT_FLOWTABLE_HW_OFFLOAD) ^ - (flags & NFT_FLOWTABLE_HW_OFFLOAD)) - return -EOPNOTSUPP; + (flags & NFT_FLOWTABLE_HW_OFFLOAD)) { + err = -EOPNOTSUPP; + goto err_flowtable_update_hook; + } } else { flags = flowtable->data.flags; } -- cgit From 9dd732e0bdf538b1b76dc7c157e2b5e560ff30d3 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 6 Jun 2022 17:15:57 +0200 Subject: netfilter: nf_tables: memleak flow rule from commit path Abort path release flow rule object, however, commit path does not. Update code to destroy these objects before releasing the transaction. Fixes: c9626a2cbdb2 ("netfilter: nf_tables: add hardware offload support") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 252796a99f5e..1a6a21bfb18d 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -8329,6 +8329,9 @@ static void nft_commit_release(struct nft_trans *trans) nf_tables_chain_destroy(&trans->ctx); break; case NFT_MSG_DELRULE: + if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD) + nft_flow_rule_destroy(nft_trans_flow_rule(trans)); + nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans)); break; case NFT_MSG_DELSET: @@ -8817,6 +8820,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) nf_tables_rule_notify(&trans->ctx, nft_trans_rule(trans), NFT_MSG_NEWRULE); + if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD) + nft_flow_rule_destroy(nft_trans_flow_rule(trans)); + nft_trans_destroy(trans); break; case NFT_MSG_DELRULE: -- cgit From c76acfb7e19dcc3a0964e0563770b1d11b8d4540 Mon Sep 17 00:00:00 2001 From: Tan Tee Min Date: Thu, 26 May 2022 17:03:47 +0800 Subject: net: phy: dp83867: retrigger SGMII AN when link change There is a limitation in TI DP83867 PHY device where SGMII AN is only triggered once after the device is booted up. Even after the PHY TPI is down and up again, SGMII AN is not triggered and hence no new in-band message from PHY to MAC side SGMII. This could cause an issue during power up, when PHY is up prior to MAC. At this condition, once MAC side SGMII is up, MAC side SGMII wouldn`t receive new in-band message from TI PHY with correct link status, speed and duplex info. As suggested by TI, implemented a SW solution here to retrigger SGMII Auto-Neg whenever there is a link change. v2: Add Fixes tag in commit message. Fixes: 2a10154abcb7 ("net: phy: dp83867: Add TI dp83867 phy") Cc: # 5.4.x Signed-off-by: Sit, Michael Wei Hong Reviewed-by: Voon Weifeng Signed-off-by: Tan Tee Min Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20220526090347.128742-1-tee.min.tan@linux.intel.com Signed-off-by: Jakub Kicinski --- drivers/net/phy/dp83867.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index 8561f2d4443b..13dafe7a29bd 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -137,6 +137,7 @@ #define DP83867_DOWNSHIFT_2_COUNT 2 #define DP83867_DOWNSHIFT_4_COUNT 4 #define DP83867_DOWNSHIFT_8_COUNT 8 +#define DP83867_SGMII_AUTONEG_EN BIT(7) /* CFG3 bits */ #define DP83867_CFG3_INT_OE BIT(7) @@ -855,6 +856,32 @@ static int dp83867_phy_reset(struct phy_device *phydev) DP83867_PHYCR_FORCE_LINK_GOOD, 0); } +static void dp83867_link_change_notify(struct phy_device *phydev) +{ + /* There is a limitation in DP83867 PHY device where SGMII AN is + * only triggered once after the device is booted up. Even after the + * PHY TPI is down and up again, SGMII AN is not triggered and + * hence no new in-band message from PHY to MAC side SGMII. + * This could cause an issue during power up, when PHY is up prior + * to MAC. At this condition, once MAC side SGMII is up, MAC side + * SGMII wouldn`t receive new in-band message from TI PHY with + * correct link status, speed and duplex info. + * Thus, implemented a SW solution here to retrigger SGMII Auto-Neg + * whenever there is a link change. + */ + if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { + int val = 0; + + val = phy_clear_bits(phydev, DP83867_CFG2, + DP83867_SGMII_AUTONEG_EN); + if (val < 0) + return; + + phy_set_bits(phydev, DP83867_CFG2, + DP83867_SGMII_AUTONEG_EN); + } +} + static struct phy_driver dp83867_driver[] = { { .phy_id = DP83867_PHY_ID, @@ -879,6 +906,8 @@ static struct phy_driver dp83867_driver[] = { .suspend = genphy_suspend, .resume = genphy_resume, + + .link_change_notify = dp83867_link_change_notify, }, }; module_phy_driver(dp83867_driver); -- cgit From e0b5c5984d4810733b7c24a3d16c904fffc086d2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Jun 2022 16:25:23 +0100 Subject: dt-bindings: mfd: bd9571mwv: update rohm,bd9571mwv.yaml reference Changeset 983b62975e90 ("dt-bindings: mfd: bd9571mwv: Convert to json-schema") renamed: Documentation/devicetree/bindings/mfd/bd9571mwv.txt to: Documentation/devicetree/bindings/mfd/rohm,bd9571mwv.yaml. Update its cross-reference accordingly. Fixes: 983b62975e90 ("dt-bindings: mfd: bd9571mwv: Convert to json-schema") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/1906a4d935eab57c10ce09358eae02175ce4abb7.1654529011.git.mchehab@kernel.org --- Documentation/ABI/testing/sysfs-driver-bd9571mwv-regulator | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-driver-bd9571mwv-regulator b/Documentation/ABI/testing/sysfs-driver-bd9571mwv-regulator index 42214b4ff14a..90596d8bb51c 100644 --- a/Documentation/ABI/testing/sysfs-driver-bd9571mwv-regulator +++ b/Documentation/ABI/testing/sysfs-driver-bd9571mwv-regulator @@ -26,6 +26,6 @@ Description: Read/write the current state of DDR Backup Mode, which controls DDR Backup Mode must be explicitly enabled by the user, to invoke step 1. - See also Documentation/devicetree/bindings/mfd/bd9571mwv.txt. + See also Documentation/devicetree/bindings/mfd/rohm,bd9571mwv.yaml. Users: User space applications for embedded boards equipped with a BD9571MWV PMIC. -- cgit From 7e40381d8a33e41e347cea5bdd000091653000c6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Jun 2022 16:25:24 +0100 Subject: dt-bindings: interrupt-controller: update brcm,l2-intc.yaml reference Changeset 539d25b21fe8 ("dt-bindings: interrupt-controller: Convert Broadcom STB L2 to YAML") renamed: Documentation/devicetree/bindings/interrupt-controller/brcm,l2-intc.txt to: Documentation/devicetree/bindings/interrupt-controller/brcm,l2-intc.yaml. Update its cross-reference accordingly. Fixes: 539d25b21fe8 ("dt-bindings: interrupt-controller: Convert Broadcom STB L2 to YAML") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/a40c02a7aaea91ea7b6ce24b6bc574ae5bcf4cf6.1654529011.git.mchehab@kernel.org --- Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt b/Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt index 73470ecd1f12..ce91a9197697 100644 --- a/Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt +++ b/Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt @@ -16,7 +16,7 @@ has been processed. See [2] for more information on the brcm,l2-intc node. firmware. On some SoCs, this firmware supports DFS and DVFS in addition to Adaptive Voltage Scaling. -[2] Documentation/devicetree/bindings/interrupt-controller/brcm,l2-intc.txt +[2] Documentation/devicetree/bindings/interrupt-controller/brcm,l2-intc.yaml Node brcm,avs-cpu-data-mem -- cgit From 71a834b7f744fab6ae83dc1bfc22030b5baa5dd5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Jun 2022 16:25:25 +0100 Subject: dt-bindings: arm: update vexpress-config.yaml references Changeset 7e8339b5162f ("dt-bindings: arm: convert vexpress-config to DT schema") renamed: Documentation/devicetree/bindings/arm/vexpress-sysreg.txt to: Documentation/devicetree/bindings/arm/vexpress-config.yaml. Update the cross-references accordingly. Fixes: 7e8339b5162f ("dt-bindings: arm: convert vexpress-config to DT schema") Signed-off-by: Mauro Carvalho Chehab Acked-by: Guenter Roeck Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/7020edd9e183652249fc95bf61a1055cc342a4dc.1654529011.git.mchehab@kernel.org --- Documentation/devicetree/bindings/hwmon/vexpress.txt | 2 +- Documentation/devicetree/bindings/regulator/vexpress.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/hwmon/vexpress.txt b/Documentation/devicetree/bindings/hwmon/vexpress.txt index 9c27ed694bbb..4a4df4ffc460 100644 --- a/Documentation/devicetree/bindings/hwmon/vexpress.txt +++ b/Documentation/devicetree/bindings/hwmon/vexpress.txt @@ -9,7 +9,7 @@ Requires node properties: "arm,vexpress-power" "arm,vexpress-energy" - "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg - (see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt + (see Documentation/devicetree/bindings/arm/vexpress-config.yaml for more details) Optional node properties: diff --git a/Documentation/devicetree/bindings/regulator/vexpress.txt b/Documentation/devicetree/bindings/regulator/vexpress.txt index d775f72487aa..1c2e92c7831e 100644 --- a/Documentation/devicetree/bindings/regulator/vexpress.txt +++ b/Documentation/devicetree/bindings/regulator/vexpress.txt @@ -4,7 +4,7 @@ Versatile Express voltage regulators Requires node properties: - "compatible" value: "arm,vexpress-volt" - "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg - (see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt + (see Documentation/devicetree/bindings/arm/vexpress-config.yaml for more details) Required regulator properties: -- cgit From 47a22a251543f4710b954f4b36f3e6063017a82b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Jun 2022 16:25:26 +0100 Subject: dt-bindings: reset: update st,stih407-powerdown.yaml references Changeset 2ca065dc9468 ("dt-bindings: reset: st,sti-powerdown: Convert to yaml") renamed: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt to: Documentation/devicetree/bindings/reset/st,stih407-powerdown.yaml. Update the cross-references accordingly. Fixes: 2ca065dc9468 ("dt-bindings: reset: st,sti-powerdown: Convert to yaml") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/debdd5a9a1bfa0cf1c7e9c45da32edbc2ac2d10a.1654529011.git.mchehab@kernel.org --- Documentation/devicetree/bindings/phy/phy-stih407-usb.txt | 2 +- Documentation/devicetree/bindings/usb/dwc3-st.txt | 2 +- Documentation/devicetree/bindings/usb/ehci-st.txt | 2 +- Documentation/devicetree/bindings/usb/ohci-st.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt b/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt index de6a706abcdb..35f03df00130 100644 --- a/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt +++ b/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt @@ -9,7 +9,7 @@ Required properties: - resets : list of phandle and reset specifier pairs. There should be two entries, one for the whole phy and one for the port - reset-names : list of reset signal names. Should be "global" and "port" -See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt +See: Documentation/devicetree/bindings/reset/st,stih407-powerdown.yaml See: Documentation/devicetree/bindings/reset/reset.txt Example: diff --git a/Documentation/devicetree/bindings/usb/dwc3-st.txt b/Documentation/devicetree/bindings/usb/dwc3-st.txt index bf73de0d5b4a..4aa368447b1e 100644 --- a/Documentation/devicetree/bindings/usb/dwc3-st.txt +++ b/Documentation/devicetree/bindings/usb/dwc3-st.txt @@ -13,7 +13,7 @@ Required properties: - resets : list of phandle and reset specifier pairs. There should be two entries, one for the powerdown and softreset lines of the usb3 IP - reset-names : list of reset signal names. Names should be "powerdown" and "softreset" -See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt +See: Documentation/devicetree/bindings/reset/st,stih407-powerdown.yaml See: Documentation/devicetree/bindings/reset/reset.txt - #address-cells, #size-cells : should be '1' if the device has sub-nodes diff --git a/Documentation/devicetree/bindings/usb/ehci-st.txt b/Documentation/devicetree/bindings/usb/ehci-st.txt index 065c91d955ad..d6f2bdee20fc 100644 --- a/Documentation/devicetree/bindings/usb/ehci-st.txt +++ b/Documentation/devicetree/bindings/usb/ehci-st.txt @@ -17,7 +17,7 @@ See: Documentation/devicetree/bindings/clock/clock-bindings.txt - resets : phandle + reset specifier pairs to the powerdown and softreset lines of the USB IP - reset-names : should be "power" and "softreset" -See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt +See: Documentation/devicetree/bindings/reset/st,stih407-powerdown.yaml See: Documentation/devicetree/bindings/reset/reset.txt Example: diff --git a/Documentation/devicetree/bindings/usb/ohci-st.txt b/Documentation/devicetree/bindings/usb/ohci-st.txt index 44c998c16f85..1c735573abc0 100644 --- a/Documentation/devicetree/bindings/usb/ohci-st.txt +++ b/Documentation/devicetree/bindings/usb/ohci-st.txt @@ -15,7 +15,7 @@ See: Documentation/devicetree/bindings/clock/clock-bindings.txt - resets : phandle to the powerdown and reset controller for the USB IP - reset-names : should be "power" and "softreset". -See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt +See: Documentation/devicetree/bindings/reset/st,stih407-powerdown.yaml See: Documentation/devicetree/bindings/reset/reset.txt Example: -- cgit From 69c2533eb9dfc650baa5f0f624ee4e7cc57afd7a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Jun 2022 16:25:27 +0100 Subject: dt-bindings: mfd: rk808: update rockchip,rk808.yaml reference Changeset 6c38ca03406e ("dt-bindings: mfd: rk808: Convert bindings to yaml") renamed: Documentation/devicetree/bindings/mfd/rk808.txt to: Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml. Update its cross-reference accordingly. Fixes: 6c38ca03406e ("dt-bindings: mfd: rk808: Convert bindings to yaml") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/417281c270e098eefed763859480014bec75c883.1654529011.git.mchehab@kernel.org --- Documentation/devicetree/bindings/pinctrl/pinctrl-rk805.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-rk805.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-rk805.txt index cbcbd31e3ce8..939cb5b6ffea 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-rk805.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-rk805.txt @@ -27,7 +27,7 @@ Required properties: - pins: List of pins. Valid values of pins properties are: gpio0, gpio1. First 2 properties must be added in the RK805 PMIC node, documented in -Documentation/devicetree/bindings/mfd/rk808.txt +Documentation/devicetree/bindings/mfd/rockchip,rk808.yaml Optional properties: ------------------- -- cgit From 7470ce60be24de8117b71614a3d610b8619f2108 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Jun 2022 16:25:39 +0100 Subject: MAINTAINERS: update cortina,gemini-ethernet.yaml reference Changeset 208b65f7b5cc ("dt-bindings: net: convert net/cortina,gemini-ethernet to yaml") renamed: Documentation/devicetree/bindings/net/cortina,gemini-ethernet.txt to: Documentation/devicetree/bindings/net/cortina,gemini-ethernet.yaml. Update its cross-reference accordingly. Fixes: 208b65f7b5cc ("dt-bindings: net: convert net/cortina,gemini-ethernet to yaml") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/d27b5d508fb757147b720bf573ce5a2e3fc5920e.1654529011.git.mchehab@kernel.org --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index a6d3bd9d2a8d..d6bf4f0d1f04 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2009,7 +2009,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://github.com/ulli-kroll/linux.git F: Documentation/devicetree/bindings/arm/gemini.yaml -F: Documentation/devicetree/bindings/net/cortina,gemini-ethernet.txt +F: Documentation/devicetree/bindings/net/cortina,gemini-ethernet.yaml F: Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt F: Documentation/devicetree/bindings/rtc/faraday,ftrtc010.yaml F: arch/arm/boot/dts/gemini* -- cgit From e5f580e72498ef634ae293c8d4ba7184f5191c74 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Jun 2022 16:25:40 +0100 Subject: MAINTAINERS: update dongwoon,dw9807-vcm.yaml reference Changeset a1f4626b282d ("media: dt-bindings: Convert Dongwoon dw9807-vcm bindings to json-schema") renamed: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.txt to: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.yaml. Update its cross-reference accordingly. Fixes: a1f4626b282d ("media: dt-bindings: Convert Dongwoon dw9807-vcm bindings to json-schema") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/89f11772dd4afe9700d6cbbb3da8749eb98b396a.1654529011.git.mchehab@kernel.org --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index d6bf4f0d1f04..3c9723f9d61c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6078,7 +6078,7 @@ M: Sakari Ailus L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git -F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.txt +F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.yaml F: drivers/media/i2c/dw9807-vcm.c DOUBLETALK DRIVER -- cgit From 09fed02c20a659e15c9b47a52e8cf2dffa41cda9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Jun 2022 16:25:42 +0100 Subject: MAINTAINERS: update snps,axs10x-reset.yaml reference Changeset 820f722c05dd ("dt-bindings: reset: snps,axs10x-reset: Convert to yaml") renamed: Documentation/devicetree/bindings/reset/snps,axs10x-reset.txt to: Documentation/devicetree/bindings/reset/snps,axs10x-reset.yaml. Update its cross-reference accordingly. Fixes: 820f722c05dd ("dt-bindings: reset: snps,axs10x-reset: Convert to yaml") Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/56560a2bcc06af94d36a28ed2cfdb25de481eee5.1654529011.git.mchehab@kernel.org --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 3c9723f9d61c..5400bdc2104e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19220,7 +19220,7 @@ F: arch/arc/plat-axs10x SYNOPSYS AXS10x RESET CONTROLLER DRIVER M: Eugeniy Paltsev S: Supported -F: Documentation/devicetree/bindings/reset/snps,axs10x-reset.txt +F: Documentation/devicetree/bindings/reset/snps,axs10x-reset.yaml F: drivers/reset/reset-axs10x.c SYNOPSYS CREG GPIO DRIVER -- cgit From a2d2bfc9d56513684260b6aab26a2e0b56b09d92 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Wed, 1 Jun 2022 06:17:46 +0200 Subject: MAINTAINERS: rectify entries for ARM DRM DRIVERS after dt conversion The three commits: 36fd2a65bcaf ("dt-bindings: display: convert Arm HDLCD to DT schema") 0f6983509ea1 ("dt-bindings: display: convert Arm Komeda to DT schema") 2c8b082a3ab1 ("dt-bindings: display: convert Arm Mali-DP to DT schema") convert the arm display dt-bindings, arm,*.txt to arm,*.yaml, but miss to adjust its reference in MAINTAINERS. Hence, ./scripts/get_maintainer.pl --self-test=patterns complains about broken references. Repair these file references in ARM HDLCD DRM DRIVER, ARM KOMEDA DRM-KMS DRIVER and ARM MALI-DP DRM DRIVER. Signed-off-by: Lukas Bulwahn Acked-by: Andre Przywara Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20220601041746.22986-1-lukas.bulwahn@gmail.com --- MAINTAINERS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 5400bdc2104e..7e970b1d5650 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1507,7 +1507,7 @@ F: drivers/clocksource/arm_arch_timer.c ARM HDLCD DRM DRIVER M: Liviu Dudau S: Supported -F: Documentation/devicetree/bindings/display/arm,hdlcd.txt +F: Documentation/devicetree/bindings/display/arm,hdlcd.yaml F: drivers/gpu/drm/arm/hdlcd_* ARM INTEGRATOR, VERSATILE AND REALVIEW SUPPORT @@ -1542,7 +1542,7 @@ M: Mihail Atanassov L: Mali DP Maintainers S: Supported T: git git://anongit.freedesktop.org/drm/drm-misc -F: Documentation/devicetree/bindings/display/arm,komeda.txt +F: Documentation/devicetree/bindings/display/arm,komeda.yaml F: Documentation/gpu/komeda-kms.rst F: drivers/gpu/drm/arm/display/include/ F: drivers/gpu/drm/arm/display/komeda/ @@ -1564,7 +1564,7 @@ M: Brian Starkey L: Mali DP Maintainers S: Supported T: git git://anongit.freedesktop.org/drm/drm-misc -F: Documentation/devicetree/bindings/display/arm,malidp.txt +F: Documentation/devicetree/bindings/display/arm,malidp.yaml F: Documentation/gpu/afbc.rst F: drivers/gpu/drm/arm/ -- cgit From 3a41c64d9c1185a2f3a184015e2a9b78bfc99c71 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 6 Jun 2022 17:31:29 +0200 Subject: netfilter: nf_tables: bail out early if hardware offload is not supported If user requests for NFT_CHAIN_HW_OFFLOAD, then check if either device provides the .ndo_setup_tc interface or there is an indirect flow block that has been registered. Otherwise, bail out early from the preparation phase. Moreover, validate that family == NFPROTO_NETDEV and hook is NF_NETDEV_INGRESS. Fixes: c9626a2cbdb2 ("netfilter: nf_tables: add hardware offload support") Signed-off-by: Pablo Neira Ayuso --- include/net/flow_offload.h | 1 + include/net/netfilter/nf_tables_offload.h | 2 +- net/core/flow_offload.c | 6 ++++++ net/netfilter/nf_tables_api.c | 2 +- net/netfilter/nf_tables_offload.c | 23 ++++++++++++++++++++++- 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index 021778a7e1af..6484095a8c01 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -612,5 +612,6 @@ int flow_indr_dev_setup_offload(struct net_device *dev, struct Qdisc *sch, enum tc_setup_type type, void *data, struct flow_block_offload *bo, void (*cleanup)(struct flow_block_cb *block_cb)); +bool flow_indr_dev_exists(void); #endif /* _NET_FLOW_OFFLOAD_H */ diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h index 797147843958..3568b6a2f5f0 100644 --- a/include/net/netfilter/nf_tables_offload.h +++ b/include/net/netfilter/nf_tables_offload.h @@ -92,7 +92,7 @@ int nft_flow_rule_offload_commit(struct net *net); NFT_OFFLOAD_MATCH(__key, __base, __field, __len, __reg) \ memset(&(__reg)->mask, 0xff, (__reg)->len); -int nft_chain_offload_priority(struct nft_base_chain *basechain); +bool nft_chain_offload_support(const struct nft_base_chain *basechain); int nft_offload_init(void); void nft_offload_exit(void); diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c index 73f68d4625f3..929f6379a279 100644 --- a/net/core/flow_offload.c +++ b/net/core/flow_offload.c @@ -595,3 +595,9 @@ int flow_indr_dev_setup_offload(struct net_device *dev, struct Qdisc *sch, return (bo && list_empty(&bo->cb_list)) ? -EOPNOTSUPP : count; } EXPORT_SYMBOL(flow_indr_dev_setup_offload); + +bool flow_indr_dev_exists(void) +{ + return !list_empty(&flow_block_indr_dev_list); +} +EXPORT_SYMBOL(flow_indr_dev_exists); diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 1a6a21bfb18d..51144fc66889 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -2166,7 +2166,7 @@ static int nft_basechain_init(struct nft_base_chain *basechain, u8 family, chain->flags |= NFT_CHAIN_BASE | flags; basechain->policy = NF_ACCEPT; if (chain->flags & NFT_CHAIN_HW_OFFLOAD && - nft_chain_offload_priority(basechain) < 0) + !nft_chain_offload_support(basechain)) return -EOPNOTSUPP; flow_block_init(&basechain->flow_block); diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c index 2d36952b1392..910ef881c3b8 100644 --- a/net/netfilter/nf_tables_offload.c +++ b/net/netfilter/nf_tables_offload.c @@ -208,7 +208,7 @@ static int nft_setup_cb_call(enum tc_setup_type type, void *type_data, return 0; } -int nft_chain_offload_priority(struct nft_base_chain *basechain) +static int nft_chain_offload_priority(const struct nft_base_chain *basechain) { if (basechain->ops.priority <= 0 || basechain->ops.priority > USHRT_MAX) @@ -217,6 +217,27 @@ int nft_chain_offload_priority(struct nft_base_chain *basechain) return 0; } +bool nft_chain_offload_support(const struct nft_base_chain *basechain) +{ + struct net_device *dev; + struct nft_hook *hook; + + if (nft_chain_offload_priority(basechain) < 0) + return false; + + list_for_each_entry(hook, &basechain->hook_list, list) { + if (hook->ops.pf != NFPROTO_NETDEV || + hook->ops.hooknum != NF_NETDEV_INGRESS) + return false; + + dev = hook->ops.dev; + if (!dev->netdev_ops->ndo_setup_tc && !flow_indr_dev_exists()) + return false; + } + + return true; +} + static void nft_flow_cls_offload_setup(struct flow_cls_offload *cls_flow, const struct nft_base_chain *basechain, const struct nft_rule *rule, -- cgit From ca871659ec1606d33b1e76de8d4cf924cf627e34 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 28 Feb 2022 12:25:31 -0800 Subject: drm/bridge: analogix_dp: Support PSR-exit to disable transition Most eDP panel functions only work correctly when the panel is not in self-refresh. In particular, analogix_dp_bridge_disable() tends to hit AUX channel errors if the panel is in self-refresh. Given the above, it appears that so far, this driver assumes that we are never in self-refresh when it comes time to fully disable the bridge. Prior to commit 846c7dfc1193 ("drm/atomic: Try to preserve the crtc enabled state in drm_atomic_remove_fb, v2."), this tended to be true, because we would automatically disable the pipe when framebuffers were removed, and so we'd typically disable the bridge shortly after the last display activity. However, that is not guaranteed: an idle (self-refresh) display pipe may be disabled, e.g., when switching CRTCs. We need to exit PSR first. Stable notes: this is definitely a bugfix, and the bug has likely existed in some form for quite a while. It may predate the "PSR helpers" refactor, but the code looked very different before that, and it's probably not worth rewriting the fix. Cc: Fixes: 6c836d965bad ("drm/rockchip: Use the helpers for PSR") Signed-off-by: Brian Norris Reviewed-by: Sean Paul Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20220228122522.v2.1.I161904be17ba14526f78536ccd78b85818449b51@changeid --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 42 +++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index eb590fb8e8d0..0300f670a4fd 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1268,6 +1268,25 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge, return 0; } +static +struct drm_crtc *analogix_dp_get_old_crtc(struct analogix_dp_device *dp, + struct drm_atomic_state *state) +{ + struct drm_encoder *encoder = dp->encoder; + struct drm_connector *connector; + struct drm_connector_state *conn_state; + + connector = drm_atomic_get_old_connector_for_encoder(state, encoder); + if (!connector) + return NULL; + + conn_state = drm_atomic_get_old_connector_state(state, connector); + if (!conn_state) + return NULL; + + return conn_state->crtc; +} + static struct drm_crtc *analogix_dp_get_new_crtc(struct analogix_dp_device *dp, struct drm_atomic_state *state) @@ -1448,14 +1467,16 @@ analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, { struct drm_atomic_state *old_state = old_bridge_state->base.state; struct analogix_dp_device *dp = bridge->driver_private; - struct drm_crtc *crtc; + struct drm_crtc *old_crtc, *new_crtc; + struct drm_crtc_state *old_crtc_state = NULL; struct drm_crtc_state *new_crtc_state = NULL; + int ret; - crtc = analogix_dp_get_new_crtc(dp, old_state); - if (!crtc) + new_crtc = analogix_dp_get_new_crtc(dp, old_state); + if (!new_crtc) goto out; - new_crtc_state = drm_atomic_get_new_crtc_state(old_state, crtc); + new_crtc_state = drm_atomic_get_new_crtc_state(old_state, new_crtc); if (!new_crtc_state) goto out; @@ -1464,6 +1485,19 @@ analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, return; out: + old_crtc = analogix_dp_get_old_crtc(dp, old_state); + if (old_crtc) { + old_crtc_state = drm_atomic_get_old_crtc_state(old_state, + old_crtc); + + /* When moving from PSR to fully disabled, exit PSR first. */ + if (old_crtc_state && old_crtc_state->self_refresh_active) { + ret = analogix_dp_disable_psr(dp); + if (ret) + DRM_ERROR("Failed to disable psr (%d)\n", ret); + } + } + analogix_dp_bridge_disable(bridge); } -- cgit From e54a4424925a27ed94dff046db3ce5caf4b1e748 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 28 Feb 2022 12:25:32 -0800 Subject: drm/atomic: Force bridge self-refresh-exit on CRTC switch It's possible to change which CRTC is in use for a given connector/encoder/bridge while we're in self-refresh without fully disabling the connector/encoder/bridge along the way. This can confuse the bridge encoder/bridge, because (a) it needs to track the SR state (trying to perform "active" operations while the panel is still in SR can be Bad(TM)); and (b) it tracks the SR state via the CRTC state (and after the switch, the previous SR state is lost). Thus, we need to either somehow carry the self-refresh state over to the new CRTC, or else force an encoder/bridge self-refresh transition during such a switch. I choose the latter, so we disable the encoder (and exit PSR) before attaching it to the new CRTC (where we can continue to assume a clean (non-self-refresh) state). This fixes PSR issues seen on Rockchip RK3399 systems with drivers/gpu/drm/bridge/analogix/analogix_dp_core.c. Change in v2: - Drop "->enable" condition; this could possibly be "->active" to reflect the intended hardware state, but it also is a little over-specific. We want to make a transition through "disabled" any time we're exiting PSR at the same time as a CRTC switch. (Thanks Liu Ying) Cc: Liu Ying Cc: Fixes: 1452c25b0e60 ("drm: Add helpers to kick off self refresh mode in drivers") Signed-off-by: Brian Norris Reviewed-by: Sean Paul Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20220228122522.v2.2.Ic15a2ef69c540aee8732703103e2cff51fb9c399@changeid --- drivers/gpu/drm/drm_atomic_helper.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 9603193d2fa1..987e4b212e9f 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1011,9 +1011,19 @@ crtc_needs_disable(struct drm_crtc_state *old_state, return drm_atomic_crtc_effectively_active(old_state); /* - * We need to run through the crtc_funcs->disable() function if the CRTC - * is currently on, if it's transitioning to self refresh mode, or if - * it's in self refresh mode and needs to be fully disabled. + * We need to disable bridge(s) and CRTC if we're transitioning out of + * self-refresh and changing CRTCs at the same time, because the + * bridge tracks self-refresh status via CRTC state. + */ + if (old_state->self_refresh_active && + old_state->crtc != new_state->crtc) + return true; + + /* + * We also need to run through the crtc_funcs->disable() function if + * the CRTC is currently on, if it's transitioning to self refresh + * mode, or if it's in self refresh mode and needs to be fully + * disabled. */ return old_state->active || (old_state->self_refresh_active && !new_state->active) || -- cgit From 11fe58c4450a8108b498d2f849976ba2686820fc Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 6 Jun 2022 15:46:20 -0500 Subject: ASoC: SOF: Intel: add MeteorLake machines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for MeteorLake (MTL) machines support, starting with mockup devices. Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Reviewed-by: Ranjani Sridharan Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220606204622.144424-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc-acpi-intel-match.h | 2 ++ sound/soc/intel/common/Makefile | 1 + sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 41 +++++++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 sound/soc/intel/common/soc-acpi-intel-mtl-match.c diff --git a/include/sound/soc-acpi-intel-match.h b/include/sound/soc-acpi-intel-match.h index 59551b1f22f3..bc7fd46ec2bc 100644 --- a/include/sound/soc-acpi-intel-match.h +++ b/include/sound/soc-acpi-intel-match.h @@ -30,6 +30,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[]; @@ -37,6 +38,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[]; /* * generic table used for HDA codec-based platforms, possibly with diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index fef0b2d1de68..8ca8f872ec80 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile @@ -9,6 +9,7 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m soc-acpi-intel-cml-match.o soc-acpi-intel-icl-match.o \ soc-acpi-intel-tgl-match.o soc-acpi-intel-ehl-match.o \ soc-acpi-intel-jsl-match.o soc-acpi-intel-adl-match.o \ + soc-acpi-intel-mtl-match.o \ soc-acpi-intel-hda-match.o \ soc-acpi-intel-sdw-mockup-match.o diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c new file mode 100644 index 000000000000..cc594b27e03b --- /dev/null +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * soc-acpi-intel-mtl-match.c - tables and support for MTL ACPI enumeration. + * + * Copyright (c) 2022, Intel Corporation. + * + */ + +#include +#include +#include "soc-acpi-intel-sdw-mockup-match.h" + +struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { + {}, +}; +EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_machines); + +/* this table is used when there is no I2S codec present */ +struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = { + /* mockup tests need to be first */ + { + .link_mask = GENMASK(3, 0), + .links = sdw_mockup_headset_2amps_mic, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-rt711-rt1308-rt715.tplg", + }, + { + .link_mask = BIT(0) | BIT(1) | BIT(3), + .links = sdw_mockup_headset_1amp_mic, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-rt711-rt1308-mono-rt715.tplg", + }, + { + .link_mask = GENMASK(2, 0), + .links = sdw_mockup_mic_headset_1amp, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-rt715-rt711-rt1308-mono.tplg", + }, + {}, +}; +EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_sdw_machines); -- cgit From 93693dcf2a4d7ab6a355f80c14653cd9c27a1422 Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Mon, 6 Jun 2022 15:46:21 -0500 Subject: ASoC: Intel: boards: rename RTL1019 compatible driver to rt1019p Use rt1019p for rt1015p.c compatible codec and reserve the name rt1019 for 10EC1019 matched driver in sof_realtek_common. Reviewed-by: Bard Liao Signed-off-by: Yong Zhi Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220606204622.144424-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_realtek_common.c | 24 ++++++++++++------------ sound/soc/intel/boards/sof_realtek_common.h | 6 +++--- sound/soc/intel/boards/sof_rt5682.c | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/sof_realtek_common.c b/sound/soc/intel/boards/sof_realtek_common.c index 2ab568c1d40b..b9643ca2e2f2 100644 --- a/sound/soc/intel/boards/sof_realtek_common.c +++ b/sound/soc/intel/boards/sof_realtek_common.c @@ -463,26 +463,26 @@ EXPORT_SYMBOL_NS(sof_rt1308_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); * 2-amp Configuration for RT1019 */ -static const struct snd_soc_dapm_route rt1019_dapm_routes[] = { +static const struct snd_soc_dapm_route rt1019p_dapm_routes[] = { /* speaker */ { "Left Spk", NULL, "Speaker" }, { "Right Spk", NULL, "Speaker" }, }; -static struct snd_soc_dai_link_component rt1019_components[] = { +static struct snd_soc_dai_link_component rt1019p_components[] = { { - .name = RT1019_DEV0_NAME, - .dai_name = RT1019_CODEC_DAI, + .name = RT1019P_DEV0_NAME, + .dai_name = RT1019P_CODEC_DAI, }, }; -static int rt1019_init(struct snd_soc_pcm_runtime *rtd) +static int rt1019p_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; int ret; - ret = snd_soc_dapm_add_routes(&card->dapm, rt1019_dapm_routes, - ARRAY_SIZE(rt1019_dapm_routes)); + ret = snd_soc_dapm_add_routes(&card->dapm, rt1019p_dapm_routes, + ARRAY_SIZE(rt1019p_dapm_routes)); if (ret) { dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret); return ret; @@ -490,13 +490,13 @@ static int rt1019_init(struct snd_soc_pcm_runtime *rtd) return ret; } -void sof_rt1019_dai_link(struct snd_soc_dai_link *link) +void sof_rt1019p_dai_link(struct snd_soc_dai_link *link) { - link->codecs = rt1019_components; - link->num_codecs = ARRAY_SIZE(rt1019_components); - link->init = rt1019_init; + link->codecs = rt1019p_components; + link->num_codecs = ARRAY_SIZE(rt1019p_components); + link->init = rt1019p_init; } -EXPORT_SYMBOL_NS(sof_rt1019_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); +EXPORT_SYMBOL_NS(sof_rt1019p_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); MODULE_DESCRIPTION("ASoC Intel SOF Realtek helpers"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/intel/boards/sof_realtek_common.h b/sound/soc/intel/boards/sof_realtek_common.h index ec3eea633e04..778443421090 100644 --- a/sound/soc/intel/boards/sof_realtek_common.h +++ b/sound/soc/intel/boards/sof_realtek_common.h @@ -39,9 +39,9 @@ void sof_rt1015_codec_conf(struct snd_soc_card *card); #define RT1308_DEV0_NAME "i2c-10EC1308:00" void sof_rt1308_dai_link(struct snd_soc_dai_link *link); -#define RT1019_CODEC_DAI "HiFi" -#define RT1019_DEV0_NAME "RTL1019:00" +#define RT1019P_CODEC_DAI "HiFi" +#define RT1019P_DEV0_NAME "RTL1019:00" -void sof_rt1019_dai_link(struct snd_soc_dai_link *link); +void sof_rt1019p_dai_link(struct snd_soc_dai_link *link); #endif /* __SOF_REALTEK_COMMON_H */ diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 5d67a2c87a1d..f28dae64587e 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -735,7 +735,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, } else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) { sof_rt1015p_dai_link(&links[id]); } else if (sof_rt5682_quirk & SOF_RT1019_SPEAKER_AMP_PRESENT) { - sof_rt1019_dai_link(&links[id]); + sof_rt1019p_dai_link(&links[id]); } else if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) { links[id].codecs = max_98373_components; -- cgit From 8208dd75eb468d1bb90aef52f385e5b3486bb737 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:46:22 -0500 Subject: ASoC: Intel: sof_sdw: allow HDaudio/HDMI disable For tests, it's rather common to disable the HDaudio links and codecs in the build. Since we already get a codec_mask parameter indicating that there are no codecs detected, it's straightforward to skip the HDMI dailink creation and create a card. Note that when disabling HDMI, a modified topology without HDMI pipelines needs to be provided as well. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606204622.144424-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 1 - sound/soc/intel/boards/sof_sdw.c | 24 +++++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index f3873b5bea87..4b4c1e1e4808 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -660,7 +660,6 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST depends on SOUNDWIRE - depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_MAX98373_I2C select SND_SOC_MAX98373_SDW select SND_SOC_RT700_SDW diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 1f00679b4240..f871daa5cb33 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1127,10 +1127,14 @@ static int sof_card_dai_links_create(struct device *dev, for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) codec_info_list[i].amp_num = 0; - if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) - hdmi_num = SOF_TGL_HDMI_COUNT; - else - hdmi_num = SOF_PRE_TGL_HDMI_COUNT; + if (mach_params->codec_mask & IDISP_CODEC_MASK) { + ctx->idisp_codec = true; + + if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) + hdmi_num = SOF_TGL_HDMI_COUNT; + else + hdmi_num = SOF_PRE_TGL_HDMI_COUNT; + } ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); /* @@ -1150,9 +1154,6 @@ static int sof_card_dai_links_create(struct device *dev, return ret; } - if (mach_params->codec_mask & IDISP_CODEC_MASK) - ctx->idisp_codec = true; - /* enable dmic01 & dmic16k */ dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0; comp_num += dmic_num; @@ -1375,7 +1376,9 @@ HDMI: static int sof_sdw_card_late_probe(struct snd_soc_card *card) { - int i, ret; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + int ret = 0; + int i; for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { if (!codec_info_list[i].late_probe) @@ -1386,7 +1389,10 @@ static int sof_sdw_card_late_probe(struct snd_soc_card *card) return ret; } - return sof_sdw_hdmi_card_late_probe(card); + if (ctx->idisp_codec) + ret = sof_sdw_hdmi_card_late_probe(card); + + return ret; } /* SoC card */ -- cgit From b585692fc937dc8f9d494078b5ffe2aafe31ec18 Mon Sep 17 00:00:00 2001 From: Ajit Kumar Pandey Date: Mon, 6 Jun 2022 16:02:08 -0500 Subject: ASoC: SOF: amd: Add SOF pm ops callback for Renoir Add SOF PM ops callback in renoir dsp ops to power off and on ACP IP block during system suspend and resume on Renoir platform. Signed-off-by: Ajit Kumar Pandey Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220606210212.146626-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp-dsp-offset.h | 2 ++ sound/soc/sof/amd/acp.c | 36 ++++++++++++++++++++++++++++++++++++ sound/soc/sof/amd/acp.h | 4 ++++ sound/soc/sof/amd/pci-rn.c | 4 ++++ sound/soc/sof/amd/renoir.c | 4 ++++ 5 files changed, 50 insertions(+) diff --git a/sound/soc/sof/amd/acp-dsp-offset.h b/sound/soc/sof/amd/acp-dsp-offset.h index 40fbf11facba..56cefd4a84fc 100644 --- a/sound/soc/sof/amd/acp-dsp-offset.h +++ b/sound/soc/sof/amd/acp-dsp-offset.h @@ -46,12 +46,14 @@ #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0xC3C #define ACPAXI2AXI_ATU_CTRL 0xC40 #define ACP_SOFT_RESET 0x1000 +#define ACP_CONTROL 0x1004 #define ACP_I2S_PIN_CONFIG 0x1400 /* Registers from ACP_PGFSM block */ #define ACP_PGFSM_CONTROL 0x141C #define ACP_PGFSM_STATUS 0x1420 +#define ACP_CLKMUX_SEL 0x1424 /* Registers from ACP_INTR block */ #define ACP_EXTERNAL_INTR_ENB 0x1800 diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index 0c272573df97..c40d2900dd36 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -413,10 +413,46 @@ static int acp_init(struct snd_sof_dev *sdev) dev_err(sdev->dev, "ACP power on failed\n"); return ret; } + + snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_CONTROL, 0x01); /* Reset */ return acp_reset(sdev); } +int amd_sof_acp_suspend(struct snd_sof_dev *sdev, u32 target_state) +{ + int ret; + + ret = acp_reset(sdev); + if (ret) { + dev_err(sdev->dev, "ACP Reset failed\n"); + return ret; + } + + snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_CONTROL, 0x00); + + return 0; +} +EXPORT_SYMBOL_NS(amd_sof_acp_suspend, SND_SOC_SOF_AMD_COMMON); + +int amd_sof_acp_resume(struct snd_sof_dev *sdev) +{ + int ret; + + ret = acp_init(sdev); + if (ret) { + dev_err(sdev->dev, "ACP Init failed\n"); + return ret; + } + + snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_CLKMUX_SEL, 0x03); + + ret = acp_memory_init(sdev); + + return ret; +} +EXPORT_SYMBOL_NS(amd_sof_acp_resume, SND_SOC_SOF_AMD_COMMON); + int amd_sof_acp_probe(struct snd_sof_dev *sdev) { struct pci_dev *pci = to_pci_dev(sdev->dev); diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index 291b44c54bcc..4c42b8fd6abf 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -216,6 +216,10 @@ int acp_sof_trace_init(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, struct sof_ipc_dma_trace_params_ext *dtrace_params); int acp_sof_trace_release(struct snd_sof_dev *sdev); +/* PM Callbacks */ +int amd_sof_acp_suspend(struct snd_sof_dev *sdev, u32 target_state); +int amd_sof_acp_resume(struct snd_sof_dev *sdev); + struct sof_amd_acp_desc { unsigned int host_bridge_id; }; diff --git a/sound/soc/sof/amd/pci-rn.c b/sound/soc/sof/amd/pci-rn.c index d5d9bcc2c997..3a7fed25a226 100644 --- a/sound/soc/sof/amd/pci-rn.c +++ b/sound/soc/sof/amd/pci-rn.c @@ -49,6 +49,7 @@ static const struct sof_amd_acp_desc renoir_chip_info = { static const struct sof_dev_desc renoir_desc = { .machines = snd_soc_acpi_amd_sof_machines, + .use_acpi_target_states = true, .resindex_lpe_base = 0, .resindex_pcicfg_base = -1, .resindex_imr_base = -1, @@ -166,6 +167,9 @@ static struct pci_driver snd_sof_pci_amd_rn_driver = { .id_table = rn_pci_ids, .probe = acp_pci_rn_probe, .remove = acp_pci_rn_remove, + .driver = { + .pm = &sof_pci_pm, + }, }; module_pci_driver(snd_sof_pci_amd_rn_driver); diff --git a/sound/soc/sof/amd/renoir.c b/sound/soc/sof/amd/renoir.c index 70190365328c..9261c8bc2236 100644 --- a/sound/soc/sof/amd/renoir.c +++ b/sound/soc/sof/amd/renoir.c @@ -173,6 +173,10 @@ struct snd_sof_dsp_ops sof_renoir_ops = { /* Trace Logger */ .trace_init = acp_sof_trace_init, .trace_release = acp_sof_trace_release, + + /* PM */ + .suspend = amd_sof_acp_suspend, + .resume = amd_sof_acp_resume, }; EXPORT_SYMBOL(sof_renoir_ops); -- cgit From e53b20598f394e37951d6355f1c88ae01165b53f Mon Sep 17 00:00:00 2001 From: YC Hung Date: Mon, 6 Jun 2022 16:02:09 -0500 Subject: ASoC: SOF: mediatek: revise mt8195 clock sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clock enable : enable and set audio_h selection as 26M. Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: YC Hung Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220606210212.146626-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/mediatek/mt8195/mt8195-clk.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/sof/mediatek/mt8195/mt8195-clk.c b/sound/soc/sof/mediatek/mt8195/mt8195-clk.c index 6bcb4b9b00fb..9ef08e43aa38 100644 --- a/sound/soc/sof/mediatek/mt8195/mt8195-clk.c +++ b/sound/soc/sof/mediatek/mt8195/mt8195-clk.c @@ -132,6 +132,13 @@ static int adsp_default_clk_init(struct snd_sof_dev *sdev, bool enable) return ret; } + ret = clk_set_parent(priv->clk[CLK_TOP_AUDIO_H], + priv->clk[CLK_TOP_CLK26M]); + if (ret) { + dev_err(dev, "set audio_h_sel failed %d\n", ret); + return ret; + } + ret = adsp_enable_all_clock(sdev); if (ret) { dev_err(dev, "failed to adsp_enable_clock: %d\n", ret); -- cgit From fd43dcbb859c85831a05e37287e1c5395f54aba8 Mon Sep 17 00:00:00 2001 From: YC Hung Date: Mon, 6 Jun 2022 16:02:10 -0500 Subject: ASoC: SOF: mediatek: Add shared_size for mediatek common chip information Add shared_size for mediatek common chip information which is used for audio and trace dma. Reviewed-by: Curtis Malainey Reviewed-by: Ranjani Sridharan Signed-off-by: YC Hung Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220606210212.146626-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/mediatek/adsp_helper.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/mediatek/adsp_helper.h b/sound/soc/sof/mediatek/adsp_helper.h index 4ab998756bbc..d41e904e6614 100644 --- a/sound/soc/sof/mediatek/adsp_helper.h +++ b/sound/soc/sof/mediatek/adsp_helper.h @@ -20,6 +20,7 @@ struct mtk_adsp_chip_info { u32 sramsize; u32 dramsize; u32 cfgregsize; + u32 shared_size; void __iomem *va_sram; /* corresponding to pa_sram */ void __iomem *va_dram; /* corresponding to pa_dram */ void __iomem *va_cfgreg; -- cgit From 0bf4276cc7883d65e594926c1159d4c0712d02e7 Mon Sep 17 00:00:00 2001 From: YC Hung Date: Mon, 6 Jun 2022 16:02:11 -0500 Subject: ASoC: SOF: mediatek: mt8195 modify dram type as non-cache Modify dram as non-cache memory type to avoid wrong access between host and dsp side and get the size of shared dma from device tree. Reviewed-by: Curtis Malainey Reviewed-by: Ranjani Sridharan Signed-off-by: YC Hung Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220606210212.146626-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/mediatek/mt8195/mt8195.c | 37 +++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.c b/sound/soc/sof/mediatek/mt8195/mt8195.c index 30111ab23bf5..64d1b5a4e31b 100644 --- a/sound/soc/sof/mediatek/mt8195/mt8195.c +++ b/sound/soc/sof/mediatek/mt8195/mt8195.c @@ -145,6 +145,14 @@ static int platform_parse_resource(struct platform_device *pdev, void *data) dev_dbg(dev, "DMA %pR\n", &res); + adsp->pa_shared_dram = (phys_addr_t)res.start; + adsp->shared_size = resource_size(&res); + if (adsp->pa_shared_dram & DRAM_REMAP_MASK) { + dev_err(dev, "adsp shared dma memory(%#x) is not 4K-aligned\n", + (u32)adsp->pa_shared_dram); + return -EINVAL; + } + ret = of_reserved_mem_device_init(dev); if (ret) { dev_err(dev, "of_reserved_mem_device_init failed\n"); @@ -273,23 +281,18 @@ static int adsp_shared_base_ioremap(struct platform_device *pdev, void *data) { struct device *dev = &pdev->dev; struct mtk_adsp_chip_info *adsp = data; - u32 shared_size; /* remap shared-dram base to be non-cachable */ - shared_size = TOTAL_SIZE_SHARED_DRAM_FROM_TAIL; - adsp->pa_shared_dram = adsp->pa_dram + adsp->dramsize - shared_size; - if (adsp->va_dram) { - adsp->shared_dram = adsp->va_dram + DSP_DRAM_SIZE - shared_size; - } else { - adsp->shared_dram = devm_ioremap(dev, adsp->pa_shared_dram, - shared_size); - if (!adsp->shared_dram) { - dev_err(dev, "ioremap failed for shared DRAM\n"); - return -ENOMEM; - } + adsp->shared_dram = devm_ioremap(dev, adsp->pa_shared_dram, + adsp->shared_size); + if (!adsp->shared_dram) { + dev_err(dev, "failed to ioremap base %pa size %#x\n", + adsp->shared_dram, adsp->shared_size); + return -ENOMEM; } + dev_dbg(dev, "shared-dram vbase=%p, phy addr :%pa, size=%#x\n", - adsp->shared_dram, &adsp->pa_shared_dram, shared_size); + adsp->shared_dram, &adsp->pa_shared_dram, adsp->shared_size); return 0; } @@ -361,9 +364,11 @@ static int mt8195_dsp_probe(struct snd_sof_dev *sdev) goto err_adsp_sram_power_off; } - sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap_wc(sdev->dev, - priv->adsp->pa_dram, - priv->adsp->dramsize); + priv->adsp->va_sram = sdev->bar[SOF_FW_BLK_TYPE_IRAM]; + + sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap(sdev->dev, + priv->adsp->pa_dram, + priv->adsp->dramsize); if (!sdev->bar[SOF_FW_BLK_TYPE_SRAM]) { dev_err(sdev->dev, "failed to ioremap base %pa size %#x\n", &priv->adsp->pa_dram, priv->adsp->dramsize); -- cgit From 078f28fee5aa417169d8e8906815c684beddbe74 Mon Sep 17 00:00:00 2001 From: YC Hung Date: Mon, 6 Jun 2022 16:02:12 -0500 Subject: ASoC: SOF: mediatek: mt8195 suspend check dsp idle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During suspend flow, sof_suspend will be called and the pm_ops->ctx_save callback notifies DSP of the upcoming power down. Upon receipt of the ctx_save IPC, the DSP will start the D3 transition. Before the DSP enter idle, an interrupt is generated to notify the host of the power state change. Since the host and DSP are two different processors, there could be a race condition, which can be avoided by polling with 1s timeout and 500us intervals Reviewed-by: Péter Ujfalusi Signed-off-by: YC Hung Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220606210212.146626-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/mediatek/mt8195/mt8195.c | 13 +++++++++++++ sound/soc/sof/mediatek/mt8195/mt8195.h | 5 +++++ 2 files changed, 18 insertions(+) diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.c b/sound/soc/sof/mediatek/mt8195/mt8195.c index 64d1b5a4e31b..9c146015cd1b 100644 --- a/sound/soc/sof/mediatek/mt8195/mt8195.c +++ b/sound/soc/sof/mediatek/mt8195/mt8195.c @@ -443,6 +443,19 @@ static int mt8195_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) { struct platform_device *pdev = container_of(sdev->dev, struct platform_device, dev); int ret; + u32 reset_sw, dbg_pc; + + /* wait dsp enter idle, timeout is 1 second */ + ret = snd_sof_dsp_read_poll_timeout(sdev, DSP_REG_BAR, + DSP_RESET_SW, reset_sw, + ((reset_sw & ADSP_PWAIT) == ADSP_PWAIT), + SUSPEND_DSP_IDLE_POLL_INTERVAL_US, + SUSPEND_DSP_IDLE_TIMEOUT_US); + if (ret < 0) { + dbg_pc = snd_sof_dsp_read(sdev, DSP_REG_BAR, DSP_PDEBUGPC); + dev_warn(sdev->dev, "dsp not idle, powering off anyway : swrest %#x, pc %#x, ret %d\n", + reset_sw, dbg_pc, ret); + } /* stall and reset dsp */ sof_hifixdsp_shutdown(sdev); diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.h b/sound/soc/sof/mediatek/mt8195/mt8195.h index 929424182357..7ffd523f936c 100644 --- a/sound/soc/sof/mediatek/mt8195/mt8195.h +++ b/sound/soc/sof/mediatek/mt8195/mt8195.h @@ -34,6 +34,7 @@ struct snd_sof_dev; #define ADSP_DRESET_SW BIT(1) #define ADSP_RUNSTALL BIT(3) #define STATVECTOR_SEL BIT(4) +#define ADSP_PWAIT BIT(16) #define DSP_PFAULTBUS 0x0028 #define DSP_PFAULTINFO 0x002c #define DSP_GPR00 0x0030 @@ -153,6 +154,10 @@ struct snd_sof_dev; #define DRAM_REMAP_SHIFT 12 #define DRAM_REMAP_MASK (BIT(DRAM_REMAP_SHIFT) - 1) +/* suspend dsp idle check interval and timeout */ +#define SUSPEND_DSP_IDLE_TIMEOUT_US 1000000 /* timeout to wait dsp idle, 1 sec */ +#define SUSPEND_DSP_IDLE_POLL_INTERVAL_US 500 /* 0.5 msec */ + void sof_hifixdsp_boot_sequence(struct snd_sof_dev *sdev, u32 boot_addr); void sof_hifixdsp_shutdown(struct snd_sof_dev *sdev); #endif -- cgit From f55a07074fdd38cab8c097ac5bd397d68eff733c Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Thu, 2 Jun 2022 14:01:06 +0000 Subject: amt: fix wrong usage of pskb_may_pull() It adds missing pskb_may_pull() in amt_update_handler() and amt_multicast_data_handler(). And it fixes wrong parameter of pskb_may_pull() in amt_advertisement_handler() and amt_membership_query_handler(). Reported-by: Jakub Kicinski Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") Signed-off-by: Taehee Yoo Signed-off-by: Jakub Kicinski --- drivers/net/amt.c | 55 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/drivers/net/amt.c b/drivers/net/amt.c index ebee5f07a208..900948e135ad 100644 --- a/drivers/net/amt.c +++ b/drivers/net/amt.c @@ -2220,8 +2220,7 @@ static bool amt_advertisement_handler(struct amt_dev *amt, struct sk_buff *skb) struct amt_header_advertisement *amta; int hdr_size; - hdr_size = sizeof(*amta) - sizeof(struct amt_header); - + hdr_size = sizeof(*amta) + sizeof(struct udphdr); if (!pskb_may_pull(skb, hdr_size)) return true; @@ -2251,19 +2250,27 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) struct ethhdr *eth; struct iphdr *iph; + hdr_size = sizeof(*amtmd) + sizeof(struct udphdr); + if (!pskb_may_pull(skb, hdr_size)) + return true; + amtmd = (struct amt_header_mcast_data *)(udp_hdr(skb) + 1); if (amtmd->reserved || amtmd->version) return true; - hdr_size = sizeof(*amtmd) + sizeof(struct udphdr); if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_IP), false)) return true; + skb_reset_network_header(skb); skb_push(skb, sizeof(*eth)); skb_reset_mac_header(skb); skb_pull(skb, sizeof(*eth)); eth = eth_hdr(skb); + + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; iph = ip_hdr(skb); + if (iph->version == 4) { if (!ipv4_is_multicast(iph->daddr)) return true; @@ -2274,6 +2281,9 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) } else if (iph->version == 6) { struct ipv6hdr *ip6h; + if (!pskb_may_pull(skb, sizeof(*ip6h))) + return true; + ip6h = ipv6_hdr(skb); if (!ipv6_addr_is_multicast(&ip6h->daddr)) return true; @@ -2306,8 +2316,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, struct iphdr *iph; int hdr_size, len; - hdr_size = sizeof(*amtmq) - sizeof(struct amt_header); - + hdr_size = sizeof(*amtmq) + sizeof(struct udphdr); if (!pskb_may_pull(skb, hdr_size)) return true; @@ -2315,22 +2324,27 @@ static bool amt_membership_query_handler(struct amt_dev *amt, if (amtmq->reserved || amtmq->version) return true; - hdr_size = sizeof(*amtmq) + sizeof(struct udphdr) - sizeof(*eth); + hdr_size -= sizeof(*eth); if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false)) return true; + oeth = eth_hdr(skb); skb_reset_mac_header(skb); skb_pull(skb, sizeof(*eth)); skb_reset_network_header(skb); eth = eth_hdr(skb); + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + iph = ip_hdr(skb); if (iph->version == 4) { - if (!ipv4_is_multicast(iph->daddr)) - return true; if (!pskb_may_pull(skb, sizeof(*iph) + AMT_IPHDR_OPTS + sizeof(*ihv3))) return true; + if (!ipv4_is_multicast(iph->daddr)) + return true; + ihv3 = skb_pull(skb, sizeof(*iph) + AMT_IPHDR_OPTS); skb_reset_transport_header(skb); skb_push(skb, sizeof(*iph) + AMT_IPHDR_OPTS); @@ -2345,15 +2359,17 @@ static bool amt_membership_query_handler(struct amt_dev *amt, ip_eth_mc_map(iph->daddr, eth->h_dest); #if IS_ENABLED(CONFIG_IPV6) } else if (iph->version == 6) { - struct ipv6hdr *ip6h = ipv6_hdr(skb); struct mld2_query *mld2q; + struct ipv6hdr *ip6h; - if (!ipv6_addr_is_multicast(&ip6h->daddr)) - return true; if (!pskb_may_pull(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS + sizeof(*mld2q))) return true; + ip6h = ipv6_hdr(skb); + if (!ipv6_addr_is_multicast(&ip6h->daddr)) + return true; + mld2q = skb_pull(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS); skb_reset_transport_header(skb); skb_push(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS); @@ -2389,23 +2405,23 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) { struct amt_header_membership_update *amtmu; struct amt_tunnel_list *tunnel; - struct udphdr *udph; struct ethhdr *eth; struct iphdr *iph; - int len; + int len, hdr_size; iph = ip_hdr(skb); - udph = udp_hdr(skb); - if (__iptunnel_pull_header(skb, sizeof(*udph), skb->protocol, - false, false)) + hdr_size = sizeof(*amtmu) + sizeof(struct udphdr); + if (!pskb_may_pull(skb, hdr_size)) return true; - amtmu = (struct amt_header_membership_update *)skb->data; + amtmu = (struct amt_header_membership_update *)(udp_hdr(skb) + 1); if (amtmu->reserved || amtmu->version) return true; - skb_pull(skb, sizeof(*amtmu)); + if (iptunnel_pull_header(skb, hdr_size, skb->protocol, false)) + return true; + skb_reset_network_header(skb); list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) { @@ -2426,6 +2442,9 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) return true; report: + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + iph = ip_hdr(skb); if (iph->version == 4) { if (ip_mc_check_igmp(skb)) { -- cgit From d16207f92a4a823c48b4ea953ad51f4483456768 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Thu, 2 Jun 2022 14:01:07 +0000 Subject: amt: fix possible null-ptr-deref in amt_rcv() When amt interface receives amt message, it tries to obtain amt private data from sock. If there is no amt private data, it frees an skb immediately. After kfree_skb(), it increases the rx_dropped stats. But in order to use rx_dropped, amt private data is needed. So, it makes amt_rcv() to do not increase rx_dropped stats when it can not obtain amt private data. Reported-by: kernel test robot Reported-by: Dan Carpenter Fixes: 1a1a0e80e005 ("amt: fix possible memory leak in amt_rcv()") Signed-off-by: Taehee Yoo Signed-off-by: Jakub Kicinski --- drivers/net/amt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/amt.c b/drivers/net/amt.c index 900948e135ad..ef483bf51033 100644 --- a/drivers/net/amt.c +++ b/drivers/net/amt.c @@ -2698,7 +2698,8 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) amt = rcu_dereference_sk_user_data(sk); if (!amt) { err = true; - goto drop; + kfree_skb(skb); + goto out; } skb->dev = amt->dev; -- cgit From d7970039d87c926bb648982e920cb9851c19f3e1 Mon Sep 17 00:00:00 2001 From: Taehee Yoo Date: Thu, 2 Jun 2022 14:01:08 +0000 Subject: amt: fix wrong type string definition amt message type definition starts from 1, not 0. But type_str[] starts from 0. So, it prints wrong type information. Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") Signed-off-by: Taehee Yoo Signed-off-by: Jakub Kicinski --- drivers/net/amt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/amt.c b/drivers/net/amt.c index ef483bf51033..be2719a3ba70 100644 --- a/drivers/net/amt.c +++ b/drivers/net/amt.c @@ -51,6 +51,7 @@ static char *status_str[] = { }; static char *type_str[] = { + "", /* Type 0 is not defined */ "AMT_MSG_DISCOVERY", "AMT_MSG_ADVERTISEMENT", "AMT_MSG_REQUEST", -- cgit From b8d91399775c55162073bb2aca061ec42e3d4bc1 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Fri, 3 Jun 2022 17:32:38 +0400 Subject: net: ethernet: bgmac: Fix refcount leak in bcma_mdio_mii_register of_get_child_by_name() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Add missing of_node_put() to avoid refcount leak. Fixes: 55954f3bfdac ("net: ethernet: bgmac: move BCMA MDIO Phy code into a separate file") Signed-off-by: Miaoqian Lin Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/r/20220603133238.44114-1-linmq006@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c b/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c index 086739e4f40a..9b83d5361699 100644 --- a/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c +++ b/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c @@ -234,6 +234,7 @@ struct mii_bus *bcma_mdio_mii_register(struct bgmac *bgmac) np = of_get_child_by_name(core->dev.of_node, "mdio"); err = of_mdiobus_register(mii_bus, np); + of_node_put(np); if (err) { dev_err(&core->dev, "Registration of mii bus failed\n"); goto err_free_bus; -- cgit From 8ea21823aa584b55ba4b861307093b78054b0c1b Mon Sep 17 00:00:00 2001 From: Shyam Prasad N Date: Tue, 31 May 2022 12:31:05 +0000 Subject: cifs: return errors during session setup during reconnects During reconnects, we check the return value from cifs_negotiate_protocol, and have handlers for both success and failures. But if that passes, and cifs_setup_session returns any errors other than -EACCES, we do not handle that. This fix adds a handler for that, so that we don't go ahead and try a tree_connect on a failed session. Signed-off-by: Shyam Prasad N Reviewed-by: Enzo Matsumiya Cc: stable@vger.kernel.org Signed-off-by: Steve French --- fs/cifs/smb2pdu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 0e8c85249579..eaf975f1ad89 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -288,6 +288,9 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, mutex_unlock(&ses->session_mutex); rc = -EHOSTDOWN; goto failed; + } else if (rc) { + mutex_unlock(&ses->session_mutex); + goto out; } } else { mutex_unlock(&ses->session_mutex); -- cgit From dbac14a5a05ff8e1ce7c0da0e1f520ce39ec62ea Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 6 Jun 2022 13:59:20 +0900 Subject: xen: unexport __init-annotated xen_xlate_map_ballooned_pages() EXPORT_SYMBOL and __init is a bad combination because the .init.text section is freed up after the initialization. Hence, modules cannot use symbols annotated __init. The access to a freed symbol may end up with kernel panic. modpost used to detect it, but it has been broken for a decade. Recently, I fixed modpost so it started to warn it again, then this showed up in linux-next builds. There are two ways to fix it: - Remove __init - Remove EXPORT_SYMBOL I chose the latter for this case because none of the in-tree call-sites (arch/arm/xen/enlighten.c, arch/x86/xen/grant-table.c) is compiled as modular. Fixes: 243848fc018c ("xen/grant-table: Move xlated_setup_gnttab_pages to common place") Reported-by: Stephen Rothwell Signed-off-by: Masahiro Yamada Reviewed-by: Oleksandr Tyshchenko Acked-by: Stefano Stabellini Link: https://lore.kernel.org/r/20220606045920.4161881-1-masahiroy@kernel.org Signed-off-by: Juergen Gross --- drivers/xen/xlate_mmu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c index 34742c6e189e..f17c4c03db30 100644 --- a/drivers/xen/xlate_mmu.c +++ b/drivers/xen/xlate_mmu.c @@ -261,7 +261,6 @@ int __init xen_xlate_map_ballooned_pages(xen_pfn_t **gfns, void **virt, return 0; } -EXPORT_SYMBOL_GPL(xen_xlate_map_ballooned_pages); struct remap_pfn { struct mm_struct *mm; -- cgit From 77991645952c21962a095910c51fe0f73d35bf91 Mon Sep 17 00:00:00 2001 From: Roger Knecht Date: Sat, 21 May 2022 14:47:45 +0200 Subject: crc-itu-t: fix typo in CRC ITU-T polynomial comment The code comment says that the polynomial is x^16 + x^12 + x^15 + 1, but the correct polynomial is x^16 + x^12 + x^5 + 1. Quoting from page 2 in the ITU-T V.41 specification [1]: 2 Encoding and checking process The service bits and information bits, taken in conjunction, correspond to the coefficients of a message polynomial having terms from x^(n-1) (n = total number of bits in a block or sequence) down to x^16. This polynomial is divided, modulo 2, by the generating polynomial x^16 + x^12 + x^5 + 1. The hex (truncated) polynomial 0x1021 and CRC code implementation are correct, however. [1] https://www.itu.int/rec/T-REC-V.41-198811-I/en Signed-off-by: Roger Knecht Acked-by: Randy Dunlap Signed-off-by: Jason A. Donenfeld --- include/linux/crc-itu-t.h | 2 +- lib/crc-itu-t.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/crc-itu-t.h b/include/linux/crc-itu-t.h index a4367051e192..2f991a427ade 100644 --- a/include/linux/crc-itu-t.h +++ b/include/linux/crc-itu-t.h @@ -4,7 +4,7 @@ * * Implements the standard CRC ITU-T V.41: * Width 16 - * Poly 0x1021 (x^16 + x^12 + x^15 + 1) + * Poly 0x1021 (x^16 + x^12 + x^5 + 1) * Init 0 */ diff --git a/lib/crc-itu-t.c b/lib/crc-itu-t.c index 1974b355c148..1d26a1647da5 100644 --- a/lib/crc-itu-t.c +++ b/lib/crc-itu-t.c @@ -7,7 +7,7 @@ #include #include -/** CRC table for the CRC ITU-T V.41 0x1021 (x^16 + x^12 + x^15 + 1) */ +/* CRC table for the CRC ITU-T V.41 0x1021 (x^16 + x^12 + x^5 + 1) */ const u16 crc_itu_t_table[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, -- cgit From 5e74a4b3ec1816e3bbfd715d46ae29d2508079cb Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 5 Jun 2022 22:50:48 +0200 Subject: stmmac: intel: Fix an error handling path in intel_eth_pci_probe() When the managed API is used, there is no need to explicitly call pci_free_irq_vectors(). This looks to be a left-over from the commit in the Fixes tag. Only the .remove() function had been updated. So remove this unused function call and update goto label accordingly. Fixes: 8accc467758e ("stmmac: intel: use managed PCI function on probe and resume") Signed-off-by: Christophe JAILLET Reviewed-by: Wong Vee Khee Link: https://lore.kernel.org/r/1ac9b6787b0db83b0095711882c55c77c8ea8da0.1654462241.git.christophe.jaillet@wanadoo.fr Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index f9f80933e0c9..38fe77d1035e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -1072,13 +1072,11 @@ static int intel_eth_pci_probe(struct pci_dev *pdev, ret = stmmac_dvr_probe(&pdev->dev, plat, &res); if (ret) { - goto err_dvr_probe; + goto err_alloc_irq; } return 0; -err_dvr_probe: - pci_free_irq_vectors(pdev); err_alloc_irq: clk_disable_unprepare(plat->stmmac_clk); clk_unregister_fixed_rate(plat->stmmac_clk); -- cgit From 662a80946ce13633ae90a55379f1346c10f0c432 Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Sun, 5 Jun 2022 16:23:25 -0700 Subject: af_unix: Fix a data-race in unix_dgram_peer_wake_me(). unix_dgram_poll() calls unix_dgram_peer_wake_me() without `other`'s lock held and check if its receive queue is full. Here we need to use unix_recvq_full_lockless() instead of unix_recvq_full(), otherwise KCSAN will report a data-race. Fixes: 7d267278a9ec ("unix: avoid use-after-free in ep_remove_wait_queue") Signed-off-by: Kuniyuki Iwashima Link: https://lore.kernel.org/r/20220605232325.11804-1-kuniyu@amazon.com Signed-off-by: Paolo Abeni --- net/unix/af_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 654dcef7cfb3..2206e6f8902d 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -490,7 +490,7 @@ static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other) * -ECONNREFUSED. Otherwise, if we haven't queued any skbs * to other and its full, we will hang waiting for POLLOUT. */ - if (unix_recvq_full(other) && !sock_flag(other, SOCK_DEAD)) + if (unix_recvq_full_lockless(other) && !sock_flag(other, SOCK_DEAD)) return 1; if (connected) -- cgit From aa0d5f095093610e7274591d41a28381f60467a8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sun, 5 Jun 2022 17:39:04 +0200 Subject: ASoC: Intel: broadwell: Make broadwell_disable_jack() return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit broadwell_disable_jack() returns zero unconditionally. Letting it return void instead makes it easier to see in the callers that there is no error to handle. This is a preparation for making platform remove callbacks return void. Signed-off-by: Uwe Kleine-König Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220605153904.26921-1-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/intel/boards/broadwell.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index c30a9dca6801..b29d77dfb281 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -227,7 +227,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { }, }; -static int broadwell_disable_jack(struct snd_soc_card *card) +static void broadwell_disable_jack(struct snd_soc_card *card) { struct snd_soc_component *component; @@ -239,13 +239,13 @@ static int broadwell_disable_jack(struct snd_soc_card *card) break; } } - - return 0; } static int broadwell_suspend(struct snd_soc_card *card) { - return broadwell_disable_jack(card); + broadwell_disable_jack(card); + + return 0; } static int broadwell_resume(struct snd_soc_card *card){ @@ -315,7 +315,9 @@ static int broadwell_audio_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - return broadwell_disable_jack(card); + broadwell_disable_jack(card); + + return 0; } static struct platform_driver broadwell_audio = { -- cgit From 69c8027c5ff43d68449fda4510a8cce70e8578b0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 6 Jun 2022 16:25:44 +0100 Subject: ASoC: wm8731: update wlf,wm8731.yaml reference Changeset 0e336eeaf467 ("ASoC: wm8731: Convert DT bindings to YAML format") renamed: Documentation/devicetree/bindings/sound/wm8731.txt to: Documentation/devicetree/bindings/sound/wlf,wm8731.yaml. Update its cross-reference accordingly. Fixes: 0e336eeaf467 ("ASoC: wm8731: Convert DT bindings to YAML format") Signed-off-by: Mauro Carvalho Chehab Acked-by: Rob Herring Link: https://lore.kernel.org/r/e56e54fe0ebb1b6e8dd2e245c398190016eb0a34.1654529011.git.mchehab@kernel.org Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt b/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt index 0720857089a7..8facbce53db8 100644 --- a/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt +++ b/Documentation/devicetree/bindings/sound/atmel-sam9x5-wm8731-audio.txt @@ -16,7 +16,7 @@ Board connectors: * Line In Jack wm8731 pins: -cf Documentation/devicetree/bindings/sound/wm8731.txt +cf Documentation/devicetree/bindings/sound/wlf,wm8731.yaml Example: sound { -- cgit From e6f08af6340eaf88e9eeff71bd4533eee9a04119 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sun, 5 Jun 2022 17:35:37 +0200 Subject: ASoC: simple-card-utils: Make asoc_simple_clean_reference() return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit asoc_simple_clean_reference() returns zero unconditionally. Letting it return void instead makes it easier to see in the caller that there is no error to handle. This is a preparation for making platform remove callbacks return void. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20220605153537.26591-1-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 2 +- sound/soc/generic/simple-card-utils.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 8faa649f712b..fe2337fde1f4 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -173,7 +173,7 @@ void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platfo void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link_component *cpus, int is_single_links); -int asoc_simple_clean_reference(struct snd_soc_card *card); +void asoc_simple_clean_reference(struct snd_soc_card *card); void asoc_simple_convert_fixup(struct asoc_simple_data *data, struct snd_pcm_hw_params *params); diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index fa080f166345..0beda9739ebe 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -609,7 +609,7 @@ void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link_component *cpus, } EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_cpu); -int asoc_simple_clean_reference(struct snd_soc_card *card) +void asoc_simple_clean_reference(struct snd_soc_card *card) { struct snd_soc_dai_link *dai_link; struct snd_soc_dai_link_component *cpu; @@ -622,7 +622,6 @@ int asoc_simple_clean_reference(struct snd_soc_card *card) for_each_link_codecs(dai_link, j, codec) of_node_put(codec->of_node); } - return 0; } EXPORT_SYMBOL_GPL(asoc_simple_clean_reference); @@ -877,7 +876,9 @@ int asoc_simple_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - return asoc_simple_clean_reference(card); + asoc_simple_clean_reference(card); + + return 0; } EXPORT_SYMBOL_GPL(asoc_simple_remove); -- cgit From efe2178d1a32492f99e7f1f2568eea5c88a85729 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Fri, 3 Jun 2022 16:42:41 +0400 Subject: ASoC: mediatek: mt8173-rt5650: Fix refcount leak in mt8173_rt5650_dev_probe of_parse_phandle() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Fix refcount leak in some error paths. Fixes: 0f83f9296d5c ("ASoC: mediatek: Add machine driver for ALC5650 codec") Signed-off-by: Miaoqian Lin Link: https://lore.kernel.org/r/20220603124243.31358-1-linmq006@gmail.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-rt5650.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-rt5650.c b/sound/soc/mediatek/mt8173/mt8173-rt5650.c index d1c94acb4516..e05f2b0231fe 100644 --- a/sound/soc/mediatek/mt8173/mt8173-rt5650.c +++ b/sound/soc/mediatek/mt8173/mt8173-rt5650.c @@ -280,7 +280,8 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) if (!mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); - return -EINVAL; + ret = -EINVAL; + goto put_platform_node; } mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node = mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node; @@ -293,7 +294,7 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) dev_err(&pdev->dev, "%s codec_capture_dai name fail %d\n", __func__, ret); - return ret; + goto put_platform_node; } mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[1].dai_name = codec_capture_dai; @@ -315,12 +316,14 @@ static int mt8173_rt5650_dev_probe(struct platform_device *pdev) if (!mt8173_rt5650_dais[DAI_LINK_HDMI_I2S].codecs->of_node) { dev_err(&pdev->dev, "Property 'audio-codec' missing or invalid\n"); - return -EINVAL; + ret = -EINVAL; + goto put_platform_node; } card->dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, card); +put_platform_node: of_node_put(platform_node); return ret; } -- cgit From cf67838c4422eab826679b076dad99f96152b4de Mon Sep 17 00:00:00 2001 From: Lina Wang Date: Mon, 6 Jun 2022 14:45:17 +0800 Subject: selftests net: fix bpf build error bpf_helpers.h has been moved to tools/lib/bpf since 5.10, so add more including path. Fixes: edae34a3ed92 ("selftests net: add UDP GRO fraglist + bpf self-tests") Reported-by: kernel test robot Signed-off-by: Lina Wang Acked-by: Song Liu Acked-by: Paolo Abeni Link: https://lore.kernel.org/r/20220606064517.8175-1-lina.wang@mediatek.com Signed-off-by: Paolo Abeni --- tools/testing/selftests/net/bpf/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/net/bpf/Makefile b/tools/testing/selftests/net/bpf/Makefile index f91bf14bbee7..8a69c91fcca0 100644 --- a/tools/testing/selftests/net/bpf/Makefile +++ b/tools/testing/selftests/net/bpf/Makefile @@ -2,6 +2,7 @@ CLANG ?= clang CCINCLUDE += -I../../bpf +CCINCLUDE += -I../../../lib CCINCLUDE += -I../../../../../usr/include/ TEST_CUSTOM_PROGS = $(OUTPUT)/bpf/nat6to4.o @@ -10,5 +11,4 @@ all: $(TEST_CUSTOM_PROGS) $(OUTPUT)/%.o: %.c $(CLANG) -O2 -target bpf -c $< $(CCINCLUDE) -o $@ -clean: - rm -f $(TEST_CUSTOM_PROGS) +EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) -- cgit From e8bc2427018826e02add7b0ed0fc625a60390ae5 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Wed, 1 Jun 2022 03:43:28 +0200 Subject: KVM: Don't null dereference ops->destroy A KVM device cleanup happens in either of two callbacks: 1) destroy() which is called when the VM is being destroyed; 2) release() which is called when a device fd is closed. Most KVM devices use 1) but Book3s's interrupt controller KVM devices (XICS, XIVE, XIVE-native) use 2) as they need to close and reopen during the machine execution. The error handling in kvm_ioctl_create_device() assumes destroy() is always defined which leads to NULL dereference as discovered by Syzkaller. This adds a checks for destroy!=NULL and adds a missing release(). This is not changing kvm_destroy_devices() as devices with defined release() should have been removed from the KVM devices list by then. Suggested-by: Paolo Bonzini Signed-off-by: Alexey Kardashevskiy Signed-off-by: Paolo Bonzini --- virt/kvm/kvm_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 342043b30125..f2922ba3b7a8 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -4300,8 +4300,11 @@ static int kvm_ioctl_create_device(struct kvm *kvm, kvm_put_kvm_no_destroy(kvm); mutex_lock(&kvm->lock); list_del(&dev->vm_node); + if (ops->release) + ops->release(dev); mutex_unlock(&kvm->lock); - ops->destroy(dev); + if (ops->destroy) + ops->destroy(dev); return ret; } -- cgit From 3e684903a8574ffc9475fdf13c4780a7adb506ad Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Wed, 4 May 2022 13:08:40 -0500 Subject: entry/kvm: Exit to user mode when TIF_NOTIFY_SIGNAL is set A livepatch transition may stall indefinitely when a kvm vCPU is heavily loaded. To the host, the vCPU task is a user thread which is spending a very long time in the ioctl(KVM_RUN) syscall. During livepatch transition, set_notify_signal() will be called on such tasks to interrupt the syscall so that the task can be transitioned. This interrupts guest execution, but when xfer_to_guest_mode_work() sees that TIF_NOTIFY_SIGNAL is set but not TIF_SIGPENDING it concludes that an exit to user mode is unnecessary, and guest execution is resumed without transitioning the task for the livepatch. This handling of TIF_NOTIFY_SIGNAL is incorrect, as set_notify_signal() is expected to break tasks out of interruptible kernel loops and cause them to return to userspace. Change xfer_to_guest_mode_work() to handle TIF_NOTIFY_SIGNAL the same as TIF_SIGPENDING, signaling to the vCPU run loop that an exit to userpsace is needed. Any pending task_work will be run when get_signal() is called from exit_to_user_mode_loop(), so there is no longer any need to run task work from xfer_to_guest_mode_work(). Suggested-by: "Eric W. Biederman" Cc: Petr Mladek Signed-off-by: Seth Forshee Message-Id: <20220504180840.2907296-1-sforshee@digitalocean.com> Signed-off-by: Paolo Bonzini --- kernel/entry/kvm.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/kernel/entry/kvm.c b/kernel/entry/kvm.c index 9d09f489b60e..2e0f75bcb7fd 100644 --- a/kernel/entry/kvm.c +++ b/kernel/entry/kvm.c @@ -9,12 +9,6 @@ static int xfer_to_guest_mode_work(struct kvm_vcpu *vcpu, unsigned long ti_work) int ret; if (ti_work & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) { - clear_notify_signal(); - if (task_work_pending(current)) - task_work_run(); - } - - if (ti_work & _TIF_SIGPENDING) { kvm_handle_signal_exit(vcpu); return -EINTR; } -- cgit From cf4a8693d97a51dccf5a1557248d12d6d8be4b9e Mon Sep 17 00:00:00 2001 From: Shaoqin Huang Date: Mon, 6 Jun 2022 18:59:05 -0600 Subject: KVM: x86/mmu: Check every prev_roots in __kvm_mmu_free_obsolete_roots() When freeing obsolete previous roots, check prev_roots as intended, not the current root. Signed-off-by: Shaoqin Huang Fixes: 527d5cd7eece ("KVM: x86/mmu: Zap only obsolete roots if a root shadow page is zapped") Message-Id: <20220607005905.2933378-1-shaoqin.huang@intel.com> Cc: stable@vger.kernel.org Reviewed-by: Sean Christopherson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index efe5a3dca1e0..e46771e95191 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -5179,7 +5179,7 @@ static void __kvm_mmu_free_obsolete_roots(struct kvm *kvm, struct kvm_mmu *mmu) roots_to_free |= KVM_MMU_ROOT_CURRENT; for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++) { - if (is_obsolete_root(kvm, mmu->root.hpa)) + if (is_obsolete_root(kvm, mmu->prev_roots[i].hpa)) roots_to_free |= KVM_MMU_ROOT_PREVIOUS(i); } -- cgit From 1df931d95f4dc1c11db1123e85d4e08156e46ef9 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 7 Jun 2022 17:00:53 +0200 Subject: x86: drop bogus "cc" clobber from __try_cmpxchg_user_asm() As noted (and fixed) a couple of times in the past, "=@cc" outputs and clobbering of "cc" don't work well together. The compiler appears to mean to reject such, but doesn't - in its upstream form - quite manage to yet for "cc". Furthermore two similar macros don't clobber "cc", and clobbering "cc" is pointless in asm()-s for x86 anyway - the compiler always assumes status flags to be clobbered there. Fixes: 989b5db215a2 ("x86/uaccess: Implement macros for CMPXCHG on user addresses") Signed-off-by: Jan Beulich Message-Id: <485c0c0b-a3a7-0b7c-5264-7d00c01de032@suse.com> Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 35f222aa66bf..913e593a3b45 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -439,7 +439,7 @@ do { \ [ptr] "+m" (*_ptr), \ [old] "+a" (__old) \ : [new] ltype (__new) \ - : "memory", "cc"); \ + : "memory"); \ if (unlikely(__err)) \ goto label; \ if (unlikely(!success)) \ -- cgit From 5ba7c4c6d1c7af47a916f728bb5940669684a087 Mon Sep 17 00:00:00 2001 From: Ben Gardon Date: Wed, 25 May 2022 23:09:04 +0000 Subject: KVM: x86/MMU: Zap non-leaf SPTEs when disabling dirty logging Currently disabling dirty logging with the TDP MMU is extremely slow. On a 96 vCPU / 96G VM backed with gigabyte pages, it takes ~200 seconds to disable dirty logging with the TDP MMU, as opposed to ~4 seconds with the shadow MMU. When disabling dirty logging, zap non-leaf parent entries to allow replacement with huge pages instead of recursing and zapping all of the child, leaf entries. This reduces the number of TLB flushes required. and reduces the disable dirty log time with the TDP MMU to ~3 seconds. Opportunistically add a WARN() to catch GFNs that are mapped at a higher level than their max level. Signed-off-by: Ben Gardon Message-Id: <20220525230904.1584480-1-bgardon@google.com> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu/tdp_iter.c | 9 +++++++++ arch/x86/kvm/mmu/tdp_iter.h | 1 + arch/x86/kvm/mmu/tdp_mmu.c | 38 ++++++++++++++++++++++++++++++++------ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/mmu/tdp_iter.c b/arch/x86/kvm/mmu/tdp_iter.c index 6d3b3e5a5533..ee4802d7b36c 100644 --- a/arch/x86/kvm/mmu/tdp_iter.c +++ b/arch/x86/kvm/mmu/tdp_iter.c @@ -145,6 +145,15 @@ static bool try_step_up(struct tdp_iter *iter) return true; } +/* + * Step the iterator back up a level in the paging structure. Should only be + * used when the iterator is below the root level. + */ +void tdp_iter_step_up(struct tdp_iter *iter) +{ + WARN_ON(!try_step_up(iter)); +} + /* * Step to the next SPTE in a pre-order traversal of the paging structure. * To get to the next SPTE, the iterator either steps down towards the goal diff --git a/arch/x86/kvm/mmu/tdp_iter.h b/arch/x86/kvm/mmu/tdp_iter.h index f0af385c56e0..adfca0cf94d3 100644 --- a/arch/x86/kvm/mmu/tdp_iter.h +++ b/arch/x86/kvm/mmu/tdp_iter.h @@ -114,5 +114,6 @@ void tdp_iter_start(struct tdp_iter *iter, struct kvm_mmu_page *root, int min_level, gfn_t next_last_level_gfn); void tdp_iter_next(struct tdp_iter *iter); void tdp_iter_restart(struct tdp_iter *iter); +void tdp_iter_step_up(struct tdp_iter *iter); #endif /* __KVM_X86_MMU_TDP_ITER_H */ diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index 841feaa48be5..7b9265d67131 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -1742,12 +1742,12 @@ static void zap_collapsible_spte_range(struct kvm *kvm, gfn_t start = slot->base_gfn; gfn_t end = start + slot->npages; struct tdp_iter iter; + int max_mapping_level; kvm_pfn_t pfn; rcu_read_lock(); tdp_root_for_each_pte(iter, root, start, end) { -retry: if (tdp_mmu_iter_cond_resched(kvm, &iter, false, true)) continue; @@ -1755,15 +1755,41 @@ retry: !is_last_spte(iter.old_spte, iter.level)) continue; + /* + * This is a leaf SPTE. Check if the PFN it maps can + * be mapped at a higher level. + */ pfn = spte_to_pfn(iter.old_spte); - if (kvm_is_reserved_pfn(pfn) || - iter.level >= kvm_mmu_max_mapping_level(kvm, slot, iter.gfn, - pfn, PG_LEVEL_NUM)) + + if (kvm_is_reserved_pfn(pfn)) continue; + max_mapping_level = kvm_mmu_max_mapping_level(kvm, slot, + iter.gfn, pfn, PG_LEVEL_NUM); + + WARN_ON(max_mapping_level < iter.level); + + /* + * If this page is already mapped at the highest + * viable level, there's nothing more to do. + */ + if (max_mapping_level == iter.level) + continue; + + /* + * The page can be remapped at a higher level, so step + * up to zap the parent SPTE. + */ + while (max_mapping_level > iter.level) + tdp_iter_step_up(&iter); + /* Note, a successful atomic zap also does a remote TLB flush. */ - if (tdp_mmu_zap_spte_atomic(kvm, &iter)) - goto retry; + tdp_mmu_zap_spte_atomic(kvm, &iter); + + /* + * If the atomic zap fails, the iter will recurse back into + * the same subtree to retry. + */ } rcu_read_unlock(); -- cgit From eae260be3a0111a28fe95923e117a55dddec0384 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Wed, 1 Jun 2022 16:43:22 +0200 Subject: KVM: selftests: Make hyperv_clock selftest more stable hyperv_clock doesn't always give a stable test result, especially with AMD CPUs. The test compares Hyper-V MSR clocksource (acquired either with rdmsr() from within the guest or KVM_GET_MSRS from the host) against rdtsc(). To increase the accuracy, increase the measured delay (done with nop loop) by two orders of magnitude and take the mean rdtsc() value before and after rdmsr()/KVM_GET_MSRS. Reported-by: Maxim Levitsky Signed-off-by: Vitaly Kuznetsov Reviewed-by: Maxim Levitsky Tested-by: Maxim Levitsky Message-Id: <20220601144322.1968742-1-vkuznets@redhat.com> Signed-off-by: Paolo Bonzini --- tools/testing/selftests/kvm/x86_64/hyperv_clock.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_clock.c b/tools/testing/selftests/kvm/x86_64/hyperv_clock.c index e0b2bb1339b1..3330fb183c68 100644 --- a/tools/testing/selftests/kvm/x86_64/hyperv_clock.c +++ b/tools/testing/selftests/kvm/x86_64/hyperv_clock.c @@ -44,7 +44,7 @@ static inline void nop_loop(void) { int i; - for (i = 0; i < 1000000; i++) + for (i = 0; i < 100000000; i++) asm volatile("nop"); } @@ -56,12 +56,14 @@ static inline void check_tsc_msr_rdtsc(void) tsc_freq = rdmsr(HV_X64_MSR_TSC_FREQUENCY); GUEST_ASSERT(tsc_freq > 0); - /* First, check MSR-based clocksource */ + /* For increased accuracy, take mean rdtsc() before and afrer rdmsr() */ r1 = rdtsc(); t1 = rdmsr(HV_X64_MSR_TIME_REF_COUNT); + r1 = (r1 + rdtsc()) / 2; nop_loop(); r2 = rdtsc(); t2 = rdmsr(HV_X64_MSR_TIME_REF_COUNT); + r2 = (r2 + rdtsc()) / 2; GUEST_ASSERT(r2 > r1 && t2 > t1); @@ -181,12 +183,14 @@ static void host_check_tsc_msr_rdtsc(struct kvm_vm *vm) tsc_freq = vcpu_get_msr(vm, VCPU_ID, HV_X64_MSR_TSC_FREQUENCY); TEST_ASSERT(tsc_freq > 0, "TSC frequency must be nonzero"); - /* First, check MSR-based clocksource */ + /* For increased accuracy, take mean rdtsc() before and afrer ioctl */ r1 = rdtsc(); t1 = vcpu_get_msr(vm, VCPU_ID, HV_X64_MSR_TIME_REF_COUNT); + r1 = (r1 + rdtsc()) / 2; nop_loop(); r2 = rdtsc(); t2 = vcpu_get_msr(vm, VCPU_ID, HV_X64_MSR_TIME_REF_COUNT); + r2 = (r2 + rdtsc()) / 2; TEST_ASSERT(t2 > t1, "Time reference MSR is not monotonic (%ld <= %ld)", t1, t2); -- cgit From 11d39e8cc43e1c6737af19ca9372e590061b5ad2 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Mon, 6 Jun 2022 21:11:49 +0300 Subject: KVM: SVM: fix tsc scaling cache logic SVM uses a per-cpu variable to cache the current value of the tsc scaling multiplier msr on each cpu. Commit 1ab9287add5e2 ("KVM: X86: Add vendor callbacks for writing the TSC multiplier") broke this caching logic. Refactor the code so that all TSC scaling multiplier writes go through a single function which checks and updates the cache. This fixes the following scenario: 1. A CPU runs a guest with some tsc scaling ratio. 2. New guest with different tsc scaling ratio starts on this CPU and terminates almost immediately. This ensures that the short running guest had set the tsc scaling ratio just once when it was set via KVM_SET_TSC_KHZ. Due to the bug, the per-cpu cache is not updated. 3. The original guest continues to run, it doesn't restore the msr value back to its own value, because the cache matches, and thus continues to run with a wrong tsc scaling ratio. Fixes: 1ab9287add5e2 ("KVM: X86: Add vendor callbacks for writing the TSC multiplier") Signed-off-by: Maxim Levitsky Message-Id: <20220606181149.103072-1-mlevitsk@redhat.com> Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm/nested.c | 4 ++-- arch/x86/kvm/svm/svm.c | 32 ++++++++++++++++++++------------ arch/x86/kvm/svm/svm.h | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index bed5e1692cef..3361258640a2 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -982,7 +982,7 @@ int nested_svm_vmexit(struct vcpu_svm *svm) if (svm->tsc_ratio_msr != kvm_default_tsc_scaling_ratio) { WARN_ON(!svm->tsc_scaling_enabled); vcpu->arch.tsc_scaling_ratio = vcpu->arch.l1_tsc_scaling_ratio; - svm_write_tsc_multiplier(vcpu, vcpu->arch.tsc_scaling_ratio); + __svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio); } svm->nested.ctl.nested_cr3 = 0; @@ -1387,7 +1387,7 @@ void nested_svm_update_tsc_ratio_msr(struct kvm_vcpu *vcpu) vcpu->arch.tsc_scaling_ratio = kvm_calc_nested_tsc_multiplier(vcpu->arch.l1_tsc_scaling_ratio, svm->tsc_ratio_msr); - svm_write_tsc_multiplier(vcpu, vcpu->arch.tsc_scaling_ratio); + __svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio); } /* Inverse operation of nested_copy_vmcb_control_to_cache(). asid is copied too. */ diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 63880b33ce37..478e6ee81d88 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -465,11 +465,24 @@ static int has_svm(void) return 1; } +void __svm_write_tsc_multiplier(u64 multiplier) +{ + preempt_disable(); + + if (multiplier == __this_cpu_read(current_tsc_ratio)) + goto out; + + wrmsrl(MSR_AMD64_TSC_RATIO, multiplier); + __this_cpu_write(current_tsc_ratio, multiplier); +out: + preempt_enable(); +} + static void svm_hardware_disable(void) { /* Make sure we clean up behind us */ if (tsc_scaling) - wrmsrl(MSR_AMD64_TSC_RATIO, SVM_TSC_RATIO_DEFAULT); + __svm_write_tsc_multiplier(SVM_TSC_RATIO_DEFAULT); cpu_svm_disable(); @@ -515,8 +528,7 @@ static int svm_hardware_enable(void) * Set the default value, even if we don't use TSC scaling * to avoid having stale value in the msr */ - wrmsrl(MSR_AMD64_TSC_RATIO, SVM_TSC_RATIO_DEFAULT); - __this_cpu_write(current_tsc_ratio, SVM_TSC_RATIO_DEFAULT); + __svm_write_tsc_multiplier(SVM_TSC_RATIO_DEFAULT); } @@ -999,11 +1011,12 @@ static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) vmcb_mark_dirty(svm->vmcb, VMCB_INTERCEPTS); } -void svm_write_tsc_multiplier(struct kvm_vcpu *vcpu, u64 multiplier) +static void svm_write_tsc_multiplier(struct kvm_vcpu *vcpu, u64 multiplier) { - wrmsrl(MSR_AMD64_TSC_RATIO, multiplier); + __svm_write_tsc_multiplier(multiplier); } + /* Evaluate instruction intercepts that depend on guest CPUID features. */ static void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu, struct vcpu_svm *svm) @@ -1363,13 +1376,8 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu) sev_es_prepare_switch_to_guest(hostsa); } - if (tsc_scaling) { - u64 tsc_ratio = vcpu->arch.tsc_scaling_ratio; - if (tsc_ratio != __this_cpu_read(current_tsc_ratio)) { - __this_cpu_write(current_tsc_ratio, tsc_ratio); - wrmsrl(MSR_AMD64_TSC_RATIO, tsc_ratio); - } - } + if (tsc_scaling) + __svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio); if (likely(tsc_aux_uret_slot >= 0)) kvm_set_user_return_msr(tsc_aux_uret_slot, svm->tsc_aux, -1ull); diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 45a87b2a8b3c..29d6fd205a49 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -590,7 +590,7 @@ int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, bool has_error_code, u32 error_code); int nested_svm_exit_special(struct vcpu_svm *svm); void nested_svm_update_tsc_ratio_msr(struct kvm_vcpu *vcpu); -void svm_write_tsc_multiplier(struct kvm_vcpu *vcpu, u64 multiplier); +void __svm_write_tsc_multiplier(u64 multiplier); void nested_copy_vmcb_control_to_cache(struct vcpu_svm *svm, struct vmcb_control_area *control); void nested_copy_vmcb_save_to_cache(struct vcpu_svm *svm, -- cgit From c3c09e393a5e25fb2fd30b62f3c689e92b4343c4 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 6 Jun 2022 16:22:30 -0500 Subject: dt-bindings: nvme: apple,nvme-ans: Drop 'maxItems' from 'apple,sart' A 'phandle' type is always a single cell, so 'maxItems: 1' is redundant. Fixes: 82b96552f15a ("dt-bindings: nvme: Add Apple ANS NVMe") Signed-off-by: Rob Herring Reviewed-by: Sven Peter Link: https://lore.kernel.org/r/20220606212230.1360617-1-robh@kernel.org --- Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml b/Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml index ddff9233b159..34dd1cc67124 100644 --- a/Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml +++ b/Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml @@ -55,7 +55,6 @@ properties: maxItems: 1 apple,sart: - maxItems: 1 $ref: /schemas/types.yaml#/definitions/phandle description: | Reference to the SART address filter. -- cgit From 927c63e07810fe41cc0428d767ea4b59db193b80 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 6 Jun 2022 17:51:36 -0500 Subject: dt-bindings: Drop more redundant 'maxItems/minItems' in if/then schemas Another round from new cases in 5.19-rc of removing redundant minItems/maxItems when 'items' list is specified. This time it is in if/then schemas as the meta-schema was failing to check this case. If a property has an 'items' list, then a 'minItems' or 'maxItems' with the same size as the list is redundant and can be dropped. Note that is DT schema specific behavior and not standard json-schema behavior. The tooling will fixup the final schema adding any unspecified minItems/maxItems. Signed-off-by: Rob Herring Acked-by: Guenter Roeck Reviewed-by: Krzysztof Kozlowski Acked-by: Ulf Hansson Link: https://lore.kernel.org/r/20220606225137.1536010-1-robh@kernel.org --- .../devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml | 3 --- Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml | 1 - .../devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml | 1 - 3 files changed, 5 deletions(-) diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml index c7cfa6c2cd81..935d63d181d9 100644 --- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml +++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra186-mc.yaml @@ -150,7 +150,6 @@ allOf: description: 5 memory controller channels and 1 for stream-id registers reg-names: - maxItems: 6 items: - const: sid - const: broadcast @@ -170,7 +169,6 @@ allOf: description: 17 memory controller channels and 1 for stream-id registers reg-names: - minItems: 18 items: - const: sid - const: broadcast @@ -202,7 +200,6 @@ allOf: description: 17 memory controller channels and 1 for stream-id registers reg-names: - minItems: 18 items: - const: sid - const: broadcast diff --git a/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml b/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml index c79639e9027e..7a2b22dd6d05 100644 --- a/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.yaml @@ -145,7 +145,6 @@ allOf: items: - description: Xenon IP registers - description: Armada 3700 SoC PHY PAD Voltage Control register - minItems: 2 marvell,pad-type: $ref: /schemas/types.yaml#/definitions/string diff --git a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml index cbcf19f51411..ed6c1ca80dcc 100644 --- a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml @@ -64,7 +64,6 @@ if: then: properties: clocks: - minItems: 2 items: - description: High-frequency oscillator input, divided internally - description: Low-frequency oscillator input -- cgit From 7bf179de5b2dfae54a6839eaf7caba44a888ee2e Mon Sep 17 00:00:00 2001 From: Kevin Locke Date: Mon, 6 Jun 2022 20:42:54 -0600 Subject: kbuild: avoid regex RS for POSIX awk In 22f26f21774f8 awk was added to deduplicate *.mod files. The awk invocation passes -v RS='( |\n)' to match a space or newline character as the record separator. Unfortunately, POSIX states[1] > If RS contains more than one character, the results are unspecified. Some implementations (such as the One True Awk[2] used by the BSDs) do not treat RS as a regular expression. When awk does not support regex RS, build failures such as the following are produced (first error using allmodconfig): CC [M] arch/x86/events/intel/uncore.o CC [M] arch/x86/events/intel/uncore_nhmex.o CC [M] arch/x86/events/intel/uncore_snb.o CC [M] arch/x86/events/intel/uncore_snbep.o CC [M] arch/x86/events/intel/uncore_discovery.o LD [M] arch/x86/events/intel/intel-uncore.o ld: cannot find uncore_nhmex.o: No such file or directory ld: cannot find uncore_snb.o: No such file or directory ld: cannot find uncore_snbep.o: No such file or directory ld: cannot find uncore_discovery.o: No such file or directory make[3]: *** [scripts/Makefile.build:422: arch/x86/events/intel/intel-uncore.o] Error 1 make[2]: *** [scripts/Makefile.build:487: arch/x86/events/intel] Error 2 make[1]: *** [scripts/Makefile.build:487: arch/x86/events] Error 2 make: *** [Makefile:1839: arch/x86] Error 2 To avoid this, use printf(1) to produce a newline between each object path, instead of the space produced by echo(1), so that the default RS can be used by awk. [1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html [2]: https://github.com/onetrueawk/awk Fixes: 22f26f21774f ("kbuild: get rid of duplication in *.mod files") Signed-off-by: Kevin Locke Signed-off-by: Masahiro Yamada --- scripts/Makefile.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 1f01ac65c0cd..cac070aee791 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -251,8 +251,8 @@ $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE # To make this rule robust against "Argument list too long" error, # ensure to add $(obj)/ prefix by a shell command. -cmd_mod = echo $(call real-search, $*.o, .o, -objs -y -m) | \ - $(AWK) -v RS='( |\n)' '!x[$$0]++ { print("$(obj)/"$$0) }' > $@ +cmd_mod = printf '%s\n' $(call real-search, $*.o, .o, -objs -y -m) | \ + $(AWK) '!x[$$0]++ { print("$(obj)/"$$0) }' > $@ $(obj)/%.mod: FORCE $(call if_changed,mod) -- cgit From c4f135d643823a869becfa87539f7820ef9d5bfa Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Wed, 1 Jun 2022 16:32:47 +0900 Subject: workqueue: Wrap flush_workqueue() using a macro Since flush operation synchronously waits for completion, flushing system-wide WQs (e.g. system_wq) might introduce possibility of deadlock due to unexpected locking dependency. Tejun Heo commented at [1] that it makes no sense at all to call flush_workqueue() on the shared WQs as the caller has no idea what it's gonna end up waiting for. Although there is flush_scheduled_work() which flushes system_wq WQ with "Think twice before calling this function! It's very easy to get into trouble if you don't take great care." warning message, syzbot found a circular locking dependency caused by flushing system_wq WQ [2]. Therefore, let's change the direction to that developers had better use their local WQs if flush_scheduled_work()/flush_workqueue(system_*_wq) is inevitable. Steps for converting system-wide WQs into local WQs are explained at [3], and a conversion to stop flushing system-wide WQs is in progress. Now we want some mechanism for preventing developers who are not aware of this conversion from again start flushing system-wide WQs. Since I found that WARN_ON() is complete but awkward approach for teaching developers about this problem, let's use __compiletime_warning() for incomplete but handy approach. For completeness, we will also insert WARN_ON() into __flush_workqueue() after all in-tree users stopped calling flush_scheduled_work(). Link: https://lore.kernel.org/all/YgnQGZWT%2Fn3VAITX@slm.duckdns.org/ [1] Link: https://syzkaller.appspot.com/bug?extid=bde0f89deacca7c765b8 [2] Link: https://lkml.kernel.org/r/49925af7-78a8-a3dd-bce6-cfc02e1a9236@I-love.SAKURA.ne.jp [3] Signed-off-by: Tetsuo Handa Signed-off-by: Tejun Heo --- include/linux/workqueue.h | 64 +++++++++++++++++++++++++++++++++++++++++------ kernel/workqueue.c | 16 +++++++++--- 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 7fee9b6cfede..e1f1c8b1121b 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -445,7 +445,7 @@ extern bool mod_delayed_work_on(int cpu, struct workqueue_struct *wq, struct delayed_work *dwork, unsigned long delay); extern bool queue_rcu_work(struct workqueue_struct *wq, struct rcu_work *rwork); -extern void flush_workqueue(struct workqueue_struct *wq); +extern void __flush_workqueue(struct workqueue_struct *wq); extern void drain_workqueue(struct workqueue_struct *wq); extern int schedule_on_each_cpu(work_func_t func); @@ -563,15 +563,23 @@ static inline bool schedule_work(struct work_struct *work) return queue_work(system_wq, work); } +/* + * Detect attempt to flush system-wide workqueues at compile time when possible. + * + * See https://lkml.kernel.org/r/49925af7-78a8-a3dd-bce6-cfc02e1a9236@I-love.SAKURA.ne.jp + * for reasons and steps for converting system-wide workqueues into local workqueues. + */ +extern void __warn_flushing_systemwide_wq(void) + __compiletime_warning("Please avoid flushing system-wide workqueues."); + /** * flush_scheduled_work - ensure that any scheduled work has run to completion. * * Forces execution of the kernel-global workqueue and blocks until its * completion. * - * Think twice before calling this function! It's very easy to get into - * trouble if you don't take great care. Either of the following situations - * will lead to deadlock: + * It's very easy to get into trouble if you don't take great care. + * Either of the following situations will lead to deadlock: * * One of the work items currently on the workqueue needs to acquire * a lock held by your code or its caller. @@ -586,11 +594,51 @@ static inline bool schedule_work(struct work_struct *work) * need to know that a particular work item isn't queued and isn't running. * In such cases you should use cancel_delayed_work_sync() or * cancel_work_sync() instead. + * + * Please stop calling this function! A conversion to stop flushing system-wide + * workqueues is in progress. This function will be removed after all in-tree + * users stopped calling this function. */ -static inline void flush_scheduled_work(void) -{ - flush_workqueue(system_wq); -} +/* + * The background of commit 771c035372a036f8 ("deprecate the + * '__deprecated' attribute warnings entirely and for good") is that, + * since Linus builds all modules between every single pull he does, + * the standard kernel build needs to be _clean_ in order to be able to + * notice when new problems happen. Therefore, don't emit warning while + * there are in-tree users. + */ +#define flush_scheduled_work() \ +({ \ + if (0) \ + __warn_flushing_systemwide_wq(); \ + __flush_workqueue(system_wq); \ +}) + +/* + * Although there is no longer in-tree caller, for now just emit warning + * in order to give out-of-tree callers time to update. + */ +#define flush_workqueue(wq) \ +({ \ + struct workqueue_struct *_wq = (wq); \ + \ + if ((__builtin_constant_p(_wq == system_wq) && \ + _wq == system_wq) || \ + (__builtin_constant_p(_wq == system_highpri_wq) && \ + _wq == system_highpri_wq) || \ + (__builtin_constant_p(_wq == system_long_wq) && \ + _wq == system_long_wq) || \ + (__builtin_constant_p(_wq == system_unbound_wq) && \ + _wq == system_unbound_wq) || \ + (__builtin_constant_p(_wq == system_freezable_wq) && \ + _wq == system_freezable_wq) || \ + (__builtin_constant_p(_wq == system_power_efficient_wq) && \ + _wq == system_power_efficient_wq) || \ + (__builtin_constant_p(_wq == system_freezable_power_efficient_wq) && \ + _wq == system_freezable_power_efficient_wq)) \ + __warn_flushing_systemwide_wq(); \ + __flush_workqueue(_wq); \ +}) /** * schedule_delayed_work_on - queue work in global workqueue on CPU after delay diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 4056f2a3f9d5..1ea50f6be843 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -2788,13 +2788,13 @@ static bool flush_workqueue_prep_pwqs(struct workqueue_struct *wq, } /** - * flush_workqueue - ensure that any scheduled work has run to completion. + * __flush_workqueue - ensure that any scheduled work has run to completion. * @wq: workqueue to flush * * This function sleeps until all work items which were queued on entry * have finished execution, but it is not livelocked by new incoming ones. */ -void flush_workqueue(struct workqueue_struct *wq) +void __flush_workqueue(struct workqueue_struct *wq) { struct wq_flusher this_flusher = { .list = LIST_HEAD_INIT(this_flusher.list), @@ -2943,7 +2943,7 @@ void flush_workqueue(struct workqueue_struct *wq) out_unlock: mutex_unlock(&wq->mutex); } -EXPORT_SYMBOL(flush_workqueue); +EXPORT_SYMBOL(__flush_workqueue); /** * drain_workqueue - drain a workqueue @@ -2971,7 +2971,7 @@ void drain_workqueue(struct workqueue_struct *wq) wq->flags |= __WQ_DRAINING; mutex_unlock(&wq->mutex); reflush: - flush_workqueue(wq); + __flush_workqueue(wq); mutex_lock(&wq->mutex); @@ -6111,3 +6111,11 @@ void __init workqueue_init(void) wq_online = true; wq_watchdog_init(); } + +/* + * Despite the naming, this is a no-op function which is here only for avoiding + * link error. Since compile-time warning may fail to catch, we will need to + * emit run-time warning from __flush_workqueue(). + */ +void __warn_flushing_systemwide_wq(void) { } +EXPORT_SYMBOL(__warn_flushing_systemwide_wq); -- cgit From 873a400938b31a1e443c4d94b560b78300787540 Mon Sep 17 00:00:00 2001 From: Wonhyuk Yang Date: Wed, 4 May 2022 11:32:03 +0900 Subject: workqueue: Fix type of cpu in trace event The trace event "workqueue_queue_work" use unsigned int type for req_cpu, cpu. This casue confusing cpu number like below log. $ cat /sys/kernel/debug/tracing/trace cat-317 [001] ...: workqueue_queue_work: ... req_cpu=8192 cpu=4294967295 So, change unsigned type to signed type in the trace event. After applying this patch, cpu number will be printed as -1 instead of 4294967295 as folllows. $ cat /sys/kernel/debug/tracing/trace cat-1338 [002] ...: workqueue_queue_work: ... req_cpu=8192 cpu=-1 Cc: Baik Song An Cc: Hong Yeon Kim Cc: Taeung Song Cc: linuxgeek@linuxgeek.io Signed-off-by: Wonhyuk Yang Signed-off-by: Tejun Heo --- include/trace/events/workqueue.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/trace/events/workqueue.h b/include/trace/events/workqueue.h index 6154a2e72bce..262d52021c23 100644 --- a/include/trace/events/workqueue.h +++ b/include/trace/events/workqueue.h @@ -22,7 +22,7 @@ struct pool_workqueue; */ TRACE_EVENT(workqueue_queue_work, - TP_PROTO(unsigned int req_cpu, struct pool_workqueue *pwq, + TP_PROTO(int req_cpu, struct pool_workqueue *pwq, struct work_struct *work), TP_ARGS(req_cpu, pwq, work), @@ -31,8 +31,8 @@ TRACE_EVENT(workqueue_queue_work, __field( void *, work ) __field( void *, function) __string( workqueue, pwq->wq->name) - __field( unsigned int, req_cpu ) - __field( unsigned int, cpu ) + __field( int, req_cpu ) + __field( int, cpu ) ), TP_fast_assign( @@ -43,7 +43,7 @@ TRACE_EVENT(workqueue_queue_work, __entry->cpu = pwq->pool->cpu; ), - TP_printk("work struct=%p function=%ps workqueue=%s req_cpu=%u cpu=%u", + TP_printk("work struct=%p function=%ps workqueue=%s req_cpu=%d cpu=%d", __entry->work, __entry->function, __get_str(workqueue), __entry->req_cpu, __entry->cpu) ); -- cgit From 10f3b29c65bb2fe0d47c2945cd0b4087be1c5218 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 31 May 2022 14:51:13 -0700 Subject: bpf, arm64: Clear prog->jited_len along prog->jited syzbot reported an illegal copy_to_user() attempt from bpf_prog_get_info_by_fd() [1] There was no repro yet on this bug, but I think that commit 0aef499f3172 ("mm/usercopy: Detect vmalloc overruns") is exposing a prior bug in bpf arm64. bpf_prog_get_info_by_fd() looks at prog->jited_len to determine if the JIT image can be copied out to user space. My theory is that syzbot managed to get a prog where prog->jited_len has been set to 43, while prog->bpf_func has ben cleared. It is not clear why copy_to_user(uinsns, NULL, ulen) is triggering this particular warning. I thought find_vma_area(NULL) would not find a vm_struct. As we do not hold vmap_area_lock spinlock, it might be possible that the found vm_struct was garbage. [1] usercopy: Kernel memory exposure attempt detected from vmalloc (offset 792633534417210172, size 43)! kernel BUG at mm/usercopy.c:101! Internal error: Oops - BUG: 0 [#1] PREEMPT SMP Modules linked in: CPU: 0 PID: 25002 Comm: syz-executor.1 Not tainted 5.18.0-syzkaller-10139-g8291eaafed36 #0 Hardware name: linux,dummy-virt (DT) pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : usercopy_abort+0x90/0x94 mm/usercopy.c:101 lr : usercopy_abort+0x90/0x94 mm/usercopy.c:89 sp : ffff80000b773a20 x29: ffff80000b773a30 x28: faff80000b745000 x27: ffff80000b773b48 x26: 0000000000000000 x25: 000000000000002b x24: 0000000000000000 x23: 00000000000000e0 x22: ffff80000b75db67 x21: 0000000000000001 x20: 000000000000002b x19: ffff80000b75db3c x18: 00000000fffffffd x17: 2820636f6c6c616d x16: 76206d6f72662064 x15: 6574636574656420 x14: 74706d6574746120 x13: 2129333420657a69 x12: 73202c3237313031 x11: 3237313434333533 x10: 3336323937207465 x9 : 657275736f707865 x8 : ffff80000a30c550 x7 : ffff80000b773830 x6 : ffff80000b773830 x5 : 0000000000000000 x4 : ffff00007fbbaa10 x3 : 0000000000000000 x2 : 0000000000000000 x1 : f7ff000028fc0000 x0 : 0000000000000064 Call trace: usercopy_abort+0x90/0x94 mm/usercopy.c:89 check_heap_object mm/usercopy.c:186 [inline] __check_object_size mm/usercopy.c:252 [inline] __check_object_size+0x198/0x36c mm/usercopy.c:214 check_object_size include/linux/thread_info.h:199 [inline] check_copy_size include/linux/thread_info.h:235 [inline] copy_to_user include/linux/uaccess.h:159 [inline] bpf_prog_get_info_by_fd.isra.0+0xf14/0xfdc kernel/bpf/syscall.c:3993 bpf_obj_get_info_by_fd+0x12c/0x510 kernel/bpf/syscall.c:4253 __sys_bpf+0x900/0x2150 kernel/bpf/syscall.c:4956 __do_sys_bpf kernel/bpf/syscall.c:5021 [inline] __se_sys_bpf kernel/bpf/syscall.c:5019 [inline] __arm64_sys_bpf+0x28/0x40 kernel/bpf/syscall.c:5019 __invoke_syscall arch/arm64/kernel/syscall.c:38 [inline] invoke_syscall+0x48/0x114 arch/arm64/kernel/syscall.c:52 el0_svc_common.constprop.0+0x44/0xec arch/arm64/kernel/syscall.c:142 do_el0_svc+0xa0/0xc0 arch/arm64/kernel/syscall.c:206 el0_svc+0x44/0xb0 arch/arm64/kernel/entry-common.c:624 el0t_64_sync_handler+0x1ac/0x1b0 arch/arm64/kernel/entry-common.c:642 el0t_64_sync+0x198/0x19c arch/arm64/kernel/entry.S:581 Code: aa0003e3 d00038c0 91248000 97fff65f (d4210000) Fixes: db496944fdaa ("bpf: arm64: add JIT support for multi-function programs") Reported-by: syzbot Signed-off-by: Eric Dumazet Signed-off-by: Daniel Borkmann Acked-by: Song Liu Link: https://lore.kernel.org/bpf/20220531215113.1100754-1-eric.dumazet@gmail.com Signed-off-by: Alexei Starovoitov --- arch/arm64/net/bpf_jit_comp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index 8ab4035dea27..42f2e9a8616c 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -1478,6 +1478,7 @@ skip_init_ctx: bpf_jit_binary_free(header); prog->bpf_func = NULL; prog->jited = 0; + prog->jited_len = 0; goto out_off; } bpf_jit_binary_lock_ro(header); -- cgit From fd58f7df2415ef747782e01f94880fefad1247cf Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 26 May 2022 13:24:05 +0300 Subject: bpf: Use safer kvmalloc_array() where possible The kvmalloc_array() function is safer because it has a check for integer overflows. These sizes come from the user and I was not able to see any bounds checking so an integer overflow seems like a realistic concern. Fixes: 0dcac2725406 ("bpf: Add multi kprobe link") Signed-off-by: Dan Carpenter Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/Yo9VRVMeHbALyjUH@kili Signed-off-by: Alexei Starovoitov --- kernel/trace/bpf_trace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 10b157a6d73e..7a13e6ac6327 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -2263,11 +2263,11 @@ static int copy_user_syms(struct user_syms *us, unsigned long __user *usyms, u32 int err = -ENOMEM; unsigned int i; - syms = kvmalloc(cnt * sizeof(*syms), GFP_KERNEL); + syms = kvmalloc_array(cnt, sizeof(*syms), GFP_KERNEL); if (!syms) goto error; - buf = kvmalloc(cnt * KSYM_NAME_LEN, GFP_KERNEL); + buf = kvmalloc_array(cnt, KSYM_NAME_LEN, GFP_KERNEL); if (!buf) goto error; @@ -2464,7 +2464,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr return -EINVAL; size = cnt * sizeof(*addrs); - addrs = kvmalloc(size, GFP_KERNEL); + addrs = kvmalloc_array(cnt, sizeof(*addrs), GFP_KERNEL); if (!addrs) return -ENOMEM; @@ -2489,7 +2489,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr ucookies = u64_to_user_ptr(attr->link_create.kprobe_multi.cookies); if (ucookies) { - cookies = kvmalloc(size, GFP_KERNEL); + cookies = kvmalloc_array(cnt, sizeof(*addrs), GFP_KERNEL); if (!cookies) { err = -ENOMEM; goto error; -- cgit From f858c2b2ca04fc7ead291821a793638ae120c11d Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Mon, 6 Jun 2022 09:52:51 +0200 Subject: bpf: Fix calling global functions from BPF_PROG_TYPE_EXT programs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The verifier allows programs to call global functions as long as their argument types match, using BTF to check the function arguments. One of the allowed argument types to such global functions is PTR_TO_CTX; however the check for this fails on BPF_PROG_TYPE_EXT functions because the verifier uses the wrong type to fetch the vmlinux BTF ID for the program context type. This failure is seen when an XDP program is loaded using libxdp (which loads it as BPF_PROG_TYPE_EXT and attaches it to a global XDP type program). Fix the issue by passing in the target program type instead of the BPF_PROG_TYPE_EXT type to bpf_prog_get_ctx() when checking function argument compatibility. The first Fixes tag refers to the latest commit that touched the code in question, while the second one points to the code that first introduced the global function call verification. v2: - Use resolve_prog_type() Fixes: 3363bd0cfbb8 ("bpf: Extend kfunc with PTR_TO_CTX, PTR_TO_MEM argument support") Fixes: 51c39bb1d5d1 ("bpf: Introduce function-by-function verification") Reported-by: Simon Sundberg Signed-off-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20220606075253.28422-1-toke@redhat.com Signed-off-by: Alexei Starovoitov --- kernel/bpf/btf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 7bccaa4646e5..63d0ac7dfe2f 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -6054,6 +6054,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, struct bpf_reg_state *regs, bool ptr_to_mem_ok) { + enum bpf_prog_type prog_type = resolve_prog_type(env->prog); struct bpf_verifier_log *log = &env->log; u32 i, nargs, ref_id, ref_obj_id = 0; bool is_kfunc = btf_is_kernel(btf); @@ -6171,7 +6172,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, return -EINVAL; } /* rest of the arguments can be anything, like normal kfunc */ - } else if (btf_get_prog_ctx_type(log, btf, t, env->prog->type, i)) { + } else if (btf_get_prog_ctx_type(log, btf, t, prog_type, i)) { /* If function expects ctx type in BTF check that caller * is passing PTR_TO_CTX. */ -- cgit From 2cf7b7ffdae519b284f1406012b52e2282fa36bf Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Mon, 6 Jun 2022 09:52:52 +0200 Subject: selftests/bpf: Add selftest for calling global functions from freplace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a selftest that calls a global function with a context object parameter from an freplace function to check that the program context type is correctly converted to the freplace target when fetching the context type from the kernel BTF. v2: - Trim includes - Get rid of global function - Use __noinline Signed-off-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20220606075253.28422-2-toke@redhat.com Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c | 14 ++++++++++++++ .../testing/selftests/bpf/progs/freplace_global_func.c | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/freplace_global_func.c diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c index d9aad15e0d24..02bb8cbf9194 100644 --- a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c +++ b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c @@ -395,6 +395,18 @@ static void test_func_map_prog_compatibility(void) "./test_attach_probe.o"); } +static void test_func_replace_global_func(void) +{ + const char *prog_name[] = { + "freplace/test_pkt_access", + }; + + test_fexit_bpf2bpf_common("./freplace_global_func.o", + "./test_pkt_access.o", + ARRAY_SIZE(prog_name), + prog_name, false, NULL); +} + /* NOTE: affect other tests, must run in serial mode */ void serial_test_fexit_bpf2bpf(void) { @@ -416,4 +428,6 @@ void serial_test_fexit_bpf2bpf(void) test_func_replace_multi(); if (test__start_subtest("fmod_ret_freplace")) test_fmod_ret_freplace(); + if (test__start_subtest("func_replace_global_func")) + test_func_replace_global_func(); } diff --git a/tools/testing/selftests/bpf/progs/freplace_global_func.c b/tools/testing/selftests/bpf/progs/freplace_global_func.c new file mode 100644 index 000000000000..96cb61a6ce87 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/freplace_global_func.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include + +__noinline +int test_ctx_global_func(struct __sk_buff *skb) +{ + volatile int retval = 1; + return retval; +} + +SEC("freplace/test_pkt_access") +int new_test_pkt_access(struct __sk_buff *skb) +{ + return test_ctx_global_func(skb); +} + +char _license[] SEC("license") = "GPL"; -- cgit From 2b8c612c6102f751e6e3e1bd425f64e9d3d3f638 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Mon, 6 Jun 2022 19:56:40 +0300 Subject: kernel/reboot: Fix powering off using a non-syscall code paths There are other methods of powering off machine than the reboot syscall. Previously we missed to cover those methods and it created power-off regression for some machines, like the PowerPC e500. Fix this problem by moving the legacy sys-off handler registration to the latest phase of power-off process and making the kernel_can_power_off() check the legacy pm_power_off presence. Tested-by: Michael Ellerman # ppce500 Reported-by: Michael Ellerman # ppce500 Fixes: da007f171fc9 ("kernel/reboot: Change registration order of legacy power-off handler") Signed-off-by: Dmitry Osipenko Signed-off-by: Rafael J. Wysocki --- kernel/reboot.c | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/kernel/reboot.c b/kernel/reboot.c index 3b19b123efec..b5a71d1ff603 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -320,6 +320,7 @@ static struct sys_off_handler platform_sys_off_handler; static struct sys_off_handler *alloc_sys_off_handler(int priority) { struct sys_off_handler *handler; + gfp_t flags; /* * Platforms like m68k can't allocate sys_off handler dynamically @@ -330,7 +331,12 @@ static struct sys_off_handler *alloc_sys_off_handler(int priority) if (handler->cb_data) return ERR_PTR(-EBUSY); } else { - handler = kzalloc(sizeof(*handler), GFP_KERNEL); + if (system_state > SYSTEM_RUNNING) + flags = GFP_ATOMIC; + else + flags = GFP_KERNEL; + + handler = kzalloc(sizeof(*handler), flags); if (!handler) return ERR_PTR(-ENOMEM); } @@ -440,7 +446,7 @@ void unregister_sys_off_handler(struct sys_off_handler *handler) { int err; - if (!handler) + if (IS_ERR_OR_NULL(handler)) return; if (handler->blocking) @@ -615,7 +621,23 @@ static void do_kernel_power_off_prepare(void) */ void do_kernel_power_off(void) { + struct sys_off_handler *sys_off = NULL; + + /* + * Register sys-off handlers for legacy PM callback. This allows + * legacy PM callbacks temporary co-exist with the new sys-off API. + * + * TODO: Remove legacy handlers once all legacy PM users will be + * switched to the sys-off based APIs. + */ + if (pm_power_off) + sys_off = register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, + SYS_OFF_PRIO_DEFAULT, + legacy_pm_power_off, NULL); + atomic_notifier_call_chain(&power_off_handler_list, 0, NULL); + + unregister_sys_off_handler(sys_off); } /** @@ -626,7 +648,8 @@ void do_kernel_power_off(void) */ bool kernel_can_power_off(void) { - return !atomic_notifier_call_chain_is_empty(&power_off_handler_list); + return !atomic_notifier_call_chain_is_empty(&power_off_handler_list) || + pm_power_off; } EXPORT_SYMBOL_GPL(kernel_can_power_off); @@ -661,7 +684,6 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg) { struct pid_namespace *pid_ns = task_active_pid_ns(current); - struct sys_off_handler *sys_off = NULL; char buffer[256]; int ret = 0; @@ -686,21 +708,6 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, if (ret) return ret; - /* - * Register sys-off handlers for legacy PM callback. This allows - * legacy PM callbacks temporary co-exist with the new sys-off API. - * - * TODO: Remove legacy handlers once all legacy PM users will be - * switched to the sys-off based APIs. - */ - if (pm_power_off) { - sys_off = register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, - SYS_OFF_PRIO_DEFAULT, - legacy_pm_power_off, NULL); - if (IS_ERR(sys_off)) - return PTR_ERR(sys_off); - } - /* Instead of trying to make the power_off code look like * halt when pm_power_off is not set do it the easy way. */ @@ -758,7 +765,6 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, break; } mutex_unlock(&system_transition_mutex); - unregister_sys_off_handler(sys_off); return ret; } -- cgit From 803e9895ea2b0fe80bc85980ae2d7a7e44037914 Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Wed, 6 Apr 2022 11:52:51 +0200 Subject: ixgbe: fix bcast packets Rx on VF after promisc removal After a VF requested to remove the promiscuous flag on an interface, the broadcast packets are not received anymore. This breaks some protocols like ARP. In ixgbe_update_vf_xcast_mode(), we should keep the IXGBE_VMOLR_BAM bit (Broadcast Accept) on promiscuous removal. This flag is already set by default in ixgbe_set_vmolr() on VF reset. Fixes: 8443c1a4b192 ("ixgbe, ixgbevf: Add new mbox API xcast mode") Cc: stable@vger.kernel.org Cc: Nicolas Dichtel Signed-off-by: Olivier Matz Tested-by: Konrad Jankowski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 7f11c0a8e7a9..8d108a78941b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -1184,9 +1184,9 @@ static int ixgbe_update_vf_xcast_mode(struct ixgbe_adapter *adapter, switch (xcast_mode) { case IXGBEVF_XCAST_MODE_NONE: - disable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE | + disable = IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_MPE | IXGBE_VMOLR_UPE | IXGBE_VMOLR_VPE; - enable = 0; + enable = IXGBE_VMOLR_BAM; break; case IXGBEVF_XCAST_MODE_MULTI: disable = IXGBE_VMOLR_MPE | IXGBE_VMOLR_UPE | IXGBE_VMOLR_VPE; -- cgit From 7bb0fb7c63df95d6027dc50d6af3bc3bbbc25483 Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Wed, 6 Apr 2022 11:52:52 +0200 Subject: ixgbe: fix unexpected VLAN Rx in promisc mode on VF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the promiscuous mode is enabled on a VF, the IXGBE_VMOLR_VPE bit (VLAN Promiscuous Enable) is set. This means that the VF will receive packets whose VLAN is not the same than the VLAN of the VF. For instance, in this situation: ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ │ │ │ │ │ │ │ │ │ │ VF0├────┤VF1 VF2├────┤VF3 │ │ │ │ │ │ │ └────────┘ └────────┘ └────────┘ VM1 VM2 VM3 vf 0: vlan 1000 vf 1: vlan 1000 vf 2: vlan 1001 vf 3: vlan 1001 If we tcpdump on VF3, we see all the packets, even those transmitted on vlan 1000. This behavior prevents to bridge VF1 and VF2 in VM2, because it will create a loop: packets transmitted on VF1 will be received by VF2 and vice-versa, and bridged again through the software bridge. This patch remove the activation of VLAN Promiscuous when a VF enables the promiscuous mode. However, the IXGBE_VMOLR_UPE bit (Unicast Promiscuous) is kept, so that a VF receives all packets that has the same VLAN, whatever the destination MAC address. Fixes: 8443c1a4b192 ("ixgbe, ixgbevf: Add new mbox API xcast mode") Cc: stable@vger.kernel.org Cc: Nicolas Dichtel Signed-off-by: Olivier Matz Tested-by: Konrad Jankowski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 8d108a78941b..d4e63f0644c3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -1208,9 +1208,9 @@ static int ixgbe_update_vf_xcast_mode(struct ixgbe_adapter *adapter, return -EPERM; } - disable = 0; + disable = IXGBE_VMOLR_VPE; enable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE | - IXGBE_VMOLR_MPE | IXGBE_VMOLR_UPE | IXGBE_VMOLR_VPE; + IXGBE_VMOLR_MPE | IXGBE_VMOLR_UPE; break; default: return -EOPNOTSUPP; -- cgit From f9e9bdd5bb180325256e3bdfeb9c4c6526133478 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:46 -0500 Subject: ASoC: Realtek/Maxim SoundWire codecs: disable pm_runtime on remove When binding/unbinding codec drivers, the following warnings are thrown: [ 107.266879] rt715-sdca sdw:3:025d:0714:01: Unbalanced pm_runtime_enable! [ 306.879700] rt711-sdca sdw:0:025d:0711:01: Unbalanced pm_runtime_enable! Add a remove callback for all Realtek/Maxim SoundWire codecs and remove this warning. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98373-sdw.c | 12 +++++++++++- sound/soc/codecs/rt1308-sdw.c | 11 +++++++++++ sound/soc/codecs/rt1316-sdw.c | 11 +++++++++++ sound/soc/codecs/rt5682-sdw.c | 5 ++++- sound/soc/codecs/rt700-sdw.c | 6 +++++- sound/soc/codecs/rt711-sdca-sdw.c | 6 +++++- sound/soc/codecs/rt711-sdw.c | 6 +++++- sound/soc/codecs/rt715-sdca-sdw.c | 12 ++++++++++++ sound/soc/codecs/rt715-sdw.c | 12 ++++++++++++ 9 files changed, 76 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index f47e956d4f55..97b64477dde6 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -862,6 +862,16 @@ static int max98373_sdw_probe(struct sdw_slave *slave, return max98373_init(slave, regmap); } +static int max98373_sdw_remove(struct sdw_slave *slave) +{ + struct max98373_priv *max98373 = dev_get_drvdata(&slave->dev); + + if (max98373->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + #if defined(CONFIG_OF) static const struct of_device_id max98373_of_match[] = { { .compatible = "maxim,max98373", }, @@ -893,7 +903,7 @@ static struct sdw_driver max98373_sdw_driver = { .pm = &max98373_pm, }, .probe = max98373_sdw_probe, - .remove = NULL, + .remove = max98373_sdw_remove, .ops = &max98373_slave_ops, .id_table = max98373_id, }; diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 1c11b42dd76e..72f673f278ee 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -691,6 +691,16 @@ static int rt1308_sdw_probe(struct sdw_slave *slave, return 0; } +static int rt1308_sdw_remove(struct sdw_slave *slave) +{ + struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(&slave->dev); + + if (rt1308->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + static const struct sdw_device_id rt1308_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x1308, 0x2, 0, 0), {}, @@ -750,6 +760,7 @@ static struct sdw_driver rt1308_sdw_driver = { .pm = &rt1308_pm, }, .probe = rt1308_sdw_probe, + .remove = rt1308_sdw_remove, .ops = &rt1308_slave_ops, .id_table = rt1308_id, }; diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c index 60baa9ff1907..2d6b5f9d4d77 100644 --- a/sound/soc/codecs/rt1316-sdw.c +++ b/sound/soc/codecs/rt1316-sdw.c @@ -676,6 +676,16 @@ static int rt1316_sdw_probe(struct sdw_slave *slave, return rt1316_sdw_init(&slave->dev, regmap, slave); } +static int rt1316_sdw_remove(struct sdw_slave *slave) +{ + struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(&slave->dev); + + if (rt1316->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + static const struct sdw_device_id rt1316_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x1316, 0x3, 0x1, 0), {}, @@ -735,6 +745,7 @@ static struct sdw_driver rt1316_sdw_driver = { .pm = &rt1316_pm, }, .probe = rt1316_sdw_probe, + .remove = rt1316_sdw_remove, .ops = &rt1316_slave_ops, .id_table = rt1316_id, }; diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 248257a2e4e0..f04e18c32489 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -719,9 +719,12 @@ static int rt5682_sdw_remove(struct sdw_slave *slave) { struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); - if (rt5682 && rt5682->hw_init) + if (rt5682->hw_init) cancel_delayed_work_sync(&rt5682->jack_detect_work); + if (rt5682->first_hw_init) + pm_runtime_disable(&slave->dev); + return 0; } diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index bda594899664..f7439e40ca8b 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include "rt700.h" @@ -463,11 +464,14 @@ static int rt700_sdw_remove(struct sdw_slave *slave) { struct rt700_priv *rt700 = dev_get_drvdata(&slave->dev); - if (rt700 && rt700->hw_init) { + if (rt700->hw_init) { cancel_delayed_work_sync(&rt700->jack_detect_work); cancel_delayed_work_sync(&rt700->jack_btn_check_work); } + if (rt700->first_hw_init) + pm_runtime_disable(&slave->dev); + return 0; } diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c index aaf5af153d3f..c722a2b0041f 100644 --- a/sound/soc/codecs/rt711-sdca-sdw.c +++ b/sound/soc/codecs/rt711-sdca-sdw.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "rt711-sdca.h" #include "rt711-sdca-sdw.h" @@ -364,11 +365,14 @@ static int rt711_sdca_sdw_remove(struct sdw_slave *slave) { struct rt711_sdca_priv *rt711 = dev_get_drvdata(&slave->dev); - if (rt711 && rt711->hw_init) { + if (rt711->hw_init) { cancel_delayed_work_sync(&rt711->jack_detect_work); cancel_delayed_work_sync(&rt711->jack_btn_check_work); } + if (rt711->first_hw_init) + pm_runtime_disable(&slave->dev); + return 0; } diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index bda2cc9439c9..f49c94baa37c 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include "rt711.h" @@ -464,12 +465,15 @@ static int rt711_sdw_remove(struct sdw_slave *slave) { struct rt711_priv *rt711 = dev_get_drvdata(&slave->dev); - if (rt711 && rt711->hw_init) { + if (rt711->hw_init) { cancel_delayed_work_sync(&rt711->jack_detect_work); cancel_delayed_work_sync(&rt711->jack_btn_check_work); cancel_work_sync(&rt711->calibration_work); } + if (rt711->first_hw_init) + pm_runtime_disable(&slave->dev); + return 0; } diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c index 0ecd2948f7aa..13e731d16675 100644 --- a/sound/soc/codecs/rt715-sdca-sdw.c +++ b/sound/soc/codecs/rt715-sdca-sdw.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include "rt715-sdca.h" @@ -193,6 +194,16 @@ static int rt715_sdca_sdw_probe(struct sdw_slave *slave, return rt715_sdca_init(&slave->dev, mbq_regmap, regmap, slave); } +static int rt715_sdca_sdw_remove(struct sdw_slave *slave) +{ + struct rt715_sdca_priv *rt715 = dev_get_drvdata(&slave->dev); + + if (rt715->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + static const struct sdw_device_id rt715_sdca_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x3, 0x1, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x3, 0x1, 0), @@ -267,6 +278,7 @@ static struct sdw_driver rt715_sdw_driver = { .pm = &rt715_pm, }, .probe = rt715_sdca_sdw_probe, + .remove = rt715_sdca_sdw_remove, .ops = &rt715_sdca_slave_ops, .id_table = rt715_sdca_id, }; diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index a7b21b03c08b..b047bf87a100 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -514,6 +515,16 @@ static int rt715_sdw_probe(struct sdw_slave *slave, return 0; } +static int rt715_sdw_remove(struct sdw_slave *slave) +{ + struct rt715_priv *rt715 = dev_get_drvdata(&slave->dev); + + if (rt715->first_hw_init) + pm_runtime_disable(&slave->dev); + + return 0; +} + static const struct sdw_device_id rt715_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x2, 0, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x2, 0, 0), @@ -575,6 +586,7 @@ static struct sdw_driver rt715_sdw_driver = { .pm = &rt715_pm, }, .probe = rt715_sdw_probe, + .remove = rt715_sdw_remove, .ops = &rt715_slave_ops, .id_table = rt715_id, }; -- cgit From 716c2e7e1608a89423ec84398b99ff2fa855d161 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:47 -0500 Subject: ASoC: rt711-sdca-sdw: fix calibrate mutex initialization In codec driver bind/unbind test, the following warning is thrown: DEBUG_LOCKS_WARN_ON(lock->magic != lock) ... [ 699.182495] rt711_sdca_jack_init+0x1b/0x1d0 [snd_soc_rt711_sdca] [ 699.182498] rt711_sdca_set_jack_detect+0x3b/0x90 [snd_soc_rt711_sdca] [ 699.182500] snd_soc_component_set_jack+0x24/0x50 [snd_soc_core] A quick check in the code shows that the 'calibrate_mutex' used by this driver are not initialized at probe time. Moving the initialization to the probe removes the issue. BugLink: https://github.com/thesofproject/linux/issues/3644 Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdca-sdw.c | 3 +++ sound/soc/codecs/rt711-sdca.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c index c722a2b0041f..a085b2f530aa 100644 --- a/sound/soc/codecs/rt711-sdca-sdw.c +++ b/sound/soc/codecs/rt711-sdca-sdw.c @@ -373,6 +373,9 @@ static int rt711_sdca_sdw_remove(struct sdw_slave *slave) if (rt711->first_hw_init) pm_runtime_disable(&slave->dev); + mutex_destroy(&rt711->calibrate_mutex); + mutex_destroy(&rt711->disable_irq_lock); + return 0; } diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index 57629c18db38..af73bcb4560a 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -1412,6 +1412,7 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap, rt711->regmap = regmap; rt711->mbq_regmap = mbq_regmap; + mutex_init(&rt711->calibrate_mutex); mutex_init(&rt711->disable_irq_lock); /* @@ -1550,7 +1551,6 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave) rt711_sdca_jack_detect_handler); INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_sdca_btn_check_handler); - mutex_init(&rt711->calibrate_mutex); } /* calibration */ -- cgit From 768ad6d80db2dbbb1bfbb5e616d701a0b560f12a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:48 -0500 Subject: ASoC: Intel: sof_sdw: handle errors on card registration If the card registration fails, typically because of deferred probes, the device properties added for headset codecs are not removed, which leads to kernel oopses in driver bind/unbind tests. We already clean-up the device properties when the card is removed, this code can be moved as a helper and called upon card registration errors. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 51 +++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 1f00679b4240..ad826ad82d51 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1398,6 +1398,33 @@ static struct snd_soc_card card_sof_sdw = { .late_probe = sof_sdw_card_late_probe, }; +static void mc_dailink_exit_loop(struct snd_soc_card *card) +{ + struct snd_soc_dai_link *link; + int ret; + int i, j; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { + if (!codec_info_list[i].exit) + continue; + /* + * We don't need to call .exit function if there is no matched + * dai link found. + */ + for_each_card_prelinks(card, j, link) { + if (!strcmp(link->codecs[0].dai_name, + codec_info_list[i].dai_name)) { + ret = codec_info_list[i].exit(card, link); + if (ret) + dev_warn(card->dev, + "codec exit failed %d\n", + ret); + break; + } + } + } +} + static int mc_probe(struct platform_device *pdev) { struct snd_soc_card *card = &card_sof_sdw; @@ -1462,6 +1489,7 @@ static int mc_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { dev_err(card->dev, "snd_soc_register_card failed %d\n", ret); + mc_dailink_exit_loop(card); return ret; } @@ -1473,29 +1501,8 @@ static int mc_probe(struct platform_device *pdev) static int mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - struct snd_soc_dai_link *link; - int ret; - int i, j; - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { - if (!codec_info_list[i].exit) - continue; - /* - * We don't need to call .exit function if there is no matched - * dai link found. - */ - for_each_card_prelinks(card, j, link) { - if (!strcmp(link->codecs[0].dai_name, - codec_info_list[i].dai_name)) { - ret = codec_info_list[i].exit(card, link); - if (ret) - dev_warn(&pdev->dev, - "codec exit failed %d\n", - ret); - break; - } - } - } + mc_dailink_exit_loop(card); return 0; } -- cgit From 74d40901ebad7c466a95b1ae3c6891f1ba09786f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:49 -0500 Subject: ASoC: rt711: fix calibrate mutex initialization Follow the same flow as rt711-sdca and initialize all mutexes at probe time. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdw.c | 3 +++ sound/soc/codecs/rt711.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index f49c94baa37c..4fe68bcf2a7c 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -474,6 +474,9 @@ static int rt711_sdw_remove(struct sdw_slave *slave) if (rt711->first_hw_init) pm_runtime_disable(&slave->dev); + mutex_destroy(&rt711->calibrate_mutex); + mutex_destroy(&rt711->disable_irq_lock); + return 0; } diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 9838fb4d5b9c..1e35ba433a7e 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -1204,6 +1204,7 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap, rt711->sdw_regmap = sdw_regmap; rt711->regmap = regmap; + mutex_init(&rt711->calibrate_mutex); mutex_init(&rt711->disable_irq_lock); /* @@ -1318,7 +1319,6 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave) rt711_jack_detect_handler); INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_btn_check_handler); - mutex_init(&rt711->calibrate_mutex); INIT_WORK(&rt711->calibration_work, rt711_calibration_work); schedule_work(&rt711->calibration_work); } -- cgit From 05ba4c00fa9cb077a0dd91f5e6056951a787f63c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:50 -0500 Subject: ASoC: rt7*-sdw: harden jack_detect_handler Realtek headset codec drivers typically check if the card is instantiated before proceeding with the jack detection. The rt700, rt711 and rt711-sdca are however missing a check on the card pointer, which can lead to NULL dereferences encountered in driver bind/unbind tests. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt700.c | 2 +- sound/soc/codecs/rt711-sdca.c | 2 +- sound/soc/codecs/rt711.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c index af32295fa9b9..4a99d5f4706f 100644 --- a/sound/soc/codecs/rt700.c +++ b/sound/soc/codecs/rt700.c @@ -162,7 +162,7 @@ static void rt700_jack_detect_handler(struct work_struct *work) if (!rt700->hs_jack) return; - if (!rt700->component->card->instantiated) + if (!rt700->component->card || !rt700->component->card->instantiated) return; reg = RT700_VERB_GET_PIN_SENSE | RT700_HP_OUT; diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index af73bcb4560a..93b36f05cb56 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -294,7 +294,7 @@ static void rt711_sdca_jack_detect_handler(struct work_struct *work) if (!rt711->hs_jack) return; - if (!rt711->component->card->instantiated) + if (!rt711->component->card || !rt711->component->card->instantiated) return; /* SDW_SCP_SDCA_INT_SDCA_0 is used for jack detection */ diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 1e35ba433a7e..2f445b27305a 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -242,7 +242,7 @@ static void rt711_jack_detect_handler(struct work_struct *work) if (!rt711->hs_jack) return; - if (!rt711->component->card->instantiated) + if (!rt711->component->card || !rt711->component->card->instantiated) return; if (pm_runtime_status_suspended(rt711->slave->dev.parent)) { -- cgit From a49267a3bd102e3991514e884aac89cc0d0b5f35 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:51 -0500 Subject: ASoC: codecs: rt700/rt711/rt711-sdca: initialize workqueues in probe The workqueues are initialized in the io_init functions, which isn't quite right. In some tests, this leads to warnings throw from __queue_delayed_work() WARN_ON_FUNCTION_MISMATCH(timer->function, delayed_work_timer_fn); Move all the initializations to the probe functions. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt700.c | 12 +++++------- sound/soc/codecs/rt711-sdca.c | 10 +++------- sound/soc/codecs/rt711.c | 12 +++++------- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c index 4a99d5f4706f..7a6cf3434591 100644 --- a/sound/soc/codecs/rt700.c +++ b/sound/soc/codecs/rt700.c @@ -1115,6 +1115,11 @@ int rt700_init(struct device *dev, struct regmap *sdw_regmap, mutex_init(&rt700->disable_irq_lock); + INIT_DELAYED_WORK(&rt700->jack_detect_work, + rt700_jack_detect_handler); + INIT_DELAYED_WORK(&rt700->jack_btn_check_work, + rt700_btn_check_handler); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1209,13 +1214,6 @@ int rt700_io_init(struct device *dev, struct sdw_slave *slave) /* Finish Initial Settings, set power to D3 */ regmap_write(rt700->regmap, RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D3); - if (!rt700->first_hw_init) { - INIT_DELAYED_WORK(&rt700->jack_detect_work, - rt700_jack_detect_handler); - INIT_DELAYED_WORK(&rt700->jack_btn_check_work, - rt700_btn_check_handler); - } - /* * if set_jack callback occurred early than io_init, * we set up the jack detection function now diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index 93b36f05cb56..2b3b77577d1f 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -1415,6 +1415,9 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap, mutex_init(&rt711->calibrate_mutex); mutex_init(&rt711->disable_irq_lock); + INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_sdca_jack_detect_handler); + INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_sdca_btn_check_handler); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1546,13 +1549,6 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave) rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, RT711_PUSH_BTN_INT_CTL0, 0x20, 0x00); - if (!rt711->first_hw_init) { - INIT_DELAYED_WORK(&rt711->jack_detect_work, - rt711_sdca_jack_detect_handler); - INIT_DELAYED_WORK(&rt711->jack_btn_check_work, - rt711_sdca_btn_check_handler); - } - /* calibration */ ret = rt711_sdca_calibration(rt711); if (ret < 0) diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 2f445b27305a..5709a6bbe8fc 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -1207,6 +1207,10 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap, mutex_init(&rt711->calibrate_mutex); mutex_init(&rt711->disable_irq_lock); + INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_jack_detect_handler); + INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_btn_check_handler); + INIT_WORK(&rt711->calibration_work, rt711_calibration_work); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1314,14 +1318,8 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave) if (rt711->first_hw_init) rt711_calibration(rt711); - else { - INIT_DELAYED_WORK(&rt711->jack_detect_work, - rt711_jack_detect_handler); - INIT_DELAYED_WORK(&rt711->jack_btn_check_work, - rt711_btn_check_handler); - INIT_WORK(&rt711->calibration_work, rt711_calibration_work); + else schedule_work(&rt711->calibration_work); - } /* * if set_jack callback occurred early than io_init, -- cgit From e02b99e9b79ff272e8c299a3ee53bdb194ca885e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 6 Jun 2022 15:37:52 -0500 Subject: ASoC: codecs: rt700/rt711/rt711-sdca: resume bus/codec in .set_jack_detect The .set_jack_detect() codec component callback is invoked during card registration, which happens when the machine driver is probed. The issue is that this callback can race with the bus suspend/resume, and IO timeouts can happen. This can be reproduced very easily if the machine driver is 'blacklisted' and manually probed after the bus suspends. The bus and codec need to be re-initialized using pm_runtime helpers. Previous contributions tried to make sure accesses to the bus during the .set_jack_detect() component callback only happen when the bus is active. This was done by changing the regcache status on a component remove. This is however a layering violation, the regcache status should only be modified on device probe, suspend and resume. The component probe/remove should not modify how the device regcache is handled. This solution also didn't handle all the possible race conditions, and the RT700 headset codec was not handled. This patch tries to resume the codec device before handling the jack initializations. In case the codec has not yet been initialized, pm_runtime may not be enabled yet, so we don't squelch the -EACCES error code and only stop the jack information. When the codec reports as attached, the jack initialization will proceed as usual. BugLink: https://github.com/thesofproject/linux/issues/3643 Fixes: 7ad4d237e7c4a ('ASoC: rt711-sdca: Add RT711 SDCA vendor-specific driver') Fixes: 899b12542b089 ('ASoC: rt711: add snd_soc_component remove callback') Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220606203752.144159-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt700.c | 16 +++++++++++++--- sound/soc/codecs/rt711-sdca.c | 26 ++++++++++++++------------ sound/soc/codecs/rt711.c | 24 +++++++++++++----------- 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c index 7a6cf3434591..9bceeeb830b1 100644 --- a/sound/soc/codecs/rt700.c +++ b/sound/soc/codecs/rt700.c @@ -315,17 +315,27 @@ static int rt700_set_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *hs_jack, void *data) { struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component); + int ret; rt700->hs_jack = hs_jack; - if (!rt700->hw_init) { - dev_dbg(&rt700->slave->dev, - "%s hw_init not ready yet\n", __func__); + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0) { + if (ret != -EACCES) { + dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret); + return ret; + } + + /* pm_runtime not enabled yet */ + dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__); return 0; } rt700_jack_init(rt700); + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + return 0; } diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index 2b3b77577d1f..dfe3c9299ebd 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -487,16 +487,27 @@ static int rt711_sdca_set_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *hs_jack, void *data) { struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + int ret; rt711->hs_jack = hs_jack; - if (!rt711->hw_init) { - dev_dbg(&rt711->slave->dev, - "%s hw_init not ready yet\n", __func__); + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0) { + if (ret != -EACCES) { + dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret); + return ret; + } + + /* pm_runtime not enabled yet */ + dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__); return 0; } rt711_sdca_jack_init(rt711); + + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + return 0; } @@ -1190,14 +1201,6 @@ static int rt711_sdca_probe(struct snd_soc_component *component) return 0; } -static void rt711_sdca_remove(struct snd_soc_component *component) -{ - struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); - - regcache_cache_only(rt711->regmap, true); - regcache_cache_only(rt711->mbq_regmap, true); -} - static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { .probe = rt711_sdca_probe, .controls = rt711_sdca_snd_controls, @@ -1207,7 +1210,6 @@ static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { .dapm_routes = rt711_sdca_audio_map, .num_dapm_routes = ARRAY_SIZE(rt711_sdca_audio_map), .set_jack = rt711_sdca_set_jack_detect, - .remove = rt711_sdca_remove, .endianness = 1, }; diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 5709a6bbe8fc..9df800abfc2d 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -457,17 +457,27 @@ static int rt711_set_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *hs_jack, void *data) { struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component); + int ret; rt711->hs_jack = hs_jack; - if (!rt711->hw_init) { - dev_dbg(&rt711->slave->dev, - "%s hw_init not ready yet\n", __func__); + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0) { + if (ret != -EACCES) { + dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret); + return ret; + } + + /* pm_runtime not enabled yet */ + dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__); return 0; } rt711_jack_init(rt711); + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + return 0; } @@ -932,13 +942,6 @@ static int rt711_probe(struct snd_soc_component *component) return 0; } -static void rt711_remove(struct snd_soc_component *component) -{ - struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component); - - regcache_cache_only(rt711->regmap, true); -} - static const struct snd_soc_component_driver soc_codec_dev_rt711 = { .probe = rt711_probe, .set_bias_level = rt711_set_bias_level, @@ -949,7 +952,6 @@ static const struct snd_soc_component_driver soc_codec_dev_rt711 = { .dapm_routes = rt711_audio_map, .num_dapm_routes = ARRAY_SIZE(rt711_audio_map), .set_jack = rt711_set_jack_detect, - .remove = rt711_remove, .endianness = 1, }; -- cgit From 41782d7056e2866ca40cb2d3f56c4c97fd5af337 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Mon, 6 Jun 2022 10:09:48 +0800 Subject: Revert "drm/amdgpu: Ensure the DMA engine is deactivated during set ups" This reverts commit b992a19085885c096b19625a85c674cb89829ca1. This causes regression in GPU reset related test. Cc: Alexander Deucher Cc: ricetons@gmail.com Signed-off-by: Guchun Chen Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 109 ++++++++++++++------------------- 1 file changed, 45 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c index 06b2635b142a..83c6ccaaa9e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c @@ -469,6 +469,7 @@ static void sdma_v5_2_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se } } + /** * sdma_v5_2_gfx_stop - stop the gfx async dma engines * @@ -514,21 +515,17 @@ static void sdma_v5_2_rlc_stop(struct amdgpu_device *adev) } /** - * sdma_v5_2_ctx_switch_enable_for_instance - start the async dma engines - * context switch for an instance + * sdma_v5_2_ctx_switch_enable - stop the async dma engines context switch * * @adev: amdgpu_device pointer - * @instance_idx: the index of the SDMA instance + * @enable: enable/disable the DMA MEs context switch. * - * Unhalt the async dma engines context switch. + * Halt or unhalt the async dma engines context switch. */ -static void sdma_v5_2_ctx_switch_enable_for_instance(struct amdgpu_device *adev, int instance_idx) +static void sdma_v5_2_ctx_switch_enable(struct amdgpu_device *adev, bool enable) { u32 f32_cntl, phase_quantum = 0; - - if (WARN_ON(instance_idx >= adev->sdma.num_instances)) { - return; - } + int i; if (amdgpu_sdma_phase_quantum) { unsigned value = amdgpu_sdma_phase_quantum; @@ -552,68 +549,50 @@ static void sdma_v5_2_ctx_switch_enable_for_instance(struct amdgpu_device *adev, phase_quantum = value << SDMA0_PHASE0_QUANTUM__VALUE__SHIFT | unit << SDMA0_PHASE0_QUANTUM__UNIT__SHIFT; - - WREG32_SOC15_IP(GC, - sdma_v5_2_get_reg_offset(adev, instance_idx, mmSDMA0_PHASE0_QUANTUM), - phase_quantum); - WREG32_SOC15_IP(GC, - sdma_v5_2_get_reg_offset(adev, instance_idx, mmSDMA0_PHASE1_QUANTUM), - phase_quantum); - WREG32_SOC15_IP(GC, - sdma_v5_2_get_reg_offset(adev, instance_idx, mmSDMA0_PHASE2_QUANTUM), - phase_quantum); } - if (!amdgpu_sriov_vf(adev)) { - f32_cntl = RREG32(sdma_v5_2_get_reg_offset(adev, instance_idx, mmSDMA0_CNTL)); - f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, - AUTO_CTXSW_ENABLE, 1); - WREG32(sdma_v5_2_get_reg_offset(adev, instance_idx, mmSDMA0_CNTL), f32_cntl); + for (i = 0; i < adev->sdma.num_instances; i++) { + if (enable && amdgpu_sdma_phase_quantum) { + WREG32_SOC15_IP(GC, sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_PHASE0_QUANTUM), + phase_quantum); + WREG32_SOC15_IP(GC, sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_PHASE1_QUANTUM), + phase_quantum); + WREG32_SOC15_IP(GC, sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_PHASE2_QUANTUM), + phase_quantum); + } + + if (!amdgpu_sriov_vf(adev)) { + f32_cntl = RREG32(sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_CNTL)); + f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, + AUTO_CTXSW_ENABLE, enable ? 1 : 0); + WREG32(sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_CNTL), f32_cntl); + } } + } /** - * sdma_v5_2_ctx_switch_disable_all - stop the async dma engines context switch + * sdma_v5_2_enable - stop the async dma engines * * @adev: amdgpu_device pointer + * @enable: enable/disable the DMA MEs. * - * Halt the async dma engines context switch. + * Halt or unhalt the async dma engines. */ -static void sdma_v5_2_ctx_switch_disable_all(struct amdgpu_device *adev) +static void sdma_v5_2_enable(struct amdgpu_device *adev, bool enable) { u32 f32_cntl; int i; - if (amdgpu_sriov_vf(adev)) - return; - - for (i = 0; i < adev->sdma.num_instances; i++) { - f32_cntl = RREG32(sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_CNTL)); - f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL, - AUTO_CTXSW_ENABLE, 0); - WREG32(sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_CNTL), f32_cntl); + if (!enable) { + sdma_v5_2_gfx_stop(adev); + sdma_v5_2_rlc_stop(adev); } -} - -/** - * sdma_v5_2_halt - stop the async dma engines - * - * @adev: amdgpu_device pointer - * - * Halt the async dma engines. - */ -static void sdma_v5_2_halt(struct amdgpu_device *adev) -{ - int i; - u32 f32_cntl; - - sdma_v5_2_gfx_stop(adev); - sdma_v5_2_rlc_stop(adev); if (!amdgpu_sriov_vf(adev)) { for (i = 0; i < adev->sdma.num_instances; i++) { f32_cntl = RREG32(sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_F32_CNTL)); - f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, 1); + f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, enable ? 0 : 1); WREG32(sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_F32_CNTL), f32_cntl); } } @@ -625,9 +604,6 @@ static void sdma_v5_2_halt(struct amdgpu_device *adev) * @adev: amdgpu_device pointer * * Set up the gfx DMA ring buffers and enable them. - * It assumes that the dma engine is stopped for each instance. - * The function enables the engine and preemptions sequentially for each instance. - * * Returns 0 for success, error for failure. */ static int sdma_v5_2_gfx_resume(struct amdgpu_device *adev) @@ -769,7 +745,10 @@ static int sdma_v5_2_gfx_resume(struct amdgpu_device *adev) ring->sched.ready = true; - sdma_v5_2_ctx_switch_enable_for_instance(adev, i); + if (amdgpu_sriov_vf(adev)) { /* bare-metal sequence doesn't need below to lines */ + sdma_v5_2_ctx_switch_enable(adev, true); + sdma_v5_2_enable(adev, true); + } r = amdgpu_ring_test_ring(ring); if (r) { @@ -813,7 +792,7 @@ static int sdma_v5_2_load_microcode(struct amdgpu_device *adev) int i, j; /* halt the MEs */ - sdma_v5_2_halt(adev); + sdma_v5_2_enable(adev, false); for (i = 0; i < adev->sdma.num_instances; i++) { if (!adev->sdma.instance[i].fw) @@ -885,8 +864,8 @@ static int sdma_v5_2_start(struct amdgpu_device *adev) int r = 0; if (amdgpu_sriov_vf(adev)) { - sdma_v5_2_ctx_switch_disable_all(adev); - sdma_v5_2_halt(adev); + sdma_v5_2_ctx_switch_enable(adev, false); + sdma_v5_2_enable(adev, false); /* set RB registers */ r = sdma_v5_2_gfx_resume(adev); @@ -910,10 +889,12 @@ static int sdma_v5_2_start(struct amdgpu_device *adev) amdgpu_gfx_off_ctrl(adev, false); sdma_v5_2_soft_reset(adev); + /* unhalt the MEs */ + sdma_v5_2_enable(adev, true); + /* enable sdma ring preemption */ + sdma_v5_2_ctx_switch_enable(adev, true); - /* Soft reset supposes to disable the dma engine and preemption. - * Now start the gfx rings and rlc compute queues. - */ + /* start the gfx rings and rlc compute queues */ r = sdma_v5_2_gfx_resume(adev); if (adev->in_s0ix) amdgpu_gfx_off_ctrl(adev, true); @@ -1447,8 +1428,8 @@ static int sdma_v5_2_hw_fini(void *handle) if (amdgpu_sriov_vf(adev)) return 0; - sdma_v5_2_ctx_switch_disable_all(adev); - sdma_v5_2_halt(adev); + sdma_v5_2_ctx_switch_enable(adev, false); + sdma_v5_2_enable(adev, false); return 0; } -- cgit From 8b8ce2b90af1bea3d7b24e250832fcc3c7e687ea Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 17 May 2022 10:12:27 -0400 Subject: Revert "drm/amd/display: Pass the new context into disable OTG WA" This reverts commit 8440f57532496d398a461887e56ca6f45089fbcf. Causes a hang when hotplugging DP, shutting down system, or enabling dual eDP. Reviewed-by: Dmytro Laktyushkin Acked-by: Hamza Mahfooz Signed-off-by: Nicholas Kazlauskas Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 8 ++++---- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 6a81c1aea0be..bca5f01da763 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -99,13 +99,13 @@ static int dcn31_get_active_display_cnt_wa( return display_count; } -static void dcn31_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) +static void dcn31_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable) { struct dc *dc = clk_mgr_base->ctx->dc; int i; for (i = 0; i < dc->res_pool->pipe_count; ++i) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; if (pipe->top_pipe || pipe->prev_odm_pipe) continue; @@ -211,11 +211,11 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base, } if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { - dcn31_disable_otg_wa(clk_mgr_base, context, true); + dcn31_disable_otg_wa(clk_mgr_base, true); clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; dcn31_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); - dcn31_disable_otg_wa(clk_mgr_base, context, false); + dcn31_disable_otg_wa(clk_mgr_base, false); update_dispclk = true; } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c index aa01a18df419..fb4ae800e919 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c @@ -79,13 +79,13 @@ static int dcn315_get_active_display_cnt_wa( return display_count; } -static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) +static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable) { struct dc *dc = clk_mgr_base->ctx->dc; int i; for (i = 0; i < dc->res_pool->pipe_count; ++i) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; if (pipe->top_pipe || pipe->prev_odm_pipe) continue; @@ -173,11 +173,11 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, } if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { - dcn315_disable_otg_wa(clk_mgr_base, context, true); + dcn315_disable_otg_wa(clk_mgr_base, true); clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; dcn315_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); - dcn315_disable_otg_wa(clk_mgr_base, context, false); + dcn315_disable_otg_wa(clk_mgr_base, false); update_dispclk = true; } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c index 7192f30858eb..e4bb9c6193b5 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c @@ -112,13 +112,13 @@ static int dcn316_get_active_display_cnt_wa( return display_count; } -static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) +static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, bool disable) { struct dc *dc = clk_mgr_base->ctx->dc; int i; for (i = 0; i < dc->res_pool->pipe_count; ++i) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; if (pipe->top_pipe || pipe->prev_odm_pipe) continue; @@ -221,11 +221,11 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, } if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { - dcn316_disable_otg_wa(clk_mgr_base, context, true); + dcn316_disable_otg_wa(clk_mgr_base, true); clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; dcn316_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); - dcn316_disable_otg_wa(clk_mgr_base, context, false); + dcn316_disable_otg_wa(clk_mgr_base, false); update_dispclk = true; } -- cgit From b3f9234e106c9ca4dd0fab3cebbdc8ac74504f97 Mon Sep 17 00:00:00 2001 From: Joseph Greathouse Date: Mon, 6 Jun 2022 16:09:25 -0500 Subject: drm/amdgpu: Add MODE register to wave debug info in gfx11 All other chips, from gfx6-gfx10, now include the MODE register at the end of the wave debug state. This appears to have been missed in gfx11, so this patch adds in MODE to the debug state for gfx11. Signed-off-by: Joseph Greathouse Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 10e180b2d0f5..a4a6751b1e44 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -1096,6 +1096,7 @@ static void gfx_v11_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_IB_STS2); dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_IB_DBG1); dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_M0); + dst[(*no_fields)++] = wave_read_ind(adev, wave, ixSQ_WAVE_MODE); } static void gfx_v11_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, -- cgit From c42e65664390be7c1ef3838cd84956d3a2739d60 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Tue, 7 Jun 2022 12:11:33 -0700 Subject: Input: bcm5974 - set missing URB_NO_TRANSFER_DMA_MAP urb flag The bcm5974 driver does the allocation and dma mapping of the usb urb data buffer, but driver does not set the URB_NO_TRANSFER_DMA_MAP flag to let usb core know the buffer is already mapped. usb core tries to map the already mapped buffer, causing a warning: "xhci_hcd 0000:00:14.0: rejecting DMA map of vmalloc memory" Fix this by setting the URB_NO_TRANSFER_DMA_MAP, letting usb core know buffer is already mapped by bcm5974 driver Signed-off-by: Mathias Nyman Cc: stable@vger.kernel.org Link: https://bugzilla.kernel.org/show_bug.cgi?id=215890 Link: https://lore.kernel.org/r/20220606113636.588955-1-mathias.nyman@linux.intel.com Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/bcm5974.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 59a14505b9cd..ca150618d32f 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -942,17 +942,22 @@ static int bcm5974_probe(struct usb_interface *iface, if (!dev->tp_data) goto err_free_bt_buffer; - if (dev->bt_urb) + if (dev->bt_urb) { usb_fill_int_urb(dev->bt_urb, udev, usb_rcvintpipe(udev, cfg->bt_ep), dev->bt_data, dev->cfg.bt_datalen, bcm5974_irq_button, dev, 1); + dev->bt_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + } + usb_fill_int_urb(dev->tp_urb, udev, usb_rcvintpipe(udev, cfg->tp_ep), dev->tp_data, dev->cfg.tp_datalen, bcm5974_irq_trackpad, dev, 1); + dev->tp_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + /* create bcm5974 device */ usb_make_path(udev, dev->phys, sizeof(dev->phys)); strlcat(dev->phys, "/input0", sizeof(dev->phys)); -- cgit From 6ab2e51898cd4343bbdf8587af8ce8fbabddbcb5 Mon Sep 17 00:00:00 2001 From: Marius Hoch Date: Tue, 7 Jun 2022 12:10:52 -0700 Subject: Input: soc_button_array - also add Lenovo Yoga Tablet2 1051F to dmi_use_low_level_irq Commit 223f61b8c5ad ("Input: soc_button_array - add Lenovo Yoga Tablet2 1051L to the dmi_use_low_level_irq list") added the 1051L to this list already, but the same problem applies to the 1051F. As there are no further 1051 variants (just the F/L), we can just DMI match 1051. Tested on a Lenovo Yoga Tablet2 1051F: Without this patch the home-button stops working after a wakeup from suspend. Signed-off-by: Marius Hoch Reviewed-by: Hans de Goede Link: https://lore.kernel.org/r/20220603120246.3065-1-mail@mariushoch.de Signed-off-by: Dmitry Torokhov --- drivers/input/misc/soc_button_array.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index cb6ec59a045d..efffcf0ebd3b 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -85,13 +85,13 @@ static const struct dmi_system_id dmi_use_low_level_irq[] = { }, { /* - * Lenovo Yoga Tab2 1051L, something messes with the home-button + * Lenovo Yoga Tab2 1051F/1051L, something messes with the home-button * IRQ settings, leading to a non working home-button. */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_NAME, "60073"), - DMI_MATCH(DMI_PRODUCT_VERSION, "1051L"), + DMI_MATCH(DMI_PRODUCT_VERSION, "1051"), }, }, {} /* Terminating entry */ -- cgit From f92de9d110429e39929a49240d823251c2fe903e Mon Sep 17 00:00:00 2001 From: Tyler Erickson Date: Thu, 2 Jun 2022 16:51:13 -0600 Subject: scsi: sd: Fix interpretation of VPD B9h length Fixing the interpretation of the length of the B9h VPD page (Concurrent Positioning Ranges). Adding 4 is necessary as the first 4 bytes of the page is the header with page number and length information. Adding 3 was likely a misinterpretation of the SBC-5 specification which sets all offsets starting at zero. This fixes the error in dmesg: [ 9.014456] sd 1:0:0:0: [sda] Invalid Concurrent Positioning Ranges VPD page Link: https://lore.kernel.org/r/20220602225113.10218-4-tyler.erickson@seagate.com Fixes: e815d36548f0 ("scsi: sd: add concurrent positioning ranges support") Cc: stable@vger.kernel.org Tested-by: Michael English Reviewed-by: Muhammad Ahmad Reviewed-by: Damien Le Moal Reviewed-by: Hannes Reinecke Signed-off-by: Tyler Erickson Signed-off-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 895b56c8f25e..a1a2ac09066f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3072,7 +3072,7 @@ static void sd_read_cpr(struct scsi_disk *sdkp) goto out; /* We must have at least a 64B header and one 32B range descriptor */ - vpd_len = get_unaligned_be16(&buffer[2]) + 3; + vpd_len = get_unaligned_be16(&buffer[2]) + 4; if (vpd_len > buf_len || vpd_len < 64 + 32 || (vpd_len & 31)) { sd_printk(KERN_ERR, sdkp, "Invalid Concurrent Positioning Ranges VPD page\n"); -- cgit From cf71d59c2eceadfcde0fb52e237990a0909880d7 Mon Sep 17 00:00:00 2001 From: Wentao Wang Date: Thu, 2 Jun 2022 08:57:00 +0000 Subject: scsi: vmw_pvscsi: Expand vcpuHint to 16 bits vcpuHint has been expanded to 16 bit on host to enable routing to more CPUs. Guest side should align with the change. This change has been tested with hosts with 8-bit and 16-bit vcpuHint, on both platforms host side can get correct value. Link: https://lore.kernel.org/r/EF35F4D5-5DCC-42C5-BCC4-29DF1729B24C@vmware.com Signed-off-by: Wentao Wang Signed-off-by: Martin K. Petersen --- drivers/scsi/vmw_pvscsi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/vmw_pvscsi.h b/drivers/scsi/vmw_pvscsi.h index 51a82f7803d3..9d16cf925483 100644 --- a/drivers/scsi/vmw_pvscsi.h +++ b/drivers/scsi/vmw_pvscsi.h @@ -331,8 +331,8 @@ struct PVSCSIRingReqDesc { u8 tag; u8 bus; u8 target; - u8 vcpuHint; - u8 unused[59]; + u16 vcpuHint; + u8 unused[58]; } __packed; /* -- cgit From 44ba9786b67345dc4e5eabe537c9ef2bfd889888 Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 3 Jun 2022 10:43:21 -0700 Subject: scsi: lpfc: Correct BDE type for XMIT_SEQ64_WQE in lpfc_ct_reject_event() A previous commit assumed all XMIT_SEQ64_WQEs are prepped with the correct BDE type in word 0-2. However, lpfc_ct_reject_event() routine was missed and is still filling out the incorrect BDE type. Fix lpfc_ct_reject_event() routine so that type BUFF_TYPE_BDE_64 is set instead of BUFF_TYPE_BLP_64. Link: https://lore.kernel.org/r/20220603174329.63777-2-jsmart2021@gmail.com Fixes: 596fc8adb171 ("scsi: lpfc: Fix dmabuf ptr assignment in lpfc_ct_reject_event()") Co-developed-by: Justin Tee Signed-off-by: Justin Tee Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 9d36b20fb878..13dfe285493d 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -197,7 +197,7 @@ lpfc_ct_reject_event(struct lpfc_nodelist *ndlp, memset(bpl, 0, sizeof(struct ulp_bde64)); bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys)); bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys)); - bpl->tus.f.bdeFlags = BUFF_TYPE_BLP_64; + bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64; bpl->tus.f.bdeSize = (LPFC_CT_PREAMBLE - 4); bpl->tus.w = le32_to_cpu(bpl->tus.w); -- cgit From 24e1f056677eefe834d5dcf61905cce857ca4b19 Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 3 Jun 2022 10:43:22 -0700 Subject: scsi: lpfc: Resolve some cleanup issues following abort path refactoring Refactoring and consolidation of abort paths: - lpfc_sli4_abort_fcp_cmpl() and lpfc_sli_abort_fcp_cmpl() are combined into a single generic lpfc_sli_abort_fcp_cmpl() routine. Thus, remove extraneous lpfc_sli4_abort_fcp_cmpl() prototype declaration. - lpfc_nvme_abort_fcreq_cmpl() abort completion routine is called with a mismatched argument type. This may result in misleading log message content. Update to the correct argument type of lpfc_iocbq instead of lpfc_wcqe_complete. The lpfc_wcqe_complete should be derived from the lpfc_iocbq structure. Link: https://lore.kernel.org/r/20220603174329.63777-3-jsmart2021@gmail.com Fixes: 31a59f75702f ("scsi: lpfc: SLI path split: Refactor Abort paths") Cc: # v5.18 Co-developed-by: Justin Tee Signed-off-by: Justin Tee Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_crtn.h | 4 +--- drivers/scsi/lpfc/lpfc_nvme.c | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index b1be0dd0337a..f5d74958b664 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -420,8 +420,6 @@ int lpfc_sli_issue_iocb_wait(struct lpfc_hba *, uint32_t, uint32_t); void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *, struct lpfc_iocbq *, struct lpfc_iocbq *); -void lpfc_sli4_abort_fcp_cmpl(struct lpfc_hba *h, struct lpfc_iocbq *i, - struct lpfc_wcqe_complete *w); void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *); @@ -630,7 +628,7 @@ void lpfc_nvmet_invalidate_host(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp); void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - struct lpfc_wcqe_complete *abts_cmpl); + struct lpfc_iocbq *rspiocb); void lpfc_create_multixri_pools(struct lpfc_hba *phba); void lpfc_create_destroy_pools(struct lpfc_hba *phba); void lpfc_move_xri_pvt_to_pbl(struct lpfc_hba *phba, u32 hwqid); diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 335e90633933..88fa630ab93a 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -1787,7 +1787,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport, * lpfc_nvme_abort_fcreq_cmpl - Complete an NVME FCP abort request. * @phba: Pointer to HBA context object * @cmdiocb: Pointer to command iocb object. - * @abts_cmpl: Pointer to wcqe complete object. + * @rspiocb: Pointer to response iocb object. * * This is the callback function for any NVME FCP IO that was aborted. * @@ -1796,8 +1796,10 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport, **/ void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, - struct lpfc_wcqe_complete *abts_cmpl) + struct lpfc_iocbq *rspiocb) { + struct lpfc_wcqe_complete *abts_cmpl = &rspiocb->wcqe_cmpl; + lpfc_printf_log(phba, KERN_INFO, LOG_NVME, "6145 ABORT_XRI_CN completing on rpi x%x " "original iotag x%x, abort cmd iotag x%x " -- cgit From e27f05147bff21408c1b8410ad8e90cd286e7952 Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 3 Jun 2022 10:43:23 -0700 Subject: scsi: lpfc: Resolve some cleanup issues following SLI path refactoring Following refactoring and consolidation in SLI processing, fix up some minor issues related to SLI path: - Correct the setting of LPFC_EXCHANGE_BUSY flag in response IOCB. - Fix some typographical errors. - Fix duplicate log messages. Link: https://lore.kernel.org/r/20220603174329.63777-4-jsmart2021@gmail.com Fixes: 1b64aa9eae28 ("scsi: lpfc: SLI path split: Refactor fast and slow paths to native SLI4") Cc: # v5.18 Co-developed-by: Justin Tee Signed-off-by: Justin Tee Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 25 ++++++++++++------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 93b94c64518d..750dd1e9f2cc 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -12188,7 +12188,7 @@ lpfc_sli_enable_msi(struct lpfc_hba *phba) rc = pci_enable_msi(phba->pcidev); if (!rc) lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "0462 PCI enable MSI mode success.\n"); + "0012 PCI enable MSI mode success.\n"); else { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0471 PCI enable MSI mode failed (%d)\n", rc); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 6ed696c4602a..80ac3a051c19 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1930,7 +1930,7 @@ lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total) sync_buf = __lpfc_sli_get_iocbq(phba); if (!sync_buf) { lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT, - "6213 No available WQEs for CMF_SYNC_WQE\n"); + "6244 No available WQEs for CMF_SYNC_WQE\n"); ret_val = ENOMEM; goto out_unlock; } @@ -3805,7 +3805,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, set_job_ulpword4(cmdiocbp, IOERR_ABORT_REQUESTED); /* - * For SLI4, irsiocb contains + * For SLI4, irspiocb contains * NO_XRI in sli_xritag, it * shall not affect releasing * sgl (xri) process. @@ -3823,7 +3823,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } } } - (cmdiocbp->cmd_cmpl) (phba, cmdiocbp, saveq); + cmdiocbp->cmd_cmpl(phba, cmdiocbp, saveq); } else lpfc_sli_release_iocbq(phba, cmdiocbp); } else { @@ -4063,8 +4063,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, cmdiocbq->cmd_flag &= ~LPFC_DRIVER_ABORTED; if (cmdiocbq->cmd_cmpl) { spin_unlock_irqrestore(&phba->hbalock, iflag); - (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, - &rspiocbq); + cmdiocbq->cmd_cmpl(phba, cmdiocbq, &rspiocbq); spin_lock_irqsave(&phba->hbalock, iflag); } break; @@ -10288,7 +10287,7 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number, * @flag: Flag indicating if this command can be put into txq. * * __lpfc_sli_issue_fcp_io_s3 is wrapper function to invoke lockless func to - * send an iocb command to an HBA with SLI-4 interface spec. + * send an iocb command to an HBA with SLI-3 interface spec. * * This function takes the hbalock before invoking the lockless version. * The function will return success after it successfully submit the wqe to @@ -12740,7 +12739,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, cmdiocbq->cmd_cmpl = cmdiocbq->wait_cmd_cmpl; cmdiocbq->wait_cmd_cmpl = NULL; if (cmdiocbq->cmd_cmpl) - (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, NULL); + cmdiocbq->cmd_cmpl(phba, cmdiocbq, NULL); else lpfc_sli_release_iocbq(phba, cmdiocbq); return; @@ -12754,9 +12753,9 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, /* Set the exchange busy flag for task management commands */ if ((cmdiocbq->cmd_flag & LPFC_IO_FCP) && - !(cmdiocbq->cmd_flag & LPFC_IO_LIBDFC)) { + !(cmdiocbq->cmd_flag & LPFC_IO_LIBDFC)) { lpfc_cmd = container_of(cmdiocbq, struct lpfc_io_buf, - cur_iocbq); + cur_iocbq); if (rspiocbq && (rspiocbq->cmd_flag & LPFC_EXCHANGE_BUSY)) lpfc_cmd->flags |= LPFC_SBUF_XBUSY; else @@ -13896,7 +13895,7 @@ void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba) * @irspiocbq: Pointer to work-queue completion queue entry. * * This routine handles an ELS work-queue completion event and construct - * a pseudo response ELS IODBQ from the SLI4 ELS WCQE for the common + * a pseudo response ELS IOCBQ from the SLI4 ELS WCQE for the common * discovery engine to handle. * * Return: Pointer to the receive IOCBQ, NULL otherwise. @@ -13940,7 +13939,7 @@ lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba, if (bf_get(lpfc_wcqe_c_xb, wcqe)) { spin_lock_irqsave(&phba->hbalock, iflags); - cmdiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY; + irspiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY; spin_unlock_irqrestore(&phba->hbalock, iflags); } @@ -14799,7 +14798,7 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, /* Pass the cmd_iocb and the wcqe to the upper layer */ memcpy(&cmdiocbq->wcqe_cmpl, wcqe, sizeof(struct lpfc_wcqe_complete)); - (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, cmdiocbq); + cmdiocbq->cmd_cmpl(phba, cmdiocbq, cmdiocbq); } else { lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "0375 FCP cmdiocb not callback function " @@ -18956,7 +18955,7 @@ lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport, /* Free iocb created in lpfc_prep_seq */ list_for_each_entry_safe(curr_iocb, next_iocb, - &iocbq->list, list) { + &iocbq->list, list) { list_del_init(&curr_iocb->list); lpfc_sli_release_iocbq(phba, curr_iocb); } -- cgit From 6f808bd78e8296b4ded813b7182988d57e1f6176 Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 3 Jun 2022 10:43:24 -0700 Subject: scsi: lpfc: Address NULL pointer dereference after starget_to_rport() Calls to starget_to_rport() may return NULL. Add check for NULL rport before dereference. Link: https://lore.kernel.org/r/20220603174329.63777-5-jsmart2021@gmail.com Fixes: bb21fc9911ee ("scsi: lpfc: Use fc_block_rport()") Cc: # v5.18 Co-developed-by: Justin Tee Signed-off-by: Justin Tee Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_scsi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index d43968203248..ba5e4016262e 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -6062,6 +6062,9 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) int status; u32 logit = LOG_FCP; + if (!rport) + return FAILED; + rdata = rport->dd_data; if (!rdata || !rdata->pnode) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, @@ -6140,6 +6143,9 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) unsigned long flags; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); + if (!rport) + return FAILED; + rdata = rport->dd_data; if (!rdata || !rdata->pnode) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, -- cgit From b1b3440f437b75fb2a9b0cfe58df461e40eca474 Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 3 Jun 2022 10:43:25 -0700 Subject: scsi: lpfc: Resolve NULL ptr dereference after an ELS LOGO is aborted A use-after-free crash can occur after an ELS LOGO is aborted. Specifically, a nodelist structure is freed and then ndlp->vport->cfg_log_verbose is dereferenced in lpfc_nlp_get() when the discovery state machine is mistakenly called a second time with NLP_EVT_DEVICE_RM argument. Rework lpfc_cmpl_els_logo() to prevent the duplicate calls to release a nodelist structure. Link: https://lore.kernel.org/r/20220603174329.63777-6-jsmart2021@gmail.com Co-developed-by: Justin Tee Signed-off-by: Justin Tee Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 07f9a6e61e10..3fababb7c181 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -2998,10 +2998,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp->nlp_DID, ulp_status, ulp_word4); - /* Call NLP_EVT_DEVICE_RM if link is down or LOGO is aborted */ if (lpfc_error_lost_link(ulp_status, ulp_word4)) { - lpfc_disc_state_machine(vport, ndlp, cmdiocb, - NLP_EVT_DEVICE_RM); skip_recovery = 1; goto out; } @@ -3021,18 +3018,10 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, spin_unlock_irq(&ndlp->lock); lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_DEVICE_RM); - lpfc_els_free_iocb(phba, cmdiocb); - lpfc_nlp_put(ndlp); - - /* Presume the node was released. */ - return; + goto out_rsrc_free; } out: - /* Driver is done with the IO. */ - lpfc_els_free_iocb(phba, cmdiocb); - lpfc_nlp_put(ndlp); - /* At this point, the LOGO processing is complete. NOTE: For a * pt2pt topology, we are assuming the NPortID will only change * on link up processing. For a LOGO / PLOGI initiated by the @@ -3059,6 +3048,10 @@ out: ndlp->nlp_DID, ulp_status, ulp_word4, tmo, vport->num_disc_nodes); + + lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); + lpfc_disc_start(vport); return; } @@ -3075,6 +3068,10 @@ out: lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_DEVICE_RM); } +out_rsrc_free: + /* Driver is done with the I/O. */ + lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); } /** -- cgit From 336d63615466b4c06b9401c987813fd19bdde39b Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 3 Jun 2022 10:43:26 -0700 Subject: scsi: lpfc: Fix port stuck in bypassed state after LIP in PT2PT topology After issuing a LIP, a specific target vendor does not ACC the FLOGI that lpfc sends. However, it does send its own FLOGI that lpfc ACCs. The target then establishes the port IDs by sending a PLOGI. lpfc PLOGI_ACCs and starts the RPI registration for DID 0x000001. The target then sends a LOGO to the fabric DID. lpfc is currently treating the LOGO from the fabric DID as a link down and cleans up all the ndlps. The ndlp for DID 0x000001 is put back into NPR and discovery stops, leaving the port in stuck in bypassed mode. Change lpfc behavior such that if a LOGO is received for the fabric DID in PT2PT topology skip the lpfc_linkdown_port() routine and just move the fabric DID back to NPR. Link: https://lore.kernel.org/r/20220603174329.63777-7-jsmart2021@gmail.com Co-developed-by: Justin Tee Signed-off-by: Justin Tee Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nportdisc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 639f86635127..b86ff9fcdf0c 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -834,7 +834,8 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_nvmet_invalidate_host(phba, ndlp); if (ndlp->nlp_DID == Fabric_DID) { - if (vport->port_state <= LPFC_FDISC) + if (vport->port_state <= LPFC_FDISC || + vport->fc_flag & FC_PT2PT) goto out; lpfc_linkdown_port(vport); spin_lock_irq(shost->host_lock); -- cgit From ea7bd1f393311e823716a232e9d8857fb64eb105 Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 3 Jun 2022 10:43:27 -0700 Subject: scsi: lpfc: Add more logging of cmd and cqe information for aborted NVMe cmds When an NVMe command is aborted or completes with an ERSP, log the opcode and command ID fields to help provide more detail on the failed command. Link: https://lore.kernel.org/r/20220603174329.63777-8-jsmart2021@gmail.com Co-developed-by: Justin Tee Signed-off-by: Justin Tee Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvme.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 88fa630ab93a..9cc22cefcb37 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -1065,25 +1065,37 @@ lpfc_nvme_io_cmd_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, nCmd->rcv_rsplen = wcqe->parameter; nCmd->status = 0; + /* Get the NVME cmd details for this unique error. */ + cp = (struct nvme_fc_cmd_iu *)nCmd->cmdaddr; + ep = (struct nvme_fc_ersp_iu *)nCmd->rspaddr; + /* Check if this is really an ERSP */ if (nCmd->rcv_rsplen == LPFC_NVME_ERSP_LEN) { lpfc_ncmd->status = IOSTAT_SUCCESS; lpfc_ncmd->result = 0; lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME, - "6084 NVME Completion ERSP: " - "xri %x placed x%x\n", - lpfc_ncmd->cur_iocbq.sli4_xritag, - wcqe->total_data_placed); + "6084 NVME FCP_ERR ERSP: " + "xri %x placed x%x opcode x%x cmd_id " + "x%x cqe_status x%x\n", + lpfc_ncmd->cur_iocbq.sli4_xritag, + wcqe->total_data_placed, + cp->sqe.common.opcode, + cp->sqe.common.command_id, + ep->cqe.status); break; } lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6081 NVME Completion Protocol Error: " "xri %x status x%x result x%x " - "placed x%x\n", + "placed x%x opcode x%x cmd_id x%x, " + "cqe_status x%x\n", lpfc_ncmd->cur_iocbq.sli4_xritag, lpfc_ncmd->status, lpfc_ncmd->result, - wcqe->total_data_placed); + wcqe->total_data_placed, + cp->sqe.common.opcode, + cp->sqe.common.command_id, + ep->cqe.status); break; case IOSTAT_LOCAL_REJECT: /* Let fall through to set command final state. */ @@ -1842,6 +1854,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, struct lpfc_nvme_fcpreq_priv *freqpriv; unsigned long flags; int ret_val; + struct nvme_fc_cmd_iu *cp; /* Validate pointers. LLDD fault handling with transport does * have timing races. @@ -1965,10 +1978,16 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, return; } + /* + * Get Command Id from cmd to plug into response. This + * code is not needed in the next NVME Transport drop. + */ + cp = (struct nvme_fc_cmd_iu *)lpfc_nbuf->nvmeCmd->cmdaddr; lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_ABTS, "6138 Transport Abort NVME Request Issued for " - "ox_id x%x\n", - nvmereq_wqe->sli4_xritag); + "ox_id x%x nvme opcode x%x nvme cmd_id x%x\n", + nvmereq_wqe->sli4_xritag, cp->sqe.common.opcode, + cp->sqe.common.command_id); return; out_unlock: -- cgit From 2e7e9c0c1ec05f18d320ecc8a31eec59d2af1af9 Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 3 Jun 2022 10:43:28 -0700 Subject: scsi: lpfc: Allow reduced polling rate for nvme_admin_async_event cmd completion NVMe Asynchronous Event Request commands have no command timeout value per specifications. Set WQE option to allow a reduced FLUSH polling rate for I/O error detection specifically for nvme_admin_async_event commands. Link: https://lore.kernel.org/r/20220603174329.63777-9-jsmart2021@gmail.com Co-developed-by: Justin Tee Signed-off-by: Justin Tee Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hw4.h | 3 +++ drivers/scsi/lpfc/lpfc_nvme.c | 11 +++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 8511369d2cf8..f024415731ac 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -4487,6 +4487,9 @@ struct wqe_common { #define wqe_sup_SHIFT 6 #define wqe_sup_MASK 0x00000001 #define wqe_sup_WORD word11 +#define wqe_ffrq_SHIFT 6 +#define wqe_ffrq_MASK 0x00000001 +#define wqe_ffrq_WORD word11 #define wqe_wqec_SHIFT 7 #define wqe_wqec_MASK 0x00000001 #define wqe_wqec_WORD word11 diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 9cc22cefcb37..cd10ee6482fc 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -1207,7 +1207,8 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, { struct lpfc_hba *phba = vport->phba; struct nvmefc_fcp_req *nCmd = lpfc_ncmd->nvmeCmd; - struct lpfc_iocbq *pwqeq = &(lpfc_ncmd->cur_iocbq); + struct nvme_common_command *sqe; + struct lpfc_iocbq *pwqeq = &lpfc_ncmd->cur_iocbq; union lpfc_wqe128 *wqe = &pwqeq->wqe; uint32_t req_len; @@ -1264,8 +1265,14 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, cstat->control_requests++; } - if (pnode->nlp_nvme_info & NLP_NVME_NSLER) + if (pnode->nlp_nvme_info & NLP_NVME_NSLER) { bf_set(wqe_erp, &wqe->generic.wqe_com, 1); + sqe = &((struct nvme_fc_cmd_iu *) + nCmd->cmdaddr)->sqe.common; + if (sqe->opcode == nvme_admin_async_event) + bf_set(wqe_ffrq, &wqe->generic.wqe_com, 1); + } + /* * Finish initializing those WQE fields that are independent * of the nvme_cmnd request_buffer -- cgit From 1af48fffd7ffe280e0c225659d826fd5ae802a08 Mon Sep 17 00:00:00 2001 From: James Smart Date: Fri, 3 Jun 2022 10:43:29 -0700 Subject: scsi: lpfc: Update lpfc version to 14.2.0.4 Update lpfc version to 14.2.0.4 Link: https://lore.kernel.org/r/20220603174329.63777-10-jsmart2021@gmail.com Co-developed-by: Justin Tee Signed-off-by: Justin Tee Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 4fab79ed58ed..2ab6f7db64d8 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "14.2.0.3" +#define LPFC_DRIVER_VERSION "14.2.0.4" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ -- cgit From 120f1d95efb1cdb6fe023c84e38ba06d8f78cd03 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 31 May 2022 22:09:27 +0200 Subject: scsi: mpt3sas: Fix out-of-bounds compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm facing this warning when building for the parisc64 architecture: drivers/scsi/mpt3sas/mpt3sas_base.c: In function ‘_base_make_ioc_operational’: drivers/scsi/mpt3sas/mpt3sas_base.c:5396:40: warning: array subscript ‘Mpi2SasIOUnitPage1_t {aka struct _MPI2_CONFIG_PAGE_SASIOUNIT_1}[0]’ is partly outside array bounds of ‘unsigned char[20]’ [-Warray-bounds] 5396 | (le16_to_cpu(sas_iounit_pg1->SASWideMaxQueueDepth)) ? drivers/scsi/mpt3sas/mpt3sas_base.c:5382:26: note: referencing an object of size 20 allocated by ‘kzalloc’ 5382 | sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); | ^~~~~~~~~~~~~~~~~~~~~~~ The problem is, that only 20 bytes are allocated with kmalloc(), which is sufficient to hold the bytes which are needed. Nevertheless, gcc complains because the whole Mpi2SasIOUnitPage1_t struct is 32 bytes in size and thus doesn't fit into those 20 bytes. This patch simply allocates all 32 bytes (instead of 20) and thus avoids the warning. There is no functional change introduced by this patch. While touching the code I cleaned up to calculation of max_wideport_qd, max_narrowport_qd and max_sata_qd to make it easier readable. Test successfully tested on a HP C8000 PA-RISC workstation with 64-bit kernel. Link: https://lore.kernel.org/r/YpZ197iZdDZSCzrT@p100 Signed-off-by: Helge Deller Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 37d46ae5c61d..9a1ae52bb621 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -5369,6 +5369,7 @@ static int _base_assign_fw_reported_qd(struct MPT3SAS_ADAPTER *ioc) Mpi2ConfigReply_t mpi_reply; Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; Mpi26PCIeIOUnitPage1_t pcie_iounit_pg1; + u16 depth; int sz; int rc = 0; @@ -5380,7 +5381,7 @@ static int _base_assign_fw_reported_qd(struct MPT3SAS_ADAPTER *ioc) goto out; /* sas iounit page 1 */ sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData); - sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); + sas_iounit_pg1 = kzalloc(sizeof(Mpi2SasIOUnitPage1_t), GFP_KERNEL); if (!sas_iounit_pg1) { pr_err("%s: failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, __func__); @@ -5393,16 +5394,16 @@ static int _base_assign_fw_reported_qd(struct MPT3SAS_ADAPTER *ioc) ioc->name, __FILE__, __LINE__, __func__); goto out; } - ioc->max_wideport_qd = - (le16_to_cpu(sas_iounit_pg1->SASWideMaxQueueDepth)) ? - le16_to_cpu(sas_iounit_pg1->SASWideMaxQueueDepth) : - MPT3SAS_SAS_QUEUE_DEPTH; - ioc->max_narrowport_qd = - (le16_to_cpu(sas_iounit_pg1->SASNarrowMaxQueueDepth)) ? - le16_to_cpu(sas_iounit_pg1->SASNarrowMaxQueueDepth) : - MPT3SAS_SAS_QUEUE_DEPTH; - ioc->max_sata_qd = (sas_iounit_pg1->SATAMaxQDepth) ? - sas_iounit_pg1->SATAMaxQDepth : MPT3SAS_SATA_QUEUE_DEPTH; + + depth = le16_to_cpu(sas_iounit_pg1->SASWideMaxQueueDepth); + ioc->max_wideport_qd = (depth ? depth : MPT3SAS_SAS_QUEUE_DEPTH); + + depth = le16_to_cpu(sas_iounit_pg1->SASNarrowMaxQueueDepth); + ioc->max_narrowport_qd = (depth ? depth : MPT3SAS_SAS_QUEUE_DEPTH); + + depth = sas_iounit_pg1->SATAMaxQDepth; + ioc->max_sata_qd = (depth ? depth : MPT3SAS_SATA_QUEUE_DEPTH); + /* pcie iounit page 1 */ rc = mpt3sas_config_get_pcie_iounit_pg1(ioc, &mpi_reply, &pcie_iounit_pg1, sizeof(Mpi26PCIeIOUnitPage1_t)); -- cgit From d64c491911322af1dcada98e5b9ee0d87e8c8fee Mon Sep 17 00:00:00 2001 From: Chengguang Xu Date: Sun, 29 May 2022 23:34:53 +0800 Subject: scsi: ipr: Fix missing/incorrect resource cleanup in error case Fix missing resource cleanup (when '(--i) == 0') for error case in ipr_alloc_mem() and skip incorrect resource cleanup (when '(--i) == 0') for error case in ipr_request_other_msi_irqs() because variable i started from 1. Link: https://lore.kernel.org/r/20220529153456.4183738-4-cgxu519@mykernel.net Reviewed-by: Dan Carpenter Acked-by: Brian King Signed-off-by: Chengguang Xu Signed-off-by: Martin K. Petersen --- drivers/scsi/ipr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 256ec6d08c16..9d01a3e3c26a 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -9795,7 +9795,7 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) GFP_KERNEL); if (!ioa_cfg->hrrq[i].host_rrq) { - while (--i > 0) + while (--i >= 0) dma_free_coherent(&pdev->dev, sizeof(u32) * ioa_cfg->hrrq[i].size, ioa_cfg->hrrq[i].host_rrq, @@ -10068,7 +10068,7 @@ static int ipr_request_other_msi_irqs(struct ipr_ioa_cfg *ioa_cfg, ioa_cfg->vectors_info[i].desc, &ioa_cfg->hrrq[i]); if (rc) { - while (--i >= 0) + while (--i > 0) free_irq(pci_irq_vector(pdev, i), &ioa_cfg->hrrq[i]); return rc; -- cgit From ec1e8adcbdf661c57c395bca342945f4f815add7 Mon Sep 17 00:00:00 2001 From: Chengguang Xu Date: Sun, 29 May 2022 23:34:55 +0800 Subject: scsi: pmcraid: Fix missing resource cleanup in error case Fix missing resource cleanup (when '(--i) == 0') for error case in pmcraid_register_interrupt_handler(). Link: https://lore.kernel.org/r/20220529153456.4183738-6-cgxu519@mykernel.net Reviewed-by: Dan Carpenter Signed-off-by: Chengguang Xu Signed-off-by: Martin K. Petersen --- drivers/scsi/pmcraid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index bfce60183a6e..836ddc476764 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -4031,7 +4031,7 @@ pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance) return 0; out_unwind: - while (--i > 0) + while (--i >= 0) free_irq(pci_irq_vector(pdev, i), &pinstance->hrrq_vector[i]); pci_free_irq_vectors(pdev); return rc; -- cgit From 255b4658c809e194bc10236ac24a722ec14a83d6 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Sun, 5 Jun 2022 16:19:53 +0800 Subject: LoongArch: Fix the !CONFIG_SMP build 1, We assume arch/loongarch/include/asm/smp.h be included in include/ linux/smp.h is valid and the reverse inclusion isn't. So remove the in arch/loongarch/include/asm/smp.h. 2, arch/loongarch/include/asm/smp.h is only needed when CONFIG_SMP, and setup.c include it only because it need plat_smp_setup(). So, reorganize setup.c & smp.h, and then remove in setup.c. 3, Fix cacheinfo.c and percpu.h build error by adding the missing header files when !CONFIG_SMP. 4, Fix acpi.c build error by adding CONFIG_SMP guards. 5, Move irq_stat definition from smp.c to irq.c and fix its declaration. 6, Select CONFIG_SMP for CONFIG_NUMA, similar as other architectures do. Signed-off-by: Huacai Chen --- arch/loongarch/Kconfig | 1 + arch/loongarch/include/asm/hardirq.h | 2 +- arch/loongarch/include/asm/percpu.h | 1 + arch/loongarch/include/asm/smp.h | 23 +++++++---------------- arch/loongarch/kernel/acpi.c | 4 ++++ arch/loongarch/kernel/cacheinfo.c | 1 + arch/loongarch/kernel/irq.c | 7 ++++++- arch/loongarch/kernel/setup.c | 5 ++--- arch/loongarch/kernel/smp.c | 2 -- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index 80657bf83b05..1920d52653b4 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -343,6 +343,7 @@ config NR_CPUS config NUMA bool "NUMA Support" + select SMP select ACPI_NUMA if ACPI help Say Y to compile the kernel with NUMA (Non-Uniform Memory Access) diff --git a/arch/loongarch/include/asm/hardirq.h b/arch/loongarch/include/asm/hardirq.h index befe8184aa08..0ef3b18f8980 100644 --- a/arch/loongarch/include/asm/hardirq.h +++ b/arch/loongarch/include/asm/hardirq.h @@ -19,7 +19,7 @@ typedef struct { unsigned int __softirq_pending; } ____cacheline_aligned irq_cpustat_t; -DECLARE_PER_CPU_ALIGNED(irq_cpustat_t, irq_stat); +DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); #define __ARCH_IRQ_STAT diff --git a/arch/loongarch/include/asm/percpu.h b/arch/loongarch/include/asm/percpu.h index 34f15a6fb1e7..e6569f18c6dd 100644 --- a/arch/loongarch/include/asm/percpu.h +++ b/arch/loongarch/include/asm/percpu.h @@ -6,6 +6,7 @@ #define __ASM_PERCPU_H #include +#include /* Use r21 for fast access */ register unsigned long __my_cpu_offset __asm__("$r21"); diff --git a/arch/loongarch/include/asm/smp.h b/arch/loongarch/include/asm/smp.h index 551e1f37c705..71189b28bfb2 100644 --- a/arch/loongarch/include/asm/smp.h +++ b/arch/loongarch/include/asm/smp.h @@ -9,10 +9,16 @@ #include #include #include -#include #include #include +extern int smp_num_siblings; +extern int num_processors; +extern int disabled_cpus; +extern cpumask_t cpu_sibling_map[]; +extern cpumask_t cpu_core_map[]; +extern cpumask_t cpu_foreign_map[]; + void loongson3_smp_setup(void); void loongson3_prepare_cpus(unsigned int max_cpus); void loongson3_boot_secondary(int cpu, struct task_struct *idle); @@ -25,26 +31,11 @@ int loongson3_cpu_disable(void); void loongson3_cpu_die(unsigned int cpu); #endif -#ifdef CONFIG_SMP - static inline void plat_smp_setup(void) { loongson3_smp_setup(); } -#else /* !CONFIG_SMP */ - -static inline void plat_smp_setup(void) { } - -#endif /* !CONFIG_SMP */ - -extern int smp_num_siblings; -extern int num_processors; -extern int disabled_cpus; -extern cpumask_t cpu_sibling_map[]; -extern cpumask_t cpu_core_map[]; -extern cpumask_t cpu_foreign_map[]; - static inline int raw_smp_processor_id(void) { #if defined(__VDSO__) diff --git a/arch/loongarch/kernel/acpi.c b/arch/loongarch/kernel/acpi.c index b16c3dea5eeb..bb729ee8a237 100644 --- a/arch/loongarch/kernel/acpi.c +++ b/arch/loongarch/kernel/acpi.c @@ -138,6 +138,7 @@ void __init acpi_boot_table_init(void) } } +#ifdef CONFIG_SMP static int set_processor_mask(u32 id, u32 flags) { @@ -166,15 +167,18 @@ static int set_processor_mask(u32 id, u32 flags) return cpu; } +#endif static void __init acpi_process_madt(void) { +#ifdef CONFIG_SMP int i; for (i = 0; i < NR_CPUS; i++) { __cpu_number_map[i] = -1; __cpu_logical_map[i] = -1; } +#endif loongson_sysconf.nr_cpus = num_processors; } diff --git a/arch/loongarch/kernel/cacheinfo.c b/arch/loongarch/kernel/cacheinfo.c index 8c9fe29e98f0..b38f5489d094 100644 --- a/arch/loongarch/kernel/cacheinfo.c +++ b/arch/loongarch/kernel/cacheinfo.c @@ -4,6 +4,7 @@ * * Copyright (C) 2020-2022 Loongson Technology Corporation Limited */ +#include #include /* Populates leaf and increments to next leaf */ diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index 4b671d305ede..b34b8d792aa4 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -22,6 +22,8 @@ #include DEFINE_PER_CPU(unsigned long, irq_stack); +DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); +EXPORT_PER_CPU_SYMBOL(irq_stat); struct irq_domain *cpu_domain; struct irq_domain *liointc_domain; @@ -56,8 +58,11 @@ int arch_show_interrupts(struct seq_file *p, int prec) void __init init_IRQ(void) { - int i, r, ipi_irq; + int i; +#ifdef CONFIG_SMP + int r, ipi_irq; static int ipi_dummy_dev; +#endif unsigned int order = get_order(IRQ_STACK_SIZE); struct page *page; diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index 185e4035811a..c74860b53375 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #define SMBIOS_BIOSSIZE_OFFSET 0x09 @@ -349,8 +348,6 @@ static void __init prefill_possible_map(void) nr_cpu_ids = possible; } -#else -static inline void prefill_possible_map(void) {} #endif void __init setup_arch(char **cmdline_p) @@ -367,8 +364,10 @@ void __init setup_arch(char **cmdline_p) arch_mem_init(cmdline_p); resource_init(); +#ifdef CONFIG_SMP plat_smp_setup(); prefill_possible_map(); +#endif paging_init(); } diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index b8c53b755a25..73cec62504fb 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -66,8 +66,6 @@ static cpumask_t cpu_core_setup_map; struct secondary_data cpuboot_data; static DEFINE_PER_CPU(int, cpu_state); -DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); -EXPORT_PER_CPU_SYMBOL(irq_stat); enum ipi_msg_type { IPI_RESCHEDULE, -- cgit From 0626e1c9f3e5536545431538d12c762d5abf59c8 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Sun, 5 Jun 2022 16:20:03 +0800 Subject: LoongArch: Fix copy_thread() build errors Commit c5febea0956fd387 ("fork: Pass struct kernel_clone_args into copy_thread") change the prototype of copy_thread(), while commit 5bd2e97c868a8a44 ("fork: Generalize PF_IO_WORKER handling") change the structure of kernel_clone_args. They cause build errors, so fix it. Fixes: 5bd2e97c868a8a44 ("fork: Generalize PF_IO_WORKER handling") Fixes: c5febea0956fd387 ("fork: Pass struct kernel_clone_args into copy_thread") Signed-off-by: Huacai Chen --- arch/loongarch/kernel/process.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/loongarch/kernel/process.c b/arch/loongarch/kernel/process.c index 6d944d65f600..bfa0dfe8b7d7 100644 --- a/arch/loongarch/kernel/process.c +++ b/arch/loongarch/kernel/process.c @@ -120,10 +120,12 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) /* * Copy architecture-specific thread state */ -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long kthread_arg, struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) { unsigned long childksp; + unsigned long tls = args->tls; + unsigned long usp = args->stack; + unsigned long clone_flags = args->flags; struct pt_regs *childregs, *regs = current_pt_regs(); childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32; @@ -136,12 +138,12 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, p->thread.csr_crmd = csr_read32(LOONGARCH_CSR_CRMD); p->thread.csr_prmd = csr_read32(LOONGARCH_CSR_PRMD); p->thread.csr_ecfg = csr_read32(LOONGARCH_CSR_ECFG); - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { /* kernel thread */ - p->thread.reg23 = usp; /* fn */ - p->thread.reg24 = kthread_arg; p->thread.reg03 = childksp; - p->thread.reg01 = (unsigned long) ret_from_kernel_thread; + p->thread.reg23 = (unsigned long)args->fn; + p->thread.reg24 = (unsigned long)args->fn_arg; + p->thread.reg01 = (unsigned long)ret_from_kernel_thread; memset(childregs, 0, sizeof(struct pt_regs)); childregs->csr_euen = p->thread.csr_euen; childregs->csr_crmd = p->thread.csr_crmd; -- cgit From 5c95fe8b02011c3b69173e0d86aff6d4c2798601 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sun, 5 Jun 2022 16:20:08 +0800 Subject: LoongArch: Remove MIPS comment about cycle counter This comment block was taken originally from the MIPS architecture code, where indeed there are particular assumptions one can make regarding SMP and !SMP and cycle counters. On LoongArch, however, the rdtime family of functions is always available. As Xuerui wrote: The rdtime family of instructions is in fact guaranteed to be available on LoongArch; LoongArch's subsets all contain them, even the 32-bit "Primary" subset intended for university teaching -- they provide the rdtimeh.w and rdtimel.w pair of instructions that access the same 64-bit counter. So this commit simply removes the incorrect comment block. Link: https://lore.kernel.org/lkml/e78940bc-9be2-2fe7-026f-9e64a1416c9f@xen0n.name/ Fixes: b738c106f735 ("LoongArch: Add other common headers") Reviewed-by: WANG Xuerui Signed-off-by: Jason A. Donenfeld Signed-off-by: Huacai Chen --- arch/loongarch/include/asm/timex.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/loongarch/include/asm/timex.h b/arch/loongarch/include/asm/timex.h index d3ed99a4fdbd..fb41e9e7a222 100644 --- a/arch/loongarch/include/asm/timex.h +++ b/arch/loongarch/include/asm/timex.h @@ -12,13 +12,6 @@ #include #include -/* - * Standard way to access the cycle counter. - * Currently only used on SMP for scheduling. - * - * We know that all SMP capable CPUs have cycle counters. - */ - typedef unsigned long cycles_t; #define get_cycles get_cycles -- cgit From c745dfc541e78428ba3986f1d17fe1dfdaca8184 Mon Sep 17 00:00:00 2001 From: Tyler Erickson Date: Thu, 2 Jun 2022 16:51:11 -0600 Subject: libata: fix reading concurrent positioning ranges log The concurrent positioning ranges log is not a fixed size and may depend on how many ranges are supported by the device. This patch uses the size reported in the GPL directory to determine the number of pages supported by the device before attempting to read this log page. This resolves this error from the dmesg output: ata6.00: Read log 0x47 page 0x00 failed, Emask 0x1 Cc: stable@vger.kernel.org Fixes: fe22e1c2f705 ("libata: support concurrent positioning ranges log") Signed-off-by: Tyler Erickson Reviewed-by: Muhammad Ahmad Tested-by: Michael English Signed-off-by: Damien Le Moal --- drivers/ata/libata-core.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c214ff928e45..9601fa92950a 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2010,16 +2010,16 @@ retry: return err_mask; } -static bool ata_log_supported(struct ata_device *dev, u8 log) +static int ata_log_supported(struct ata_device *dev, u8 log) { struct ata_port *ap = dev->link->ap; if (dev->horkage & ATA_HORKAGE_NO_LOG_DIR) - return false; + return 0; if (ata_read_log_page(dev, ATA_LOG_DIRECTORY, 0, ap->sector_buf, 1)) - return false; - return get_unaligned_le16(&ap->sector_buf[log * 2]) ? true : false; + return 0; + return get_unaligned_le16(&ap->sector_buf[log * 2]); } static bool ata_identify_page_supported(struct ata_device *dev, u8 page) @@ -2455,15 +2455,20 @@ static void ata_dev_config_cpr(struct ata_device *dev) struct ata_cpr_log *cpr_log = NULL; u8 *desc, *buf = NULL; - if (ata_id_major_version(dev->id) < 11 || - !ata_log_supported(dev, ATA_LOG_CONCURRENT_POSITIONING_RANGES)) + if (ata_id_major_version(dev->id) < 11) + goto out; + + buf_len = ata_log_supported(dev, ATA_LOG_CONCURRENT_POSITIONING_RANGES); + if (buf_len == 0) goto out; /* * Read the concurrent positioning ranges log (0x47). We can have at - * most 255 32B range descriptors plus a 64B header. + * most 255 32B range descriptors plus a 64B header. This log varies in + * size, so use the size reported in the GPL directory. Reading beyond + * the supported length will result in an error. */ - buf_len = (64 + 255 * 32 + 511) & ~511; + buf_len <<= 9; buf = kzalloc(buf_len, GFP_KERNEL); if (!buf) goto out; -- cgit From 6d11acd452fd885ef6ace184c9c70bc863a8c72f Mon Sep 17 00:00:00 2001 From: Tyler Erickson Date: Thu, 2 Jun 2022 16:51:12 -0600 Subject: libata: fix translation of concurrent positioning ranges Fixing the page length in the SCSI translation for the concurrent positioning ranges VPD page. It was writing starting in offset 3 rather than offset 2 where the MSB is supposed to start for the VPD page length. Cc: stable@vger.kernel.org Fixes: fe22e1c2f705 ("libata: support concurrent positioning ranges log") Signed-off-by: Tyler Erickson Reviewed-by: Muhammad Ahmad Tested-by: Michael English Reviewed-by: Hannes Reinecke Signed-off-by: Damien Le Moal --- drivers/ata/libata-scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 42cecf95a4e5..86dbb1cdfabd 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2125,7 +2125,7 @@ static unsigned int ata_scsiop_inq_b9(struct ata_scsi_args *args, u8 *rbuf) /* SCSI Concurrent Positioning Ranges VPD page: SBC-5 rev 1 or later */ rbuf[1] = 0xb9; - put_unaligned_be16(64 + (int)cpr_log->nr_cpr * 32 - 4, &rbuf[3]); + put_unaligned_be16(64 + (int)cpr_log->nr_cpr * 32 - 4, &rbuf[2]); for (i = 0; i < cpr_log->nr_cpr; i++, desc += 32) { desc[0] = cpr_log->cpr[i].num; -- cgit From 0737e018a05e2aa352828c52bdeed3b02cff2930 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Sun, 5 Jun 2022 11:23:34 +0400 Subject: net: dsa: lantiq_gswip: Fix refcount leak in gswip_gphy_fw_list Every iteration of for_each_available_child_of_node() decrements the reference count of the previous node. when breaking early from a for_each_available_child_of_node() loop, we need to explicitly call of_node_put() on the gphy_fw_np. Add missing of_node_put() to avoid refcount leak. Fixes: 14fceff4771e ("net: dsa: Add Lantiq / Intel DSA driver for vrx200") Signed-off-by: Miaoqian Lin Link: https://lore.kernel.org/r/20220605072335.11257-1-linmq006@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/lantiq_gswip.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index 8af4def38a98..e531b93f3cb2 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -2070,8 +2070,10 @@ static int gswip_gphy_fw_list(struct gswip_priv *priv, for_each_available_child_of_node(gphy_fw_list_np, gphy_fw_np) { err = gswip_gphy_fw_probe(priv, &priv->gphy_fw[i], gphy_fw_np, i); - if (err) + if (err) { + of_node_put(gphy_fw_np); goto remove_gphy; + } i++; } -- cgit From f5826c8c9d57210a17031af5527056eefdc2b7eb Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Mon, 6 Jun 2022 14:57:18 +0300 Subject: net/mlx4_en: Fix wrong return value on ioctl EEPROM query failure The ioctl EEPROM query wrongly returns success on read failures, fix that by returning the appropriate error code. Fixes: 7202da8b7f71 ("ethtool, net/mlx4_en: Cable info, get_module_info/eeprom ethtool support") Signed-off-by: Gal Pressman Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20220606115718.14233-1-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index ed5038d98ef6..6400a827173c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -2110,7 +2110,7 @@ static int mlx4_en_get_module_eeprom(struct net_device *dev, en_err(priv, "mlx4_get_module_info i(%d) offset(%d) bytes_to_read(%d) - FAILED (0x%x)\n", i, offset, ee->len - i, ret); - return 0; + return ret; } i += ret; -- cgit From a2a513be7139b279f1b5b2cee59c6c4950c34346 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 2 Jun 2022 23:16:57 +0900 Subject: zonefs: fix handling of explicit_open option on mount Ignoring the explicit_open mount option on mount for devices that do not have a limit on the number of open zones must be done after the mount options are parsed and set in s_mount_opts. Move the check to ignore the explicit_open option after the call to zonefs_parse_options() in zonefs_fill_super(). Fixes: b5c00e975779 ("zonefs: open/close zone on file open/close") Cc: Signed-off-by: Damien Le Moal Reviewed-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn --- fs/zonefs/super.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c index bcb21aea990a..ecce84909ca1 100644 --- a/fs/zonefs/super.c +++ b/fs/zonefs/super.c @@ -1760,12 +1760,6 @@ static int zonefs_fill_super(struct super_block *sb, void *data, int silent) atomic_set(&sbi->s_wro_seq_files, 0); sbi->s_max_wro_seq_files = bdev_max_open_zones(sb->s_bdev); - if (!sbi->s_max_wro_seq_files && - sbi->s_mount_opts & ZONEFS_MNTOPT_EXPLICIT_OPEN) { - zonefs_info(sb, "No open zones limit. Ignoring explicit_open mount option\n"); - sbi->s_mount_opts &= ~ZONEFS_MNTOPT_EXPLICIT_OPEN; - } - atomic_set(&sbi->s_active_seq_files, 0); sbi->s_max_active_seq_files = bdev_max_active_zones(sb->s_bdev); @@ -1790,6 +1784,12 @@ static int zonefs_fill_super(struct super_block *sb, void *data, int silent) zonefs_info(sb, "Mounting %u zones", blkdev_nr_zones(sb->s_bdev->bd_disk)); + if (!sbi->s_max_wro_seq_files && + sbi->s_mount_opts & ZONEFS_MNTOPT_EXPLICIT_OPEN) { + zonefs_info(sb, "No open zones limit. Ignoring explicit_open mount option\n"); + sbi->s_mount_opts &= ~ZONEFS_MNTOPT_EXPLICIT_OPEN; + } + /* Create root directory inode */ ret = -ENOMEM; inode = new_inode(sb); -- cgit From 96eca145cb51f4e0132a3ea8066dfc6fdf75f24a Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 2 Jun 2022 21:33:25 +0900 Subject: zonefs: Do not ignore explicit_open with active zone limit A zoned device may have no limit on the number of open zones but may have a limit on the number of active zones it can support. In such case, the explicit_open mount option should not be ignored to ensure that the open() system call activates the zone with an explicit zone open command, thus guaranteeing that the zone can be written. Enforce this by ignoring the explicit_open mount option only for devices that have both the open and active zone limits equal to 0. Fixes: 87c9ce3ffec9 ("zonefs: Add active seq file accounting") Signed-off-by: Damien Le Moal Reviewed-by: Christoph Hellwig --- fs/zonefs/super.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c index ecce84909ca1..123464d2145a 100644 --- a/fs/zonefs/super.c +++ b/fs/zonefs/super.c @@ -1085,7 +1085,8 @@ static int zonefs_seq_file_write_open(struct inode *inode) if (sbi->s_mount_opts & ZONEFS_MNTOPT_EXPLICIT_OPEN) { - if (wro > sbi->s_max_wro_seq_files) { + if (sbi->s_max_wro_seq_files + && wro > sbi->s_max_wro_seq_files) { atomic_dec(&sbi->s_wro_seq_files); ret = -EBUSY; goto unlock; @@ -1785,8 +1786,10 @@ static int zonefs_fill_super(struct super_block *sb, void *data, int silent) blkdev_nr_zones(sb->s_bdev->bd_disk)); if (!sbi->s_max_wro_seq_files && + !sbi->s_max_active_seq_files && sbi->s_mount_opts & ZONEFS_MNTOPT_EXPLICIT_OPEN) { - zonefs_info(sb, "No open zones limit. Ignoring explicit_open mount option\n"); + zonefs_info(sb, + "No open and active zone limits. Ignoring explicit_open mount option\n"); sbi->s_mount_opts &= ~ZONEFS_MNTOPT_EXPLICIT_OPEN; } -- cgit From 54aa83c90198e68eee8b0850c749bc70efb548da Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 7 Jun 2022 10:07:11 -0400 Subject: KVM: x86: do not set st->preempted when going back to user space Similar to the Xen path, only change the vCPU's reported state if the vCPU was actually preempted. The reason for KVM's behavior is that for example optimistic spinning might not be a good idea if the guest is doing repeated exits to userspace; however, it is confusing and unlikely to make a difference, because well-tuned guests will hardly ever exit KVM_RUN in the first place. Suggested-by: Sean Christopherson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/x86.c | 26 ++++++++++++++------------ arch/x86/kvm/xen.h | 6 ++++-- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b81ef4f497f4..a8bb635cb76b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4654,19 +4654,21 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) { int idx; - if (vcpu->preempted && !vcpu->arch.guest_state_protected) - vcpu->arch.preempted_in_kernel = !static_call(kvm_x86_get_cpl)(vcpu); + if (vcpu->preempted) { + if (!vcpu->arch.guest_state_protected) + vcpu->arch.preempted_in_kernel = !static_call(kvm_x86_get_cpl)(vcpu); - /* - * Take the srcu lock as memslots will be accessed to check the gfn - * cache generation against the memslots generation. - */ - idx = srcu_read_lock(&vcpu->kvm->srcu); - if (kvm_xen_msr_enabled(vcpu->kvm)) - kvm_xen_runstate_set_preempted(vcpu); - else - kvm_steal_time_set_preempted(vcpu); - srcu_read_unlock(&vcpu->kvm->srcu, idx); + /* + * Take the srcu lock as memslots will be accessed to check the gfn + * cache generation against the memslots generation. + */ + idx = srcu_read_lock(&vcpu->kvm->srcu); + if (kvm_xen_msr_enabled(vcpu->kvm)) + kvm_xen_runstate_set_preempted(vcpu); + else + kvm_steal_time_set_preempted(vcpu); + srcu_read_unlock(&vcpu->kvm->srcu, idx); + } static_call(kvm_x86_vcpu_put)(vcpu); vcpu->arch.last_host_tsc = rdtsc(); diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h index ee5c4ae0755c..532a535a9e99 100644 --- a/arch/x86/kvm/xen.h +++ b/arch/x86/kvm/xen.h @@ -159,8 +159,10 @@ static inline void kvm_xen_runstate_set_preempted(struct kvm_vcpu *vcpu) * behalf of the vCPU. Only if the VMM does actually block * does it need to enter RUNSTATE_blocked. */ - if (vcpu->preempted) - kvm_xen_update_runstate_guest(vcpu, RUNSTATE_runnable); + if (WARN_ON_ONCE(!vcpu->preempted)) + return; + + kvm_xen_update_runstate_guest(vcpu, RUNSTATE_runnable); } /* 32-bit compatibility definitions, also used natively in 32-bit build */ -- cgit From 6cd88243c7e03845a450795e134b488fc2afb736 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 7 Jun 2022 10:09:03 -0400 Subject: KVM: x86: do not report a vCPU as preempted outside instruction boundaries If a vCPU is outside guest mode and is scheduled out, it might be in the process of making a memory access. A problem occurs if another vCPU uses the PV TLB flush feature during the period when the vCPU is scheduled out, and a virtual address has already been translated but has not yet been accessed, because this is equivalent to using a stale TLB entry. To avoid this, only report a vCPU as preempted if sure that the guest is at an instruction boundary. A rescheduling request will be delivered to the host physical CPU as an external interrupt, so for simplicity consider any vmexit *not* instruction boundary except for external interrupts. It would in principle be okay to report the vCPU as preempted also if it is sleeping in kvm_vcpu_block(): a TLB flush IPI will incur the vmentry/vmexit overhead unnecessarily, and optimistic spinning is also unlikely to succeed. However, leave it for later because right now kvm_vcpu_check_block() is doing memory accesses. Even though the TLB flush issue only applies to virtual memory address, it's very much preferrable to be conservative. Reported-by: Jann Horn Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/kvm_host.h | 3 +++ arch/x86/kvm/svm/svm.c | 2 ++ arch/x86/kvm/vmx/vmx.c | 1 + arch/x86/kvm/x86.c | 22 ++++++++++++++++++++++ 4 files changed, 28 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 959d66b9be94..3a240a64ac68 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -653,6 +653,7 @@ struct kvm_vcpu_arch { u64 ia32_misc_enable_msr; u64 smbase; u64 smi_count; + bool at_instruction_boundary; bool tpr_access_reporting; bool xsaves_enabled; bool xfd_no_write_intercept; @@ -1300,6 +1301,8 @@ struct kvm_vcpu_stat { u64 nested_run; u64 directed_yield_attempted; u64 directed_yield_successful; + u64 preemption_reported; + u64 preemption_other; u64 guest_mode; }; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 478e6ee81d88..921fcb85a9cd 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4263,6 +4263,8 @@ out: static void svm_handle_exit_irqoff(struct kvm_vcpu *vcpu) { + if (to_svm(vcpu)->vmcb->control.exit_code == SVM_EXIT_INTR) + vcpu->arch.at_instruction_boundary = true; } static void svm_sched_in(struct kvm_vcpu *vcpu, int cpu) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index f5aeade623d6..14e01178a753 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6547,6 +6547,7 @@ static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu) return; handle_interrupt_nmi_irqoff(vcpu, gate_offset(desc)); + vcpu->arch.at_instruction_boundary = true; } static void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index a8bb635cb76b..25a517206c4d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -296,6 +296,8 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { STATS_DESC_COUNTER(VCPU, nested_run), STATS_DESC_COUNTER(VCPU, directed_yield_attempted), STATS_DESC_COUNTER(VCPU, directed_yield_successful), + STATS_DESC_COUNTER(VCPU, preemption_reported), + STATS_DESC_COUNTER(VCPU, preemption_other), STATS_DESC_ICOUNTER(VCPU, guest_mode) }; @@ -4625,6 +4627,19 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) struct kvm_memslots *slots; static const u8 preempted = KVM_VCPU_PREEMPTED; + /* + * The vCPU can be marked preempted if and only if the VM-Exit was on + * an instruction boundary and will not trigger guest emulation of any + * kind (see vcpu_run). Vendor specific code controls (conservatively) + * when this is true, for example allowing the vCPU to be marked + * preempted if and only if the VM-Exit was due to a host interrupt. + */ + if (!vcpu->arch.at_instruction_boundary) { + vcpu->stat.preemption_other++; + return; + } + + vcpu->stat.preemption_reported++; if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) return; @@ -10424,6 +10439,13 @@ static int vcpu_run(struct kvm_vcpu *vcpu) vcpu->arch.l1tf_flush_l1d = true; for (;;) { + /* + * If another guest vCPU requests a PV TLB flush in the middle + * of instruction emulation, the rest of the emulation could + * use a stale page translation. Assume that any code after + * this point can start executing an instruction. + */ + vcpu->arch.at_instruction_boundary = false; if (kvm_vcpu_running(vcpu)) { r = vcpu_enter_guest(vcpu); } else { -- cgit From c1c1204c0d0c1dccc1310b9277fb2bd8b663d8fe Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Mon, 23 May 2022 16:29:10 +0900 Subject: zonefs: fix zonefs_iomap_begin() for reads If a readahead is issued to a sequential zone file with an offset exactly equal to the current file size, the iomap type is set to IOMAP_UNWRITTEN, which will prevent an IO, but the iomap length is calculated as 0. This causes a WARN_ON() in iomap_iter(): [17309.548939] WARNING: CPU: 3 PID: 2137 at fs/iomap/iter.c:34 iomap_iter+0x9cf/0xe80 [...] [17309.650907] RIP: 0010:iomap_iter+0x9cf/0xe80 [...] [17309.754560] Call Trace: [17309.757078] [17309.759240] ? lock_is_held_type+0xd8/0x130 [17309.763531] iomap_readahead+0x1a8/0x870 [17309.767550] ? iomap_read_folio+0x4c0/0x4c0 [17309.771817] ? lockdep_hardirqs_on_prepare+0x400/0x400 [17309.778848] ? lock_release+0x370/0x750 [17309.784462] ? folio_add_lru+0x217/0x3f0 [17309.790220] ? reacquire_held_locks+0x4e0/0x4e0 [17309.796543] read_pages+0x17d/0xb60 [17309.801854] ? folio_add_lru+0x238/0x3f0 [17309.807573] ? readahead_expand+0x5f0/0x5f0 [17309.813554] ? policy_node+0xb5/0x140 [17309.819018] page_cache_ra_unbounded+0x27d/0x450 [17309.825439] filemap_get_pages+0x500/0x1450 [17309.831444] ? filemap_add_folio+0x140/0x140 [17309.837519] ? lock_is_held_type+0xd8/0x130 [17309.843509] filemap_read+0x28c/0x9f0 [17309.848953] ? zonefs_file_read_iter+0x1ea/0x4d0 [zonefs] [17309.856162] ? trace_contention_end+0xd6/0x130 [17309.862416] ? __mutex_lock+0x221/0x1480 [17309.868151] ? zonefs_file_read_iter+0x166/0x4d0 [zonefs] [17309.875364] ? filemap_get_pages+0x1450/0x1450 [17309.881647] ? __mutex_unlock_slowpath+0x15e/0x620 [17309.888248] ? wait_for_completion_io_timeout+0x20/0x20 [17309.895231] ? lock_is_held_type+0xd8/0x130 [17309.901115] ? lock_is_held_type+0xd8/0x130 [17309.906934] zonefs_file_read_iter+0x356/0x4d0 [zonefs] [17309.913750] new_sync_read+0x2d8/0x520 [17309.919035] ? __x64_sys_lseek+0x1d0/0x1d0 Furthermore, this causes iomap_readahead() to loop forever as iomap_readahead_iter() always returns 0, making no progress. Fix this by treating reads after the file size as access to holes, setting the iomap type to IOMAP_HOLE, the iomap addr to IOMAP_NULL_ADDR and using the length argument as is for the iomap length. To simplify the code with this change, zonefs_iomap_begin() is split into the read variant, zonefs_read_iomap_begin() and zonefs_read_iomap_ops, and the write variant, zonefs_write_iomap_begin() and zonefs_write_iomap_ops. Reported-by: Jorgen Hansen Fixes: 8dcc1a9d90c1 ("fs: New zonefs file system") Signed-off-by: Damien Le Moal Reviewed-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn Reviewed-by: Jorgen Hansen --- fs/zonefs/super.c | 94 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c index 123464d2145a..053299758deb 100644 --- a/fs/zonefs/super.c +++ b/fs/zonefs/super.c @@ -110,15 +110,51 @@ static inline void zonefs_i_size_write(struct inode *inode, loff_t isize) } } -static int zonefs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, - unsigned int flags, struct iomap *iomap, - struct iomap *srcmap) +static int zonefs_read_iomap_begin(struct inode *inode, loff_t offset, + loff_t length, unsigned int flags, + struct iomap *iomap, struct iomap *srcmap) { struct zonefs_inode_info *zi = ZONEFS_I(inode); struct super_block *sb = inode->i_sb; loff_t isize; - /* All I/Os should always be within the file maximum size */ + /* + * All blocks are always mapped below EOF. If reading past EOF, + * act as if there is a hole up to the file maximum size. + */ + mutex_lock(&zi->i_truncate_mutex); + iomap->bdev = inode->i_sb->s_bdev; + iomap->offset = ALIGN_DOWN(offset, sb->s_blocksize); + isize = i_size_read(inode); + if (iomap->offset >= isize) { + iomap->type = IOMAP_HOLE; + iomap->addr = IOMAP_NULL_ADDR; + iomap->length = length; + } else { + iomap->type = IOMAP_MAPPED; + iomap->addr = (zi->i_zsector << SECTOR_SHIFT) + iomap->offset; + iomap->length = isize - iomap->offset; + } + mutex_unlock(&zi->i_truncate_mutex); + + trace_zonefs_iomap_begin(inode, iomap); + + return 0; +} + +static const struct iomap_ops zonefs_read_iomap_ops = { + .iomap_begin = zonefs_read_iomap_begin, +}; + +static int zonefs_write_iomap_begin(struct inode *inode, loff_t offset, + loff_t length, unsigned int flags, + struct iomap *iomap, struct iomap *srcmap) +{ + struct zonefs_inode_info *zi = ZONEFS_I(inode); + struct super_block *sb = inode->i_sb; + loff_t isize; + + /* All write I/Os should always be within the file maximum size */ if (WARN_ON_ONCE(offset + length > zi->i_max_size)) return -EIO; @@ -128,7 +164,7 @@ static int zonefs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, * operation. */ if (WARN_ON_ONCE(zi->i_ztype == ZONEFS_ZTYPE_SEQ && - (flags & IOMAP_WRITE) && !(flags & IOMAP_DIRECT))) + !(flags & IOMAP_DIRECT))) return -EIO; /* @@ -137,47 +173,44 @@ static int zonefs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, * write pointer) and unwriten beyond. */ mutex_lock(&zi->i_truncate_mutex); + iomap->bdev = inode->i_sb->s_bdev; + iomap->offset = ALIGN_DOWN(offset, sb->s_blocksize); + iomap->addr = (zi->i_zsector << SECTOR_SHIFT) + iomap->offset; isize = i_size_read(inode); - if (offset >= isize) + if (iomap->offset >= isize) { iomap->type = IOMAP_UNWRITTEN; - else + iomap->length = zi->i_max_size - iomap->offset; + } else { iomap->type = IOMAP_MAPPED; - if (flags & IOMAP_WRITE) - length = zi->i_max_size - offset; - else - length = min(length, isize - offset); + iomap->length = isize - iomap->offset; + } mutex_unlock(&zi->i_truncate_mutex); - iomap->offset = ALIGN_DOWN(offset, sb->s_blocksize); - iomap->length = ALIGN(offset + length, sb->s_blocksize) - iomap->offset; - iomap->bdev = inode->i_sb->s_bdev; - iomap->addr = (zi->i_zsector << SECTOR_SHIFT) + iomap->offset; - trace_zonefs_iomap_begin(inode, iomap); return 0; } -static const struct iomap_ops zonefs_iomap_ops = { - .iomap_begin = zonefs_iomap_begin, +static const struct iomap_ops zonefs_write_iomap_ops = { + .iomap_begin = zonefs_write_iomap_begin, }; static int zonefs_read_folio(struct file *unused, struct folio *folio) { - return iomap_read_folio(folio, &zonefs_iomap_ops); + return iomap_read_folio(folio, &zonefs_read_iomap_ops); } static void zonefs_readahead(struct readahead_control *rac) { - iomap_readahead(rac, &zonefs_iomap_ops); + iomap_readahead(rac, &zonefs_read_iomap_ops); } /* * Map blocks for page writeback. This is used only on conventional zone files, * which implies that the page range can only be within the fixed inode size. */ -static int zonefs_map_blocks(struct iomap_writepage_ctx *wpc, - struct inode *inode, loff_t offset) +static int zonefs_write_map_blocks(struct iomap_writepage_ctx *wpc, + struct inode *inode, loff_t offset) { struct zonefs_inode_info *zi = ZONEFS_I(inode); @@ -191,12 +224,12 @@ static int zonefs_map_blocks(struct iomap_writepage_ctx *wpc, offset < wpc->iomap.offset + wpc->iomap.length) return 0; - return zonefs_iomap_begin(inode, offset, zi->i_max_size - offset, - IOMAP_WRITE, &wpc->iomap, NULL); + return zonefs_write_iomap_begin(inode, offset, zi->i_max_size - offset, + IOMAP_WRITE, &wpc->iomap, NULL); } static const struct iomap_writeback_ops zonefs_writeback_ops = { - .map_blocks = zonefs_map_blocks, + .map_blocks = zonefs_write_map_blocks, }; static int zonefs_writepage(struct page *page, struct writeback_control *wbc) @@ -226,7 +259,8 @@ static int zonefs_swap_activate(struct swap_info_struct *sis, return -EINVAL; } - return iomap_swapfile_activate(sis, swap_file, span, &zonefs_iomap_ops); + return iomap_swapfile_activate(sis, swap_file, span, + &zonefs_read_iomap_ops); } static const struct address_space_operations zonefs_file_aops = { @@ -647,7 +681,7 @@ static vm_fault_t zonefs_filemap_page_mkwrite(struct vm_fault *vmf) /* Serialize against truncates */ filemap_invalidate_lock_shared(inode->i_mapping); - ret = iomap_page_mkwrite(vmf, &zonefs_iomap_ops); + ret = iomap_page_mkwrite(vmf, &zonefs_write_iomap_ops); filemap_invalidate_unlock_shared(inode->i_mapping); sb_end_pagefault(inode->i_sb); @@ -899,7 +933,7 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from) if (append) ret = zonefs_file_dio_append(iocb, from); else - ret = iomap_dio_rw(iocb, from, &zonefs_iomap_ops, + ret = iomap_dio_rw(iocb, from, &zonefs_write_iomap_ops, &zonefs_write_dio_ops, 0, NULL, 0); if (zi->i_ztype == ZONEFS_ZTYPE_SEQ && (ret > 0 || ret == -EIOCBQUEUED)) { @@ -948,7 +982,7 @@ static ssize_t zonefs_file_buffered_write(struct kiocb *iocb, if (ret <= 0) goto inode_unlock; - ret = iomap_file_buffered_write(iocb, from, &zonefs_iomap_ops); + ret = iomap_file_buffered_write(iocb, from, &zonefs_write_iomap_ops); if (ret > 0) iocb->ki_pos += ret; else if (ret == -EIO) @@ -1041,7 +1075,7 @@ static ssize_t zonefs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) goto inode_unlock; } file_accessed(iocb->ki_filp); - ret = iomap_dio_rw(iocb, to, &zonefs_iomap_ops, + ret = iomap_dio_rw(iocb, to, &zonefs_read_iomap_ops, &zonefs_read_dio_ops, 0, NULL, 0); } else { ret = generic_file_read_iter(iocb, to); -- cgit From b09654e39c89a86680528345f3a95b832236ee82 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 8 Jun 2022 09:23:38 +0100 Subject: ASoC: mediatek: mt8186: Fix a handful of spelling mistakes There are several spelling mistakes in dev_err messages. Fix them. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20220608082338.2083456-1-colin.i.king@gmail.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8186/mt8186-afe-gpio.c | 8 ++++---- sound/soc/mediatek/mt8186/mt8186-dai-adda.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c index 5ba28095b7da..255ffba637d3 100644 --- a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c @@ -137,25 +137,25 @@ static int mt8186_afe_gpio_adda_dl(struct device *dev, bool enable) if (enable) { ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_ON); if (ret) { - dev_err(dev, "%s(), MOSI CLK ON slect fail!\n", __func__); + dev_err(dev, "%s(), MOSI CLK ON select fail!\n", __func__); return ret; } ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_ON); if (ret) { - dev_err(dev, "%s(), MOSI DAT ON slect fail!\n", __func__); + dev_err(dev, "%s(), MOSI DAT ON select fail!\n", __func__); return ret; } } else { ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_OFF); if (ret) { - dev_err(dev, "%s(), MOSI DAT OFF slect fail!\n", __func__); + dev_err(dev, "%s(), MOSI DAT OFF select fail!\n", __func__); return ret; } ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_OFF); if (ret) { - dev_err(dev, "%s(), MOSI CLK ON slect fail!\n", __func__); + dev_err(dev, "%s(), MOSI CLK ON select fail!\n", __func__); return ret; } } diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c index c66861fd197d..db71b032770d 100644 --- a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c +++ b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c @@ -341,7 +341,7 @@ static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w, if (afe_priv->mtkaif_chosen_phase[0] < 0 || afe_priv->mtkaif_chosen_phase[1] < 0) { dev_err(afe->dev, - "%s(), skip dealy setting mtkaif_chosen_phase[0/1]:%d/%d\n", + "%s(), skip delay setting mtkaif_chosen_phase[0/1]:%d/%d\n", __func__, afe_priv->mtkaif_chosen_phase[0], afe_priv->mtkaif_chosen_phase[1]); -- cgit From dda5384313a40ecbaafd8a9a80f47483255e4c4d Mon Sep 17 00:00:00 2001 From: David Safford Date: Tue, 7 Jun 2022 14:07:57 -0400 Subject: KEYS: trusted: tpm2: Fix migratable logic When creating (sealing) a new trusted key, migratable trusted keys have the FIXED_TPM and FIXED_PARENT attributes set, and non-migratable keys don't. This is backwards, and also causes creation to fail when creating a migratable key under a migratable parent. (The TPM thinks you are trying to seal a non-migratable blob under a migratable parent.) The following simple patch fixes the logic, and has been tested for all four combinations of migratable and non-migratable trusted keys and parent storage keys. With this logic, you will get a proper failure if you try to create a non-migratable trusted key under a migratable parent storage key, and all other combinations work correctly. Cc: stable@vger.kernel.org # v5.13+ Fixes: e5fb5d2c5a03 ("security: keys: trusted: Make sealed key properly interoperable") Signed-off-by: David Safford Reviewed-by: Ahmad Fatoum Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- security/keys/trusted-keys/trusted_tpm2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c index 0165da386289..2b2c8eb258d5 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -283,8 +283,8 @@ int tpm2_seal_trusted(struct tpm_chip *chip, /* key properties */ flags = 0; flags |= options->policydigest_len ? 0 : TPM2_OA_USER_WITH_AUTH; - flags |= payload->migratable ? (TPM2_OA_FIXED_TPM | - TPM2_OA_FIXED_PARENT) : 0; + flags |= payload->migratable ? 0 : (TPM2_OA_FIXED_TPM | + TPM2_OA_FIXED_PARENT); tpm_buf_append_u32(&buf, flags); /* policy */ -- cgit From 49c3ca34f7dbe5227c0163cba4deb5d29e145fae Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 8 Jun 2022 00:18:40 +0900 Subject: scripts/nsdeps: adjust to the format change of *.mod files Commit 22f26f21774f ("kbuild: get rid of duplication in *.mod files") changed the format of *.mod files to put one object per line, but missed to adjust scripts/nsdeps. Fixes: 22f26f21774f ("kbuild: get rid of duplication in *.mod files") Signed-off-by: Masahiro Yamada --- scripts/nsdeps | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/nsdeps b/scripts/nsdeps index 04c4b96e95ec..f1718cc0d700 100644 --- a/scripts/nsdeps +++ b/scripts/nsdeps @@ -34,9 +34,8 @@ generate_deps() { local mod=${1%.ko:} shift local namespaces="$*" - local mod_source_files="`cat $mod.mod | sed -n 1p \ - | sed -e 's/\.o/\.c/g' \ - | sed "s|[^ ]* *|${src_prefix}&|g"`" + local mod_source_files=$(sed "s|^\(.*\)\.o$|${src_prefix}\1.c|" $mod.mod) + for ns in $namespaces; do echo "Adding namespace $ns to module $mod.ko." generate_deps_for_ns $ns "$mod_source_files" -- cgit From ec3ad554b956d5dbefa1962c419f164ba223e6b3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 8 Jun 2022 02:09:16 +0000 Subject: ASoC: ak4613: cares Simple-Audio-Card case for TDM Renesas is the only user of ak4613 on upstream for now, and commit f28dbaa958fbd8 ("ASoC: ak4613: add TDM256 support") added TDM256 support. Renesas tested part of it, because of board connection. It was assuming ak4613 is probed via Audio-Graph-Card, but it might be probed via Simple-Audio-Card either. It will indicates WARNING in such case. This patch fixup it. Reported-by: Geert Uytterhoeven Signed-off-by: Kuninori Morimoto Tested-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/87h74v29f7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/codecs/ak4613.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index 55e773f92122..93606e5afd8f 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -868,10 +868,12 @@ static void ak4613_parse_of(struct ak4613_priv *priv, /* * connected STDI + * TDM support is assuming it is probed via Audio-Graph-Card style here. + * Default is SDTIx1 if it was probed via Simple-Audio-Card for now. */ sdti_num = of_graph_get_endpoint_count(np); - if (WARN_ON((sdti_num > 3) || (sdti_num < 1))) - return; + if ((sdti_num >= SDTx_MAX) || (sdti_num < 1)) + sdti_num = 1; AK4613_CONFIG_SDTI_set(priv, sdti_num); } -- cgit From 228432551bd8783211e494ab35f42a4344580502 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 8 Jun 2022 14:14:22 +0800 Subject: virtio-rng: make device ready before making request Current virtio-rng does a entropy request before DRIVER_OK, this violates the spec: virtio spec requires that all drivers set DRIVER_OK before using devices. Further, kernel will ignore the interrupt after commit 8b4ec69d7e09 ("virtio: harden vring IRQ"). Fixing this by making device ready before the request. Cc: stable@vger.kernel.org Fixes: 8b4ec69d7e09 ("virtio: harden vring IRQ") Fixes: f7f510ec1957 ("virtio: An entropy device, as suggested by hpa.") Reported-and-tested-by: syzbot+5b59d6d459306a556f54@syzkaller.appspotmail.com Signed-off-by: Jason Wang Message-Id: <20220608061422.38437-1-jasowang@redhat.com> Signed-off-by: Michael S. Tsirkin Reviewed-by: Laurent Vivier --- drivers/char/hw_random/virtio-rng.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index e856df7e285c..a6f3a8a2aca6 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -159,6 +159,8 @@ static int probe_common(struct virtio_device *vdev) goto err_find; } + virtio_device_ready(vdev); + /* we always have a pending entropy request */ request_entropy(vi); -- cgit From 2f72b2262d317093596c72bd5b27b9880be7611e Mon Sep 17 00:00:00 2001 From: Xiang wangx Date: Sat, 4 Jun 2022 22:38:58 +0800 Subject: vdpa/mlx5: Fix syntax errors in comments Delete the redundant word 'is'. Signed-off-by: Xiang wangx Message-Id: <20220604143858.16073-1-wangxiang@cdjrlc.com> Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang --- drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index b7a955479156..b878c1095530 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -107,7 +107,7 @@ struct mlx5_vdpa_virtqueue { /* Resources for implementing the notification channel from the device * to the driver. fwqp is the firmware end of an RC connection; the - * other end is vqqp used by the driver. cq is is where completions are + * other end is vqqp used by the driver. cq is where completions are * reported. */ struct mlx5_vdpa_cq cq; -- cgit From a58a7f97ba11391d2d0d408e0b24f38d86ae748e Mon Sep 17 00:00:00 2001 From: chengkaitao Date: Thu, 2 Jun 2022 08:55:42 +0800 Subject: virtio-mmio: fix missing put_device() when vm_cmdline_parent registration failed The reference must be released when device_register(&vm_cmdline_parent) failed. Add the corresponding 'put_device()' in the error handling path. Signed-off-by: chengkaitao Message-Id: <20220602005542.16489-1-chengkaitao@didiglobal.com> Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang --- drivers/virtio/virtio_mmio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index f9a36bc7ac27..5ce79bf9f92b 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -701,6 +701,7 @@ static int vm_cmdline_set(const char *device, if (!vm_cmdline_parent_registered) { err = device_register(&vm_cmdline_parent); if (err) { + put_device(&vm_cmdline_parent); pr_err("Failed to register parent device!\n"); return err; } -- cgit From f766c409fcb33cfd0f511e8251831520e089eb89 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 7 Jun 2022 09:49:25 +0300 Subject: vdpa/mlx5: fix error code for deleting vlan Return success if we were able to delete a vlan. The current code always returns failure. Fixes: baf2ad3f6a98 ("vdpa/mlx5: Add RX MAC VLAN filter support") Signed-off-by: Dan Carpenter Message-Id: Signed-off-by: Michael S. Tsirkin Acked-by: Eli Cohen Acked-by: Si-Wei Liu --- drivers/vdpa/mlx5/net/mlx5_vnet.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index b878c1095530..51fb15c35e42 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -1814,6 +1814,7 @@ static virtio_net_ctrl_ack handle_ctrl_vlan(struct mlx5_vdpa_dev *mvdev, u8 cmd) id = mlx5vdpa16_to_cpu(mvdev, vlan); mac_vlan_del(ndev, ndev->config.mac, id, true); + status = VIRTIO_NET_OK; break; default: break; -- cgit From f38b3c6a788f75da151b46c7da61ff26649e1843 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 7 Jun 2022 09:50:09 +0300 Subject: vdpa/mlx5: clean up indenting in handle_ctrl_vlan() These lines were supposed to be indented. Signed-off-by: Dan Carpenter Message-Id: Signed-off-by: Michael S. Tsirkin Acked-by: Eli Cohen Acked-by: Si-Wei Liu --- drivers/vdpa/mlx5/net/mlx5_vnet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index 51fb15c35e42..1b6d46b86f81 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -1817,10 +1817,10 @@ static virtio_net_ctrl_ack handle_ctrl_vlan(struct mlx5_vdpa_dev *mvdev, u8 cmd) status = VIRTIO_NET_OK; break; default: - break; -} + break; + } -return status; + return status; } static void mlx5_cvq_kick_handler(struct work_struct *work) -- cgit From dbd29e0752286af74243cf891accf472b2f3edd8 Mon Sep 17 00:00:00 2001 From: Xie Yongji Date: Thu, 5 May 2022 18:09:10 +0800 Subject: vringh: Fix loop descriptors check in the indirect cases We should use size of descriptor chain to test loop condition in the indirect case. And another statistical count is also introduced for indirect descriptors to avoid conflict with the statistical count of direct descriptors. Fixes: f87d0fbb5798 ("vringh: host-side implementation of virtio rings.") Signed-off-by: Xie Yongji Signed-off-by: Fam Zheng Message-Id: <20220505100910.137-1-xieyongji@bytedance.com> Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang --- drivers/vhost/vringh.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c index 14e2043d7685..eab55accf381 100644 --- a/drivers/vhost/vringh.c +++ b/drivers/vhost/vringh.c @@ -292,7 +292,7 @@ __vringh_iov(struct vringh *vrh, u16 i, int (*copy)(const struct vringh *vrh, void *dst, const void *src, size_t len)) { - int err, count = 0, up_next, desc_max; + int err, count = 0, indirect_count = 0, up_next, desc_max; struct vring_desc desc, *descs; struct vringh_range range = { -1ULL, 0 }, slowrange; bool slow = false; @@ -349,7 +349,12 @@ __vringh_iov(struct vringh *vrh, u16 i, continue; } - if (count++ == vrh->vring.num) { + if (up_next == -1) + count++; + else + indirect_count++; + + if (count > vrh->vring.num || indirect_count > desc_max) { vringh_bad("Descriptor loop in %p", descs); err = -ELOOP; goto fail; @@ -411,6 +416,7 @@ __vringh_iov(struct vringh *vrh, u16 i, i = return_from_indirect(vrh, &up_next, &descs, &desc_max); slow = false; + indirect_count = 0; } else break; } -- cgit From b27ee76c74dc831d6e092eaebc2dfc9c0beed1c9 Mon Sep 17 00:00:00 2001 From: Xie Yongji Date: Tue, 26 Apr 2022 15:36:56 +0800 Subject: vduse: Fix NULL pointer dereference on sysfs access The control device has no drvdata. So we will get a NULL pointer dereference when accessing control device's msg_timeout attribute via sysfs: [ 132.841881][ T3644] BUG: kernel NULL pointer dereference, address: 00000000000000f8 [ 132.850619][ T3644] RIP: 0010:msg_timeout_show (drivers/vdpa/vdpa_user/vduse_dev.c:1271) [ 132.869447][ T3644] dev_attr_show (drivers/base/core.c:2094) [ 132.870215][ T3644] sysfs_kf_seq_show (fs/sysfs/file.c:59) [ 132.871164][ T3644] ? device_remove_bin_file (drivers/base/core.c:2088) [ 132.872082][ T3644] kernfs_seq_show (fs/kernfs/file.c:164) [ 132.872838][ T3644] seq_read_iter (fs/seq_file.c:230) [ 132.873578][ T3644] ? __vmalloc_area_node (mm/vmalloc.c:3041) [ 132.874532][ T3644] kernfs_fop_read_iter (fs/kernfs/file.c:238) [ 132.875513][ T3644] __kernel_read (fs/read_write.c:440 (discriminator 1)) [ 132.876319][ T3644] kernel_read (fs/read_write.c:459) [ 132.877129][ T3644] kernel_read_file (fs/kernel_read_file.c:94) [ 132.877978][ T3644] kernel_read_file_from_fd (include/linux/file.h:45 fs/kernel_read_file.c:186) [ 132.879019][ T3644] __do_sys_finit_module (kernel/module.c:4207) [ 132.879930][ T3644] __ia32_sys_finit_module (kernel/module.c:4189) [ 132.880930][ T3644] do_int80_syscall_32 (arch/x86/entry/common.c:112 arch/x86/entry/common.c:132) [ 132.881847][ T3644] entry_INT80_compat (arch/x86/entry/entry_64_compat.S:419) To fix it, don't create the unneeded attribute for control device anymore. Fixes: c8a6153b6c59 ("vduse: Introduce VDUSE - vDPA Device in Userspace") Reported-by: kernel test robot Cc: stable@vger.kernel.org Signed-off-by: Xie Yongji Message-Id: <20220426073656.229-1-xieyongji@bytedance.com> Signed-off-by: Michael S. Tsirkin --- drivers/vdpa/vdpa_user/vduse_dev.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c index d503848b3b6e..776ad7496f53 100644 --- a/drivers/vdpa/vdpa_user/vduse_dev.c +++ b/drivers/vdpa/vdpa_user/vduse_dev.c @@ -1345,9 +1345,9 @@ static int vduse_create_dev(struct vduse_dev_config *config, dev->minor = ret; dev->msg_timeout = VDUSE_MSG_DEFAULT_TIMEOUT; - dev->dev = device_create(vduse_class, NULL, - MKDEV(MAJOR(vduse_major), dev->minor), - dev, "%s", config->name); + dev->dev = device_create_with_groups(vduse_class, NULL, + MKDEV(MAJOR(vduse_major), dev->minor), + dev, vduse_dev_groups, "%s", config->name); if (IS_ERR(dev->dev)) { ret = PTR_ERR(dev->dev); goto err_dev; @@ -1596,7 +1596,6 @@ static int vduse_init(void) return PTR_ERR(vduse_class); vduse_class->devnode = vduse_devnode; - vduse_class->dev_groups = vduse_dev_groups; ret = alloc_chrdev_region(&vduse_major, 0, VDUSE_DEV_MAX, "vduse"); if (ret) -- cgit From d678cbd2f867a564a3c5b276c454e873f43f02f8 Mon Sep 17 00:00:00 2001 From: Maciej Fijalkowski Date: Tue, 7 Jun 2022 16:22:00 +0200 Subject: xsk: Fix handling of invalid descriptors in XSK TX batching API xdpxceiver run on a AF_XDP ZC enabled driver revealed a problem with XSK Tx batching API. There is a test that checks how invalid Tx descriptors are handled by AF_XDP. Each valid descriptor is followed by invalid one on Tx side whereas the Rx side expects only to receive a set of valid descriptors. In current xsk_tx_peek_release_desc_batch() function, the amount of available descriptors is hidden inside xskq_cons_peek_desc_batch(). This can be problematic in cases where invalid descriptors are present due to the fact that xskq_cons_peek_desc_batch() returns only a count of valid descriptors. This means that it is impossible to properly update XSK ring state when calling xskq_cons_release_n(). To address this issue, pull out the contents of xskq_cons_peek_desc_batch() so that callers (currently only xsk_tx_peek_release_desc_batch()) will always be able to update the state of ring properly, as total count of entries is now available and use this value as an argument in xskq_cons_release_n(). By doing so, xskq_cons_peek_desc_batch() can be dropped altogether. Fixes: 9349eb3a9d2a ("xsk: Introduce batched Tx descriptor interfaces") Signed-off-by: Maciej Fijalkowski Signed-off-by: Daniel Borkmann Acked-by: Magnus Karlsson Link: https://lore.kernel.org/bpf/20220607142200.576735-1-maciej.fijalkowski@intel.com --- net/xdp/xsk.c | 5 +++-- net/xdp/xsk_queue.h | 8 -------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index e0a4526ab66b..19ac872a6624 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c @@ -373,7 +373,8 @@ u32 xsk_tx_peek_release_desc_batch(struct xsk_buff_pool *pool, u32 max_entries) goto out; } - nb_pkts = xskq_cons_peek_desc_batch(xs->tx, pool, max_entries); + max_entries = xskq_cons_nb_entries(xs->tx, max_entries); + nb_pkts = xskq_cons_read_desc_batch(xs->tx, pool, max_entries); if (!nb_pkts) { xs->tx->queue_empty_descs++; goto out; @@ -389,7 +390,7 @@ u32 xsk_tx_peek_release_desc_batch(struct xsk_buff_pool *pool, u32 max_entries) if (!nb_pkts) goto out; - xskq_cons_release_n(xs->tx, nb_pkts); + xskq_cons_release_n(xs->tx, max_entries); __xskq_cons_release(xs->tx); xs->sk.sk_write_space(&xs->sk); diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h index a794410989cc..fb20bf7207cf 100644 --- a/net/xdp/xsk_queue.h +++ b/net/xdp/xsk_queue.h @@ -282,14 +282,6 @@ static inline bool xskq_cons_peek_desc(struct xsk_queue *q, return xskq_cons_read_desc(q, desc, pool); } -static inline u32 xskq_cons_peek_desc_batch(struct xsk_queue *q, struct xsk_buff_pool *pool, - u32 max) -{ - u32 entries = xskq_cons_nb_entries(q, max); - - return xskq_cons_read_desc_batch(q, pool, entries); -} - /* To improve performance in the xskq_cons_release functions, only update local state here. * Reflect this to global state when we get new entries from the ring in * xskq_cons_get_entries() and whenever Rx or Tx processing are completed in the NAPI loop. -- cgit From 7c217aca85dd31dd2c8f45f6a7520767c9fae766 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Wed, 8 Jun 2022 13:14:28 +0100 Subject: MAINTAINERS: Add a maintainer for bpftool I've been contributing and reviewing patches for bpftool for some time, and I'm taking care of its external mirror. On Alexei, KP, and Daniel's suggestion, I would like to step forwards and become a maintainer for the tool. This patch adds a dedicated entry to MAINTAINERS. Signed-off-by: Quentin Monnet Signed-off-by: Daniel Borkmann Acked-by: Jakub Kicinski Acked-by: KP Singh Acked-by: Alexei Starovoitov Link: https://lore.kernel.org/bpf/20220608121428.69708-1-quentin@isovalent.com --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 033a01b07f8f..92c8adc5471b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3731,6 +3731,13 @@ F: include/linux/bpf_lsm.h F: kernel/bpf/bpf_lsm.c F: security/bpf/ +BPFTOOL +M: Quentin Monnet +L: bpf@vger.kernel.org +S: Maintained +F: kernel/bpf/disasm.* +F: tools/bpf/bpftool/ + BROADCOM B44 10/100 ETHERNET DRIVER M: Michael Chan L: netdev@vger.kernel.org -- cgit From a956a11ee669d069047525c8ec897b4c21a9cda1 Mon Sep 17 00:00:00 2001 From: Jesse Zhang Date: Tue, 7 Jun 2022 10:44:57 +0800 Subject: drm/amdkfd:Fix fw version for 10.3.6 fix fw error when loading fw for 10.3.6 Signed-off-by: Jesse Zhang Reviewed-by: Alex Deucher Reviewed-by: Mario Limonciello Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 5.18.x --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index f8635e768513..bf4200457772 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -182,7 +182,9 @@ static void kfd_device_info_init(struct kfd_dev *kfd, if (gc_version < IP_VERSION(11, 0, 0)) { /* Navi2x+, Navi1x+ */ - if (gc_version >= IP_VERSION(10, 3, 0)) + if (gc_version == IP_VERSION(10, 3, 6)) + kfd->device_info.no_atomic_fw_version = 14; + else if (gc_version >= IP_VERSION(10, 3, 0)) kfd->device_info.no_atomic_fw_version = 92; else if (gc_version >= IP_VERSION(10, 1, 1)) kfd->device_info.no_atomic_fw_version = 145; -- cgit From 1d2afeb7983081ecf656c2338c7db6fd405c653c Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 3 Jun 2022 12:21:06 +0200 Subject: drm/amdgpu: fix limiting AV1 to the first instance on VCN3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The job is not yet initialized here. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2037 Reviewed-by: Alex Deucher Tested-by: Pierre-Eric Pelloux-Prayer Signed-off-by: Christian König Fixes: cdc7893fc93f ("drm/amdgpu: use job and ib structures directly in CS parsers") Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 3cabceee5f57..39405f0db824 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -1761,23 +1761,21 @@ static const struct amdgpu_ring_funcs vcn_v3_0_dec_sw_ring_vm_funcs = { .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper, }; -static int vcn_v3_0_limit_sched(struct amdgpu_cs_parser *p, - struct amdgpu_job *job) +static int vcn_v3_0_limit_sched(struct amdgpu_cs_parser *p) { struct drm_gpu_scheduler **scheds; /* The create msg must be in the first IB submitted */ - if (atomic_read(&job->base.entity->fence_seq)) + if (atomic_read(&p->entity->fence_seq)) return -EINVAL; scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_DEC] [AMDGPU_RING_PRIO_DEFAULT].sched; - drm_sched_entity_modify_sched(job->base.entity, scheds, 1); + drm_sched_entity_modify_sched(p->entity, scheds, 1); return 0; } -static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, - uint64_t addr) +static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, uint64_t addr) { struct ttm_operation_ctx ctx = { false, false }; struct amdgpu_bo_va_mapping *map; @@ -1848,7 +1846,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11) continue; - r = vcn_v3_0_limit_sched(p, job); + r = vcn_v3_0_limit_sched(p); if (r) goto out; } @@ -1862,7 +1860,7 @@ static int vcn_v3_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, struct amdgpu_job *job, struct amdgpu_ib *ib) { - struct amdgpu_ring *ring = to_amdgpu_ring(job->base.sched); + struct amdgpu_ring *ring = to_amdgpu_ring(p->entity->rq->sched); uint32_t msg_lo = 0, msg_hi = 0; unsigned i; int r; @@ -1881,8 +1879,7 @@ static int vcn_v3_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, msg_hi = val; } else if (reg == PACKET0(p->adev->vcn.internal.cmd, 0) && val == 0) { - r = vcn_v3_0_dec_msg(p, job, - ((u64)msg_hi) << 32 | msg_lo); + r = vcn_v3_0_dec_msg(p, ((u64)msg_hi) << 32 | msg_lo); if (r) return r; } -- cgit From 84205d00934394076552e2f597cf04a835df3364 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 3 Jun 2022 15:05:04 +0200 Subject: drm/amdgpu: always flush the TLB on gfx8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TLB on GFX8 stores each block of 8 PTEs where any of the valid bits are set. Fixes: 5255e146c99a ("drm/amdgpu: rework TLB flushing") Reviewed-by: Alex Deucher Tested-by: Michal Kubecek Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 109d8dd71c11..dc76d2b3ce52 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -793,6 +793,11 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm, flush_tlb |= adev->gmc.xgmi.num_physical_nodes && adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 0); + /* + * On GFX8 and older any 8 PTE block with a valid bit set enters the TLB + */ + flush_tlb |= adev->ip_versions[GC_HWIP][0] < IP_VERSION(9, 0, 0); + memset(¶ms, 0, sizeof(params)); params.adev = adev; params.vm = vm; -- cgit From 578eb31776df57c81307fb3f96ef0781332c3c7c Mon Sep 17 00:00:00 2001 From: Mohammad Zafar Ziya Date: Tue, 7 Jun 2022 11:38:16 +0800 Subject: drm/amdgpu/jpeg2: Add jpeg vmid update under IB submit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add jpeg vmid update under IB submit Signed-off-by: Mohammad Zafar Ziya Acked-by: Christian König Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c | 6 +++++- drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c index d2722adabd1b..f3c1af5130ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c @@ -535,6 +535,10 @@ void jpeg_v2_0_dec_ring_emit_ib(struct amdgpu_ring *ring, { unsigned vmid = AMDGPU_JOB_GET_VMID(job); + amdgpu_ring_write(ring, PACKETJ(mmUVD_JPEG_IH_CTRL_INTERNAL_OFFSET, + 0, 0, PACKETJ_TYPE0)); + amdgpu_ring_write(ring, (vmid << JPEG_IH_CTRL__IH_VMID__SHIFT)); + amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET, 0, 0, PACKETJ_TYPE0)); amdgpu_ring_write(ring, (vmid | (vmid << 4))); @@ -768,7 +772,7 @@ static const struct amdgpu_ring_funcs jpeg_v2_0_dec_ring_vm_funcs = { 8 + /* jpeg_v2_0_dec_ring_emit_vm_flush */ 18 + 18 + /* jpeg_v2_0_dec_ring_emit_fence x2 vm fence */ 8 + 16, - .emit_ib_size = 22, /* jpeg_v2_0_dec_ring_emit_ib */ + .emit_ib_size = 24, /* jpeg_v2_0_dec_ring_emit_ib */ .emit_ib = jpeg_v2_0_dec_ring_emit_ib, .emit_fence = jpeg_v2_0_dec_ring_emit_fence, .emit_vm_flush = jpeg_v2_0_dec_ring_emit_vm_flush, diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.h index 1a03baa59755..654e43e83e2c 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.h +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.h @@ -41,6 +41,7 @@ #define mmUVD_JRBC_RB_REF_DATA_INTERNAL_OFFSET 0x4084 #define mmUVD_JRBC_STATUS_INTERNAL_OFFSET 0x4089 #define mmUVD_JPEG_PITCH_INTERNAL_OFFSET 0x401f +#define mmUVD_JPEG_IH_CTRL_INTERNAL_OFFSET 0x4149 #define JRBC_DEC_EXTERNAL_REG_WRITE_ADDR 0x18000 -- cgit From 32d4fd5751eadbe1823a37eb38df85ec5c8e6207 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 8 Jun 2022 16:27:27 +0200 Subject: cpuidle,intel_idle: Fix CPUIDLE_FLAG_IRQ_ENABLE Commit c227233ad64c ("intel_idle: enable interrupts before C1 on Xeons") wrecked intel_idle in two ways: - must not have tracing in idle functions - must return with IRQs disabled Additionally, it added a branch for no good reason. Fixes: c227233ad64c ("intel_idle: enable interrupts before C1 on Xeons") Signed-off-by: Peter Zijlstra (Intel) [ rjw: Moved the intel_idle() kerneldoc comment next to the function ] Cc: 5.16+ # 5.16+ Signed-off-by: Rafael J. Wysocki --- drivers/idle/intel_idle.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index b9bb94bd0f67..424ef470223d 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -115,6 +115,18 @@ static unsigned int mwait_substates __initdata; #define flg2MWAIT(flags) (((flags) >> 24) & 0xFF) #define MWAIT2flg(eax) ((eax & 0xFF) << 24) +static __always_inline int __intel_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + struct cpuidle_state *state = &drv->states[index]; + unsigned long eax = flg2MWAIT(state->flags); + unsigned long ecx = 1; /* break on interrupt flag */ + + mwait_idle_with_hints(eax, ecx); + + return index; +} + /** * intel_idle - Ask the processor to enter the given idle state. * @dev: cpuidle device of the target CPU. @@ -132,16 +144,19 @@ static unsigned int mwait_substates __initdata; static __cpuidle int intel_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - struct cpuidle_state *state = &drv->states[index]; - unsigned long eax = flg2MWAIT(state->flags); - unsigned long ecx = 1; /* break on interrupt flag */ + return __intel_idle(dev, drv, index); +} - if (state->flags & CPUIDLE_FLAG_IRQ_ENABLE) - local_irq_enable(); +static __cpuidle int intel_idle_irq(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + int ret; - mwait_idle_with_hints(eax, ecx); + raw_local_irq_enable(); + ret = __intel_idle(dev, drv, index); + raw_local_irq_disable(); - return index; + return ret; } /** @@ -1801,6 +1816,9 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv) /* Structure copy. */ drv->states[drv->state_count] = cpuidle_state_table[cstate]; + if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IRQ_ENABLE) + drv->states[drv->state_count].enter = intel_idle_irq; + if ((disabled_states_mask & BIT(drv->state_count)) || ((icpu->use_acpi || force_use_acpi) && intel_idle_off_by_default(mwait_hint) && -- cgit From 6c254bf3b637dd4ef4f78eb78c7447419c0161d7 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 7 Jun 2022 16:47:52 -0400 Subject: SUNRPC: Fix the calculation of xdr->end in xdr_get_next_encode_buffer() I found that NFSD's new NFSv3 READDIRPLUS XDR encoder was screwing up right at the end of the page array. xdr_get_next_encode_buffer() does not compute the value of xdr->end correctly: * The check to see if we're on the final available page in xdr->buf needs to account for the space consumed by @nbytes. * The new xdr->end value needs to account for the portion of @nbytes that is to be encoded into the previous buffer. Fixes: 2825a7f90753 ("nfsd4: allow encoding across page boundaries") Signed-off-by: Chuck Lever Reviewed-by: NeilBrown Reviewed-by: J. Bruce Fields --- net/sunrpc/xdr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index df194cc07035..b57cf9df4de8 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -979,7 +979,11 @@ static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, */ xdr->p = (void *)p + frag2bytes; space_left = xdr->buf->buflen - xdr->buf->len; - xdr->end = (void *)p + min_t(int, space_left, PAGE_SIZE); + if (space_left - nbytes >= PAGE_SIZE) + xdr->end = (void *)p + PAGE_SIZE; + else + xdr->end = (void *)p + space_left - frag1bytes; + xdr->buf->page_len += frag2bytes; xdr->buf->len += nbytes; return p; -- cgit From 62ed448cc53b654036f7d7f3c99f299d79ad14c3 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 7 Jun 2022 16:47:58 -0400 Subject: SUNRPC: Optimize xdr_reserve_space() Transitioning between encode buffers is quite infrequent. It happens about 1 time in 400 calls to xdr_reserve_space(), measured on NFSD with a typical build/test workload. Force the compiler to remove that code from xdr_reserve_space(), which is a hot path on both the server and the client. This change reduces the size of xdr_reserve_space() from 10 cache lines to 2 when compiled with -Os. Signed-off-by: Chuck Lever Reviewed-by: J. Bruce Fields --- include/linux/sunrpc/xdr.h | 16 +++++++++++++++- net/sunrpc/xdr.c | 17 ++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 4417f667c757..5860f32e3958 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -243,7 +243,7 @@ extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes); extern int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec, size_t nbytes); -extern void xdr_commit_encode(struct xdr_stream *xdr); +extern void __xdr_commit_encode(struct xdr_stream *xdr); extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len); extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen); extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, @@ -306,6 +306,20 @@ xdr_reset_scratch_buffer(struct xdr_stream *xdr) xdr_set_scratch_buffer(xdr, NULL, 0); } +/** + * xdr_commit_encode - Ensure all data is written to xdr->buf + * @xdr: pointer to xdr_stream + * + * Handle encoding across page boundaries by giving the caller a + * temporary location to write to, then later copying the data into + * place. __xdr_commit_encode() does that copying. + */ +static inline void xdr_commit_encode(struct xdr_stream *xdr) +{ + if (unlikely(xdr->scratch.iov_len)) + __xdr_commit_encode(xdr); +} + /** * xdr_stream_remaining - Return the number of bytes remaining in the stream * @xdr: pointer to struct xdr_stream diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index b57cf9df4de8..1ad8b4ef14de 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -919,7 +919,7 @@ void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p, EXPORT_SYMBOL_GPL(xdr_init_encode); /** - * xdr_commit_encode - Ensure all data is written to buffer + * __xdr_commit_encode - Ensure all data is written to buffer * @xdr: pointer to xdr_stream * * We handle encoding across page boundaries by giving the caller a @@ -931,22 +931,25 @@ EXPORT_SYMBOL_GPL(xdr_init_encode); * required at the end of encoding, or any other time when the xdr_buf * data might be read. */ -inline void xdr_commit_encode(struct xdr_stream *xdr) +void __xdr_commit_encode(struct xdr_stream *xdr) { int shift = xdr->scratch.iov_len; void *page; - if (shift == 0) - return; page = page_address(*xdr->page_ptr); memcpy(xdr->scratch.iov_base, page, shift); memmove(page, page + shift, (void *)xdr->p - page); xdr_reset_scratch_buffer(xdr); } -EXPORT_SYMBOL_GPL(xdr_commit_encode); +EXPORT_SYMBOL_GPL(__xdr_commit_encode); -static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, - size_t nbytes) +/* + * The buffer space to be reserved crosses the boundary between + * xdr->buf->head and xdr->buf->pages, or between two pages + * in xdr->buf->pages. + */ +static noinline __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, + size_t nbytes) { __be32 *p; int space_left; -- cgit From 90d871b3b9bb7ef8f835d6b53095f01b9c74b7b3 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 7 Jun 2022 16:48:05 -0400 Subject: SUNRPC: Clean up xdr_commit_encode() Both the kvec::iov_len field and the third parameter of memcpy() and memmove() are size_t. There's no reason for the implicit conversion from size_t to int and back. Change the type of @shift to make the code easier to read and understand. Signed-off-by: Chuck Lever Reviewed-by: NeilBrown Reviewed-by: J. Bruce Fields --- net/sunrpc/xdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 1ad8b4ef14de..3c182041e790 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -933,7 +933,7 @@ EXPORT_SYMBOL_GPL(xdr_init_encode); */ void __xdr_commit_encode(struct xdr_stream *xdr) { - int shift = xdr->scratch.iov_len; + size_t shift = xdr->scratch.iov_len; void *page; page = page_address(*xdr->page_ptr); -- cgit From bd07a64176a2be03f5195c64943063fd119f9f21 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 7 Jun 2022 16:48:11 -0400 Subject: SUNRPC: Clean up xdr_get_next_encode_buffer() The value of @p is not used until the "location of the next item" is computed. Help human readers by moving its initial assignment to the paragraph where that value is used and by clarifying the antecedents in the documenting comment. Signed-off-by: Chuck Lever Reviewed-by: NeilBrown Reviewed-by: J. Bruce Fields --- net/sunrpc/xdr.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 3c182041e790..eca02d122476 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -967,6 +967,7 @@ static noinline __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, xdr->buf->page_len += frag1bytes; xdr->page_ptr++; xdr->iov = NULL; + /* * If the last encode didn't end exactly on a page boundary, the * next one will straddle boundaries. Encode into the next @@ -975,11 +976,12 @@ static noinline __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, * space at the end of the previous buffer: */ xdr_set_scratch_buffer(xdr, xdr->p, frag1bytes); - p = page_address(*xdr->page_ptr); + /* - * Note this is where the next encode will start after we've - * shifted this one back: + * xdr->p is where the next encode will start after + * xdr_commit_encode() has shifted this one back: */ + p = page_address(*xdr->page_ptr); xdr->p = (void *)p + frag2bytes; space_left = xdr->buf->buflen - xdr->buf->len; if (space_left - nbytes >= PAGE_SIZE) -- cgit From da9e94fe000e11f21d3d6f66012fe5c6379bd93c Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 7 Jun 2022 16:48:18 -0400 Subject: SUNRPC: Remove pointer type casts from xdr_get_next_encode_buffer() To make the code easier to read, remove visual clutter by changing the declared type of @p. Signed-off-by: Chuck Lever Reviewed-by: NeilBrown Reviewed-by: J. Bruce Fields --- net/sunrpc/xdr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index eca02d122476..f87a2d8f23a7 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -951,9 +951,9 @@ EXPORT_SYMBOL_GPL(__xdr_commit_encode); static noinline __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, size_t nbytes) { - __be32 *p; int space_left; int frag1bytes, frag2bytes; + void *p; if (nbytes > PAGE_SIZE) goto out_overflow; /* Bigger buffers require special handling */ @@ -982,12 +982,12 @@ static noinline __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, * xdr_commit_encode() has shifted this one back: */ p = page_address(*xdr->page_ptr); - xdr->p = (void *)p + frag2bytes; + xdr->p = p + frag2bytes; space_left = xdr->buf->buflen - xdr->buf->len; if (space_left - nbytes >= PAGE_SIZE) - xdr->end = (void *)p + PAGE_SIZE; + xdr->end = p + PAGE_SIZE; else - xdr->end = (void *)p + space_left - frag1bytes; + xdr->end = p + space_left - frag1bytes; xdr->buf->page_len += frag2bytes; xdr->buf->len += nbytes; -- cgit From ff87d619ac180444db297f043962a5c325ded47b Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 19 May 2022 20:36:48 +0800 Subject: ASoC: fsl_sai: Enable MCTL_MCLK_EN bit for master mode On i.MX8MM, the MCTL_MCLK_EN bit it is not only the gate for MCLK output to PAD, but also the gate bit between root clock and SAI module, So it is need to be enabled for master mode, otherwise there is no bclk generated. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1652963808-14515-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index b65c9c7cf54a..b4dd3122c45e 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -437,6 +437,12 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) FSL_SAI_CR2_DIV_MASK | FSL_SAI_CR2_BYP, savediv / 2 - 1); + if (sai->soc_data->max_register >= FSL_SAI_MCTL) { + /* SAI is in master mode at this point, so enable MCLK */ + regmap_update_bits(sai->regmap, FSL_SAI_MCTL, + FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN); + } + return 0; } -- cgit From 35b42dce619701f1300fb8498dae82c9bb1f0263 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 6 Jun 2022 13:53:53 +0900 Subject: net: mdio: unexport __init-annotated mdio_bus_init() EXPORT_SYMBOL and __init is a bad combination because the .init.text section is freed up after the initialization. Hence, modules cannot use symbols annotated __init. The access to a freed symbol may end up with kernel panic. modpost used to detect it, but it has been broken for a decade. Recently, I fixed modpost so it started to warn it again, then this showed up in linux-next builds. There are two ways to fix it: - Remove __init - Remove EXPORT_SYMBOL I chose the latter for this case because the only in-tree call-site, drivers/net/phy/phy_device.c is never compiled as modular. (CONFIG_PHYLIB is boolean) Fixes: 90eff9096c01 ("net: phy: Allow splitting MDIO bus/device support from PHYs") Reported-by: Stephen Rothwell Signed-off-by: Masahiro Yamada Reviewed-by: Florian Fainelli Reviewed-by: Russell King (Oracle) Signed-off-by: Jakub Kicinski --- drivers/net/phy/mdio_bus.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 58d602985877..8a2dbe849866 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -1046,7 +1046,6 @@ int __init mdio_bus_init(void) return ret; } -EXPORT_SYMBOL_GPL(mdio_bus_init); #if IS_ENABLED(CONFIG_PHYLIB) void mdio_bus_exit(void) -- cgit From 4a388f08d8784af48f352193d2b72aaf167a57a1 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 6 Jun 2022 13:53:54 +0900 Subject: net: xfrm: unexport __init-annotated xfrm4_protocol_init() EXPORT_SYMBOL and __init is a bad combination because the .init.text section is freed up after the initialization. Hence, modules cannot use symbols annotated __init. The access to a freed symbol may end up with kernel panic. modpost used to detect it, but it has been broken for a decade. Recently, I fixed modpost so it started to warn it again, then this showed up in linux-next builds. There are two ways to fix it: - Remove __init - Remove EXPORT_SYMBOL I chose the latter for this case because the only in-tree call-site, net/ipv4/xfrm4_policy.c is never compiled as modular. (CONFIG_XFRM is boolean) Fixes: 2f32b51b609f ("xfrm: Introduce xfrm_input_afinfo to access the the callbacks properly") Reported-by: Stephen Rothwell Signed-off-by: Masahiro Yamada Acked-by: Steffen Klassert Signed-off-by: Jakub Kicinski --- net/ipv4/xfrm4_protocol.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv4/xfrm4_protocol.c b/net/ipv4/xfrm4_protocol.c index 2fe5860c21d6..b146ce88c5d0 100644 --- a/net/ipv4/xfrm4_protocol.c +++ b/net/ipv4/xfrm4_protocol.c @@ -304,4 +304,3 @@ void __init xfrm4_protocol_init(void) { xfrm_input_register_afinfo(&xfrm4_input_afinfo); } -EXPORT_SYMBOL(xfrm4_protocol_init); -- cgit From 5801f064e35181c71857a80ff18af4dbec3c5f5c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 6 Jun 2022 13:53:55 +0900 Subject: net: ipv6: unexport __init-annotated seg6_hmac_init() EXPORT_SYMBOL and __init is a bad combination because the .init.text section is freed up after the initialization. Hence, modules cannot use symbols annotated __init. The access to a freed symbol may end up with kernel panic. modpost used to detect it, but it has been broken for a decade. Recently, I fixed modpost so it started to warn it again, then this showed up in linux-next builds. There are two ways to fix it: - Remove __init - Remove EXPORT_SYMBOL I chose the latter for this case because the caller (net/ipv6/seg6.c) and the callee (net/ipv6/seg6_hmac.c) belong to the same module. It seems an internal function call in ipv6.ko. Fixes: bf355b8d2c30 ("ipv6: sr: add core files for SR HMAC support") Reported-by: Stephen Rothwell Signed-off-by: Masahiro Yamada Signed-off-by: Jakub Kicinski --- net/ipv6/seg6_hmac.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c index 29bc4e7c3046..6de01185cc68 100644 --- a/net/ipv6/seg6_hmac.c +++ b/net/ipv6/seg6_hmac.c @@ -399,7 +399,6 @@ int __init seg6_hmac_init(void) { return seg6_hmac_init_algo(); } -EXPORT_SYMBOL(seg6_hmac_init); int __net_init seg6_hmac_net_init(struct net *net) { -- cgit From 77e5fe8f176a525523ae091d6fd0fbb8834c156d Mon Sep 17 00:00:00 2001 From: Martin Faltesek Date: Mon, 6 Jun 2022 21:57:27 -0500 Subject: nfc: st21nfca: fix incorrect validating logic in EVT_TRANSACTION The first validation check for EVT_TRANSACTION has two different checks tied together with logical AND. One is a check for minimum packet length, and the other is for a valid aid_tag. If either condition is true (fails), then an error should be triggered. The fix is to change && to ||. Fixes: 26fc6c7f02cb ("NFC: st21nfca: Add HCI transaction event support") Cc: stable@vger.kernel.org Signed-off-by: Martin Faltesek Reviewed-by: Guenter Roeck Reviewed-by: Krzysztof Kozlowski Signed-off-by: Jakub Kicinski --- drivers/nfc/st21nfca/se.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c index 7e213f8ddc98..9645777f2544 100644 --- a/drivers/nfc/st21nfca/se.c +++ b/drivers/nfc/st21nfca/se.c @@ -315,7 +315,7 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host, * AID 81 5 to 16 * PARAMETERS 82 0 to 255 */ - if (skb->len < NFC_MIN_AID_LENGTH + 2 && + if (skb->len < NFC_MIN_AID_LENGTH + 2 || skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG) return -EPROTO; -- cgit From 996419e0594abb311fb958553809f24f38e7abbe Mon Sep 17 00:00:00 2001 From: Martin Faltesek Date: Mon, 6 Jun 2022 21:57:28 -0500 Subject: nfc: st21nfca: fix memory leaks in EVT_TRANSACTION handling Error paths do not free previously allocated memory. Add devm_kfree() to those failure paths. Fixes: 26fc6c7f02cb ("NFC: st21nfca: Add HCI transaction event support") Fixes: 4fbcc1a4cb20 ("nfc: st21nfca: Fix potential buffer overflows in EVT_TRANSACTION") Cc: stable@vger.kernel.org Signed-off-by: Martin Faltesek Reviewed-by: Guenter Roeck Reviewed-by: Krzysztof Kozlowski Signed-off-by: Jakub Kicinski --- drivers/nfc/st21nfca/se.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c index 9645777f2544..8e1113ce139b 100644 --- a/drivers/nfc/st21nfca/se.c +++ b/drivers/nfc/st21nfca/se.c @@ -326,22 +326,29 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host, transaction->aid_len = skb->data[1]; /* Checking if the length of the AID is valid */ - if (transaction->aid_len > sizeof(transaction->aid)) + if (transaction->aid_len > sizeof(transaction->aid)) { + devm_kfree(dev, transaction); return -EINVAL; + } memcpy(transaction->aid, &skb->data[2], transaction->aid_len); /* Check next byte is PARAMETERS tag (82) */ if (skb->data[transaction->aid_len + 2] != - NFC_EVT_TRANSACTION_PARAMS_TAG) + NFC_EVT_TRANSACTION_PARAMS_TAG) { + devm_kfree(dev, transaction); return -EPROTO; + } transaction->params_len = skb->data[transaction->aid_len + 3]; /* Total size is allocated (skb->len - 2) minus fixed array members */ - if (transaction->params_len > ((skb->len - 2) - sizeof(struct nfc_evt_transaction))) + if (transaction->params_len > ((skb->len - 2) - + sizeof(struct nfc_evt_transaction))) { + devm_kfree(dev, transaction); return -EINVAL; + } memcpy(transaction->params, skb->data + transaction->aid_len + 4, transaction->params_len); -- cgit From f2e19b36593caed4c977c2f55aeba7408aeb2132 Mon Sep 17 00:00:00 2001 From: Martin Faltesek Date: Mon, 6 Jun 2022 21:57:29 -0500 Subject: nfc: st21nfca: fix incorrect sizing calculations in EVT_TRANSACTION The transaction buffer is allocated by using the size of the packet buf, and subtracting two which seem intended to remove the two tags which are not present in the target structure. This calculation leads to under counting memory because of differences between the packet contents and the target structure. The aid_len field is a u8 in the packet, but a u32 in the structure, resulting in at least 3 bytes always being under counted. Further, the aid data is a variable length field in the packet, but fixed in the structure, so if this field is less than the max, the difference is added to the under counting. The last validation check for transaction->params_len is also incorrect since it employs the same accounting error. To fix, perform validation checks progressively to safely reach the next field, to determine the size of both buffers and verify both tags. Once all validation checks pass, allocate the buffer and copy the data. This eliminates freeing memory on the error path, as those checks are moved ahead of memory allocation. Fixes: 26fc6c7f02cb ("NFC: st21nfca: Add HCI transaction event support") Fixes: 4fbcc1a4cb20 ("nfc: st21nfca: Fix potential buffer overflows in EVT_TRANSACTION") Cc: stable@vger.kernel.org Signed-off-by: Martin Faltesek Reviewed-by: Guenter Roeck Reviewed-by: Krzysztof Kozlowski Signed-off-by: Jakub Kicinski --- drivers/nfc/st21nfca/se.c | 60 +++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/nfc/st21nfca/se.c b/drivers/nfc/st21nfca/se.c index 8e1113ce139b..df8d27cf2956 100644 --- a/drivers/nfc/st21nfca/se.c +++ b/drivers/nfc/st21nfca/se.c @@ -300,6 +300,8 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host, int r = 0; struct device *dev = &hdev->ndev->dev; struct nfc_evt_transaction *transaction; + u32 aid_len; + u8 params_len; pr_debug("connectivity gate event: %x\n", event); @@ -308,50 +310,48 @@ int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host, r = nfc_se_connectivity(hdev->ndev, host); break; case ST21NFCA_EVT_TRANSACTION: - /* - * According to specification etsi 102 622 + /* According to specification etsi 102 622 * 11.2.2.4 EVT_TRANSACTION Table 52 * Description Tag Length * AID 81 5 to 16 * PARAMETERS 82 0 to 255 + * + * The key differences are aid storage length is variably sized + * in the packet, but fixed in nfc_evt_transaction, and that the aid_len + * is u8 in the packet, but u32 in the structure, and the tags in + * the packet are not included in nfc_evt_transaction. + * + * size in bytes: 1 1 5-16 1 1 0-255 + * offset: 0 1 2 aid_len + 2 aid_len + 3 aid_len + 4 + * member name: aid_tag(M) aid_len aid params_tag(M) params_len params + * example: 0x81 5-16 X 0x82 0-255 X */ - if (skb->len < NFC_MIN_AID_LENGTH + 2 || - skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG) + if (skb->len < 2 || skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG) return -EPROTO; - transaction = devm_kzalloc(dev, skb->len - 2, GFP_KERNEL); - if (!transaction) - return -ENOMEM; - - transaction->aid_len = skb->data[1]; + aid_len = skb->data[1]; - /* Checking if the length of the AID is valid */ - if (transaction->aid_len > sizeof(transaction->aid)) { - devm_kfree(dev, transaction); - return -EINVAL; - } + if (skb->len < aid_len + 4 || aid_len > sizeof(transaction->aid)) + return -EPROTO; - memcpy(transaction->aid, &skb->data[2], - transaction->aid_len); + params_len = skb->data[aid_len + 3]; - /* Check next byte is PARAMETERS tag (82) */ - if (skb->data[transaction->aid_len + 2] != - NFC_EVT_TRANSACTION_PARAMS_TAG) { - devm_kfree(dev, transaction); + /* Verify PARAMETERS tag is (82), and final check that there is enough + * space in the packet to read everything. + */ + if ((skb->data[aid_len + 2] != NFC_EVT_TRANSACTION_PARAMS_TAG) || + (skb->len < aid_len + 4 + params_len)) return -EPROTO; - } - transaction->params_len = skb->data[transaction->aid_len + 3]; + transaction = devm_kzalloc(dev, sizeof(*transaction) + params_len, GFP_KERNEL); + if (!transaction) + return -ENOMEM; - /* Total size is allocated (skb->len - 2) minus fixed array members */ - if (transaction->params_len > ((skb->len - 2) - - sizeof(struct nfc_evt_transaction))) { - devm_kfree(dev, transaction); - return -EINVAL; - } + transaction->aid_len = aid_len; + transaction->params_len = params_len; - memcpy(transaction->params, skb->data + - transaction->aid_len + 4, transaction->params_len); + memcpy(transaction->aid, &skb->data[2], aid_len); + memcpy(transaction->params, &skb->data[aid_len + 4], params_len); r = nfc_se_transaction(hdev->ndev, host, transaction); break; -- cgit From 8a4d480702b71184fabcf379b80bf7539716752e Mon Sep 17 00:00:00 2001 From: Xiaohui Zhang Date: Tue, 7 Jun 2022 16:32:30 +0800 Subject: nfc: nfcmrvl: Fix memory leak in nfcmrvl_play_deferred Similar to the handling of play_deferred in commit 19cfe912c37b ("Bluetooth: btusb: Fix memory leak in play_deferred"), we thought a patch might be needed here as well. Currently usb_submit_urb is called directly to submit deferred tx urbs after unanchor them. So the usb_giveback_urb_bh would failed to unref it in usb_unanchor_urb and cause memory leak. Put those urbs in tx_anchor to avoid the leak, and also fix the error handling. Signed-off-by: Xiaohui Zhang Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220607083230.6182-1-xiaohuizhang@ruc.edu.cn Signed-off-by: Jakub Kicinski --- drivers/nfc/nfcmrvl/usb.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/nfc/nfcmrvl/usb.c b/drivers/nfc/nfcmrvl/usb.c index a99aedff795d..ea7309453096 100644 --- a/drivers/nfc/nfcmrvl/usb.c +++ b/drivers/nfc/nfcmrvl/usb.c @@ -388,13 +388,25 @@ static void nfcmrvl_play_deferred(struct nfcmrvl_usb_drv_data *drv_data) int err; while ((urb = usb_get_from_anchor(&drv_data->deferred))) { + usb_anchor_urb(urb, &drv_data->tx_anchor); + err = usb_submit_urb(urb, GFP_ATOMIC); - if (err) + if (err) { + kfree(urb->setup_packet); + usb_unanchor_urb(urb); + usb_free_urb(urb); break; + } drv_data->tx_in_flight++; + usb_free_urb(urb); + } + + /* Cleanup the rest deferred urbs. */ + while ((urb = usb_get_from_anchor(&drv_data->deferred))) { + kfree(urb->setup_packet); + usb_free_urb(urb); } - usb_scuttle_anchored_urbs(&drv_data->deferred); } static int nfcmrvl_resume(struct usb_interface *intf) -- cgit From a3d52ac7750025b5a1f99eb1ccea0e31b58bf7bb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 7 Jun 2022 17:51:28 +0100 Subject: arm64/sme: Fix tests for 0b1111 value ID registers For both ID_AA64SMFR0_EL1.I16I64 and ID_AA64SMFR0_EL1.I8I32 we check for the presence of the feature by looking for a specific ID value of 0x4 but should instead be checking for the value 0xf defined by the architecture. This had no practical effect since we are looking for values >= our define and the only valid values in the architecture are 0b0000 and 0b1111 so we would detect things appropriately with the architecture as it stands even with the incorrect defines. Signed-off-by: Mark Brown Fixes: b4adc83b0770 ("arm64/sme: System register and exception syndrome definitions") Link: https://lore.kernel.org/r/20220607165128.2833157-1-broonie@kernel.org Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/sysreg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 55f998c3dc28..42ff95dba6da 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -843,9 +843,9 @@ #define ID_AA64SMFR0_F32F32_SHIFT 32 #define ID_AA64SMFR0_FA64 0x1 -#define ID_AA64SMFR0_I16I64 0x4 +#define ID_AA64SMFR0_I16I64 0xf #define ID_AA64SMFR0_F64F64 0x1 -#define ID_AA64SMFR0_I8I32 0x4 +#define ID_AA64SMFR0_I8I32 0xf #define ID_AA64SMFR0_F16F32 0x1 #define ID_AA64SMFR0_B16F32 0x1 #define ID_AA64SMFR0_F32F32 0x1 -- cgit From f539316fe8106b4f4b4e95c1e70a31b545523b03 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 8 Jun 2022 12:59:15 +0100 Subject: arm64/sme: Fix SVE/SME typo in ABI documentation Fix a cut'n'paste error. Reported-by: Luis Machado Signed-off-by: Mark Brown Link: https://lore.kernel.org/r/20220608115915.251870-1-broonie@kernel.org Signed-off-by: Catalin Marinas --- Documentation/arm64/sme.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/arm64/sme.rst b/Documentation/arm64/sme.rst index 8ba677b87e90..937147f58cc5 100644 --- a/Documentation/arm64/sme.rst +++ b/Documentation/arm64/sme.rst @@ -371,7 +371,7 @@ The regset data starts with struct user_za_header, containing: Appendix A. SME programmer's model (informative) ================================================= -This section provides a minimal description of the additions made by SVE to the +This section provides a minimal description of the additions made by SME to the ARMv8-A programmer's model that are relevant to this document. Note: This section is for information only and not intended to be complete or -- cgit From f93431c86b631bbca5614c66f966bf3ddb3c2803 Mon Sep 17 00:00:00 2001 From: Wang Yufen Date: Tue, 7 Jun 2022 20:00:27 +0800 Subject: ipv6: Fix signed integer overflow in __ip6_append_data Resurrect ubsan overflow checks and ubsan report this warning, fix it by change the variable [length] type to size_t. UBSAN: signed-integer-overflow in net/ipv6/ip6_output.c:1489:19 2147479552 + 8567 cannot be represented in type 'int' CPU: 0 PID: 253 Comm: err Not tainted 5.16.0+ #1 Hardware name: linux,dummy-virt (DT) Call trace: dump_backtrace+0x214/0x230 show_stack+0x30/0x78 dump_stack_lvl+0xf8/0x118 dump_stack+0x18/0x30 ubsan_epilogue+0x18/0x60 handle_overflow+0xd0/0xf0 __ubsan_handle_add_overflow+0x34/0x44 __ip6_append_data.isra.48+0x1598/0x1688 ip6_append_data+0x128/0x260 udpv6_sendmsg+0x680/0xdd0 inet6_sendmsg+0x54/0x90 sock_sendmsg+0x70/0x88 ____sys_sendmsg+0xe8/0x368 ___sys_sendmsg+0x98/0xe0 __sys_sendmmsg+0xf4/0x3b8 __arm64_sys_sendmmsg+0x34/0x48 invoke_syscall+0x64/0x160 el0_svc_common.constprop.4+0x124/0x300 do_el0_svc+0x44/0xc8 el0_svc+0x3c/0x1e8 el0t_64_sync_handler+0x88/0xb0 el0t_64_sync+0x16c/0x170 Changes since v1: -Change the variable [length] type to unsigned, as Eric Dumazet suggested. Changes since v2: -Don't change exthdrlen type in ip6_make_skb, as Paolo Abeni suggested. Changes since v3: -Don't change ulen type in udpv6_sendmsg and l2tp_ip6_sendmsg, as Jakub Kicinski suggested. Reported-by: Hulk Robot Signed-off-by: Wang Yufen Link: https://lore.kernel.org/r/20220607120028.845916-1-wangyufen@huawei.com Signed-off-by: Jakub Kicinski --- include/net/ipv6.h | 4 ++-- net/ipv6/ip6_output.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 5b38bf1a586b..de9dcc5652c4 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -1063,7 +1063,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr); int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), - void *from, int length, int transhdrlen, + void *from, size_t length, int transhdrlen, struct ipcm6_cookie *ipc6, struct flowi6 *fl6, struct rt6_info *rt, unsigned int flags); @@ -1079,7 +1079,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk, struct sk_buff_head *queue, struct sk_buff *ip6_make_skb(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), - void *from, int length, int transhdrlen, + void *from, size_t length, int transhdrlen, struct ipcm6_cookie *ipc6, struct rt6_info *rt, unsigned int flags, struct inet_cork_full *cork); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4081b12a01ff..77e3f5970ce4 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1450,7 +1450,7 @@ static int __ip6_append_data(struct sock *sk, struct page_frag *pfrag, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), - void *from, int length, int transhdrlen, + void *from, size_t length, int transhdrlen, unsigned int flags, struct ipcm6_cookie *ipc6) { struct sk_buff *skb, *skb_prev = NULL; @@ -1798,7 +1798,7 @@ error: int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), - void *from, int length, int transhdrlen, + void *from, size_t length, int transhdrlen, struct ipcm6_cookie *ipc6, struct flowi6 *fl6, struct rt6_info *rt, unsigned int flags) { @@ -1995,7 +1995,7 @@ EXPORT_SYMBOL_GPL(ip6_flush_pending_frames); struct sk_buff *ip6_make_skb(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), - void *from, int length, int transhdrlen, + void *from, size_t length, int transhdrlen, struct ipcm6_cookie *ipc6, struct rt6_info *rt, unsigned int flags, struct inet_cork_full *cork) { -- cgit From f638a84afef3dfe10554c51820c16e39a278c915 Mon Sep 17 00:00:00 2001 From: Wang Yufen Date: Tue, 7 Jun 2022 20:00:28 +0800 Subject: ipv6: Fix signed integer overflow in l2tp_ip6_sendmsg When len >= INT_MAX - transhdrlen, ulen = len + transhdrlen will be overflow. To fix, we can follow what udpv6 does and subtract the transhdrlen from the max. Signed-off-by: Wang Yufen Link: https://lore.kernel.org/r/20220607120028.845916-2-wangyufen@huawei.com Signed-off-by: Jakub Kicinski --- net/l2tp/l2tp_ip6.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index c6ff8bf9b55f..9dbd801ddb98 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -504,14 +504,15 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) struct ipcm6_cookie ipc6; int addr_len = msg->msg_namelen; int transhdrlen = 4; /* zero session-id */ - int ulen = len + transhdrlen; + int ulen; int err; /* Rough check on arithmetic overflow, * better check is made in ip6_append_data(). */ - if (len > INT_MAX) + if (len > INT_MAX - transhdrlen) return -EMSGSIZE; + ulen = len + transhdrlen; /* Mirror BSD error message compatibility */ if (msg->msg_flags & MSG_OOB) -- cgit From 29dec90a0f1d961b93f34f910e9319d8cb23edbd Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 8 Jun 2022 08:34:06 +0200 Subject: dm: fix bio_set allocation The use of bioset_init_from_src mean that the pre-allocated pools weren't used for anything except parameter passing, and the integrity pool creation got completely lost for the actual live mapped_device. Fix that by assigning the actual preallocated dm_md_mempools to the mapped_device and using that for I/O instead of creating new mempools. Fixes: 2a2a4c510b76 ("dm: use bioset_init_from_src() to copy bio_set") Signed-off-by: Christoph Hellwig Signed-off-by: Mike Snitzer --- drivers/md/dm-core.h | 11 +++++-- drivers/md/dm-rq.c | 2 +- drivers/md/dm-table.c | 11 ------- drivers/md/dm.c | 84 +++++++++++++++------------------------------------ drivers/md/dm.h | 2 -- 5 files changed, 35 insertions(+), 75 deletions(-) diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h index d21648a923ea..54c0473a51dd 100644 --- a/drivers/md/dm-core.h +++ b/drivers/md/dm-core.h @@ -33,6 +33,14 @@ struct dm_kobject_holder { * access their members! */ +/* + * For mempools pre-allocation at the table loading time. + */ +struct dm_md_mempools { + struct bio_set bs; + struct bio_set io_bs; +}; + struct mapped_device { struct mutex suspend_lock; @@ -110,8 +118,7 @@ struct mapped_device { /* * io objects are allocated from here. */ - struct bio_set io_bs; - struct bio_set bs; + struct dm_md_mempools *mempools; /* kobject and completion */ struct dm_kobject_holder kobj_holder; diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index 6087cdcaad46..a83b98a8d2a9 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -319,7 +319,7 @@ static int setup_clone(struct request *clone, struct request *rq, { int r; - r = blk_rq_prep_clone(clone, rq, &tio->md->bs, gfp_mask, + r = blk_rq_prep_clone(clone, rq, &tio->md->mempools->bs, gfp_mask, dm_rq_bio_constructor, tio); if (r) return r; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 0e833a154b31..bd539afbfe88 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1038,17 +1038,6 @@ static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device * return 0; } -void dm_table_free_md_mempools(struct dm_table *t) -{ - dm_free_md_mempools(t->mempools); - t->mempools = NULL; -} - -struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t) -{ - return t->mempools; -} - static int setup_indexes(struct dm_table *t) { int i; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index dfb0a551bd88..8b21155d3c4f 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -136,14 +136,6 @@ static int get_swap_bios(void) return latch; } -/* - * For mempools pre-allocation at the table loading time. - */ -struct dm_md_mempools { - struct bio_set bs; - struct bio_set io_bs; -}; - struct table_device { struct list_head list; refcount_t count; @@ -581,7 +573,7 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio) struct dm_target_io *tio; struct bio *clone; - clone = bio_alloc_clone(NULL, bio, GFP_NOIO, &md->io_bs); + clone = bio_alloc_clone(NULL, bio, GFP_NOIO, &md->mempools->io_bs); /* Set default bdev, but target must bio_set_dev() before issuing IO */ clone->bi_bdev = md->disk->part0; @@ -628,7 +620,8 @@ static struct bio *alloc_tio(struct clone_info *ci, struct dm_target *ti, } else { struct mapped_device *md = ci->io->md; - clone = bio_alloc_clone(NULL, ci->bio, gfp_mask, &md->bs); + clone = bio_alloc_clone(NULL, ci->bio, gfp_mask, + &md->mempools->bs); if (!clone) return NULL; /* Set default bdev, but target must bio_set_dev() before issuing IO */ @@ -1876,8 +1869,7 @@ static void cleanup_mapped_device(struct mapped_device *md) { if (md->wq) destroy_workqueue(md->wq); - bioset_exit(&md->bs); - bioset_exit(&md->io_bs); + dm_free_md_mempools(md->mempools); if (md->dax_dev) { dax_remove_host(md->disk); @@ -2049,48 +2041,6 @@ static void free_dev(struct mapped_device *md) kvfree(md); } -static int __bind_mempools(struct mapped_device *md, struct dm_table *t) -{ - struct dm_md_mempools *p = dm_table_get_md_mempools(t); - int ret = 0; - - if (dm_table_bio_based(t)) { - /* - * The md may already have mempools that need changing. - * If so, reload bioset because front_pad may have changed - * because a different table was loaded. - */ - bioset_exit(&md->bs); - bioset_exit(&md->io_bs); - - } else if (bioset_initialized(&md->bs)) { - /* - * There's no need to reload with request-based dm - * because the size of front_pad doesn't change. - * Note for future: If you are to reload bioset, - * prep-ed requests in the queue may refer - * to bio from the old bioset, so you must walk - * through the queue to unprep. - */ - goto out; - } - - BUG_ON(!p || - bioset_initialized(&md->bs) || - bioset_initialized(&md->io_bs)); - - ret = bioset_init_from_src(&md->bs, &p->bs); - if (ret) - goto out; - ret = bioset_init_from_src(&md->io_bs, &p->io_bs); - if (ret) - bioset_exit(&md->bs); -out: - /* mempool bind completed, no longer need any mempools in the table */ - dm_table_free_md_mempools(t); - return ret; -} - /* * Bind a table to the device. */ @@ -2144,12 +2094,28 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, * immutable singletons - used to optimize dm_mq_queue_rq. */ md->immutable_target = dm_table_get_immutable_target(t); - } - ret = __bind_mempools(md, t); - if (ret) { - old_map = ERR_PTR(ret); - goto out; + /* + * There is no need to reload with request-based dm because the + * size of front_pad doesn't change. + * + * Note for future: If you are to reload bioset, prep-ed + * requests in the queue may refer to bio from the old bioset, + * so you must walk through the queue to unprep. + */ + if (!md->mempools) { + md->mempools = t->mempools; + t->mempools = NULL; + } + } else { + /* + * The md may already have mempools that need changing. + * If so, reload bioset because front_pad may have changed + * because a different table was loaded. + */ + dm_free_md_mempools(md->mempools); + md->mempools = t->mempools; + t->mempools = NULL; } ret = dm_table_set_restrictions(t, md->queue, limits); diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 3f89664fea01..a8405ce305a9 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -71,8 +71,6 @@ struct dm_target *dm_table_get_immutable_target(struct dm_table *t); struct dm_target *dm_table_get_wildcard_target(struct dm_table *t); bool dm_table_bio_based(struct dm_table *t); bool dm_table_request_based(struct dm_table *t); -void dm_table_free_md_mempools(struct dm_table *t); -struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); void dm_lock_md_type(struct mapped_device *md); void dm_unlock_md_type(struct mapped_device *md); -- cgit From d5a37b19983725d2045588cfa3a4699f5b39ae26 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 8 Jun 2022 08:34:07 +0200 Subject: block: remove bioset_init_from_src Unused now, and the interface never really made a whole lot of sense to start with. Signed-off-by: Christoph Hellwig Signed-off-by: Mike Snitzer --- block/bio.c | 20 -------------------- include/linux/bio.h | 1 - 2 files changed, 21 deletions(-) diff --git a/block/bio.c b/block/bio.c index f92d0223247b..51c99f2c5c90 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1747,26 +1747,6 @@ bad: } EXPORT_SYMBOL(bioset_init); -/* - * Initialize and setup a new bio_set, based on the settings from - * another bio_set. - */ -int bioset_init_from_src(struct bio_set *bs, struct bio_set *src) -{ - int flags; - - flags = 0; - if (src->bvec_pool.min_nr) - flags |= BIOSET_NEED_BVECS; - if (src->rescue_workqueue) - flags |= BIOSET_NEED_RESCUER; - if (src->cache) - flags |= BIOSET_PERCPU_CACHE; - - return bioset_init(bs, src->bio_pool.min_nr, src->front_pad, flags); -} -EXPORT_SYMBOL(bioset_init_from_src); - static int __init init_bio(void) { int i; diff --git a/include/linux/bio.h b/include/linux/bio.h index 1cf3738ef1ea..992ee987f273 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -403,7 +403,6 @@ enum { extern int bioset_init(struct bio_set *, unsigned int, unsigned int, int flags); extern void bioset_exit(struct bio_set *); extern int biovec_init_pool(mempool_t *pool, int pool_entries); -extern int bioset_init_from_src(struct bio_set *bs, struct bio_set *src); struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs, unsigned int opf, gfp_t gfp_mask, -- cgit From a6958951ebe7db60e84b2437ee53aa4843028726 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 7 Jun 2022 11:01:46 +0200 Subject: au1000_eth: stop using virt_to_bus() The conversion to the dma-mapping API in linux-2.6.11 was incomplete and left a virt_to_bus() call around. There have been a number of fixes for DMA mapping API abuse in this driver, but this one always slipped through. Change it to just use the existing dma_addr_t pointer, and make it use the correct types throughout the driver to make it easier to understand the virtual vs dma address spaces. Signed-off-by: Arnd Bergmann Tested-by: Manuel Lauss Link: https://lore.kernel.org/r/20220607090206.19830-1-arnd@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/au1000_eth.c | 22 +++++++++++----------- drivers/net/ethernet/amd/au1000_eth.h | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index c6f003975621..d5f2c6989221 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -820,7 +820,7 @@ static int au1000_rx(struct net_device *dev) pr_cont("\n"); } } - prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE); + prxd->buff_stat = lower_32_bits(pDB->dma_addr) | RX_DMA_ENABLE; aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1); wmb(); /* drain writebuffer */ @@ -996,7 +996,7 @@ static netdev_tx_t au1000_tx(struct sk_buff *skb, struct net_device *dev) ps->tx_packets++; ps->tx_bytes += ptxd->len; - ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE; + ptxd->buff_stat = lower_32_bits(pDB->dma_addr) | TX_DMA_ENABLE; wmb(); /* drain writebuffer */ dev_kfree_skb(skb); aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1); @@ -1131,9 +1131,9 @@ static int au1000_probe(struct platform_device *pdev) /* Allocate the data buffers * Snooping works fine with eth on all au1xxx */ - aup->vaddr = (u32)dma_alloc_coherent(&pdev->dev, MAX_BUF_SIZE * - (NUM_TX_BUFFS + NUM_RX_BUFFS), - &aup->dma_addr, 0); + aup->vaddr = dma_alloc_coherent(&pdev->dev, MAX_BUF_SIZE * + (NUM_TX_BUFFS + NUM_RX_BUFFS), + &aup->dma_addr, 0); if (!aup->vaddr) { dev_err(&pdev->dev, "failed to allocate data buffers\n"); err = -ENOMEM; @@ -1234,8 +1234,8 @@ static int au1000_probe(struct platform_device *pdev) for (i = 0; i < (NUM_TX_BUFFS+NUM_RX_BUFFS); i++) { pDB->pnext = pDBfree; pDBfree = pDB; - pDB->vaddr = (u32 *)((unsigned)aup->vaddr + MAX_BUF_SIZE*i); - pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr); + pDB->vaddr = aup->vaddr + MAX_BUF_SIZE * i; + pDB->dma_addr = aup->dma_addr + MAX_BUF_SIZE * i; pDB++; } aup->pDBfree = pDBfree; @@ -1246,7 +1246,7 @@ static int au1000_probe(struct platform_device *pdev) if (!pDB) goto err_out; - aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr; + aup->rx_dma_ring[i]->buff_stat = lower_32_bits(pDB->dma_addr); aup->rx_db_inuse[i] = pDB; } @@ -1255,7 +1255,7 @@ static int au1000_probe(struct platform_device *pdev) if (!pDB) goto err_out; - aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr; + aup->tx_dma_ring[i]->buff_stat = lower_32_bits(pDB->dma_addr); aup->tx_dma_ring[i]->len = 0; aup->tx_db_inuse[i] = pDB; } @@ -1310,7 +1310,7 @@ err_remap2: iounmap(aup->mac); err_remap1: dma_free_coherent(&pdev->dev, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), - (void *)aup->vaddr, aup->dma_addr); + aup->vaddr, aup->dma_addr); err_vaddr: free_netdev(dev); err_alloc: @@ -1343,7 +1343,7 @@ static int au1000_remove(struct platform_device *pdev) au1000_ReleaseDB(aup, aup->tx_db_inuse[i]); dma_free_coherent(&pdev->dev, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), - (void *)aup->vaddr, aup->dma_addr); + aup->vaddr, aup->dma_addr); iounmap(aup->macdma); iounmap(aup->mac); diff --git a/drivers/net/ethernet/amd/au1000_eth.h b/drivers/net/ethernet/amd/au1000_eth.h index e3a3ed29db61..2489c2f4fd8a 100644 --- a/drivers/net/ethernet/amd/au1000_eth.h +++ b/drivers/net/ethernet/amd/au1000_eth.h @@ -106,8 +106,8 @@ struct au1000_private { struct mac_reg *mac; /* mac registers */ u32 *enable; /* address of MAC Enable Register */ void __iomem *macdma; /* base of MAC DMA port */ - u32 vaddr; /* virtual address of rx/tx buffers */ - dma_addr_t dma_addr; /* dma address of rx/tx buffers */ + void *vaddr; /* virtual address of rx/tx buffers */ + dma_addr_t dma_addr; /* dma address of rx/tx buffers */ spinlock_t lock; /* Serialise access to device */ -- cgit From ed872f92fd0946ba30f2acd05fc57e29cac29cd2 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Wed, 1 Jun 2022 06:57:38 +0200 Subject: MAINTAINERS: adjust MELLANOX ETHERNET INNOVA DRIVERS to TLS support removal Commit 40379a0084c2 ("net/mlx5_fpga: Drop INNOVA TLS support") removes all files in the directory drivers/net/ethernet/mellanox/mlx5/core/accel/, but misses to adjust its reference in MAINTAINERS. Hence, ./scripts/get_maintainer.pl --self-test=patterns complains about a broken reference. Remove the file entry to the removed directory in MELLANOX ETHERNET INNOVA DRIVERS. Signed-off-by: Lukas Bulwahn Signed-off-by: Saeed Mahameed --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 033a01b07f8f..bab9e131ec9c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12651,7 +12651,6 @@ L: netdev@vger.kernel.org S: Supported W: http://www.mellanox.com Q: https://patchwork.kernel.org/project/netdevbpf/list/ -F: drivers/net/ethernet/mellanox/mlx5/core/accel/* F: drivers/net/ethernet/mellanox/mlx5/core/en_accel/* F: drivers/net/ethernet/mellanox/mlx5/core/fpga/* F: include/linux/mlx5/mlx5_ifc_fpga.h -- cgit From 4d995c1b9d49ee657e879745aa5e445f031c0dba Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Fri, 3 Jun 2022 14:33:03 -0700 Subject: Revert "net/mlx5e: Allow relaxed ordering over VFs" FW is not ready, fix was sent too soon. This reverts commit f05ec8d9d0d62367b6e1f2cb50d7d2a45e7747cf. Fixes: f05ec8d9d0d6 ("net/mlx5e: Allow relaxed ordering over VFs") Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/params.c | 3 ++- drivers/net/ethernet/mellanox/mlx5/core/en_common.c | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c index 68364484a435..3c1edfa33aa7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c @@ -565,7 +565,8 @@ static void mlx5e_build_rx_cq_param(struct mlx5_core_dev *mdev, static u8 rq_end_pad_mode(struct mlx5_core_dev *mdev, struct mlx5e_params *params) { bool lro_en = params->packet_merge.type == MLX5E_PACKET_MERGE_LRO; - bool ro = MLX5_CAP_GEN(mdev, relaxed_ordering_write); + bool ro = pcie_relaxed_ordering_enabled(mdev->pdev) && + MLX5_CAP_GEN(mdev, relaxed_ordering_write); return ro && lro_en ? MLX5_WQ_END_PAD_MODE_NONE : MLX5_WQ_END_PAD_MODE_ALIGN; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c index 43a536cb81db..c0f409c195bf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c @@ -38,11 +38,12 @@ void mlx5e_mkey_set_relaxed_ordering(struct mlx5_core_dev *mdev, void *mkc) { + bool ro_pci_enable = pcie_relaxed_ordering_enabled(mdev->pdev); bool ro_write = MLX5_CAP_GEN(mdev, relaxed_ordering_write); bool ro_read = MLX5_CAP_GEN(mdev, relaxed_ordering_read); - MLX5_SET(mkc, mkc, relaxed_ordering_read, ro_read); - MLX5_SET(mkc, mkc, relaxed_ordering_write, ro_write); + MLX5_SET(mkc, mkc, relaxed_ordering_read, ro_pci_enable && ro_read); + MLX5_SET(mkc, mkc, relaxed_ordering_write, ro_pci_enable && ro_write); } static int mlx5e_create_mkey(struct mlx5_core_dev *mdev, u32 pdn, -- cgit From 15ef9efa855cf405fadd78272e1e5d04e09a1cf3 Mon Sep 17 00:00:00 2001 From: Paul Blakey Date: Tue, 29 Mar 2022 18:37:18 +0300 Subject: net/mlx5e: CT: Fix cleanup of CT before cleanup of TC ct rules CT cleanup assumes that all tc rules were deleted first, and so is free to delete the CT shared resources (e.g the dr_action fwd_action which is shared for all tuples). But currently for uplink, this is happens in reverse, causing the below trace. CT cleanup is called from: mlx5e_cleanup_rep_tx()->mlx5e_cleanup_uplink_rep_tx()-> mlx5e_rep_tc_cleanup()->mlx5e_tc_esw_cleanup()-> mlx5_tc_ct_clean() Only afterwards, tc cleanup is called from: mlx5e_cleanup_rep_tx()->mlx5e_tc_ht_cleanup() which would have deleted all the tc ct rules, and so delete all the offloaded tuples. Fix this reversing the order of init and on cleanup, which will result in tc cleanup then ct cleanup. [ 9443.593347] WARNING: CPU: 2 PID: 206774 at drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c:1882 mlx5dr_action_destroy+0x188/0x1a0 [mlx5_core] [ 9443.593349] Modules linked in: act_ct nf_flow_table rdma_ucm(O) rdma_cm(O) iw_cm(O) ib_ipoib(O) ib_cm(O) ib_umad(O) mlx5_core(O-) mlxfw(O) mlxdevm(O) auxiliary(O) ib_uverbs(O) psample ib_core(O) mlx_compat(O) ip_gre gre ip_tunnel act_vlan bonding geneve esp6_offload esp6 esp4_offload esp4 act_tunnel_key vxlan ip6_udp_tunnel udp_tunnel act_mirred act_skbedit act_gact cls_flower sch_ingress nfnetlink_cttimeout nfnetlink xfrm_user xfrm_algo 8021q garp stp ipmi_devintf mrp ipmi_msghandler llc openvswitch nsh nf_conncount nf_nat mst_pciconf(O) dm_multipath sbsa_gwdt uio_pdrv_genirq uio mlxbf_pmc mlxbf_pka mlx_trio mlx_bootctl(O) bluefield_edac sch_fq_codel ip_tables ipv6 crc_ccitt btrfs zstd_compress raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor xor_neon raid6_pq raid1 raid0 crct10dif_ce i2c_mlxbf gpio_mlxbf2 mlxbf_gige aes_neon_bs aes_neon_blk [last unloaded: mlx5_ib] [ 9443.593419] CPU: 2 PID: 206774 Comm: modprobe Tainted: G O 5.4.0-1023.24.gc14613d-bluefield #1 [ 9443.593422] Hardware name: https://www.mellanox.com BlueField SoC/BlueField SoC, BIOS BlueField:143ebaf Jan 11 2022 [ 9443.593424] pstate: 20000005 (nzCv daif -PAN -UAO) [ 9443.593489] pc : mlx5dr_action_destroy+0x188/0x1a0 [mlx5_core] [ 9443.593545] lr : mlx5_ct_fs_smfs_destroy+0x24/0x30 [mlx5_core] [ 9443.593546] sp : ffff8000135dbab0 [ 9443.593548] x29: ffff8000135dbab0 x28: ffff0003a6ab8e80 [ 9443.593550] x27: 0000000000000000 x26: ffff0003e07d7000 [ 9443.593552] x25: ffff800009609de0 x24: ffff000397fb2120 [ 9443.593554] x23: ffff0003975c0000 x22: 0000000000000000 [ 9443.593556] x21: ffff0003975f08c0 x20: ffff800009609de0 [ 9443.593558] x19: ffff0003c8a13380 x18: 0000000000000014 [ 9443.593560] x17: 0000000067f5f125 x16: 000000006529c620 [ 9443.593561] x15: 000000000000000b x14: 0000000000000000 [ 9443.593563] x13: 0000000000000002 x12: 0000000000000001 [ 9443.593565] x11: ffff800011108868 x10: 0000000000000000 [ 9443.593567] x9 : 0000000000000000 x8 : ffff8000117fb270 [ 9443.593569] x7 : ffff0003ebc01288 x6 : 0000000000000000 [ 9443.593571] x5 : ffff800009591ab8 x4 : fffffe000f6d9a20 [ 9443.593572] x3 : 0000000080040001 x2 : fffffe000f6d9a20 [ 9443.593574] x1 : ffff8000095901d8 x0 : 0000000000000025 [ 9443.593577] Call trace: [ 9443.593634] mlx5dr_action_destroy+0x188/0x1a0 [mlx5_core] [ 9443.593688] mlx5_ct_fs_smfs_destroy+0x24/0x30 [mlx5_core] [ 9443.593743] mlx5_tc_ct_clean+0x34/0xa8 [mlx5_core] [ 9443.593797] mlx5e_tc_esw_cleanup+0x58/0x88 [mlx5_core] [ 9443.593851] mlx5e_rep_tc_cleanup+0x24/0x30 [mlx5_core] [ 9443.593905] mlx5e_cleanup_rep_tx+0x6c/0x78 [mlx5_core] [ 9443.593959] mlx5e_detach_netdev+0x74/0x98 [mlx5_core] [ 9443.594013] mlx5e_netdev_change_profile+0x70/0x180 [mlx5_core] [ 9443.594067] mlx5e_netdev_attach_nic_profile+0x34/0x40 [mlx5_core] [ 9443.594122] mlx5e_vport_rep_unload+0x15c/0x1a8 [mlx5_core] [ 9443.594177] mlx5_eswitch_unregister_vport_reps+0x228/0x298 [mlx5_core] [ 9443.594231] mlx5e_rep_remove+0x2c/0x38 [mlx5_core] [ 9443.594236] auxiliary_bus_remove+0x30/0x50 [auxiliary] [ 9443.594246] device_release_driver_internal+0x108/0x1d0 [ 9443.594248] driver_detach+0x5c/0xe8 [ 9443.594250] bus_remove_driver+0x64/0xd8 [ 9443.594253] driver_unregister+0x38/0x60 [ 9443.594255] auxiliary_driver_unregister+0x24/0x38 [auxiliary] [ 9443.594311] mlx5e_rep_cleanup+0x20/0x38 [mlx5_core] [ 9443.594365] mlx5e_cleanup+0x18/0x30 [mlx5_core] [ 9443.594419] cleanup+0xc/0x20cc [mlx5_core] [ 9443.594424] __arm64_sys_delete_module+0x154/0x2b0 [ 9443.594429] el0_svc_common.constprop.0+0xf4/0x200 [ 9443.594432] el0_svc_handler+0x38/0xa8 [ 9443.594435] el0_svc+0x10/0x26c Fixes: d1a3138f7913 ("net/mlx5e: TC, Move flow hashtable to be per rep") Signed-off-by: Paul Blakey Reviewed-by: Oz Shlomo Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 31 ++++++++++++------------ 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index eb90e79388f1..f797fd97d305 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -950,6 +950,13 @@ err_event_reg: return err; } +static void mlx5e_cleanup_uplink_rep_tx(struct mlx5e_rep_priv *rpriv) +{ + mlx5e_rep_tc_netdevice_event_unregister(rpriv); + mlx5e_rep_bond_cleanup(rpriv); + mlx5e_rep_tc_cleanup(rpriv); +} + static int mlx5e_init_rep_tx(struct mlx5e_priv *priv) { struct mlx5e_rep_priv *rpriv = priv->ppriv; @@ -961,42 +968,36 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv) return err; } - err = mlx5e_tc_ht_init(&rpriv->tc_ht); - if (err) - goto err_ht_init; - if (rpriv->rep->vport == MLX5_VPORT_UPLINK) { err = mlx5e_init_uplink_rep_tx(rpriv); if (err) goto err_init_tx; } + err = mlx5e_tc_ht_init(&rpriv->tc_ht); + if (err) + goto err_ht_init; + return 0; -err_init_tx: - mlx5e_tc_ht_cleanup(&rpriv->tc_ht); err_ht_init: + if (rpriv->rep->vport == MLX5_VPORT_UPLINK) + mlx5e_cleanup_uplink_rep_tx(rpriv); +err_init_tx: mlx5e_destroy_tises(priv); return err; } -static void mlx5e_cleanup_uplink_rep_tx(struct mlx5e_rep_priv *rpriv) -{ - mlx5e_rep_tc_netdevice_event_unregister(rpriv); - mlx5e_rep_bond_cleanup(rpriv); - mlx5e_rep_tc_cleanup(rpriv); -} - static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv) { struct mlx5e_rep_priv *rpriv = priv->ppriv; - mlx5e_destroy_tises(priv); + mlx5e_tc_ht_cleanup(&rpriv->tc_ht); if (rpriv->rep->vport == MLX5_VPORT_UPLINK) mlx5e_cleanup_uplink_rep_tx(rpriv); - mlx5e_tc_ht_cleanup(&rpriv->tc_ht); + mlx5e_destroy_tises(priv); } static void mlx5e_rep_enable(struct mlx5e_priv *priv) -- cgit From 3008e6a0049361e731b803c60fe8f3ab44e1d73f Mon Sep 17 00:00:00 2001 From: Mark Bloch Date: Thu, 26 May 2022 08:15:28 +0300 Subject: net/mlx5: E-Switch, pair only capable devices OFFLOADS paring using devcom is possible only on devices that support LAG. Filter based on lag capabilities. This fixes an issue where mlx5_get_next_phys_dev() was called without holding the interface lock. This issue was found when commit bc4c2f2e0179 ("net/mlx5: Lag, filter non compatible devices") added an assert that verifies the interface lock is held. WARNING: CPU: 9 PID: 1706 at drivers/net/ethernet/mellanox/mlx5/core/dev.c:642 mlx5_get_next_phys_dev+0xd2/0x100 [mlx5_core] Modules linked in: mlx5_vdpa vringh vhost_iotlb vdpa mlx5_ib mlx5_core xt_conntrack xt_MASQUERADE nf_conntrack_netlink nfnetlink xt_addrtype iptable_nat nf_nat br_netfilter rpcrdma rdma_ucm ib_iser libiscsi scsi_transport_iscsi rdma_cm iw_cm ib_umad ib_ipoib ib_cm ib_uverbs ib_core overlay fuse [last unloaded: mlx5_core] CPU: 9 PID: 1706 Comm: devlink Not tainted 5.18.0-rc7+ #11 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 RIP: 0010:mlx5_get_next_phys_dev+0xd2/0x100 [mlx5_core] Code: 02 00 75 48 48 8b 85 80 04 00 00 5d c3 31 c0 5d c3 be ff ff ff ff 48 c7 c7 08 41 5b a0 e8 36 87 28 e3 85 c0 0f 85 6f ff ff ff <0f> 0b e9 68 ff ff ff 48 c7 c7 0c 91 cc 84 e8 cb 36 6f e1 e9 4d ff RSP: 0018:ffff88811bf47458 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff88811b398000 RCX: 0000000000000001 RDX: 0000000080000000 RSI: ffffffffa05b4108 RDI: ffff88812daaaa78 RBP: ffff88812d050380 R08: 0000000000000001 R09: ffff88811d6b3437 R10: 0000000000000001 R11: 00000000fddd3581 R12: ffff88815238c000 R13: ffff88812d050380 R14: ffff8881018aa7e0 R15: ffff88811d6b3428 FS: 00007fc82e18ae80(0000) GS:ffff88842e080000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f9630d1b421 CR3: 0000000149802004 CR4: 0000000000370ea0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: mlx5_esw_offloads_devcom_event+0x99/0x3b0 [mlx5_core] mlx5_devcom_send_event+0x167/0x1d0 [mlx5_core] esw_offloads_enable+0x1153/0x1500 [mlx5_core] ? mlx5_esw_offloads_controller_valid+0x170/0x170 [mlx5_core] ? wait_for_completion_io_timeout+0x20/0x20 ? mlx5_rescan_drivers_locked+0x318/0x810 [mlx5_core] mlx5_eswitch_enable_locked+0x586/0xc50 [mlx5_core] ? mlx5_eswitch_disable_pf_vf_vports+0x1d0/0x1d0 [mlx5_core] ? mlx5_esw_try_lock+0x1b/0xb0 [mlx5_core] ? mlx5_eswitch_enable+0x270/0x270 [mlx5_core] ? __debugfs_create_file+0x260/0x3e0 mlx5_devlink_eswitch_mode_set+0x27e/0x870 [mlx5_core] ? mutex_lock_io_nested+0x12c0/0x12c0 ? esw_offloads_disable+0x250/0x250 [mlx5_core] ? devlink_nl_cmd_trap_get_dumpit+0x470/0x470 ? rcu_read_lock_sched_held+0x3f/0x70 devlink_nl_cmd_eswitch_set_doit+0x217/0x620 Fixes: dd3fddb82780 ("net/mlx5: E-Switch, handle devcom events only for ports on the same device") Signed-off-by: Mark Bloch Reviewed-by: Roi Dayan Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/dev.c | 18 ------------------ .../net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 9 ++++++--- drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h | 10 ++++++++++ drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h | 1 - 4 files changed, 16 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c index 0eb9d74547f8..50422b56a64d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c @@ -579,17 +579,6 @@ static void *pci_get_other_drvdata(struct device *this, struct device *other) return pci_get_drvdata(to_pci_dev(other)); } -static int next_phys_dev(struct device *dev, const void *data) -{ - struct mlx5_core_dev *mdev, *this = (struct mlx5_core_dev *)data; - - mdev = pci_get_other_drvdata(this->device, dev); - if (!mdev) - return 0; - - return _next_phys_dev(mdev, data); -} - static int next_phys_dev_lag(struct device *dev, const void *data) { struct mlx5_core_dev *mdev, *this = (struct mlx5_core_dev *)data; @@ -623,13 +612,6 @@ static struct mlx5_core_dev *mlx5_get_next_dev(struct mlx5_core_dev *dev, return pci_get_drvdata(to_pci_dev(next)); } -/* Must be called with intf_mutex held */ -struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev) -{ - lockdep_assert_held(&mlx5_intf_mutex); - return mlx5_get_next_dev(dev, &next_phys_dev); -} - /* Must be called with intf_mutex held */ struct mlx5_core_dev *mlx5_get_next_phys_dev_lag(struct mlx5_core_dev *dev) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 217cac29057f..2ce3728576d1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2690,9 +2690,6 @@ static int mlx5_esw_offloads_devcom_event(int event, switch (event) { case ESW_OFFLOADS_DEVCOM_PAIR: - if (mlx5_get_next_phys_dev(esw->dev) != peer_esw->dev) - break; - if (mlx5_eswitch_vport_match_metadata_enabled(esw) != mlx5_eswitch_vport_match_metadata_enabled(peer_esw)) break; @@ -2744,6 +2741,9 @@ static void esw_offloads_devcom_init(struct mlx5_eswitch *esw) if (!MLX5_CAP_ESW(esw->dev, merged_eswitch)) return; + if (!mlx5_is_lag_supported(esw->dev)) + return; + mlx5_devcom_register_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS, mlx5_esw_offloads_devcom_event, @@ -2761,6 +2761,9 @@ static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) if (!MLX5_CAP_ESW(esw->dev, merged_eswitch)) return; + if (!mlx5_is_lag_supported(esw->dev)) + return; + mlx5_devcom_send_event(devcom, MLX5_DEVCOM_ESW_OFFLOADS, ESW_OFFLOADS_DEVCOM_UNPAIR, esw); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h index 72f70fad4641..c81b173156d2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h @@ -74,6 +74,16 @@ struct mlx5_lag { struct lag_mpesw lag_mpesw; }; +static inline bool mlx5_is_lag_supported(struct mlx5_core_dev *dev) +{ + if (!MLX5_CAP_GEN(dev, vport_group_manager) || + !MLX5_CAP_GEN(dev, lag_master) || + MLX5_CAP_GEN(dev, num_lag_ports) < 2 || + MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS) + return false; + return true; +} + static inline struct mlx5_lag * mlx5_lag_dev(struct mlx5_core_dev *dev) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 484cb1e4fc7f..9cc7afea2758 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -209,7 +209,6 @@ int mlx5_attach_device(struct mlx5_core_dev *dev); void mlx5_detach_device(struct mlx5_core_dev *dev); int mlx5_register_device(struct mlx5_core_dev *dev); void mlx5_unregister_device(struct mlx5_core_dev *dev); -struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev); struct mlx5_core_dev *mlx5_get_next_phys_dev_lag(struct mlx5_core_dev *dev); void mlx5_dev_list_lock(void); void mlx5_dev_list_unlock(void); -- cgit From 8bf94e6414c9481bfa28269022688ab445d0081d Mon Sep 17 00:00:00 2001 From: Feras Daoud Date: Sat, 19 Mar 2022 21:47:48 +0200 Subject: net/mlx5: Rearm the FW tracer after each tracer event The current design does not arm the tracer if traces are available before the tracer string database is fully loaded, leading to an unfunctional tracer. This fix will rearm the tracer every time the FW triggers tracer event regardless of the tracer strings database status. Fixes: c71ad41ccb0c ("net/mlx5: FW tracer, events handling") Signed-off-by: Feras Daoud Signed-off-by: Roy Novich Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c index eae9aa9c0811..978a2bb8e122 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c @@ -675,6 +675,9 @@ static void mlx5_fw_tracer_handle_traces(struct work_struct *work) if (!tracer->owner) return; + if (unlikely(!tracer->str_db.loaded)) + goto arm; + block_count = tracer->buff.size / TRACER_BLOCK_SIZE_BYTE; start_offset = tracer->buff.consumer_index * TRACER_BLOCK_SIZE_BYTE; @@ -732,6 +735,7 @@ static void mlx5_fw_tracer_handle_traces(struct work_struct *work) &tmp_trace_block[TRACES_PER_BLOCK - 1]); } +arm: mlx5_fw_tracer_arm(dev); } @@ -1136,8 +1140,7 @@ static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void queue_work(tracer->work_queue, &tracer->ownership_change_work); break; case MLX5_TRACER_SUBTYPE_TRACES_AVAILABLE: - if (likely(tracer->str_db.loaded)) - queue_work(tracer->work_queue, &tracer->handle_traces_work); + queue_work(tracer->work_queue, &tracer->handle_traces_work); break; default: mlx5_core_dbg(dev, "FWTracer: Event with unrecognized subtype: sub_type %d\n", -- cgit From 8fa5e7b20e01042b14f8cd684d2da9b638460c74 Mon Sep 17 00:00:00 2001 From: Mark Bloch Date: Mon, 30 May 2022 10:46:59 +0300 Subject: net/mlx5: fs, fail conflicting actions When combining two steering rules into one check not only do they share the same actions but those actions are also the same. This resolves an issue where when creating two different rules with the same match the actions are overwritten and one of the rules is deleted a FW syndrome can be seen in dmesg. mlx5_core 0000:03:00.0: mlx5_cmd_check:819:(pid 2105): DEALLOC_MODIFY_HEADER_CONTEXT(0x941) op_mod(0x0) failed, status bad resource state(0x9), syndrome (0x1ab444) Fixes: 0d235c3fabb7 ("net/mlx5: Add hash table to search FTEs in a flow-group") Signed-off-by: Mark Bloch Reviewed-by: Maor Gottlieb Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 35 +++++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index fdcf7f529330..21e5c709b2d3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -1574,9 +1574,22 @@ static struct mlx5_flow_rule *find_flow_rule(struct fs_fte *fte, return NULL; } -static bool check_conflicting_actions(u32 action1, u32 action2) +static bool check_conflicting_actions_vlan(const struct mlx5_fs_vlan *vlan0, + const struct mlx5_fs_vlan *vlan1) { - u32 xored_actions = action1 ^ action2; + return vlan0->ethtype != vlan1->ethtype || + vlan0->vid != vlan1->vid || + vlan0->prio != vlan1->prio; +} + +static bool check_conflicting_actions(const struct mlx5_flow_act *act1, + const struct mlx5_flow_act *act2) +{ + u32 action1 = act1->action; + u32 action2 = act2->action; + u32 xored_actions; + + xored_actions = action1 ^ action2; /* if one rule only wants to count, it's ok */ if (action1 == MLX5_FLOW_CONTEXT_ACTION_COUNT || @@ -1593,6 +1606,22 @@ static bool check_conflicting_actions(u32 action1, u32 action2) MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2)) return true; + if (action1 & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT && + act1->pkt_reformat != act2->pkt_reformat) + return true; + + if (action1 & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR && + act1->modify_hdr != act2->modify_hdr) + return true; + + if (action1 & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH && + check_conflicting_actions_vlan(&act1->vlan[0], &act2->vlan[0])) + return true; + + if (action1 & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2 && + check_conflicting_actions_vlan(&act1->vlan[1], &act2->vlan[1])) + return true; + return false; } @@ -1600,7 +1629,7 @@ static int check_conflicting_ftes(struct fs_fte *fte, const struct mlx5_flow_context *flow_context, const struct mlx5_flow_act *flow_act) { - if (check_conflicting_actions(flow_act->action, fte->action.action)) { + if (check_conflicting_actions(flow_act, &fte->action)) { mlx5_core_warn(get_dev(&fte->node), "Found two FTEs with conflicting actions\n"); return -EEXIST; -- cgit From 431d071286524bd4f9ba2e46b1be87b479220174 Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Fri, 3 Jun 2022 10:24:31 +0800 Subject: drm/amdgpu/mes: only invalid/prime icache when finish loading both pipe MES FWs. invalid/prime icahce operation takes effect both pipes cuconrrently, therefore CP_MES_IC_BASE_LO/HI and CP_MES_MDBASE_LO/HI both have to be set before prime icache. Otherwise MES hardware gets garbage data in above regsters and causes page fault [ 470.873200] amdgpu 0000:33:00.0: amdgpu: [gfxhub] page fault (src_id:0 ring:217 vmid:0 pasid:0, for process pid 0 thread pid 0) [ 470.873222] amdgpu 0000:33:00.0: amdgpu: in page starting at address 0x000092cb89b00000 from client 10 [ 470.873234] amdgpu 0000:33:00.0: amdgpu: GCVM_L2_PROTECTION_FAULT_STATUS:0x00000BB3 [ 470.873242] amdgpu 0000:33:00.0: amdgpu: Faulty UTCL2 client ID: CPC (0x5) [ 470.873247] amdgpu 0000:33:00.0: amdgpu: MORE_FAULTS: 0x1 [ 470.873251] amdgpu 0000:33:00.0: amdgpu: WALKER_ERROR: 0x1 [ 470.873256] amdgpu 0000:33:00.0: amdgpu: PERMISSION_FAULTS: 0xb [ 470.873260] amdgpu 0000:33:00.0: amdgpu: MAPPING_ERROR: 0x1 [ 470.873264] amdgpu 0000:33:00.0: amdgpu: RW: 0x0 Signed-off-by: Yifan Zhang Acked-by: Alex Deucher Reviewed-by: Tim Huang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 36 +++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index fcf51947bb18..7eee004cf3ce 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -541,7 +541,7 @@ static void mes_v11_0_enable(struct amdgpu_device *adev, bool enable) /* This function is for backdoor MES firmware */ static int mes_v11_0_load_microcode(struct amdgpu_device *adev, - enum admgpu_mes_pipe pipe) + enum admgpu_mes_pipe pipe, bool prime_icache) { int r; uint32_t data; @@ -593,16 +593,18 @@ static int mes_v11_0_load_microcode(struct amdgpu_device *adev, /* Set 0x3FFFF (256K-1) to CP_MES_MDBOUND_LO */ WREG32_SOC15(GC, 0, regCP_MES_MDBOUND_LO, 0x3FFFF); - /* invalidate ICACHE */ - data = RREG32_SOC15(GC, 0, regCP_MES_IC_OP_CNTL); - data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 0); - data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, INVALIDATE_CACHE, 1); - WREG32_SOC15(GC, 0, regCP_MES_IC_OP_CNTL, data); - - /* prime the ICACHE. */ - data = RREG32_SOC15(GC, 0, regCP_MES_IC_OP_CNTL); - data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 1); - WREG32_SOC15(GC, 0, regCP_MES_IC_OP_CNTL, data); + if (prime_icache) { + /* invalidate ICACHE */ + data = RREG32_SOC15(GC, 0, regCP_MES_IC_OP_CNTL); + data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 0); + data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, INVALIDATE_CACHE, 1); + WREG32_SOC15(GC, 0, regCP_MES_IC_OP_CNTL, data); + + /* prime the ICACHE. */ + data = RREG32_SOC15(GC, 0, regCP_MES_IC_OP_CNTL); + data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 1); + WREG32_SOC15(GC, 0, regCP_MES_IC_OP_CNTL, data); + } soc21_grbm_select(adev, 0, 0, 0, 0); mutex_unlock(&adev->srbm_mutex); @@ -1044,17 +1046,19 @@ static int mes_v11_0_kiq_hw_init(struct amdgpu_device *adev) int r = 0; if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { - r = mes_v11_0_load_microcode(adev, AMDGPU_MES_KIQ_PIPE); + + r = mes_v11_0_load_microcode(adev, AMDGPU_MES_SCHED_PIPE, false); if (r) { - DRM_ERROR("failed to load MES kiq fw, r=%d\n", r); + DRM_ERROR("failed to load MES fw, r=%d\n", r); return r; } - r = mes_v11_0_load_microcode(adev, AMDGPU_MES_SCHED_PIPE); + r = mes_v11_0_load_microcode(adev, AMDGPU_MES_KIQ_PIPE, true); if (r) { - DRM_ERROR("failed to load MES fw, r=%d\n", r); + DRM_ERROR("failed to load MES kiq fw, r=%d\n", r); return r; } + } mes_v11_0_enable(adev, true); @@ -1086,7 +1090,7 @@ static int mes_v11_0_hw_init(void *handle) if (!adev->enable_mes_kiq) { if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { r = mes_v11_0_load_microcode(adev, - AMDGPU_MES_SCHED_PIPE); + AMDGPU_MES_SCHED_PIPE, true); if (r) { DRM_ERROR("failed to MES fw, r=%d\n", r); return r; -- cgit From 6bfb56e93bcef41859c2d5ab234ffd80b691be35 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 8 Jun 2022 13:18:39 -0700 Subject: cert host tools: Stop complaining about deprecated OpenSSL functions OpenSSL 3.0 deprecated the OpenSSL's ENGINE API. That is as may be, but the kernel build host tools still use it. Disable the warning about deprecated declarations until somebody who cares fixes it. Signed-off-by: Linus Torvalds --- certs/extract-cert.c | 7 +++++++ scripts/sign-file.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/certs/extract-cert.c b/certs/extract-cert.c index f7ef7862f207..8c1fb9a70d66 100644 --- a/certs/extract-cert.c +++ b/certs/extract-cert.c @@ -23,6 +23,13 @@ #include #include +/* + * OpenSSL 3.0 deprecates the OpenSSL's ENGINE API. + * + * Remove this if/when that API is no longer used + */ +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #define PKEY_ID_PKCS7 2 static __attribute__((noreturn)) diff --git a/scripts/sign-file.c b/scripts/sign-file.c index fbd34b8e8f57..7434e9ea926e 100644 --- a/scripts/sign-file.c +++ b/scripts/sign-file.c @@ -29,6 +29,13 @@ #include #include +/* + * OpenSSL 3.0 deprecates the OpenSSL's ENGINE API. + * + * Remove this if/when that API is no longer used + */ +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + /* * Use CMS if we have openssl-1.0.0 or newer available - otherwise we have to * assume that it's not available and its header file is missing and that we -- cgit From 72aad489f992871e908ff6d9055b26c6366fb864 Mon Sep 17 00:00:00 2001 From: Sergey Shtylyov Date: Wed, 8 Jun 2022 22:51:07 +0300 Subject: ata: libata-transport: fix {dma|pio|xfer}_mode sysfs files The {dma|pio}_mode sysfs files are incorrectly documented as having a list of the supported DMA/PIO transfer modes, while the corresponding fields of the *struct* ata_device hold the transfer mode IDs, not masks. To match these docs, the {dma|pio}_mode (and even xfer_mode!) sysfs files are handled by the ata_bitfield_name_match() macro which leads to reading such kind of nonsense from them: $ cat /sys/class/ata_device/dev3.0/pio_mode XFER_UDMA_7, XFER_UDMA_6, XFER_UDMA_5, XFER_UDMA_4, XFER_MW_DMA_4, XFER_PIO_6, XFER_PIO_5, XFER_PIO_4, XFER_PIO_3, XFER_PIO_2, XFER_PIO_1, XFER_PIO_0 Using the correct ata_bitfield_name_search() macro fixes that: $ cat /sys/class/ata_device/dev3.0/pio_mode XFER_PIO_4 While fixing the file documentation, somewhat reword the {dma|pio}_mode file doc and add a note about being mostly useful for PATA devices to the xfer_mode file doc... Fixes: d9027470b886 ("[libata] Add ATA transport class") Signed-off-by: Sergey Shtylyov Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal --- Documentation/ABI/testing/sysfs-ata | 11 ++++++----- drivers/ata/libata-transport.c | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-ata b/Documentation/ABI/testing/sysfs-ata index 2f726c914752..3daecac48964 100644 --- a/Documentation/ABI/testing/sysfs-ata +++ b/Documentation/ABI/testing/sysfs-ata @@ -107,13 +107,14 @@ Description: described in ATA8 7.16 and 7.17. Only valid if the device is not a PM. - pio_mode: (RO) Transfer modes supported by the device when - in PIO mode. Mostly used by PATA device. + pio_mode: (RO) PIO transfer mode used by the device. + Mostly used by PATA devices. - xfer_mode: (RO) Current transfer mode + xfer_mode: (RO) Current transfer mode. Mostly used by + PATA devices. - dma_mode: (RO) Transfer modes supported by the device when - in DMA mode. Mostly used by PATA device. + dma_mode: (RO) DMA transfer mode used by the device. + Mostly used by PATA devices. class: (RO) Device class. Can be "ata" for disk, "atapi" for packet device, "pmp" for PM, or diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index ca129854a88c..c38027887499 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -196,7 +196,7 @@ static struct { { XFER_PIO_0, "XFER_PIO_0" }, { XFER_PIO_SLOW, "XFER_PIO_SLOW" } }; -ata_bitfield_name_match(xfer,ata_xfer_names) +ata_bitfield_name_search(xfer, ata_xfer_names) /* * ATA Port attributes -- cgit From 481f7017c37a8c722a0b09985db1a35f15749d5d Mon Sep 17 00:00:00 2001 From: Sergey Shtylyov Date: Wed, 8 Jun 2022 23:37:09 +0300 Subject: MAINTAINERS: add ATA sysfs file documentation to libata entry Add the (still missing!) ATA sysfs file documentation to the libata subsystem entry in the MAINTAINERS file. Signed-off-by: Sergey Shtylyov Signed-off-by: Damien Le Moal --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index a6d3bd9d2a8d..7b14ba508b68 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11257,6 +11257,7 @@ M: Damien Le Moal L: linux-ide@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/libata.git +F: Documentation/ABI/testing/sysfs-ata F: Documentation/devicetree/bindings/ata/ F: drivers/ata/ F: include/linux/ata.h -- cgit From 8d21e9963bec1aad2280cdd034c8993033ef2948 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Mon, 6 Jun 2022 09:21:07 -0400 Subject: ip_gre: test csum_start instead of transport header GRE with TUNNEL_CSUM will apply local checksum offload on CHECKSUM_PARTIAL packets. ipgre_xmit must validate csum_start after an optional skb_pull, else lco_csum may trigger an overflow. The original check was if (csum && skb_checksum_start(skb) < skb->data) return -EINVAL; This had false positives when skb_checksum_start is undefined: when ip_summed is not CHECKSUM_PARTIAL. A discussed refinement was straightforward if (csum && skb->ip_summed == CHECKSUM_PARTIAL && skb_checksum_start(skb) < skb->data) return -EINVAL; But was eventually revised more thoroughly: - restrict the check to the only branch where needed, in an uncommon GRE path that uses header_ops and calls skb_pull. - test skb_transport_header, which is set along with csum_start in skb_partial_csum_set in the normal header_ops datapath. Turns out skbs can arrive in this branch without the transport header set, e.g., through BPF redirection. Revise the check back to check csum_start directly, and only if CHECKSUM_PARTIAL. Do leave the check in the updated location. Check field regardless of whether TUNNEL_CSUM is configured. Link: https://lore.kernel.org/netdev/YS+h%2FtqCJJiQei+W@shredder/ Link: https://lore.kernel.org/all/20210902193447.94039-2-willemdebruijn.kernel@gmail.com/T/#u Fixes: 8a0ed250f911 ("ip_gre: validate csum_start only on pull") Reported-by: syzbot Signed-off-by: Willem de Bruijn Reviewed-by: Eric Dumazet Reviewed-by: Alexander Duyck Link: https://lore.kernel.org/r/20220606132107.3582565-1-willemdebruijn.kernel@gmail.com Signed-off-by: Jakub Kicinski --- net/ipv4/ip_gre.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 7e474a85deaf..3b9cd487075a 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -629,21 +629,20 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, } if (dev->header_ops) { - const int pull_len = tunnel->hlen + sizeof(struct iphdr); - if (skb_cow_head(skb, 0)) goto free_skb; tnl_params = (const struct iphdr *)skb->data; - if (pull_len > skb_transport_offset(skb)) - goto free_skb; - /* Pull skb since ip_tunnel_xmit() needs skb->data pointing * to gre header. */ - skb_pull(skb, pull_len); + skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); skb_reset_mac_header(skb); + + if (skb->ip_summed == CHECKSUM_PARTIAL && + skb_checksum_start(skb) < skb->data) + goto free_skb; } else { if (skb_cow_head(skb, dev->needed_headroom)) goto free_skb; -- cgit From 2f2c0d2919a14002760f89f4e02960c735a316d2 Mon Sep 17 00:00:00 2001 From: Chen Lin Date: Wed, 8 Jun 2022 20:46:53 +0800 Subject: net: ethernet: mtk_eth_soc: fix misuse of mem alloc interface netdev[napi]_alloc_frag When rx_flag == MTK_RX_FLAGS_HWLRO, rx_data_len = MTK_MAX_LRO_RX_LENGTH(4096 * 3) > PAGE_SIZE. netdev_alloc_frag is for alloction of page fragment only. Reference to other drivers and Documentation/vm/page_frags.rst Branch to use __get_free_pages when ring->frag_size > PAGE_SIZE. Signed-off-by: Chen Lin Link: https://lore.kernel.org/r/1654692413-2598-1-git-send-email-chen45464546@163.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index b3b3c079a0fa..59c9a10f83ba 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -899,6 +899,17 @@ static bool mtk_rx_get_desc(struct mtk_eth *eth, struct mtk_rx_dma_v2 *rxd, return true; } +static void *mtk_max_lro_buf_alloc(gfp_t gfp_mask) +{ + unsigned int size = mtk_max_frag_size(MTK_MAX_LRO_RX_LENGTH); + unsigned long data; + + data = __get_free_pages(gfp_mask | __GFP_COMP | __GFP_NOWARN, + get_order(size)); + + return (void *)data; +} + /* the qdma core needs scratch memory to be setup */ static int mtk_init_fq_dma(struct mtk_eth *eth) { @@ -1467,7 +1478,10 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, goto release_desc; /* alloc new buffer */ - new_data = napi_alloc_frag(ring->frag_size); + if (ring->frag_size <= PAGE_SIZE) + new_data = napi_alloc_frag(ring->frag_size); + else + new_data = mtk_max_lro_buf_alloc(GFP_ATOMIC); if (unlikely(!new_data)) { netdev->stats.rx_dropped++; goto release_desc; @@ -1914,7 +1928,10 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) return -ENOMEM; for (i = 0; i < rx_dma_size; i++) { - ring->data[i] = netdev_alloc_frag(ring->frag_size); + if (ring->frag_size <= PAGE_SIZE) + ring->data[i] = netdev_alloc_frag(ring->frag_size); + else + ring->data[i] = mtk_max_lro_buf_alloc(GFP_KERNEL); if (!ring->data[i]) return -ENOMEM; } -- cgit From 2061ecfdf2350994e5b61c43e50e98a7a70e95ee Mon Sep 17 00:00:00 2001 From: Ilya Maximets Date: Tue, 7 Jun 2022 00:11:40 +0200 Subject: net: openvswitch: fix misuse of the cached connection on tuple changes If packet headers changed, the cached nfct is no longer relevant for the packet and attempt to re-use it leads to the incorrect packet classification. This issue is causing broken connectivity in OpenStack deployments with OVS/OVN due to hairpin traffic being unexpectedly dropped. The setup has datapath flows with several conntrack actions and tuple changes between them: actions:ct(commit,zone=8,mark=0/0x1,nat(src)), set(eth(src=00:00:00:00:00:01,dst=00:00:00:00:00:06)), set(ipv4(src=172.18.2.10,dst=192.168.100.6,ttl=62)), ct(zone=8),recirc(0x4) After the first ct() action the packet headers are almost fully re-written. The next ct() tries to re-use the existing nfct entry and marks the packet as invalid, so it gets dropped later in the pipeline. Clearing the cached conntrack entry whenever packet tuple is changed to avoid the issue. The flow key should not be cleared though, because we should still be able to match on the ct_state if the recirculation happens after the tuple change but before the next ct() action. Cc: stable@vger.kernel.org Fixes: 7f8a436eaa2c ("openvswitch: Add conntrack action") Reported-by: Frode Nordahl Link: https://mail.openvswitch.org/pipermail/ovs-discuss/2022-May/051829.html Link: https://bugs.launchpad.net/ubuntu/+source/ovn/+bug/1967856 Signed-off-by: Ilya Maximets Link: https://lore.kernel.org/r/20220606221140.488984-1-i.maximets@ovn.org Signed-off-by: Jakub Kicinski --- net/openvswitch/actions.c | 6 ++++++ net/openvswitch/conntrack.c | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 1b5d73079dc9..868db4669a29 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c @@ -373,6 +373,7 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh, update_ip_l4_checksum(skb, nh, *addr, new_addr); csum_replace4(&nh->check, *addr, new_addr); skb_clear_hash(skb); + ovs_ct_clear(skb, NULL); *addr = new_addr; } @@ -420,6 +421,7 @@ static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto, update_ipv6_checksum(skb, l4_proto, addr, new_addr); skb_clear_hash(skb); + ovs_ct_clear(skb, NULL); memcpy(addr, new_addr, sizeof(__be32[4])); } @@ -660,6 +662,7 @@ static int set_nsh(struct sk_buff *skb, struct sw_flow_key *flow_key, static void set_tp_port(struct sk_buff *skb, __be16 *port, __be16 new_port, __sum16 *check) { + ovs_ct_clear(skb, NULL); inet_proto_csum_replace2(check, skb, *port, new_port, false); *port = new_port; } @@ -699,6 +702,7 @@ static int set_udp(struct sk_buff *skb, struct sw_flow_key *flow_key, uh->dest = dst; flow_key->tp.src = src; flow_key->tp.dst = dst; + ovs_ct_clear(skb, NULL); } skb_clear_hash(skb); @@ -761,6 +765,8 @@ static int set_sctp(struct sk_buff *skb, struct sw_flow_key *flow_key, sh->checksum = old_csum ^ old_correct_csum ^ new_csum; skb_clear_hash(skb); + ovs_ct_clear(skb, NULL); + flow_key->tp.src = sh->source; flow_key->tp.dst = sh->dest; diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 4a947c13c813..4e70df91d0f2 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -1342,7 +1342,9 @@ int ovs_ct_clear(struct sk_buff *skb, struct sw_flow_key *key) nf_ct_put(ct); nf_ct_set(skb, NULL, IP_CT_UNTRACKED); - ovs_ct_fill_key(skb, key, false); + + if (key) + ovs_ct_fill_key(skb, key, false); return 0; } -- cgit From 11ec18b1d8d92b9df307d31950dcba0b3dd7283c Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Tue, 7 Jun 2022 08:11:43 +0400 Subject: net: altera: Fix refcount leak in altera_tse_mdio_create Every iteration of for_each_child_of_node() decrements the reference count of the previous node. When break from a for_each_child_of_node() loop, we need to explicitly call of_node_put() on the child node when not need anymore. Add missing of_node_put() to avoid refcount leak. Fixes: bbd2190ce96d ("Altera TSE: Add main and header file for Altera Ethernet Driver") Signed-off-by: Miaoqian Lin Link: https://lore.kernel.org/r/20220607041144.7553-1-linmq006@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/altera/altera_tse_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index a3816264c35c..8c5828582c21 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -163,7 +163,8 @@ static int altera_tse_mdio_create(struct net_device *dev, unsigned int id) mdio = mdiobus_alloc(); if (mdio == NULL) { netdev_err(dev, "Error allocating MDIO bus\n"); - return -ENOMEM; + ret = -ENOMEM; + goto put_node; } mdio->name = ALTERA_TSE_RESOURCE_NAME; @@ -180,6 +181,7 @@ static int altera_tse_mdio_create(struct net_device *dev, unsigned int id) mdio->id); goto out_free_mdio; } + of_node_put(mdio_node); if (netif_msg_drv(priv)) netdev_info(dev, "MDIO bus %s: created\n", mdio->id); @@ -189,6 +191,8 @@ static int altera_tse_mdio_create(struct net_device *dev, unsigned int id) out_free_mdio: mdiobus_free(mdio); mdio = NULL; +put_node: + of_node_put(mdio_node); return ret; } -- cgit From 47e96930d6e6106d5252e85b868d3c7e29296de0 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 7 Jun 2022 12:28:42 +0100 Subject: net: dsa: mv88e6xxx: use BMSR_ANEGCOMPLETE bit for filling an_complete MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit ede359d8843a ("net: dsa: mv88e6xxx: Link in pcs_get_state() if AN is bypassed") added the ability to link if AN was bypassed, and added filling of state->an_complete field, but set it to true if AN was enabled in BMCR, not when AN was reported complete in BMSR. This was done because for some reason, when I wanted to use BMSR value to infer an_complete, I was looking at BMSR_ANEGCAPABLE bit (which was always 1), instead of BMSR_ANEGCOMPLETE bit. Use BMSR_ANEGCOMPLETE for filling state->an_complete. Fixes: ede359d8843a ("net: dsa: mv88e6xxx: Link in pcs_get_state() if AN is bypassed") Signed-off-by: Marek Behún Signed-off-by: Russell King (Oracle) Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mv88e6xxx/serdes.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 7b37d45bc9fb..1a19c5284f2c 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -50,22 +50,17 @@ static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip, } static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, - u16 ctrl, u16 status, u16 lpa, + u16 bmsr, u16 lpa, u16 status, struct phylink_link_state *state) { state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK); + state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE); if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) { /* The Spped and Duplex Resolved register is 1 if AN is enabled * and complete, or if AN is disabled. So with disabled AN we - * still get here on link up. But we want to set an_complete - * only if AN was enabled, thus we look at BMCR_ANENABLE. - * (According to 802.3-2008 section 22.2.4.2.10, we should be - * able to get this same value from BMSR_ANEGCAPABLE, but tests - * show that these Marvell PHYs don't conform to this part of - * the specificaion - BMSR_ANEGCAPABLE is simply always 1.) + * still get here on link up. */ - state->an_complete = !!(ctrl & BMCR_ANENABLE); state->duplex = status & MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ? DUPLEX_FULL : DUPLEX_HALF; @@ -191,12 +186,12 @@ int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, int lane, struct phylink_link_state *state) { - u16 lpa, status, ctrl; + u16 bmsr, lpa, status; int err; - err = mv88e6352_serdes_read(chip, MII_BMCR, &ctrl); + err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr); if (err) { - dev_err(chip->dev, "can't read Serdes PHY control: %d\n", err); + dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err); return err; } @@ -212,7 +207,7 @@ int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, return err; } - return mv88e6xxx_serdes_pcs_get_state(chip, ctrl, status, lpa, state); + return mv88e6xxx_serdes_pcs_get_state(chip, bmsr, lpa, status, state); } int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, @@ -918,13 +913,13 @@ int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, int port, int lane, struct phylink_link_state *state) { - u16 lpa, status, ctrl; + u16 bmsr, lpa, status; int err; err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_BMCR, &ctrl); + MV88E6390_SGMII_BMSR, &bmsr); if (err) { - dev_err(chip->dev, "can't read Serdes PHY control: %d\n", err); + dev_err(chip->dev, "can't read Serdes PHY BMSR: %d\n", err); return err; } @@ -942,7 +937,7 @@ static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, return err; } - return mv88e6xxx_serdes_pcs_get_state(chip, ctrl, status, lpa, state); + return mv88e6xxx_serdes_pcs_get_state(chip, bmsr, lpa, status, state); } static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, -- cgit From 2b4bb9cd9bcdbe1f791fec18a7c8728cb6989bf8 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Tue, 7 Jun 2022 12:28:47 +0100 Subject: net: dsa: mv88e6xxx: fix BMSR error to be consistent with others Other errors accessing the registers in mv88e6352_serdes_pcs_get_state() print "PHY " before the register name, except for the BMSR. Make this consistent with the other error messages. Signed-off-by: Russell King (Oracle) Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mv88e6xxx/serdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 1a19c5284f2c..47bf87d530b0 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -191,7 +191,7 @@ int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr); if (err) { - dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err); + dev_err(chip->dev, "can't read Serdes PHY BMSR: %d\n", err); return err; } -- cgit From b4d78731b34bd6bfd1bfedce26a55e3582b0bc14 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Tue, 7 Jun 2022 12:28:52 +0100 Subject: net: dsa: mv88e6xxx: correctly report serdes link failure Phylink wants to know if the link has dropped since the last time state was retrieved, and the BMSR gives us that. Read the BMSR and use it when deciding the link state. Fill in the an_complete member as well for the emulated PHY state. Signed-off-by: Russell King (Oracle) Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mv88e6xxx/serdes.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 47bf87d530b0..d94150d8f3f4 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -53,6 +53,14 @@ static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, u16 bmsr, u16 lpa, u16 status, struct phylink_link_state *state) { + state->link = false; + + /* If the BMSR reports that the link had failed, report this to + * phylink. + */ + if (!(bmsr & BMSR_LSTATUS)) + return 0; + state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK); state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE); -- cgit From 487994ff75880569d32504d7e70da8b3328e0693 Mon Sep 17 00:00:00 2001 From: Alvin Šipraga Date: Tue, 7 Jun 2022 20:46:24 +0200 Subject: net: dsa: realtek: rtl8365mb: fix GMII caps for ports with internal PHY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit a18e6521a7d9 ("net: phylink: handle NA interface mode in phylink_fwnode_phy_connect()"), phylib defaults to GMII when no phy-mode or phy-connection-type property is specified in a DSA port node of the device tree. The same commit caused a regression in rtl8365mb whereby phylink would fail to connect, because the driver did not advertise support for GMII for ports with internal PHY. It should be noted that the aforementioned regression is not because the blamed commit was incorrect: on the contrary, the blamed commit is correcting the previous behaviour whereby unspecified phy-mode would cause the internal interface mode to be PHY_INTERFACE_MODE_NA. The rtl8365mb driver only worked by accident before because it _did_ advertise support for PHY_INTERFACE_MODE_NA, despite NA being reserved for internal use by phylink. With one mistake fixed, the other was exposed. Commit a5dba0f207e5 ("net: dsa: rtl8365mb: add GMII as user port mode") then introduced implicit support for GMII mode on ports with internal PHY to allow a PHY connection for device trees where the phy-mode is not explicitly set to "internal". At this point everything was working OK again. Subsequently, commit 6ff6064605e9 ("net: dsa: realtek: convert to phylink_generic_validate()") broke this behaviour again by discarding the usage of rtl8365mb_phy_mode_supported() - where this GMII support was indicated - while switching to the new .phylink_get_caps API. With the new API, rtl8365mb_phy_mode_supported() is no longer needed. Remove it altogether and add back the GMII capability - this time to rtl8365mb_phylink_get_caps() - so that the above default behaviour works for ports with internal PHY again. Fixes: 6ff6064605e9 ("net: dsa: realtek: convert to phylink_generic_validate()") Signed-off-by: Alvin Šipraga Reviewed-by: Russell King (Oracle) Link: https://lore.kernel.org/r/20220607184624.417641-1-alvin@pqrs.dk Signed-off-by: Jakub Kicinski --- drivers/net/dsa/realtek/rtl8365mb.c | 38 +++++++++---------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c index 3bb42a9f236d..769f672e9128 100644 --- a/drivers/net/dsa/realtek/rtl8365mb.c +++ b/drivers/net/dsa/realtek/rtl8365mb.c @@ -955,35 +955,21 @@ static int rtl8365mb_ext_config_forcemode(struct realtek_priv *priv, int port, return 0; } -static bool rtl8365mb_phy_mode_supported(struct dsa_switch *ds, int port, - phy_interface_t interface) -{ - int ext_int; - - ext_int = rtl8365mb_extint_port_map[port]; - - if (ext_int < 0 && - (interface == PHY_INTERFACE_MODE_NA || - interface == PHY_INTERFACE_MODE_INTERNAL || - interface == PHY_INTERFACE_MODE_GMII)) - /* Internal PHY */ - return true; - else if ((ext_int >= 1) && - phy_interface_mode_is_rgmii(interface)) - /* Extension MAC */ - return true; - - return false; -} - static void rtl8365mb_phylink_get_caps(struct dsa_switch *ds, int port, struct phylink_config *config) { - if (dsa_is_user_port(ds, port)) + if (dsa_is_user_port(ds, port)) { __set_bit(PHY_INTERFACE_MODE_INTERNAL, config->supported_interfaces); - else if (dsa_is_cpu_port(ds, port)) + + /* GMII is the default interface mode for phylib, so + * we have to support it for ports with integrated PHY. + */ + __set_bit(PHY_INTERFACE_MODE_GMII, + config->supported_interfaces); + } else if (dsa_is_cpu_port(ds, port)) { phy_interface_set_rgmii(config->supported_interfaces); + } config->mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD; @@ -996,12 +982,6 @@ static void rtl8365mb_phylink_mac_config(struct dsa_switch *ds, int port, struct realtek_priv *priv = ds->priv; int ret; - if (!rtl8365mb_phy_mode_supported(ds, port, state->interface)) { - dev_err(priv->dev, "phy mode %s is unsupported on port %d\n", - phy_modes(state->interface), port); - return; - } - if (mode != MLO_AN_PHY && mode != MLO_AN_FIXED) { dev_err(priv->dev, "port %d supports only conventional PHY or fixed-link\n", -- cgit From e67b72b90b7e19a4be4d9c29f3feea6f58ab43f8 Mon Sep 17 00:00:00 2001 From: Muchun Song Date: Tue, 7 Jun 2022 15:02:14 +0800 Subject: tcp: use alloc_large_system_hash() to allocate table_perturb In our server, there may be no high order (>= 6) memory since we reserve lots of HugeTLB pages when booting. Then the system panic. So use alloc_large_system_hash() to allocate table_perturb. Fixes: e9261476184b ("tcp: dynamically allocate the perturb table used by source ports") Signed-off-by: Muchun Song Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/20220607070214.94443-1-songmuchun@bytedance.com Signed-off-by: Jakub Kicinski --- net/ipv4/inet_hashtables.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index e8de5e699b3f..545f91b6cb5e 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -1026,10 +1026,12 @@ void __init inet_hashinfo2_init(struct inet_hashinfo *h, const char *name, init_hashinfo_lhash2(h); /* this one is used for source ports of outgoing connections */ - table_perturb = kmalloc_array(INET_TABLE_PERTURB_SIZE, - sizeof(*table_perturb), GFP_KERNEL); - if (!table_perturb) - panic("TCP: failed to alloc table_perturb"); + table_perturb = alloc_large_system_hash("Table-perturb", + sizeof(*table_perturb), + INET_TABLE_PERTURB_SIZE, + 0, 0, NULL, NULL, + INET_TABLE_PERTURB_SIZE, + INET_TABLE_PERTURB_SIZE); } int inet_hashinfo2_init_mod(struct inet_hashinfo *h) -- cgit From 647df0d41b6bd8f4987dde6e8d8d0aba5b082985 Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Tue, 7 Jun 2022 12:11:19 -0700 Subject: net: amd-xgbe: fix clang -Wformat warning see warning: | drivers/net/ethernet/amd/xgbe/xgbe-drv.c:2787:43: warning: format specifies | type 'unsigned short' but the argument has type 'int' [-Wformat] | netdev_dbg(netdev, "Protocol: %#06hx\n", ntohs(eth->h_proto)); | ~~~~~~ ^~~~~~~~~~~~~~~~~~~ Variadic functions (printf-like) undergo default argument promotion. Documentation/core-api/printk-formats.rst specifically recommends using the promoted-to-type's format flag. Also, as per C11 6.3.1.1: (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf) `If an int can represent all values of the original type ..., the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.` Since the argument is a u16 it will get promoted to an int and thus it is most accurate to use the %x format specifier here. It should be noted that the `#06` formatting sugar does not alter the promotion rules. Link: https://github.com/ClangBuiltLinux/linux/issues/378 Signed-off-by: Justin Stitt Reviewed-by: Nick Desaulniers Link: https://lore.kernel.org/r/20220607191119.20686-1-jstitt007@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index a3593290886f..4d46780fad13 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -2784,7 +2784,7 @@ void xgbe_print_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx) netdev_dbg(netdev, "Dst MAC addr: %pM\n", eth->h_dest); netdev_dbg(netdev, "Src MAC addr: %pM\n", eth->h_source); - netdev_dbg(netdev, "Protocol: %#06hx\n", ntohs(eth->h_proto)); + netdev_dbg(netdev, "Protocol: %#06x\n", ntohs(eth->h_proto)); for (i = 0; i < skb->len; i += 32) { unsigned int len = min(skb->len - i, 32U); -- cgit From acb0055e187334554398a381a16de72f1a3d47bb Mon Sep 17 00:00:00 2001 From: Bo Liu Date: Wed, 8 Jun 2022 23:11:06 -0400 Subject: virtio: Fix all occurences of the "the the" typo There are double "the" in message in file virtio_mmio.c and virtio_pci_modern_dev.c, fix it. Signed-off-by: Bo Liu Message-Id: <20220609031106.2161-1-liubo03@inspur.com> Signed-off-by: Michael S. Tsirkin --- drivers/virtio/virtio_mmio.c | 2 +- drivers/virtio/virtio_pci_modern_dev.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 5ce79bf9f92b..c9bec3813e94 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -255,7 +255,7 @@ static void vm_set_status(struct virtio_device *vdev, u8 status) /* * Per memory-barriers.txt, wmb() is not needed to guarantee - * that the the cache coherent memory writes have completed + * that the cache coherent memory writes have completed * before writing to the MMIO region. */ writel(status, vm_dev->base + VIRTIO_MMIO_STATUS); diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c index a0fa14f28a7f..b790f30b2b56 100644 --- a/drivers/virtio/virtio_pci_modern_dev.c +++ b/drivers/virtio/virtio_pci_modern_dev.c @@ -469,7 +469,7 @@ void vp_modern_set_status(struct virtio_pci_modern_device *mdev, /* * Per memory-barriers.txt, wmb() is not needed to guarantee - * that the the cache coherent memory writes have completed + * that the cache coherent memory writes have completed * before writing to the MMIO region. */ vp_iowrite8(status, &cfg->device_status); -- cgit From 00d1f546470d89e072dd3cda12b5c794341e7268 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 9 Jun 2022 12:19:01 +0800 Subject: vdpa: make get_vq_group and set_group_asid optional This patch makes get_vq_group and set_group_asid optional. This is needed to unbreak the vDPA parent that doesn't support multiple address spaces. Cc: Gautam Dawar Fixes: aaca8373c4b1 ("vhost-vdpa: support ASID based IOTLB API") Signed-off-by: Jason Wang Message-Id: <20220609041901.2029-1-jasowang@redhat.com> Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vdpa.c | 2 ++ include/linux/vdpa.h | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index 935a1d0ddb97..5ad2596c6e8a 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -499,6 +499,8 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, ops->set_vq_ready(vdpa, idx, s.num); return 0; case VHOST_VDPA_GET_VRING_GROUP: + if (!ops->get_vq_group) + return -EOPNOTSUPP; s.index = idx; s.num = ops->get_vq_group(vdpa, idx); if (s.num >= vdpa->ngroups) diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h index 4700a88a28f6..7b4a13d3bd91 100644 --- a/include/linux/vdpa.h +++ b/include/linux/vdpa.h @@ -178,7 +178,8 @@ struct vdpa_map_file { * for the device * @vdev: vdpa device * Returns virtqueue algin requirement - * @get_vq_group: Get the group id for a specific virtqueue + * @get_vq_group: Get the group id for a specific + * virtqueue (optional) * @vdev: vdpa device * @idx: virtqueue index * Returns u32: group id for this virtqueue @@ -243,7 +244,7 @@ struct vdpa_map_file { * Returns the iova range supported by * the device. * @set_group_asid: Set address space identifier for a - * virtqueue group + * virtqueue group (optional) * @vdev: vdpa device * @group: virtqueue group * @asid: address space id for this group -- cgit From 477277c7fd43d48ae68cbdcaa7c0f82024a87421 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 7 Jun 2022 11:20:04 +0200 Subject: drm/ast: Support multiple outputs Systems with AST graphics can have multiple output; typically VGA plus some other port. Record detected output chips in a bitmask and initialize each output on its own. Assume a VGA output by default and use SIL164 and DP501 if available. For ASTDP assume that it can run in parallel with VGA. Tested on AST2100. v3: * define a macro for each BIT(ast_tx_chip) (Patrik) v2: * make VGA/SIL164/DP501 mutually exclusive Signed-off-by: Thomas Zimmermann Reviewed-by: Patrik Jakobsson Fixes: a59b026419f3 ("drm/ast: Initialize encoder and connector for VGA in helper function") Cc: Thomas Zimmermann Cc: Javier Martinez Canillas Cc: Dave Airlie Cc: dri-devel@lists.freedesktop.org Link: https://patchwork.freedesktop.org/patch/msgid/20220607092008.22123-2-tzimmermann@suse.de (cherry picked from commit 7f35680ada234ce00828b8ea841ba7ca1e00ff52) Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/ast/ast_dp.c | 5 ++--- drivers/gpu/drm/ast/ast_dp501.c | 2 +- drivers/gpu/drm/ast/ast_drv.h | 9 +++++++-- drivers/gpu/drm/ast/ast_main.c | 21 +++++++++------------ drivers/gpu/drm/ast/ast_mode.c | 38 +++++++++++++++++++++----------------- drivers/gpu/drm/ast/ast_post.c | 2 +- 6 files changed, 41 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index 4551bc8a3ecf..f573d582407e 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -160,13 +160,12 @@ void ast_dp_launch(struct drm_device *dev, u8 bPower) } if (bDPExecute) - ast->tx_chip_type = AST_TX_ASTDP; + ast->tx_chip_types |= BIT(AST_TX_ASTDP); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK, ASTDP_HOST_EDID_READ_DONE); - } else - ast->tx_chip_type = AST_TX_NONE; + } } diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c index 204c926a18ea..4f75a9efb610 100644 --- a/drivers/gpu/drm/ast/ast_dp501.c +++ b/drivers/gpu/drm/ast/ast_dp501.c @@ -450,7 +450,7 @@ void ast_init_3rdtx(struct drm_device *dev) ast_init_dvo(dev); break; default: - if (ast->tx_chip_type == AST_TX_SIL164) + if (ast->tx_chip_types & BIT(AST_TX_SIL164)) ast_init_dvo(dev); else ast_init_analog(dev); diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index afebe35f205e..a34db4380f68 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -73,6 +73,11 @@ enum ast_tx_chip { AST_TX_ASTDP, }; +#define AST_TX_NONE_BIT BIT(AST_TX_NONE) +#define AST_TX_SIL164_BIT BIT(AST_TX_SIL164) +#define AST_TX_DP501_BIT BIT(AST_TX_DP501) +#define AST_TX_ASTDP_BIT BIT(AST_TX_ASTDP) + #define AST_DRAM_512Mx16 0 #define AST_DRAM_1Gx16 1 #define AST_DRAM_512Mx32 2 @@ -173,7 +178,7 @@ struct ast_private { struct drm_plane primary_plane; struct ast_cursor_plane cursor_plane; struct drm_crtc crtc; - union { + struct { struct { struct drm_encoder encoder; struct ast_vga_connector vga_connector; @@ -199,7 +204,7 @@ struct ast_private { ast_use_defaults } config_mode; - enum ast_tx_chip tx_chip_type; + unsigned long tx_chip_types; /* bitfield of enum ast_chip_type */ u8 *dp501_fw_addr; const struct firmware *dp501_fw; /* dp501 fw */ }; diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index d770d5a23c1a..067453266897 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -216,7 +216,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) } /* Check 3rd Tx option (digital output afaik) */ - ast->tx_chip_type = AST_TX_NONE; + ast->tx_chip_types |= AST_TX_NONE_BIT; /* * VGACRA3 Enhanced Color Mode Register, check if DVO is already @@ -229,7 +229,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) if (!*need_post) { jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xff); if (jreg & 0x80) - ast->tx_chip_type = AST_TX_SIL164; + ast->tx_chip_types = AST_TX_SIL164_BIT; } if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST2500)) { @@ -241,7 +241,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff); switch (jreg) { case 0x04: - ast->tx_chip_type = AST_TX_SIL164; + ast->tx_chip_types = AST_TX_SIL164_BIT; break; case 0x08: ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, GFP_KERNEL); @@ -254,22 +254,19 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) } fallthrough; case 0x0c: - ast->tx_chip_type = AST_TX_DP501; + ast->tx_chip_types = AST_TX_DP501_BIT; } } else if (ast->chip == AST2600) ast_dp_launch(&ast->base, 0); /* Print stuff for diagnostic purposes */ - switch(ast->tx_chip_type) { - case AST_TX_SIL164: + if (ast->tx_chip_types & AST_TX_NONE_BIT) + drm_info(dev, "Using analog VGA\n"); + if (ast->tx_chip_types & AST_TX_SIL164_BIT) drm_info(dev, "Using Sil164 TMDS transmitter\n"); - break; - case AST_TX_DP501: + if (ast->tx_chip_types & AST_TX_DP501_BIT) drm_info(dev, "Using DP501 DisplayPort transmitter\n"); - break; - default: - drm_info(dev, "Analog VGA only\n"); - } + return 0; } diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 323af2746aa9..db2010a55674 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -997,10 +997,10 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_ON: ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, 0); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0); - if (ast->tx_chip_type == AST_TX_DP501) + if (ast->tx_chip_types & AST_TX_DP501_BIT) ast_set_dp501_video_output(crtc->dev, 1); - if (ast->tx_chip_type == AST_TX_ASTDP) { + if (ast->tx_chip_types & AST_TX_ASTDP_BIT) { ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON); ast_wait_for_vretrace(ast); ast_dp_set_on_off(crtc->dev, 1); @@ -1012,17 +1012,17 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: ch = mode; - if (ast->tx_chip_type == AST_TX_DP501) + if (ast->tx_chip_types & AST_TX_DP501_BIT) ast_set_dp501_video_output(crtc->dev, 0); - break; - if (ast->tx_chip_type == AST_TX_ASTDP) { + if (ast->tx_chip_types & AST_TX_ASTDP_BIT) { ast_dp_set_on_off(crtc->dev, 0); ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF); } ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, 0x20); ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch); + break; } } @@ -1155,7 +1155,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, ast_crtc_load_lut(ast, crtc); //Set Aspeed Display-Port - if (ast->tx_chip_type == AST_TX_ASTDP) + if (ast->tx_chip_types & AST_TX_ASTDP_BIT) ast_dp_set_mode(crtc, vbios_mode_info); mutex_unlock(&ast->ioregs_lock); @@ -1739,22 +1739,26 @@ int ast_mode_config_init(struct ast_private *ast) ast_crtc_init(dev); - switch (ast->tx_chip_type) { - case AST_TX_NONE: + if (ast->tx_chip_types & AST_TX_NONE_BIT) { ret = ast_vga_output_init(ast); - break; - case AST_TX_SIL164: + if (ret) + return ret; + } + if (ast->tx_chip_types & AST_TX_SIL164_BIT) { ret = ast_sil164_output_init(ast); - break; - case AST_TX_DP501: + if (ret) + return ret; + } + if (ast->tx_chip_types & AST_TX_DP501_BIT) { ret = ast_dp501_output_init(ast); - break; - case AST_TX_ASTDP: + if (ret) + return ret; + } + if (ast->tx_chip_types & AST_TX_ASTDP_BIT) { ret = ast_astdp_output_init(ast); - break; + if (ret) + return ret; } - if (ret) - return ret; drm_mode_config_reset(dev); diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index 0aa9cf0fb5c3..82fd3c8adee1 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c @@ -391,7 +391,7 @@ void ast_post_gpu(struct drm_device *dev) ast_init_3rdtx(dev); } else { - if (ast->tx_chip_type != AST_TX_NONE) + if (ast->tx_chip_types & AST_TX_SIL164_BIT) ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */ } } -- cgit From 537b4a0c8b9490d762e70c0ecec38144c83d0c37 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 9 Jun 2022 11:59:47 +0300 Subject: ASoC: SOF: Intel: hda-dsp: Expose hda_dsp_core_power_up() The hda_dsp_core_power_up() needs to be exposed so that it can be used in hda-loader.c to correct the boot flow. The first step must not unstall the core, it should only power up the core(s). Add sanity check for the core_mask while exposing it to be safe. Complements: 2a68ff846164 ("ASoC: SOF: Intel: hda: Revisit IMR boot sequence") Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20220609085949.29062-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 10 +++++++++- sound/soc/sof/intel/hda.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 000ea906670c..e24eea725acb 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -181,12 +181,20 @@ int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask) * Power Management. */ -static int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask) +int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; + const struct sof_intel_dsp_desc *chip = hda->desc; unsigned int cpa; u32 adspcs; int ret; + /* restrict core_mask to host managed cores mask */ + core_mask &= chip->host_managed_cores_mask; + /* return if core_mask is not valid */ + if (!core_mask) + return 0; + /* update bits */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS, HDA_DSP_ADSPCS_SPA_MASK(core_mask), diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 3e0f7b0c586a..0f57ef5d9b8e 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -497,6 +497,7 @@ struct sof_intel_hda_stream { */ int hda_dsp_probe(struct snd_sof_dev *sdev); int hda_dsp_remove(struct snd_sof_dev *sdev); +int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev, -- cgit From fcb3c775f7073410965ce9414ddb2a1f339c502b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 9 Jun 2022 11:59:48 +0300 Subject: ASoC: SOF: Intel: hda-loader: Make sure that the fw load sequence is followed The hda_dsp_enable_core() is powering up _and_ unstall the core in one call while the first step of the firmware loading must not unstall the core. The core can be unstalled only after the set cpb_cfp and the configuration of the IPC register for the ROM_CONTROL message. Complements: 2a68ff846164 ("ASoC: SOF: Intel: hda: Revisit IMR boot sequence") Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20220609085949.29062-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 64290125d7cd..103e62bcfa82 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -110,7 +110,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) int ret; /* step 1: power up corex */ - ret = hda_dsp_enable_core(sdev, chip->host_managed_cores_mask); + ret = hda_dsp_core_power_up(sdev, chip->host_managed_cores_mask); if (ret < 0) { if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n"); -- cgit From 4643e10a17e549467420aaeeb35c9b3480716618 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 9 Jun 2022 11:59:49 +0300 Subject: ASoC: SOF: Intel: hda-loader: Clarify the cl_dsp_init() flow Update the comment for the cl_dsp_init() to clarify what is done by the function and use the chip->init_core_mask instead of BIT(0) when unstalling/running the init core. Complements: 2a68ff846164 ("ASoC: SOF: Intel: hda: Revisit IMR boot sequence") Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20220609085949.29062-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 103e62bcfa82..d3ec5996a9a3 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -95,9 +95,9 @@ out_put: } /* - * first boot sequence has some extra steps. core 0 waits for power - * status on core 1, so power up core 1 also momentarily, keep it in - * reset/stall and then turn it off + * first boot sequence has some extra steps. + * power on all host managed cores and only unstall/run the boot core to boot the + * DSP then turn off all non boot cores (if any) is powered on. */ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) { @@ -127,7 +127,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr); /* step 3: unset core 0 reset state & unstall/run core 0 */ - ret = hda_dsp_core_run(sdev, BIT(0)); + ret = hda_dsp_core_run(sdev, chip->init_core_mask); if (ret < 0) { if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) dev_err(sdev->dev, -- cgit From 142d456204cf4dabe18be59e043d806440f609d4 Mon Sep 17 00:00:00 2001 From: Minghao Chi Date: Mon, 6 Jun 2022 03:37:05 +0000 Subject: ASoC: imx-audmux: remove unnecessary check of clk_disable_unprepare/clk_prepare_enable Because clk_disable_unprepare/clk_prepare_enable already checked NULL clock parameter, so the additional checks are unnecessary, just remove them. Reported-by: Zeal Robot Signed-off-by: Minghao Chi Acked-by: Shengjiu Wang Link: https://lore.kernel.org/r/20220606033705.291048-1-chi.minghao@zte.com.cn Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audmux.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index a8e5e0f57faf..50b71e5d4589 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c @@ -62,17 +62,14 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, uintptr_t port = (uintptr_t)file->private_data; u32 pdcr, ptcr; - if (audmux_clk) { - ret = clk_prepare_enable(audmux_clk); - if (ret) - return ret; - } + ret = clk_prepare_enable(audmux_clk); + if (ret) + return ret; ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port)); pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port)); - if (audmux_clk) - clk_disable_unprepare(audmux_clk); + clk_disable_unprepare(audmux_clk); buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!buf) @@ -209,17 +206,14 @@ int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr, if (!audmux_base) return -ENOSYS; - if (audmux_clk) { - ret = clk_prepare_enable(audmux_clk); - if (ret) - return ret; - } + ret = clk_prepare_enable(audmux_clk); + if (ret) + return ret; writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port)); writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port)); - if (audmux_clk) - clk_disable_unprepare(audmux_clk); + clk_disable_unprepare(audmux_clk); return 0; } -- cgit From 8e1278444446fc97778a5e5c99bca1ce0bbc5ec9 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 7 Jun 2022 00:34:56 +1000 Subject: powerpc/32: Fix overread/overwrite of thread_struct via ptrace The ptrace PEEKUSR/POKEUSR (aka PEEKUSER/POKEUSER) API allows a process to read/write registers of another process. To get/set a register, the API takes an index into an imaginary address space called the "USER area", where the registers of the process are laid out in some fashion. The kernel then maps that index to a particular register in its own data structures and gets/sets the value. The API only allows a single machine-word to be read/written at a time. So 4 bytes on 32-bit kernels and 8 bytes on 64-bit kernels. The way floating point registers (FPRs) are addressed is somewhat complicated, because double precision float values are 64-bit even on 32-bit CPUs. That means on 32-bit kernels each FPR occupies two word-sized locations in the USER area. On 64-bit kernels each FPR occupies one word-sized location in the USER area. Internally the kernel stores the FPRs in an array of u64s, or if VSX is enabled, an array of pairs of u64s where one half of each pair stores the FPR. Which half of the pair stores the FPR depends on the kernel's endianness. To handle the different layouts of the FPRs depending on VSX/no-VSX and big/little endian, the TS_FPR() macro was introduced. Unfortunately the TS_FPR() macro does not take into account the fact that the addressing of each FPR differs between 32-bit and 64-bit kernels. It just takes the index into the "USER area" passed from userspace and indexes into the fp_state.fpr array. On 32-bit there are 64 indexes that address FPRs, but only 32 entries in the fp_state.fpr array, meaning the user can read/write 256 bytes past the end of the array. Because the fp_state sits in the middle of the thread_struct there are various fields than can be overwritten, including some pointers. As such it may be exploitable. It has also been observed to cause systems to hang or otherwise misbehave when using gdbserver, and is probably the root cause of this report which could not be easily reproduced: https://lore.kernel.org/linuxppc-dev/dc38afe9-6b78-f3f5-666b-986939e40fc6@keymile.com/ Rather than trying to make the TS_FPR() macro even more complicated to fix the bug, or add more macros, instead add a special-case for 32-bit kernels. This is more obvious and hopefully avoids a similar bug happening again in future. Note that because 32-bit kernels never have VSX enabled the code doesn't need to consider TS_FPRWIDTH/OFFSET at all. Add a BUILD_BUG_ON() to ensure that 32-bit && VSX is never enabled. Fixes: 87fec0514f61 ("powerpc: PTRACE_PEEKUSR/PTRACE_POKEUSER of FPR registers in little endian builds") Cc: stable@vger.kernel.org # v3.13+ Reported-by: Ariel Miculas Tested-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20220609133245.573565-1-mpe@ellerman.id.au --- arch/powerpc/kernel/ptrace/ptrace-fpu.c | 20 ++++++++++++++------ arch/powerpc/kernel/ptrace/ptrace.c | 3 +++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/ptrace/ptrace-fpu.c b/arch/powerpc/kernel/ptrace/ptrace-fpu.c index 5dca19361316..09c49632bfe5 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-fpu.c +++ b/arch/powerpc/kernel/ptrace/ptrace-fpu.c @@ -17,9 +17,13 @@ int ptrace_get_fpr(struct task_struct *child, int index, unsigned long *data) #ifdef CONFIG_PPC_FPU_REGS flush_fp_to_thread(child); - if (fpidx < (PT_FPSCR - PT_FPR0)) - memcpy(data, &child->thread.TS_FPR(fpidx), sizeof(long)); - else + if (fpidx < (PT_FPSCR - PT_FPR0)) { + if (IS_ENABLED(CONFIG_PPC32)) + // On 32-bit the index we are passed refers to 32-bit words + *data = ((u32 *)child->thread.fp_state.fpr)[fpidx]; + else + memcpy(data, &child->thread.TS_FPR(fpidx), sizeof(long)); + } else *data = child->thread.fp_state.fpscr; #else *data = 0; @@ -39,9 +43,13 @@ int ptrace_put_fpr(struct task_struct *child, int index, unsigned long data) #ifdef CONFIG_PPC_FPU_REGS flush_fp_to_thread(child); - if (fpidx < (PT_FPSCR - PT_FPR0)) - memcpy(&child->thread.TS_FPR(fpidx), &data, sizeof(long)); - else + if (fpidx < (PT_FPSCR - PT_FPR0)) { + if (IS_ENABLED(CONFIG_PPC32)) + // On 32-bit the index we are passed refers to 32-bit words + ((u32 *)child->thread.fp_state.fpr)[fpidx] = data; + else + memcpy(&child->thread.TS_FPR(fpidx), &data, sizeof(long)); + } else child->thread.fp_state.fpscr = data; #endif diff --git a/arch/powerpc/kernel/ptrace/ptrace.c b/arch/powerpc/kernel/ptrace/ptrace.c index 4d2dc22d4a2d..5d7a72b41ae7 100644 --- a/arch/powerpc/kernel/ptrace/ptrace.c +++ b/arch/powerpc/kernel/ptrace/ptrace.c @@ -444,4 +444,7 @@ void __init pt_regs_check(void) * real registers. */ BUILD_BUG_ON(PT_DSCR < sizeof(struct user_pt_regs) / sizeof(unsigned long)); + + // ptrace_get/put_fpr() rely on PPC32 and VSX being incompatible + BUILD_BUG_ON(IS_ENABLED(CONFIG_PPC32) && IS_ENABLED(CONFIG_VSX)); } -- cgit From 5860800e8696d2cbbd1a0dd60b433549d176e668 Mon Sep 17 00:00:00 2001 From: Zheng Zengkai Date: Thu, 9 Jun 2022 10:56:56 +0800 Subject: Documentation/features: Update the arch support status files The arch support status files don't match reality as of v5.19-rc1, use the features-refresh.sh to refresh all the arch-support.txt files in place. The main effect is to add entries for the new loong architecture. Signed-off-by: Zheng Zengkai Link: https://lore.kernel.org/r/20220609025656.143460-1-zhengzengkai@huawei.com Signed-off-by: Jonathan Corbet --- Documentation/features/core/cBPF-JIT/arch-support.txt | 1 + Documentation/features/core/eBPF-JIT/arch-support.txt | 1 + Documentation/features/core/generic-idle-thread/arch-support.txt | 1 + Documentation/features/core/jump-labels/arch-support.txt | 1 + Documentation/features/core/thread-info-in-task/arch-support.txt | 1 + Documentation/features/core/tracehook/arch-support.txt | 1 + Documentation/features/debug/KASAN/arch-support.txt | 1 + Documentation/features/debug/debug-vm-pgtable/arch-support.txt | 3 ++- Documentation/features/debug/gcov-profile-all/arch-support.txt | 3 ++- Documentation/features/debug/kcov/arch-support.txt | 1 + Documentation/features/debug/kgdb/arch-support.txt | 1 + Documentation/features/debug/kmemleak/arch-support.txt | 1 + Documentation/features/debug/kprobes-on-ftrace/arch-support.txt | 1 + Documentation/features/debug/kprobes/arch-support.txt | 1 + Documentation/features/debug/kretprobes/arch-support.txt | 1 + Documentation/features/debug/optprobes/arch-support.txt | 1 + Documentation/features/debug/stackprotector/arch-support.txt | 1 + Documentation/features/debug/uprobes/arch-support.txt | 1 + Documentation/features/debug/user-ret-profiler/arch-support.txt | 1 + Documentation/features/io/dma-contiguous/arch-support.txt | 1 + Documentation/features/locking/cmpxchg-local/arch-support.txt | 1 + Documentation/features/locking/lockdep/arch-support.txt | 1 + Documentation/features/locking/queued-rwlocks/arch-support.txt | 3 ++- Documentation/features/locking/queued-spinlocks/arch-support.txt | 1 + Documentation/features/perf/kprobes-event/arch-support.txt | 3 ++- Documentation/features/perf/perf-regs/arch-support.txt | 1 + Documentation/features/perf/perf-stackdump/arch-support.txt | 1 + Documentation/features/sched/membarrier-sync-core/arch-support.txt | 1 + Documentation/features/sched/numa-balancing/arch-support.txt | 1 + Documentation/features/seccomp/seccomp-filter/arch-support.txt | 1 + Documentation/features/time/arch-tick-broadcast/arch-support.txt | 1 + Documentation/features/time/clockevents/arch-support.txt | 1 + Documentation/features/time/context-tracking/arch-support.txt | 1 + Documentation/features/time/irq-time-acct/arch-support.txt | 1 + Documentation/features/time/virt-cpuacct/arch-support.txt | 1 + Documentation/features/vm/ELF-ASLR/arch-support.txt | 1 + Documentation/features/vm/PG_uncached/arch-support.txt | 1 + Documentation/features/vm/THP/arch-support.txt | 1 + Documentation/features/vm/TLB/arch-support.txt | 1 + Documentation/features/vm/huge-vmap/arch-support.txt | 1 + Documentation/features/vm/ioremap_prot/arch-support.txt | 1 + Documentation/features/vm/pte_special/arch-support.txt | 3 ++- 42 files changed, 47 insertions(+), 5 deletions(-) diff --git a/Documentation/features/core/cBPF-JIT/arch-support.txt b/Documentation/features/core/cBPF-JIT/arch-support.txt index 10482dee8703..a053667a7a8c 100644 --- a/Documentation/features/core/cBPF-JIT/arch-support.txt +++ b/Documentation/features/core/cBPF-JIT/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/core/eBPF-JIT/arch-support.txt b/Documentation/features/core/eBPF-JIT/arch-support.txt index bcefb5afc7d6..c0bb9c92937f 100644 --- a/Documentation/features/core/eBPF-JIT/arch-support.txt +++ b/Documentation/features/core/eBPF-JIT/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/core/generic-idle-thread/arch-support.txt b/Documentation/features/core/generic-idle-thread/arch-support.txt index d80d99449ac1..c9bfff292816 100644 --- a/Documentation/features/core/generic-idle-thread/arch-support.txt +++ b/Documentation/features/core/generic-idle-thread/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | ok | | ia64: | ok | + | loong: | ok | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/core/jump-labels/arch-support.txt b/Documentation/features/core/jump-labels/arch-support.txt index 53eab154925d..35e2a44b1448 100644 --- a/Documentation/features/core/jump-labels/arch-support.txt +++ b/Documentation/features/core/jump-labels/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/core/thread-info-in-task/arch-support.txt b/Documentation/features/core/thread-info-in-task/arch-support.txt index 94926451afb9..9b3e2ce12b44 100644 --- a/Documentation/features/core/thread-info-in-task/arch-support.txt +++ b/Documentation/features/core/thread-info-in-task/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | TODO | diff --git a/Documentation/features/core/tracehook/arch-support.txt b/Documentation/features/core/tracehook/arch-support.txt index b4274b8141b6..9c7ffec5d51d 100644 --- a/Documentation/features/core/tracehook/arch-support.txt +++ b/Documentation/features/core/tracehook/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | ok | | ia64: | ok | + | loong: | ok | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/debug/KASAN/arch-support.txt b/Documentation/features/debug/KASAN/arch-support.txt index c15bb4b21b6f..2fd5fb6f5f23 100644 --- a/Documentation/features/debug/KASAN/arch-support.txt +++ b/Documentation/features/debug/KASAN/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | TODO | diff --git a/Documentation/features/debug/debug-vm-pgtable/arch-support.txt b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt index 4c31fc92a312..c45711e55c7b 100644 --- a/Documentation/features/debug/debug-vm-pgtable/arch-support.txt +++ b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt @@ -13,12 +13,13 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | TODO | | nios2: | TODO | | openrisc: | TODO | - | parisc: | TODO | + | parisc: | ok | | powerpc: | ok | | riscv: | ok | | s390: | ok | diff --git a/Documentation/features/debug/gcov-profile-all/arch-support.txt b/Documentation/features/debug/gcov-profile-all/arch-support.txt index d7a5ac4bc1fe..502c1d409648 100644 --- a/Documentation/features/debug/gcov-profile-all/arch-support.txt +++ b/Documentation/features/debug/gcov-profile-all/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | ok | | mips: | ok | @@ -24,7 +25,7 @@ | s390: | ok | | sh: | ok | | sparc: | TODO | - | um: | TODO | + | um: | ok | | x86: | ok | | xtensa: | TODO | ----------------------- diff --git a/Documentation/features/debug/kcov/arch-support.txt b/Documentation/features/debug/kcov/arch-support.txt index 136e14c2b603..afb90bebded2 100644 --- a/Documentation/features/debug/kcov/arch-support.txt +++ b/Documentation/features/debug/kcov/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/debug/kgdb/arch-support.txt b/Documentation/features/debug/kgdb/arch-support.txt index 5b3f3d8ae462..04120d278c22 100644 --- a/Documentation/features/debug/kgdb/arch-support.txt +++ b/Documentation/features/debug/kgdb/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | ok | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | ok | | mips: | ok | diff --git a/Documentation/features/debug/kmemleak/arch-support.txt b/Documentation/features/debug/kmemleak/arch-support.txt index 7a2eab4fdf9d..e487c356ab20 100644 --- a/Documentation/features/debug/kmemleak/arch-support.txt +++ b/Documentation/features/debug/kmemleak/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | ok | | mips: | ok | diff --git a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt index db02ab194138..b3697f4c806e 100644 --- a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt +++ b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | TODO | diff --git a/Documentation/features/debug/kprobes/arch-support.txt b/Documentation/features/debug/kprobes/arch-support.txt index ec186e7deebc..452385ac9e06 100644 --- a/Documentation/features/debug/kprobes/arch-support.txt +++ b/Documentation/features/debug/kprobes/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | ok | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/debug/kretprobes/arch-support.txt b/Documentation/features/debug/kretprobes/arch-support.txt index 4b7865e693f6..daecf046e72b 100644 --- a/Documentation/features/debug/kretprobes/arch-support.txt +++ b/Documentation/features/debug/kretprobes/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | ok | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/debug/optprobes/arch-support.txt b/Documentation/features/debug/optprobes/arch-support.txt index 5d9befa041c7..adb1bd055bfd 100644 --- a/Documentation/features/debug/optprobes/arch-support.txt +++ b/Documentation/features/debug/optprobes/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | TODO | diff --git a/Documentation/features/debug/stackprotector/arch-support.txt b/Documentation/features/debug/stackprotector/arch-support.txt index d97fd38460e6..ddcd7161d14c 100644 --- a/Documentation/features/debug/stackprotector/arch-support.txt +++ b/Documentation/features/debug/stackprotector/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/debug/uprobes/arch-support.txt b/Documentation/features/debug/uprobes/arch-support.txt index d30e3475904e..25121200f9f9 100644 --- a/Documentation/features/debug/uprobes/arch-support.txt +++ b/Documentation/features/debug/uprobes/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/debug/user-ret-profiler/arch-support.txt b/Documentation/features/debug/user-ret-profiler/arch-support.txt index 9ae1fa2eb27c..f2fcff8e77b7 100644 --- a/Documentation/features/debug/user-ret-profiler/arch-support.txt +++ b/Documentation/features/debug/user-ret-profiler/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | TODO | diff --git a/Documentation/features/io/dma-contiguous/arch-support.txt b/Documentation/features/io/dma-contiguous/arch-support.txt index 9e09988eb654..95e485c87e36 100644 --- a/Documentation/features/io/dma-contiguous/arch-support.txt +++ b/Documentation/features/io/dma-contiguous/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | + | loong: | ok | | m68k: | TODO | | microblaze: | ok | | mips: | ok | diff --git a/Documentation/features/locking/cmpxchg-local/arch-support.txt b/Documentation/features/locking/cmpxchg-local/arch-support.txt index 5c4ec316dbac..8b1a8d9e1c79 100644 --- a/Documentation/features/locking/cmpxchg-local/arch-support.txt +++ b/Documentation/features/locking/cmpxchg-local/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | TODO | diff --git a/Documentation/features/locking/lockdep/arch-support.txt b/Documentation/features/locking/lockdep/arch-support.txt index 65007c1ac44f..ab69e8f56a37 100644 --- a/Documentation/features/locking/lockdep/arch-support.txt +++ b/Documentation/features/locking/lockdep/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | ok | | ia64: | TODO | + | loong: | ok | | m68k: | TODO | | microblaze: | ok | | mips: | ok | diff --git a/Documentation/features/locking/queued-rwlocks/arch-support.txt b/Documentation/features/locking/queued-rwlocks/arch-support.txt index 20056670fb09..0bfb72a08d82 100644 --- a/Documentation/features/locking/queued-rwlocks/arch-support.txt +++ b/Documentation/features/locking/queued-rwlocks/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | + | loong: | ok | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | @@ -20,7 +21,7 @@ | openrisc: | ok | | parisc: | TODO | | powerpc: | ok | - | riscv: | TODO | + | riscv: | ok | | s390: | TODO | | sh: | TODO | | sparc: | ok | diff --git a/Documentation/features/locking/queued-spinlocks/arch-support.txt b/Documentation/features/locking/queued-spinlocks/arch-support.txt index 707514faac7b..d2f2201febc8 100644 --- a/Documentation/features/locking/queued-spinlocks/arch-support.txt +++ b/Documentation/features/locking/queued-spinlocks/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/perf/kprobes-event/arch-support.txt b/Documentation/features/perf/kprobes-event/arch-support.txt index 9f31ce9b9f2a..0d0647b06762 100644 --- a/Documentation/features/perf/kprobes-event/arch-support.txt +++ b/Documentation/features/perf/kprobes-event/arch-support.txt @@ -7,12 +7,13 @@ | arch |status| ----------------------- | alpha: | TODO | - | arc: | TODO | + | arc: | ok | | arm: | ok | | arm64: | ok | | csky: | ok | | hexagon: | ok | | ia64: | TODO | + | loong: | ok | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/perf/perf-regs/arch-support.txt b/Documentation/features/perf/perf-regs/arch-support.txt index f148c4329c7a..13c297bbf05c 100644 --- a/Documentation/features/perf/perf-regs/arch-support.txt +++ b/Documentation/features/perf/perf-regs/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/perf/perf-stackdump/arch-support.txt b/Documentation/features/perf/perf-stackdump/arch-support.txt index 32c88b6a910c..931687eec671 100644 --- a/Documentation/features/perf/perf-stackdump/arch-support.txt +++ b/Documentation/features/perf/perf-stackdump/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/sched/membarrier-sync-core/arch-support.txt b/Documentation/features/sched/membarrier-sync-core/arch-support.txt index d82a1f0cdc91..336d728b8a45 100644 --- a/Documentation/features/sched/membarrier-sync-core/arch-support.txt +++ b/Documentation/features/sched/membarrier-sync-core/arch-support.txt @@ -36,6 +36,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | TODO | diff --git a/Documentation/features/sched/numa-balancing/arch-support.txt b/Documentation/features/sched/numa-balancing/arch-support.txt index 2687564e5fa8..76d012118372 100644 --- a/Documentation/features/sched/numa-balancing/arch-support.txt +++ b/Documentation/features/sched/numa-balancing/arch-support.txt @@ -13,6 +13,7 @@ | csky: | .. | | hexagon: | .. | | ia64: | TODO | + | loong: | ok | | m68k: | .. | | microblaze: | .. | | mips: | TODO | diff --git a/Documentation/features/seccomp/seccomp-filter/arch-support.txt b/Documentation/features/seccomp/seccomp-filter/arch-support.txt index 1b4109199e9d..a86b8b1f3d10 100644 --- a/Documentation/features/seccomp/seccomp-filter/arch-support.txt +++ b/Documentation/features/seccomp/seccomp-filter/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | + | loong: | ok | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/time/arch-tick-broadcast/arch-support.txt b/Documentation/features/time/arch-tick-broadcast/arch-support.txt index 27327256bd05..364169f00ee2 100644 --- a/Documentation/features/time/arch-tick-broadcast/arch-support.txt +++ b/Documentation/features/time/arch-tick-broadcast/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | ok | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/time/clockevents/arch-support.txt b/Documentation/features/time/clockevents/arch-support.txt index b9a4bda2c8f5..6ea274790e47 100644 --- a/Documentation/features/time/clockevents/arch-support.txt +++ b/Documentation/features/time/clockevents/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | ok | | ia64: | TODO | + | loong: | ok | | m68k: | TODO | | microblaze: | ok | | mips: | ok | diff --git a/Documentation/features/time/context-tracking/arch-support.txt b/Documentation/features/time/context-tracking/arch-support.txt index 4aa51c9fa32b..c9e0a16290e6 100644 --- a/Documentation/features/time/context-tracking/arch-support.txt +++ b/Documentation/features/time/context-tracking/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | TODO | + | loong: | ok | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/time/irq-time-acct/arch-support.txt b/Documentation/features/time/irq-time-acct/arch-support.txt index 0306ece41faa..fd17d8de5ef1 100644 --- a/Documentation/features/time/irq-time-acct/arch-support.txt +++ b/Documentation/features/time/irq-time-acct/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | .. | + | loong: | ok | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/time/virt-cpuacct/arch-support.txt b/Documentation/features/time/virt-cpuacct/arch-support.txt index 5d64e40c0092..1a859ac05e9e 100644 --- a/Documentation/features/time/virt-cpuacct/arch-support.txt +++ b/Documentation/features/time/virt-cpuacct/arch-support.txt @@ -13,6 +13,7 @@ | csky: | ok | | hexagon: | TODO | | ia64: | ok | + | loong: | ok | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/vm/ELF-ASLR/arch-support.txt b/Documentation/features/vm/ELF-ASLR/arch-support.txt index 92c9db24a6a3..b1229953391b 100644 --- a/Documentation/features/vm/ELF-ASLR/arch-support.txt +++ b/Documentation/features/vm/ELF-ASLR/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/vm/PG_uncached/arch-support.txt b/Documentation/features/vm/PG_uncached/arch-support.txt index 7424fea37614..02f325fbfcd0 100644 --- a/Documentation/features/vm/PG_uncached/arch-support.txt +++ b/Documentation/features/vm/PG_uncached/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | ok | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | TODO | diff --git a/Documentation/features/vm/THP/arch-support.txt b/Documentation/features/vm/THP/arch-support.txt index 60985067626b..9bfff977ef55 100644 --- a/Documentation/features/vm/THP/arch-support.txt +++ b/Documentation/features/vm/THP/arch-support.txt @@ -13,6 +13,7 @@ | csky: | .. | | hexagon: | .. | | ia64: | TODO | + | loong: | ok | | m68k: | .. | | microblaze: | .. | | mips: | ok | diff --git a/Documentation/features/vm/TLB/arch-support.txt b/Documentation/features/vm/TLB/arch-support.txt index f2dcbec6020e..039e4e91ada3 100644 --- a/Documentation/features/vm/TLB/arch-support.txt +++ b/Documentation/features/vm/TLB/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | .. | | microblaze: | .. | | mips: | TODO | diff --git a/Documentation/features/vm/huge-vmap/arch-support.txt b/Documentation/features/vm/huge-vmap/arch-support.txt index 680090df03e1..13b4940e0c3a 100644 --- a/Documentation/features/vm/huge-vmap/arch-support.txt +++ b/Documentation/features/vm/huge-vmap/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | TODO | | m68k: | TODO | | microblaze: | TODO | | mips: | TODO | diff --git a/Documentation/features/vm/ioremap_prot/arch-support.txt b/Documentation/features/vm/ioremap_prot/arch-support.txt index 205a90e82050..b01bf7bca3e6 100644 --- a/Documentation/features/vm/ioremap_prot/arch-support.txt +++ b/Documentation/features/vm/ioremap_prot/arch-support.txt @@ -13,6 +13,7 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | ok | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | diff --git a/Documentation/features/vm/pte_special/arch-support.txt b/Documentation/features/vm/pte_special/arch-support.txt index 9f16d6e4e11e..fc3687b5e89b 100644 --- a/Documentation/features/vm/pte_special/arch-support.txt +++ b/Documentation/features/vm/pte_special/arch-support.txt @@ -13,12 +13,13 @@ | csky: | TODO | | hexagon: | TODO | | ia64: | TODO | + | loong: | ok | | m68k: | TODO | | microblaze: | TODO | | mips: | ok | | nios2: | TODO | | openrisc: | TODO | - | parisc: | TODO | + | parisc: | ok | | powerpc: | ok | | riscv: | ok | | s390: | ok | -- cgit From 788183a6e8b098b90e15214e800ae5194591018a Mon Sep 17 00:00:00 2001 From: Justin Swartz Date: Sat, 4 Jun 2022 17:54:31 +0200 Subject: docs: usb: fix literal block marker in usbmon verification example The "Verify that bus sockets are present" example was not properly formatted due to a typo in the literal block marker. Signed-off-by: Justin Swartz Link: https://lore.kernel.org/r/20220604155431.23246-1-justin.swartz@risingedge.co.za Signed-off-by: Jonathan Corbet --- Documentation/usb/usbmon.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/usb/usbmon.rst b/Documentation/usb/usbmon.rst index b0bd51080799..6d5ec1e62d09 100644 --- a/Documentation/usb/usbmon.rst +++ b/Documentation/usb/usbmon.rst @@ -42,7 +42,7 @@ if usbmon is built into the kernel:: # modprobe usbmon # -Verify that bus sockets are present: +Verify that bus sockets are present:: # ls /sys/kernel/debug/usb/usbmon 0s 0u 1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u -- cgit From 9c73e1e06e0d6d72c445a1b1f50493da260b0c4e Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Mon, 6 Jun 2022 08:40:55 -0600 Subject: docs: Move the HTE documentation to driver-api/ The hardware timestamp engine documentation is driver API material, and really belongs in the driver-API book; move it there. Cc: Thierry Reding Acked-by: Dipen Patel Signed-off-by: Jonathan Corbet --- Documentation/driver-api/hte/hte.rst | 79 +++++++++++++++++++++++++++ Documentation/driver-api/hte/index.rst | 22 ++++++++ Documentation/driver-api/hte/tegra194-hte.rst | 49 +++++++++++++++++ Documentation/driver-api/index.rst | 1 + Documentation/hte/hte.rst | 79 --------------------------- Documentation/hte/index.rst | 22 -------- Documentation/hte/tegra194-hte.rst | 49 ----------------- Documentation/index.rst | 1 - MAINTAINERS | 2 +- 9 files changed, 152 insertions(+), 152 deletions(-) create mode 100644 Documentation/driver-api/hte/hte.rst create mode 100644 Documentation/driver-api/hte/index.rst create mode 100644 Documentation/driver-api/hte/tegra194-hte.rst delete mode 100644 Documentation/hte/hte.rst delete mode 100644 Documentation/hte/index.rst delete mode 100644 Documentation/hte/tegra194-hte.rst diff --git a/Documentation/driver-api/hte/hte.rst b/Documentation/driver-api/hte/hte.rst new file mode 100644 index 000000000000..153f3233c100 --- /dev/null +++ b/Documentation/driver-api/hte/hte.rst @@ -0,0 +1,79 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +============================================ +The Linux Hardware Timestamping Engine (HTE) +============================================ + +:Author: Dipen Patel + +Introduction +------------ + +Certain devices have built in hardware timestamping engines which can +monitor sets of system signals, lines, buses etc... in realtime for state +change; upon detecting the change they can automatically store the timestamp at +the moment of occurrence. Such functionality may help achieve better accuracy +in obtaining timestamps than using software counterparts i.e. ktime and +friends. + +This document describes the API that can be used by hardware timestamping +engine provider and consumer drivers that want to use the hardware timestamping +engine (HTE) framework. Both consumers and providers must include +``#include ``. + +The HTE framework APIs for the providers +---------------------------------------- + +.. kernel-doc:: drivers/hte/hte.c + :functions: devm_hte_register_chip hte_push_ts_ns + +The HTE framework APIs for the consumers +---------------------------------------- + +.. kernel-doc:: drivers/hte/hte.c + :functions: hte_init_line_attr hte_ts_get hte_ts_put devm_hte_request_ts_ns hte_request_ts_ns hte_enable_ts hte_disable_ts of_hte_req_count hte_get_clk_src_info + +The HTE framework public structures +----------------------------------- +.. kernel-doc:: include/linux/hte.h + +More on the HTE timestamp data +------------------------------ +The ``struct hte_ts_data`` is used to pass timestamp details between the +consumers and the providers. It expresses timestamp data in nanoseconds in +u64. An example of the typical timestamp data life cycle, for the GPIO line is +as follows:: + + - Monitors GPIO line change. + - Detects the state change on GPIO line. + - Converts timestamps in nanoseconds. + - Stores GPIO raw level in raw_level variable if the provider has that + hardware capability. + - Pushes this hte_ts_data object to HTE subsystem. + - HTE subsystem increments seq counter and invokes consumer provided callback. + Based on callback return value, the HTE core invokes secondary callback in + the thread context. + +HTE subsystem debugfs attributes +-------------------------------- +HTE subsystem creates debugfs attributes at ``/sys/kernel/debug/hte/``. +It also creates line/signal-related debugfs attributes at +``/sys/kernel/debug/hte//