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, ®_voice);377 if (err)378 return err;379 err = regmap_read(cpcap->regmap, CPCAP_REG_RXSDOA, ®_hifi);380 if (err)381 return err;382 err = regmap_read(cpcap->regmap, CPCAP_REG_RXEPOA, ®_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, ®val);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, ®val);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