^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright(c) 2015-17 Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Soundwire Intel Master Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/soundwire/sdw_registers.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/soundwire/sdw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/soundwire/sdw_intel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "cadence_master.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "bus.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "intel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define INTEL_MASTER_SUSPEND_DELAY_MS 3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * debug/config flags for the Intel SoundWire Master.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * Since we may have multiple masters active, we can have up to 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * flags reused in each byte, with master0 using the ls-byte, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define SDW_INTEL_MASTER_DISABLE_PM_RUNTIME BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define SDW_INTEL_MASTER_DISABLE_CLOCK_STOP BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define SDW_INTEL_MASTER_DISABLE_PM_RUNTIME_IDLE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define SDW_INTEL_MASTER_DISABLE_MULTI_LINK BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int md_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) module_param_named(sdw_md_flags, md_flags, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) MODULE_PARM_DESC(sdw_md_flags, "SoundWire Intel Master device flags (0x0 all off)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* Intel SHIM Registers Definition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define SDW_SHIM_LCAP 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define SDW_SHIM_LCTL 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define SDW_SHIM_IPPTR 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SDW_SHIM_SYNC 0xC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define SDW_SHIM_CTLSCAP(x) (0x010 + 0x60 * (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define SDW_SHIM_CTLS0CM(x) (0x012 + 0x60 * (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define SDW_SHIM_CTLS1CM(x) (0x014 + 0x60 * (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define SDW_SHIM_CTLS2CM(x) (0x016 + 0x60 * (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define SDW_SHIM_CTLS3CM(x) (0x018 + 0x60 * (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define SDW_SHIM_PCMSCAP(x) (0x020 + 0x60 * (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define SDW_SHIM_PCMSYCHM(x, y) (0x022 + (0x60 * (x)) + (0x2 * (y)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define SDW_SHIM_PCMSYCHC(x, y) (0x042 + (0x60 * (x)) + (0x2 * (y)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define SDW_SHIM_PDMSCAP(x) (0x062 + 0x60 * (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define SDW_SHIM_IOCTL(x) (0x06C + 0x60 * (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define SDW_SHIM_CTMCTL(x) (0x06E + 0x60 * (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define SDW_SHIM_WAKEEN 0x190
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define SDW_SHIM_WAKESTS 0x192
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define SDW_SHIM_LCTL_SPA BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define SDW_SHIM_LCTL_SPA_MASK GENMASK(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define SDW_SHIM_LCTL_CPA BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define SDW_SHIM_LCTL_CPA_MASK GENMASK(11, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define SDW_SHIM_SYNC_SYNCPRD_VAL_24 (24000 / SDW_CADENCE_GSYNC_KHZ - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define SDW_SHIM_SYNC_SYNCPRD_VAL_38_4 (38400 / SDW_CADENCE_GSYNC_KHZ - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define SDW_SHIM_SYNC_SYNCPRD GENMASK(14, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define SDW_SHIM_SYNC_SYNCCPU BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define SDW_SHIM_SYNC_CMDSYNC_MASK GENMASK(19, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define SDW_SHIM_SYNC_CMDSYNC BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define SDW_SHIM_SYNC_SYNCGO BIT(24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define SDW_SHIM_PCMSCAP_ISS GENMASK(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define SDW_SHIM_PCMSCAP_OSS GENMASK(7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define SDW_SHIM_PCMSCAP_BSS GENMASK(12, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define SDW_SHIM_PCMSYCM_LCHN GENMASK(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define SDW_SHIM_PCMSYCM_HCHN GENMASK(7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define SDW_SHIM_PCMSYCM_STREAM GENMASK(13, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define SDW_SHIM_PCMSYCM_DIR BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define SDW_SHIM_PDMSCAP_ISS GENMASK(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define SDW_SHIM_PDMSCAP_OSS GENMASK(7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define SDW_SHIM_PDMSCAP_BSS GENMASK(12, 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define SDW_SHIM_PDMSCAP_CPSS GENMASK(15, 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define SDW_SHIM_IOCTL_MIF BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define SDW_SHIM_IOCTL_CO BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define SDW_SHIM_IOCTL_COE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define SDW_SHIM_IOCTL_DO BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define SDW_SHIM_IOCTL_DOE BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define SDW_SHIM_IOCTL_BKE BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define SDW_SHIM_IOCTL_WPDD BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define SDW_SHIM_IOCTL_CIBD BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define SDW_SHIM_IOCTL_DIBD BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define SDW_SHIM_CTMCTL_DACTQE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define SDW_SHIM_CTMCTL_DODS BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define SDW_SHIM_CTMCTL_DOAIS GENMASK(4, 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define SDW_SHIM_WAKEEN_ENABLE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define SDW_SHIM_WAKESTS_STATUS BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* Intel ALH Register definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define SDW_ALH_STRMZCFG(x) (0x000 + (0x4 * (x)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define SDW_ALH_NUM_STREAMS 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define SDW_ALH_STRMZCFG_DMAT_VAL 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define SDW_ALH_STRMZCFG_DMAT GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #define SDW_ALH_STRMZCFG_CHN GENMASK(19, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) enum intel_pdi_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) INTEL_PDI_IN = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) INTEL_PDI_OUT = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) INTEL_PDI_BD = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define cdns_to_intel(_cdns) container_of(_cdns, struct sdw_intel, cdns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * Read, write helpers for HW registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static inline int intel_readl(void __iomem *base, int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return readl(base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static inline void intel_writel(void __iomem *base, int offset, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) writel(value, base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static inline u16 intel_readw(void __iomem *base, int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return readw(base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static inline void intel_writew(void __iomem *base, int offset, u16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) writew(value, base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int intel_wait_bit(void __iomem *base, int offset, u32 mask, u32 target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int timeout = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) u32 reg_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) reg_read = readl(base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if ((reg_read & mask) == target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) timeout--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) usleep_range(50, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) } while (timeout != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static int intel_clear_bit(void __iomem *base, int offset, u32 value, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) writel(value, base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return intel_wait_bit(base, offset, mask, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int intel_set_bit(void __iomem *base, int offset, u32 value, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) writel(value, base + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return intel_wait_bit(base, offset, mask, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * debugfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define RD_BUF (2 * PAGE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static ssize_t intel_sprintf(void __iomem *mem, bool l,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) char *buf, size_t pos, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (l)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) value = intel_readl(mem, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) value = intel_readw(mem, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return scnprintf(buf + pos, RD_BUF - pos, "%4x\t%4x\n", reg, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static int intel_reg_show(struct seq_file *s_file, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct sdw_intel *sdw = s_file->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) void __iomem *s = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) void __iomem *a = sdw->link_res->alh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) unsigned int links, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) buf = kzalloc(RD_BUF, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) links = intel_readl(s, SDW_SHIM_LCAP) & GENMASK(2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ret = scnprintf(buf, RD_BUF, "Register Value\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ret += scnprintf(buf + ret, RD_BUF - ret, "\nShim\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) for (i = 0; i < links; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) reg = SDW_SHIM_LCAP + i * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ret += intel_sprintf(s, true, buf, ret, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) for (i = 0; i < links; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ret += scnprintf(buf + ret, RD_BUF - ret, "\nLink%d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_CTLSCAP(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_CTLS0CM(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_CTLS1CM(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_CTLS2CM(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_CTLS3CM(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_PCMSCAP(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ret += scnprintf(buf + ret, RD_BUF - ret, "\n PCMSyCH registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * the value 10 is the number of PDIs. We will need a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * cleanup to remove hard-coded Intel configurations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * from cadence_master.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) for (j = 0; j < 10; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ret += intel_sprintf(s, false, buf, ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) SDW_SHIM_PCMSYCHM(i, j));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ret += intel_sprintf(s, false, buf, ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) SDW_SHIM_PCMSYCHC(i, j));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ret += scnprintf(buf + ret, RD_BUF - ret, "\n PDMSCAP, IOCTL, CTMCTL\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_PDMSCAP(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_IOCTL(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_CTMCTL(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ret += scnprintf(buf + ret, RD_BUF - ret, "\nWake registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_WAKEEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_WAKESTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ret += scnprintf(buf + ret, RD_BUF - ret, "\nALH STRMzCFG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) for (i = 0; i < SDW_ALH_NUM_STREAMS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) ret += intel_sprintf(a, true, buf, ret, SDW_ALH_STRMZCFG(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) seq_printf(s_file, "%s", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) DEFINE_SHOW_ATTRIBUTE(intel_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static int intel_set_m_datamode(void *data, u64 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct sdw_intel *sdw = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct sdw_bus *bus = &sdw->cdns.bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (value > SDW_PORT_DATA_MODE_STATIC_1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* Userspace changed the hardware state behind the kernel's back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) add_taint(TAINT_USER, LOCKDEP_STILL_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) bus->params.m_data_mode = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) DEFINE_DEBUGFS_ATTRIBUTE(intel_set_m_datamode_fops, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) intel_set_m_datamode, "%llu\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static int intel_set_s_datamode(void *data, u64 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct sdw_intel *sdw = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) struct sdw_bus *bus = &sdw->cdns.bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (value > SDW_PORT_DATA_MODE_STATIC_1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* Userspace changed the hardware state behind the kernel's back */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) add_taint(TAINT_USER, LOCKDEP_STILL_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) bus->params.s_data_mode = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) DEFINE_DEBUGFS_ATTRIBUTE(intel_set_s_datamode_fops, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) intel_set_s_datamode, "%llu\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static void intel_debugfs_init(struct sdw_intel *sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct dentry *root = sdw->cdns.bus.debugfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (!root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) sdw->debugfs = debugfs_create_dir("intel-sdw", root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) debugfs_create_file("intel-registers", 0400, sdw->debugfs, sdw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) &intel_reg_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) debugfs_create_file("intel-m-datamode", 0200, sdw->debugfs, sdw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) &intel_set_m_datamode_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) debugfs_create_file("intel-s-datamode", 0200, sdw->debugfs, sdw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) &intel_set_s_datamode_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) sdw_cdns_debugfs_init(&sdw->cdns, sdw->debugfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static void intel_debugfs_exit(struct sdw_intel *sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) debugfs_remove_recursive(sdw->debugfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static void intel_debugfs_init(struct sdw_intel *sdw) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static void intel_debugfs_exit(struct sdw_intel *sdw) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) #endif /* CONFIG_DEBUG_FS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * shim ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static int intel_link_power_up(struct sdw_intel *sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) unsigned int link_id = sdw->instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) void __iomem *shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) u32 *shim_mask = sdw->link_res->shim_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct sdw_bus *bus = &sdw->cdns.bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct sdw_master_prop *prop = &bus->prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) u32 spa_mask, cpa_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) u32 link_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) u32 syncprd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) u32 sync_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) mutex_lock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * The hardware relies on an internal counter, typically 4kHz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * to generate the SoundWire SSP - which defines a 'safe'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * synchronization point between commands and audio transport
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * and allows for multi link synchronization. The SYNCPRD value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * is only dependent on the oscillator clock provided to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * the IP, so adjust based on _DSD properties reported in DSDT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * tables. The values reported are based on either 24MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * (CNL/CML) or 38.4 MHz (ICL/TGL+).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (prop->mclk_freq % 6000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_38_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (!*shim_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) dev_dbg(sdw->cdns.dev, "%s: powering up all links\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* we first need to program the SyncPRD/CPU registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) dev_dbg(sdw->cdns.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) "%s: first link up, programming SYNCPRD\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* set SyncPRD period */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) sync_reg = intel_readl(shim, SDW_SHIM_SYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) u32p_replace_bits(&sync_reg, syncprd, SDW_SHIM_SYNC_SYNCPRD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) /* Set SyncCPU bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) sync_reg |= SDW_SHIM_SYNC_SYNCCPU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) intel_writel(shim, SDW_SHIM_SYNC, sync_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /* Link power up sequence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) link_control = intel_readl(shim, SDW_SHIM_LCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /* only power-up enabled links */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) spa_mask = FIELD_PREP(SDW_SHIM_LCTL_SPA_MASK, sdw->link_res->link_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) cpa_mask = FIELD_PREP(SDW_SHIM_LCTL_CPA_MASK, sdw->link_res->link_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) link_control |= spa_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) ret = intel_set_bit(shim, SDW_SHIM_LCTL, link_control, cpa_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) dev_err(sdw->cdns.dev, "Failed to power up link: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /* SyncCPU will change once link is active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) ret = intel_wait_bit(shim, SDW_SHIM_SYNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) SDW_SHIM_SYNC_SYNCCPU, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) dev_err(sdw->cdns.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) "Failed to set SHIM_SYNC: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) *shim_mask |= BIT(link_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) sdw->cdns.link_up = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) mutex_unlock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /* this needs to be called with shim_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static void intel_shim_glue_to_master_ip(struct sdw_intel *sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) void __iomem *shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) unsigned int link_id = sdw->instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) u16 ioctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /* Switch to MIP from Glue logic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) ioctl = intel_readw(shim, SDW_SHIM_IOCTL(link_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) ioctl &= ~(SDW_SHIM_IOCTL_DOE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) intel_writew(shim, SDW_SHIM_IOCTL(link_id), ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) usleep_range(10, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) ioctl &= ~(SDW_SHIM_IOCTL_DO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) intel_writew(shim, SDW_SHIM_IOCTL(link_id), ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) usleep_range(10, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) ioctl |= (SDW_SHIM_IOCTL_MIF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) intel_writew(shim, SDW_SHIM_IOCTL(link_id), ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) usleep_range(10, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) ioctl &= ~(SDW_SHIM_IOCTL_BKE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ioctl &= ~(SDW_SHIM_IOCTL_COE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) intel_writew(shim, SDW_SHIM_IOCTL(link_id), ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) usleep_range(10, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* at this point Master IP has full control of the I/Os */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /* this needs to be called with shim_lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static void intel_shim_master_ip_to_glue(struct sdw_intel *sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) unsigned int link_id = sdw->instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) void __iomem *shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) u16 ioctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* Glue logic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ioctl = intel_readw(shim, SDW_SHIM_IOCTL(link_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ioctl |= SDW_SHIM_IOCTL_BKE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) ioctl |= SDW_SHIM_IOCTL_COE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) intel_writew(shim, SDW_SHIM_IOCTL(link_id), ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) usleep_range(10, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) ioctl &= ~(SDW_SHIM_IOCTL_MIF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) intel_writew(shim, SDW_SHIM_IOCTL(link_id), ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) usleep_range(10, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /* at this point Integration Glue has full control of the I/Os */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) static int intel_shim_init(struct sdw_intel *sdw, bool clock_stop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) void __iomem *shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) unsigned int link_id = sdw->instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) u16 ioctl = 0, act = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) mutex_lock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* Initialize Shim */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) ioctl |= SDW_SHIM_IOCTL_BKE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) intel_writew(shim, SDW_SHIM_IOCTL(link_id), ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) usleep_range(10, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) ioctl |= SDW_SHIM_IOCTL_WPDD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) intel_writew(shim, SDW_SHIM_IOCTL(link_id), ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) usleep_range(10, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ioctl |= SDW_SHIM_IOCTL_DO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) intel_writew(shim, SDW_SHIM_IOCTL(link_id), ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) usleep_range(10, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ioctl |= SDW_SHIM_IOCTL_DOE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) intel_writew(shim, SDW_SHIM_IOCTL(link_id), ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) usleep_range(10, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) intel_shim_glue_to_master_ip(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) u16p_replace_bits(&act, 0x1, SDW_SHIM_CTMCTL_DOAIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) act |= SDW_SHIM_CTMCTL_DACTQE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) act |= SDW_SHIM_CTMCTL_DODS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) intel_writew(shim, SDW_SHIM_CTMCTL(link_id), act);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) usleep_range(10, 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) mutex_unlock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static void intel_shim_wake(struct sdw_intel *sdw, bool wake_enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) void __iomem *shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) unsigned int link_id = sdw->instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) u16 wake_en, wake_sts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) mutex_lock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) wake_en = intel_readw(shim, SDW_SHIM_WAKEEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (wake_enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) /* Enable the wakeup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) wake_en |= (SDW_SHIM_WAKEEN_ENABLE << link_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) intel_writew(shim, SDW_SHIM_WAKEEN, wake_en);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* Disable the wake up interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) wake_en &= ~(SDW_SHIM_WAKEEN_ENABLE << link_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) intel_writew(shim, SDW_SHIM_WAKEEN, wake_en);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* Clear wake status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) wake_sts = intel_readw(shim, SDW_SHIM_WAKESTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) wake_sts |= (SDW_SHIM_WAKESTS_STATUS << link_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) intel_writew(shim, SDW_SHIM_WAKESTS, wake_sts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) mutex_unlock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static int intel_link_power_down(struct sdw_intel *sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) u32 link_control, spa_mask, cpa_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) unsigned int link_id = sdw->instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) void __iomem *shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) u32 *shim_mask = sdw->link_res->shim_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) mutex_lock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (!(*shim_mask & BIT(link_id)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) dev_err(sdw->cdns.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) "%s: Unbalanced power-up/down calls\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) sdw->cdns.link_up = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) intel_shim_master_ip_to_glue(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) *shim_mask &= ~BIT(link_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (!*shim_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) dev_dbg(sdw->cdns.dev, "%s: powering down all links\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /* Link power down sequence */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) link_control = intel_readl(shim, SDW_SHIM_LCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* only power-down enabled links */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) spa_mask = FIELD_PREP(SDW_SHIM_LCTL_SPA_MASK, ~sdw->link_res->link_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) cpa_mask = FIELD_PREP(SDW_SHIM_LCTL_CPA_MASK, sdw->link_res->link_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) link_control &= spa_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) ret = intel_clear_bit(shim, SDW_SHIM_LCTL, link_control, cpa_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) dev_err(sdw->cdns.dev, "%s: could not power down link\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * we leave the sdw->cdns.link_up flag as false since we've disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * the link at this point and cannot handle interrupts any longer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) link_control = intel_readl(shim, SDW_SHIM_LCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) mutex_unlock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static void intel_shim_sync_arm(struct sdw_intel *sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) void __iomem *shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) u32 sync_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) mutex_lock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* update SYNC register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) sync_reg = intel_readl(shim, SDW_SHIM_SYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) sync_reg |= (SDW_SHIM_SYNC_CMDSYNC << sdw->instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) intel_writel(shim, SDW_SHIM_SYNC, sync_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) mutex_unlock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) static int intel_shim_sync_go_unlocked(struct sdw_intel *sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) void __iomem *shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) u32 sync_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) /* Read SYNC register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) sync_reg = intel_readl(shim, SDW_SHIM_SYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * Set SyncGO bit to synchronously trigger a bank switch for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * all the masters. A write to SYNCGO bit clears CMDSYNC bit for all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * the Masters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) sync_reg |= SDW_SHIM_SYNC_SYNCGO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ret = intel_clear_bit(shim, SDW_SHIM_SYNC, sync_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) SDW_SHIM_SYNC_SYNCGO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) dev_err(sdw->cdns.dev, "SyncGO clear failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) static int intel_shim_sync_go(struct sdw_intel *sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) mutex_lock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) ret = intel_shim_sync_go_unlocked(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) mutex_unlock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * PDI routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static void intel_pdi_init(struct sdw_intel *sdw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) struct sdw_cdns_stream_config *config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) void __iomem *shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) unsigned int link_id = sdw->instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) int pcm_cap, pdm_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) /* PCM Stream Capability */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) pcm_cap = intel_readw(shim, SDW_SHIM_PCMSCAP(link_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) config->pcm_bd = FIELD_GET(SDW_SHIM_PCMSCAP_BSS, pcm_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) config->pcm_in = FIELD_GET(SDW_SHIM_PCMSCAP_ISS, pcm_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) config->pcm_out = FIELD_GET(SDW_SHIM_PCMSCAP_OSS, pcm_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) dev_dbg(sdw->cdns.dev, "PCM cap bd:%d in:%d out:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) config->pcm_bd, config->pcm_in, config->pcm_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /* PDM Stream Capability */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) pdm_cap = intel_readw(shim, SDW_SHIM_PDMSCAP(link_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) config->pdm_bd = FIELD_GET(SDW_SHIM_PDMSCAP_BSS, pdm_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) config->pdm_in = FIELD_GET(SDW_SHIM_PDMSCAP_ISS, pdm_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) config->pdm_out = FIELD_GET(SDW_SHIM_PDMSCAP_OSS, pdm_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) dev_dbg(sdw->cdns.dev, "PDM cap bd:%d in:%d out:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) config->pdm_bd, config->pdm_in, config->pdm_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) intel_pdi_get_ch_cap(struct sdw_intel *sdw, unsigned int pdi_num, bool pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) void __iomem *shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) unsigned int link_id = sdw->instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (pcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) count = intel_readw(shim, SDW_SHIM_PCMSYCHC(link_id, pdi_num));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * WORKAROUND: on all existing Intel controllers, pdi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * number 2 reports channel count as 1 even though it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * supports 8 channels. Performing hardcoding for pdi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * number 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (pdi_num == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) count = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) count = intel_readw(shim, SDW_SHIM_PDMSCAP(link_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) count = FIELD_GET(SDW_SHIM_PDMSCAP_CPSS, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) /* zero based values for channel count in register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) static int intel_pdi_get_ch_update(struct sdw_intel *sdw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) struct sdw_cdns_pdi *pdi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) unsigned int num_pdi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) unsigned int *num_ch, bool pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) int i, ch_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) for (i = 0; i < num_pdi; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) pdi->ch_count = intel_pdi_get_ch_cap(sdw, pdi->num, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) ch_count += pdi->ch_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) pdi++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) *num_ch = ch_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static int intel_pdi_stream_ch_update(struct sdw_intel *sdw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) struct sdw_cdns_streams *stream, bool pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) intel_pdi_get_ch_update(sdw, stream->bd, stream->num_bd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) &stream->num_ch_bd, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) intel_pdi_get_ch_update(sdw, stream->in, stream->num_in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) &stream->num_ch_in, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) intel_pdi_get_ch_update(sdw, stream->out, stream->num_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) &stream->num_ch_out, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static int intel_pdi_ch_update(struct sdw_intel *sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) /* First update PCM streams followed by PDM streams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) intel_pdi_stream_ch_update(sdw, &sdw->cdns.pcm, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) intel_pdi_stream_ch_update(sdw, &sdw->cdns.pdm, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) intel_pdi_shim_configure(struct sdw_intel *sdw, struct sdw_cdns_pdi *pdi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) void __iomem *shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) unsigned int link_id = sdw->instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) int pdi_conf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /* the Bulk and PCM streams are not contiguous */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) pdi->intel_alh_id = (link_id * 16) + pdi->num + 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (pdi->num >= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) pdi->intel_alh_id += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * Program stream parameters to stream SHIM register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * This is applicable for PCM stream only.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (pdi->type != SDW_STREAM_PCM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (pdi->dir == SDW_DATA_DIR_RX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) pdi_conf |= SDW_SHIM_PCMSYCM_DIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) pdi_conf &= ~(SDW_SHIM_PCMSYCM_DIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) u32p_replace_bits(&pdi_conf, pdi->intel_alh_id, SDW_SHIM_PCMSYCM_STREAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) u32p_replace_bits(&pdi_conf, pdi->l_ch_num, SDW_SHIM_PCMSYCM_LCHN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) u32p_replace_bits(&pdi_conf, pdi->h_ch_num, SDW_SHIM_PCMSYCM_HCHN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) intel_writew(shim, SDW_SHIM_PCMSYCHM(link_id, pdi->num), pdi_conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) intel_pdi_alh_configure(struct sdw_intel *sdw, struct sdw_cdns_pdi *pdi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) void __iomem *alh = sdw->link_res->alh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) unsigned int link_id = sdw->instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) unsigned int conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) /* the Bulk and PCM streams are not contiguous */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) pdi->intel_alh_id = (link_id * 16) + pdi->num + 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (pdi->num >= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) pdi->intel_alh_id += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /* Program Stream config ALH register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) conf = intel_readl(alh, SDW_ALH_STRMZCFG(pdi->intel_alh_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) u32p_replace_bits(&conf, SDW_ALH_STRMZCFG_DMAT_VAL, SDW_ALH_STRMZCFG_DMAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) u32p_replace_bits(&conf, pdi->ch_count - 1, SDW_ALH_STRMZCFG_CHN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) intel_writel(alh, SDW_ALH_STRMZCFG(pdi->intel_alh_id), conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) static int intel_params_stream(struct sdw_intel *sdw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) struct snd_soc_dai *dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) struct snd_pcm_hw_params *hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) int link_id, int alh_stream_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) struct sdw_intel_link_res *res = sdw->link_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) struct sdw_intel_stream_params_data params_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) params_data.substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) params_data.dai = dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) params_data.hw_params = hw_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) params_data.link_id = link_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) params_data.alh_stream_id = alh_stream_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (res->ops && res->ops->params_stream && res->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return res->ops->params_stream(res->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) ¶ms_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) static int intel_free_stream(struct sdw_intel *sdw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) struct snd_soc_dai *dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) int link_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) struct sdw_intel_link_res *res = sdw->link_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) struct sdw_intel_stream_free_data free_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) free_data.substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) free_data.dai = dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) free_data.link_id = link_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (res->ops && res->ops->free_stream && res->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return res->ops->free_stream(res->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) &free_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * bank switch routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static int intel_pre_bank_switch(struct sdw_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) struct sdw_cdns *cdns = bus_to_cdns(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) struct sdw_intel *sdw = cdns_to_intel(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) /* Write to register only for multi-link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (!bus->multi_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) intel_shim_sync_arm(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) static int intel_post_bank_switch(struct sdw_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct sdw_cdns *cdns = bus_to_cdns(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) struct sdw_intel *sdw = cdns_to_intel(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) void __iomem *shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) int sync_reg, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) /* Write to register only for multi-link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (!bus->multi_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) mutex_lock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) /* Read SYNC register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) sync_reg = intel_readl(shim, SDW_SHIM_SYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) * post_bank_switch() ops is called from the bus in loop for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) * all the Masters in the steam with the expectation that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) * we trigger the bankswitch for the only first Master in the list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) * and do nothing for the other Masters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * So, set the SYNCGO bit only if CMDSYNC bit is set for any Master.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (!(sync_reg & SDW_SHIM_SYNC_CMDSYNC_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) ret = intel_shim_sync_go_unlocked(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) mutex_unlock(sdw->link_res->shim_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) dev_err(sdw->cdns.dev, "Post bank switch failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) * DAI routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) static int intel_startup(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) ret = pm_runtime_get_sync(cdns->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (ret < 0 && ret != -EACCES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) dev_err_ratelimited(cdns->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) "pm_runtime_get_sync failed in %s, ret %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) pm_runtime_put_noidle(cdns->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) static int intel_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) struct sdw_intel *sdw = cdns_to_intel(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) struct sdw_cdns_dma_data *dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) struct sdw_cdns_pdi *pdi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) struct sdw_stream_config sconfig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) struct sdw_port_config *pconfig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) int ch, dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) bool pcm = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) dma = snd_soc_dai_get_dma_data(dai, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (!dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) ch = params_channels(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) dir = SDW_DATA_DIR_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) dir = SDW_DATA_DIR_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (dma->stream_type == SDW_STREAM_PDM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) pcm = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) pdi = sdw_cdns_alloc_pdi(cdns, &cdns->pcm, ch, dir, dai->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) pdi = sdw_cdns_alloc_pdi(cdns, &cdns->pdm, ch, dir, dai->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (!pdi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /* do run-time configurations for SHIM, ALH and PDI/PORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) intel_pdi_shim_configure(sdw, pdi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) intel_pdi_alh_configure(sdw, pdi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) sdw_cdns_config_stream(cdns, ch, dir, pdi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) /* store pdi and hw_params, may be needed in prepare step */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) dma->suspended = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) dma->pdi = pdi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) dma->hw_params = params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /* Inform DSP about PDI stream number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) ret = intel_params_stream(sdw, substream, dai, params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) sdw->instance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) pdi->intel_alh_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) sconfig.direction = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) sconfig.ch_count = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) sconfig.frame_rate = params_rate(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) sconfig.type = dma->stream_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (dma->stream_type == SDW_STREAM_PDM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) sconfig.frame_rate *= 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) sconfig.bps = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) sconfig.bps = snd_pcm_format_width(params_format(params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) /* Port configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) pconfig = kcalloc(1, sizeof(*pconfig), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (!pconfig) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) pconfig->num = pdi->num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) pconfig->ch_mask = (1 << ch) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) ret = sdw_stream_add_master(&cdns->bus, &sconfig,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) pconfig, 1, dma->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) dev_err(cdns->dev, "add master to stream failed:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) kfree(pconfig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) static int intel_prepare(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct sdw_intel *sdw = cdns_to_intel(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct sdw_cdns_dma_data *dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) int ch, dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) dma = snd_soc_dai_get_dma_data(dai, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (!dma) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) dev_err(dai->dev, "failed to get dma data in %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (dma->suspended) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) dma->suspended = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * .prepare() is called after system resume, where we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * need to reinitialize the SHIM/ALH/Cadence IP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) * .prepare() is also called to deal with underflows,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * but in those cases we cannot touch ALH/SHIM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) * registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) /* configure stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) ch = params_channels(dma->hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) dir = SDW_DATA_DIR_RX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) dir = SDW_DATA_DIR_TX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) intel_pdi_shim_configure(sdw, dma->pdi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) intel_pdi_alh_configure(sdw, dma->pdi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) sdw_cdns_config_stream(cdns, ch, dir, dma->pdi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) /* Inform DSP about PDI stream number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) ret = intel_params_stream(sdw, substream, dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) dma->hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) sdw->instance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) dma->pdi->intel_alh_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) struct sdw_intel *sdw = cdns_to_intel(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) struct sdw_cdns_dma_data *dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) dma = snd_soc_dai_get_dma_data(dai, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (!dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) * The sdw stream state will transition to RELEASED when stream->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) * master_list is empty. So the stream state will transition to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) * DEPREPARED for the first cpu-dai and to RELEASED for the last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) * cpu-dai.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) ret = sdw_stream_remove_master(&cdns->bus, dma->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) dev_err(dai->dev, "remove master from stream %s failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) dma->stream->name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) ret = intel_free_stream(sdw, substream, dai, sdw->instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) dev_err(dai->dev, "intel_free_stream: failed %d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) dma->hw_params = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) dma->pdi = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) static void intel_shutdown(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) pm_runtime_mark_last_busy(cdns->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) pm_runtime_put_autosuspend(cdns->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) static int intel_component_dais_suspend(struct snd_soc_component *component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) struct sdw_cdns_dma_data *dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) struct snd_soc_dai *dai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) for_each_component_dais(component, dai) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) * we don't have a .suspend dai_ops, and we don't have access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) * to the substream, so let's mark both capture and playback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) * DMA contexts as suspended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) dma = dai->playback_dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) dma->suspended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) dma = dai->capture_dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) dma->suspended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) static int intel_pcm_set_sdw_stream(struct snd_soc_dai *dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) void *stream, int direction)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return cdns_set_sdw_stream(dai, stream, true, direction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) static int intel_pdm_set_sdw_stream(struct snd_soc_dai *dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) void *stream, int direction)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) return cdns_set_sdw_stream(dai, stream, false, direction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) static void *intel_get_sdw_stream(struct snd_soc_dai *dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) int direction)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) struct sdw_cdns_dma_data *dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) if (direction == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) dma = dai->playback_dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) dma = dai->capture_dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (!dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) return dma->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) static const struct snd_soc_dai_ops intel_pcm_dai_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) .startup = intel_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) .hw_params = intel_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) .prepare = intel_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) .hw_free = intel_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) .shutdown = intel_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) .set_sdw_stream = intel_pcm_set_sdw_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) .get_sdw_stream = intel_get_sdw_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) static const struct snd_soc_dai_ops intel_pdm_dai_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) .startup = intel_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) .hw_params = intel_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) .prepare = intel_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) .hw_free = intel_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) .shutdown = intel_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) .set_sdw_stream = intel_pdm_set_sdw_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) .get_sdw_stream = intel_get_sdw_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) static const struct snd_soc_component_driver dai_component = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) .name = "soundwire",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) .suspend = intel_component_dais_suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) static int intel_create_dai(struct sdw_cdns *cdns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) struct snd_soc_dai_driver *dais,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) enum intel_pdi_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) u32 num, u32 off, u32 max_ch, bool pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) if (num == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) /* TODO: Read supported rates/formats from hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) for (i = off; i < (off + num); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) dais[i].name = devm_kasprintf(cdns->dev, GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) "SDW%d Pin%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) cdns->instance, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) if (!dais[i].name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (type == INTEL_PDI_BD || type == INTEL_PDI_OUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) dais[i].playback.channels_min = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) dais[i].playback.channels_max = max_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) dais[i].playback.rates = SNDRV_PCM_RATE_48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) dais[i].playback.formats = SNDRV_PCM_FMTBIT_S16_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (type == INTEL_PDI_BD || type == INTEL_PDI_IN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) dais[i].capture.channels_min = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) dais[i].capture.channels_max = max_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) dais[i].capture.rates = SNDRV_PCM_RATE_48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) dais[i].capture.formats = SNDRV_PCM_FMTBIT_S16_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) dais[i].ops = &intel_pcm_dai_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) dais[i].ops = &intel_pdm_dai_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) static int intel_register_dai(struct sdw_intel *sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) struct sdw_cdns *cdns = &sdw->cdns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) struct sdw_cdns_streams *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) struct snd_soc_dai_driver *dais;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) int num_dai, ret, off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) /* DAIs are created based on total number of PDIs supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) num_dai = cdns->pcm.num_pdi + cdns->pdm.num_pdi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) dais = devm_kcalloc(cdns->dev, num_dai, sizeof(*dais), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (!dais)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) /* Create PCM DAIs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) stream = &cdns->pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) ret = intel_create_dai(cdns, dais, INTEL_PDI_IN, cdns->pcm.num_in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) off, stream->num_ch_in, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) off += cdns->pcm.num_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) ret = intel_create_dai(cdns, dais, INTEL_PDI_OUT, cdns->pcm.num_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) off, stream->num_ch_out, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) off += cdns->pcm.num_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) ret = intel_create_dai(cdns, dais, INTEL_PDI_BD, cdns->pcm.num_bd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) off, stream->num_ch_bd, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) /* Create PDM DAIs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) stream = &cdns->pdm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) off += cdns->pcm.num_bd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) ret = intel_create_dai(cdns, dais, INTEL_PDI_IN, cdns->pdm.num_in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) off, stream->num_ch_in, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) off += cdns->pdm.num_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) ret = intel_create_dai(cdns, dais, INTEL_PDI_OUT, cdns->pdm.num_out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) off, stream->num_ch_out, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) off += cdns->pdm.num_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) ret = intel_create_dai(cdns, dais, INTEL_PDI_BD, cdns->pdm.num_bd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) off, stream->num_ch_bd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) return snd_soc_register_component(cdns->dev, &dai_component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) dais, num_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) static int sdw_master_read_intel_prop(struct sdw_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) struct sdw_master_prop *prop = &bus->prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) struct fwnode_handle *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) char name[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) u32 quirk_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) /* Find master handle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) snprintf(name, sizeof(name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) "mipi-sdw-link-%d-subproperties", bus->link_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) link = device_get_named_child_node(bus->dev, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) if (!link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) dev_err(bus->dev, "Master node %s not found\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) fwnode_property_read_u32(link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) "intel-sdw-ip-clock",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) &prop->mclk_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) /* the values reported by BIOS are the 2x clock, not the bus clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) prop->mclk_freq /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) fwnode_property_read_u32(link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) "intel-quirk-mask",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) &quirk_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) if (quirk_mask & SDW_INTEL_QUIRK_MASK_BUS_DISABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) prop->hw_disabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) static int intel_prop_read(struct sdw_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) /* Initialize with default handler to read all DisCo properties */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) sdw_master_read_prop(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) /* read Intel-specific properties */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) sdw_master_read_intel_prop(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) static struct sdw_master_ops sdw_intel_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) .read_prop = sdw_master_read_prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) .xfer_msg = cdns_xfer_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) .xfer_msg_defer = cdns_xfer_msg_defer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) .reset_page_addr = cdns_reset_page_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) .set_bus_conf = cdns_bus_conf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) .pre_bank_switch = intel_pre_bank_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) .post_bank_switch = intel_post_bank_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) static int intel_init(struct sdw_intel *sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) bool clock_stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) /* Initialize shim and controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) intel_link_power_up(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) clock_stop = sdw_cdns_is_clock_stop(&sdw->cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) intel_shim_init(sdw, clock_stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) * probe and init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) static int intel_master_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) struct sdw_intel *sdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) struct sdw_cdns *cdns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) struct sdw_bus *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) sdw = devm_kzalloc(dev, sizeof(*sdw), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (!sdw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) cdns = &sdw->cdns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) bus = &cdns->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) sdw->instance = pdev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) sdw->link_res = dev_get_platdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) cdns->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) cdns->registers = sdw->link_res->registers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) cdns->instance = sdw->instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) cdns->msg_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) bus->link_id = pdev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) sdw_cdns_probe(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) /* Set property read ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) sdw_intel_ops.read_prop = intel_prop_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) bus->ops = &sdw_intel_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) /* set driver data, accessed by snd_soc_dai_get_drvdata() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) dev_set_drvdata(dev, cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) /* use generic bandwidth allocation algorithm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) sdw->cdns.bus.compute_params = sdw_compute_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) ret = sdw_bus_master_add(bus, dev, dev->fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) dev_err(dev, "sdw_bus_master_add fail: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if (bus->prop.hw_disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) dev_info(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) "SoundWire master %d is disabled, will be ignored\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) bus->link_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) * Ignore BIOS err_threshold, it's a really bad idea when dealing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * with multiple hardware synchronized links
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) bus->prop.err_threshold = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) int intel_master_startup(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) struct sdw_cdns_stream_config config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) struct sdw_cdns *cdns = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) struct sdw_intel *sdw = cdns_to_intel(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) struct sdw_bus *bus = &cdns->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) int link_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) bool multi_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) u32 clock_stop_quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) if (bus->prop.hw_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) dev_info(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) "SoundWire master %d is disabled, ignoring\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) sdw->instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) link_flags = md_flags >> (bus->link_id * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) multi_link = !(link_flags & SDW_INTEL_MASTER_DISABLE_MULTI_LINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) if (!multi_link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) dev_dbg(dev, "Multi-link is disabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) bus->multi_link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) * hardware-based synchronization is required regardless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) * of the number of segments used by a stream: SSP-based
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) * synchronization is gated by gsync when the multi-master
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) * mode is set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) bus->multi_link = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) bus->hw_sync_min_links = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) /* Initialize shim, controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) ret = intel_init(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) goto err_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) /* Read the PDI config and initialize cadence PDI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) intel_pdi_init(sdw, &config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) ret = sdw_cdns_pdi_init(cdns, config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) goto err_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) intel_pdi_ch_update(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) ret = sdw_cdns_enable_interrupt(cdns, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) dev_err(dev, "cannot enable interrupts\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) goto err_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) * follow recommended programming flows to avoid timeouts when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) * gsync is enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) if (multi_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) intel_shim_sync_arm(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) ret = sdw_cdns_init(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) dev_err(dev, "unable to initialize Cadence IP\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) goto err_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) ret = sdw_cdns_exit_reset(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) dev_err(dev, "unable to exit bus reset sequence\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) goto err_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) if (multi_link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) ret = intel_shim_sync_go(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) dev_err(dev, "sync go failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) goto err_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) /* Register DAIs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) ret = intel_register_dai(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) dev_err(dev, "DAI registration failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) snd_soc_unregister_component(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) goto err_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) intel_debugfs_init(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) /* Enable runtime PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) if (!(link_flags & SDW_INTEL_MASTER_DISABLE_PM_RUNTIME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) pm_runtime_set_autosuspend_delay(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) INTEL_MASTER_SUSPEND_DELAY_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) pm_runtime_use_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) pm_runtime_set_active(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) pm_runtime_enable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) clock_stop_quirks = sdw->link_res->clock_stop_quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) if (clock_stop_quirks & SDW_INTEL_CLK_STOP_NOT_ALLOWED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) * To keep the clock running we need to prevent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) * pm_runtime suspend from happening by increasing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) * reference count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) * This quirk is specified by the parent PCI device in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) * case of specific latency requirements. It will have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) * no effect if pm_runtime is disabled by the user via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) * a module parameter for testing purposes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) pm_runtime_get_noresume(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) * The runtime PM status of Slave devices is "Unsupported"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) * until they report as ATTACHED. If they don't, e.g. because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) * there are no Slave devices populated or if the power-on is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) * delayed or dependent on a power switch, the Master will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) * remain active and prevent its parent from suspending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) * Conditionally force the pm_runtime core to re-evaluate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) * Master status in the absence of any Slave activity. A quirk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) * is provided to e.g. deal with Slaves that may be powered on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) * with a delay. A more complete solution would require the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) * definition of Master properties.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) if (!(link_flags & SDW_INTEL_MASTER_DISABLE_PM_RUNTIME_IDLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) pm_runtime_idle(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) err_interrupt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) sdw_cdns_enable_interrupt(cdns, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) err_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) static int intel_master_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) struct sdw_cdns *cdns = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) struct sdw_intel *sdw = cdns_to_intel(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) struct sdw_bus *bus = &cdns->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) * Since pm_runtime is already disabled, we don't decrease
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) * the refcount when the clock_stop_quirk is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) * SDW_INTEL_CLK_STOP_NOT_ALLOWED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) if (!bus->prop.hw_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) intel_debugfs_exit(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) sdw_cdns_enable_interrupt(cdns, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) snd_soc_unregister_component(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) sdw_bus_master_delete(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) int intel_master_process_wakeen_event(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) struct sdw_intel *sdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) struct sdw_bus *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) void __iomem *shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) u16 wake_sts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) sdw = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) bus = &sdw->cdns.bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) if (bus->prop.hw_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n", bus->link_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) shim = sdw->link_res->shim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) wake_sts = intel_readw(shim, SDW_SHIM_WAKESTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) if (!(wake_sts & BIT(sdw->instance)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) /* disable WAKEEN interrupt ASAP to prevent interrupt flood */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) intel_shim_wake(sdw, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) * resume the Master, which will generate a bus reset and result in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) * Slaves re-attaching and be re-enumerated. The SoundWire physical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) * device which generated the wake will trigger an interrupt, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) * will in turn cause the corresponding Linux Slave device to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) * resumed and the Slave codec driver to check the status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) pm_request_resume(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) * PM calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) static int __maybe_unused intel_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) struct sdw_cdns *cdns = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) struct sdw_intel *sdw = cdns_to_intel(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) struct sdw_bus *bus = &cdns->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) u32 clock_stop_quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) if (bus->prop.hw_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) bus->link_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) if (pm_runtime_suspended(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) dev_dbg(dev, "%s: pm_runtime status: suspended\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) clock_stop_quirks = sdw->link_res->clock_stop_quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) if ((clock_stop_quirks & SDW_INTEL_CLK_STOP_BUS_RESET ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) !clock_stop_quirks) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) !pm_runtime_suspended(dev->parent)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) * if we've enabled clock stop, and the parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) * is still active, disable shim wake. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) * SHIM registers are not accessible if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) * parent is already pm_runtime suspended so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) * it's too late to change that configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) intel_shim_wake(sdw, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) ret = sdw_cdns_enable_interrupt(cdns, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) dev_err(dev, "cannot disable interrupts on suspend\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) ret = intel_link_power_down(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) dev_err(dev, "Link power down failed: %d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) intel_shim_wake(sdw, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) static int intel_suspend_runtime(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) struct sdw_cdns *cdns = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) struct sdw_intel *sdw = cdns_to_intel(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) struct sdw_bus *bus = &cdns->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) u32 clock_stop_quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) if (bus->prop.hw_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) bus->link_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) clock_stop_quirks = sdw->link_res->clock_stop_quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) if (clock_stop_quirks & SDW_INTEL_CLK_STOP_TEARDOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) ret = sdw_cdns_enable_interrupt(cdns, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) dev_err(dev, "cannot disable interrupts on suspend\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) ret = intel_link_power_down(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) dev_err(dev, "Link power down failed: %d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) intel_shim_wake(sdw, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) } else if (clock_stop_quirks & SDW_INTEL_CLK_STOP_BUS_RESET ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) !clock_stop_quirks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) ret = sdw_cdns_clock_stop(cdns, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) dev_err(dev, "cannot enable clock stop on suspend\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) ret = sdw_cdns_enable_interrupt(cdns, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) dev_err(dev, "cannot disable interrupts on suspend\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) ret = intel_link_power_down(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) dev_err(dev, "Link power down failed: %d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) intel_shim_wake(sdw, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) dev_err(dev, "%s clock_stop_quirks %x unsupported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) __func__, clock_stop_quirks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) static int __maybe_unused intel_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) struct sdw_cdns *cdns = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) struct sdw_intel *sdw = cdns_to_intel(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) struct sdw_bus *bus = &cdns->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) int link_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) bool multi_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) if (bus->prop.hw_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) bus->link_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) link_flags = md_flags >> (bus->link_id * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) multi_link = !(link_flags & SDW_INTEL_MASTER_DISABLE_MULTI_LINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) if (pm_runtime_suspended(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) dev_dbg(dev, "%s: pm_runtime status was suspended, forcing active\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) /* follow required sequence from runtime_pm.rst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) pm_runtime_disable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) pm_runtime_set_active(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) pm_runtime_enable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) link_flags = md_flags >> (bus->link_id * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) if (!(link_flags & SDW_INTEL_MASTER_DISABLE_PM_RUNTIME_IDLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) pm_runtime_idle(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) ret = intel_init(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) dev_err(dev, "%s failed: %d", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) * make sure all Slaves are tagged as UNATTACHED and provide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) * reason for reinitialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) sdw_clear_slave_status(bus, SDW_UNATTACH_REQUEST_MASTER_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) ret = sdw_cdns_enable_interrupt(cdns, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) dev_err(dev, "cannot enable interrupts during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) * follow recommended programming flows to avoid timeouts when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) * gsync is enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) if (multi_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) intel_shim_sync_arm(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) ret = sdw_cdns_init(&sdw->cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) dev_err(dev, "unable to initialize Cadence IP during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) ret = sdw_cdns_exit_reset(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) dev_err(dev, "unable to exit bus reset sequence during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) if (multi_link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) ret = intel_shim_sync_go(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) dev_err(dev, "sync go failed during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) * after system resume, the pm_runtime suspend() may kick in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) * during the enumeration, before any children device force the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) * master device to remain active. Using pm_runtime_get()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) * routines is not really possible, since it'd prevent the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) * master from suspending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) * A reasonable compromise is to update the pm_runtime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) * counters and delay the pm_runtime suspend by several
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) * seconds, by when all enumeration should be complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) pm_runtime_mark_last_busy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) static int intel_resume_runtime(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) struct sdw_cdns *cdns = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) struct sdw_intel *sdw = cdns_to_intel(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) struct sdw_bus *bus = &cdns->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) u32 clock_stop_quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) bool clock_stop0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) int link_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) bool multi_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) if (bus->prop.hw_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) bus->link_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) link_flags = md_flags >> (bus->link_id * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) multi_link = !(link_flags & SDW_INTEL_MASTER_DISABLE_MULTI_LINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) clock_stop_quirks = sdw->link_res->clock_stop_quirks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) if (clock_stop_quirks & SDW_INTEL_CLK_STOP_TEARDOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) ret = intel_init(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) dev_err(dev, "%s failed: %d", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) * make sure all Slaves are tagged as UNATTACHED and provide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) * reason for reinitialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) sdw_clear_slave_status(bus, SDW_UNATTACH_REQUEST_MASTER_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) ret = sdw_cdns_enable_interrupt(cdns, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) dev_err(dev, "cannot enable interrupts during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) * follow recommended programming flows to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) * timeouts when gsync is enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) if (multi_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) intel_shim_sync_arm(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) ret = sdw_cdns_init(&sdw->cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) dev_err(dev, "unable to initialize Cadence IP during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) ret = sdw_cdns_exit_reset(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) dev_err(dev, "unable to exit bus reset sequence during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) if (multi_link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) ret = intel_shim_sync_go(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) dev_err(dev, "sync go failed during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) } else if (clock_stop_quirks & SDW_INTEL_CLK_STOP_BUS_RESET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) ret = intel_init(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) dev_err(dev, "%s failed: %d", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) * An exception condition occurs for the CLK_STOP_BUS_RESET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) * case if one or more masters remain active. In this condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) * all the masters are powered on for they are in the same power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) * domain. Master can preserve its context for clock stop0, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) * there is no need to clear slave status and reset bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) clock_stop0 = sdw_cdns_is_clock_stop(&sdw->cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) if (!clock_stop0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) * make sure all Slaves are tagged as UNATTACHED and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) * provide reason for reinitialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) status = SDW_UNATTACH_REQUEST_MASTER_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) sdw_clear_slave_status(bus, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) ret = sdw_cdns_enable_interrupt(cdns, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) dev_err(dev, "cannot enable interrupts during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) * follow recommended programming flows to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) * timeouts when gsync is enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) if (multi_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) intel_shim_sync_arm(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) * Re-initialize the IP since it was powered-off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) sdw_cdns_init(&sdw->cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) ret = sdw_cdns_enable_interrupt(cdns, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) dev_err(dev, "cannot enable interrupts during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) ret = sdw_cdns_clock_restart(cdns, !clock_stop0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) dev_err(dev, "unable to restart clock during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) if (!clock_stop0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) ret = sdw_cdns_exit_reset(cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) dev_err(dev, "unable to exit bus reset sequence during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) if (multi_link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) ret = intel_shim_sync_go(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) dev_err(sdw->cdns.dev, "sync go failed during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) } else if (!clock_stop_quirks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) clock_stop0 = sdw_cdns_is_clock_stop(&sdw->cdns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) if (!clock_stop0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) dev_err(dev, "%s invalid configuration, clock was not stopped", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) ret = intel_init(sdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) dev_err(dev, "%s failed: %d", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) ret = sdw_cdns_enable_interrupt(cdns, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) dev_err(dev, "cannot enable interrupts during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) ret = sdw_cdns_clock_restart(cdns, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) dev_err(dev, "unable to resume master during resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) dev_err(dev, "%s clock_stop_quirks %x unsupported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) __func__, clock_stop_quirks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) static const struct dev_pm_ops intel_pm = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) SET_SYSTEM_SLEEP_PM_OPS(intel_suspend, intel_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) SET_RUNTIME_PM_OPS(intel_suspend_runtime, intel_resume_runtime, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) static struct platform_driver sdw_intel_drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) .probe = intel_master_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) .remove = intel_master_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) .name = "intel-sdw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) .pm = &intel_pm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) module_platform_driver(sdw_intel_drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) MODULE_LICENSE("Dual BSD/GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) MODULE_ALIAS("platform:intel-sdw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) MODULE_DESCRIPTION("Intel Soundwire Master Driver");