Loading asoc/codecs/bolero/bolero-cdc-registers.h +7 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _BOLERO_CDC_REGISTERS_H Loading @@ -25,6 +25,12 @@ #define BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL (TX_START_OFFSET + 0x00CC) #define BOLERO_CDC_TX_TOP_CSR_SWR_AMIC0_CTL (TX_START_OFFSET + 0x00D0) #define BOLERO_CDC_TX_TOP_CSR_SWR_AMIC1_CTL (TX_START_OFFSET + 0x00D4) #define BOLERO_CDC_TX_TOP_CSR_SWR_MIC2_CTL (TX_START_OFFSET + 0x00C0) #define BOLERO_CDC_TX_TOP_CSR_SWR_MIC3_CTL (TX_START_OFFSET + 0x00C4) #define BOLERO_CDC_TX_TOP_CSR_SWR_MIC4_CTL (TX_START_OFFSET + 0x00C8) #define BOLERO_CDC_TX_TOP_CSR_SWR_MIC5_CTL (TX_START_OFFSET + 0x00CC) #define BOLERO_CDC_TX_TOP_CSR_SWR_MIC0_CTL (TX_START_OFFSET + 0x00D0) #define BOLERO_CDC_TX_TOP_CSR_SWR_MIC1_CTL (TX_START_OFFSET + 0x00D4) #define BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0 (TX_START_OFFSET + 0x0100) #define BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 (TX_START_OFFSET + 0x0104) #define BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0 (TX_START_OFFSET + 0x0108) Loading asoc/codecs/bolero/tx-macro.c +37 −0 Original line number Diff line number Diff line Loading @@ -904,6 +904,7 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, u16 hpf_gate_reg = 0; u16 tx_gain_ctl_reg = 0; u8 hpf_cut_off_freq = 0; u16 adc_mux_reg = 0; int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS; int unmute_delay = TX_MACRO_DMIC_UNMUTE_DELAY_MS; struct device *tx_dev = NULL; Loading @@ -925,6 +926,8 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, TX_MACRO_TX_PATH_OFFSET * decimator; tx_gain_ctl_reg = BOLERO_CDC_TX0_TX_VOL_CTL + TX_MACRO_TX_PATH_OFFSET * decimator; adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 + TX_MACRO_ADC_MUX_CFG_OFFSET * decimator; switch (event) { case SND_SOC_DAPM_PRE_PMU: Loading Loading @@ -1008,6 +1011,32 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, 0x40); } if (tx_priv->version == BOLERO_VERSION_2_0) { if (snd_soc_component_read32(component, adc_mux_reg) & SWR_MIC) { snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_CTRL, 0x01, 0x01); snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_MIC0_CTL, 0x0E, 0x0C); snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_MIC1_CTL, 0x0E, 0x0C); snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_MIC2_CTL, 0x0E, 0x00); snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_MIC3_CTL, 0x0E, 0x00); snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_MIC4_CTL, 0x0E, 0x00); snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_MIC5_CTL, 0x0E, 0x00); } } break; case SND_SOC_DAPM_PRE_PMD: hpf_cut_off_freq = Loading Loading @@ -1036,6 +1065,14 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, } cancel_delayed_work_sync( &tx_priv->tx_mute_dwork[decimator].dwork); if (tx_priv->version == BOLERO_VERSION_2_0) { if (snd_soc_component_read32(component, adc_mux_reg) & SWR_MIC) snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_CTRL, 0x01, 0x00); } break; case SND_SOC_DAPM_POST_PMD: snd_soc_component_update_bits(component, tx_vol_ctl_reg, Loading asoc/codecs/swr-dmic.c +190 −264 Original line number Diff line number Diff line Loading @@ -27,13 +27,25 @@ #include <asoc/msm-cdc-pinctrl.h> #include <asoc/msm-cdc-supply.h> #include <dt-bindings/sound/audio-codec-port-types.h> #include "wcd938x/wcd938x.h" #include "swr-dmic.h" #define itoa(x) ('0' + x) #define DAI_NAME_NUM_INDEX 11 #define AIF_NAME_NUM_INDEX 12 #define DEFAULT_CODEC_NAME "swr_dmic_tx0" #define DEFAULT_AIF_NAME "SWR_DMIC_AIF0 Playback" static int swr_master_channel_map[] = { ZERO, SWRM_TX1_CH1, SWRM_TX1_CH2, SWRM_TX1_CH3, SWRM_TX1_CH4, SWRM_TX2_CH1, SWRM_TX2_CH2, SWRM_TX2_CH3, SWRM_TX2_CH4, SWRM_TX3_CH1, SWRM_TX3_CH2, SWRM_TX3_CH3, SWRM_TX3_CH4, SWRM_PCM_IN, }; /* * Private data Structure for swr-dmic. All parameters related to Loading @@ -44,12 +56,12 @@ struct swr_dmic_priv { struct swr_device *swr_slave; struct snd_soc_component *component; struct snd_soc_component_driver *driver; struct snd_soc_dai_driver *dai_driver; const char *supply_name; struct snd_soc_component *supply_component; u32 micb_num; struct device_node *wcd_handle; struct cdc_wcd_supply *cdc_supply; bool is_wcd_supply; int tx_mode; int is_en_supply; int port_type; u8 tx_master_port_map[SWR_DMIC_MAX_PORTS]; }; Loading @@ -58,127 +70,34 @@ const char *codec_name_list[] = { "swr-dmic-02", "swr-dmic-03", "swr-dmic-04", "swr-dmic-05", }; static int get_master_port(int val) { int master_port = 0; switch(val) { case 0: master_port = SWRM_TX1_CH1; break; case 1: master_port = SWRM_TX1_CH2; break; case 2: master_port = SWRM_TX1_CH3; break; case 3: master_port = SWRM_TX1_CH4; break; case 4: master_port = SWRM_TX2_CH1; break; case 5: master_port = SWRM_TX2_CH2; break; case 6: master_port = SWRM_TX2_CH3; break; case 7: master_port = SWRM_TX2_CH4; break; case 8: master_port = SWRM_TX3_CH1; break; case 9: master_port = SWRM_TX3_CH2; break; case 10: master_port = SWRM_TX3_CH3; break; case 11: master_port = SWRM_TX3_CH4; break; case 12: master_port = SWRM_PCM_IN; break; default: master_port = SWRM_TX1_CH1; pr_debug("%s: undefined value, fall back to default master_port: %d\n", __func__, master_port); break; } pr_debug("%s: master_port: %d\n", __func__, master_port); return master_port; } static int get_master_port_val(int master_port) { int val = 0; const char *dai_name_list[] = { "swr_dmic_tx0", "swr_dmic_tx1", "swr_dmic_tx2", "swr_dmic_tx3", }; switch (master_port) { case SWRM_TX1_CH1: val = 0; break; case SWRM_TX1_CH2: val = 1; break; case SWRM_TX1_CH3: val = 2; break; case SWRM_TX1_CH4: val = 3; break; case SWRM_TX2_CH1: val = 4; break; case SWRM_TX2_CH2: val = 5; break; case SWRM_TX2_CH3: val = 6; break; case SWRM_TX2_CH4: val = 7; break; case SWRM_TX3_CH1: val = 8; break; case SWRM_TX3_CH2: val = 9; break; case SWRM_TX3_CH3: val = 10; break; case SWRM_TX3_CH4: val = 11; break; case SWRM_PCM_IN: val = 12; break; default: val = 0; pr_debug("%s: undefined master_port:%d, fallback to default val: %d\n", __func__, master_port, val); break; } const char *aif_name_list[] = { "SWR_DMIC_AIF0 Playback", "SWR_DMIC_AIF1 Playback", "SWR_DMIC_AIF2 Playback", "SWR_DMIC_AIF3 Playback", }; pr_debug("%s: master_port:%d val: %d\n", __func__, master_port, val); return val; } static int swr_dmic_reset(struct swr_device *pdev); static int swr_dmic_up(struct swr_device *pdev); static int swr_dmic_down(struct swr_device *pdev); static inline int swr_dmic_tx_get_slave_port_type_idx(const char *wname, unsigned int *port_idx) { u8 port_type; if (strnstr(wname, "HIFI", sizeof("HIFI"))) if (strnstr(wname, "HIFI", strlen(wname))) port_type = SWR_DMIC_HIFI_PORT; else if (strnstr(wname, "LP", sizeof("LP"))) else if (strnstr(wname, "LP", strlen(wname))) port_type = SWR_DMIC_LP_PORT; else return -EINVAL; Loading @@ -187,6 +106,16 @@ static inline int swr_dmic_tx_get_slave_port_type_idx(const char *wname, return 0; } static inline int swr_dmic_get_master_port_val(int port) { int i; for (i = 0; i < ARRAY_SIZE(swr_master_channel_map); i++) if (port == swr_master_channel_map[i]) return i; return 0; } static int swr_dmic_tx_master_port_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading @@ -202,14 +131,15 @@ static int swr_dmic_tx_master_port_get(struct snd_kcontrol *kcontrol, dev_dbg(component->dev, "%s: invalid port string\n", __func__); return ret; } swr_dmic->port_type = slave_port_idx; if (slave_port_idx >= 0 && slave_port_idx < SWR_DMIC_MAX_PORTS) ucontrol->value.integer.value[0] = get_master_port_val( ucontrol->value.integer.value[0] = swr_dmic_get_master_port_val( swr_dmic->tx_master_port_map[slave_port_idx]); dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", __func__, ucontrol->value.integer.value[0]); return 0; } Loading @@ -228,17 +158,13 @@ static int swr_dmic_tx_master_port_put(struct snd_kcontrol *kcontrol, dev_dbg(component->dev, "%s: invalid port string\n", __func__); return ret; } swr_dmic->port_type = slave_port_idx; dev_dbg(component->dev, "%s: slave_port_idx: %d", __func__, slave_port_idx); dev_dbg(component->dev, "%s: ucontrol->value.enumerated.item[0] = %ld\n", __func__, ucontrol->value.enumerated.item[0]); if (slave_port_idx >= 0 && slave_port_idx < SWR_DMIC_MAX_PORTS) swr_dmic->tx_master_port_map[slave_port_idx] = get_master_port( ucontrol->value.enumerated.item[0]); swr_master_channel_map[ucontrol->value.enumerated.item[0]]; dev_dbg(component->dev, "%s: slv port id: %d, master_port_type: %d\n", __func__, slave_port_idx, swr_dmic->tx_master_port_map[slave_port_idx]); return 0; } Loading @@ -254,20 +180,27 @@ static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w, u8 num_ch = 1; u8 ch_mask = 0x01; // only DpnChannelEN1 register is available u8 port_type = 0; u32 ch_rate = 0; u32 ch_rate = SWR_CLK_RATE_4P8MHZ; u8 num_port = 1; u8 port_type = 0; u8 port_id = swr_dmic->port_type; /* * Port 1 is high quality / 2.4 or 3.072 Mbps * Port 2 is listen low power / 0.6 or 0.768 Mbps */ u8 port_id = swr_dmic->tx_mode; if(swr_dmic->port_type) ch_rate = SWR_CLK_RATE_2P4MHZ; else ch_rate = SWR_CLK_RATE_4P8MHZ; port_type = swr_dmic->tx_master_port_map[port_id]; switch (event) { case SND_SOC_DAPM_PRE_PMU: ret = swr_connect_port(swr_dmic->swr_slave, &port_id, num_port, &ch_mask, &ch_rate, &num_ch, &port_type); ret = swr_connect_port(swr_dmic->swr_slave, &port_id, num_port, &ch_mask, &ch_rate, &num_ch, &port_type); break; case SND_SOC_DAPM_POST_PMU: ret = swr_slvdev_datapath_control(swr_dmic->swr_slave, Loading @@ -278,56 +211,48 @@ static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w, swr_dmic->swr_slave->dev_num, false); break; case SND_SOC_DAPM_POST_PMD: ret = swr_disconnect_port(swr_dmic->swr_slave, &port_id, num_port, &ch_mask, &port_type); ret = swr_disconnect_port(swr_dmic->swr_slave, &port_id, num_port, &ch_mask, &port_type); break; }; return ret; } static const char * const tx_mode_text_swr_mic[] = { "MIC_HIFI", "MIC_LP", }; static int swr_mic_tx_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) static int swr_dmic_enable_supply(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); snd_soc_dapm_to_component(w->dapm); struct swr_dmic_priv *swr_dmic = snd_soc_component_get_drvdata(component); int ret = 0; dev_dbg(component->dev, "%s: tx_mode = %ld\n", __func__, ucontrol->value.integer.value[0]); swr_dmic->tx_mode = ucontrol->value.integer.value[0]; dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__, w->name, event); return 0; switch (event) { case SND_SOC_DAPM_PRE_PMU: ret = swr_dmic_up(swr_dmic->swr_slave); break; case SND_SOC_DAPM_POST_PMU: ret = swr_dmic_reset(swr_dmic->swr_slave); break; case SND_SOC_DAPM_POST_PMD: ret = swr_dmic_down(swr_dmic->swr_slave); break; } static int swr_mic_tx_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct swr_dmic_priv *swr_dmic = snd_soc_component_get_drvdata(component); ucontrol->value.integer.value[0] = swr_dmic->tx_mode; if (ret) dev_dbg(component->dev, "%s wname: %s event: %d ret : %d\n", __func__, w->name, event, ret); dev_dbg(component->dev, "%s: tx_mode = 0x%x\n", __func__, swr_dmic->tx_mode); return 0; return ret; } static const struct soc_enum tx_mode_enum_swr_mic = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tx_mode_text_swr_mic), tx_mode_text_swr_mic); static const char * const tx_master_port_text[] = { "SWRM_TX1_CH1", "SWRM_TX1_CH2", "SWRM_TX1_CH3", "SWRM_TX1_CH4", "ZERO", "SWRM_TX1_CH1", "SWRM_TX1_CH2", "SWRM_TX1_CH3", "SWRM_TX1_CH4", "SWRM_TX2_CH1", "SWRM_TX2_CH2", "SWRM_TX2_CH3", "SWRM_TX2_CH4", "SWRM_TX3_CH1", "SWRM_TX3_CH2", "SWRM_TX3_CH3", "SWRM_TX3_CH4", "SWRM_PCM_IN", Loading @@ -338,9 +263,6 @@ static const struct soc_enum tx_master_port_enum = tx_master_port_text); static const struct snd_kcontrol_new swr_dmic_snd_controls[] = { SOC_ENUM_EXT("TX MODE", tx_mode_enum_swr_mic, swr_mic_tx_mode_get, swr_mic_tx_mode_put), SOC_ENUM_EXT("HIFI PortMap", tx_master_port_enum, swr_dmic_tx_master_port_get, swr_dmic_tx_master_port_put), SOC_ENUM_EXT("LP PortMap", tx_master_port_enum, Loading @@ -352,17 +274,23 @@ static const struct snd_kcontrol_new dmic_switch[] = { }; static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = { SND_SOC_DAPM_MIXER_E("DMIC_SWR_MIXER", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MIXER_E("SWR_DMIC_MIXER", SND_SOC_NOPM, 0, 0, dmic_switch, ARRAY_SIZE(dmic_switch), dmic_swr_ctrl, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_INPUT("SWR_DMIC"), SND_SOC_DAPM_SUPPLY_S("SMIC_SUPPLY", 1, SND_SOC_NOPM, 0, 0, swr_dmic_enable_supply, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_OUTPUT("SWR_DMIC_OUTPUT"), }; static const struct snd_soc_dapm_route swr_dmic_audio_map[] = { {"SWR_DMIC", NULL, "SMIC_SUPPLY"}, {"SWR_DMIC_MIXER", "Switch", "SWR_DMIC"}, {"SWR_DMIC_OUTPUT", NULL, "SWR_DMIC_MIXER"}, }; Loading Loading @@ -400,55 +328,63 @@ static const struct snd_soc_component_driver soc_codec_dev_swr_dmic = { .num_dapm_routes = ARRAY_SIZE(swr_dmic_audio_map), }; static struct snd_soc_dai_ops wsa_dai_ops = { }; static int enable_wcd_codec_supply(struct swr_dmic_priv *swr_dmic, bool enable) { int rc = 0; int micb_num = swr_dmic->micb_num; struct snd_soc_component *component = swr_dmic->supply_component; if (!component) { pr_err("%s: component is NULL\n", __func__); return -EINVAL; } static struct snd_soc_dai_driver swr_dmic_dai[] = { if (enable) rc = wcd938x_codec_force_enable_micbias_v2(component, SND_SOC_DAPM_PRE_PMU, micb_num); else rc = wcd938x_codec_force_enable_micbias_v2(component, SND_SOC_DAPM_POST_PMD, micb_num); return rc; } static int swr_dmic_parse_supply(struct device_node *np, struct swr_dmic_priv *swr_dmic) { .name = "", .id = 0, .playback = { .stream_name = "", .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE), .rate_max = 192000, .rate_min = 8000, .channels_min = 1, .channels_max = 2, }, .ops = &wsa_dai_ops, }, }; struct platform_device *pdev = NULL; if (!np || !swr_dmic) return -EINVAL; pdev = of_find_device_by_node(np); if (!pdev) return -EINVAL; swr_dmic->supply_component = snd_soc_lookup_component(&pdev->dev, NULL); return 0; } static int swr_dmic_probe(struct swr_device *pdev) { int ret = 0; struct swr_dmic_priv *swr_dmic; int i = 0; u8 devnum = 0; u8 swr_devnum = 0; int dev_index = -1; char* prefix_name = NULL; struct swr_dmic_priv *swr_dmic = NULL; const char *swr_dmic_name_prefix_of = NULL; const char *swr_dmic_codec_name_of = NULL; struct snd_soc_component *component; char *dai_name; char *aif_name; struct snd_soc_component *component = NULL; swr_dmic = devm_kzalloc(&pdev->dev, sizeof(struct swr_dmic_priv), GFP_KERNEL); if (!swr_dmic) return -ENOMEM; swr_dmic->cdc_supply = devm_kzalloc(&pdev->dev, sizeof(struct cdc_wcd_supply), GFP_KERNEL); if (!swr_dmic->cdc_supply) return -ENOMEM; ret = of_property_read_string(pdev->dev.of_node, "qcom,swr-dmic-supply", &swr_dmic->supply_name); ret = of_property_read_u32(pdev->dev.of_node, "qcom,swr-dmic-supply", &swr_dmic->micb_num); if (ret) { dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n", __func__, "qcom,swr-dmic-supply", Loading @@ -462,17 +398,17 @@ static int swr_dmic_probe(struct swr_device *pdev) __func__); swr_dmic->is_wcd_supply = false; } else { msm_cdc_init_wcd_supply(swr_dmic->wcd_handle, swr_dmic->supply_name, swr_dmic->cdc_supply); swr_dmic_parse_supply(swr_dmic->wcd_handle, swr_dmic); swr_dmic->is_wcd_supply = true; } if (swr_dmic->is_wcd_supply) { ret = msm_cdc_enable_wcd_supply(swr_dmic->cdc_supply, true); ret = enable_wcd_codec_supply(swr_dmic, true); if (ret) { ret = -EPROBE_DEFER; goto err; } ++swr_dmic->is_en_supply; } swr_set_dev_data(pdev, swr_dmic); Loading @@ -485,7 +421,7 @@ static int swr_dmic_probe(struct swr_device *pdev) dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n", __func__, "qcom,swr-dmic-prefix", pdev->dev.of_node->full_name); goto err; goto dev_err; } ret = of_property_read_string(pdev->dev.of_node, "qcom,codec-name", Loading @@ -494,7 +430,7 @@ static int swr_dmic_probe(struct swr_device *pdev) dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n", __func__, "qcom,codec-name", pdev->dev.of_node->full_name); goto err; goto dev_err; } /* Loading @@ -503,14 +439,16 @@ static int swr_dmic_probe(struct swr_device *pdev) * as per HW requirement. */ usleep_range(5000, 5010); ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum); ret = swr_get_logical_dev_num(pdev, pdev->addr, &swr_devnum); if (ret) { dev_dbg(&pdev->dev, "%s get devnum %d for dev addr %lx failed\n", __func__, devnum, pdev->addr); goto dev_err; __func__, swr_devnum, pdev->addr); ret = -EPROBE_DEFER; goto err; } pdev->dev_num = devnum; pdev->dev_num = swr_devnum; swr_dmic->driver = devm_kzalloc(&pdev->dev, sizeof(struct snd_soc_component_driver), GFP_KERNEL); Loading @@ -521,53 +459,23 @@ static int swr_dmic_probe(struct swr_device *pdev) memcpy(swr_dmic->driver, &soc_codec_dev_swr_dmic, sizeof(struct snd_soc_component_driver)); swr_dmic->driver->name = devm_kzalloc(&pdev->dev, strlen(swr_dmic_codec_name_of), GFP_KERNEL); if (!swr_dmic->driver->name) { ret = -ENOMEM; goto dev_err; } for (i = 0; i < ARRAY_SIZE(codec_name_list); i++) { if (!strcmp(swr_dmic_codec_name_of, codec_name_list[i])) if (!strcmp(swr_dmic_codec_name_of, codec_name_list[i])) { dev_index = i; break; } if (i == ARRAY_SIZE(codec_name_list)) goto dev_err; swr_dmic->dai_driver = devm_kzalloc(&pdev->dev, sizeof(struct snd_soc_dai_driver), GFP_KERNEL); if (!swr_dmic->dai_driver) { ret = -ENOMEM; goto dev_err; } memcpy(swr_dmic->dai_driver, swr_dmic_dai, sizeof(struct snd_soc_dai_driver)); dai_name = devm_kzalloc(&pdev->dev, strlen(DEFAULT_CODEC_NAME), GFP_KERNEL); if (!dai_name) { ret = -ENOMEM; if (dev_index < 0) { ret = -EINVAL; goto dev_err; } memcpy(dai_name, DEFAULT_CODEC_NAME, strlen(DEFAULT_CODEC_NAME)); dai_name[DAI_NAME_NUM_INDEX] = itoa(i); swr_dmic->dai_driver->name = dai_name; swr_dmic->dai_driver->id = i; aif_name = devm_kzalloc(&pdev->dev, strlen(DEFAULT_AIF_NAME), GFP_KERNEL); if (!aif_name) { ret = -ENOMEM; goto dev_err; } memcpy(aif_name, DEFAULT_AIF_NAME, strlen(DEFAULT_AIF_NAME)); aif_name[AIF_NAME_NUM_INDEX] = itoa(i); swr_dmic->dai_driver->playback.stream_name = aif_name; swr_dmic->driver->name = dai_name_list[dev_index]; ret = snd_soc_register_component(&pdev->dev, swr_dmic->driver, swr_dmic->dai_driver, 1); NULL, 0); if (ret) { dev_err(&pdev->dev, "%s: Codec registration failed\n", __func__); Loading @@ -577,19 +485,26 @@ static int swr_dmic_probe(struct swr_device *pdev) component = snd_soc_lookup_component(&pdev->dev, swr_dmic->driver->name); swr_dmic->component = component; component->name_prefix = devm_kzalloc(&pdev->dev, prefix_name = devm_kzalloc(&pdev->dev, strlen(swr_dmic_name_prefix_of), GFP_KERNEL); if (!component->name_prefix) { if (!prefix_name) { ret = -ENOMEM; goto dev_err; } strlcpy(prefix_name, swr_dmic_name_prefix_of, strlen(swr_dmic_name_prefix_of)); component->name_prefix = prefix_name; return 0; dev_err: if (swr_dmic->is_wcd_supply) msm_cdc_enable_wcd_supply(swr_dmic->cdc_supply, false); if (swr_dmic->is_en_supply == 1) { enable_wcd_codec_supply(swr_dmic, false); --swr_dmic->is_en_supply; } swr_dmic->is_wcd_supply = false; swr_dmic->wcd_handle = NULL; swr_remove_device(pdev); err: return ret; Loading Loading @@ -620,8 +535,10 @@ static int swr_dmic_up(struct swr_device *pdev) dev_err(&pdev->dev, "%s: swr_dmic is NULL\n", __func__); return -EINVAL; } if (swr_dmic->is_wcd_supply) ret = msm_cdc_enable_wcd_supply(swr_dmic->cdc_supply, true); ++swr_dmic->is_en_supply; if (swr_dmic->is_en_supply == 1) ret = enable_wcd_codec_supply(swr_dmic, true); return ret; } Loading @@ -636,9 +553,18 @@ static int swr_dmic_down(struct swr_device *pdev) dev_err(&pdev->dev, "%s: swr_dmic is NULL\n", __func__); return -EINVAL; } if (swr_dmic->is_wcd_supply) ret = msm_cdc_enable_wcd_supply(swr_dmic->cdc_supply, false); --swr_dmic->is_en_supply; if (swr_dmic->is_en_supply < 0) { dev_warn(&pdev->dev, "%s: mismatch in supply count %d\n", __func__, swr_dmic->is_en_supply); swr_dmic->is_en_supply = 0; goto done; } if (!swr_dmic->is_en_supply) enable_wcd_codec_supply(swr_dmic, false); done: return ret; } Loading asoc/lahaina-port-config.h +3 −5 Original line number Diff line number Diff line Loading @@ -43,11 +43,9 @@ static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = { /* TX UC1: TX1: 1ch, TX2: 2chs, TX3: 1ch(MBHC) */ static struct port_params tx_frame_params_default[SWR_MSTR_PORT_LEN] = { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},/* PCM OUT */ {1, 1, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}, /* TX1 */ {1, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1}, /* TX2 */ {3, 2, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}, /* TX3 */ {3, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1}, /* TX4 */ {3, 1, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}, /* TX1 */ {3, 2, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}, /* TX2 */ {3, 1, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}, /* TX3 */ }; /* TX UC1: TX1: 1ch, TX2: 2chs, TX3: 1ch(MBHC) */ Loading asoc/lahaina.c +177 −14 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
asoc/codecs/bolero/bolero-cdc-registers.h +7 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef _BOLERO_CDC_REGISTERS_H Loading @@ -25,6 +25,12 @@ #define BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL (TX_START_OFFSET + 0x00CC) #define BOLERO_CDC_TX_TOP_CSR_SWR_AMIC0_CTL (TX_START_OFFSET + 0x00D0) #define BOLERO_CDC_TX_TOP_CSR_SWR_AMIC1_CTL (TX_START_OFFSET + 0x00D4) #define BOLERO_CDC_TX_TOP_CSR_SWR_MIC2_CTL (TX_START_OFFSET + 0x00C0) #define BOLERO_CDC_TX_TOP_CSR_SWR_MIC3_CTL (TX_START_OFFSET + 0x00C4) #define BOLERO_CDC_TX_TOP_CSR_SWR_MIC4_CTL (TX_START_OFFSET + 0x00C8) #define BOLERO_CDC_TX_TOP_CSR_SWR_MIC5_CTL (TX_START_OFFSET + 0x00CC) #define BOLERO_CDC_TX_TOP_CSR_SWR_MIC0_CTL (TX_START_OFFSET + 0x00D0) #define BOLERO_CDC_TX_TOP_CSR_SWR_MIC1_CTL (TX_START_OFFSET + 0x00D4) #define BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG0 (TX_START_OFFSET + 0x0100) #define BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 (TX_START_OFFSET + 0x0104) #define BOLERO_CDC_TX_INP_MUX_ADC_MUX1_CFG0 (TX_START_OFFSET + 0x0108) Loading
asoc/codecs/bolero/tx-macro.c +37 −0 Original line number Diff line number Diff line Loading @@ -904,6 +904,7 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, u16 hpf_gate_reg = 0; u16 tx_gain_ctl_reg = 0; u8 hpf_cut_off_freq = 0; u16 adc_mux_reg = 0; int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS; int unmute_delay = TX_MACRO_DMIC_UNMUTE_DELAY_MS; struct device *tx_dev = NULL; Loading @@ -925,6 +926,8 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, TX_MACRO_TX_PATH_OFFSET * decimator; tx_gain_ctl_reg = BOLERO_CDC_TX0_TX_VOL_CTL + TX_MACRO_TX_PATH_OFFSET * decimator; adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 + TX_MACRO_ADC_MUX_CFG_OFFSET * decimator; switch (event) { case SND_SOC_DAPM_PRE_PMU: Loading Loading @@ -1008,6 +1011,32 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, BOLERO_CDC_TX0_TX_PATH_SEC7, 0x40, 0x40); } if (tx_priv->version == BOLERO_VERSION_2_0) { if (snd_soc_component_read32(component, adc_mux_reg) & SWR_MIC) { snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_CTRL, 0x01, 0x01); snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_MIC0_CTL, 0x0E, 0x0C); snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_MIC1_CTL, 0x0E, 0x0C); snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_MIC2_CTL, 0x0E, 0x00); snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_MIC3_CTL, 0x0E, 0x00); snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_MIC4_CTL, 0x0E, 0x00); snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_MIC5_CTL, 0x0E, 0x00); } } break; case SND_SOC_DAPM_PRE_PMD: hpf_cut_off_freq = Loading Loading @@ -1036,6 +1065,14 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, } cancel_delayed_work_sync( &tx_priv->tx_mute_dwork[decimator].dwork); if (tx_priv->version == BOLERO_VERSION_2_0) { if (snd_soc_component_read32(component, adc_mux_reg) & SWR_MIC) snd_soc_component_update_bits(component, BOLERO_CDC_TX_TOP_CSR_SWR_CTRL, 0x01, 0x00); } break; case SND_SOC_DAPM_POST_PMD: snd_soc_component_update_bits(component, tx_vol_ctl_reg, Loading
asoc/codecs/swr-dmic.c +190 −264 Original line number Diff line number Diff line Loading @@ -27,13 +27,25 @@ #include <asoc/msm-cdc-pinctrl.h> #include <asoc/msm-cdc-supply.h> #include <dt-bindings/sound/audio-codec-port-types.h> #include "wcd938x/wcd938x.h" #include "swr-dmic.h" #define itoa(x) ('0' + x) #define DAI_NAME_NUM_INDEX 11 #define AIF_NAME_NUM_INDEX 12 #define DEFAULT_CODEC_NAME "swr_dmic_tx0" #define DEFAULT_AIF_NAME "SWR_DMIC_AIF0 Playback" static int swr_master_channel_map[] = { ZERO, SWRM_TX1_CH1, SWRM_TX1_CH2, SWRM_TX1_CH3, SWRM_TX1_CH4, SWRM_TX2_CH1, SWRM_TX2_CH2, SWRM_TX2_CH3, SWRM_TX2_CH4, SWRM_TX3_CH1, SWRM_TX3_CH2, SWRM_TX3_CH3, SWRM_TX3_CH4, SWRM_PCM_IN, }; /* * Private data Structure for swr-dmic. All parameters related to Loading @@ -44,12 +56,12 @@ struct swr_dmic_priv { struct swr_device *swr_slave; struct snd_soc_component *component; struct snd_soc_component_driver *driver; struct snd_soc_dai_driver *dai_driver; const char *supply_name; struct snd_soc_component *supply_component; u32 micb_num; struct device_node *wcd_handle; struct cdc_wcd_supply *cdc_supply; bool is_wcd_supply; int tx_mode; int is_en_supply; int port_type; u8 tx_master_port_map[SWR_DMIC_MAX_PORTS]; }; Loading @@ -58,127 +70,34 @@ const char *codec_name_list[] = { "swr-dmic-02", "swr-dmic-03", "swr-dmic-04", "swr-dmic-05", }; static int get_master_port(int val) { int master_port = 0; switch(val) { case 0: master_port = SWRM_TX1_CH1; break; case 1: master_port = SWRM_TX1_CH2; break; case 2: master_port = SWRM_TX1_CH3; break; case 3: master_port = SWRM_TX1_CH4; break; case 4: master_port = SWRM_TX2_CH1; break; case 5: master_port = SWRM_TX2_CH2; break; case 6: master_port = SWRM_TX2_CH3; break; case 7: master_port = SWRM_TX2_CH4; break; case 8: master_port = SWRM_TX3_CH1; break; case 9: master_port = SWRM_TX3_CH2; break; case 10: master_port = SWRM_TX3_CH3; break; case 11: master_port = SWRM_TX3_CH4; break; case 12: master_port = SWRM_PCM_IN; break; default: master_port = SWRM_TX1_CH1; pr_debug("%s: undefined value, fall back to default master_port: %d\n", __func__, master_port); break; } pr_debug("%s: master_port: %d\n", __func__, master_port); return master_port; } static int get_master_port_val(int master_port) { int val = 0; const char *dai_name_list[] = { "swr_dmic_tx0", "swr_dmic_tx1", "swr_dmic_tx2", "swr_dmic_tx3", }; switch (master_port) { case SWRM_TX1_CH1: val = 0; break; case SWRM_TX1_CH2: val = 1; break; case SWRM_TX1_CH3: val = 2; break; case SWRM_TX1_CH4: val = 3; break; case SWRM_TX2_CH1: val = 4; break; case SWRM_TX2_CH2: val = 5; break; case SWRM_TX2_CH3: val = 6; break; case SWRM_TX2_CH4: val = 7; break; case SWRM_TX3_CH1: val = 8; break; case SWRM_TX3_CH2: val = 9; break; case SWRM_TX3_CH3: val = 10; break; case SWRM_TX3_CH4: val = 11; break; case SWRM_PCM_IN: val = 12; break; default: val = 0; pr_debug("%s: undefined master_port:%d, fallback to default val: %d\n", __func__, master_port, val); break; } const char *aif_name_list[] = { "SWR_DMIC_AIF0 Playback", "SWR_DMIC_AIF1 Playback", "SWR_DMIC_AIF2 Playback", "SWR_DMIC_AIF3 Playback", }; pr_debug("%s: master_port:%d val: %d\n", __func__, master_port, val); return val; } static int swr_dmic_reset(struct swr_device *pdev); static int swr_dmic_up(struct swr_device *pdev); static int swr_dmic_down(struct swr_device *pdev); static inline int swr_dmic_tx_get_slave_port_type_idx(const char *wname, unsigned int *port_idx) { u8 port_type; if (strnstr(wname, "HIFI", sizeof("HIFI"))) if (strnstr(wname, "HIFI", strlen(wname))) port_type = SWR_DMIC_HIFI_PORT; else if (strnstr(wname, "LP", sizeof("LP"))) else if (strnstr(wname, "LP", strlen(wname))) port_type = SWR_DMIC_LP_PORT; else return -EINVAL; Loading @@ -187,6 +106,16 @@ static inline int swr_dmic_tx_get_slave_port_type_idx(const char *wname, return 0; } static inline int swr_dmic_get_master_port_val(int port) { int i; for (i = 0; i < ARRAY_SIZE(swr_master_channel_map); i++) if (port == swr_master_channel_map[i]) return i; return 0; } static int swr_dmic_tx_master_port_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading @@ -202,14 +131,15 @@ static int swr_dmic_tx_master_port_get(struct snd_kcontrol *kcontrol, dev_dbg(component->dev, "%s: invalid port string\n", __func__); return ret; } swr_dmic->port_type = slave_port_idx; if (slave_port_idx >= 0 && slave_port_idx < SWR_DMIC_MAX_PORTS) ucontrol->value.integer.value[0] = get_master_port_val( ucontrol->value.integer.value[0] = swr_dmic_get_master_port_val( swr_dmic->tx_master_port_map[slave_port_idx]); dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n", __func__, ucontrol->value.integer.value[0]); return 0; } Loading @@ -228,17 +158,13 @@ static int swr_dmic_tx_master_port_put(struct snd_kcontrol *kcontrol, dev_dbg(component->dev, "%s: invalid port string\n", __func__); return ret; } swr_dmic->port_type = slave_port_idx; dev_dbg(component->dev, "%s: slave_port_idx: %d", __func__, slave_port_idx); dev_dbg(component->dev, "%s: ucontrol->value.enumerated.item[0] = %ld\n", __func__, ucontrol->value.enumerated.item[0]); if (slave_port_idx >= 0 && slave_port_idx < SWR_DMIC_MAX_PORTS) swr_dmic->tx_master_port_map[slave_port_idx] = get_master_port( ucontrol->value.enumerated.item[0]); swr_master_channel_map[ucontrol->value.enumerated.item[0]]; dev_dbg(component->dev, "%s: slv port id: %d, master_port_type: %d\n", __func__, slave_port_idx, swr_dmic->tx_master_port_map[slave_port_idx]); return 0; } Loading @@ -254,20 +180,27 @@ static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w, u8 num_ch = 1; u8 ch_mask = 0x01; // only DpnChannelEN1 register is available u8 port_type = 0; u32 ch_rate = 0; u32 ch_rate = SWR_CLK_RATE_4P8MHZ; u8 num_port = 1; u8 port_type = 0; u8 port_id = swr_dmic->port_type; /* * Port 1 is high quality / 2.4 or 3.072 Mbps * Port 2 is listen low power / 0.6 or 0.768 Mbps */ u8 port_id = swr_dmic->tx_mode; if(swr_dmic->port_type) ch_rate = SWR_CLK_RATE_2P4MHZ; else ch_rate = SWR_CLK_RATE_4P8MHZ; port_type = swr_dmic->tx_master_port_map[port_id]; switch (event) { case SND_SOC_DAPM_PRE_PMU: ret = swr_connect_port(swr_dmic->swr_slave, &port_id, num_port, &ch_mask, &ch_rate, &num_ch, &port_type); ret = swr_connect_port(swr_dmic->swr_slave, &port_id, num_port, &ch_mask, &ch_rate, &num_ch, &port_type); break; case SND_SOC_DAPM_POST_PMU: ret = swr_slvdev_datapath_control(swr_dmic->swr_slave, Loading @@ -278,56 +211,48 @@ static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w, swr_dmic->swr_slave->dev_num, false); break; case SND_SOC_DAPM_POST_PMD: ret = swr_disconnect_port(swr_dmic->swr_slave, &port_id, num_port, &ch_mask, &port_type); ret = swr_disconnect_port(swr_dmic->swr_slave, &port_id, num_port, &ch_mask, &port_type); break; }; return ret; } static const char * const tx_mode_text_swr_mic[] = { "MIC_HIFI", "MIC_LP", }; static int swr_mic_tx_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) static int swr_dmic_enable_supply(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); snd_soc_dapm_to_component(w->dapm); struct swr_dmic_priv *swr_dmic = snd_soc_component_get_drvdata(component); int ret = 0; dev_dbg(component->dev, "%s: tx_mode = %ld\n", __func__, ucontrol->value.integer.value[0]); swr_dmic->tx_mode = ucontrol->value.integer.value[0]; dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__, w->name, event); return 0; switch (event) { case SND_SOC_DAPM_PRE_PMU: ret = swr_dmic_up(swr_dmic->swr_slave); break; case SND_SOC_DAPM_POST_PMU: ret = swr_dmic_reset(swr_dmic->swr_slave); break; case SND_SOC_DAPM_POST_PMD: ret = swr_dmic_down(swr_dmic->swr_slave); break; } static int swr_mic_tx_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct swr_dmic_priv *swr_dmic = snd_soc_component_get_drvdata(component); ucontrol->value.integer.value[0] = swr_dmic->tx_mode; if (ret) dev_dbg(component->dev, "%s wname: %s event: %d ret : %d\n", __func__, w->name, event, ret); dev_dbg(component->dev, "%s: tx_mode = 0x%x\n", __func__, swr_dmic->tx_mode); return 0; return ret; } static const struct soc_enum tx_mode_enum_swr_mic = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tx_mode_text_swr_mic), tx_mode_text_swr_mic); static const char * const tx_master_port_text[] = { "SWRM_TX1_CH1", "SWRM_TX1_CH2", "SWRM_TX1_CH3", "SWRM_TX1_CH4", "ZERO", "SWRM_TX1_CH1", "SWRM_TX1_CH2", "SWRM_TX1_CH3", "SWRM_TX1_CH4", "SWRM_TX2_CH1", "SWRM_TX2_CH2", "SWRM_TX2_CH3", "SWRM_TX2_CH4", "SWRM_TX3_CH1", "SWRM_TX3_CH2", "SWRM_TX3_CH3", "SWRM_TX3_CH4", "SWRM_PCM_IN", Loading @@ -338,9 +263,6 @@ static const struct soc_enum tx_master_port_enum = tx_master_port_text); static const struct snd_kcontrol_new swr_dmic_snd_controls[] = { SOC_ENUM_EXT("TX MODE", tx_mode_enum_swr_mic, swr_mic_tx_mode_get, swr_mic_tx_mode_put), SOC_ENUM_EXT("HIFI PortMap", tx_master_port_enum, swr_dmic_tx_master_port_get, swr_dmic_tx_master_port_put), SOC_ENUM_EXT("LP PortMap", tx_master_port_enum, Loading @@ -352,17 +274,23 @@ static const struct snd_kcontrol_new dmic_switch[] = { }; static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = { SND_SOC_DAPM_MIXER_E("DMIC_SWR_MIXER", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_MIXER_E("SWR_DMIC_MIXER", SND_SOC_NOPM, 0, 0, dmic_switch, ARRAY_SIZE(dmic_switch), dmic_swr_ctrl, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_INPUT("SWR_DMIC"), SND_SOC_DAPM_SUPPLY_S("SMIC_SUPPLY", 1, SND_SOC_NOPM, 0, 0, swr_dmic_enable_supply, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_OUTPUT("SWR_DMIC_OUTPUT"), }; static const struct snd_soc_dapm_route swr_dmic_audio_map[] = { {"SWR_DMIC", NULL, "SMIC_SUPPLY"}, {"SWR_DMIC_MIXER", "Switch", "SWR_DMIC"}, {"SWR_DMIC_OUTPUT", NULL, "SWR_DMIC_MIXER"}, }; Loading Loading @@ -400,55 +328,63 @@ static const struct snd_soc_component_driver soc_codec_dev_swr_dmic = { .num_dapm_routes = ARRAY_SIZE(swr_dmic_audio_map), }; static struct snd_soc_dai_ops wsa_dai_ops = { }; static int enable_wcd_codec_supply(struct swr_dmic_priv *swr_dmic, bool enable) { int rc = 0; int micb_num = swr_dmic->micb_num; struct snd_soc_component *component = swr_dmic->supply_component; if (!component) { pr_err("%s: component is NULL\n", __func__); return -EINVAL; } static struct snd_soc_dai_driver swr_dmic_dai[] = { if (enable) rc = wcd938x_codec_force_enable_micbias_v2(component, SND_SOC_DAPM_PRE_PMU, micb_num); else rc = wcd938x_codec_force_enable_micbias_v2(component, SND_SOC_DAPM_POST_PMD, micb_num); return rc; } static int swr_dmic_parse_supply(struct device_node *np, struct swr_dmic_priv *swr_dmic) { .name = "", .id = 0, .playback = { .stream_name = "", .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE), .rate_max = 192000, .rate_min = 8000, .channels_min = 1, .channels_max = 2, }, .ops = &wsa_dai_ops, }, }; struct platform_device *pdev = NULL; if (!np || !swr_dmic) return -EINVAL; pdev = of_find_device_by_node(np); if (!pdev) return -EINVAL; swr_dmic->supply_component = snd_soc_lookup_component(&pdev->dev, NULL); return 0; } static int swr_dmic_probe(struct swr_device *pdev) { int ret = 0; struct swr_dmic_priv *swr_dmic; int i = 0; u8 devnum = 0; u8 swr_devnum = 0; int dev_index = -1; char* prefix_name = NULL; struct swr_dmic_priv *swr_dmic = NULL; const char *swr_dmic_name_prefix_of = NULL; const char *swr_dmic_codec_name_of = NULL; struct snd_soc_component *component; char *dai_name; char *aif_name; struct snd_soc_component *component = NULL; swr_dmic = devm_kzalloc(&pdev->dev, sizeof(struct swr_dmic_priv), GFP_KERNEL); if (!swr_dmic) return -ENOMEM; swr_dmic->cdc_supply = devm_kzalloc(&pdev->dev, sizeof(struct cdc_wcd_supply), GFP_KERNEL); if (!swr_dmic->cdc_supply) return -ENOMEM; ret = of_property_read_string(pdev->dev.of_node, "qcom,swr-dmic-supply", &swr_dmic->supply_name); ret = of_property_read_u32(pdev->dev.of_node, "qcom,swr-dmic-supply", &swr_dmic->micb_num); if (ret) { dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n", __func__, "qcom,swr-dmic-supply", Loading @@ -462,17 +398,17 @@ static int swr_dmic_probe(struct swr_device *pdev) __func__); swr_dmic->is_wcd_supply = false; } else { msm_cdc_init_wcd_supply(swr_dmic->wcd_handle, swr_dmic->supply_name, swr_dmic->cdc_supply); swr_dmic_parse_supply(swr_dmic->wcd_handle, swr_dmic); swr_dmic->is_wcd_supply = true; } if (swr_dmic->is_wcd_supply) { ret = msm_cdc_enable_wcd_supply(swr_dmic->cdc_supply, true); ret = enable_wcd_codec_supply(swr_dmic, true); if (ret) { ret = -EPROBE_DEFER; goto err; } ++swr_dmic->is_en_supply; } swr_set_dev_data(pdev, swr_dmic); Loading @@ -485,7 +421,7 @@ static int swr_dmic_probe(struct swr_device *pdev) dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n", __func__, "qcom,swr-dmic-prefix", pdev->dev.of_node->full_name); goto err; goto dev_err; } ret = of_property_read_string(pdev->dev.of_node, "qcom,codec-name", Loading @@ -494,7 +430,7 @@ static int swr_dmic_probe(struct swr_device *pdev) dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n", __func__, "qcom,codec-name", pdev->dev.of_node->full_name); goto err; goto dev_err; } /* Loading @@ -503,14 +439,16 @@ static int swr_dmic_probe(struct swr_device *pdev) * as per HW requirement. */ usleep_range(5000, 5010); ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum); ret = swr_get_logical_dev_num(pdev, pdev->addr, &swr_devnum); if (ret) { dev_dbg(&pdev->dev, "%s get devnum %d for dev addr %lx failed\n", __func__, devnum, pdev->addr); goto dev_err; __func__, swr_devnum, pdev->addr); ret = -EPROBE_DEFER; goto err; } pdev->dev_num = devnum; pdev->dev_num = swr_devnum; swr_dmic->driver = devm_kzalloc(&pdev->dev, sizeof(struct snd_soc_component_driver), GFP_KERNEL); Loading @@ -521,53 +459,23 @@ static int swr_dmic_probe(struct swr_device *pdev) memcpy(swr_dmic->driver, &soc_codec_dev_swr_dmic, sizeof(struct snd_soc_component_driver)); swr_dmic->driver->name = devm_kzalloc(&pdev->dev, strlen(swr_dmic_codec_name_of), GFP_KERNEL); if (!swr_dmic->driver->name) { ret = -ENOMEM; goto dev_err; } for (i = 0; i < ARRAY_SIZE(codec_name_list); i++) { if (!strcmp(swr_dmic_codec_name_of, codec_name_list[i])) if (!strcmp(swr_dmic_codec_name_of, codec_name_list[i])) { dev_index = i; break; } if (i == ARRAY_SIZE(codec_name_list)) goto dev_err; swr_dmic->dai_driver = devm_kzalloc(&pdev->dev, sizeof(struct snd_soc_dai_driver), GFP_KERNEL); if (!swr_dmic->dai_driver) { ret = -ENOMEM; goto dev_err; } memcpy(swr_dmic->dai_driver, swr_dmic_dai, sizeof(struct snd_soc_dai_driver)); dai_name = devm_kzalloc(&pdev->dev, strlen(DEFAULT_CODEC_NAME), GFP_KERNEL); if (!dai_name) { ret = -ENOMEM; if (dev_index < 0) { ret = -EINVAL; goto dev_err; } memcpy(dai_name, DEFAULT_CODEC_NAME, strlen(DEFAULT_CODEC_NAME)); dai_name[DAI_NAME_NUM_INDEX] = itoa(i); swr_dmic->dai_driver->name = dai_name; swr_dmic->dai_driver->id = i; aif_name = devm_kzalloc(&pdev->dev, strlen(DEFAULT_AIF_NAME), GFP_KERNEL); if (!aif_name) { ret = -ENOMEM; goto dev_err; } memcpy(aif_name, DEFAULT_AIF_NAME, strlen(DEFAULT_AIF_NAME)); aif_name[AIF_NAME_NUM_INDEX] = itoa(i); swr_dmic->dai_driver->playback.stream_name = aif_name; swr_dmic->driver->name = dai_name_list[dev_index]; ret = snd_soc_register_component(&pdev->dev, swr_dmic->driver, swr_dmic->dai_driver, 1); NULL, 0); if (ret) { dev_err(&pdev->dev, "%s: Codec registration failed\n", __func__); Loading @@ -577,19 +485,26 @@ static int swr_dmic_probe(struct swr_device *pdev) component = snd_soc_lookup_component(&pdev->dev, swr_dmic->driver->name); swr_dmic->component = component; component->name_prefix = devm_kzalloc(&pdev->dev, prefix_name = devm_kzalloc(&pdev->dev, strlen(swr_dmic_name_prefix_of), GFP_KERNEL); if (!component->name_prefix) { if (!prefix_name) { ret = -ENOMEM; goto dev_err; } strlcpy(prefix_name, swr_dmic_name_prefix_of, strlen(swr_dmic_name_prefix_of)); component->name_prefix = prefix_name; return 0; dev_err: if (swr_dmic->is_wcd_supply) msm_cdc_enable_wcd_supply(swr_dmic->cdc_supply, false); if (swr_dmic->is_en_supply == 1) { enable_wcd_codec_supply(swr_dmic, false); --swr_dmic->is_en_supply; } swr_dmic->is_wcd_supply = false; swr_dmic->wcd_handle = NULL; swr_remove_device(pdev); err: return ret; Loading Loading @@ -620,8 +535,10 @@ static int swr_dmic_up(struct swr_device *pdev) dev_err(&pdev->dev, "%s: swr_dmic is NULL\n", __func__); return -EINVAL; } if (swr_dmic->is_wcd_supply) ret = msm_cdc_enable_wcd_supply(swr_dmic->cdc_supply, true); ++swr_dmic->is_en_supply; if (swr_dmic->is_en_supply == 1) ret = enable_wcd_codec_supply(swr_dmic, true); return ret; } Loading @@ -636,9 +553,18 @@ static int swr_dmic_down(struct swr_device *pdev) dev_err(&pdev->dev, "%s: swr_dmic is NULL\n", __func__); return -EINVAL; } if (swr_dmic->is_wcd_supply) ret = msm_cdc_enable_wcd_supply(swr_dmic->cdc_supply, false); --swr_dmic->is_en_supply; if (swr_dmic->is_en_supply < 0) { dev_warn(&pdev->dev, "%s: mismatch in supply count %d\n", __func__, swr_dmic->is_en_supply); swr_dmic->is_en_supply = 0; goto done; } if (!swr_dmic->is_en_supply) enable_wcd_codec_supply(swr_dmic, false); done: return ret; } Loading
asoc/lahaina-port-config.h +3 −5 Original line number Diff line number Diff line Loading @@ -43,11 +43,9 @@ static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = { /* TX UC1: TX1: 1ch, TX2: 2chs, TX3: 1ch(MBHC) */ static struct port_params tx_frame_params_default[SWR_MSTR_PORT_LEN] = { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},/* PCM OUT */ {1, 1, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}, /* TX1 */ {1, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1}, /* TX2 */ {3, 2, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}, /* TX3 */ {3, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1}, /* TX4 */ {3, 1, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}, /* TX1 */ {3, 2, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}, /* TX2 */ {3, 1, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}, /* TX3 */ }; /* TX UC1: TX1: 1ch, TX2: 2chs, TX3: 1ch(MBHC) */ Loading