Loading asoc/sa6155.c +317 −164 Original line number Diff line number Diff line Loading @@ -128,26 +128,24 @@ enum { }; enum pinctrl_pin_state { STATE_DISABLE = 0, /* All pins are in sleep state */ STATE_MI2S_ACTIVE, /* I2S = active, TDM = sleep */ STATE_TDM_ACTIVE, /* I2S = sleep, TDM = active */ STATE_SLEEP = 0, /* All pins are in sleep state */ STATE_ACTIVE, /* TDM = active */ }; struct msm_pinctrl_info { struct pinctrl *pinctrl; struct pinctrl_state *mi2s_disable; struct pinctrl_state *tdm_disable; struct pinctrl_state *mi2s_active; struct pinctrl_state *tdm_active; struct pinctrl_state *sleep; struct pinctrl_state *active; enum pinctrl_pin_state curr_state; }; struct msm_asoc_mach_data { struct msm_pinctrl_info pinctrl_info; }; static const char *const pin_states[] = {"sleep", "active"}; static const char *const pin_states[] = {"sleep", "i2s-active", "tdm-active"}; static const char *const tdm_gpio_phandle[] = {"qcom,pri-tdm-gpios", "qcom,sec-tdm-gpios", "qcom,tert-tdm-gpios", "qcom,quat-tdm-gpios", "qcom,quin-tdm-gpios"}; enum { TDM_0 = 0, Loading Loading @@ -175,6 +173,11 @@ struct tdm_port { u32 channel; }; struct tdm_conf { struct mutex lock; u32 ref_cnt; }; /* TDM default config */ static struct dev_config tdm_rx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = { { /* PRI TDM */ Loading Loading @@ -743,7 +746,11 @@ static struct afe_clk_set mi2s_clk[MI2S_MAX] = { }; static struct mi2s_conf mi2s_intf_conf[MI2S_MAX]; struct msm_asoc_mach_data { struct msm_pinctrl_info pinctrl_info[TDM_INTERFACE_MAX]; struct mi2s_conf mi2s_intf_conf[MI2S_MAX]; struct tdm_conf tdm_intf_conf[TDM_INTERFACE_MAX]; }; static int usb_audio_rx_ch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) Loading Loading @@ -3735,7 +3742,6 @@ static int msm_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable) return ret; } #ifdef ENABLE_PINCTRL static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info, enum pinctrl_pin_state new_state) { Loading @@ -3743,13 +3749,13 @@ static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info, int curr_state = 0; if (pinctrl_info == NULL) { pr_err("%s: pinctrl_info is NULL\n", __func__); pr_err("%s: pinctrl info is NULL\n", __func__); ret = -EINVAL; goto err; } if (pinctrl_info->pinctrl == NULL) { pr_err("%s: pinctrl_info->pinctrl is NULL\n", __func__); pr_err("%s: pinctrl handle is NULL\n", __func__); ret = -EINVAL; goto err; } Loading @@ -3760,55 +3766,40 @@ static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info, pin_states[curr_state], pin_states[pinctrl_info->curr_state]); if (curr_state == pinctrl_info->curr_state) { pr_debug("%s: Already in same state\n", __func__); pr_debug("%s: pin already in same state\n", __func__); goto err; } if (curr_state != STATE_DISABLE && pinctrl_info->curr_state != STATE_DISABLE) { pr_debug("%s: state already active cannot switch\n", __func__); if (curr_state != STATE_SLEEP && pinctrl_info->curr_state != STATE_SLEEP) { pr_debug("%s: pin state is already active, cannot switch\n", __func__); ret = -EIO; goto err; } switch (pinctrl_info->curr_state) { case STATE_MI2S_ACTIVE: case STATE_ACTIVE: ret = pinctrl_select_state(pinctrl_info->pinctrl, pinctrl_info->mi2s_active); pinctrl_info->active); if (ret) { pr_err("%s: MI2S state select failed with %d\n", pr_err("%s: state select to active failed with %d\n", __func__, ret); ret = -EIO; goto err; } break; case STATE_TDM_ACTIVE: case STATE_SLEEP: ret = pinctrl_select_state(pinctrl_info->pinctrl, pinctrl_info->tdm_active); pinctrl_info->sleep); if (ret) { pr_err("%s: TDM state select failed with %d\n", __func__, ret); ret = -EIO; goto err; } break; case STATE_DISABLE: if (curr_state == STATE_MI2S_ACTIVE) { ret = pinctrl_select_state(pinctrl_info->pinctrl, pinctrl_info->mi2s_disable); } else { ret = pinctrl_select_state(pinctrl_info->pinctrl, pinctrl_info->tdm_disable); } if (ret) { pr_err("%s: state disable failed with %d\n", pr_err("%s: state select to sleep failed with %d\n", __func__, ret); ret = -EIO; goto err; } break; default: pr_err("%s: TLMM pin state is invalid\n", __func__); pr_err("%s: pin state is invalid\n", __func__); return -EINVAL; } Loading @@ -3820,97 +3811,191 @@ static void msm_release_pinctrl(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; struct msm_pinctrl_info *pinctrl_info = NULL; int i; for (i = TDM_PRI; i < TDM_INTERFACE_MAX; i++) { pinctrl_info = &pdata->pinctrl_info[i]; if (pinctrl_info == NULL) continue; if (pinctrl_info->pinctrl) { devm_pinctrl_put(pinctrl_info->pinctrl); pinctrl_info->pinctrl = NULL; } } } static int msm_get_pinctrl(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = NULL; struct pinctrl *pinctrl; struct pinctrl *pinctrl = NULL; int i, j; struct device_node *np = NULL; struct platform_device *pdev_np = NULL; int ret = 0; pinctrl_info = &pdata->pinctrl_info; for (i = TDM_PRI; i < TDM_INTERFACE_MAX; i++) { np = of_parse_phandle(pdev->dev.of_node, tdm_gpio_phandle[i], 0); if (!np) { pr_debug("%s: device node %s is null\n", __func__, tdm_gpio_phandle[i]); continue; } pdev_np = of_find_device_by_node(np); if (!pdev_np) { pr_err("%s: platform device not found\n", __func__); continue; } pinctrl_info = &pdata->pinctrl_info[i]; if (pinctrl_info == NULL) { pr_err("%s: pinctrl_info is NULL\n", __func__); return -EINVAL; pr_err("%s: pinctrl info is null\n", __func__); continue; } pinctrl = devm_pinctrl_get(&pdev->dev); pinctrl = devm_pinctrl_get(&pdev_np->dev); if (IS_ERR_OR_NULL(pinctrl)) { pr_err("%s: Unable to get pinctrl handle\n", __func__); return -EINVAL; pr_err("%s: fail to get pinctrl handle\n", __func__); goto err; } pinctrl_info->pinctrl = pinctrl; /* get all the states handles from Device Tree */ pinctrl_info->mi2s_disable = pinctrl_lookup_state(pinctrl, "quat_mi2s_disable"); if (IS_ERR(pinctrl_info->mi2s_disable)) { pr_err("%s: could not get mi2s_disable pinstate\n", __func__); goto err; } pinctrl_info->mi2s_active = pinctrl_lookup_state(pinctrl, "quat_mi2s_enable"); if (IS_ERR(pinctrl_info->mi2s_active)) { pr_err("%s: could not get mi2s_active pinstate\n", __func__); goto err; } pinctrl_info->tdm_disable = pinctrl_lookup_state(pinctrl, "quat_tdm_disable"); if (IS_ERR(pinctrl_info->tdm_disable)) { pr_err("%s: could not get tdm_disable pinstate\n", __func__); pinctrl_info->sleep = pinctrl_lookup_state(pinctrl, "sleep"); if (IS_ERR(pinctrl_info->sleep)) { pr_err("%s: could not get sleep pin state\n", __func__); goto err; } pinctrl_info->tdm_active = pinctrl_lookup_state(pinctrl, "quat_tdm_enable"); if (IS_ERR(pinctrl_info->tdm_active)) { pr_err("%s: could not get tdm_active pinstate\n", pinctrl_info->active = pinctrl_lookup_state(pinctrl, "default"); if (IS_ERR(pinctrl_info->active)) { pr_err("%s: could not get active pin state\n", __func__); goto err; } /* Reset the TLMM pins to a default state */ /* Reset the TLMM pins to a sleep state */ ret = pinctrl_select_state(pinctrl_info->pinctrl, pinctrl_info->mi2s_disable); pinctrl_info->sleep); if (ret != 0) { pr_err("%s: Disable TLMM pins failed with %d\n", pr_err("%s: set pin state to sleep failed with %d\n", __func__, ret); ret = -EIO; goto err; } pinctrl_info->curr_state = STATE_DISABLE; pinctrl_info->curr_state = STATE_SLEEP; } return 0; err: devm_pinctrl_put(pinctrl); for (j = i; j >= 0; j--) { pinctrl_info = &pdata->pinctrl_info[j]; if (pinctrl_info == NULL) continue; if (pinctrl_info->pinctrl) { devm_pinctrl_put(pinctrl_info->pinctrl); pinctrl_info->pinctrl = NULL; return -EINVAL; } #else static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info, enum pinctrl_pin_state new_state) { return 0; } static void msm_release_pinctrl(struct platform_device *pdev) { return; return -EINVAL; } static int msm_get_pinctrl(struct platform_device *pdev) static int msm_tdm_get_intf_idx(u16 id) { return 0; switch (id) { case AFE_PORT_ID_PRIMARY_TDM_RX: case AFE_PORT_ID_PRIMARY_TDM_RX_1: case AFE_PORT_ID_PRIMARY_TDM_RX_2: case AFE_PORT_ID_PRIMARY_TDM_RX_3: case AFE_PORT_ID_PRIMARY_TDM_RX_4: case AFE_PORT_ID_PRIMARY_TDM_RX_5: case AFE_PORT_ID_PRIMARY_TDM_RX_6: case AFE_PORT_ID_PRIMARY_TDM_RX_7: case AFE_PORT_ID_PRIMARY_TDM_TX: case AFE_PORT_ID_PRIMARY_TDM_TX_1: case AFE_PORT_ID_PRIMARY_TDM_TX_2: case AFE_PORT_ID_PRIMARY_TDM_TX_3: case AFE_PORT_ID_PRIMARY_TDM_TX_4: case AFE_PORT_ID_PRIMARY_TDM_TX_5: case AFE_PORT_ID_PRIMARY_TDM_TX_6: case AFE_PORT_ID_PRIMARY_TDM_TX_7: return TDM_PRI; case AFE_PORT_ID_SECONDARY_TDM_RX: case AFE_PORT_ID_SECONDARY_TDM_RX_1: case AFE_PORT_ID_SECONDARY_TDM_RX_2: case AFE_PORT_ID_SECONDARY_TDM_RX_3: case AFE_PORT_ID_SECONDARY_TDM_RX_4: case AFE_PORT_ID_SECONDARY_TDM_RX_5: case AFE_PORT_ID_SECONDARY_TDM_RX_6: case AFE_PORT_ID_SECONDARY_TDM_RX_7: case AFE_PORT_ID_SECONDARY_TDM_TX: case AFE_PORT_ID_SECONDARY_TDM_TX_1: case AFE_PORT_ID_SECONDARY_TDM_TX_2: case AFE_PORT_ID_SECONDARY_TDM_TX_3: case AFE_PORT_ID_SECONDARY_TDM_TX_4: case AFE_PORT_ID_SECONDARY_TDM_TX_5: case AFE_PORT_ID_SECONDARY_TDM_TX_6: case AFE_PORT_ID_SECONDARY_TDM_TX_7: return TDM_SEC; case AFE_PORT_ID_TERTIARY_TDM_RX: case AFE_PORT_ID_TERTIARY_TDM_RX_1: case AFE_PORT_ID_TERTIARY_TDM_RX_2: case AFE_PORT_ID_TERTIARY_TDM_RX_3: case AFE_PORT_ID_TERTIARY_TDM_RX_4: case AFE_PORT_ID_TERTIARY_TDM_RX_5: case AFE_PORT_ID_TERTIARY_TDM_RX_6: case AFE_PORT_ID_TERTIARY_TDM_RX_7: case AFE_PORT_ID_TERTIARY_TDM_TX: case AFE_PORT_ID_TERTIARY_TDM_TX_1: case AFE_PORT_ID_TERTIARY_TDM_TX_2: case AFE_PORT_ID_TERTIARY_TDM_TX_3: case AFE_PORT_ID_TERTIARY_TDM_TX_4: case AFE_PORT_ID_TERTIARY_TDM_TX_5: case AFE_PORT_ID_TERTIARY_TDM_TX_6: case AFE_PORT_ID_TERTIARY_TDM_TX_7: return TDM_TERT; case AFE_PORT_ID_QUATERNARY_TDM_RX: case AFE_PORT_ID_QUATERNARY_TDM_RX_1: case AFE_PORT_ID_QUATERNARY_TDM_RX_2: case AFE_PORT_ID_QUATERNARY_TDM_RX_3: case AFE_PORT_ID_QUATERNARY_TDM_RX_4: case AFE_PORT_ID_QUATERNARY_TDM_RX_5: case AFE_PORT_ID_QUATERNARY_TDM_RX_6: case AFE_PORT_ID_QUATERNARY_TDM_RX_7: case AFE_PORT_ID_QUATERNARY_TDM_TX: case AFE_PORT_ID_QUATERNARY_TDM_TX_1: case AFE_PORT_ID_QUATERNARY_TDM_TX_2: case AFE_PORT_ID_QUATERNARY_TDM_TX_3: case AFE_PORT_ID_QUATERNARY_TDM_TX_4: case AFE_PORT_ID_QUATERNARY_TDM_TX_5: case AFE_PORT_ID_QUATERNARY_TDM_TX_6: case AFE_PORT_ID_QUATERNARY_TDM_TX_7: return TDM_QUAT; case AFE_PORT_ID_QUINARY_TDM_RX: case AFE_PORT_ID_QUINARY_TDM_RX_1: case AFE_PORT_ID_QUINARY_TDM_RX_2: case AFE_PORT_ID_QUINARY_TDM_RX_3: case AFE_PORT_ID_QUINARY_TDM_RX_4: case AFE_PORT_ID_QUINARY_TDM_RX_5: case AFE_PORT_ID_QUINARY_TDM_RX_6: case AFE_PORT_ID_QUINARY_TDM_RX_7: case AFE_PORT_ID_QUINARY_TDM_TX: case AFE_PORT_ID_QUINARY_TDM_TX_1: case AFE_PORT_ID_QUINARY_TDM_TX_2: case AFE_PORT_ID_QUINARY_TDM_TX_3: case AFE_PORT_ID_QUINARY_TDM_TX_4: case AFE_PORT_ID_QUINARY_TDM_TX_5: case AFE_PORT_ID_QUINARY_TDM_TX_6: case AFE_PORT_ID_QUINARY_TDM_TX_7: return TDM_QUIN; default: return -EINVAL; } } #endif static int msm_tdm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) Loading Loading @@ -4661,37 +4746,76 @@ static int sa6155_tdm_snd_startup(struct snd_pcm_substream *substream) struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_card *card = rtd->card; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; struct msm_pinctrl_info *pinctrl_info = NULL; struct tdm_conf *intf_conf = NULL; int ret_pinctrl = 0; int index; /* currently only supporting TDM_RX_0 and TDM_TX_0 */ if ((cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_RX) || (cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_TX)) { ret = msm_set_pinctrl(pinctrl_info, STATE_TDM_ACTIVE); if (ret) pr_debug("%s: substream = %s, stream = %d, dai name = %s, dai id = %d\n", __func__, substream->name, substream->stream, cpu_dai->name, cpu_dai->id); index = msm_tdm_get_intf_idx(cpu_dai->id); if (index < 0) { ret = -EINVAL; pr_err("%s: CPU DAI id (%d) out of range\n", __func__, cpu_dai->id); goto err; } /* * Mutex protection in case the same TDM * interface using for both TX and RX so * that the same clock won't be enable twice. */ intf_conf = &pdata->tdm_intf_conf[index]; mutex_lock(&intf_conf->lock); if (++intf_conf->ref_cnt == 1) { pinctrl_info = &pdata->pinctrl_info[index]; ret_pinctrl = msm_set_pinctrl(pinctrl_info, STATE_ACTIVE); if (ret_pinctrl) pr_err("%s: TDM TLMM pinctrl set failed with %d\n", __func__, ret); __func__, ret_pinctrl); } mutex_unlock(&intf_conf->lock); err: return ret; } static void sa6155_tdm_snd_shutdown(struct snd_pcm_substream *substream) { int ret = 0; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_card *card = rtd->card; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; struct msm_pinctrl_info *pinctrl_info = NULL; struct tdm_conf *intf_conf = NULL; int ret_pinctrl = 0; int index; /* currently only supporting TDM_RX_0 and TDM_TX_0 */ if ((cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_RX) || (cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_TX)) { ret = msm_set_pinctrl(pinctrl_info, STATE_DISABLE); if (ret) pr_debug("%s: substream = %s, stream = %d\n", __func__, substream->name, substream->stream); index = msm_tdm_get_intf_idx(cpu_dai->id); if (index < 0) { pr_err("%s: CPU DAI id (%d) out of range\n", __func__, cpu_dai->id); return; } intf_conf = &pdata->tdm_intf_conf[index]; mutex_lock(&intf_conf->lock); if (--intf_conf->ref_cnt == 0) { pinctrl_info = &pdata->pinctrl_info[index]; ret_pinctrl = msm_set_pinctrl(pinctrl_info, STATE_SLEEP); if (ret_pinctrl) pr_err("%s: TDM TLMM pinctrl set failed with %d\n", __func__, ret); __func__, ret_pinctrl); } mutex_unlock(&intf_conf->lock); } static struct snd_soc_ops sa6155_tdm_be_ops = { Loading Loading @@ -4733,7 +4857,8 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; struct snd_soc_card *card = rtd->card; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; struct msm_pinctrl_info *pinctrl_info = NULL; struct mi2s_conf *intf_conf = NULL; int ret_pinctrl = 0; dev_dbg(rtd->card->dev, Loading @@ -4753,10 +4878,11 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) * interface using for both TX and RX so * that the same clock won't be enable twice. */ mutex_lock(&mi2s_intf_conf[index].lock); if (++mi2s_intf_conf[index].ref_cnt == 1) { intf_conf = &pdata->mi2s_intf_conf[index]; mutex_lock(&intf_conf->lock); if (++intf_conf->ref_cnt == 1) { /* Check if msm needs to provide the clock to the interface */ if (!mi2s_intf_conf[index].msm_is_mi2s_master) { if (!intf_conf->msm_is_mi2s_master) { mi2s_clk[index].clk_id = mi2s_ebit_clk[index]; fmt = SND_SOC_DAIFMT_CBM_CFM; } Loading @@ -4774,21 +4900,21 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) __func__, index, ret); goto clk_off; } if (index == QUAT_MI2S) { pinctrl_info = &pdata->pinctrl_info[index]; ret_pinctrl = msm_set_pinctrl(pinctrl_info, STATE_MI2S_ACTIVE); STATE_ACTIVE); if (ret_pinctrl) pr_err("%s: MI2S TLMM pinctrl set failed with %d\n", __func__, ret_pinctrl); } } clk_off: if (ret < 0) msm_mi2s_set_sclk(substream, false); clean_up: if (ret < 0) mi2s_intf_conf[index].ref_cnt--; mutex_unlock(&mi2s_intf_conf[index].lock); intf_conf->ref_cnt--; mutex_unlock(&intf_conf->lock); err: return ret; } Loading @@ -4800,7 +4926,8 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) int index = rtd->cpu_dai->id; struct snd_soc_card *card = rtd->card; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; struct msm_pinctrl_info *pinctrl_info = NULL; struct mi2s_conf *intf_conf = NULL; int ret_pinctrl = 0; pr_debug("%s(): substream = %s stream = %d\n", __func__, Loading @@ -4810,21 +4937,22 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) return; } mutex_lock(&mi2s_intf_conf[index].lock); if (--mi2s_intf_conf[index].ref_cnt == 0) { intf_conf = &pdata->mi2s_intf_conf[index]; mutex_lock(&intf_conf->lock); if (--intf_conf->ref_cnt == 0) { ret = msm_mi2s_set_sclk(substream, false); if (ret < 0) pr_err("%s:clock disable failed for MI2S (%d); ret=%d\n", __func__, index, ret); if (index == QUAT_MI2S) { pinctrl_info = &pdata->pinctrl_info[index]; ret_pinctrl = msm_set_pinctrl(pinctrl_info, STATE_DISABLE); STATE_SLEEP); if (ret_pinctrl) pr_err("%s: MI2S TLMM pinctrl set failed with %d\n", __func__, ret_pinctrl); } } mutex_unlock(&mi2s_intf_conf[index].lock); mutex_unlock(&intf_conf->lock); } static struct snd_soc_ops msm_mi2s_be_ops = { Loading Loading @@ -7087,19 +7215,22 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) /***************************************************************************** * TO BE UPDATED: Codec/Platform specific tdm slot and offset table selection *****************************************************************************/ static int msm_tdm_init(struct device *dev) static int msm_tdm_init(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); const struct of_device_id *match; int count; match = of_match_node(sa6155_asoc_machine_of_match, dev->of_node); match = of_match_node(sa6155_asoc_machine_of_match, pdev->dev.of_node); if (!match) { dev_err(dev, "%s: No DT match found for sound card\n", dev_err(&pdev->dev, "%s: No DT match found for sound card\n", __func__); return -EINVAL; } if (!strcmp(match->data, "custom_codec")) { dev_dbg(dev, "%s: custom tdm configuration\n", __func__); dev_dbg(&pdev->dev, "%s: custom tdm configuration\n", __func__); memcpy(tdm_rx_slot_offset, tdm_rx_slot_offset_custom, Loading @@ -7111,21 +7242,40 @@ static int msm_tdm_init(struct device *dev) tdm_slot_custom, sizeof(tdm_slot_custom)); } else { dev_dbg(dev, "%s: default tdm configuration\n", __func__); dev_dbg(&pdev->dev, "%s: default tdm configuration\n", __func__); } for (count = 0; count < TDM_INTERFACE_MAX; count++) { mutex_init(&pdata->tdm_intf_conf[count].lock); pdata->tdm_intf_conf[count].ref_cnt = 0; } return 0; } static void msm_tdm_deinit(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); int count; for (count = 0; count < TDM_INTERFACE_MAX; count++) { mutex_destroy(&pdata->tdm_intf_conf[count].lock); pdata->tdm_intf_conf[count].ref_cnt = 0; } } static void msm_i2s_auxpcm_init(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); int count; u32 mi2s_master_slave[MI2S_MAX]; int ret; for (count = 0; count < MI2S_MAX; count++) { mutex_init(&mi2s_intf_conf[count].lock); mi2s_intf_conf[count].ref_cnt = 0; mutex_init(&pdata->mi2s_intf_conf[count].lock); pdata->mi2s_intf_conf[count].ref_cnt = 0; } ret = of_property_read_u32_array(pdev->dev.of_node, Loading @@ -7136,20 +7286,22 @@ static void msm_i2s_auxpcm_init(struct platform_device *pdev) __func__); } else { for (count = 0; count < MI2S_MAX; count++) { mi2s_intf_conf[count].msm_is_mi2s_master = pdata->mi2s_intf_conf[count].msm_is_mi2s_master = mi2s_master_slave[count]; } } } static void msm_i2s_auxpcm_deinit(void) static void msm_i2s_auxpcm_deinit(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); int count; for (count = 0; count < MI2S_MAX; count++) { mutex_destroy(&mi2s_intf_conf[count].lock); mi2s_intf_conf[count].ref_cnt = 0; mi2s_intf_conf[count].msm_is_mi2s_master = 0; mutex_destroy(&pdata->mi2s_intf_conf[count].lock); pdata->mi2s_intf_conf[count].ref_cnt = 0; pdata->mi2s_intf_conf[count].msm_is_mi2s_master = 0; } } Loading Loading @@ -7275,7 +7427,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) card->controls = msm_snd_controls; card->num_controls = ARRAY_SIZE(msm_snd_controls); ret = msm_tdm_init(&pdev->dev); ret = msm_tdm_init(pdev); if (ret) { ret = -EPROBE_DEFER; goto err; Loading @@ -7297,7 +7449,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) pr_debug("%s: pinctrl parsing successful\n", __func__); } else { dev_dbg(&pdev->dev, "%s: Parsing pinctrl failed with %d. Cannot use Ports\n", "%s: pinctrl parsing failed with %d\n", __func__, ret); ret = 0; } Loading @@ -7318,7 +7470,8 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) static int msm_asoc_machine_remove(struct platform_device *pdev) { msm_i2s_auxpcm_deinit(); msm_i2s_auxpcm_deinit(pdev); msm_tdm_deinit(pdev); msm_release_pinctrl(pdev); return 0; Loading Loading
asoc/sa6155.c +317 −164 Original line number Diff line number Diff line Loading @@ -128,26 +128,24 @@ enum { }; enum pinctrl_pin_state { STATE_DISABLE = 0, /* All pins are in sleep state */ STATE_MI2S_ACTIVE, /* I2S = active, TDM = sleep */ STATE_TDM_ACTIVE, /* I2S = sleep, TDM = active */ STATE_SLEEP = 0, /* All pins are in sleep state */ STATE_ACTIVE, /* TDM = active */ }; struct msm_pinctrl_info { struct pinctrl *pinctrl; struct pinctrl_state *mi2s_disable; struct pinctrl_state *tdm_disable; struct pinctrl_state *mi2s_active; struct pinctrl_state *tdm_active; struct pinctrl_state *sleep; struct pinctrl_state *active; enum pinctrl_pin_state curr_state; }; struct msm_asoc_mach_data { struct msm_pinctrl_info pinctrl_info; }; static const char *const pin_states[] = {"sleep", "active"}; static const char *const pin_states[] = {"sleep", "i2s-active", "tdm-active"}; static const char *const tdm_gpio_phandle[] = {"qcom,pri-tdm-gpios", "qcom,sec-tdm-gpios", "qcom,tert-tdm-gpios", "qcom,quat-tdm-gpios", "qcom,quin-tdm-gpios"}; enum { TDM_0 = 0, Loading Loading @@ -175,6 +173,11 @@ struct tdm_port { u32 channel; }; struct tdm_conf { struct mutex lock; u32 ref_cnt; }; /* TDM default config */ static struct dev_config tdm_rx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = { { /* PRI TDM */ Loading Loading @@ -743,7 +746,11 @@ static struct afe_clk_set mi2s_clk[MI2S_MAX] = { }; static struct mi2s_conf mi2s_intf_conf[MI2S_MAX]; struct msm_asoc_mach_data { struct msm_pinctrl_info pinctrl_info[TDM_INTERFACE_MAX]; struct mi2s_conf mi2s_intf_conf[MI2S_MAX]; struct tdm_conf tdm_intf_conf[TDM_INTERFACE_MAX]; }; static int usb_audio_rx_ch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) Loading Loading @@ -3735,7 +3742,6 @@ static int msm_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable) return ret; } #ifdef ENABLE_PINCTRL static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info, enum pinctrl_pin_state new_state) { Loading @@ -3743,13 +3749,13 @@ static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info, int curr_state = 0; if (pinctrl_info == NULL) { pr_err("%s: pinctrl_info is NULL\n", __func__); pr_err("%s: pinctrl info is NULL\n", __func__); ret = -EINVAL; goto err; } if (pinctrl_info->pinctrl == NULL) { pr_err("%s: pinctrl_info->pinctrl is NULL\n", __func__); pr_err("%s: pinctrl handle is NULL\n", __func__); ret = -EINVAL; goto err; } Loading @@ -3760,55 +3766,40 @@ static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info, pin_states[curr_state], pin_states[pinctrl_info->curr_state]); if (curr_state == pinctrl_info->curr_state) { pr_debug("%s: Already in same state\n", __func__); pr_debug("%s: pin already in same state\n", __func__); goto err; } if (curr_state != STATE_DISABLE && pinctrl_info->curr_state != STATE_DISABLE) { pr_debug("%s: state already active cannot switch\n", __func__); if (curr_state != STATE_SLEEP && pinctrl_info->curr_state != STATE_SLEEP) { pr_debug("%s: pin state is already active, cannot switch\n", __func__); ret = -EIO; goto err; } switch (pinctrl_info->curr_state) { case STATE_MI2S_ACTIVE: case STATE_ACTIVE: ret = pinctrl_select_state(pinctrl_info->pinctrl, pinctrl_info->mi2s_active); pinctrl_info->active); if (ret) { pr_err("%s: MI2S state select failed with %d\n", pr_err("%s: state select to active failed with %d\n", __func__, ret); ret = -EIO; goto err; } break; case STATE_TDM_ACTIVE: case STATE_SLEEP: ret = pinctrl_select_state(pinctrl_info->pinctrl, pinctrl_info->tdm_active); pinctrl_info->sleep); if (ret) { pr_err("%s: TDM state select failed with %d\n", __func__, ret); ret = -EIO; goto err; } break; case STATE_DISABLE: if (curr_state == STATE_MI2S_ACTIVE) { ret = pinctrl_select_state(pinctrl_info->pinctrl, pinctrl_info->mi2s_disable); } else { ret = pinctrl_select_state(pinctrl_info->pinctrl, pinctrl_info->tdm_disable); } if (ret) { pr_err("%s: state disable failed with %d\n", pr_err("%s: state select to sleep failed with %d\n", __func__, ret); ret = -EIO; goto err; } break; default: pr_err("%s: TLMM pin state is invalid\n", __func__); pr_err("%s: pin state is invalid\n", __func__); return -EINVAL; } Loading @@ -3820,97 +3811,191 @@ static void msm_release_pinctrl(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; struct msm_pinctrl_info *pinctrl_info = NULL; int i; for (i = TDM_PRI; i < TDM_INTERFACE_MAX; i++) { pinctrl_info = &pdata->pinctrl_info[i]; if (pinctrl_info == NULL) continue; if (pinctrl_info->pinctrl) { devm_pinctrl_put(pinctrl_info->pinctrl); pinctrl_info->pinctrl = NULL; } } } static int msm_get_pinctrl(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = NULL; struct pinctrl *pinctrl; struct pinctrl *pinctrl = NULL; int i, j; struct device_node *np = NULL; struct platform_device *pdev_np = NULL; int ret = 0; pinctrl_info = &pdata->pinctrl_info; for (i = TDM_PRI; i < TDM_INTERFACE_MAX; i++) { np = of_parse_phandle(pdev->dev.of_node, tdm_gpio_phandle[i], 0); if (!np) { pr_debug("%s: device node %s is null\n", __func__, tdm_gpio_phandle[i]); continue; } pdev_np = of_find_device_by_node(np); if (!pdev_np) { pr_err("%s: platform device not found\n", __func__); continue; } pinctrl_info = &pdata->pinctrl_info[i]; if (pinctrl_info == NULL) { pr_err("%s: pinctrl_info is NULL\n", __func__); return -EINVAL; pr_err("%s: pinctrl info is null\n", __func__); continue; } pinctrl = devm_pinctrl_get(&pdev->dev); pinctrl = devm_pinctrl_get(&pdev_np->dev); if (IS_ERR_OR_NULL(pinctrl)) { pr_err("%s: Unable to get pinctrl handle\n", __func__); return -EINVAL; pr_err("%s: fail to get pinctrl handle\n", __func__); goto err; } pinctrl_info->pinctrl = pinctrl; /* get all the states handles from Device Tree */ pinctrl_info->mi2s_disable = pinctrl_lookup_state(pinctrl, "quat_mi2s_disable"); if (IS_ERR(pinctrl_info->mi2s_disable)) { pr_err("%s: could not get mi2s_disable pinstate\n", __func__); goto err; } pinctrl_info->mi2s_active = pinctrl_lookup_state(pinctrl, "quat_mi2s_enable"); if (IS_ERR(pinctrl_info->mi2s_active)) { pr_err("%s: could not get mi2s_active pinstate\n", __func__); goto err; } pinctrl_info->tdm_disable = pinctrl_lookup_state(pinctrl, "quat_tdm_disable"); if (IS_ERR(pinctrl_info->tdm_disable)) { pr_err("%s: could not get tdm_disable pinstate\n", __func__); pinctrl_info->sleep = pinctrl_lookup_state(pinctrl, "sleep"); if (IS_ERR(pinctrl_info->sleep)) { pr_err("%s: could not get sleep pin state\n", __func__); goto err; } pinctrl_info->tdm_active = pinctrl_lookup_state(pinctrl, "quat_tdm_enable"); if (IS_ERR(pinctrl_info->tdm_active)) { pr_err("%s: could not get tdm_active pinstate\n", pinctrl_info->active = pinctrl_lookup_state(pinctrl, "default"); if (IS_ERR(pinctrl_info->active)) { pr_err("%s: could not get active pin state\n", __func__); goto err; } /* Reset the TLMM pins to a default state */ /* Reset the TLMM pins to a sleep state */ ret = pinctrl_select_state(pinctrl_info->pinctrl, pinctrl_info->mi2s_disable); pinctrl_info->sleep); if (ret != 0) { pr_err("%s: Disable TLMM pins failed with %d\n", pr_err("%s: set pin state to sleep failed with %d\n", __func__, ret); ret = -EIO; goto err; } pinctrl_info->curr_state = STATE_DISABLE; pinctrl_info->curr_state = STATE_SLEEP; } return 0; err: devm_pinctrl_put(pinctrl); for (j = i; j >= 0; j--) { pinctrl_info = &pdata->pinctrl_info[j]; if (pinctrl_info == NULL) continue; if (pinctrl_info->pinctrl) { devm_pinctrl_put(pinctrl_info->pinctrl); pinctrl_info->pinctrl = NULL; return -EINVAL; } #else static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info, enum pinctrl_pin_state new_state) { return 0; } static void msm_release_pinctrl(struct platform_device *pdev) { return; return -EINVAL; } static int msm_get_pinctrl(struct platform_device *pdev) static int msm_tdm_get_intf_idx(u16 id) { return 0; switch (id) { case AFE_PORT_ID_PRIMARY_TDM_RX: case AFE_PORT_ID_PRIMARY_TDM_RX_1: case AFE_PORT_ID_PRIMARY_TDM_RX_2: case AFE_PORT_ID_PRIMARY_TDM_RX_3: case AFE_PORT_ID_PRIMARY_TDM_RX_4: case AFE_PORT_ID_PRIMARY_TDM_RX_5: case AFE_PORT_ID_PRIMARY_TDM_RX_6: case AFE_PORT_ID_PRIMARY_TDM_RX_7: case AFE_PORT_ID_PRIMARY_TDM_TX: case AFE_PORT_ID_PRIMARY_TDM_TX_1: case AFE_PORT_ID_PRIMARY_TDM_TX_2: case AFE_PORT_ID_PRIMARY_TDM_TX_3: case AFE_PORT_ID_PRIMARY_TDM_TX_4: case AFE_PORT_ID_PRIMARY_TDM_TX_5: case AFE_PORT_ID_PRIMARY_TDM_TX_6: case AFE_PORT_ID_PRIMARY_TDM_TX_7: return TDM_PRI; case AFE_PORT_ID_SECONDARY_TDM_RX: case AFE_PORT_ID_SECONDARY_TDM_RX_1: case AFE_PORT_ID_SECONDARY_TDM_RX_2: case AFE_PORT_ID_SECONDARY_TDM_RX_3: case AFE_PORT_ID_SECONDARY_TDM_RX_4: case AFE_PORT_ID_SECONDARY_TDM_RX_5: case AFE_PORT_ID_SECONDARY_TDM_RX_6: case AFE_PORT_ID_SECONDARY_TDM_RX_7: case AFE_PORT_ID_SECONDARY_TDM_TX: case AFE_PORT_ID_SECONDARY_TDM_TX_1: case AFE_PORT_ID_SECONDARY_TDM_TX_2: case AFE_PORT_ID_SECONDARY_TDM_TX_3: case AFE_PORT_ID_SECONDARY_TDM_TX_4: case AFE_PORT_ID_SECONDARY_TDM_TX_5: case AFE_PORT_ID_SECONDARY_TDM_TX_6: case AFE_PORT_ID_SECONDARY_TDM_TX_7: return TDM_SEC; case AFE_PORT_ID_TERTIARY_TDM_RX: case AFE_PORT_ID_TERTIARY_TDM_RX_1: case AFE_PORT_ID_TERTIARY_TDM_RX_2: case AFE_PORT_ID_TERTIARY_TDM_RX_3: case AFE_PORT_ID_TERTIARY_TDM_RX_4: case AFE_PORT_ID_TERTIARY_TDM_RX_5: case AFE_PORT_ID_TERTIARY_TDM_RX_6: case AFE_PORT_ID_TERTIARY_TDM_RX_7: case AFE_PORT_ID_TERTIARY_TDM_TX: case AFE_PORT_ID_TERTIARY_TDM_TX_1: case AFE_PORT_ID_TERTIARY_TDM_TX_2: case AFE_PORT_ID_TERTIARY_TDM_TX_3: case AFE_PORT_ID_TERTIARY_TDM_TX_4: case AFE_PORT_ID_TERTIARY_TDM_TX_5: case AFE_PORT_ID_TERTIARY_TDM_TX_6: case AFE_PORT_ID_TERTIARY_TDM_TX_7: return TDM_TERT; case AFE_PORT_ID_QUATERNARY_TDM_RX: case AFE_PORT_ID_QUATERNARY_TDM_RX_1: case AFE_PORT_ID_QUATERNARY_TDM_RX_2: case AFE_PORT_ID_QUATERNARY_TDM_RX_3: case AFE_PORT_ID_QUATERNARY_TDM_RX_4: case AFE_PORT_ID_QUATERNARY_TDM_RX_5: case AFE_PORT_ID_QUATERNARY_TDM_RX_6: case AFE_PORT_ID_QUATERNARY_TDM_RX_7: case AFE_PORT_ID_QUATERNARY_TDM_TX: case AFE_PORT_ID_QUATERNARY_TDM_TX_1: case AFE_PORT_ID_QUATERNARY_TDM_TX_2: case AFE_PORT_ID_QUATERNARY_TDM_TX_3: case AFE_PORT_ID_QUATERNARY_TDM_TX_4: case AFE_PORT_ID_QUATERNARY_TDM_TX_5: case AFE_PORT_ID_QUATERNARY_TDM_TX_6: case AFE_PORT_ID_QUATERNARY_TDM_TX_7: return TDM_QUAT; case AFE_PORT_ID_QUINARY_TDM_RX: case AFE_PORT_ID_QUINARY_TDM_RX_1: case AFE_PORT_ID_QUINARY_TDM_RX_2: case AFE_PORT_ID_QUINARY_TDM_RX_3: case AFE_PORT_ID_QUINARY_TDM_RX_4: case AFE_PORT_ID_QUINARY_TDM_RX_5: case AFE_PORT_ID_QUINARY_TDM_RX_6: case AFE_PORT_ID_QUINARY_TDM_RX_7: case AFE_PORT_ID_QUINARY_TDM_TX: case AFE_PORT_ID_QUINARY_TDM_TX_1: case AFE_PORT_ID_QUINARY_TDM_TX_2: case AFE_PORT_ID_QUINARY_TDM_TX_3: case AFE_PORT_ID_QUINARY_TDM_TX_4: case AFE_PORT_ID_QUINARY_TDM_TX_5: case AFE_PORT_ID_QUINARY_TDM_TX_6: case AFE_PORT_ID_QUINARY_TDM_TX_7: return TDM_QUIN; default: return -EINVAL; } } #endif static int msm_tdm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) Loading Loading @@ -4661,37 +4746,76 @@ static int sa6155_tdm_snd_startup(struct snd_pcm_substream *substream) struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_card *card = rtd->card; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; struct msm_pinctrl_info *pinctrl_info = NULL; struct tdm_conf *intf_conf = NULL; int ret_pinctrl = 0; int index; /* currently only supporting TDM_RX_0 and TDM_TX_0 */ if ((cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_RX) || (cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_TX)) { ret = msm_set_pinctrl(pinctrl_info, STATE_TDM_ACTIVE); if (ret) pr_debug("%s: substream = %s, stream = %d, dai name = %s, dai id = %d\n", __func__, substream->name, substream->stream, cpu_dai->name, cpu_dai->id); index = msm_tdm_get_intf_idx(cpu_dai->id); if (index < 0) { ret = -EINVAL; pr_err("%s: CPU DAI id (%d) out of range\n", __func__, cpu_dai->id); goto err; } /* * Mutex protection in case the same TDM * interface using for both TX and RX so * that the same clock won't be enable twice. */ intf_conf = &pdata->tdm_intf_conf[index]; mutex_lock(&intf_conf->lock); if (++intf_conf->ref_cnt == 1) { pinctrl_info = &pdata->pinctrl_info[index]; ret_pinctrl = msm_set_pinctrl(pinctrl_info, STATE_ACTIVE); if (ret_pinctrl) pr_err("%s: TDM TLMM pinctrl set failed with %d\n", __func__, ret); __func__, ret_pinctrl); } mutex_unlock(&intf_conf->lock); err: return ret; } static void sa6155_tdm_snd_shutdown(struct snd_pcm_substream *substream) { int ret = 0; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_card *card = rtd->card; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; struct msm_pinctrl_info *pinctrl_info = NULL; struct tdm_conf *intf_conf = NULL; int ret_pinctrl = 0; int index; /* currently only supporting TDM_RX_0 and TDM_TX_0 */ if ((cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_RX) || (cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_TX)) { ret = msm_set_pinctrl(pinctrl_info, STATE_DISABLE); if (ret) pr_debug("%s: substream = %s, stream = %d\n", __func__, substream->name, substream->stream); index = msm_tdm_get_intf_idx(cpu_dai->id); if (index < 0) { pr_err("%s: CPU DAI id (%d) out of range\n", __func__, cpu_dai->id); return; } intf_conf = &pdata->tdm_intf_conf[index]; mutex_lock(&intf_conf->lock); if (--intf_conf->ref_cnt == 0) { pinctrl_info = &pdata->pinctrl_info[index]; ret_pinctrl = msm_set_pinctrl(pinctrl_info, STATE_SLEEP); if (ret_pinctrl) pr_err("%s: TDM TLMM pinctrl set failed with %d\n", __func__, ret); __func__, ret_pinctrl); } mutex_unlock(&intf_conf->lock); } static struct snd_soc_ops sa6155_tdm_be_ops = { Loading Loading @@ -4733,7 +4857,8 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; struct snd_soc_card *card = rtd->card; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; struct msm_pinctrl_info *pinctrl_info = NULL; struct mi2s_conf *intf_conf = NULL; int ret_pinctrl = 0; dev_dbg(rtd->card->dev, Loading @@ -4753,10 +4878,11 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) * interface using for both TX and RX so * that the same clock won't be enable twice. */ mutex_lock(&mi2s_intf_conf[index].lock); if (++mi2s_intf_conf[index].ref_cnt == 1) { intf_conf = &pdata->mi2s_intf_conf[index]; mutex_lock(&intf_conf->lock); if (++intf_conf->ref_cnt == 1) { /* Check if msm needs to provide the clock to the interface */ if (!mi2s_intf_conf[index].msm_is_mi2s_master) { if (!intf_conf->msm_is_mi2s_master) { mi2s_clk[index].clk_id = mi2s_ebit_clk[index]; fmt = SND_SOC_DAIFMT_CBM_CFM; } Loading @@ -4774,21 +4900,21 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) __func__, index, ret); goto clk_off; } if (index == QUAT_MI2S) { pinctrl_info = &pdata->pinctrl_info[index]; ret_pinctrl = msm_set_pinctrl(pinctrl_info, STATE_MI2S_ACTIVE); STATE_ACTIVE); if (ret_pinctrl) pr_err("%s: MI2S TLMM pinctrl set failed with %d\n", __func__, ret_pinctrl); } } clk_off: if (ret < 0) msm_mi2s_set_sclk(substream, false); clean_up: if (ret < 0) mi2s_intf_conf[index].ref_cnt--; mutex_unlock(&mi2s_intf_conf[index].lock); intf_conf->ref_cnt--; mutex_unlock(&intf_conf->lock); err: return ret; } Loading @@ -4800,7 +4926,8 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) int index = rtd->cpu_dai->id; struct snd_soc_card *card = rtd->card; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; struct msm_pinctrl_info *pinctrl_info = NULL; struct mi2s_conf *intf_conf = NULL; int ret_pinctrl = 0; pr_debug("%s(): substream = %s stream = %d\n", __func__, Loading @@ -4810,21 +4937,22 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) return; } mutex_lock(&mi2s_intf_conf[index].lock); if (--mi2s_intf_conf[index].ref_cnt == 0) { intf_conf = &pdata->mi2s_intf_conf[index]; mutex_lock(&intf_conf->lock); if (--intf_conf->ref_cnt == 0) { ret = msm_mi2s_set_sclk(substream, false); if (ret < 0) pr_err("%s:clock disable failed for MI2S (%d); ret=%d\n", __func__, index, ret); if (index == QUAT_MI2S) { pinctrl_info = &pdata->pinctrl_info[index]; ret_pinctrl = msm_set_pinctrl(pinctrl_info, STATE_DISABLE); STATE_SLEEP); if (ret_pinctrl) pr_err("%s: MI2S TLMM pinctrl set failed with %d\n", __func__, ret_pinctrl); } } mutex_unlock(&mi2s_intf_conf[index].lock); mutex_unlock(&intf_conf->lock); } static struct snd_soc_ops msm_mi2s_be_ops = { Loading Loading @@ -7087,19 +7215,22 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) /***************************************************************************** * TO BE UPDATED: Codec/Platform specific tdm slot and offset table selection *****************************************************************************/ static int msm_tdm_init(struct device *dev) static int msm_tdm_init(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); const struct of_device_id *match; int count; match = of_match_node(sa6155_asoc_machine_of_match, dev->of_node); match = of_match_node(sa6155_asoc_machine_of_match, pdev->dev.of_node); if (!match) { dev_err(dev, "%s: No DT match found for sound card\n", dev_err(&pdev->dev, "%s: No DT match found for sound card\n", __func__); return -EINVAL; } if (!strcmp(match->data, "custom_codec")) { dev_dbg(dev, "%s: custom tdm configuration\n", __func__); dev_dbg(&pdev->dev, "%s: custom tdm configuration\n", __func__); memcpy(tdm_rx_slot_offset, tdm_rx_slot_offset_custom, Loading @@ -7111,21 +7242,40 @@ static int msm_tdm_init(struct device *dev) tdm_slot_custom, sizeof(tdm_slot_custom)); } else { dev_dbg(dev, "%s: default tdm configuration\n", __func__); dev_dbg(&pdev->dev, "%s: default tdm configuration\n", __func__); } for (count = 0; count < TDM_INTERFACE_MAX; count++) { mutex_init(&pdata->tdm_intf_conf[count].lock); pdata->tdm_intf_conf[count].ref_cnt = 0; } return 0; } static void msm_tdm_deinit(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); int count; for (count = 0; count < TDM_INTERFACE_MAX; count++) { mutex_destroy(&pdata->tdm_intf_conf[count].lock); pdata->tdm_intf_conf[count].ref_cnt = 0; } } static void msm_i2s_auxpcm_init(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); int count; u32 mi2s_master_slave[MI2S_MAX]; int ret; for (count = 0; count < MI2S_MAX; count++) { mutex_init(&mi2s_intf_conf[count].lock); mi2s_intf_conf[count].ref_cnt = 0; mutex_init(&pdata->mi2s_intf_conf[count].lock); pdata->mi2s_intf_conf[count].ref_cnt = 0; } ret = of_property_read_u32_array(pdev->dev.of_node, Loading @@ -7136,20 +7286,22 @@ static void msm_i2s_auxpcm_init(struct platform_device *pdev) __func__); } else { for (count = 0; count < MI2S_MAX; count++) { mi2s_intf_conf[count].msm_is_mi2s_master = pdata->mi2s_intf_conf[count].msm_is_mi2s_master = mi2s_master_slave[count]; } } } static void msm_i2s_auxpcm_deinit(void) static void msm_i2s_auxpcm_deinit(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); int count; for (count = 0; count < MI2S_MAX; count++) { mutex_destroy(&mi2s_intf_conf[count].lock); mi2s_intf_conf[count].ref_cnt = 0; mi2s_intf_conf[count].msm_is_mi2s_master = 0; mutex_destroy(&pdata->mi2s_intf_conf[count].lock); pdata->mi2s_intf_conf[count].ref_cnt = 0; pdata->mi2s_intf_conf[count].msm_is_mi2s_master = 0; } } Loading Loading @@ -7275,7 +7427,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) card->controls = msm_snd_controls; card->num_controls = ARRAY_SIZE(msm_snd_controls); ret = msm_tdm_init(&pdev->dev); ret = msm_tdm_init(pdev); if (ret) { ret = -EPROBE_DEFER; goto err; Loading @@ -7297,7 +7449,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) pr_debug("%s: pinctrl parsing successful\n", __func__); } else { dev_dbg(&pdev->dev, "%s: Parsing pinctrl failed with %d. Cannot use Ports\n", "%s: pinctrl parsing failed with %d\n", __func__, ret); ret = 0; } Loading @@ -7318,7 +7470,8 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) static int msm_asoc_machine_remove(struct platform_device *pdev) { msm_i2s_auxpcm_deinit(); msm_i2s_auxpcm_deinit(pdev); msm_tdm_deinit(pdev); msm_release_pinctrl(pdev); return 0; Loading