diff --git a/asoc/sa8155.c b/asoc/sa8155.c index e01b2315d514..88fc7166ee30 100644 --- a/asoc/sa8155.c +++ b/asoc/sa8155.c @@ -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;