|
@@ -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,
|
|
@@ -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 */
|
|
@@ -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)
|
|
@@ -3735,7 +3742,6 @@ err:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-#ifdef ENABLE_PINCTRL
|
|
|
static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info,
|
|
|
enum pinctrl_pin_state new_state)
|
|
|
{
|
|
@@ -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;
|
|
|
}
|
|
@@ -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);
|
|
|
- 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);
|
|
|
- }
|
|
|
+ pinctrl_info->sleep);
|
|
|
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;
|
|
|
}
|
|
|
|
|
@@ -3820,11 +3811,17 @@ 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;
|
|
|
|
|
|
- if (pinctrl_info->pinctrl) {
|
|
|
- devm_pinctrl_put(pinctrl_info->pinctrl);
|
|
|
- pinctrl_info->pinctrl = NULL;
|
|
|
+ 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;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3833,84 +3830,172 @@ 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;
|
|
|
+ }
|
|
|
|
|
|
- if (pinctrl_info == NULL) {
|
|
|
- pr_err("%s: pinctrl_info is NULL\n", __func__);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
+ pdev_np = of_find_device_by_node(np);
|
|
|
+ if (!pdev_np) {
|
|
|
+ pr_err("%s: platform device not found\n", __func__);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- pinctrl = devm_pinctrl_get(&pdev->dev);
|
|
|
- if (IS_ERR_OR_NULL(pinctrl)) {
|
|
|
- pr_err("%s: Unable to get pinctrl handle\n", __func__);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- pinctrl_info->pinctrl = pinctrl;
|
|
|
+ pinctrl_info = &pdata->pinctrl_info[i];
|
|
|
+ if (pinctrl_info == NULL) {
|
|
|
+ pr_err("%s: pinctrl info is null\n", __func__);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- /* 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__);
|
|
|
- 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",
|
|
|
- __func__);
|
|
|
- goto err;
|
|
|
- }
|
|
|
- /* Reset the TLMM pins to a default state */
|
|
|
- ret = pinctrl_select_state(pinctrl_info->pinctrl,
|
|
|
- pinctrl_info->mi2s_disable);
|
|
|
- if (ret != 0) {
|
|
|
- pr_err("%s: Disable TLMM pins failed with %d\n",
|
|
|
- __func__, ret);
|
|
|
- ret = -EIO;
|
|
|
- goto err;
|
|
|
- }
|
|
|
- pinctrl_info->curr_state = STATE_DISABLE;
|
|
|
+ pinctrl = devm_pinctrl_get(&pdev_np->dev);
|
|
|
+ if (IS_ERR_OR_NULL(pinctrl)) {
|
|
|
+ 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->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->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 sleep state */
|
|
|
+ ret = pinctrl_select_state(pinctrl_info->pinctrl,
|
|
|
+ pinctrl_info->sleep);
|
|
|
+ if (ret != 0) {
|
|
|
+ pr_err("%s: set pin state to sleep failed with %d\n",
|
|
|
+ __func__, ret);
|
|
|
+ ret = -EIO;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+ pinctrl_info->curr_state = STATE_SLEEP;
|
|
|
+ }
|
|
|
return 0;
|
|
|
|
|
|
err:
|
|
|
- devm_pinctrl_put(pinctrl);
|
|
|
- pinctrl_info->pinctrl = NULL;
|
|
|
+ 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)
|
|
|
+static int msm_tdm_get_intf_idx(u16 id)
|
|
|
{
|
|
|
- return;
|
|
|
-}
|
|
|
-
|
|
|
-static int msm_get_pinctrl(struct platform_device *pdev)
|
|
|
-{
|
|
|
- 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)
|
|
@@ -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;
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
|
|
|
- /* 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)
|
|
|
+ /*
|
|
|
+ * 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 = {
|
|
@@ -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,
|
|
@@ -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;
|
|
|
}
|
|
@@ -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) {
|
|
|
- ret_pinctrl = msm_set_pinctrl(pinctrl_info,
|
|
|
- STATE_MI2S_ACTIVE);
|
|
|
- if (ret_pinctrl)
|
|
|
- pr_err("%s: MI2S TLMM pinctrl set failed with %d\n",
|
|
|
- __func__, ret_pinctrl);
|
|
|
- }
|
|
|
+
|
|
|
+ pinctrl_info = &pdata->pinctrl_info[index];
|
|
|
+ ret_pinctrl = msm_set_pinctrl(pinctrl_info,
|
|
|
+ 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;
|
|
|
}
|
|
@@ -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__,
|
|
@@ -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) {
|
|
|
- ret_pinctrl = msm_set_pinctrl(pinctrl_info,
|
|
|
- STATE_DISABLE);
|
|
|
- if (ret_pinctrl)
|
|
|
- pr_err("%s: MI2S TLMM pinctrl set failed with %d\n",
|
|
|
- __func__, ret_pinctrl);
|
|
|
- }
|
|
|
+
|
|
|
+ pinctrl_info = &pdata->pinctrl_info[index];
|
|
|
+ ret_pinctrl = msm_set_pinctrl(pinctrl_info,
|
|
|
+ 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 = {
|
|
@@ -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,
|
|
@@ -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,
|
|
@@ -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;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -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;
|
|
@@ -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;
|
|
|
}
|
|
@@ -7318,7 +7470,8 @@ err:
|
|
|
|
|
|
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;
|