ASoC: msm: enable tdm pinctrl config on 8155 machine

Enable dynamic TDM pinctrl configuration based
on CPU DAI activity on auto 8155 machine drv.

Change-Id: I31ada624f043653018624cdae0542c76dcc1a9a1
Signed-off-by: Derek Chen <chenche@codeaurora.org>
This commit is contained in:
Derek Chen 2019-06-19 13:57:19 -07:00 committed by Gerrit - the friendly Code Review server
parent ac2cc5456a
commit 6208d04bd4

View File

@ -119,26 +119,24 @@ enum {
};
enum pinctrl_pin_state {
STATE_DISABLE = 0, /* All pins are in sleep state */
STATE_MI2S_ACTIVE, /* IS2 = active, TDM = sleep */
STATE_TDM_ACTIVE, /* IS2 = 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,
@ -166,6 +164,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 */
@ -610,7 +613,7 @@ static char const *usb_sample_rate_text[] = {"KHZ_8", "KHZ_11P025",
"KHZ_192", "KHZ_352P8", "KHZ_384"};
static char const *ext_disp_sample_rate_text[] = {"KHZ_48", "KHZ_96",
"KHZ_192", "KHZ_32", "KHZ_44P1",
"KHZ_88P2", "KHZ_176P4" };
"KHZ_88P2", "KHZ_176P4"};
static char const *tdm_ch_text[] = {
"One", "Two", "Three", "Four",
"Five", "Six", "Seven", "Eight",
@ -737,7 +740,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)
@ -1099,13 +1106,13 @@ static int usb_audio_tx_format_put(struct snd_kcontrol *kcontrol,
static int ext_disp_get_port_idx(struct snd_kcontrol *kcontrol)
{
int idx;
int idx = 0;
if (strnstr(kcontrol->id.name, "Display Port RX",
sizeof("Display Port RX"))) {
idx = DP_RX_IDX;
} else {
pr_err("%s: unsupported BE: %s",
pr_err("%s: unsupported BE: %s\n",
__func__, kcontrol->id.name);
idx = -EINVAL;
}
@ -1384,7 +1391,7 @@ static int tdm_get_sample_rate_val(int sample_rate)
static int aux_pcm_get_sample_rate_val(int sample_rate)
{
int sample_rate_val;
int sample_rate_val = 0;
switch (sample_rate) {
case SAMPLING_RATE_16KHZ:
@ -1400,7 +1407,7 @@ static int aux_pcm_get_sample_rate_val(int sample_rate)
static int tdm_get_mode(struct snd_kcontrol *kcontrol)
{
int mode;
int mode = -EINVAL;
if (strnstr(kcontrol->id.name, "PRI",
sizeof(kcontrol->id.name))) {
@ -1428,7 +1435,7 @@ static int tdm_get_mode(struct snd_kcontrol *kcontrol)
static int tdm_get_channel(struct snd_kcontrol *kcontrol)
{
int channel;
int channel = -EINVAL;
if (strnstr(kcontrol->id.name, "RX_0",
sizeof(kcontrol->id.name)) ||
@ -1502,7 +1509,7 @@ static int tdm_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
ucontrol->value.enumerated.item[0] = tdm_get_sample_rate_val(
@ -1522,7 +1529,7 @@ static int tdm_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
tdm_rx_cfg[port.mode][port.channel].sample_rate =
@ -1562,7 +1569,7 @@ static int tdm_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
tdm_tx_cfg[port.mode][port.channel].sample_rate =
@ -1624,7 +1631,7 @@ static int tdm_rx_format_get(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
ucontrol->value.enumerated.item[0] = tdm_get_format_val(
@ -1644,7 +1651,7 @@ static int tdm_rx_format_put(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
tdm_rx_cfg[port.mode][port.channel].bit_format =
@ -1664,7 +1671,7 @@ static int tdm_tx_format_get(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
ucontrol->value.enumerated.item[0] = tdm_get_format_val(
@ -1684,7 +1691,7 @@ static int tdm_tx_format_put(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
tdm_tx_cfg[port.mode][port.channel].bit_format =
@ -1704,7 +1711,7 @@ static int tdm_rx_ch_get(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
@ -1725,7 +1732,7 @@ static int tdm_rx_ch_put(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
tdm_rx_cfg[port.mode][port.channel].channels =
@ -1745,7 +1752,7 @@ static int tdm_tx_ch_get(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
ucontrol->value.enumerated.item[0] =
@ -1765,7 +1772,7 @@ static int tdm_tx_ch_put(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
tdm_tx_cfg[port.mode][port.channel].channels =
@ -1780,7 +1787,7 @@ static int tdm_tx_ch_put(struct snd_kcontrol *kcontrol,
static int tdm_get_slot_num_val(int slot_num)
{
int slot_num_val;
int slot_num_val = 0;
switch (slot_num) {
case 1:
@ -1814,7 +1821,7 @@ static int tdm_slot_num_get(struct snd_kcontrol *kcontrol,
int mode = tdm_get_mode(kcontrol);
if (mode < 0) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
return mode;
}
@ -1831,7 +1838,7 @@ static int tdm_slot_num_get(struct snd_kcontrol *kcontrol,
static int tdm_get_slot_num(int value)
{
int slot_num;
int slot_num = 0;
switch (value) {
case 0:
@ -1865,7 +1872,7 @@ static int tdm_slot_num_put(struct snd_kcontrol *kcontrol,
int mode = tdm_get_mode(kcontrol);
if (mode < 0) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
return mode;
}
@ -1882,7 +1889,7 @@ static int tdm_slot_num_put(struct snd_kcontrol *kcontrol,
static int tdm_get_slot_width_val(int slot_width)
{
int slot_width_val;
int slot_width_val = 2;
switch (slot_width) {
case 16:
@ -1907,7 +1914,7 @@ static int tdm_slot_width_get(struct snd_kcontrol *kcontrol,
int mode = tdm_get_mode(kcontrol);
if (mode < 0) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
return mode;
}
@ -1924,7 +1931,7 @@ static int tdm_slot_width_get(struct snd_kcontrol *kcontrol,
static int tdm_get_slot_width(int value)
{
int slot_width;
int slot_width = 32;
switch (value) {
case 0:
@ -1949,7 +1956,7 @@ static int tdm_slot_width_put(struct snd_kcontrol *kcontrol,
int mode = tdm_get_mode(kcontrol);
if (mode < 0) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
return mode;
}
@ -1973,7 +1980,7 @@ static int tdm_rx_slot_mapping_get(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
slot_offset = tdm_rx_slot_offset[port.mode][port.channel];
@ -1997,7 +2004,7 @@ static int tdm_rx_slot_mapping_put(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
slot_offset = tdm_rx_slot_offset[port.mode][port.channel];
@ -2021,7 +2028,7 @@ static int tdm_tx_slot_mapping_get(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
slot_offset = tdm_tx_slot_offset[port.mode][port.channel];
@ -2045,7 +2052,7 @@ static int tdm_tx_slot_mapping_put(struct snd_kcontrol *kcontrol,
int ret = tdm_get_port_idx(kcontrol, &port);
if (ret) {
pr_err("%s: unsupported control: %s",
pr_err("%s: unsupported control: %s\n",
__func__, kcontrol->id.name);
} else {
slot_offset = tdm_tx_slot_offset[port.mode][port.channel];
@ -2080,7 +2087,7 @@ static int aux_pcm_get_port_idx(struct snd_kcontrol *kcontrol)
sizeof("QUIN_AUX_PCM")))
idx = QUIN_AUX_PCM;
else {
pr_err("%s: unsupported port: %s",
pr_err("%s: unsupported port: %s\n",
__func__, kcontrol->id.name);
idx = -EINVAL;
}
@ -2195,7 +2202,7 @@ static int mi2s_get_port_idx(struct snd_kcontrol *kcontrol)
sizeof("QUIN_MI2S_TX")))
idx = QUIN_MI2S;
else {
pr_err("%s: unsupported channel: %s",
pr_err("%s: unsupported channel: %s\n",
__func__, kcontrol->id.name);
idx = -EINVAL;
}
@ -3729,7 +3736,6 @@ err:
return ret;
}
#ifdef ENABLE_PINCTRL
static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info,
enum pinctrl_pin_state new_state)
{
@ -3737,13 +3743,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;
}
@ -3754,55 +3760,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;
}
@ -3814,11 +3805,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;
}
}
}
@ -3827,85 +3824,173 @@ 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;
int ret;
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;
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;
}
}
static int msm_get_pinctrl(struct platform_device *pdev)
{
return 0;
}
#endif
static int msm_tdm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@ -4640,10 +4725,9 @@ static int sa8155_tdm_snd_hw_params(struct snd_pcm_substream *substream,
rate = params_rate(params);
clk_freq = rate * slot_width * slots;
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, clk_freq, SND_SOC_CLOCK_OUT);
if (ret < 0) {
if (ret < 0)
pr_err("%s: failed to set tdm clk, err:%d\n",
__func__, ret);
}
end:
return ret;
@ -4656,37 +4740,76 @@ static int sa8155_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_err("%s: TDM TLMM pinctrl set failed with %d\n",
__func__, 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_pinctrl);
}
mutex_unlock(&intf_conf->lock);
err:
return ret;
}
static void sa8155_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_err("%s: TDM TLMM pinctrl set failed with %d\n",
__func__, 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_pinctrl);
}
mutex_unlock(&intf_conf->lock);
}
static struct snd_soc_ops sa8155_tdm_be_ops = {
@ -4728,7 +4851,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,
@ -4748,10 +4872,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;
}
@ -4769,21 +4894,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;
}
@ -4795,7 +4920,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__,
@ -4805,21 +4931,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 = {
@ -7053,19 +7180,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(sa8155_asoc_machine_of_match, dev->of_node);
match = of_match_node(sa8155_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,
@ -7077,21 +7207,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,
@ -7102,20 +7251,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;
}
}
static int msm_asoc_machine_probe(struct platform_device *pdev)
@ -7169,7 +7320,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;
@ -7192,7 +7343,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;
}
@ -7208,7 +7359,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;