diff --git a/asoc/codecs/swr-dmic.c b/asoc/codecs/swr-dmic.c index 57b0768b86d2..1bed34212a53 100644 --- a/asoc/codecs/swr-dmic.c +++ b/asoc/codecs/swr-dmic.c @@ -169,6 +169,34 @@ static int swr_dmic_tx_master_port_put(struct snd_kcontrol *kcontrol, return 0; } +static int swr_dmic_port_enable(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + int ret = 0; + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct swr_dmic_priv *swr_dmic = + snd_soc_component_get_drvdata(component); + + u8 ch_mask = 0x01; // only DpnChannelEN1 register is available + u8 num_port = 1; + u8 port_id = swr_dmic->port_type; + u8 port_type = swr_dmic->tx_master_port_map[port_id]; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + ret = swr_slvdev_datapath_control(swr_dmic->swr_slave, + swr_dmic->swr_slave->dev_num, true); + break; + case SND_SOC_DAPM_PRE_PMD: + ret = swr_disconnect_port(swr_dmic->swr_slave, + &port_id, num_port, &ch_mask, &port_type); + break; + }; + + return ret; +} + static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -189,31 +217,26 @@ static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w, * Port 1 is high quality / 2.4 or 3.072 Mbps * Port 2 is listen low power / 0.6 or 0.768 Mbps */ - if(swr_dmic->port_type) + if(swr_dmic->port_type == SWR_DMIC_HIFI_PORT) ch_rate = SWR_CLK_RATE_2P4MHZ; else - ch_rate = SWR_CLK_RATE_4P8MHZ; + ch_rate = SWR_CLK_RATE_0P6MHZ; port_type = swr_dmic->tx_master_port_map[port_id]; + dev_dbg(component->dev, "%s port_type: %d event: %d\n", __func__, + port_type, event); + 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); break; - case SND_SOC_DAPM_POST_PMU: - ret = swr_slvdev_datapath_control(swr_dmic->swr_slave, - swr_dmic->swr_slave->dev_num, true); - break; - case SND_SOC_DAPM_PRE_PMD: + case SND_SOC_DAPM_POST_PMD: ret = swr_slvdev_datapath_control(swr_dmic->swr_slave, 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); - break; }; return ret; @@ -276,8 +299,7 @@ static const struct snd_kcontrol_new dmic_switch[] = { static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = { 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_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_INPUT("SWR_DMIC"), @@ -285,14 +307,17 @@ static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = { swr_dmic_enable_supply, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - + SND_SOC_DAPM_OUT_DRV_E("SMIC_PORT_EN", SND_SOC_NOPM, 0, 0, NULL, 0, + swr_dmic_port_enable, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_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"}, + {"SMIC_PORT_EN", NULL, "SWR_DMIC_MIXER"}, + {"SWR_DMIC_OUTPUT", NULL, "SMIC_PORT_EN"}, }; static int swr_dmic_codec_probe(struct snd_soc_component *component) @@ -590,6 +615,7 @@ static int swr_dmic_reset(struct swr_device *pdev) usleep_range(1000, 1100); } pdev->dev_num = devnum; + dev_dbg(&pdev->dev, "%s: devnum: %d\n", __func__, devnum); return 0; } diff --git a/asoc/lahaina-port-config.h b/asoc/lahaina-port-config.h index 42ef69efd4a6..72382cd88299 100644 --- a/asoc/lahaina-port-config.h +++ b/asoc/lahaina-port-config.h @@ -43,7 +43,7 @@ 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] = { - {3, 1, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0}, /* TX1 */ + {7, 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 */ }; diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 3c0e95d5a20a..7491a16b7f72 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -1182,10 +1182,13 @@ static void swrm_copy_data_port_config(struct swr_master *master, u8 bank) struct swr_port_info *port_req; int i; struct swrm_mports *mport; + struct swrm_mports *prev_mport = NULL; u32 reg[SWRM_MAX_PORT_REG]; u32 val[SWRM_MAX_PORT_REG]; int len = 0; u8 hparams; + u8 offset1 = 0; + struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master); if (!swrm) { @@ -1217,9 +1220,18 @@ static void swrm_copy_data_port_config(struct swr_master *master, u8 bank) port_req->dev_num, 0x00, SWRS_DP_SAMPLE_CONTROL_1_BANK(slv_id, bank)); - + /* Assumption: If different channels in the same port + * on master is enabled for different slaves, then each + * slave offset should be configured differently. + */ + if (prev_mport == mport) + offset1 += mport->offset1; + else { + offset1 = mport->offset1; + prev_mport = mport; + } reg[len] = SWRM_CMD_FIFO_WR_CMD; - val[len++] = SWR_REG_VAL_PACK(mport->offset1, + val[len++] = SWR_REG_VAL_PACK(offset1, port_req->dev_num, 0x00, SWRS_DP_OFFSET_CONTROL_1_BANK(slv_id, bank)); @@ -1567,9 +1579,8 @@ static int swrm_connect_port(struct swr_master *master, mport->req_ch |= mstr_ch_msk; master->port_en_mask |= (1 << mstr_port_id); if (swrm->clk_stop_mode0_supp && - swrm->dynamic_port_map_supported && - (mport->ch_rate < portinfo->ch_rate[i])) { - mport->ch_rate = portinfo->ch_rate[i]; + swrm->dynamic_port_map_supported) { + mport->ch_rate += portinfo->ch_rate[i]; swrm_update_bus_clk(swrm); } }