brintos

brintos / linux-shallow public Read only

0
0
Text · 50.6 KiB · 4f9dabd Raw
1690 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * ALSA SoC CPCAP codec driver4 *5 * Copyright (C) 2017 - 2018 Sebastian Reichel <sre@kernel.org>6 *7 * Very loosely based on original driver from Motorola:8 * Copyright (C) 2007 - 2009 Motorola, Inc.9 */10 11#include <linux/module.h>12#include <linux/regmap.h>13#include <linux/platform_device.h>14#include <linux/mfd/motorola-cpcap.h>15#include <sound/core.h>16#include <sound/soc.h>17#include <sound/tlv.h>18 19/* Register 512 CPCAP_REG_VAUDIOC --- Audio Regulator and Bias Voltage */20#define CPCAP_BIT_AUDIO_LOW_PWR           621#define CPCAP_BIT_AUD_LOWPWR_SPEED        522#define CPCAP_BIT_VAUDIOPRISTBY           423#define CPCAP_BIT_VAUDIO_MODE1            224#define CPCAP_BIT_VAUDIO_MODE0            125#define CPCAP_BIT_V_AUDIO_EN              026 27/* Register 513 CPCAP_REG_CC     --- CODEC */28#define CPCAP_BIT_CDC_CLK2                1529#define CPCAP_BIT_CDC_CLK1                1430#define CPCAP_BIT_CDC_CLK0                1331#define CPCAP_BIT_CDC_SR3                 1232#define CPCAP_BIT_CDC_SR2                 1133#define CPCAP_BIT_CDC_SR1                 1034#define CPCAP_BIT_CDC_SR0                 935#define CPCAP_BIT_CDC_CLOCK_TREE_RESET    836#define CPCAP_BIT_MIC2_CDC_EN             737#define CPCAP_BIT_CDC_EN_RX               638#define CPCAP_BIT_DF_RESET                539#define CPCAP_BIT_MIC1_CDC_EN             440#define CPCAP_BIT_AUDOHPF_1		  341#define CPCAP_BIT_AUDOHPF_0		  242#define CPCAP_BIT_AUDIHPF_1		  143#define CPCAP_BIT_AUDIHPF_0		  044 45/* Register 514 CPCAP_REG_CDI    --- CODEC Digital Audio Interface */46#define CPCAP_BIT_CDC_PLL_SEL             1547#define CPCAP_BIT_CLK_IN_SEL              1348#define CPCAP_BIT_DIG_AUD_IN              1249#define CPCAP_BIT_CDC_CLK_EN              1150#define CPCAP_BIT_CDC_DIG_AUD_FS1         1051#define CPCAP_BIT_CDC_DIG_AUD_FS0         952#define CPCAP_BIT_MIC2_TIMESLOT2          853#define CPCAP_BIT_MIC2_TIMESLOT1          754#define CPCAP_BIT_MIC2_TIMESLOT0          655#define CPCAP_BIT_MIC1_RX_TIMESLOT2       556#define CPCAP_BIT_MIC1_RX_TIMESLOT1       457#define CPCAP_BIT_MIC1_RX_TIMESLOT0       358#define CPCAP_BIT_FS_INV                  259#define CPCAP_BIT_CLK_INV                 160#define CPCAP_BIT_SMB_CDC                 061 62/* Register 515 CPCAP_REG_SDAC   --- Stereo DAC */63#define CPCAP_BIT_FSYNC_CLK_IN_COMMON     1164#define CPCAP_BIT_SLAVE_PLL_CLK_INPUT     1065#define CPCAP_BIT_ST_CLOCK_TREE_RESET     966#define CPCAP_BIT_DF_RESET_ST_DAC         867#define CPCAP_BIT_ST_SR3                  768#define CPCAP_BIT_ST_SR2                  669#define CPCAP_BIT_ST_SR1                  570#define CPCAP_BIT_ST_SR0                  471#define CPCAP_BIT_ST_DAC_CLK2             372#define CPCAP_BIT_ST_DAC_CLK1             273#define CPCAP_BIT_ST_DAC_CLK0             174#define CPCAP_BIT_ST_DAC_EN               075 76/* Register 516 CPCAP_REG_SDACDI --- Stereo DAC Digital Audio Interface */77#define CPCAP_BIT_ST_L_TIMESLOT2          1378#define CPCAP_BIT_ST_L_TIMESLOT1          1279#define CPCAP_BIT_ST_L_TIMESLOT0          1180#define CPCAP_BIT_ST_R_TIMESLOT2          1081#define CPCAP_BIT_ST_R_TIMESLOT1          982#define CPCAP_BIT_ST_R_TIMESLOT0          883#define CPCAP_BIT_ST_DAC_CLK_IN_SEL       784#define CPCAP_BIT_ST_FS_INV               685#define CPCAP_BIT_ST_CLK_INV              586#define CPCAP_BIT_ST_DIG_AUD_FS1          487#define CPCAP_BIT_ST_DIG_AUD_FS0          388#define CPCAP_BIT_DIG_AUD_IN_ST_DAC       289#define CPCAP_BIT_ST_CLK_EN               190#define CPCAP_BIT_SMB_ST_DAC              091 92/* Register 517 CPCAP_REG_TXI    --- TX Interface */93#define CPCAP_BIT_PTT_TH		1594#define CPCAP_BIT_PTT_CMP_EN		1495#define CPCAP_BIT_HS_ID_TX		1396#define CPCAP_BIT_MB_ON2		1297#define CPCAP_BIT_MB_ON1L		1198#define CPCAP_BIT_MB_ON1R		1099#define CPCAP_BIT_RX_L_ENCODE		9100#define CPCAP_BIT_RX_R_ENCODE		8101#define CPCAP_BIT_MIC2_MUX		7102#define CPCAP_BIT_MIC2_PGA_EN		6103#define CPCAP_BIT_CDET_DIS		5104#define CPCAP_BIT_EMU_MIC_MUX		4105#define CPCAP_BIT_HS_MIC_MUX		3106#define CPCAP_BIT_MIC1_MUX		2107#define CPCAP_BIT_MIC1_PGA_EN		1108#define CPCAP_BIT_DLM			0109 110/* Register 518 CPCAP_REG_TXMP   --- Mic Gain */111#define CPCAP_BIT_MB_BIAS_R1              11112#define CPCAP_BIT_MB_BIAS_R0              10113#define CPCAP_BIT_MIC2_GAIN_4             9114#define CPCAP_BIT_MIC2_GAIN_3             8115#define CPCAP_BIT_MIC2_GAIN_2             7116#define CPCAP_BIT_MIC2_GAIN_1             6117#define CPCAP_BIT_MIC2_GAIN_0             5118#define CPCAP_BIT_MIC1_GAIN_4             4119#define CPCAP_BIT_MIC1_GAIN_3             3120#define CPCAP_BIT_MIC1_GAIN_2             2121#define CPCAP_BIT_MIC1_GAIN_1             1122#define CPCAP_BIT_MIC1_GAIN_0             0123 124/* Register 519 CPCAP_REG_RXOA   --- RX Output Amplifier */125#define CPCAP_BIT_UNUSED_519_15		15126#define CPCAP_BIT_UNUSED_519_14		14127#define CPCAP_BIT_UNUSED_519_13		13128#define CPCAP_BIT_STDAC_LOW_PWR_DISABLE	12129#define CPCAP_BIT_HS_LOW_PWR		11130#define CPCAP_BIT_HS_ID_RX		10131#define CPCAP_BIT_ST_HS_CP_EN		9132#define CPCAP_BIT_EMU_SPKR_R_EN		8133#define CPCAP_BIT_EMU_SPKR_L_EN		7134#define CPCAP_BIT_HS_L_EN		6135#define CPCAP_BIT_HS_R_EN		5136#define CPCAP_BIT_A4_LINEOUT_L_EN	4137#define CPCAP_BIT_A4_LINEOUT_R_EN	3138#define CPCAP_BIT_A2_LDSP_L_EN		2139#define CPCAP_BIT_A2_LDSP_R_EN		1140#define CPCAP_BIT_A1_EAR_EN		0141 142/* Register 520 CPCAP_REG_RXVC   --- RX Volume Control */143#define CPCAP_BIT_VOL_EXT3                15144#define CPCAP_BIT_VOL_EXT2                14145#define CPCAP_BIT_VOL_EXT1                13146#define CPCAP_BIT_VOL_EXT0                12147#define CPCAP_BIT_VOL_DAC3                11148#define CPCAP_BIT_VOL_DAC2                10149#define CPCAP_BIT_VOL_DAC1                9150#define CPCAP_BIT_VOL_DAC0                8151#define CPCAP_BIT_VOL_DAC_LSB_1dB1        7152#define CPCAP_BIT_VOL_DAC_LSB_1dB0        6153#define CPCAP_BIT_VOL_CDC3                5154#define CPCAP_BIT_VOL_CDC2                4155#define CPCAP_BIT_VOL_CDC1                3156#define CPCAP_BIT_VOL_CDC0                2157#define CPCAP_BIT_VOL_CDC_LSB_1dB1        1158#define CPCAP_BIT_VOL_CDC_LSB_1dB0        0159 160/* Register 521 CPCAP_REG_RXCOA  --- Codec to Output Amp Switches */161#define CPCAP_BIT_PGA_CDC_EN              10162#define CPCAP_BIT_CDC_SW                  9163#define CPCAP_BIT_PGA_OUTR_USBDP_CDC_SW   8164#define CPCAP_BIT_PGA_OUTL_USBDN_CDC_SW   7165#define CPCAP_BIT_ALEFT_HS_CDC_SW         6166#define CPCAP_BIT_ARIGHT_HS_CDC_SW        5167#define CPCAP_BIT_A4_LINEOUT_L_CDC_SW     4168#define CPCAP_BIT_A4_LINEOUT_R_CDC_SW     3169#define CPCAP_BIT_A2_LDSP_L_CDC_SW        2170#define CPCAP_BIT_A2_LDSP_R_CDC_SW        1171#define CPCAP_BIT_A1_EAR_CDC_SW           0172 173/* Register 522 CPCAP_REG_RXSDOA --- RX Stereo DAC to Output Amp Switches */174#define CPCAP_BIT_PGA_DAC_EN              12175#define CPCAP_BIT_ST_DAC_SW               11176#define CPCAP_BIT_MONO_DAC1               10177#define CPCAP_BIT_MONO_DAC0               9178#define CPCAP_BIT_PGA_OUTR_USBDP_DAC_SW   8179#define CPCAP_BIT_PGA_OUTL_USBDN_DAC_SW   7180#define CPCAP_BIT_ALEFT_HS_DAC_SW         6181#define CPCAP_BIT_ARIGHT_HS_DAC_SW        5182#define CPCAP_BIT_A4_LINEOUT_L_DAC_SW     4183#define CPCAP_BIT_A4_LINEOUT_R_DAC_SW     3184#define CPCAP_BIT_A2_LDSP_L_DAC_SW        2185#define CPCAP_BIT_A2_LDSP_R_DAC_SW        1186#define CPCAP_BIT_A1_EAR_DAC_SW           0187 188/* Register 523 CPCAP_REG_RXEPOA --- RX External PGA to Output Amp Switches */189#define CPCAP_BIT_PGA_EXT_L_EN            14190#define CPCAP_BIT_PGA_EXT_R_EN            13191#define CPCAP_BIT_PGA_IN_L_SW             12192#define CPCAP_BIT_PGA_IN_R_SW             11193#define CPCAP_BIT_MONO_EXT1               10194#define CPCAP_BIT_MONO_EXT0               9195#define CPCAP_BIT_PGA_OUTR_USBDP_EXT_SW   8196#define CPCAP_BIT_PGA_OUTL_USBDN_EXT_SW   7197#define CPCAP_BIT_ALEFT_HS_EXT_SW         6198#define CPCAP_BIT_ARIGHT_HS_EXT_SW        5199#define CPCAP_BIT_A4_LINEOUT_L_EXT_SW     4200#define CPCAP_BIT_A4_LINEOUT_R_EXT_SW     3201#define CPCAP_BIT_A2_LDSP_L_EXT_SW        2202#define CPCAP_BIT_A2_LDSP_R_EXT_SW        1203#define CPCAP_BIT_A1_EAR_EXT_SW           0204 205/* Register 525 CPCAP_REG_A2LA --- SPK Amplifier and Clock Config for Headset */206#define CPCAP_BIT_NCP_CLK_SYNC            7207#define CPCAP_BIT_A2_CLK_SYNC             6208#define CPCAP_BIT_A2_FREE_RUN             5209#define CPCAP_BIT_A2_CLK2                 4210#define CPCAP_BIT_A2_CLK1                 3211#define CPCAP_BIT_A2_CLK0                 2212#define CPCAP_BIT_A2_CLK_IN               1213#define CPCAP_BIT_A2_CONFIG               0214 215#define SLEEP_ACTIVATE_POWER 2216#define CLOCK_TREE_RESET_TIME 1217 218/* constants for ST delay workaround */219#define STM_STDAC_ACTIVATE_RAMP_TIME   1220#define STM_STDAC_EN_TEST_PRE          0x090C221#define STM_STDAC_EN_TEST_POST         0x0000222#define STM_STDAC_EN_ST_TEST1_PRE      0x2400223#define STM_STDAC_EN_ST_TEST1_POST     0x0400224 225struct cpcap_reg_info {226	u16 reg;227	u16 mask;228	u16 val;229};230 231static const struct cpcap_reg_info cpcap_default_regs[] = {232	{ CPCAP_REG_VAUDIOC, 0x003F, 0x0000 },233	{ CPCAP_REG_CC, 0xFFFF, 0x0000 },234	{ CPCAP_REG_CC, 0xFFFF, 0x0000 },235	{ CPCAP_REG_CDI, 0xBFFF, 0x0000 },236	{ CPCAP_REG_SDAC, 0x0FFF, 0x0000 },237	{ CPCAP_REG_SDACDI, 0x3FFF, 0x0000 },238	{ CPCAP_REG_TXI, 0x0FDF, 0x0000 },239	{ CPCAP_REG_TXMP, 0x0FFF, 0x0400 },240	{ CPCAP_REG_RXOA, 0x01FF, 0x0000 },241	{ CPCAP_REG_RXVC, 0xFF3C, 0x0000 },242	{ CPCAP_REG_RXCOA, 0x07FF, 0x0000 },243	{ CPCAP_REG_RXSDOA, 0x1FFF, 0x0000 },244	{ CPCAP_REG_RXEPOA, 0x7FFF, 0x0000 },245	{ CPCAP_REG_A2LA, BIT(CPCAP_BIT_A2_FREE_RUN),246	  BIT(CPCAP_BIT_A2_FREE_RUN) },247};248 249enum cpcap_dai {250	CPCAP_DAI_HIFI,251	CPCAP_DAI_VOICE,252};253 254struct cpcap_audio {255	struct snd_soc_component *component;256	struct regmap *regmap;257 258	u16 vendor;259 260	int codec_clk_id;261	int codec_freq;262	int codec_format;263};264 265static int cpcap_st_workaround(struct snd_soc_dapm_widget *w,266			       struct snd_kcontrol *kcontrol, int event)267{268	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);269	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);270	int err = 0;271 272	/* Only CPCAP from ST requires workaround */273	if (cpcap->vendor != CPCAP_VENDOR_ST)274		return 0;275 276	switch (event) {277	case SND_SOC_DAPM_PRE_PMU:278		err = regmap_write(cpcap->regmap, CPCAP_REG_TEST,279				   STM_STDAC_EN_TEST_PRE);280		if (err)281			return err;282		err = regmap_write(cpcap->regmap, CPCAP_REG_ST_TEST1,283				   STM_STDAC_EN_ST_TEST1_PRE);284		break;285	case SND_SOC_DAPM_POST_PMU:286		msleep(STM_STDAC_ACTIVATE_RAMP_TIME);287 288		err = regmap_write(cpcap->regmap, CPCAP_REG_ST_TEST1,289				   STM_STDAC_EN_ST_TEST1_POST);290		if (err)291			return err;292		err = regmap_write(cpcap->regmap, CPCAP_REG_TEST,293				   STM_STDAC_EN_TEST_POST);294		break;295	default:296		break;297	}298 299	return err;300}301 302/* Capture Gain Control: 0dB to 31dB in 1dB steps */303static const DECLARE_TLV_DB_SCALE(mic_gain_tlv, 0, 100, 0);304 305/* Playback Gain Control: -33dB to 12dB in 3dB steps */306static const DECLARE_TLV_DB_SCALE(vol_tlv, -3300, 300, 0);307 308static const struct snd_kcontrol_new cpcap_snd_controls[] = {309	/* Playback Gain */310	SOC_SINGLE_TLV("HiFi Playback Volume",311		CPCAP_REG_RXVC, CPCAP_BIT_VOL_DAC0, 0xF, 0, vol_tlv),312	SOC_SINGLE_TLV("Voice Playback Volume",313		CPCAP_REG_RXVC, CPCAP_BIT_VOL_CDC0, 0xF, 0, vol_tlv),314	SOC_SINGLE_TLV("Ext Playback Volume",315		CPCAP_REG_RXVC, CPCAP_BIT_VOL_EXT0, 0xF, 0, vol_tlv),316 317	/* Capture Gain */318	SOC_SINGLE_TLV("Mic1 Capture Volume",319		CPCAP_REG_TXMP, CPCAP_BIT_MIC1_GAIN_0, 0x1F, 0, mic_gain_tlv),320	SOC_SINGLE_TLV("Mic2 Capture Volume",321		CPCAP_REG_TXMP, CPCAP_BIT_MIC2_GAIN_0, 0x1F, 0, mic_gain_tlv),322 323	/* Phase Invert */324	SOC_SINGLE("Hifi Left Phase Invert Switch",325		CPCAP_REG_RXSDOA, CPCAP_BIT_MONO_DAC0, 1, 0),326	SOC_SINGLE("Ext Left Phase Invert Switch",327		CPCAP_REG_RXEPOA, CPCAP_BIT_MONO_EXT0, 1, 0),328};329 330static const char * const cpcap_out_mux_texts[] = {331	"Off", "Voice", "HiFi", "Ext"332};333 334static const char * const cpcap_in_right_mux_texts[] = {335	"Off", "Mic 1", "Headset Mic", "EMU Mic", "Ext Right"336};337 338static const char * const cpcap_in_left_mux_texts[] = {339	"Off", "Mic 2", "Ext Left"340};341 342/*343 * input muxes use unusual register layout, so that we need to use custom344 * getter/setter methods345 */346static SOC_ENUM_SINGLE_EXT_DECL(cpcap_input_left_mux_enum,347				cpcap_in_left_mux_texts);348static SOC_ENUM_SINGLE_EXT_DECL(cpcap_input_right_mux_enum,349				cpcap_in_right_mux_texts);350 351/*352 * mux uses same bit in CPCAP_REG_RXCOA, CPCAP_REG_RXSDOA & CPCAP_REG_RXEPOA;353 * even though the register layout makes it look like a mixer, this is a mux.354 * Enabling multiple inputs will result in no audio being forwarded.355 */356static SOC_ENUM_SINGLE_DECL(cpcap_earpiece_mux_enum, 0, 0, cpcap_out_mux_texts);357static SOC_ENUM_SINGLE_DECL(cpcap_spkr_r_mux_enum, 0, 1, cpcap_out_mux_texts);358static SOC_ENUM_SINGLE_DECL(cpcap_spkr_l_mux_enum, 0, 2, cpcap_out_mux_texts);359static SOC_ENUM_SINGLE_DECL(cpcap_line_r_mux_enum, 0, 3, cpcap_out_mux_texts);360static SOC_ENUM_SINGLE_DECL(cpcap_line_l_mux_enum, 0, 4, cpcap_out_mux_texts);361static SOC_ENUM_SINGLE_DECL(cpcap_hs_r_mux_enum, 0, 5, cpcap_out_mux_texts);362static SOC_ENUM_SINGLE_DECL(cpcap_hs_l_mux_enum, 0, 6, cpcap_out_mux_texts);363static SOC_ENUM_SINGLE_DECL(cpcap_emu_l_mux_enum, 0, 7, cpcap_out_mux_texts);364static SOC_ENUM_SINGLE_DECL(cpcap_emu_r_mux_enum, 0, 8, cpcap_out_mux_texts);365 366static int cpcap_output_mux_get_enum(struct snd_kcontrol *kcontrol,367				     struct snd_ctl_elem_value *ucontrol)368{369	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);370	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);371	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;372	unsigned int shift = e->shift_l;373	int reg_voice, reg_hifi, reg_ext, status;374	int err;375 376	err = regmap_read(cpcap->regmap, CPCAP_REG_RXCOA, &reg_voice);377	if (err)378		return err;379	err = regmap_read(cpcap->regmap, CPCAP_REG_RXSDOA, &reg_hifi);380	if (err)381		return err;382	err = regmap_read(cpcap->regmap, CPCAP_REG_RXEPOA, &reg_ext);383	if (err)384		return err;385 386	reg_voice = (reg_voice >> shift) & 1;387	reg_hifi = (reg_hifi >> shift) & 1;388	reg_ext = (reg_ext >> shift) & 1;389	status = reg_ext << 2 | reg_hifi << 1 | reg_voice;390 391	switch (status) {392	case 0x04:393		ucontrol->value.enumerated.item[0] = 3;394		break;395	case 0x02:396		ucontrol->value.enumerated.item[0] = 2;397		break;398	case 0x01:399		ucontrol->value.enumerated.item[0] = 1;400		break;401	default:402		ucontrol->value.enumerated.item[0] = 0;403		break;404	}405 406	return 0;407}408 409static int cpcap_output_mux_put_enum(struct snd_kcontrol *kcontrol,410				     struct snd_ctl_elem_value *ucontrol)411{412	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);413	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);414	struct snd_soc_dapm_context *dapm =415		snd_soc_dapm_kcontrol_dapm(kcontrol);416	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;417	unsigned int muxval = ucontrol->value.enumerated.item[0];418	unsigned int mask = BIT(e->shift_l);419	u16 reg_voice = 0x00, reg_hifi = 0x00, reg_ext = 0x00;420	int err;421 422	switch (muxval) {423	case 1:424		reg_voice = mask;425		break;426	case 2:427		reg_hifi = mask;428		break;429	case 3:430		reg_ext = mask;431		break;432	default:433		break;434	}435 436	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXCOA,437				 mask, reg_voice);438	if (err)439		return err;440	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXSDOA,441				 mask, reg_hifi);442	if (err)443		return err;444	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXEPOA,445				 mask, reg_ext);446	if (err)447		return err;448 449	snd_soc_dapm_mux_update_power(dapm, kcontrol, muxval, e, NULL);450 451	return 0;452}453 454static int cpcap_input_right_mux_get_enum(struct snd_kcontrol *kcontrol,455					  struct snd_ctl_elem_value *ucontrol)456{457	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);458	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);459	int regval, mask;460	int err;461 462	err = regmap_read(cpcap->regmap, CPCAP_REG_TXI, &regval);463	if (err)464		return err;465 466	mask = 0;467	mask |= BIT(CPCAP_BIT_MIC1_MUX);468	mask |= BIT(CPCAP_BIT_HS_MIC_MUX);469	mask |= BIT(CPCAP_BIT_EMU_MIC_MUX);470	mask |= BIT(CPCAP_BIT_RX_R_ENCODE);471 472	switch (regval & mask) {473	case BIT(CPCAP_BIT_RX_R_ENCODE):474		ucontrol->value.enumerated.item[0] = 4;475		break;476	case BIT(CPCAP_BIT_EMU_MIC_MUX):477		ucontrol->value.enumerated.item[0] = 3;478		break;479	case BIT(CPCAP_BIT_HS_MIC_MUX):480		ucontrol->value.enumerated.item[0] = 2;481		break;482	case BIT(CPCAP_BIT_MIC1_MUX):483		ucontrol->value.enumerated.item[0] = 1;484		break;485	default:486		ucontrol->value.enumerated.item[0] = 0;487		break;488	}489 490	return 0;491}492 493static int cpcap_input_right_mux_put_enum(struct snd_kcontrol *kcontrol,494					  struct snd_ctl_elem_value *ucontrol)495{496	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);497	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);498	struct snd_soc_dapm_context *dapm =499		snd_soc_dapm_kcontrol_dapm(kcontrol);500	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;501	unsigned int muxval = ucontrol->value.enumerated.item[0];502	int regval = 0, mask;503	int err;504 505	mask = 0;506	mask |= BIT(CPCAP_BIT_MIC1_MUX);507	mask |= BIT(CPCAP_BIT_HS_MIC_MUX);508	mask |= BIT(CPCAP_BIT_EMU_MIC_MUX);509	mask |= BIT(CPCAP_BIT_RX_R_ENCODE);510 511	switch (muxval) {512	case 1:513		regval = BIT(CPCAP_BIT_MIC1_MUX);514		break;515	case 2:516		regval = BIT(CPCAP_BIT_HS_MIC_MUX);517		break;518	case 3:519		regval = BIT(CPCAP_BIT_EMU_MIC_MUX);520		break;521	case 4:522		regval = BIT(CPCAP_BIT_RX_R_ENCODE);523		break;524	default:525		break;526	}527 528	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,529				 mask, regval);530	if (err)531		return err;532 533	snd_soc_dapm_mux_update_power(dapm, kcontrol, muxval, e, NULL);534 535	return 0;536}537 538static int cpcap_input_left_mux_get_enum(struct snd_kcontrol *kcontrol,539					 struct snd_ctl_elem_value *ucontrol)540{541	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);542	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);543	int regval, mask;544	int err;545 546	err = regmap_read(cpcap->regmap, CPCAP_REG_TXI, &regval);547	if (err)548		return err;549 550	mask = 0;551	mask |= BIT(CPCAP_BIT_MIC2_MUX);552	mask |= BIT(CPCAP_BIT_RX_L_ENCODE);553 554	switch (regval & mask) {555	case BIT(CPCAP_BIT_RX_L_ENCODE):556		ucontrol->value.enumerated.item[0] = 2;557		break;558	case BIT(CPCAP_BIT_MIC2_MUX):559		ucontrol->value.enumerated.item[0] = 1;560		break;561	default:562		ucontrol->value.enumerated.item[0] = 0;563		break;564	}565 566	return 0;567}568 569static int cpcap_input_left_mux_put_enum(struct snd_kcontrol *kcontrol,570					 struct snd_ctl_elem_value *ucontrol)571{572	struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);573	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);574	struct snd_soc_dapm_context *dapm =575		snd_soc_dapm_kcontrol_dapm(kcontrol);576	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;577	unsigned int muxval = ucontrol->value.enumerated.item[0];578	int regval = 0, mask;579	int err;580 581	mask = 0;582	mask |= BIT(CPCAP_BIT_MIC2_MUX);583	mask |= BIT(CPCAP_BIT_RX_L_ENCODE);584 585	switch (muxval) {586	case 1:587		regval = BIT(CPCAP_BIT_MIC2_MUX);588		break;589	case 2:590		regval = BIT(CPCAP_BIT_RX_L_ENCODE);591		break;592	default:593		break;594	}595 596	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,597				 mask, regval);598	if (err)599		return err;600 601	snd_soc_dapm_mux_update_power(dapm, kcontrol, muxval, e, NULL);602 603	return 0;604}605 606static const struct snd_kcontrol_new cpcap_input_left_mux =607	SOC_DAPM_ENUM_EXT("Input Left", cpcap_input_left_mux_enum,608			  cpcap_input_left_mux_get_enum,609			  cpcap_input_left_mux_put_enum);610static const struct snd_kcontrol_new cpcap_input_right_mux =611	SOC_DAPM_ENUM_EXT("Input Right", cpcap_input_right_mux_enum,612			  cpcap_input_right_mux_get_enum,613			  cpcap_input_right_mux_put_enum);614static const struct snd_kcontrol_new cpcap_emu_left_mux =615	SOC_DAPM_ENUM_EXT("EMU Left", cpcap_emu_l_mux_enum,616			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);617static const struct snd_kcontrol_new cpcap_emu_right_mux =618	SOC_DAPM_ENUM_EXT("EMU Right", cpcap_emu_r_mux_enum,619			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);620static const struct snd_kcontrol_new cpcap_hs_left_mux =621	SOC_DAPM_ENUM_EXT("Headset Left", cpcap_hs_l_mux_enum,622			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);623static const struct snd_kcontrol_new cpcap_hs_right_mux =624	SOC_DAPM_ENUM_EXT("Headset Right", cpcap_hs_r_mux_enum,625			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);626static const struct snd_kcontrol_new cpcap_line_left_mux =627	SOC_DAPM_ENUM_EXT("Line Left", cpcap_line_l_mux_enum,628			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);629static const struct snd_kcontrol_new cpcap_line_right_mux =630	SOC_DAPM_ENUM_EXT("Line Right", cpcap_line_r_mux_enum,631			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);632static const struct snd_kcontrol_new cpcap_speaker_left_mux =633	SOC_DAPM_ENUM_EXT("Speaker Left", cpcap_spkr_l_mux_enum,634			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);635static const struct snd_kcontrol_new cpcap_speaker_right_mux =636	SOC_DAPM_ENUM_EXT("Speaker Right", cpcap_spkr_r_mux_enum,637			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);638static const struct snd_kcontrol_new cpcap_earpiece_mux =639	SOC_DAPM_ENUM_EXT("Earpiece", cpcap_earpiece_mux_enum,640			  cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);641 642static const struct snd_kcontrol_new cpcap_hifi_mono_mixer_controls[] = {643	SOC_DAPM_SINGLE("HiFi Mono Playback Switch",644		CPCAP_REG_RXSDOA, CPCAP_BIT_MONO_DAC1, 1, 0),645};646static const struct snd_kcontrol_new cpcap_ext_mono_mixer_controls[] = {647	SOC_DAPM_SINGLE("Ext Mono Playback Switch",648		CPCAP_REG_RXEPOA, CPCAP_BIT_MONO_EXT0, 1, 0),649};650 651static const struct snd_kcontrol_new cpcap_extr_mute_control =652	SOC_DAPM_SINGLE("Switch",653		CPCAP_REG_RXEPOA, CPCAP_BIT_PGA_IN_R_SW, 1, 0);654static const struct snd_kcontrol_new cpcap_extl_mute_control =655	SOC_DAPM_SINGLE("Switch",656		CPCAP_REG_RXEPOA, CPCAP_BIT_PGA_IN_L_SW, 1, 0);657 658static const struct snd_kcontrol_new cpcap_voice_loopback =659	SOC_DAPM_SINGLE("Switch",660		CPCAP_REG_TXI, CPCAP_BIT_DLM, 1, 0);661 662static const struct snd_soc_dapm_widget cpcap_dapm_widgets[] = {663	/* DAIs */664	SND_SOC_DAPM_AIF_IN("HiFi RX", NULL, 0, SND_SOC_NOPM, 0, 0),665	SND_SOC_DAPM_AIF_IN("Voice RX", NULL, 0, SND_SOC_NOPM, 0, 0),666	SND_SOC_DAPM_AIF_OUT("Voice TX", NULL, 0, SND_SOC_NOPM, 0, 0),667 668	/* Power Supply */669	SND_SOC_DAPM_REGULATOR_SUPPLY("VAUDIO", SLEEP_ACTIVATE_POWER, 0),670 671	/* Highpass Filters */672	SND_SOC_DAPM_REG(snd_soc_dapm_pga, "Highpass Filter RX",673		CPCAP_REG_CC, CPCAP_BIT_AUDIHPF_0, 0x3, 0x3, 0x0),674	SND_SOC_DAPM_REG(snd_soc_dapm_pga, "Highpass Filter TX",675		CPCAP_REG_CC, CPCAP_BIT_AUDOHPF_0, 0x3, 0x3, 0x0),676 677	/* Clocks */678	SND_SOC_DAPM_SUPPLY("HiFi DAI Clock",679		CPCAP_REG_SDACDI, CPCAP_BIT_ST_CLK_EN, 0, NULL, 0),680	SND_SOC_DAPM_SUPPLY("Voice DAI Clock",681		CPCAP_REG_CDI, CPCAP_BIT_CDC_CLK_EN, 0, NULL, 0),682 683	/* Microphone Bias */684	SND_SOC_DAPM_SUPPLY("MIC1R Bias",685		CPCAP_REG_TXI, CPCAP_BIT_MB_ON1R, 0, NULL, 0),686	SND_SOC_DAPM_SUPPLY("MIC1L Bias",687		CPCAP_REG_TXI, CPCAP_BIT_MB_ON1L, 0, NULL, 0),688	SND_SOC_DAPM_SUPPLY("MIC2 Bias",689		CPCAP_REG_TXI, CPCAP_BIT_MB_ON2, 0, NULL, 0),690 691	/* Inputs */692	SND_SOC_DAPM_INPUT("MICR"),693	SND_SOC_DAPM_INPUT("HSMIC"),694	SND_SOC_DAPM_INPUT("EMUMIC"),695	SND_SOC_DAPM_INPUT("MICL"),696	SND_SOC_DAPM_INPUT("EXTR"),697	SND_SOC_DAPM_INPUT("EXTL"),698 699	/* Capture Route */700	SND_SOC_DAPM_MUX("Right Capture Route",701		SND_SOC_NOPM, 0, 0, &cpcap_input_right_mux),702	SND_SOC_DAPM_MUX("Left Capture Route",703		SND_SOC_NOPM, 0, 0, &cpcap_input_left_mux),704 705	/* Capture PGAs */706	SND_SOC_DAPM_PGA("Microphone 1 PGA",707		CPCAP_REG_TXI, CPCAP_BIT_MIC1_PGA_EN, 0, NULL, 0),708	SND_SOC_DAPM_PGA("Microphone 2 PGA",709		CPCAP_REG_TXI, CPCAP_BIT_MIC2_PGA_EN, 0, NULL, 0),710 711	/* ADC */712	SND_SOC_DAPM_ADC("ADC Right", NULL,713		CPCAP_REG_CC, CPCAP_BIT_MIC1_CDC_EN, 0),714	SND_SOC_DAPM_ADC("ADC Left", NULL,715		CPCAP_REG_CC, CPCAP_BIT_MIC2_CDC_EN, 0),716 717	/* DAC */718	SND_SOC_DAPM_DAC_E("DAC HiFi", NULL,719		CPCAP_REG_SDAC, CPCAP_BIT_ST_DAC_EN, 0,720		cpcap_st_workaround,721		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),722	SND_SOC_DAPM_DAC_E("DAC Voice", NULL,723		CPCAP_REG_CC, CPCAP_BIT_CDC_EN_RX, 0,724		cpcap_st_workaround,725		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),726 727	/* Playback PGA */728	SND_SOC_DAPM_PGA("HiFi PGA",729		CPCAP_REG_RXSDOA, CPCAP_BIT_PGA_DAC_EN, 0, NULL, 0),730	SND_SOC_DAPM_PGA("Voice PGA",731		CPCAP_REG_RXCOA, CPCAP_BIT_PGA_CDC_EN, 0, NULL, 0),732	SND_SOC_DAPM_PGA_E("Ext Right PGA",733		CPCAP_REG_RXEPOA, CPCAP_BIT_PGA_EXT_R_EN, 0,734		NULL, 0,735		cpcap_st_workaround,736		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),737	SND_SOC_DAPM_PGA_E("Ext Left PGA",738		CPCAP_REG_RXEPOA, CPCAP_BIT_PGA_EXT_L_EN, 0,739		NULL, 0,740		cpcap_st_workaround,741		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),742 743	/* Playback Switch */744	SND_SOC_DAPM_SWITCH("Ext Right Enable", SND_SOC_NOPM, 0, 0,745		&cpcap_extr_mute_control),746	SND_SOC_DAPM_SWITCH("Ext Left Enable", SND_SOC_NOPM, 0, 0,747		&cpcap_extl_mute_control),748 749	/* Loopback Switch */750	SND_SOC_DAPM_SWITCH("Voice Loopback", SND_SOC_NOPM, 0, 0,751		&cpcap_voice_loopback),752 753	/* Mono Mixer */754	SOC_MIXER_ARRAY("HiFi Mono Left Mixer", SND_SOC_NOPM, 0, 0,755		cpcap_hifi_mono_mixer_controls),756	SOC_MIXER_ARRAY("HiFi Mono Right Mixer", SND_SOC_NOPM, 0, 0,757		cpcap_hifi_mono_mixer_controls),758	SOC_MIXER_ARRAY("Ext Mono Left Mixer", SND_SOC_NOPM, 0, 0,759		cpcap_ext_mono_mixer_controls),760	SOC_MIXER_ARRAY("Ext Mono Right Mixer", SND_SOC_NOPM, 0, 0,761		cpcap_ext_mono_mixer_controls),762 763	/* Output Routes */764	SND_SOC_DAPM_MUX("Earpiece Playback Route", SND_SOC_NOPM, 0, 0,765		&cpcap_earpiece_mux),766	SND_SOC_DAPM_MUX("Speaker Right Playback Route", SND_SOC_NOPM, 0, 0,767		&cpcap_speaker_right_mux),768	SND_SOC_DAPM_MUX("Speaker Left Playback Route", SND_SOC_NOPM, 0, 0,769		&cpcap_speaker_left_mux),770	SND_SOC_DAPM_MUX("Lineout Right Playback Route", SND_SOC_NOPM, 0, 0,771		&cpcap_line_right_mux),772	SND_SOC_DAPM_MUX("Lineout Left Playback Route", SND_SOC_NOPM, 0, 0,773		&cpcap_line_left_mux),774	SND_SOC_DAPM_MUX("Headset Right Playback Route", SND_SOC_NOPM, 0, 0,775		&cpcap_hs_right_mux),776	SND_SOC_DAPM_MUX("Headset Left Playback Route", SND_SOC_NOPM, 0, 0,777		&cpcap_hs_left_mux),778	SND_SOC_DAPM_MUX("EMU Right Playback Route", SND_SOC_NOPM, 0, 0,779		&cpcap_emu_right_mux),780	SND_SOC_DAPM_MUX("EMU Left Playback Route", SND_SOC_NOPM, 0, 0,781		&cpcap_emu_left_mux),782 783	/* Output Amplifier */784	SND_SOC_DAPM_PGA("Earpiece PGA",785		CPCAP_REG_RXOA, CPCAP_BIT_A1_EAR_EN, 0, NULL, 0),786	SND_SOC_DAPM_PGA("Speaker Right PGA",787		CPCAP_REG_RXOA, CPCAP_BIT_A2_LDSP_R_EN, 0, NULL, 0),788	SND_SOC_DAPM_PGA("Speaker Left PGA",789		CPCAP_REG_RXOA, CPCAP_BIT_A2_LDSP_L_EN, 0, NULL, 0),790	SND_SOC_DAPM_PGA("Lineout Right PGA",791		CPCAP_REG_RXOA, CPCAP_BIT_A4_LINEOUT_R_EN, 0, NULL, 0),792	SND_SOC_DAPM_PGA("Lineout Left PGA",793		CPCAP_REG_RXOA, CPCAP_BIT_A4_LINEOUT_L_EN, 0, NULL, 0),794	SND_SOC_DAPM_PGA("Headset Right PGA",795		CPCAP_REG_RXOA, CPCAP_BIT_HS_R_EN, 0, NULL, 0),796	SND_SOC_DAPM_PGA("Headset Left PGA",797		CPCAP_REG_RXOA, CPCAP_BIT_HS_L_EN, 0, NULL, 0),798	SND_SOC_DAPM_PGA("EMU Right PGA",799		CPCAP_REG_RXOA, CPCAP_BIT_EMU_SPKR_R_EN, 0, NULL, 0),800	SND_SOC_DAPM_PGA("EMU Left PGA",801		CPCAP_REG_RXOA, CPCAP_BIT_EMU_SPKR_L_EN, 0, NULL, 0),802 803	/* Headet Charge Pump */804	SND_SOC_DAPM_SUPPLY("Headset Charge Pump",805		CPCAP_REG_RXOA, CPCAP_BIT_ST_HS_CP_EN, 0, NULL, 0),806 807	/* Outputs */808	SND_SOC_DAPM_OUTPUT("EP"),809	SND_SOC_DAPM_OUTPUT("SPKR"),810	SND_SOC_DAPM_OUTPUT("SPKL"),811	SND_SOC_DAPM_OUTPUT("LINER"),812	SND_SOC_DAPM_OUTPUT("LINEL"),813	SND_SOC_DAPM_OUTPUT("HSR"),814	SND_SOC_DAPM_OUTPUT("HSL"),815	SND_SOC_DAPM_OUTPUT("EMUR"),816	SND_SOC_DAPM_OUTPUT("EMUL"),817};818 819static const struct snd_soc_dapm_route intercon[] = {820	/* Power Supply */821	{"HiFi PGA", NULL, "VAUDIO"},822	{"Voice PGA", NULL, "VAUDIO"},823	{"Ext Right PGA", NULL, "VAUDIO"},824	{"Ext Left PGA", NULL, "VAUDIO"},825	{"Microphone 1 PGA", NULL, "VAUDIO"},826	{"Microphone 2 PGA", NULL, "VAUDIO"},827 828	/* Stream -> AIF */829	{"HiFi RX", NULL, "HiFi Playback"},830	{"Voice RX", NULL, "Voice Playback"},831	{"Voice Capture", NULL, "Voice TX"},832 833	/* AIF clocks */834	{"HiFi RX", NULL, "HiFi DAI Clock"},835	{"Voice RX", NULL, "Voice DAI Clock"},836	{"Voice TX", NULL, "Voice DAI Clock"},837 838	/* Digital Loopback */839	{"Voice Loopback", "Switch", "Voice TX"},840	{"Voice RX", NULL, "Voice Loopback"},841 842	/* Highpass Filters */843	{"Highpass Filter RX", NULL, "Voice RX"},844	{"Voice TX", NULL, "Highpass Filter TX"},845 846	/* AIF -> DAC mapping */847	{"DAC HiFi", NULL, "HiFi RX"},848	{"DAC Voice", NULL, "Highpass Filter RX"},849 850	/* DAC -> PGA */851	{"HiFi PGA", NULL, "DAC HiFi"},852	{"Voice PGA", NULL, "DAC Voice"},853 854	/* Ext Input -> PGA */855	{"Ext Right PGA", NULL, "EXTR"},856	{"Ext Left PGA", NULL, "EXTL"},857 858	/* Ext PGA -> Ext Playback Switch */859	{"Ext Right Enable", "Switch", "Ext Right PGA"},860	{"Ext Left Enable", "Switch", "Ext Left PGA"},861 862	/* HiFi PGA -> Mono Mixer */863	{"HiFi Mono Left Mixer", NULL, "HiFi PGA"},864	{"HiFi Mono Left Mixer", "HiFi Mono Playback Switch", "HiFi PGA"},865	{"HiFi Mono Right Mixer", NULL, "HiFi PGA"},866	{"HiFi Mono Right Mixer", "HiFi Mono Playback Switch", "HiFi PGA"},867 868	/* Ext Playback Switch -> Ext Mono Mixer */869	{"Ext Mono Right Mixer", NULL, "Ext Right Enable"},870	{"Ext Mono Right Mixer", "Ext Mono Playback Switch", "Ext Left Enable"},871	{"Ext Mono Left Mixer", NULL, "Ext Left Enable"},872	{"Ext Mono Left Mixer", "Ext Mono Playback Switch", "Ext Right Enable"},873 874	/* HiFi Mono Mixer -> Output Route */875	{"Earpiece Playback Route", "HiFi", "HiFi Mono Right Mixer"},876	{"Speaker Right Playback Route", "HiFi", "HiFi Mono Right Mixer"},877	{"Speaker Left Playback Route", "HiFi", "HiFi Mono Left Mixer"},878	{"Lineout Right Playback Route", "HiFi", "HiFi Mono Right Mixer"},879	{"Lineout Left Playback Route", "HiFi", "HiFi Mono Left Mixer"},880	{"Headset Right Playback Route", "HiFi", "HiFi Mono Right Mixer"},881	{"Headset Left Playback Route", "HiFi", "HiFi Mono Left Mixer"},882	{"EMU Right Playback Route", "HiFi", "HiFi Mono Right Mixer"},883	{"EMU Left Playback Route", "HiFi", "HiFi Mono Left Mixer"},884 885	/* Voice PGA -> Output Route */886	{"Earpiece Playback Route", "Voice", "Voice PGA"},887	{"Speaker Right Playback Route", "Voice", "Voice PGA"},888	{"Speaker Left Playback Route", "Voice", "Voice PGA"},889	{"Lineout Right Playback Route", "Voice", "Voice PGA"},890	{"Lineout Left Playback Route", "Voice", "Voice PGA"},891	{"Headset Right Playback Route", "Voice", "Voice PGA"},892	{"Headset Left Playback Route", "Voice", "Voice PGA"},893	{"EMU Right Playback Route", "Voice", "Voice PGA"},894	{"EMU Left Playback Route", "Voice", "Voice PGA"},895 896	/* Ext Mono Mixer -> Output Route */897	{"Earpiece Playback Route", "Ext", "Ext Mono Right Mixer"},898	{"Speaker Right Playback Route", "Ext", "Ext Mono Right Mixer"},899	{"Speaker Left Playback Route", "Ext", "Ext Mono Left Mixer"},900	{"Lineout Right Playback Route", "Ext", "Ext Mono Right Mixer"},901	{"Lineout Left Playback Route", "Ext", "Ext Mono Left Mixer"},902	{"Headset Right Playback Route", "Ext", "Ext Mono Right Mixer"},903	{"Headset Left Playback Route", "Ext", "Ext Mono Left Mixer"},904	{"EMU Right Playback Route", "Ext", "Ext Mono Right Mixer"},905	{"EMU Left Playback Route", "Ext", "Ext Mono Left Mixer"},906 907	/* Output Route -> Output Amplifier */908	{"Earpiece PGA", NULL, "Earpiece Playback Route"},909	{"Speaker Right PGA", NULL, "Speaker Right Playback Route"},910	{"Speaker Left PGA", NULL, "Speaker Left Playback Route"},911	{"Lineout Right PGA", NULL, "Lineout Right Playback Route"},912	{"Lineout Left PGA", NULL, "Lineout Left Playback Route"},913	{"Headset Right PGA", NULL, "Headset Right Playback Route"},914	{"Headset Left PGA", NULL, "Headset Left Playback Route"},915	{"EMU Right PGA", NULL, "EMU Right Playback Route"},916	{"EMU Left PGA", NULL, "EMU Left Playback Route"},917 918	/* Output Amplifier -> Output */919	{"EP", NULL, "Earpiece PGA"},920	{"SPKR", NULL, "Speaker Right PGA"},921	{"SPKL", NULL, "Speaker Left PGA"},922	{"LINER", NULL, "Lineout Right PGA"},923	{"LINEL", NULL, "Lineout Left PGA"},924	{"HSR", NULL, "Headset Right PGA"},925	{"HSL", NULL, "Headset Left PGA"},926	{"EMUR", NULL, "EMU Right PGA"},927	{"EMUL", NULL, "EMU Left PGA"},928 929	/* Headset Charge Pump -> Headset */930	{"HSR", NULL, "Headset Charge Pump"},931	{"HSL", NULL, "Headset Charge Pump"},932 933	/* Mic -> Mic Route */934	{"Right Capture Route", "Mic 1", "MICR"},935	{"Right Capture Route", "Headset Mic", "HSMIC"},936	{"Right Capture Route", "EMU Mic", "EMUMIC"},937	{"Right Capture Route", "Ext Right", "EXTR"},938	{"Left Capture Route", "Mic 2", "MICL"},939	{"Left Capture Route", "Ext Left", "EXTL"},940 941	/* Input Route -> Microphone PGA */942	{"Microphone 1 PGA", NULL, "Right Capture Route"},943	{"Microphone 2 PGA", NULL, "Left Capture Route"},944 945	/* Microphone PGA -> ADC */946	{"ADC Right", NULL, "Microphone 1 PGA"},947	{"ADC Left", NULL, "Microphone 2 PGA"},948 949	/* ADC -> Stream */950	{"Highpass Filter TX", NULL, "ADC Right"},951	{"Highpass Filter TX", NULL, "ADC Left"},952 953	/* Mic Bias */954	{"MICL", NULL, "MIC1L Bias"},955	{"MICR", NULL, "MIC1R Bias"},956};957 958static int cpcap_set_sysclk(struct cpcap_audio *cpcap, enum cpcap_dai dai,959			    int clk_id, int freq)960{961	u16 clkfreqreg, clkfreqshift;962	u16 clkfreqmask, clkfreqval;963	u16 clkidreg, clkidshift;964	u16 mask, val;965	int err;966 967	switch (dai) {968	case CPCAP_DAI_HIFI:969		clkfreqreg = CPCAP_REG_SDAC;970		clkfreqshift = CPCAP_BIT_ST_DAC_CLK0;971		clkidreg = CPCAP_REG_SDACDI;972		clkidshift = CPCAP_BIT_ST_DAC_CLK_IN_SEL;973		break;974	case CPCAP_DAI_VOICE:975		clkfreqreg = CPCAP_REG_CC;976		clkfreqshift = CPCAP_BIT_CDC_CLK0;977		clkidreg = CPCAP_REG_CDI;978		clkidshift = CPCAP_BIT_CLK_IN_SEL;979		break;980	default:981		dev_err(cpcap->component->dev, "invalid DAI: %d", dai);982		return -EINVAL;983	}984 985	/* setup clk id */986	if (clk_id < 0 || clk_id > 1) {987		dev_err(cpcap->component->dev, "invalid clk id %d", clk_id);988		return -EINVAL;989	}990	err = regmap_update_bits(cpcap->regmap, clkidreg, BIT(clkidshift),991				 clk_id ? BIT(clkidshift) : 0);992	if (err)993		return err;994 995	/* enable PLL for Voice DAI */996	if (dai == CPCAP_DAI_VOICE) {997		mask = BIT(CPCAP_BIT_CDC_PLL_SEL);998		val = BIT(CPCAP_BIT_CDC_PLL_SEL);999		err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,1000					 mask, val);1001		if (err)1002			return err;1003	}1004 1005	/* setup frequency */1006	clkfreqmask = 0x7 << clkfreqshift;1007	switch (freq) {1008	case 15360000:1009		clkfreqval = 0x01 << clkfreqshift;1010		break;1011	case 16800000:1012		clkfreqval = 0x02 << clkfreqshift;1013		break;1014	case 19200000:1015		clkfreqval = 0x03 << clkfreqshift;1016		break;1017	case 26000000:1018		clkfreqval = 0x04 << clkfreqshift;1019		break;1020	case 33600000:1021		clkfreqval = 0x05 << clkfreqshift;1022		break;1023	case 38400000:1024		clkfreqval = 0x06 << clkfreqshift;1025		break;1026	default:1027		dev_err(cpcap->component->dev, "unsupported freq %u", freq);1028		return -EINVAL;1029	}1030 1031	err = regmap_update_bits(cpcap->regmap, clkfreqreg,1032				 clkfreqmask, clkfreqval);1033	if (err)1034		return err;1035 1036	if (dai == CPCAP_DAI_VOICE) {1037		cpcap->codec_clk_id = clk_id;1038		cpcap->codec_freq = freq;1039	}1040 1041	return 0;1042}1043 1044static int cpcap_set_samprate(struct cpcap_audio *cpcap, enum cpcap_dai dai,1045			      int samplerate)1046{1047	struct snd_soc_component *component = cpcap->component;1048	u16 sampreg, sampmask, sampshift, sampval, sampreset;1049	int err, sampreadval;1050 1051	switch (dai) {1052	case CPCAP_DAI_HIFI:1053		sampreg = CPCAP_REG_SDAC;1054		sampshift = CPCAP_BIT_ST_SR0;1055		sampreset = BIT(CPCAP_BIT_DF_RESET_ST_DAC) |1056			    BIT(CPCAP_BIT_ST_CLOCK_TREE_RESET);1057		break;1058	case CPCAP_DAI_VOICE:1059		sampreg = CPCAP_REG_CC;1060		sampshift = CPCAP_BIT_CDC_SR0;1061		sampreset = BIT(CPCAP_BIT_DF_RESET) |1062			    BIT(CPCAP_BIT_CDC_CLOCK_TREE_RESET);1063		break;1064	default:1065		dev_err(component->dev, "invalid DAI: %d", dai);1066		return -EINVAL;1067	}1068 1069	sampmask = 0xF << sampshift | sampreset;1070	switch (samplerate) {1071	case 48000:1072		sampval = 0x8 << sampshift;1073		break;1074	case 44100:1075		sampval = 0x7 << sampshift;1076		break;1077	case 32000:1078		sampval = 0x6 << sampshift;1079		break;1080	case 24000:1081		sampval = 0x5 << sampshift;1082		break;1083	case 22050:1084		sampval = 0x4 << sampshift;1085		break;1086	case 16000:1087		sampval = 0x3 << sampshift;1088		break;1089	case 12000:1090		sampval = 0x2 << sampshift;1091		break;1092	case 11025:1093		sampval = 0x1 << sampshift;1094		break;1095	case 8000:1096		sampval = 0x0 << sampshift;1097		break;1098	default:1099		dev_err(component->dev, "unsupported samplerate %d", samplerate);1100		return -EINVAL;1101	}1102	err = regmap_update_bits(cpcap->regmap, sampreg,1103				 sampmask, sampval | sampreset);1104	if (err)1105		return err;1106 1107	/* Wait for clock tree reset to complete */1108	mdelay(CLOCK_TREE_RESET_TIME);1109 1110	err = regmap_read(cpcap->regmap, sampreg, &sampreadval);1111	if (err)1112		return err;1113 1114	if (sampreadval & sampreset) {1115		dev_err(component->dev, "reset self-clear failed: %04x",1116			sampreadval);1117		return -EIO;1118	}1119 1120	return 0;1121}1122 1123static int cpcap_hifi_hw_params(struct snd_pcm_substream *substream,1124				struct snd_pcm_hw_params *params,1125				struct snd_soc_dai *dai)1126{1127	struct snd_soc_component *component = dai->component;1128	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);1129	int rate = params_rate(params);1130 1131	dev_dbg(component->dev, "HiFi setup HW params: rate=%d", rate);1132	return cpcap_set_samprate(cpcap, CPCAP_DAI_HIFI, rate);1133}1134 1135static int cpcap_hifi_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id,1136				     unsigned int freq, int dir)1137{1138	struct snd_soc_component *component = codec_dai->component;1139	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);1140	struct device *dev = component->dev;1141 1142	dev_dbg(dev, "HiFi setup sysclk: clk_id=%u, freq=%u", clk_id, freq);1143	return cpcap_set_sysclk(cpcap, CPCAP_DAI_HIFI, clk_id, freq);1144}1145 1146static int cpcap_hifi_set_dai_fmt(struct snd_soc_dai *codec_dai,1147				  unsigned int fmt)1148{1149	struct snd_soc_component *component = codec_dai->component;1150	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);1151	struct device *dev = component->dev;1152	static const u16 reg = CPCAP_REG_SDACDI;1153	static const u16 mask =1154		BIT(CPCAP_BIT_SMB_ST_DAC) |1155		BIT(CPCAP_BIT_ST_CLK_INV) |1156		BIT(CPCAP_BIT_ST_FS_INV) |1157		BIT(CPCAP_BIT_ST_DIG_AUD_FS0) |1158		BIT(CPCAP_BIT_ST_DIG_AUD_FS1) |1159		BIT(CPCAP_BIT_ST_L_TIMESLOT0) |1160		BIT(CPCAP_BIT_ST_L_TIMESLOT1) |1161		BIT(CPCAP_BIT_ST_L_TIMESLOT2) |1162		BIT(CPCAP_BIT_ST_R_TIMESLOT0) |1163		BIT(CPCAP_BIT_ST_R_TIMESLOT1) |1164		BIT(CPCAP_BIT_ST_R_TIMESLOT2);1165	u16 val = 0x0000;1166 1167	dev_dbg(dev, "HiFi setup dai format (%08x)", fmt);1168 1169	/*1170	 * "HiFi Playback" should always be configured as1171	 * SND_SOC_DAIFMT_CBP_CFP - codec clk & frm provider1172	 * SND_SOC_DAIFMT_I2S - I2S mode1173	 */1174	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {1175	case SND_SOC_DAIFMT_CBP_CFP:1176		val &= ~BIT(CPCAP_BIT_SMB_ST_DAC);1177		break;1178	default:1179		dev_err(dev, "HiFi dai fmt failed: CPCAP should be provider");1180		return -EINVAL;1181	}1182 1183	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {1184	case SND_SOC_DAIFMT_IB_IF:1185		val |= BIT(CPCAP_BIT_ST_FS_INV);1186		val |= BIT(CPCAP_BIT_ST_CLK_INV);1187		break;1188	case SND_SOC_DAIFMT_IB_NF:1189		val &= ~BIT(CPCAP_BIT_ST_FS_INV);1190		val |= BIT(CPCAP_BIT_ST_CLK_INV);1191		break;1192	case SND_SOC_DAIFMT_NB_IF:1193		val |= BIT(CPCAP_BIT_ST_FS_INV);1194		val &= ~BIT(CPCAP_BIT_ST_CLK_INV);1195		break;1196	case SND_SOC_DAIFMT_NB_NF:1197		val &= ~BIT(CPCAP_BIT_ST_FS_INV);1198		val &= ~BIT(CPCAP_BIT_ST_CLK_INV);1199		break;1200	default:1201		dev_err(dev, "HiFi dai fmt failed: unsupported clock invert mode");1202		return -EINVAL;1203	}1204 1205	if (val & BIT(CPCAP_BIT_ST_CLK_INV))1206		val &= ~BIT(CPCAP_BIT_ST_CLK_INV);1207	else1208		val |= BIT(CPCAP_BIT_ST_CLK_INV);1209 1210	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {1211	case SND_SOC_DAIFMT_I2S:1212		val |= BIT(CPCAP_BIT_ST_DIG_AUD_FS0);1213		val |= BIT(CPCAP_BIT_ST_DIG_AUD_FS1);1214		break;1215	default:1216		/* 01 - 4 slots network mode */1217		val |= BIT(CPCAP_BIT_ST_DIG_AUD_FS0);1218		val &= ~BIT(CPCAP_BIT_ST_DIG_AUD_FS1);1219		/* L on slot 1 */1220		val |= BIT(CPCAP_BIT_ST_L_TIMESLOT0);1221		break;1222	}1223 1224	dev_dbg(dev, "HiFi dai format: val=%04x", val);1225	return regmap_update_bits(cpcap->regmap, reg, mask, val);1226}1227 1228static int cpcap_hifi_set_mute(struct snd_soc_dai *dai, int mute, int direction)1229{1230	struct snd_soc_component *component = dai->component;1231	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);1232	static const u16 reg = CPCAP_REG_RXSDOA;1233	static const u16 mask = BIT(CPCAP_BIT_ST_DAC_SW);1234	u16 val;1235 1236	if (mute)1237		val = 0;1238	else1239		val = BIT(CPCAP_BIT_ST_DAC_SW);1240 1241	dev_dbg(component->dev, "HiFi mute: %d", mute);1242	return regmap_update_bits(cpcap->regmap, reg, mask, val);1243}1244 1245static const struct snd_soc_dai_ops cpcap_dai_hifi_ops = {1246	.hw_params	= cpcap_hifi_hw_params,1247	.set_sysclk	= cpcap_hifi_set_dai_sysclk,1248	.set_fmt	= cpcap_hifi_set_dai_fmt,1249	.mute_stream	= cpcap_hifi_set_mute,1250	.no_capture_mute = 1,1251};1252 1253static int cpcap_voice_hw_params(struct snd_pcm_substream *substream,1254				 struct snd_pcm_hw_params *params,1255				 struct snd_soc_dai *dai)1256{1257	struct snd_soc_component *component = dai->component;1258	struct device *dev = component->dev;1259	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);1260	static const u16 reg_cdi = CPCAP_REG_CDI;1261	int rate = params_rate(params);1262	int channels = params_channels(params);1263	int direction = substream->stream;1264	u16 val, mask;1265	int err;1266 1267	dev_dbg(dev, "Voice setup HW params: rate=%d, direction=%d, chan=%d",1268		rate, direction, channels);1269 1270	err = cpcap_set_samprate(cpcap, CPCAP_DAI_VOICE, rate);1271	if (err)1272		return err;1273 1274	if (direction == SNDRV_PCM_STREAM_CAPTURE) {1275		mask = 0x0000;1276		mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);1277		mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT1);1278		mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT2);1279		mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT0);1280		mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT1);1281		mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT2);1282		val = 0x0000;1283		if (channels >= 2)1284			val = BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0);1285		err = regmap_update_bits(cpcap->regmap, reg_cdi, mask, val);1286		if (err)1287			return err;1288	}1289 1290	return 0;1291}1292 1293static int cpcap_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id,1294				      unsigned int freq, int dir)1295{1296	struct snd_soc_component *component = codec_dai->component;1297	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);1298 1299	dev_dbg(component->dev, "Voice setup sysclk: clk_id=%u, freq=%u",1300		clk_id, freq);1301	return cpcap_set_sysclk(cpcap, CPCAP_DAI_VOICE, clk_id, freq);1302}1303 1304static int cpcap_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,1305				   unsigned int fmt)1306{1307	struct snd_soc_component *component = codec_dai->component;1308	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);1309	static const u16 mask = BIT(CPCAP_BIT_SMB_CDC) |1310				BIT(CPCAP_BIT_CLK_INV) |1311				BIT(CPCAP_BIT_FS_INV) |1312				BIT(CPCAP_BIT_CDC_DIG_AUD_FS0) |1313				BIT(CPCAP_BIT_CDC_DIG_AUD_FS1);1314	u16 val = 0x0000;1315	int err;1316 1317	dev_dbg(component->dev, "Voice setup dai format (%08x)", fmt);1318 1319	/*1320	 * "Voice Playback" and "Voice Capture" should always be1321	 * configured as SND_SOC_DAIFMT_CBP_CFP - codec clk & frm1322	 * provider1323	 */1324	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {1325	case SND_SOC_DAIFMT_CBP_CFP:1326		val &= ~BIT(CPCAP_BIT_SMB_CDC);1327		break;1328	default:1329		dev_err(component->dev, "Voice dai fmt failed: CPCAP should be the provider");1330		val &= ~BIT(CPCAP_BIT_SMB_CDC);1331		break;1332	}1333 1334	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {1335	case SND_SOC_DAIFMT_IB_IF:1336		val |= BIT(CPCAP_BIT_CLK_INV);1337		val |= BIT(CPCAP_BIT_FS_INV);1338		break;1339	case SND_SOC_DAIFMT_IB_NF:1340		val |= BIT(CPCAP_BIT_CLK_INV);1341		val &= ~BIT(CPCAP_BIT_FS_INV);1342		break;1343	case SND_SOC_DAIFMT_NB_IF:1344		val &= ~BIT(CPCAP_BIT_CLK_INV);1345		val |= BIT(CPCAP_BIT_FS_INV);1346		break;1347	case SND_SOC_DAIFMT_NB_NF:1348		val &= ~BIT(CPCAP_BIT_CLK_INV);1349		val &= ~BIT(CPCAP_BIT_FS_INV);1350		break;1351	default:1352		dev_err(component->dev, "Voice dai fmt failed: unsupported clock invert mode");1353		break;1354	}1355 1356	if (val & BIT(CPCAP_BIT_CLK_INV))1357		val &= ~BIT(CPCAP_BIT_CLK_INV);1358	else1359		val |= BIT(CPCAP_BIT_CLK_INV);1360 1361	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {1362	case SND_SOC_DAIFMT_I2S:1363		/* 11 - true I2S mode */1364		val |= BIT(CPCAP_BIT_CDC_DIG_AUD_FS0);1365		val |= BIT(CPCAP_BIT_CDC_DIG_AUD_FS1);1366		break;1367	default:1368		/* 4 timeslots network mode */1369		val |= BIT(CPCAP_BIT_CDC_DIG_AUD_FS0);1370		val &= ~BIT(CPCAP_BIT_CDC_DIG_AUD_FS1);1371		break;1372	}1373 1374	dev_dbg(component->dev, "Voice dai format: val=%04x", val);1375	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI, mask, val);1376	if (err)1377		return err;1378 1379	cpcap->codec_format = val;1380	return 0;1381}1382 1383 1384/*1385 * Configure codec for voice call if requested.1386 *1387 * We can configure most with snd_soc_dai_set_sysclk(), snd_soc_dai_set_fmt()1388 * and snd_soc_dai_set_tdm_slot(). This function configures the rest of the1389 * cpcap related hardware as CPU is not involved in the voice call.1390 */1391static int cpcap_voice_call(struct cpcap_audio *cpcap, struct snd_soc_dai *dai,1392			    bool voice_call)1393{1394	int mask, err;1395 1396	/* Modem to codec VAUDIO_MODE1 */1397	mask = BIT(CPCAP_BIT_VAUDIO_MODE1);1398	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_VAUDIOC,1399				 mask, voice_call ? mask : 0);1400	if (err)1401		return err;1402 1403	/* Clear MIC1_MUX for call */1404	mask = BIT(CPCAP_BIT_MIC1_MUX);1405	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,1406				 mask, voice_call ? 0 : mask);1407	if (err)1408		return err;1409 1410	/* Set MIC2_MUX for call */1411	mask = BIT(CPCAP_BIT_MB_ON1L) | BIT(CPCAP_BIT_MB_ON1R) |1412		BIT(CPCAP_BIT_MIC2_MUX) | BIT(CPCAP_BIT_MIC2_PGA_EN);1413	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_TXI,1414				 mask, voice_call ? mask : 0);1415	if (err)1416		return err;1417 1418	/* Enable LDSP for call */1419	mask = BIT(CPCAP_BIT_A2_LDSP_L_EN) | BIT(CPCAP_BIT_A2_LDSP_R_EN);1420	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXOA,1421				 mask, voice_call ? mask : 0);1422	if (err)1423		return err;1424 1425	/* Enable CPCAP_BIT_PGA_CDC_EN for call */1426	mask = BIT(CPCAP_BIT_PGA_CDC_EN);1427	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_RXCOA,1428				 mask, voice_call ? mask : 0);1429	if (err)1430		return err;1431 1432	/* Unmute voice for call */1433	if (dai) {1434		err = snd_soc_dai_digital_mute(dai, !voice_call,1435					       SNDRV_PCM_STREAM_PLAYBACK);1436		if (err)1437			return err;1438	}1439 1440	/* Set modem to codec mic CDC and HPF for call */1441	mask = BIT(CPCAP_BIT_MIC2_CDC_EN) | BIT(CPCAP_BIT_CDC_EN_RX) |1442	       BIT(CPCAP_BIT_AUDOHPF_1) | BIT(CPCAP_BIT_AUDOHPF_0) |1443	       BIT(CPCAP_BIT_AUDIHPF_1) | BIT(CPCAP_BIT_AUDIHPF_0);1444	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CC,1445				 mask, voice_call ? mask : 0);1446	if (err)1447		return err;1448 1449	/* Enable modem to codec CDC for call*/1450	mask = BIT(CPCAP_BIT_CDC_CLK_EN);1451	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,1452				 mask, voice_call ? mask : 0);1453 1454	return err;1455}1456 1457static int cpcap_voice_set_tdm_slot(struct snd_soc_dai *dai,1458				    unsigned int tx_mask, unsigned int rx_mask,1459				    int slots, int slot_width)1460{1461	struct snd_soc_component *component = dai->component;1462	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);1463	int err, ts_mask, mask;1464	bool voice_call;1465 1466	/*1467	 * Primitive test for voice call, probably needs more checks1468	 * later on for 16-bit calls detected, Bluetooth headset etc.1469	 */1470	if (tx_mask == 0 && rx_mask == 1 && slot_width == 8)1471		voice_call = true;1472	else1473		voice_call = false;1474 1475	ts_mask = 0x7 << CPCAP_BIT_MIC2_TIMESLOT0;1476	ts_mask |= 0x7 << CPCAP_BIT_MIC1_RX_TIMESLOT0;1477 1478	mask = (tx_mask & 0x7) << CPCAP_BIT_MIC2_TIMESLOT0;1479	mask |= (rx_mask & 0x7) << CPCAP_BIT_MIC1_RX_TIMESLOT0;1480 1481	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,1482				 ts_mask, mask);1483	if (err)1484		return err;1485 1486	err = cpcap_set_samprate(cpcap, CPCAP_DAI_VOICE, slot_width * 1000);1487	if (err)1488		return err;1489 1490	err = cpcap_voice_call(cpcap, dai, voice_call);1491	if (err)1492		return err;1493 1494	return 0;1495}1496 1497static int cpcap_voice_set_mute(struct snd_soc_dai *dai, int mute, int direction)1498{1499	struct snd_soc_component *component = dai->component;1500	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);1501	static const u16 reg = CPCAP_REG_RXCOA;1502	static const u16 mask = BIT(CPCAP_BIT_CDC_SW);1503	u16 val;1504 1505	if (mute)1506		val = 0;1507	else1508		val = BIT(CPCAP_BIT_CDC_SW);1509 1510	dev_dbg(component->dev, "Voice mute: %d", mute);1511	return regmap_update_bits(cpcap->regmap, reg, mask, val);1512};1513 1514static const struct snd_soc_dai_ops cpcap_dai_voice_ops = {1515	.hw_params	= cpcap_voice_hw_params,1516	.set_sysclk	= cpcap_voice_set_dai_sysclk,1517	.set_fmt	= cpcap_voice_set_dai_fmt,1518	.set_tdm_slot	= cpcap_voice_set_tdm_slot,1519	.mute_stream	= cpcap_voice_set_mute,1520	.no_capture_mute = 1,1521};1522 1523static struct snd_soc_dai_driver cpcap_dai[] = {1524{1525	.id = 0,1526	.name = "cpcap-hifi",1527	.playback = {1528		.stream_name = "HiFi Playback",1529		.channels_min = 2,1530		.channels_max = 2,1531		.rates = SNDRV_PCM_RATE_8000_48000,1532		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE,1533	},1534	.ops = &cpcap_dai_hifi_ops,1535},1536{1537	.id = 1,1538	.name = "cpcap-voice",1539	.playback = {1540		.stream_name = "Voice Playback",1541		.channels_min = 1,1542		.channels_max = 1,1543		.rates = SNDRV_PCM_RATE_8000_48000,1544		.formats = SNDRV_PCM_FMTBIT_S16_LE,1545	},1546	.capture = {1547		.stream_name = "Voice Capture",1548		.channels_min = 1,1549		.channels_max = 2,1550		.rates = SNDRV_PCM_RATE_8000_48000,1551		.formats = SNDRV_PCM_FMTBIT_S16_LE,1552	},1553	.ops = &cpcap_dai_voice_ops,1554},1555};1556 1557static int cpcap_dai_mux(struct cpcap_audio *cpcap, bool swap_dai_configuration)1558{1559	u16 hifi_val, voice_val;1560	u16 hifi_mask = BIT(CPCAP_BIT_DIG_AUD_IN_ST_DAC);1561	u16 voice_mask = BIT(CPCAP_BIT_DIG_AUD_IN);1562	int err;1563 1564 1565 1566	if (!swap_dai_configuration) {1567		/* Codec on DAI0, HiFi on DAI1 */1568		voice_val = 0;1569		hifi_val = hifi_mask;1570	} else {1571		/* Codec on DAI1, HiFi on DAI0 */1572		voice_val = voice_mask;1573		hifi_val = 0;1574	}1575 1576	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_CDI,1577				 voice_mask, voice_val);1578	if (err)1579		return err;1580 1581	err = regmap_update_bits(cpcap->regmap, CPCAP_REG_SDACDI,1582				 hifi_mask, hifi_val);1583	if (err)1584		return err;1585 1586	return 0;1587}1588 1589static int cpcap_audio_reset(struct snd_soc_component *component,1590			     bool swap_dai_configuration)1591{1592	struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);1593	int i, err = 0;1594 1595	dev_dbg(component->dev, "init audio codec");1596 1597	for (i = 0; i < ARRAY_SIZE(cpcap_default_regs); i++) {1598		err = regmap_update_bits(cpcap->regmap,1599					 cpcap_default_regs[i].reg,1600					 cpcap_default_regs[i].mask,1601					 cpcap_default_regs[i].val);1602		if (err)1603			return err;1604	}1605 1606	/* setup default settings */1607	err = cpcap_dai_mux(cpcap, swap_dai_configuration);1608	if (err)1609		return err;1610 1611	err = cpcap_set_sysclk(cpcap, CPCAP_DAI_HIFI, 0, 26000000);1612	if (err)1613		return err;1614	err = cpcap_set_sysclk(cpcap, CPCAP_DAI_VOICE, 0, 26000000);1615	if (err)1616		return err;1617 1618	err = cpcap_set_samprate(cpcap, CPCAP_DAI_HIFI, 48000);1619	if (err)1620		return err;1621 1622	err = cpcap_set_samprate(cpcap, CPCAP_DAI_VOICE, 48000);1623	if (err)1624		return err;1625 1626	return 0;1627}1628 1629static int cpcap_soc_probe(struct snd_soc_component *component)1630{1631	struct cpcap_audio *cpcap;1632	int err;1633 1634	cpcap = devm_kzalloc(component->dev, sizeof(*cpcap), GFP_KERNEL);1635	if (!cpcap)1636		return -ENOMEM;1637	snd_soc_component_set_drvdata(component, cpcap);1638	cpcap->component = component;1639 1640	cpcap->regmap = dev_get_regmap(component->dev->parent, NULL);1641	if (!cpcap->regmap)1642		return -ENODEV;1643	snd_soc_component_init_regmap(component, cpcap->regmap);1644 1645	err = cpcap_get_vendor(component->dev, cpcap->regmap, &cpcap->vendor);1646	if (err)1647		return err;1648 1649	return cpcap_audio_reset(component, false);1650}1651 1652static struct snd_soc_component_driver soc_codec_dev_cpcap = {1653	.probe			= cpcap_soc_probe,1654	.controls		= cpcap_snd_controls,1655	.num_controls		= ARRAY_SIZE(cpcap_snd_controls),1656	.dapm_widgets		= cpcap_dapm_widgets,1657	.num_dapm_widgets	= ARRAY_SIZE(cpcap_dapm_widgets),1658	.dapm_routes		= intercon,1659	.num_dapm_routes	= ARRAY_SIZE(intercon),1660	.idle_bias_on		= 1,1661	.use_pmdown_time	= 1,1662	.endianness		= 1,1663};1664 1665static int cpcap_codec_probe(struct platform_device *pdev)1666{1667	struct device_node *codec_node =1668		of_get_child_by_name(pdev->dev.parent->of_node, "audio-codec");1669	if (!codec_node)1670		return -ENODEV;1671 1672	pdev->dev.of_node = codec_node;1673 1674	return devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_cpcap,1675				      cpcap_dai, ARRAY_SIZE(cpcap_dai));1676}1677 1678static struct platform_driver cpcap_codec_driver = {1679	.probe		= cpcap_codec_probe,1680	.driver		= {1681		.name	= "cpcap-codec",1682	},1683};1684module_platform_driver(cpcap_codec_driver);1685 1686MODULE_ALIAS("platform:cpcap-codec");1687MODULE_DESCRIPTION("ASoC CPCAP codec driver");1688MODULE_AUTHOR("Sebastian Reichel");1689MODULE_LICENSE("GPL v2");1690