18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * ALSA SoC CPCAP codec driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2017 - 2018 Sebastian Reichel <sre@kernel.org>
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Very loosely based on original driver from Motorola:
88c2ecf20Sopenharmony_ci * Copyright (C) 2007 - 2009 Motorola, Inc.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/regmap.h>
138c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
148c2ecf20Sopenharmony_ci#include <linux/mfd/motorola-cpcap.h>
158c2ecf20Sopenharmony_ci#include <sound/core.h>
168c2ecf20Sopenharmony_ci#include <sound/soc.h>
178c2ecf20Sopenharmony_ci#include <sound/tlv.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/* Register 513 CPCAP_REG_CC     --- CODEC */
208c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_CLK2                15
218c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_CLK1                14
228c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_CLK0                13
238c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_SR3                 12
248c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_SR2                 11
258c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_SR1                 10
268c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_SR0                 9
278c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_CLOCK_TREE_RESET    8
288c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC2_CDC_EN             7
298c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_EN_RX               6
308c2ecf20Sopenharmony_ci#define CPCAP_BIT_DF_RESET                5
318c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC1_CDC_EN             4
328c2ecf20Sopenharmony_ci#define CPCAP_BIT_AUDOHPF_1		  3
338c2ecf20Sopenharmony_ci#define CPCAP_BIT_AUDOHPF_0		  2
348c2ecf20Sopenharmony_ci#define CPCAP_BIT_AUDIHPF_1		  1
358c2ecf20Sopenharmony_ci#define CPCAP_BIT_AUDIHPF_0		  0
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/* Register 514 CPCAP_REG_CDI    --- CODEC Digital Audio Interface */
388c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_PLL_SEL             15
398c2ecf20Sopenharmony_ci#define CPCAP_BIT_CLK_IN_SEL              13
408c2ecf20Sopenharmony_ci#define CPCAP_BIT_DIG_AUD_IN              12
418c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_CLK_EN              11
428c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_DIG_AUD_FS1         10
438c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_DIG_AUD_FS0         9
448c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC2_TIMESLOT2          8
458c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC2_TIMESLOT1          7
468c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC2_TIMESLOT0          6
478c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC1_RX_TIMESLOT2       5
488c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC1_RX_TIMESLOT1       4
498c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC1_RX_TIMESLOT0       3
508c2ecf20Sopenharmony_ci#define CPCAP_BIT_FS_INV                  2
518c2ecf20Sopenharmony_ci#define CPCAP_BIT_CLK_INV                 1
528c2ecf20Sopenharmony_ci#define CPCAP_BIT_SMB_CDC                 0
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/* Register 515 CPCAP_REG_SDAC   --- Stereo DAC */
558c2ecf20Sopenharmony_ci#define CPCAP_BIT_FSYNC_CLK_IN_COMMON     11
568c2ecf20Sopenharmony_ci#define CPCAP_BIT_SLAVE_PLL_CLK_INPUT     10
578c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_CLOCK_TREE_RESET     9
588c2ecf20Sopenharmony_ci#define CPCAP_BIT_DF_RESET_ST_DAC         8
598c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_SR3                  7
608c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_SR2                  6
618c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_SR1                  5
628c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_SR0                  4
638c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_DAC_CLK2             3
648c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_DAC_CLK1             2
658c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_DAC_CLK0             1
668c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_DAC_EN               0
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci/* Register 516 CPCAP_REG_SDACDI --- Stereo DAC Digital Audio Interface */
698c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_L_TIMESLOT2          13
708c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_L_TIMESLOT1          12
718c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_L_TIMESLOT0          11
728c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_R_TIMESLOT2          10
738c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_R_TIMESLOT1          9
748c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_R_TIMESLOT0          8
758c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_DAC_CLK_IN_SEL       7
768c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_FS_INV               6
778c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_CLK_INV              5
788c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_DIG_AUD_FS1          4
798c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_DIG_AUD_FS0          3
808c2ecf20Sopenharmony_ci#define CPCAP_BIT_DIG_AUD_IN_ST_DAC       2
818c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_CLK_EN               1
828c2ecf20Sopenharmony_ci#define CPCAP_BIT_SMB_ST_DAC              0
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/* Register 517 CPCAP_REG_TXI    --- TX Interface */
858c2ecf20Sopenharmony_ci#define CPCAP_BIT_PTT_TH		15
868c2ecf20Sopenharmony_ci#define CPCAP_BIT_PTT_CMP_EN		14
878c2ecf20Sopenharmony_ci#define CPCAP_BIT_HS_ID_TX		13
888c2ecf20Sopenharmony_ci#define CPCAP_BIT_MB_ON2		12
898c2ecf20Sopenharmony_ci#define CPCAP_BIT_MB_ON1L		11
908c2ecf20Sopenharmony_ci#define CPCAP_BIT_MB_ON1R		10
918c2ecf20Sopenharmony_ci#define CPCAP_BIT_RX_L_ENCODE		9
928c2ecf20Sopenharmony_ci#define CPCAP_BIT_RX_R_ENCODE		8
938c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC2_MUX		7
948c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC2_PGA_EN		6
958c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDET_DIS		5
968c2ecf20Sopenharmony_ci#define CPCAP_BIT_EMU_MIC_MUX		4
978c2ecf20Sopenharmony_ci#define CPCAP_BIT_HS_MIC_MUX		3
988c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC1_MUX		2
998c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC1_PGA_EN		1
1008c2ecf20Sopenharmony_ci#define CPCAP_BIT_DLM			0
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci/* Register 518 CPCAP_REG_TXMP   --- Mic Gain */
1038c2ecf20Sopenharmony_ci#define CPCAP_BIT_MB_BIAS_R1              11
1048c2ecf20Sopenharmony_ci#define CPCAP_BIT_MB_BIAS_R0              10
1058c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC2_GAIN_4             9
1068c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC2_GAIN_3             8
1078c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC2_GAIN_2             7
1088c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC2_GAIN_1             6
1098c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC2_GAIN_0             5
1108c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC1_GAIN_4             4
1118c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC1_GAIN_3             3
1128c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC1_GAIN_2             2
1138c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC1_GAIN_1             1
1148c2ecf20Sopenharmony_ci#define CPCAP_BIT_MIC1_GAIN_0             0
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci/* Register 519 CPCAP_REG_RXOA   --- RX Output Amplifier */
1178c2ecf20Sopenharmony_ci#define CPCAP_BIT_UNUSED_519_15		15
1188c2ecf20Sopenharmony_ci#define CPCAP_BIT_UNUSED_519_14		14
1198c2ecf20Sopenharmony_ci#define CPCAP_BIT_UNUSED_519_13		13
1208c2ecf20Sopenharmony_ci#define CPCAP_BIT_STDAC_LOW_PWR_DISABLE	12
1218c2ecf20Sopenharmony_ci#define CPCAP_BIT_HS_LOW_PWR		11
1228c2ecf20Sopenharmony_ci#define CPCAP_BIT_HS_ID_RX		10
1238c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_HS_CP_EN		9
1248c2ecf20Sopenharmony_ci#define CPCAP_BIT_EMU_SPKR_R_EN		8
1258c2ecf20Sopenharmony_ci#define CPCAP_BIT_EMU_SPKR_L_EN		7
1268c2ecf20Sopenharmony_ci#define CPCAP_BIT_HS_L_EN		6
1278c2ecf20Sopenharmony_ci#define CPCAP_BIT_HS_R_EN		5
1288c2ecf20Sopenharmony_ci#define CPCAP_BIT_A4_LINEOUT_L_EN	4
1298c2ecf20Sopenharmony_ci#define CPCAP_BIT_A4_LINEOUT_R_EN	3
1308c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_LDSP_L_EN		2
1318c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_LDSP_R_EN		1
1328c2ecf20Sopenharmony_ci#define CPCAP_BIT_A1_EAR_EN		0
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci/* Register 520 CPCAP_REG_RXVC   --- RX Volume Control */
1358c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_EXT3                15
1368c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_EXT2                14
1378c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_EXT1                13
1388c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_EXT0                12
1398c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_DAC3                11
1408c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_DAC2                10
1418c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_DAC1                9
1428c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_DAC0                8
1438c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_DAC_LSB_1dB1        7
1448c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_DAC_LSB_1dB0        6
1458c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_CDC3                5
1468c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_CDC2                4
1478c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_CDC1                3
1488c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_CDC0                2
1498c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_CDC_LSB_1dB1        1
1508c2ecf20Sopenharmony_ci#define CPCAP_BIT_VOL_CDC_LSB_1dB0        0
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci/* Register 521 CPCAP_REG_RXCOA  --- Codec to Output Amp Switches */
1538c2ecf20Sopenharmony_ci#define CPCAP_BIT_PGA_CDC_EN              10
1548c2ecf20Sopenharmony_ci#define CPCAP_BIT_CDC_SW                  9
1558c2ecf20Sopenharmony_ci#define CPCAP_BIT_PGA_OUTR_USBDP_CDC_SW   8
1568c2ecf20Sopenharmony_ci#define CPCAP_BIT_PGA_OUTL_USBDN_CDC_SW   7
1578c2ecf20Sopenharmony_ci#define CPCAP_BIT_ALEFT_HS_CDC_SW         6
1588c2ecf20Sopenharmony_ci#define CPCAP_BIT_ARIGHT_HS_CDC_SW        5
1598c2ecf20Sopenharmony_ci#define CPCAP_BIT_A4_LINEOUT_L_CDC_SW     4
1608c2ecf20Sopenharmony_ci#define CPCAP_BIT_A4_LINEOUT_R_CDC_SW     3
1618c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_LDSP_L_CDC_SW        2
1628c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_LDSP_R_CDC_SW        1
1638c2ecf20Sopenharmony_ci#define CPCAP_BIT_A1_EAR_CDC_SW           0
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci/* Register 522 CPCAP_REG_RXSDOA --- RX Stereo DAC to Output Amp Switches */
1668c2ecf20Sopenharmony_ci#define CPCAP_BIT_PGA_DAC_EN              12
1678c2ecf20Sopenharmony_ci#define CPCAP_BIT_ST_DAC_SW               11
1688c2ecf20Sopenharmony_ci#define CPCAP_BIT_MONO_DAC1               10
1698c2ecf20Sopenharmony_ci#define CPCAP_BIT_MONO_DAC0               9
1708c2ecf20Sopenharmony_ci#define CPCAP_BIT_PGA_OUTR_USBDP_DAC_SW   8
1718c2ecf20Sopenharmony_ci#define CPCAP_BIT_PGA_OUTL_USBDN_DAC_SW   7
1728c2ecf20Sopenharmony_ci#define CPCAP_BIT_ALEFT_HS_DAC_SW         6
1738c2ecf20Sopenharmony_ci#define CPCAP_BIT_ARIGHT_HS_DAC_SW        5
1748c2ecf20Sopenharmony_ci#define CPCAP_BIT_A4_LINEOUT_L_DAC_SW     4
1758c2ecf20Sopenharmony_ci#define CPCAP_BIT_A4_LINEOUT_R_DAC_SW     3
1768c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_LDSP_L_DAC_SW        2
1778c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_LDSP_R_DAC_SW        1
1788c2ecf20Sopenharmony_ci#define CPCAP_BIT_A1_EAR_DAC_SW           0
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci/* Register 523 CPCAP_REG_RXEPOA --- RX External PGA to Output Amp Switches */
1818c2ecf20Sopenharmony_ci#define CPCAP_BIT_PGA_EXT_L_EN            14
1828c2ecf20Sopenharmony_ci#define CPCAP_BIT_PGA_EXT_R_EN            13
1838c2ecf20Sopenharmony_ci#define CPCAP_BIT_PGA_IN_L_SW             12
1848c2ecf20Sopenharmony_ci#define CPCAP_BIT_PGA_IN_R_SW             11
1858c2ecf20Sopenharmony_ci#define CPCAP_BIT_MONO_EXT1               10
1868c2ecf20Sopenharmony_ci#define CPCAP_BIT_MONO_EXT0               9
1878c2ecf20Sopenharmony_ci#define CPCAP_BIT_PGA_OUTR_USBDP_EXT_SW   8
1888c2ecf20Sopenharmony_ci#define CPCAP_BIT_PGA_OUTL_USBDN_EXT_SW   7
1898c2ecf20Sopenharmony_ci#define CPCAP_BIT_ALEFT_HS_EXT_SW         6
1908c2ecf20Sopenharmony_ci#define CPCAP_BIT_ARIGHT_HS_EXT_SW        5
1918c2ecf20Sopenharmony_ci#define CPCAP_BIT_A4_LINEOUT_L_EXT_SW     4
1928c2ecf20Sopenharmony_ci#define CPCAP_BIT_A4_LINEOUT_R_EXT_SW     3
1938c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_LDSP_L_EXT_SW        2
1948c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_LDSP_R_EXT_SW        1
1958c2ecf20Sopenharmony_ci#define CPCAP_BIT_A1_EAR_EXT_SW           0
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci/* Register 525 CPCAP_REG_A2LA --- SPK Amplifier and Clock Config for Headset */
1988c2ecf20Sopenharmony_ci#define CPCAP_BIT_NCP_CLK_SYNC            7
1998c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_CLK_SYNC             6
2008c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_FREE_RUN             5
2018c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_CLK2                 4
2028c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_CLK1                 3
2038c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_CLK0                 2
2048c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_CLK_IN               1
2058c2ecf20Sopenharmony_ci#define CPCAP_BIT_A2_CONFIG               0
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci#define SLEEP_ACTIVATE_POWER 2
2088c2ecf20Sopenharmony_ci#define CLOCK_TREE_RESET_TIME 1
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci/* constants for ST delay workaround */
2118c2ecf20Sopenharmony_ci#define STM_STDAC_ACTIVATE_RAMP_TIME   1
2128c2ecf20Sopenharmony_ci#define STM_STDAC_EN_TEST_PRE          0x090C
2138c2ecf20Sopenharmony_ci#define STM_STDAC_EN_TEST_POST         0x0000
2148c2ecf20Sopenharmony_ci#define STM_STDAC_EN_ST_TEST1_PRE      0x2400
2158c2ecf20Sopenharmony_ci#define STM_STDAC_EN_ST_TEST1_POST     0x0400
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistruct cpcap_reg_info {
2188c2ecf20Sopenharmony_ci	u16 reg;
2198c2ecf20Sopenharmony_ci	u16 mask;
2208c2ecf20Sopenharmony_ci	u16 val;
2218c2ecf20Sopenharmony_ci};
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_cistatic const struct cpcap_reg_info cpcap_default_regs[] = {
2248c2ecf20Sopenharmony_ci	{ CPCAP_REG_CC, 0xFFFF, 0x0000 },
2258c2ecf20Sopenharmony_ci	{ CPCAP_REG_CC, 0xFFFF, 0x0000 },
2268c2ecf20Sopenharmony_ci	{ CPCAP_REG_CDI, 0xBFFF, 0x0000 },
2278c2ecf20Sopenharmony_ci	{ CPCAP_REG_SDAC, 0x0FFF, 0x0000 },
2288c2ecf20Sopenharmony_ci	{ CPCAP_REG_SDACDI, 0x3FFF, 0x0000 },
2298c2ecf20Sopenharmony_ci	{ CPCAP_REG_TXI, 0x0FDF, 0x0000 },
2308c2ecf20Sopenharmony_ci	{ CPCAP_REG_TXMP, 0x0FFF, 0x0400 },
2318c2ecf20Sopenharmony_ci	{ CPCAP_REG_RXOA, 0x01FF, 0x0000 },
2328c2ecf20Sopenharmony_ci	{ CPCAP_REG_RXVC, 0xFF3C, 0x0000 },
2338c2ecf20Sopenharmony_ci	{ CPCAP_REG_RXCOA, 0x07FF, 0x0000 },
2348c2ecf20Sopenharmony_ci	{ CPCAP_REG_RXSDOA, 0x1FFF, 0x0000 },
2358c2ecf20Sopenharmony_ci	{ CPCAP_REG_RXEPOA, 0x7FFF, 0x0000 },
2368c2ecf20Sopenharmony_ci	{ CPCAP_REG_A2LA, BIT(CPCAP_BIT_A2_FREE_RUN),
2378c2ecf20Sopenharmony_ci	  BIT(CPCAP_BIT_A2_FREE_RUN) },
2388c2ecf20Sopenharmony_ci};
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_cienum cpcap_dai {
2418c2ecf20Sopenharmony_ci	CPCAP_DAI_HIFI,
2428c2ecf20Sopenharmony_ci	CPCAP_DAI_VOICE,
2438c2ecf20Sopenharmony_ci};
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_cistruct cpcap_audio {
2468c2ecf20Sopenharmony_ci	struct snd_soc_component *component;
2478c2ecf20Sopenharmony_ci	struct regmap *regmap;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	u16 vendor;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	int codec_clk_id;
2528c2ecf20Sopenharmony_ci	int codec_freq;
2538c2ecf20Sopenharmony_ci	int codec_format;
2548c2ecf20Sopenharmony_ci};
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_cistatic int cpcap_st_workaround(struct snd_soc_dapm_widget *w,
2578c2ecf20Sopenharmony_ci			       struct snd_kcontrol *kcontrol, int event)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2608c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
2618c2ecf20Sopenharmony_ci	int err = 0;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	/* Only CPCAP from ST requires workaround */
2648c2ecf20Sopenharmony_ci	if (cpcap->vendor != CPCAP_VENDOR_ST)
2658c2ecf20Sopenharmony_ci		return 0;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	switch (event) {
2688c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
2698c2ecf20Sopenharmony_ci		err = regmap_write(cpcap->regmap, CPCAP_REG_TEST,
2708c2ecf20Sopenharmony_ci				   STM_STDAC_EN_TEST_PRE);
2718c2ecf20Sopenharmony_ci		if (err)
2728c2ecf20Sopenharmony_ci			return err;
2738c2ecf20Sopenharmony_ci		err = regmap_write(cpcap->regmap, CPCAP_REG_ST_TEST1,
2748c2ecf20Sopenharmony_ci				   STM_STDAC_EN_ST_TEST1_PRE);
2758c2ecf20Sopenharmony_ci		break;
2768c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
2778c2ecf20Sopenharmony_ci		msleep(STM_STDAC_ACTIVATE_RAMP_TIME);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci		err = regmap_write(cpcap->regmap, CPCAP_REG_ST_TEST1,
2808c2ecf20Sopenharmony_ci				   STM_STDAC_EN_ST_TEST1_POST);
2818c2ecf20Sopenharmony_ci		if (err)
2828c2ecf20Sopenharmony_ci			return err;
2838c2ecf20Sopenharmony_ci		err = regmap_write(cpcap->regmap, CPCAP_REG_TEST,
2848c2ecf20Sopenharmony_ci				   STM_STDAC_EN_TEST_POST);
2858c2ecf20Sopenharmony_ci		break;
2868c2ecf20Sopenharmony_ci	default:
2878c2ecf20Sopenharmony_ci		break;
2888c2ecf20Sopenharmony_ci	}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	return err;
2918c2ecf20Sopenharmony_ci}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci/* Capture Gain Control: 0dB to 31dB in 1dB steps */
2948c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(mic_gain_tlv, 0, 100, 0);
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci/* Playback Gain Control: -33dB to 12dB in 3dB steps */
2978c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(vol_tlv, -3300, 300, 0);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_snd_controls[] = {
3008c2ecf20Sopenharmony_ci	/* Playback Gain */
3018c2ecf20Sopenharmony_ci	SOC_SINGLE_TLV("HiFi Playback Volume",
3028c2ecf20Sopenharmony_ci		CPCAP_REG_RXVC, CPCAP_BIT_VOL_DAC0, 0xF, 0, vol_tlv),
3038c2ecf20Sopenharmony_ci	SOC_SINGLE_TLV("Voice Playback Volume",
3048c2ecf20Sopenharmony_ci		CPCAP_REG_RXVC, CPCAP_BIT_VOL_CDC0, 0xF, 0, vol_tlv),
3058c2ecf20Sopenharmony_ci	SOC_SINGLE_TLV("Ext Playback Volume",
3068c2ecf20Sopenharmony_ci		CPCAP_REG_RXVC, CPCAP_BIT_VOL_EXT0, 0xF, 0, vol_tlv),
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	/* Capture Gain */
3098c2ecf20Sopenharmony_ci	SOC_SINGLE_TLV("Mic1 Capture Volume",
3108c2ecf20Sopenharmony_ci		CPCAP_REG_TXMP, CPCAP_BIT_MIC1_GAIN_0, 0x1F, 0, mic_gain_tlv),
3118c2ecf20Sopenharmony_ci	SOC_SINGLE_TLV("Mic2 Capture Volume",
3128c2ecf20Sopenharmony_ci		CPCAP_REG_TXMP, CPCAP_BIT_MIC2_GAIN_0, 0x1F, 0, mic_gain_tlv),
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	/* Phase Invert */
3158c2ecf20Sopenharmony_ci	SOC_SINGLE("Hifi Left Phase Invert Switch",
3168c2ecf20Sopenharmony_ci		CPCAP_REG_RXSDOA, CPCAP_BIT_MONO_DAC0, 1, 0),
3178c2ecf20Sopenharmony_ci	SOC_SINGLE("Ext Left Phase Invert Switch",
3188c2ecf20Sopenharmony_ci		CPCAP_REG_RXEPOA, CPCAP_BIT_MONO_EXT0, 1, 0),
3198c2ecf20Sopenharmony_ci};
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic const char * const cpcap_out_mux_texts[] = {
3228c2ecf20Sopenharmony_ci	"Off", "Voice", "HiFi", "Ext"
3238c2ecf20Sopenharmony_ci};
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_cistatic const char * const cpcap_in_right_mux_texts[] = {
3268c2ecf20Sopenharmony_ci	"Off", "Mic 1", "Headset Mic", "EMU Mic", "Ext Right"
3278c2ecf20Sopenharmony_ci};
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic const char * const cpcap_in_left_mux_texts[] = {
3308c2ecf20Sopenharmony_ci	"Off", "Mic 2", "Ext Left"
3318c2ecf20Sopenharmony_ci};
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci/*
3348c2ecf20Sopenharmony_ci * input muxes use unusual register layout, so that we need to use custom
3358c2ecf20Sopenharmony_ci * getter/setter methods
3368c2ecf20Sopenharmony_ci */
3378c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_EXT_DECL(cpcap_input_left_mux_enum,
3388c2ecf20Sopenharmony_ci				cpcap_in_left_mux_texts);
3398c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_EXT_DECL(cpcap_input_right_mux_enum,
3408c2ecf20Sopenharmony_ci				cpcap_in_right_mux_texts);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci/*
3438c2ecf20Sopenharmony_ci * mux uses same bit in CPCAP_REG_RXCOA, CPCAP_REG_RXSDOA & CPCAP_REG_RXEPOA;
3448c2ecf20Sopenharmony_ci * even though the register layout makes it look like a mixer, this is a mux.
3458c2ecf20Sopenharmony_ci * Enabling multiple inputs will result in no audio being forwarded.
3468c2ecf20Sopenharmony_ci */
3478c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(cpcap_earpiece_mux_enum, 0, 0, cpcap_out_mux_texts);
3488c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(cpcap_spkr_r_mux_enum, 0, 1, cpcap_out_mux_texts);
3498c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(cpcap_spkr_l_mux_enum, 0, 2, cpcap_out_mux_texts);
3508c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(cpcap_line_r_mux_enum, 0, 3, cpcap_out_mux_texts);
3518c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(cpcap_line_l_mux_enum, 0, 4, cpcap_out_mux_texts);
3528c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(cpcap_hs_r_mux_enum, 0, 5, cpcap_out_mux_texts);
3538c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(cpcap_hs_l_mux_enum, 0, 6, cpcap_out_mux_texts);
3548c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(cpcap_emu_l_mux_enum, 0, 7, cpcap_out_mux_texts);
3558c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(cpcap_emu_r_mux_enum, 0, 8, cpcap_out_mux_texts);
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_cistatic int cpcap_output_mux_get_enum(struct snd_kcontrol *kcontrol,
3588c2ecf20Sopenharmony_ci				     struct snd_ctl_elem_value *ucontrol)
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
3618c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
3628c2ecf20Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
3638c2ecf20Sopenharmony_ci	unsigned int shift = e->shift_l;
3648c2ecf20Sopenharmony_ci	int reg_voice, reg_hifi, reg_ext, status;
3658c2ecf20Sopenharmony_ci	int err;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	err = regmap_read(cpcap->regmap, CPCAP_REG_RXCOA, &reg_voice);
3688c2ecf20Sopenharmony_ci	if (err)
3698c2ecf20Sopenharmony_ci		return err;
3708c2ecf20Sopenharmony_ci	err = regmap_read(cpcap->regmap, CPCAP_REG_RXSDOA, &reg_hifi);
3718c2ecf20Sopenharmony_ci	if (err)
3728c2ecf20Sopenharmony_ci		return err;
3738c2ecf20Sopenharmony_ci	err = regmap_read(cpcap->regmap, CPCAP_REG_RXEPOA, &reg_ext);
3748c2ecf20Sopenharmony_ci	if (err)
3758c2ecf20Sopenharmony_ci		return err;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	reg_voice = (reg_voice >> shift) & 1;
3788c2ecf20Sopenharmony_ci	reg_hifi = (reg_hifi >> shift) & 1;
3798c2ecf20Sopenharmony_ci	reg_ext = (reg_ext >> shift) & 1;
3808c2ecf20Sopenharmony_ci	status = reg_ext << 2 | reg_hifi << 1 | reg_voice;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	switch (status) {
3838c2ecf20Sopenharmony_ci	case 0x04:
3848c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[0] = 3;
3858c2ecf20Sopenharmony_ci		break;
3868c2ecf20Sopenharmony_ci	case 0x02:
3878c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[0] = 2;
3888c2ecf20Sopenharmony_ci		break;
3898c2ecf20Sopenharmony_ci	case 0x01:
3908c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[0] = 1;
3918c2ecf20Sopenharmony_ci		break;
3928c2ecf20Sopenharmony_ci	default:
3938c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[0] = 0;
3948c2ecf20Sopenharmony_ci		break;
3958c2ecf20Sopenharmony_ci	}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	return 0;
3988c2ecf20Sopenharmony_ci}
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_cistatic int cpcap_output_mux_put_enum(struct snd_kcontrol *kcontrol,
4018c2ecf20Sopenharmony_ci				     struct snd_ctl_elem_value *ucontrol)
4028c2ecf20Sopenharmony_ci{
4038c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
4048c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
4058c2ecf20Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
4068c2ecf20Sopenharmony_ci		snd_soc_dapm_kcontrol_dapm(kcontrol);
4078c2ecf20Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
4088c2ecf20Sopenharmony_ci	unsigned int muxval = ucontrol->value.enumerated.item[0];
4098c2ecf20Sopenharmony_ci	unsigned int mask = BIT(e->shift_l);
4108c2ecf20Sopenharmony_ci	u16 reg_voice = 0x00, reg_hifi = 0x00, reg_ext = 0x00;
4118c2ecf20Sopenharmony_ci	int err;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	switch (muxval) {
4148c2ecf20Sopenharmony_ci	case 1:
4158c2ecf20Sopenharmony_ci		reg_voice = mask;
4168c2ecf20Sopenharmony_ci		break;
4178c2ecf20Sopenharmony_ci	case 2:
4188c2ecf20Sopenharmony_ci		reg_hifi = mask;
4198c2ecf20Sopenharmony_ci		break;
4208c2ecf20Sopenharmony_ci	case 3:
4218c2ecf20Sopenharmony_ci		reg_ext = mask;
4228c2ecf20Sopenharmony_ci		break;
4238c2ecf20Sopenharmony_ci	default:
4248c2ecf20Sopenharmony_ci		break;
4258c2ecf20Sopenharmony_ci	}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXCOA,
4288c2ecf20Sopenharmony_ci				 mask, reg_voice);
4298c2ecf20Sopenharmony_ci	if (err)
4308c2ecf20Sopenharmony_ci		return err;
4318c2ecf20Sopenharmony_ci	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXSDOA,
4328c2ecf20Sopenharmony_ci				 mask, reg_hifi);
4338c2ecf20Sopenharmony_ci	if (err)
4348c2ecf20Sopenharmony_ci		return err;
4358c2ecf20Sopenharmony_ci	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXEPOA,
4368c2ecf20Sopenharmony_ci				 mask, reg_ext);
4378c2ecf20Sopenharmony_ci	if (err)
4388c2ecf20Sopenharmony_ci		return err;
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	snd_soc_dapm_mux_update_power(dapm, kcontrol, muxval, e, NULL);
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	return 0;
4438c2ecf20Sopenharmony_ci}
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_cistatic int cpcap_input_right_mux_get_enum(struct snd_kcontrol *kcontrol,
4468c2ecf20Sopenharmony_ci					  struct snd_ctl_elem_value *ucontrol)
4478c2ecf20Sopenharmony_ci{
4488c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
4498c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
4508c2ecf20Sopenharmony_ci	int regval, mask;
4518c2ecf20Sopenharmony_ci	int err;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	err = regmap_read(cpcap->regmap, CPCAP_REG_TXI, &regval);
4548c2ecf20Sopenharmony_ci	if (err)
4558c2ecf20Sopenharmony_ci		return err;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	mask = 0;
4588c2ecf20Sopenharmony_ci	mask |= BIT(CPCAP_BIT_MIC1_MUX);
4598c2ecf20Sopenharmony_ci	mask |= BIT(CPCAP_BIT_HS_MIC_MUX);
4608c2ecf20Sopenharmony_ci	mask |= BIT(CPCAP_BIT_EMU_MIC_MUX);
4618c2ecf20Sopenharmony_ci	mask |= BIT(CPCAP_BIT_RX_R_ENCODE);
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	switch (regval & mask) {
4648c2ecf20Sopenharmony_ci	case BIT(CPCAP_BIT_RX_R_ENCODE):
4658c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[0] = 4;
4668c2ecf20Sopenharmony_ci		break;
4678c2ecf20Sopenharmony_ci	case BIT(CPCAP_BIT_EMU_MIC_MUX):
4688c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[0] = 3;
4698c2ecf20Sopenharmony_ci		break;
4708c2ecf20Sopenharmony_ci	case BIT(CPCAP_BIT_HS_MIC_MUX):
4718c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[0] = 2;
4728c2ecf20Sopenharmony_ci		break;
4738c2ecf20Sopenharmony_ci	case BIT(CPCAP_BIT_MIC1_MUX):
4748c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[0] = 1;
4758c2ecf20Sopenharmony_ci		break;
4768c2ecf20Sopenharmony_ci	default:
4778c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[0] = 0;
4788c2ecf20Sopenharmony_ci		break;
4798c2ecf20Sopenharmony_ci	}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	return 0;
4828c2ecf20Sopenharmony_ci}
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_cistatic int cpcap_input_right_mux_put_enum(struct snd_kcontrol *kcontrol,
4858c2ecf20Sopenharmony_ci					  struct snd_ctl_elem_value *ucontrol)
4868c2ecf20Sopenharmony_ci{
4878c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
4888c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
4898c2ecf20Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
4908c2ecf20Sopenharmony_ci		snd_soc_dapm_kcontrol_dapm(kcontrol);
4918c2ecf20Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
4928c2ecf20Sopenharmony_ci	unsigned int muxval = ucontrol->value.enumerated.item[0];
4938c2ecf20Sopenharmony_ci	int regval = 0, mask;
4948c2ecf20Sopenharmony_ci	int err;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	mask = 0;
4978c2ecf20Sopenharmony_ci	mask |= BIT(CPCAP_BIT_MIC1_MUX);
4988c2ecf20Sopenharmony_ci	mask |= BIT(CPCAP_BIT_HS_MIC_MUX);
4998c2ecf20Sopenharmony_ci	mask |= BIT(CPCAP_BIT_EMU_MIC_MUX);
5008c2ecf20Sopenharmony_ci	mask |= BIT(CPCAP_BIT_RX_R_ENCODE);
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	switch (muxval) {
5038c2ecf20Sopenharmony_ci	case 1:
5048c2ecf20Sopenharmony_ci		regval = BIT(CPCAP_BIT_MIC1_MUX);
5058c2ecf20Sopenharmony_ci		break;
5068c2ecf20Sopenharmony_ci	case 2:
5078c2ecf20Sopenharmony_ci		regval = BIT(CPCAP_BIT_HS_MIC_MUX);
5088c2ecf20Sopenharmony_ci		break;
5098c2ecf20Sopenharmony_ci	case 3:
5108c2ecf20Sopenharmony_ci		regval = BIT(CPCAP_BIT_EMU_MIC_MUX);
5118c2ecf20Sopenharmony_ci		break;
5128c2ecf20Sopenharmony_ci	case 4:
5138c2ecf20Sopenharmony_ci		regval = BIT(CPCAP_BIT_RX_R_ENCODE);
5148c2ecf20Sopenharmony_ci		break;
5158c2ecf20Sopenharmony_ci	default:
5168c2ecf20Sopenharmony_ci		break;
5178c2ecf20Sopenharmony_ci	}
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
5208c2ecf20Sopenharmony_ci				 mask, regval);
5218c2ecf20Sopenharmony_ci	if (err)
5228c2ecf20Sopenharmony_ci		return err;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	snd_soc_dapm_mux_update_power(dapm, kcontrol, muxval, e, NULL);
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	return 0;
5278c2ecf20Sopenharmony_ci}
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_cistatic int cpcap_input_left_mux_get_enum(struct snd_kcontrol *kcontrol,
5308c2ecf20Sopenharmony_ci					 struct snd_ctl_elem_value *ucontrol)
5318c2ecf20Sopenharmony_ci{
5328c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
5338c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
5348c2ecf20Sopenharmony_ci	int regval, mask;
5358c2ecf20Sopenharmony_ci	int err;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	err = regmap_read(cpcap->regmap, CPCAP_REG_TXI, &regval);
5388c2ecf20Sopenharmony_ci	if (err)
5398c2ecf20Sopenharmony_ci		return err;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	mask = 0;
5428c2ecf20Sopenharmony_ci	mask |= BIT(CPCAP_BIT_MIC2_MUX);
5438c2ecf20Sopenharmony_ci	mask |= BIT(CPCAP_BIT_RX_L_ENCODE);
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	switch (regval & mask) {
5468c2ecf20Sopenharmony_ci	case BIT(CPCAP_BIT_RX_L_ENCODE):
5478c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[0] = 2;
5488c2ecf20Sopenharmony_ci		break;
5498c2ecf20Sopenharmony_ci	case BIT(CPCAP_BIT_MIC2_MUX):
5508c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[0] = 1;
5518c2ecf20Sopenharmony_ci		break;
5528c2ecf20Sopenharmony_ci	default:
5538c2ecf20Sopenharmony_ci		ucontrol->value.enumerated.item[0] = 0;
5548c2ecf20Sopenharmony_ci		break;
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	return 0;
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_cistatic int cpcap_input_left_mux_put_enum(struct snd_kcontrol *kcontrol,
5618c2ecf20Sopenharmony_ci					 struct snd_ctl_elem_value *ucontrol)
5628c2ecf20Sopenharmony_ci{
5638c2ecf20Sopenharmony_ci	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
5648c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
5658c2ecf20Sopenharmony_ci	struct snd_soc_dapm_context *dapm =
5668c2ecf20Sopenharmony_ci		snd_soc_dapm_kcontrol_dapm(kcontrol);
5678c2ecf20Sopenharmony_ci	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
5688c2ecf20Sopenharmony_ci	unsigned int muxval = ucontrol->value.enumerated.item[0];
5698c2ecf20Sopenharmony_ci	int regval = 0, mask;
5708c2ecf20Sopenharmony_ci	int err;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	mask = 0;
5738c2ecf20Sopenharmony_ci	mask |= BIT(CPCAP_BIT_MIC2_MUX);
5748c2ecf20Sopenharmony_ci	mask |= BIT(CPCAP_BIT_RX_L_ENCODE);
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	switch (muxval) {
5778c2ecf20Sopenharmony_ci	case 1:
5788c2ecf20Sopenharmony_ci		regval = BIT(CPCAP_BIT_MIC2_MUX);
5798c2ecf20Sopenharmony_ci		break;
5808c2ecf20Sopenharmony_ci	case 2:
5818c2ecf20Sopenharmony_ci		regval = BIT(CPCAP_BIT_RX_L_ENCODE);
5828c2ecf20Sopenharmony_ci		break;
5838c2ecf20Sopenharmony_ci	default:
5848c2ecf20Sopenharmony_ci		break;
5858c2ecf20Sopenharmony_ci	}
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,
5888c2ecf20Sopenharmony_ci				 mask, regval);
5898c2ecf20Sopenharmony_ci	if (err)
5908c2ecf20Sopenharmony_ci		return err;
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci	snd_soc_dapm_mux_update_power(dapm, kcontrol, muxval, e, NULL);
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	return 0;
5958c2ecf20Sopenharmony_ci}
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_input_left_mux =
5988c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("Input Left", cpcap_input_left_mux_enum,
5998c2ecf20Sopenharmony_ci			  cpcap_input_left_mux_get_enum,
6008c2ecf20Sopenharmony_ci			  cpcap_input_left_mux_put_enum);
6018c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_input_right_mux =
6028c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("Input Right", cpcap_input_right_mux_enum,
6038c2ecf20Sopenharmony_ci			  cpcap_input_right_mux_get_enum,
6048c2ecf20Sopenharmony_ci			  cpcap_input_right_mux_put_enum);
6058c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_emu_left_mux =
6068c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("EMU Left", cpcap_emu_l_mux_enum,
6078c2ecf20Sopenharmony_ci			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);
6088c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_emu_right_mux =
6098c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("EMU Right", cpcap_emu_r_mux_enum,
6108c2ecf20Sopenharmony_ci			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);
6118c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_hs_left_mux =
6128c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("Headset Left", cpcap_hs_l_mux_enum,
6138c2ecf20Sopenharmony_ci			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);
6148c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_hs_right_mux =
6158c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("Headset Right", cpcap_hs_r_mux_enum,
6168c2ecf20Sopenharmony_ci			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);
6178c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_line_left_mux =
6188c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("Line Left", cpcap_line_l_mux_enum,
6198c2ecf20Sopenharmony_ci			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);
6208c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_line_right_mux =
6218c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("Line Right", cpcap_line_r_mux_enum,
6228c2ecf20Sopenharmony_ci			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);
6238c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_speaker_left_mux =
6248c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("Speaker Left", cpcap_spkr_l_mux_enum,
6258c2ecf20Sopenharmony_ci			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);
6268c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_speaker_right_mux =
6278c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("Speaker Right", cpcap_spkr_r_mux_enum,
6288c2ecf20Sopenharmony_ci			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);
6298c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_earpiece_mux =
6308c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM_EXT("Earpiece", cpcap_earpiece_mux_enum,
6318c2ecf20Sopenharmony_ci			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_hifi_mono_mixer_controls[] = {
6348c2ecf20Sopenharmony_ci	SOC_DAPM_SINGLE("HiFi Mono Playback Switch",
6358c2ecf20Sopenharmony_ci		CPCAP_REG_RXSDOA, CPCAP_BIT_MONO_DAC1, 1, 0),
6368c2ecf20Sopenharmony_ci};
6378c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_ext_mono_mixer_controls[] = {
6388c2ecf20Sopenharmony_ci	SOC_DAPM_SINGLE("Ext Mono Playback Switch",
6398c2ecf20Sopenharmony_ci		CPCAP_REG_RXEPOA, CPCAP_BIT_MONO_EXT0, 1, 0),
6408c2ecf20Sopenharmony_ci};
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_extr_mute_control =
6438c2ecf20Sopenharmony_ci	SOC_DAPM_SINGLE("Switch",
6448c2ecf20Sopenharmony_ci		CPCAP_REG_RXEPOA, CPCAP_BIT_PGA_IN_R_SW, 1, 0);
6458c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_extl_mute_control =
6468c2ecf20Sopenharmony_ci	SOC_DAPM_SINGLE("Switch",
6478c2ecf20Sopenharmony_ci		CPCAP_REG_RXEPOA, CPCAP_BIT_PGA_IN_L_SW, 1, 0);
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cpcap_voice_loopback =
6508c2ecf20Sopenharmony_ci	SOC_DAPM_SINGLE("Switch",
6518c2ecf20Sopenharmony_ci		CPCAP_REG_TXI, CPCAP_BIT_DLM, 1, 0);
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget cpcap_dapm_widgets[] = {
6548c2ecf20Sopenharmony_ci	/* DAIs */
6558c2ecf20Sopenharmony_ci	SND_SOC_DAPM_AIF_IN("HiFi RX", NULL, 0, SND_SOC_NOPM, 0, 0),
6568c2ecf20Sopenharmony_ci	SND_SOC_DAPM_AIF_IN("Voice RX", NULL, 0, SND_SOC_NOPM, 0, 0),
6578c2ecf20Sopenharmony_ci	SND_SOC_DAPM_AIF_OUT("Voice TX", NULL, 0, SND_SOC_NOPM, 0, 0),
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	/* Power Supply */
6608c2ecf20Sopenharmony_ci	SND_SOC_DAPM_REGULATOR_SUPPLY("VAUDIO", SLEEP_ACTIVATE_POWER, 0),
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	/* Highpass Filters */
6638c2ecf20Sopenharmony_ci	SND_SOC_DAPM_REG(snd_soc_dapm_pga, "Highpass Filter RX",
6648c2ecf20Sopenharmony_ci		CPCAP_REG_CC, CPCAP_BIT_AUDIHPF_0, 0x3, 0x3, 0x0),
6658c2ecf20Sopenharmony_ci	SND_SOC_DAPM_REG(snd_soc_dapm_pga, "Highpass Filter TX",
6668c2ecf20Sopenharmony_ci		CPCAP_REG_CC, CPCAP_BIT_AUDOHPF_0, 0x3, 0x3, 0x0),
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	/* Clocks */
6698c2ecf20Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("HiFi DAI Clock",
6708c2ecf20Sopenharmony_ci		CPCAP_REG_SDACDI, CPCAP_BIT_ST_CLK_EN, 0, NULL, 0),
6718c2ecf20Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("Voice DAI Clock",
6728c2ecf20Sopenharmony_ci		CPCAP_REG_CDI, CPCAP_BIT_CDC_CLK_EN, 0, NULL, 0),
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	/* Microphone Bias */
6758c2ecf20Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("MIC1R Bias",
6768c2ecf20Sopenharmony_ci		CPCAP_REG_TXI, CPCAP_BIT_MB_ON1R, 0, NULL, 0),
6778c2ecf20Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("MIC1L Bias",
6788c2ecf20Sopenharmony_ci		CPCAP_REG_TXI, CPCAP_BIT_MB_ON1L, 0, NULL, 0),
6798c2ecf20Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("MIC2 Bias",
6808c2ecf20Sopenharmony_ci		CPCAP_REG_TXI, CPCAP_BIT_MB_ON2, 0, NULL, 0),
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	/* Inputs */
6838c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("MICR"),
6848c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("HSMIC"),
6858c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("EMUMIC"),
6868c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("MICL"),
6878c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("EXTR"),
6888c2ecf20Sopenharmony_ci	SND_SOC_DAPM_INPUT("EXTL"),
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	/* Capture Route */
6918c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("Right Capture Route",
6928c2ecf20Sopenharmony_ci		SND_SOC_NOPM, 0, 0, &cpcap_input_right_mux),
6938c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("Left Capture Route",
6948c2ecf20Sopenharmony_ci		SND_SOC_NOPM, 0, 0, &cpcap_input_left_mux),
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	/* Capture PGAs */
6978c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("Microphone 1 PGA",
6988c2ecf20Sopenharmony_ci		CPCAP_REG_TXI, CPCAP_BIT_MIC1_PGA_EN, 0, NULL, 0),
6998c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("Microphone 2 PGA",
7008c2ecf20Sopenharmony_ci		CPCAP_REG_TXI, CPCAP_BIT_MIC2_PGA_EN, 0, NULL, 0),
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	/* ADC */
7038c2ecf20Sopenharmony_ci	SND_SOC_DAPM_ADC("ADC Right", NULL,
7048c2ecf20Sopenharmony_ci		CPCAP_REG_CC, CPCAP_BIT_MIC1_CDC_EN, 0),
7058c2ecf20Sopenharmony_ci	SND_SOC_DAPM_ADC("ADC Left", NULL,
7068c2ecf20Sopenharmony_ci		CPCAP_REG_CC, CPCAP_BIT_MIC2_CDC_EN, 0),
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	/* DAC */
7098c2ecf20Sopenharmony_ci	SND_SOC_DAPM_DAC_E("DAC HiFi", NULL,
7108c2ecf20Sopenharmony_ci		CPCAP_REG_SDAC, CPCAP_BIT_ST_DAC_EN, 0,
7118c2ecf20Sopenharmony_ci		cpcap_st_workaround,
7128c2ecf20Sopenharmony_ci		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
7138c2ecf20Sopenharmony_ci	SND_SOC_DAPM_DAC_E("DAC Voice", NULL,
7148c2ecf20Sopenharmony_ci		CPCAP_REG_CC, CPCAP_BIT_CDC_EN_RX, 0,
7158c2ecf20Sopenharmony_ci		cpcap_st_workaround,
7168c2ecf20Sopenharmony_ci		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	/* Playback PGA */
7198c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("HiFi PGA",
7208c2ecf20Sopenharmony_ci		CPCAP_REG_RXSDOA, CPCAP_BIT_PGA_DAC_EN, 0, NULL, 0),
7218c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("Voice PGA",
7228c2ecf20Sopenharmony_ci		CPCAP_REG_RXCOA, CPCAP_BIT_PGA_CDC_EN, 0, NULL, 0),
7238c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA_E("Ext Right PGA",
7248c2ecf20Sopenharmony_ci		CPCAP_REG_RXEPOA, CPCAP_BIT_PGA_EXT_R_EN, 0,
7258c2ecf20Sopenharmony_ci		NULL, 0,
7268c2ecf20Sopenharmony_ci		cpcap_st_workaround,
7278c2ecf20Sopenharmony_ci		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
7288c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA_E("Ext Left PGA",
7298c2ecf20Sopenharmony_ci		CPCAP_REG_RXEPOA, CPCAP_BIT_PGA_EXT_L_EN, 0,
7308c2ecf20Sopenharmony_ci		NULL, 0,
7318c2ecf20Sopenharmony_ci		cpcap_st_workaround,
7328c2ecf20Sopenharmony_ci		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	/* Playback Switch */
7358c2ecf20Sopenharmony_ci	SND_SOC_DAPM_SWITCH("Ext Right Enable", SND_SOC_NOPM, 0, 0,
7368c2ecf20Sopenharmony_ci		&cpcap_extr_mute_control),
7378c2ecf20Sopenharmony_ci	SND_SOC_DAPM_SWITCH("Ext Left Enable", SND_SOC_NOPM, 0, 0,
7388c2ecf20Sopenharmony_ci		&cpcap_extl_mute_control),
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	/* Loopback Switch */
7418c2ecf20Sopenharmony_ci	SND_SOC_DAPM_SWITCH("Voice Loopback", SND_SOC_NOPM, 0, 0,
7428c2ecf20Sopenharmony_ci		&cpcap_voice_loopback),
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	/* Mono Mixer */
7458c2ecf20Sopenharmony_ci	SOC_MIXER_ARRAY("HiFi Mono Left Mixer", SND_SOC_NOPM, 0, 0,
7468c2ecf20Sopenharmony_ci		cpcap_hifi_mono_mixer_controls),
7478c2ecf20Sopenharmony_ci	SOC_MIXER_ARRAY("HiFi Mono Right Mixer", SND_SOC_NOPM, 0, 0,
7488c2ecf20Sopenharmony_ci		cpcap_hifi_mono_mixer_controls),
7498c2ecf20Sopenharmony_ci	SOC_MIXER_ARRAY("Ext Mono Left Mixer", SND_SOC_NOPM, 0, 0,
7508c2ecf20Sopenharmony_ci		cpcap_ext_mono_mixer_controls),
7518c2ecf20Sopenharmony_ci	SOC_MIXER_ARRAY("Ext Mono Right Mixer", SND_SOC_NOPM, 0, 0,
7528c2ecf20Sopenharmony_ci		cpcap_ext_mono_mixer_controls),
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	/* Output Routes */
7558c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("Earpiece Playback Route", SND_SOC_NOPM, 0, 0,
7568c2ecf20Sopenharmony_ci		&cpcap_earpiece_mux),
7578c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("Speaker Right Playback Route", SND_SOC_NOPM, 0, 0,
7588c2ecf20Sopenharmony_ci		&cpcap_speaker_right_mux),
7598c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("Speaker Left Playback Route", SND_SOC_NOPM, 0, 0,
7608c2ecf20Sopenharmony_ci		&cpcap_speaker_left_mux),
7618c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("Lineout Right Playback Route", SND_SOC_NOPM, 0, 0,
7628c2ecf20Sopenharmony_ci		&cpcap_line_right_mux),
7638c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("Lineout Left Playback Route", SND_SOC_NOPM, 0, 0,
7648c2ecf20Sopenharmony_ci		&cpcap_line_left_mux),
7658c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("Headset Right Playback Route", SND_SOC_NOPM, 0, 0,
7668c2ecf20Sopenharmony_ci		&cpcap_hs_right_mux),
7678c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("Headset Left Playback Route", SND_SOC_NOPM, 0, 0,
7688c2ecf20Sopenharmony_ci		&cpcap_hs_left_mux),
7698c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("EMU Right Playback Route", SND_SOC_NOPM, 0, 0,
7708c2ecf20Sopenharmony_ci		&cpcap_emu_right_mux),
7718c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("EMU Left Playback Route", SND_SOC_NOPM, 0, 0,
7728c2ecf20Sopenharmony_ci		&cpcap_emu_left_mux),
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	/* Output Amplifier */
7758c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("Earpiece PGA",
7768c2ecf20Sopenharmony_ci		CPCAP_REG_RXOA, CPCAP_BIT_A1_EAR_EN, 0, NULL, 0),
7778c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("Speaker Right PGA",
7788c2ecf20Sopenharmony_ci		CPCAP_REG_RXOA, CPCAP_BIT_A2_LDSP_R_EN, 0, NULL, 0),
7798c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("Speaker Left PGA",
7808c2ecf20Sopenharmony_ci		CPCAP_REG_RXOA, CPCAP_BIT_A2_LDSP_L_EN, 0, NULL, 0),
7818c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("Lineout Right PGA",
7828c2ecf20Sopenharmony_ci		CPCAP_REG_RXOA, CPCAP_BIT_A4_LINEOUT_R_EN, 0, NULL, 0),
7838c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("Lineout Left PGA",
7848c2ecf20Sopenharmony_ci		CPCAP_REG_RXOA, CPCAP_BIT_A4_LINEOUT_L_EN, 0, NULL, 0),
7858c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("Headset Right PGA",
7868c2ecf20Sopenharmony_ci		CPCAP_REG_RXOA, CPCAP_BIT_HS_R_EN, 0, NULL, 0),
7878c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("Headset Left PGA",
7888c2ecf20Sopenharmony_ci		CPCAP_REG_RXOA, CPCAP_BIT_HS_L_EN, 0, NULL, 0),
7898c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("EMU Right PGA",
7908c2ecf20Sopenharmony_ci		CPCAP_REG_RXOA, CPCAP_BIT_EMU_SPKR_R_EN, 0, NULL, 0),
7918c2ecf20Sopenharmony_ci	SND_SOC_DAPM_PGA("EMU Left PGA",
7928c2ecf20Sopenharmony_ci		CPCAP_REG_RXOA, CPCAP_BIT_EMU_SPKR_L_EN, 0, NULL, 0),
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	/* Headet Charge Pump */
7958c2ecf20Sopenharmony_ci	SND_SOC_DAPM_SUPPLY("Headset Charge Pump",
7968c2ecf20Sopenharmony_ci		CPCAP_REG_RXOA, CPCAP_BIT_ST_HS_CP_EN, 0, NULL, 0),
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	/* Outputs */
7998c2ecf20Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("EP"),
8008c2ecf20Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("SPKR"),
8018c2ecf20Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("SPKL"),
8028c2ecf20Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("LINER"),
8038c2ecf20Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("LINEL"),
8048c2ecf20Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("HSR"),
8058c2ecf20Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("HSL"),
8068c2ecf20Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("EMUR"),
8078c2ecf20Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("EMUL"),
8088c2ecf20Sopenharmony_ci};
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route intercon[] = {
8118c2ecf20Sopenharmony_ci	/* Power Supply */
8128c2ecf20Sopenharmony_ci	{"HiFi PGA", NULL, "VAUDIO"},
8138c2ecf20Sopenharmony_ci	{"Voice PGA", NULL, "VAUDIO"},
8148c2ecf20Sopenharmony_ci	{"Ext Right PGA", NULL, "VAUDIO"},
8158c2ecf20Sopenharmony_ci	{"Ext Left PGA", NULL, "VAUDIO"},
8168c2ecf20Sopenharmony_ci	{"Microphone 1 PGA", NULL, "VAUDIO"},
8178c2ecf20Sopenharmony_ci	{"Microphone 2 PGA", NULL, "VAUDIO"},
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	/* Stream -> AIF */
8208c2ecf20Sopenharmony_ci	{"HiFi RX", NULL, "HiFi Playback"},
8218c2ecf20Sopenharmony_ci	{"Voice RX", NULL, "Voice Playback"},
8228c2ecf20Sopenharmony_ci	{"Voice Capture", NULL, "Voice TX"},
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	/* AIF clocks */
8258c2ecf20Sopenharmony_ci	{"HiFi RX", NULL, "HiFi DAI Clock"},
8268c2ecf20Sopenharmony_ci	{"Voice RX", NULL, "Voice DAI Clock"},
8278c2ecf20Sopenharmony_ci	{"Voice TX", NULL, "Voice DAI Clock"},
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	/* Digital Loopback */
8308c2ecf20Sopenharmony_ci	{"Voice Loopback", "Switch", "Voice TX"},
8318c2ecf20Sopenharmony_ci	{"Voice RX", NULL, "Voice Loopback"},
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	/* Highpass Filters */
8348c2ecf20Sopenharmony_ci	{"Highpass Filter RX", NULL, "Voice RX"},
8358c2ecf20Sopenharmony_ci	{"Voice TX", NULL, "Highpass Filter TX"},
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci	/* AIF -> DAC mapping */
8388c2ecf20Sopenharmony_ci	{"DAC HiFi", NULL, "HiFi RX"},
8398c2ecf20Sopenharmony_ci	{"DAC Voice", NULL, "Highpass Filter RX"},
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	/* DAC -> PGA */
8428c2ecf20Sopenharmony_ci	{"HiFi PGA", NULL, "DAC HiFi"},
8438c2ecf20Sopenharmony_ci	{"Voice PGA", NULL, "DAC Voice"},
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci	/* Ext Input -> PGA */
8468c2ecf20Sopenharmony_ci	{"Ext Right PGA", NULL, "EXTR"},
8478c2ecf20Sopenharmony_ci	{"Ext Left PGA", NULL, "EXTL"},
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	/* Ext PGA -> Ext Playback Switch */
8508c2ecf20Sopenharmony_ci	{"Ext Right Enable", "Switch", "Ext Right PGA"},
8518c2ecf20Sopenharmony_ci	{"Ext Left Enable", "Switch", "Ext Left PGA"},
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	/* HiFi PGA -> Mono Mixer */
8548c2ecf20Sopenharmony_ci	{"HiFi Mono Left Mixer", NULL, "HiFi PGA"},
8558c2ecf20Sopenharmony_ci	{"HiFi Mono Left Mixer", "HiFi Mono Playback Switch", "HiFi PGA"},
8568c2ecf20Sopenharmony_ci	{"HiFi Mono Right Mixer", NULL, "HiFi PGA"},
8578c2ecf20Sopenharmony_ci	{"HiFi Mono Right Mixer", "HiFi Mono Playback Switch", "HiFi PGA"},
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	/* Ext Playback Switch -> Ext Mono Mixer */
8608c2ecf20Sopenharmony_ci	{"Ext Mono Right Mixer", NULL, "Ext Right Enable"},
8618c2ecf20Sopenharmony_ci	{"Ext Mono Right Mixer", "Ext Mono Playback Switch", "Ext Left Enable"},
8628c2ecf20Sopenharmony_ci	{"Ext Mono Left Mixer", NULL, "Ext Left Enable"},
8638c2ecf20Sopenharmony_ci	{"Ext Mono Left Mixer", "Ext Mono Playback Switch", "Ext Right Enable"},
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	/* HiFi Mono Mixer -> Output Route */
8668c2ecf20Sopenharmony_ci	{"Earpiece Playback Route", "HiFi", "HiFi Mono Right Mixer"},
8678c2ecf20Sopenharmony_ci	{"Speaker Right Playback Route", "HiFi", "HiFi Mono Right Mixer"},
8688c2ecf20Sopenharmony_ci	{"Speaker Left Playback Route", "HiFi", "HiFi Mono Left Mixer"},
8698c2ecf20Sopenharmony_ci	{"Lineout Right Playback Route", "HiFi", "HiFi Mono Right Mixer"},
8708c2ecf20Sopenharmony_ci	{"Lineout Left Playback Route", "HiFi", "HiFi Mono Left Mixer"},
8718c2ecf20Sopenharmony_ci	{"Headset Right Playback Route", "HiFi", "HiFi Mono Right Mixer"},
8728c2ecf20Sopenharmony_ci	{"Headset Left Playback Route", "HiFi", "HiFi Mono Left Mixer"},
8738c2ecf20Sopenharmony_ci	{"EMU Right Playback Route", "HiFi", "HiFi Mono Right Mixer"},
8748c2ecf20Sopenharmony_ci	{"EMU Left Playback Route", "HiFi", "HiFi Mono Left Mixer"},
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	/* Voice PGA -> Output Route */
8778c2ecf20Sopenharmony_ci	{"Earpiece Playback Route", "Voice", "Voice PGA"},
8788c2ecf20Sopenharmony_ci	{"Speaker Right Playback Route", "Voice", "Voice PGA"},
8798c2ecf20Sopenharmony_ci	{"Speaker Left Playback Route", "Voice", "Voice PGA"},
8808c2ecf20Sopenharmony_ci	{"Lineout Right Playback Route", "Voice", "Voice PGA"},
8818c2ecf20Sopenharmony_ci	{"Lineout Left Playback Route", "Voice", "Voice PGA"},
8828c2ecf20Sopenharmony_ci	{"Headset Right Playback Route", "Voice", "Voice PGA"},
8838c2ecf20Sopenharmony_ci	{"Headset Left Playback Route", "Voice", "Voice PGA"},
8848c2ecf20Sopenharmony_ci	{"EMU Right Playback Route", "Voice", "Voice PGA"},
8858c2ecf20Sopenharmony_ci	{"EMU Left Playback Route", "Voice", "Voice PGA"},
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	/* Ext Mono Mixer -> Output Route */
8888c2ecf20Sopenharmony_ci	{"Earpiece Playback Route", "Ext", "Ext Mono Right Mixer"},
8898c2ecf20Sopenharmony_ci	{"Speaker Right Playback Route", "Ext", "Ext Mono Right Mixer"},
8908c2ecf20Sopenharmony_ci	{"Speaker Left Playback Route", "Ext", "Ext Mono Left Mixer"},
8918c2ecf20Sopenharmony_ci	{"Lineout Right Playback Route", "Ext", "Ext Mono Right Mixer"},
8928c2ecf20Sopenharmony_ci	{"Lineout Left Playback Route", "Ext", "Ext Mono Left Mixer"},
8938c2ecf20Sopenharmony_ci	{"Headset Right Playback Route", "Ext", "Ext Mono Right Mixer"},
8948c2ecf20Sopenharmony_ci	{"Headset Left Playback Route", "Ext", "Ext Mono Left Mixer"},
8958c2ecf20Sopenharmony_ci	{"EMU Right Playback Route", "Ext", "Ext Mono Right Mixer"},
8968c2ecf20Sopenharmony_ci	{"EMU Left Playback Route", "Ext", "Ext Mono Left Mixer"},
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci	/* Output Route -> Output Amplifier */
8998c2ecf20Sopenharmony_ci	{"Earpiece PGA", NULL, "Earpiece Playback Route"},
9008c2ecf20Sopenharmony_ci	{"Speaker Right PGA", NULL, "Speaker Right Playback Route"},
9018c2ecf20Sopenharmony_ci	{"Speaker Left PGA", NULL, "Speaker Left Playback Route"},
9028c2ecf20Sopenharmony_ci	{"Lineout Right PGA", NULL, "Lineout Right Playback Route"},
9038c2ecf20Sopenharmony_ci	{"Lineout Left PGA", NULL, "Lineout Left Playback Route"},
9048c2ecf20Sopenharmony_ci	{"Headset Right PGA", NULL, "Headset Right Playback Route"},
9058c2ecf20Sopenharmony_ci	{"Headset Left PGA", NULL, "Headset Left Playback Route"},
9068c2ecf20Sopenharmony_ci	{"EMU Right PGA", NULL, "EMU Right Playback Route"},
9078c2ecf20Sopenharmony_ci	{"EMU Left PGA", NULL, "EMU Left Playback Route"},
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	/* Output Amplifier -> Output */
9108c2ecf20Sopenharmony_ci	{"EP", NULL, "Earpiece PGA"},
9118c2ecf20Sopenharmony_ci	{"SPKR", NULL, "Speaker Right PGA"},
9128c2ecf20Sopenharmony_ci	{"SPKL", NULL, "Speaker Left PGA"},
9138c2ecf20Sopenharmony_ci	{"LINER", NULL, "Lineout Right PGA"},
9148c2ecf20Sopenharmony_ci	{"LINEL", NULL, "Lineout Left PGA"},
9158c2ecf20Sopenharmony_ci	{"HSR", NULL, "Headset Right PGA"},
9168c2ecf20Sopenharmony_ci	{"HSL", NULL, "Headset Left PGA"},
9178c2ecf20Sopenharmony_ci	{"EMUR", NULL, "EMU Right PGA"},
9188c2ecf20Sopenharmony_ci	{"EMUL", NULL, "EMU Left PGA"},
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	/* Headset Charge Pump -> Headset */
9218c2ecf20Sopenharmony_ci	{"HSR", NULL, "Headset Charge Pump"},
9228c2ecf20Sopenharmony_ci	{"HSL", NULL, "Headset Charge Pump"},
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	/* Mic -> Mic Route */
9258c2ecf20Sopenharmony_ci	{"Right Capture Route", "Mic 1", "MICR"},
9268c2ecf20Sopenharmony_ci	{"Right Capture Route", "Headset Mic", "HSMIC"},
9278c2ecf20Sopenharmony_ci	{"Right Capture Route", "EMU Mic", "EMUMIC"},
9288c2ecf20Sopenharmony_ci	{"Right Capture Route", "Ext Right", "EXTR"},
9298c2ecf20Sopenharmony_ci	{"Left Capture Route", "Mic 2", "MICL"},
9308c2ecf20Sopenharmony_ci	{"Left Capture Route", "Ext Left", "EXTL"},
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	/* Input Route -> Microphone PGA */
9338c2ecf20Sopenharmony_ci	{"Microphone 1 PGA", NULL, "Right Capture Route"},
9348c2ecf20Sopenharmony_ci	{"Microphone 2 PGA", NULL, "Left Capture Route"},
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	/* Microphone PGA -> ADC */
9378c2ecf20Sopenharmony_ci	{"ADC Right", NULL, "Microphone 1 PGA"},
9388c2ecf20Sopenharmony_ci	{"ADC Left", NULL, "Microphone 2 PGA"},
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	/* ADC -> Stream */
9418c2ecf20Sopenharmony_ci	{"Highpass Filter TX", NULL, "ADC Right"},
9428c2ecf20Sopenharmony_ci	{"Highpass Filter TX", NULL, "ADC Left"},
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	/* Mic Bias */
9458c2ecf20Sopenharmony_ci	{"MICL", NULL, "MIC1L Bias"},
9468c2ecf20Sopenharmony_ci	{"MICR", NULL, "MIC1R Bias"},
9478c2ecf20Sopenharmony_ci};
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_cistatic int cpcap_set_sysclk(struct cpcap_audio *cpcap, enum cpcap_dai dai,
9508c2ecf20Sopenharmony_ci			    int clk_id, int freq)
9518c2ecf20Sopenharmony_ci{
9528c2ecf20Sopenharmony_ci	u16 clkfreqreg, clkfreqshift;
9538c2ecf20Sopenharmony_ci	u16 clkfreqmask, clkfreqval;
9548c2ecf20Sopenharmony_ci	u16 clkidreg, clkidshift;
9558c2ecf20Sopenharmony_ci	u16 mask, val;
9568c2ecf20Sopenharmony_ci	int err;
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	switch (dai) {
9598c2ecf20Sopenharmony_ci	case CPCAP_DAI_HIFI:
9608c2ecf20Sopenharmony_ci		clkfreqreg = CPCAP_REG_SDAC;
9618c2ecf20Sopenharmony_ci		clkfreqshift = CPCAP_BIT_ST_DAC_CLK0;
9628c2ecf20Sopenharmony_ci		clkidreg = CPCAP_REG_SDACDI;
9638c2ecf20Sopenharmony_ci		clkidshift = CPCAP_BIT_ST_DAC_CLK_IN_SEL;
9648c2ecf20Sopenharmony_ci		break;
9658c2ecf20Sopenharmony_ci	case CPCAP_DAI_VOICE:
9668c2ecf20Sopenharmony_ci		clkfreqreg = CPCAP_REG_CC;
9678c2ecf20Sopenharmony_ci		clkfreqshift = CPCAP_BIT_CDC_CLK0;
9688c2ecf20Sopenharmony_ci		clkidreg = CPCAP_REG_CDI;
9698c2ecf20Sopenharmony_ci		clkidshift = CPCAP_BIT_CLK_IN_SEL;
9708c2ecf20Sopenharmony_ci		break;
9718c2ecf20Sopenharmony_ci	default:
9728c2ecf20Sopenharmony_ci		dev_err(cpcap->component->dev, "invalid DAI: %d", dai);
9738c2ecf20Sopenharmony_ci		return -EINVAL;
9748c2ecf20Sopenharmony_ci	}
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	/* setup clk id */
9778c2ecf20Sopenharmony_ci	if (clk_id < 0 || clk_id > 1) {
9788c2ecf20Sopenharmony_ci		dev_err(cpcap->component->dev, "invalid clk id %d", clk_id);
9798c2ecf20Sopenharmony_ci		return -EINVAL;
9808c2ecf20Sopenharmony_ci	}
9818c2ecf20Sopenharmony_ci	err = regmap_update_bits(cpcap->regmap, clkidreg, BIT(clkidshift),
9828c2ecf20Sopenharmony_ci				 clk_id ? BIT(clkidshift) : 0);
9838c2ecf20Sopenharmony_ci	if (err)
9848c2ecf20Sopenharmony_ci		return err;
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	/* enable PLL for Voice DAI */
9878c2ecf20Sopenharmony_ci	if (dai == CPCAP_DAI_VOICE) {
9888c2ecf20Sopenharmony_ci		mask = BIT(CPCAP_BIT_CDC_PLL_SEL);
9898c2ecf20Sopenharmony_ci		val = BIT(CPCAP_BIT_CDC_PLL_SEL);
9908c2ecf20Sopenharmony_ci		err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,
9918c2ecf20Sopenharmony_ci					 mask, val);
9928c2ecf20Sopenharmony_ci		if (err)
9938c2ecf20Sopenharmony_ci			return err;
9948c2ecf20Sopenharmony_ci	}
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	/* setup frequency */
9978c2ecf20Sopenharmony_ci	clkfreqmask = 0x7 << clkfreqshift;
9988c2ecf20Sopenharmony_ci	switch (freq) {
9998c2ecf20Sopenharmony_ci	case 15360000:
10008c2ecf20Sopenharmony_ci		clkfreqval = 0x01 << clkfreqshift;
10018c2ecf20Sopenharmony_ci		break;
10028c2ecf20Sopenharmony_ci	case 16800000:
10038c2ecf20Sopenharmony_ci		clkfreqval = 0x02 << clkfreqshift;
10048c2ecf20Sopenharmony_ci		break;
10058c2ecf20Sopenharmony_ci	case 19200000:
10068c2ecf20Sopenharmony_ci		clkfreqval = 0x03 << clkfreqshift;
10078c2ecf20Sopenharmony_ci		break;
10088c2ecf20Sopenharmony_ci	case 26000000:
10098c2ecf20Sopenharmony_ci		clkfreqval = 0x04 << clkfreqshift;
10108c2ecf20Sopenharmony_ci		break;
10118c2ecf20Sopenharmony_ci	case 33600000:
10128c2ecf20Sopenharmony_ci		clkfreqval = 0x05 << clkfreqshift;
10138c2ecf20Sopenharmony_ci		break;
10148c2ecf20Sopenharmony_ci	case 38400000:
10158c2ecf20Sopenharmony_ci		clkfreqval = 0x06 << clkfreqshift;
10168c2ecf20Sopenharmony_ci		break;
10178c2ecf20Sopenharmony_ci	default:
10188c2ecf20Sopenharmony_ci		dev_err(cpcap->component->dev, "unsupported freq %u", freq);
10198c2ecf20Sopenharmony_ci		return -EINVAL;
10208c2ecf20Sopenharmony_ci	}
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	err = regmap_update_bits(cpcap->regmap, clkfreqreg,
10238c2ecf20Sopenharmony_ci				 clkfreqmask, clkfreqval);
10248c2ecf20Sopenharmony_ci	if (err)
10258c2ecf20Sopenharmony_ci		return err;
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	if (dai == CPCAP_DAI_VOICE) {
10288c2ecf20Sopenharmony_ci		cpcap->codec_clk_id = clk_id;
10298c2ecf20Sopenharmony_ci		cpcap->codec_freq = freq;
10308c2ecf20Sopenharmony_ci	}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	return 0;
10338c2ecf20Sopenharmony_ci}
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_cistatic int cpcap_set_samprate(struct cpcap_audio *cpcap, enum cpcap_dai dai,
10368c2ecf20Sopenharmony_ci			      int samplerate)
10378c2ecf20Sopenharmony_ci{
10388c2ecf20Sopenharmony_ci	struct snd_soc_component *component = cpcap->component;
10398c2ecf20Sopenharmony_ci	u16 sampreg, sampmask, sampshift, sampval, sampreset;
10408c2ecf20Sopenharmony_ci	int err, sampreadval;
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	switch (dai) {
10438c2ecf20Sopenharmony_ci	case CPCAP_DAI_HIFI:
10448c2ecf20Sopenharmony_ci		sampreg = CPCAP_REG_SDAC;
10458c2ecf20Sopenharmony_ci		sampshift = CPCAP_BIT_ST_SR0;
10468c2ecf20Sopenharmony_ci		sampreset = BIT(CPCAP_BIT_DF_RESET_ST_DAC) |
10478c2ecf20Sopenharmony_ci			    BIT(CPCAP_BIT_ST_CLOCK_TREE_RESET);
10488c2ecf20Sopenharmony_ci		break;
10498c2ecf20Sopenharmony_ci	case CPCAP_DAI_VOICE:
10508c2ecf20Sopenharmony_ci		sampreg = CPCAP_REG_CC;
10518c2ecf20Sopenharmony_ci		sampshift = CPCAP_BIT_CDC_SR0;
10528c2ecf20Sopenharmony_ci		sampreset = BIT(CPCAP_BIT_DF_RESET) |
10538c2ecf20Sopenharmony_ci			    BIT(CPCAP_BIT_CDC_CLOCK_TREE_RESET);
10548c2ecf20Sopenharmony_ci		break;
10558c2ecf20Sopenharmony_ci	default:
10568c2ecf20Sopenharmony_ci		dev_err(component->dev, "invalid DAI: %d", dai);
10578c2ecf20Sopenharmony_ci		return -EINVAL;
10588c2ecf20Sopenharmony_ci	}
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci	sampmask = 0xF << sampshift | sampreset;
10618c2ecf20Sopenharmony_ci	switch (samplerate) {
10628c2ecf20Sopenharmony_ci	case 48000:
10638c2ecf20Sopenharmony_ci		sampval = 0x8 << sampshift;
10648c2ecf20Sopenharmony_ci		break;
10658c2ecf20Sopenharmony_ci	case 44100:
10668c2ecf20Sopenharmony_ci		sampval = 0x7 << sampshift;
10678c2ecf20Sopenharmony_ci		break;
10688c2ecf20Sopenharmony_ci	case 32000:
10698c2ecf20Sopenharmony_ci		sampval = 0x6 << sampshift;
10708c2ecf20Sopenharmony_ci		break;
10718c2ecf20Sopenharmony_ci	case 24000:
10728c2ecf20Sopenharmony_ci		sampval = 0x5 << sampshift;
10738c2ecf20Sopenharmony_ci		break;
10748c2ecf20Sopenharmony_ci	case 22050:
10758c2ecf20Sopenharmony_ci		sampval = 0x4 << sampshift;
10768c2ecf20Sopenharmony_ci		break;
10778c2ecf20Sopenharmony_ci	case 16000:
10788c2ecf20Sopenharmony_ci		sampval = 0x3 << sampshift;
10798c2ecf20Sopenharmony_ci		break;
10808c2ecf20Sopenharmony_ci	case 12000:
10818c2ecf20Sopenharmony_ci		sampval = 0x2 << sampshift;
10828c2ecf20Sopenharmony_ci		break;
10838c2ecf20Sopenharmony_ci	case 11025:
10848c2ecf20Sopenharmony_ci		sampval = 0x1 << sampshift;
10858c2ecf20Sopenharmony_ci		break;
10868c2ecf20Sopenharmony_ci	case 8000:
10878c2ecf20Sopenharmony_ci		sampval = 0x0 << sampshift;
10888c2ecf20Sopenharmony_ci		break;
10898c2ecf20Sopenharmony_ci	default:
10908c2ecf20Sopenharmony_ci		dev_err(component->dev, "unsupported samplerate %d", samplerate);
10918c2ecf20Sopenharmony_ci		return -EINVAL;
10928c2ecf20Sopenharmony_ci	}
10938c2ecf20Sopenharmony_ci	err = regmap_update_bits(cpcap->regmap, sampreg,
10948c2ecf20Sopenharmony_ci				 sampmask, sampval | sampreset);
10958c2ecf20Sopenharmony_ci	if (err)
10968c2ecf20Sopenharmony_ci		return err;
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ci	/* Wait for clock tree reset to complete */
10998c2ecf20Sopenharmony_ci	mdelay(CLOCK_TREE_RESET_TIME);
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	err = regmap_read(cpcap->regmap, sampreg, &sampreadval);
11028c2ecf20Sopenharmony_ci	if (err)
11038c2ecf20Sopenharmony_ci		return err;
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	if (sampreadval & sampreset) {
11068c2ecf20Sopenharmony_ci		dev_err(component->dev, "reset self-clear failed: %04x",
11078c2ecf20Sopenharmony_ci			sampreadval);
11088c2ecf20Sopenharmony_ci		return -EIO;
11098c2ecf20Sopenharmony_ci	}
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci	return 0;
11128c2ecf20Sopenharmony_ci}
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_cistatic int cpcap_hifi_hw_params(struct snd_pcm_substream *substream,
11158c2ecf20Sopenharmony_ci				struct snd_pcm_hw_params *params,
11168c2ecf20Sopenharmony_ci				struct snd_soc_dai *dai)
11178c2ecf20Sopenharmony_ci{
11188c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
11198c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
11208c2ecf20Sopenharmony_ci	int rate = params_rate(params);
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "HiFi setup HW params: rate=%d", rate);
11238c2ecf20Sopenharmony_ci	return cpcap_set_samprate(cpcap, CPCAP_DAI_HIFI, rate);
11248c2ecf20Sopenharmony_ci}
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_cistatic int cpcap_hifi_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
11278c2ecf20Sopenharmony_ci				     unsigned int freq, int dir)
11288c2ecf20Sopenharmony_ci{
11298c2ecf20Sopenharmony_ci	struct snd_soc_component *component = codec_dai->component;
11308c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
11318c2ecf20Sopenharmony_ci	struct device *dev = component->dev;
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci	dev_dbg(dev, "HiFi setup sysclk: clk_id=%u, freq=%u", clk_id, freq);
11348c2ecf20Sopenharmony_ci	return cpcap_set_sysclk(cpcap, CPCAP_DAI_HIFI, clk_id, freq);
11358c2ecf20Sopenharmony_ci}
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_cistatic int cpcap_hifi_set_dai_fmt(struct snd_soc_dai *codec_dai,
11388c2ecf20Sopenharmony_ci				  unsigned int fmt)
11398c2ecf20Sopenharmony_ci{
11408c2ecf20Sopenharmony_ci	struct snd_soc_component *component = codec_dai->component;
11418c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
11428c2ecf20Sopenharmony_ci	struct device *dev = component->dev;
11438c2ecf20Sopenharmony_ci	static const u16 reg = CPCAP_REG_SDACDI;
11448c2ecf20Sopenharmony_ci	static const u16 mask =
11458c2ecf20Sopenharmony_ci		BIT(CPCAP_BIT_SMB_ST_DAC) |
11468c2ecf20Sopenharmony_ci		BIT(CPCAP_BIT_ST_CLK_INV) |
11478c2ecf20Sopenharmony_ci		BIT(CPCAP_BIT_ST_FS_INV) |
11488c2ecf20Sopenharmony_ci		BIT(CPCAP_BIT_ST_DIG_AUD_FS0) |
11498c2ecf20Sopenharmony_ci		BIT(CPCAP_BIT_ST_DIG_AUD_FS1) |
11508c2ecf20Sopenharmony_ci		BIT(CPCAP_BIT_ST_L_TIMESLOT0) |
11518c2ecf20Sopenharmony_ci		BIT(CPCAP_BIT_ST_L_TIMESLOT1) |
11528c2ecf20Sopenharmony_ci		BIT(CPCAP_BIT_ST_L_TIMESLOT2) |
11538c2ecf20Sopenharmony_ci		BIT(CPCAP_BIT_ST_R_TIMESLOT0) |
11548c2ecf20Sopenharmony_ci		BIT(CPCAP_BIT_ST_R_TIMESLOT1) |
11558c2ecf20Sopenharmony_ci		BIT(CPCAP_BIT_ST_R_TIMESLOT2);
11568c2ecf20Sopenharmony_ci	u16 val = 0x0000;
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	dev_dbg(dev, "HiFi setup dai format (%08x)", fmt);
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	/*
11618c2ecf20Sopenharmony_ci	 * "HiFi Playback" should always be configured as
11628c2ecf20Sopenharmony_ci	 * SND_SOC_DAIFMT_CBM_CFM - codec clk & frm master
11638c2ecf20Sopenharmony_ci	 * SND_SOC_DAIFMT_I2S - I2S mode
11648c2ecf20Sopenharmony_ci	 */
11658c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
11668c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_CBM_CFM:
11678c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_SMB_ST_DAC);
11688c2ecf20Sopenharmony_ci		break;
11698c2ecf20Sopenharmony_ci	default:
11708c2ecf20Sopenharmony_ci		dev_err(dev, "HiFi dai fmt failed: CPCAP should be master");
11718c2ecf20Sopenharmony_ci		return -EINVAL;
11728c2ecf20Sopenharmony_ci	}
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
11758c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_IB_IF:
11768c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_ST_FS_INV);
11778c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_ST_CLK_INV);
11788c2ecf20Sopenharmony_ci		break;
11798c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_IB_NF:
11808c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_ST_FS_INV);
11818c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_ST_CLK_INV);
11828c2ecf20Sopenharmony_ci		break;
11838c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_NB_IF:
11848c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_ST_FS_INV);
11858c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_ST_CLK_INV);
11868c2ecf20Sopenharmony_ci		break;
11878c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_NB_NF:
11888c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_ST_FS_INV);
11898c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_ST_CLK_INV);
11908c2ecf20Sopenharmony_ci		break;
11918c2ecf20Sopenharmony_ci	default:
11928c2ecf20Sopenharmony_ci		dev_err(dev, "HiFi dai fmt failed: unsupported clock invert mode");
11938c2ecf20Sopenharmony_ci		return -EINVAL;
11948c2ecf20Sopenharmony_ci	}
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	if (val & BIT(CPCAP_BIT_ST_CLK_INV))
11978c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_ST_CLK_INV);
11988c2ecf20Sopenharmony_ci	else
11998c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_ST_CLK_INV);
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
12028c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_I2S:
12038c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_ST_DIG_AUD_FS0);
12048c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_ST_DIG_AUD_FS1);
12058c2ecf20Sopenharmony_ci		break;
12068c2ecf20Sopenharmony_ci	default:
12078c2ecf20Sopenharmony_ci		/* 01 - 4 slots network mode */
12088c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_ST_DIG_AUD_FS0);
12098c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_ST_DIG_AUD_FS1);
12108c2ecf20Sopenharmony_ci		/* L on slot 1 */
12118c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_ST_L_TIMESLOT0);
12128c2ecf20Sopenharmony_ci		break;
12138c2ecf20Sopenharmony_ci	}
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci	dev_dbg(dev, "HiFi dai format: val=%04x", val);
12168c2ecf20Sopenharmony_ci	return regmap_update_bits(cpcap->regmap, reg, mask, val);
12178c2ecf20Sopenharmony_ci}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_cistatic int cpcap_hifi_set_mute(struct snd_soc_dai *dai, int mute, int direction)
12208c2ecf20Sopenharmony_ci{
12218c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
12228c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
12238c2ecf20Sopenharmony_ci	static const u16 reg = CPCAP_REG_RXSDOA;
12248c2ecf20Sopenharmony_ci	static const u16 mask = BIT(CPCAP_BIT_ST_DAC_SW);
12258c2ecf20Sopenharmony_ci	u16 val;
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	if (mute)
12288c2ecf20Sopenharmony_ci		val = 0;
12298c2ecf20Sopenharmony_ci	else
12308c2ecf20Sopenharmony_ci		val = BIT(CPCAP_BIT_ST_DAC_SW);
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "HiFi mute: %d", mute);
12338c2ecf20Sopenharmony_ci	return regmap_update_bits(cpcap->regmap, reg, mask, val);
12348c2ecf20Sopenharmony_ci}
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops cpcap_dai_hifi_ops = {
12378c2ecf20Sopenharmony_ci	.hw_params	= cpcap_hifi_hw_params,
12388c2ecf20Sopenharmony_ci	.set_sysclk	= cpcap_hifi_set_dai_sysclk,
12398c2ecf20Sopenharmony_ci	.set_fmt	= cpcap_hifi_set_dai_fmt,
12408c2ecf20Sopenharmony_ci	.mute_stream	= cpcap_hifi_set_mute,
12418c2ecf20Sopenharmony_ci	.no_capture_mute = 1,
12428c2ecf20Sopenharmony_ci};
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_cistatic int cpcap_voice_hw_params(struct snd_pcm_substream *substream,
12458c2ecf20Sopenharmony_ci				 struct snd_pcm_hw_params *params,
12468c2ecf20Sopenharmony_ci				 struct snd_soc_dai *dai)
12478c2ecf20Sopenharmony_ci{
12488c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
12498c2ecf20Sopenharmony_ci	struct device *dev = component->dev;
12508c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
12518c2ecf20Sopenharmony_ci	static const u16 reg_cdi = CPCAP_REG_CDI;
12528c2ecf20Sopenharmony_ci	int rate = params_rate(params);
12538c2ecf20Sopenharmony_ci	int channels = params_channels(params);
12548c2ecf20Sopenharmony_ci	int direction = substream->stream;
12558c2ecf20Sopenharmony_ci	u16 val, mask;
12568c2ecf20Sopenharmony_ci	int err;
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	dev_dbg(dev, "Voice setup HW params: rate=%d, direction=%d, chan=%d",
12598c2ecf20Sopenharmony_ci		rate, direction, channels);
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	err = cpcap_set_samprate(cpcap, CPCAP_DAI_VOICE, rate);
12628c2ecf20Sopenharmony_ci	if (err)
12638c2ecf20Sopenharmony_ci		return err;
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci	if (direction == SNDRV_PCM_STREAM_CAPTURE) {
12668c2ecf20Sopenharmony_ci		mask = 0x0000;
12678c2ecf20Sopenharmony_ci		mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);
12688c2ecf20Sopenharmony_ci		mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT1);
12698c2ecf20Sopenharmony_ci		mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT2);
12708c2ecf20Sopenharmony_ci		mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT0);
12718c2ecf20Sopenharmony_ci		mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT1);
12728c2ecf20Sopenharmony_ci		mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT2);
12738c2ecf20Sopenharmony_ci		val = 0x0000;
12748c2ecf20Sopenharmony_ci		if (channels >= 2)
12758c2ecf20Sopenharmony_ci			val = BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);
12768c2ecf20Sopenharmony_ci		err = regmap_update_bits(cpcap->regmap, reg_cdi, mask, val);
12778c2ecf20Sopenharmony_ci		if (err)
12788c2ecf20Sopenharmony_ci			return err;
12798c2ecf20Sopenharmony_ci	}
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	return 0;
12828c2ecf20Sopenharmony_ci}
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_cistatic int cpcap_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
12858c2ecf20Sopenharmony_ci				      unsigned int freq, int dir)
12868c2ecf20Sopenharmony_ci{
12878c2ecf20Sopenharmony_ci	struct snd_soc_component *component = codec_dai->component;
12888c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "Voice setup sysclk: clk_id=%u, freq=%u",
12918c2ecf20Sopenharmony_ci		clk_id, freq);
12928c2ecf20Sopenharmony_ci	return cpcap_set_sysclk(cpcap, CPCAP_DAI_VOICE, clk_id, freq);
12938c2ecf20Sopenharmony_ci}
12948c2ecf20Sopenharmony_ci
12958c2ecf20Sopenharmony_cistatic int cpcap_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
12968c2ecf20Sopenharmony_ci				   unsigned int fmt)
12978c2ecf20Sopenharmony_ci{
12988c2ecf20Sopenharmony_ci	struct snd_soc_component *component = codec_dai->component;
12998c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
13008c2ecf20Sopenharmony_ci	static const u16 mask = BIT(CPCAP_BIT_SMB_CDC) |
13018c2ecf20Sopenharmony_ci				BIT(CPCAP_BIT_CLK_INV) |
13028c2ecf20Sopenharmony_ci				BIT(CPCAP_BIT_FS_INV) |
13038c2ecf20Sopenharmony_ci				BIT(CPCAP_BIT_CDC_DIG_AUD_FS0) |
13048c2ecf20Sopenharmony_ci				BIT(CPCAP_BIT_CDC_DIG_AUD_FS1);
13058c2ecf20Sopenharmony_ci	u16 val = 0x0000;
13068c2ecf20Sopenharmony_ci	int err;
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "Voice setup dai format (%08x)", fmt);
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci	/*
13118c2ecf20Sopenharmony_ci	 * "Voice Playback" and "Voice Capture" should always be
13128c2ecf20Sopenharmony_ci	 * configured as SND_SOC_DAIFMT_CBM_CFM - codec clk & frm
13138c2ecf20Sopenharmony_ci	 * master
13148c2ecf20Sopenharmony_ci	 */
13158c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
13168c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_CBM_CFM:
13178c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_SMB_CDC);
13188c2ecf20Sopenharmony_ci		break;
13198c2ecf20Sopenharmony_ci	default:
13208c2ecf20Sopenharmony_ci		dev_err(component->dev, "Voice dai fmt failed: CPCAP should be the master");
13218c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_SMB_CDC);
13228c2ecf20Sopenharmony_ci		break;
13238c2ecf20Sopenharmony_ci	}
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
13268c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_IB_IF:
13278c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_CLK_INV);
13288c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_FS_INV);
13298c2ecf20Sopenharmony_ci		break;
13308c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_IB_NF:
13318c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_CLK_INV);
13328c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_FS_INV);
13338c2ecf20Sopenharmony_ci		break;
13348c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_NB_IF:
13358c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_CLK_INV);
13368c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_FS_INV);
13378c2ecf20Sopenharmony_ci		break;
13388c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_NB_NF:
13398c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_CLK_INV);
13408c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_FS_INV);
13418c2ecf20Sopenharmony_ci		break;
13428c2ecf20Sopenharmony_ci	default:
13438c2ecf20Sopenharmony_ci		dev_err(component->dev, "Voice dai fmt failed: unsupported clock invert mode");
13448c2ecf20Sopenharmony_ci		break;
13458c2ecf20Sopenharmony_ci	}
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	if (val & BIT(CPCAP_BIT_CLK_INV))
13488c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_CLK_INV);
13498c2ecf20Sopenharmony_ci	else
13508c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_CLK_INV);
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
13538c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_I2S:
13548c2ecf20Sopenharmony_ci		/* 11 - true I2S mode */
13558c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_CDC_DIG_AUD_FS0);
13568c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_CDC_DIG_AUD_FS1);
13578c2ecf20Sopenharmony_ci		break;
13588c2ecf20Sopenharmony_ci	default:
13598c2ecf20Sopenharmony_ci		/* 4 timeslots network mode */
13608c2ecf20Sopenharmony_ci		val |= BIT(CPCAP_BIT_CDC_DIG_AUD_FS0);
13618c2ecf20Sopenharmony_ci		val &= ~BIT(CPCAP_BIT_CDC_DIG_AUD_FS1);
13628c2ecf20Sopenharmony_ci		break;
13638c2ecf20Sopenharmony_ci	}
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "Voice dai format: val=%04x", val);
13668c2ecf20Sopenharmony_ci	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI, mask, val);
13678c2ecf20Sopenharmony_ci	if (err)
13688c2ecf20Sopenharmony_ci		return err;
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_ci	cpcap->codec_format = val;
13718c2ecf20Sopenharmony_ci	return 0;
13728c2ecf20Sopenharmony_ci}
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_cistatic int cpcap_voice_set_mute(struct snd_soc_dai *dai,
13758c2ecf20Sopenharmony_ci				int mute, int direction)
13768c2ecf20Sopenharmony_ci{
13778c2ecf20Sopenharmony_ci	struct snd_soc_component *component = dai->component;
13788c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
13798c2ecf20Sopenharmony_ci	static const u16 reg = CPCAP_REG_RXCOA;
13808c2ecf20Sopenharmony_ci	static const u16 mask = BIT(CPCAP_BIT_CDC_SW);
13818c2ecf20Sopenharmony_ci	u16 val;
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci	if (mute)
13848c2ecf20Sopenharmony_ci		val = 0;
13858c2ecf20Sopenharmony_ci	else
13868c2ecf20Sopenharmony_ci		val = BIT(CPCAP_BIT_CDC_SW);
13878c2ecf20Sopenharmony_ci
13888c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "Voice mute: %d", mute);
13898c2ecf20Sopenharmony_ci	return regmap_update_bits(cpcap->regmap, reg, mask, val);
13908c2ecf20Sopenharmony_ci};
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops cpcap_dai_voice_ops = {
13938c2ecf20Sopenharmony_ci	.hw_params	= cpcap_voice_hw_params,
13948c2ecf20Sopenharmony_ci	.set_sysclk	= cpcap_voice_set_dai_sysclk,
13958c2ecf20Sopenharmony_ci	.set_fmt	= cpcap_voice_set_dai_fmt,
13968c2ecf20Sopenharmony_ci	.mute_stream	= cpcap_voice_set_mute,
13978c2ecf20Sopenharmony_ci	.no_capture_mute = 1,
13988c2ecf20Sopenharmony_ci};
13998c2ecf20Sopenharmony_ci
14008c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver cpcap_dai[] = {
14018c2ecf20Sopenharmony_ci{
14028c2ecf20Sopenharmony_ci	.id = 0,
14038c2ecf20Sopenharmony_ci	.name = "cpcap-hifi",
14048c2ecf20Sopenharmony_ci	.playback = {
14058c2ecf20Sopenharmony_ci		.stream_name = "HiFi Playback",
14068c2ecf20Sopenharmony_ci		.channels_min = 2,
14078c2ecf20Sopenharmony_ci		.channels_max = 2,
14088c2ecf20Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000_48000,
14098c2ecf20Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE,
14108c2ecf20Sopenharmony_ci	},
14118c2ecf20Sopenharmony_ci	.ops = &cpcap_dai_hifi_ops,
14128c2ecf20Sopenharmony_ci},
14138c2ecf20Sopenharmony_ci{
14148c2ecf20Sopenharmony_ci	.id = 1,
14158c2ecf20Sopenharmony_ci	.name = "cpcap-voice",
14168c2ecf20Sopenharmony_ci	.playback = {
14178c2ecf20Sopenharmony_ci		.stream_name = "Voice Playback",
14188c2ecf20Sopenharmony_ci		.channels_min = 1,
14198c2ecf20Sopenharmony_ci		.channels_max = 1,
14208c2ecf20Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000_48000,
14218c2ecf20Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
14228c2ecf20Sopenharmony_ci	},
14238c2ecf20Sopenharmony_ci	.capture = {
14248c2ecf20Sopenharmony_ci		.stream_name = "Voice Capture",
14258c2ecf20Sopenharmony_ci		.channels_min = 1,
14268c2ecf20Sopenharmony_ci		.channels_max = 2,
14278c2ecf20Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000_48000,
14288c2ecf20Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE,
14298c2ecf20Sopenharmony_ci	},
14308c2ecf20Sopenharmony_ci	.ops = &cpcap_dai_voice_ops,
14318c2ecf20Sopenharmony_ci},
14328c2ecf20Sopenharmony_ci};
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_cistatic int cpcap_dai_mux(struct cpcap_audio *cpcap, bool swap_dai_configuration)
14358c2ecf20Sopenharmony_ci{
14368c2ecf20Sopenharmony_ci	u16 hifi_val, voice_val;
14378c2ecf20Sopenharmony_ci	u16 hifi_mask = BIT(CPCAP_BIT_DIG_AUD_IN_ST_DAC);
14388c2ecf20Sopenharmony_ci	u16 voice_mask = BIT(CPCAP_BIT_DIG_AUD_IN);
14398c2ecf20Sopenharmony_ci	int err;
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_ci	if (!swap_dai_configuration) {
14448c2ecf20Sopenharmony_ci		/* Codec on DAI0, HiFi on DAI1 */
14458c2ecf20Sopenharmony_ci		voice_val = 0;
14468c2ecf20Sopenharmony_ci		hifi_val = hifi_mask;
14478c2ecf20Sopenharmony_ci	} else {
14488c2ecf20Sopenharmony_ci		/* Codec on DAI1, HiFi on DAI0 */
14498c2ecf20Sopenharmony_ci		voice_val = voice_mask;
14508c2ecf20Sopenharmony_ci		hifi_val = 0;
14518c2ecf20Sopenharmony_ci	}
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,
14548c2ecf20Sopenharmony_ci				 voice_mask, voice_val);
14558c2ecf20Sopenharmony_ci	if (err)
14568c2ecf20Sopenharmony_ci		return err;
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ci	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_SDACDI,
14598c2ecf20Sopenharmony_ci				 hifi_mask, hifi_val);
14608c2ecf20Sopenharmony_ci	if (err)
14618c2ecf20Sopenharmony_ci		return err;
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_ci	return 0;
14648c2ecf20Sopenharmony_ci}
14658c2ecf20Sopenharmony_ci
14668c2ecf20Sopenharmony_cistatic int cpcap_audio_reset(struct snd_soc_component *component,
14678c2ecf20Sopenharmony_ci			     bool swap_dai_configuration)
14688c2ecf20Sopenharmony_ci{
14698c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
14708c2ecf20Sopenharmony_ci	int i, err = 0;
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_ci	dev_dbg(component->dev, "init audio codec");
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(cpcap_default_regs); i++) {
14758c2ecf20Sopenharmony_ci		err = regmap_update_bits(cpcap->regmap,
14768c2ecf20Sopenharmony_ci					 cpcap_default_regs[i].reg,
14778c2ecf20Sopenharmony_ci					 cpcap_default_regs[i].mask,
14788c2ecf20Sopenharmony_ci					 cpcap_default_regs[i].val);
14798c2ecf20Sopenharmony_ci		if (err)
14808c2ecf20Sopenharmony_ci			return err;
14818c2ecf20Sopenharmony_ci	}
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_ci	/* setup default settings */
14848c2ecf20Sopenharmony_ci	err = cpcap_dai_mux(cpcap, swap_dai_configuration);
14858c2ecf20Sopenharmony_ci	if (err)
14868c2ecf20Sopenharmony_ci		return err;
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci	err = cpcap_set_sysclk(cpcap, CPCAP_DAI_HIFI, 0, 26000000);
14898c2ecf20Sopenharmony_ci	if (err)
14908c2ecf20Sopenharmony_ci		return err;
14918c2ecf20Sopenharmony_ci	err = cpcap_set_sysclk(cpcap, CPCAP_DAI_VOICE, 0, 26000000);
14928c2ecf20Sopenharmony_ci	if (err)
14938c2ecf20Sopenharmony_ci		return err;
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci	err = cpcap_set_samprate(cpcap, CPCAP_DAI_HIFI, 48000);
14968c2ecf20Sopenharmony_ci	if (err)
14978c2ecf20Sopenharmony_ci		return err;
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci	err = cpcap_set_samprate(cpcap, CPCAP_DAI_VOICE, 48000);
15008c2ecf20Sopenharmony_ci	if (err)
15018c2ecf20Sopenharmony_ci		return err;
15028c2ecf20Sopenharmony_ci
15038c2ecf20Sopenharmony_ci	return 0;
15048c2ecf20Sopenharmony_ci}
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_cistatic int cpcap_soc_probe(struct snd_soc_component *component)
15078c2ecf20Sopenharmony_ci{
15088c2ecf20Sopenharmony_ci	struct cpcap_audio *cpcap;
15098c2ecf20Sopenharmony_ci	int err;
15108c2ecf20Sopenharmony_ci
15118c2ecf20Sopenharmony_ci	cpcap = devm_kzalloc(component->dev, sizeof(*cpcap), GFP_KERNEL);
15128c2ecf20Sopenharmony_ci	if (!cpcap)
15138c2ecf20Sopenharmony_ci		return -ENOMEM;
15148c2ecf20Sopenharmony_ci	snd_soc_component_set_drvdata(component, cpcap);
15158c2ecf20Sopenharmony_ci	cpcap->component = component;
15168c2ecf20Sopenharmony_ci
15178c2ecf20Sopenharmony_ci	cpcap->regmap = dev_get_regmap(component->dev->parent, NULL);
15188c2ecf20Sopenharmony_ci	if (!cpcap->regmap)
15198c2ecf20Sopenharmony_ci		return -ENODEV;
15208c2ecf20Sopenharmony_ci	snd_soc_component_init_regmap(component, cpcap->regmap);
15218c2ecf20Sopenharmony_ci
15228c2ecf20Sopenharmony_ci	err = cpcap_get_vendor(component->dev, cpcap->regmap, &cpcap->vendor);
15238c2ecf20Sopenharmony_ci	if (err)
15248c2ecf20Sopenharmony_ci		return err;
15258c2ecf20Sopenharmony_ci
15268c2ecf20Sopenharmony_ci	return cpcap_audio_reset(component, false);
15278c2ecf20Sopenharmony_ci}
15288c2ecf20Sopenharmony_ci
15298c2ecf20Sopenharmony_cistatic struct snd_soc_component_driver soc_codec_dev_cpcap = {
15308c2ecf20Sopenharmony_ci	.probe			= cpcap_soc_probe,
15318c2ecf20Sopenharmony_ci	.controls		= cpcap_snd_controls,
15328c2ecf20Sopenharmony_ci	.num_controls		= ARRAY_SIZE(cpcap_snd_controls),
15338c2ecf20Sopenharmony_ci	.dapm_widgets		= cpcap_dapm_widgets,
15348c2ecf20Sopenharmony_ci	.num_dapm_widgets	= ARRAY_SIZE(cpcap_dapm_widgets),
15358c2ecf20Sopenharmony_ci	.dapm_routes		= intercon,
15368c2ecf20Sopenharmony_ci	.num_dapm_routes	= ARRAY_SIZE(intercon),
15378c2ecf20Sopenharmony_ci	.idle_bias_on		= 1,
15388c2ecf20Sopenharmony_ci	.use_pmdown_time	= 1,
15398c2ecf20Sopenharmony_ci	.endianness		= 1,
15408c2ecf20Sopenharmony_ci	.non_legacy_dai_naming	= 1,
15418c2ecf20Sopenharmony_ci};
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_cistatic int cpcap_codec_probe(struct platform_device *pdev)
15448c2ecf20Sopenharmony_ci{
15458c2ecf20Sopenharmony_ci	struct device_node *codec_node =
15468c2ecf20Sopenharmony_ci		of_get_child_by_name(pdev->dev.parent->of_node, "audio-codec");
15478c2ecf20Sopenharmony_ci	if (!codec_node)
15488c2ecf20Sopenharmony_ci		return -ENODEV;
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci	pdev->dev.of_node = codec_node;
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci	return devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_cpcap,
15538c2ecf20Sopenharmony_ci				      cpcap_dai, ARRAY_SIZE(cpcap_dai));
15548c2ecf20Sopenharmony_ci}
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_cistatic struct platform_driver cpcap_codec_driver = {
15578c2ecf20Sopenharmony_ci	.probe		= cpcap_codec_probe,
15588c2ecf20Sopenharmony_ci	.driver		= {
15598c2ecf20Sopenharmony_ci		.name	= "cpcap-codec",
15608c2ecf20Sopenharmony_ci	},
15618c2ecf20Sopenharmony_ci};
15628c2ecf20Sopenharmony_cimodule_platform_driver(cpcap_codec_driver);
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:cpcap-codec");
15658c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ASoC CPCAP codec driver");
15668c2ecf20Sopenharmony_ciMODULE_AUTHOR("Sebastian Reichel");
15678c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
1568