diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c index 1e97a0cd76ac..1c1f65fb3f5c 100644 --- a/sound/soc/msm/msm8998.c +++ b/sound/soc/msm/msm8998.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -72,8 +72,8 @@ #define WCN_CDC_SLIM_RX_CH_MAX 2 #define WCN_CDC_SLIM_TX_CH_MAX 3 -#define TDM_CHANNEL_MAX 8 -#define TDM_SLOT_OFFSET_MAX 8 +#define TDM_CHANNEL_MAX 16 +#define TDM_SLOT_OFFSET_MAX 32 #define MSM_HIFI_ON 1 @@ -396,6 +396,117 @@ static struct dev_config aux_pcm_tx_cfg[] = { [QUAT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, }; +/* TDM default slot config */ +struct tdm_slot_cfg { + u32 width; + u32 num; +}; + +static struct tdm_slot_cfg tdm_slot[TDM_INTERFACE_MAX] = { + /* PRI TDM */ + {32, 8}, + /* SEC TDM */ + {32, 8}, + /* TERT TDM */ + {32, 8}, + /* QUAT TDM */ + {32, 8} +}; + +static unsigned int tdm_rx_slot_offset + [TDM_INTERFACE_MAX][TDM_PORT_MAX][TDM_SLOT_OFFSET_MAX] = { + {/* PRI TDM */ + {0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, 0xFFFF}, + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + }, + {/* SEC TDM */ + {0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, 0xFFFF}, + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + }, + {/* TERT TDM */ + {0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, 0xFFFF}, + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + }, + {/* QUAT TDM */ + {0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, 0xFFFF}, + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + } +}; + +static unsigned int tdm_tx_slot_offset + [TDM_INTERFACE_MAX][TDM_PORT_MAX][TDM_SLOT_OFFSET_MAX] = { + {/* PRI TDM */ + {0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, 0xFFFF}, + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + }, + {/* SEC TDM */ + {0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, 0xFFFF}, + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + }, + {/* TERT TDM */ + {0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, 0xFFFF}, + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + }, + {/* QUAT TDM */ + {0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, 0xFFFF},/*MIC ARR*/ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + {0xFFFF}, /* not used */ + } +}; static int msm_vi_feed_tx_ch = 2; static const char *const slim_rx_ch_text[] = {"One", "Two", "Three", "Four", "Five", "Six", "Seven", @@ -428,11 +539,17 @@ static char const *ext_disp_sample_rate_text[] = {"KHZ_48", "KHZ_96", "KHZ_192", "KHZ_32", "KHZ_44P1", "KHZ_88P2", "KHZ_176P4"}; static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four", - "Five", "Six", "Seven", "Eight"}; + "Five", "Six", "Seven", "Eight", + "Nine", "Ten", "Eleven", "Twelve", + "Thirteen", "Fourteen", "Fifteen", + "Sixteen"}; static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S32_LE"}; static char const *tdm_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_32", "KHZ_44P1", "KHZ_48", "KHZ_96", "KHZ_192", "KHZ_352P8", "KHZ_384"}; +static const char *const tdm_slot_num_text[] = {"One", "Two", "Four", + "Eight", "Sixteen", "ThirtyTwo"}; +static const char *const tdm_slot_width_text[] = {"16", "24", "32"}; static const char *const auxpcm_rate_text[] = {"KHZ_8", "KHZ_16"}; static char const *mi2s_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_32", "KHZ_44P1", "KHZ_48", @@ -479,6 +596,8 @@ static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_sample_rate, tdm_sample_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_chs, tdm_ch_text); static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_format, tdm_bit_format_text); static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_sample_rate, tdm_sample_rate_text); +static SOC_ENUM_SINGLE_EXT_DECL(tdm_slot_num, tdm_slot_num_text); +static SOC_ENUM_SINGLE_EXT_DECL(tdm_slot_width, tdm_slot_width_text); static SOC_ENUM_SINGLE_EXT_DECL(prim_aux_pcm_rx_sample_rate, auxpcm_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(sec_aux_pcm_rx_sample_rate, auxpcm_rate_text); static SOC_ENUM_SINGLE_EXT_DECL(tert_aux_pcm_rx_sample_rate, auxpcm_rate_text); @@ -1812,73 +1931,95 @@ static int aux_pcm_get_sample_rate_val(int sample_rate) return sample_rate_val; } +static int tdm_get_mode(struct snd_kcontrol *kcontrol) +{ + int mode; + + if (strnstr(kcontrol->id.name, "PRI", + sizeof(kcontrol->id.name))) { + mode = TDM_PRI; + } else if (strnstr(kcontrol->id.name, "SEC", + sizeof(kcontrol->id.name))) { + mode = TDM_SEC; + } else if (strnstr(kcontrol->id.name, "TERT", + sizeof(kcontrol->id.name))) { + mode = TDM_TERT; + } else if (strnstr(kcontrol->id.name, "QUAT", + sizeof(kcontrol->id.name))) { + mode = TDM_QUAT; + } else { + pr_err("%s: unsupported mode in: %s", + __func__, kcontrol->id.name); + mode = -EINVAL; + } + + return mode; +} + +static int tdm_get_channel(struct snd_kcontrol *kcontrol) +{ + int channel; + + if (strnstr(kcontrol->id.name, "RX_0", + sizeof(kcontrol->id.name)) || + strnstr(kcontrol->id.name, "TX_0", + sizeof(kcontrol->id.name))) { + channel = TDM_0; + } else if (strnstr(kcontrol->id.name, "RX_1", + sizeof(kcontrol->id.name)) || + strnstr(kcontrol->id.name, "TX_1", + sizeof(kcontrol->id.name))) { + channel = TDM_1; + } else if (strnstr(kcontrol->id.name, "RX_2", + sizeof(kcontrol->id.name)) || + strnstr(kcontrol->id.name, "TX_2", + sizeof(kcontrol->id.name))) { + channel = TDM_2; + } else if (strnstr(kcontrol->id.name, "RX_3", + sizeof(kcontrol->id.name)) || + strnstr(kcontrol->id.name, "TX_3", + sizeof(kcontrol->id.name))) { + channel = TDM_3; + } else if (strnstr(kcontrol->id.name, "RX_4", + sizeof(kcontrol->id.name)) || + strnstr(kcontrol->id.name, "TX_4", + sizeof(kcontrol->id.name))) { + channel = TDM_4; + } else if (strnstr(kcontrol->id.name, "RX_5", + sizeof(kcontrol->id.name)) || + strnstr(kcontrol->id.name, "TX_5", + sizeof(kcontrol->id.name))) { + channel = TDM_5; + } else if (strnstr(kcontrol->id.name, "RX_6", + sizeof(kcontrol->id.name)) || + strnstr(kcontrol->id.name, "TX_6", + sizeof(kcontrol->id.name))) { + channel = TDM_6; + } else if (strnstr(kcontrol->id.name, "RX_7", + sizeof(kcontrol->id.name)) || + strnstr(kcontrol->id.name, "TX_7", + sizeof(kcontrol->id.name))) { + channel = TDM_7; + } else { + pr_err("%s: unsupported channel in: %s", + __func__, kcontrol->id.name); + channel = -EINVAL; + } + + return channel; +} + static int tdm_get_port_idx(struct snd_kcontrol *kcontrol, struct tdm_port *port) { if (port) { - if (strnstr(kcontrol->id.name, "PRI", - sizeof(kcontrol->id.name))) { - port->mode = TDM_PRI; - } else if (strnstr(kcontrol->id.name, "SEC", - sizeof(kcontrol->id.name))) { - port->mode = TDM_SEC; - } else if (strnstr(kcontrol->id.name, "TERT", - sizeof(kcontrol->id.name))) { - port->mode = TDM_TERT; - } else if (strnstr(kcontrol->id.name, "QUAT", - sizeof(kcontrol->id.name))) { - port->mode = TDM_QUAT; - } else { - pr_err("%s: unsupported mode in: %s", - __func__, kcontrol->id.name); - return -EINVAL; - } + port->mode = tdm_get_mode(kcontrol); + if (port->mode < 0) + return port->mode; - if (strnstr(kcontrol->id.name, "RX_0", - sizeof(kcontrol->id.name)) || - strnstr(kcontrol->id.name, "TX_0", - sizeof(kcontrol->id.name))) { - port->channel = TDM_0; - } else if (strnstr(kcontrol->id.name, "RX_1", - sizeof(kcontrol->id.name)) || - strnstr(kcontrol->id.name, "TX_1", - sizeof(kcontrol->id.name))) { - port->channel = TDM_1; - } else if (strnstr(kcontrol->id.name, "RX_2", - sizeof(kcontrol->id.name)) || - strnstr(kcontrol->id.name, "TX_2", - sizeof(kcontrol->id.name))) { - port->channel = TDM_2; - } else if (strnstr(kcontrol->id.name, "RX_3", - sizeof(kcontrol->id.name)) || - strnstr(kcontrol->id.name, "TX_3", - sizeof(kcontrol->id.name))) { - port->channel = TDM_3; - } else if (strnstr(kcontrol->id.name, "RX_4", - sizeof(kcontrol->id.name)) || - strnstr(kcontrol->id.name, "TX_4", - sizeof(kcontrol->id.name))) { - port->channel = TDM_4; - } else if (strnstr(kcontrol->id.name, "RX_5", - sizeof(kcontrol->id.name)) || - strnstr(kcontrol->id.name, "TX_5", - sizeof(kcontrol->id.name))) { - port->channel = TDM_5; - } else if (strnstr(kcontrol->id.name, "RX_6", - sizeof(kcontrol->id.name)) || - strnstr(kcontrol->id.name, "TX_6", - sizeof(kcontrol->id.name))) { - port->channel = TDM_6; - } else if (strnstr(kcontrol->id.name, "RX_7", - sizeof(kcontrol->id.name)) || - strnstr(kcontrol->id.name, "TX_7", - sizeof(kcontrol->id.name))) { - port->channel = TDM_7; - } else { - pr_err("%s: unsupported channel in: %s", - __func__, kcontrol->id.name); - return -EINVAL; - } + port->channel = tdm_get_channel(kcontrol); + if (port->channel < 0) + return port->channel; } else return -EINVAL; return 0; @@ -2167,6 +2308,316 @@ static int tdm_tx_ch_put(struct snd_kcontrol *kcontrol, return ret; } +static int tdm_get_slot_num_val(int slot_num) +{ + int slot_num_val; + + switch (slot_num) { + case 1: + slot_num_val = 0; + break; + case 2: + slot_num_val = 1; + break; + case 4: + slot_num_val = 2; + break; + case 8: + slot_num_val = 3; + break; + case 16: + slot_num_val = 4; + break; + case 32: + slot_num_val = 5; + break; + default: + slot_num_val = 5; + break; + } + return slot_num_val; +} + +static int tdm_slot_num_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int mode = tdm_get_mode(kcontrol); + + if (mode < 0) { + pr_err("%s: unsupported control: %s", + __func__, kcontrol->id.name); + return mode; + } + + ucontrol->value.enumerated.item[0] = + tdm_get_slot_num_val(tdm_slot[mode].num); + + pr_debug("%s: mode = %d, tdm_slot_num = %d, item = %d\n", __func__, + mode, tdm_slot[mode].num, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int tdm_get_slot_num(int value) +{ + int slot_num; + + switch (value) { + case 0: + slot_num = 1; + break; + case 1: + slot_num = 2; + break; + case 2: + slot_num = 4; + break; + case 3: + slot_num = 8; + break; + case 4: + slot_num = 16; + break; + case 5: + slot_num = 32; + break; + default: + slot_num = 8; + break; + } + return slot_num; +} + +static int tdm_slot_num_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int mode = tdm_get_mode(kcontrol); + + if (mode < 0) { + pr_err("%s: unsupported control: %s", + __func__, kcontrol->id.name); + return mode; + } + + tdm_slot[mode].num = + tdm_get_slot_num(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: mode = %d, tdm_slot_num = %d, item = %d\n", __func__, + mode, tdm_slot[mode].num, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int tdm_get_slot_width_val(int slot_width) +{ + int slot_width_val; + + switch (slot_width) { + case 16: + slot_width_val = 0; + break; + case 24: + slot_width_val = 1; + break; + case 32: + slot_width_val = 2; + break; + default: + slot_width_val = 2; + break; + } + return slot_width_val; +} + +static int tdm_slot_width_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int mode = tdm_get_mode(kcontrol); + + if (mode < 0) { + pr_err("%s: unsupported control: %s", + __func__, kcontrol->id.name); + return mode; + } + + ucontrol->value.enumerated.item[0] = + tdm_get_slot_width_val(tdm_slot[mode].width); + + pr_debug("%s: mode = %d, tdm_slot_width = %d, item = %d\n", __func__, + mode, tdm_slot[mode].width, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int tdm_get_slot_width(int value) +{ + int slot_width; + + switch (value) { + case 0: + slot_width = 16; + break; + case 1: + slot_width = 24; + break; + case 2: + slot_width = 32; + break; + default: + slot_width = 32; + break; + } + return slot_width; +} + +static int tdm_slot_width_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int mode = tdm_get_mode(kcontrol); + + if (mode < 0) { + pr_err("%s: unsupported control: %s", + __func__, kcontrol->id.name); + return mode; + } + + tdm_slot[mode].width = + tdm_get_slot_width(ucontrol->value.enumerated.item[0]); + + pr_debug("%s: mode = %d, tdm_slot_width = %d, item = %d\n", __func__, + mode, tdm_slot[mode].width, + ucontrol->value.enumerated.item[0]); + + return 0; +} + +static int tdm_rx_slot_mapping_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int *slot_offset; + int i; + struct tdm_port port; + int ret = tdm_get_port_idx(kcontrol, &port); + + if (ret) { + pr_err("%s: unsupported control: %s", + __func__, kcontrol->id.name); + } else { + if (port.mode < TDM_INTERFACE_MAX && + port.channel < TDM_PORT_MAX) { + slot_offset = + tdm_rx_slot_offset[port.mode][port.channel]; + pr_debug("%s: mode = %d, channel = %d\n", + __func__, port.mode, port.channel); + for (i = 0; i < TDM_SLOT_OFFSET_MAX; i++) { + ucontrol->value.integer.value[i] = + slot_offset[i]; + pr_debug("%s: offset %d, value %d\n", + __func__, i, slot_offset[i]); + } + } else { + pr_err("%s: unsupported mode/channel", __func__); + } + } + return ret; +} + +static int tdm_rx_slot_mapping_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int *slot_offset; + int i; + struct tdm_port port; + int ret = tdm_get_port_idx(kcontrol, &port); + + if (ret) { + pr_err("%s: unsupported control: %s", + __func__, kcontrol->id.name); + } else { + if (port.mode < TDM_INTERFACE_MAX && + port.channel < TDM_PORT_MAX) { + slot_offset = + tdm_rx_slot_offset[port.mode][port.channel]; + pr_debug("%s: mode = %d, channel = %d\n", + __func__, port.mode, port.channel); + for (i = 0; i < TDM_SLOT_OFFSET_MAX; i++) { + slot_offset[i] = + ucontrol->value.integer.value[i]; + pr_debug("%s: offset %d, value %d\n", + __func__, i, slot_offset[i]); + } + } else { + pr_err("%s: unsupported mode/channel", __func__); + } + } + return ret; +} + +static int tdm_tx_slot_mapping_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int *slot_offset; + int i; + struct tdm_port port; + int ret = tdm_get_port_idx(kcontrol, &port); + + if (ret) { + pr_err("%s: unsupported control: %s", + __func__, kcontrol->id.name); + } else { + if (port.mode < TDM_INTERFACE_MAX && + port.channel < TDM_PORT_MAX) { + slot_offset = + tdm_tx_slot_offset[port.mode][port.channel]; + pr_debug("%s: mode = %d, channel = %d\n", + __func__, port.mode, port.channel); + for (i = 0; i < TDM_SLOT_OFFSET_MAX; i++) { + ucontrol->value.integer.value[i] = + slot_offset[i]; + pr_debug("%s: offset %d, value %d\n", + __func__, i, slot_offset[i]); + } + } else { + pr_err("%s: unsupported mode/channel", __func__); + } + } + return ret; +} + +static int tdm_tx_slot_mapping_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned int *slot_offset; + int i; + struct tdm_port port; + int ret = tdm_get_port_idx(kcontrol, &port); + + if (ret) { + pr_err("%s: unsupported control: %s", + __func__, kcontrol->id.name); + } else { + if (port.mode < TDM_INTERFACE_MAX && + port.channel < TDM_PORT_MAX) { + slot_offset = + tdm_tx_slot_offset[port.mode][port.channel]; + pr_debug("%s: mode = %d, channel = %d\n", + __func__, port.mode, port.channel); + for (i = 0; i < TDM_SLOT_OFFSET_MAX; i++) { + slot_offset[i] = + ucontrol->value.integer.value[i]; + pr_debug("%s: offset %d, value %d\n", + __func__, i, slot_offset[i]); + } + } else { + pr_err("%s: unsupported mode/channel", __func__); + } + } + return ret; +} + static int aux_pcm_get_port_idx(struct snd_kcontrol *kcontrol) { int idx; @@ -2825,6 +3276,214 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { SOC_ENUM_EXT("QUAT_TDM_TX_0 Channels", tdm_tx_chs, tdm_tx_ch_get, tdm_tx_ch_put), + SOC_ENUM_EXT("PRI_TDM SlotNumber", tdm_slot_num, + tdm_slot_num_get, tdm_slot_num_put), + SOC_ENUM_EXT("PRI_TDM SlotWidth", tdm_slot_width, + tdm_slot_width_get, tdm_slot_width_put), + SOC_ENUM_EXT("SEC_TDM SlotNumber", tdm_slot_num, + tdm_slot_num_get, tdm_slot_num_put), + SOC_ENUM_EXT("SEC_TDM SlotWidth", tdm_slot_width, + tdm_slot_width_get, tdm_slot_width_put), + SOC_ENUM_EXT("TERT_TDM SlotNumber", tdm_slot_num, + tdm_slot_num_get, tdm_slot_num_put), + SOC_ENUM_EXT("TERT_TDM SlotWidth", tdm_slot_width, + tdm_slot_width_get, tdm_slot_width_put), + SOC_ENUM_EXT("QUAT_TDM SlotNumber", tdm_slot_num, + tdm_slot_num_get, tdm_slot_num_put), + SOC_ENUM_EXT("QUAT_TDM SlotWidth", tdm_slot_width, + tdm_slot_width_get, tdm_slot_width_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_RX_0 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_RX_1 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_RX_2 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_RX_3 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_RX_4 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_RX_5 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_RX_6 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_RX_7 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_TX_0 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_TX_1 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_TX_2 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_TX_3 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_TX_4 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_TX_5 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_TX_6 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("PRI_TDM_TX_7 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_RX_0 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_RX_1 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_RX_2 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_RX_3 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_RX_4 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_RX_5 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_RX_6 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_RX_7 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_TX_0 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_TX_1 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_TX_2 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_TX_3 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_TX_4 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_TX_5 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_TX_6 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("SEC_TDM_TX_7 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_RX_0 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_RX_1 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_RX_2 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_RX_3 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_RX_4 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_RX_5 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_RX_6 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_RX_7 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_TX_0 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_TX_1 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_TX_2 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_TX_3 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_TX_4 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_TX_5 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_TX_6 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("TERT_TDM_TX_7 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_RX_0 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_RX_1 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_RX_2 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_RX_3 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_RX_4 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_RX_5 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_RX_6 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_RX_7 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_rx_slot_mapping_get, tdm_rx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_TX_0 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_TX_1 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_TX_2 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_TX_3 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_TX_4 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_TX_5 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_TX_6 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), + SOC_SINGLE_MULTI_EXT("QUAT_TDM_TX_7 SlotMapping", + SND_SOC_NOPM, 0, 0xFFFF, 0, TDM_SLOT_OFFSET_MAX, + tdm_tx_slot_mapping_get, tdm_tx_slot_mapping_put), SOC_ENUM_EXT("PRIM_AUX_PCM_RX SampleRate", prim_aux_pcm_rx_sample_rate, aux_pcm_rx_sample_rate_get, aux_pcm_rx_sample_rate_put), @@ -4478,21 +5137,520 @@ static int msm_tdm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - - if (cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_RX) { + switch (cpu_dai->id) { + case AFE_PORT_ID_PRIMARY_TDM_RX: + channels->min = channels->max = + tdm_rx_cfg[TDM_PRI][TDM_0].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_PRI][TDM_0].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_PRI][TDM_0].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_1: + channels->min = channels->max = + tdm_rx_cfg[TDM_PRI][TDM_1].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_PRI][TDM_1].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_PRI][TDM_1].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_2: + channels->min = channels->max = + tdm_rx_cfg[TDM_PRI][TDM_2].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_PRI][TDM_2].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_PRI][TDM_2].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_3: + channels->min = channels->max = + tdm_rx_cfg[TDM_PRI][TDM_3].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_PRI][TDM_3].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_PRI][TDM_3].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_4: + channels->min = channels->max = + tdm_rx_cfg[TDM_PRI][TDM_4].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_PRI][TDM_4].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_PRI][TDM_4].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_5: + channels->min = channels->max = + tdm_rx_cfg[TDM_PRI][TDM_5].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_PRI][TDM_5].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_PRI][TDM_5].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_6: + channels->min = channels->max = + tdm_rx_cfg[TDM_PRI][TDM_6].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_PRI][TDM_6].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_PRI][TDM_6].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_7: + channels->min = channels->max = + tdm_rx_cfg[TDM_PRI][TDM_7].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_PRI][TDM_7].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_PRI][TDM_7].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX: + channels->min = channels->max = + tdm_tx_cfg[TDM_PRI][TDM_0].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_PRI][TDM_0].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_PRI][TDM_0].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_1: + channels->min = channels->max = + tdm_tx_cfg[TDM_PRI][TDM_1].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_PRI][TDM_1].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_PRI][TDM_1].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_2: + channels->min = channels->max = + tdm_tx_cfg[TDM_PRI][TDM_2].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_PRI][TDM_2].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_PRI][TDM_2].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_3: + channels->min = channels->max = + tdm_tx_cfg[TDM_PRI][TDM_3].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_PRI][TDM_3].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_PRI][TDM_3].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_4: + channels->min = channels->max = + tdm_tx_cfg[TDM_PRI][TDM_4].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_PRI][TDM_4].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_PRI][TDM_4].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_5: + channels->min = channels->max = + tdm_tx_cfg[TDM_PRI][TDM_5].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_PRI][TDM_5].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_PRI][TDM_5].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_6: + channels->min = channels->max = + tdm_tx_cfg[TDM_PRI][TDM_6].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_PRI][TDM_6].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_PRI][TDM_6].sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_7: + channels->min = channels->max = + tdm_tx_cfg[TDM_PRI][TDM_7].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_PRI][TDM_7].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_PRI][TDM_7].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX: + channels->min = channels->max = + tdm_rx_cfg[TDM_SEC][TDM_0].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_SEC][TDM_0].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_SEC][TDM_0].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_1: + channels->min = channels->max = + tdm_rx_cfg[TDM_SEC][TDM_1].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_SEC][TDM_1].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_SEC][TDM_1].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_2: + channels->min = channels->max = + tdm_rx_cfg[TDM_SEC][TDM_2].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_SEC][TDM_2].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_SEC][TDM_2].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_3: + channels->min = channels->max = + tdm_rx_cfg[TDM_SEC][TDM_3].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_SEC][TDM_3].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_SEC][TDM_3].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_4: + channels->min = channels->max = + tdm_rx_cfg[TDM_SEC][TDM_4].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_SEC][TDM_4].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_SEC][TDM_4].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_5: + channels->min = channels->max = + tdm_rx_cfg[TDM_SEC][TDM_5].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_SEC][TDM_5].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_SEC][TDM_5].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_6: + channels->min = channels->max = + tdm_rx_cfg[TDM_SEC][TDM_6].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_SEC][TDM_6].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_SEC][TDM_6].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_7: + channels->min = channels->max = + tdm_rx_cfg[TDM_SEC][TDM_7].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_SEC][TDM_7].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_SEC][TDM_7].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX: + channels->min = channels->max = + tdm_tx_cfg[TDM_SEC][TDM_0].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_SEC][TDM_0].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_SEC][TDM_0].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_1: + channels->min = channels->max = + tdm_tx_cfg[TDM_SEC][TDM_1].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_SEC][TDM_1].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_SEC][TDM_1].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_2: + channels->min = channels->max = + tdm_tx_cfg[TDM_SEC][TDM_2].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_SEC][TDM_2].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_SEC][TDM_2].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_3: + channels->min = channels->max = + tdm_tx_cfg[TDM_SEC][TDM_3].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_SEC][TDM_3].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_SEC][TDM_3].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_4: + channels->min = channels->max = + tdm_tx_cfg[TDM_SEC][TDM_4].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_SEC][TDM_4].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_SEC][TDM_4].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_5: + channels->min = channels->max = + tdm_tx_cfg[TDM_SEC][TDM_5].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_SEC][TDM_5].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_SEC][TDM_5].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_6: + channels->min = channels->max = + tdm_tx_cfg[TDM_SEC][TDM_6].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_SEC][TDM_6].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_SEC][TDM_6].sample_rate; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_7: + channels->min = channels->max = + tdm_tx_cfg[TDM_SEC][TDM_7].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_SEC][TDM_7].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_SEC][TDM_7].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX: + channels->min = channels->max = + tdm_rx_cfg[TDM_TERT][TDM_0].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_TERT][TDM_0].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_TERT][TDM_0].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_1: + channels->min = channels->max = + tdm_rx_cfg[TDM_TERT][TDM_1].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_TERT][TDM_1].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_TERT][TDM_1].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_2: + channels->min = channels->max = + tdm_rx_cfg[TDM_TERT][TDM_2].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_TERT][TDM_2].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_TERT][TDM_2].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_3: + channels->min = channels->max = + tdm_rx_cfg[TDM_TERT][TDM_3].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_TERT][TDM_3].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_TERT][TDM_3].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_4: + channels->min = channels->max = + tdm_rx_cfg[TDM_TERT][TDM_4].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_TERT][TDM_4].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_TERT][TDM_4].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_5: + channels->min = channels->max = + tdm_rx_cfg[TDM_TERT][TDM_5].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_TERT][TDM_5].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_TERT][TDM_5].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_6: + channels->min = channels->max = + tdm_rx_cfg[TDM_TERT][TDM_6].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_TERT][TDM_6].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_TERT][TDM_6].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_7: + channels->min = channels->max = + tdm_rx_cfg[TDM_TERT][TDM_7].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_TERT][TDM_7].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_TERT][TDM_7].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX: + channels->min = channels->max = + tdm_tx_cfg[TDM_TERT][TDM_0].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_TERT][TDM_0].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_TERT][TDM_0].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_1: + channels->min = channels->max = + tdm_tx_cfg[TDM_TERT][TDM_1].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_TERT][TDM_1].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_TERT][TDM_1].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_2: + channels->min = channels->max = + tdm_tx_cfg[TDM_TERT][TDM_2].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_TERT][TDM_2].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_TERT][TDM_2].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_3: + channels->min = channels->max = + tdm_tx_cfg[TDM_TERT][TDM_3].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_TERT][TDM_3].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_TERT][TDM_3].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_4: + channels->min = channels->max = + tdm_tx_cfg[TDM_TERT][TDM_4].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_TERT][TDM_4].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_TERT][TDM_4].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_5: + channels->min = channels->max = + tdm_tx_cfg[TDM_TERT][TDM_5].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_TERT][TDM_5].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_TERT][TDM_5].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_6: + channels->min = channels->max = + tdm_tx_cfg[TDM_TERT][TDM_6].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_TERT][TDM_6].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_TERT][TDM_6].sample_rate; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_7: + channels->min = channels->max = + tdm_tx_cfg[TDM_TERT][TDM_7].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_TERT][TDM_7].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_TERT][TDM_7].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX: channels->min = channels->max = tdm_rx_cfg[TDM_QUAT][TDM_0].channels; param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, tdm_rx_cfg[TDM_QUAT][TDM_0].bit_format); rate->min = rate->max = tdm_rx_cfg[TDM_QUAT][TDM_0].sample_rate; - } else if (cpu_dai->id == AFE_PORT_ID_SECONDARY_TDM_RX) { + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_1: channels->min = channels->max = - tdm_rx_cfg[TDM_SEC][TDM_0].channels; + tdm_rx_cfg[TDM_QUAT][TDM_1].channels; param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, - tdm_rx_cfg[TDM_SEC][TDM_0].bit_format); - rate->min = rate->max = tdm_rx_cfg[TDM_SEC][TDM_0].sample_rate; - } else { + tdm_rx_cfg[TDM_QUAT][TDM_1].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_QUAT][TDM_1].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_2: + channels->min = channels->max = + tdm_rx_cfg[TDM_QUAT][TDM_2].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_QUAT][TDM_2].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_QUAT][TDM_2].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_3: + channels->min = channels->max = + tdm_rx_cfg[TDM_QUAT][TDM_3].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_QUAT][TDM_3].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_QUAT][TDM_3].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_4: + channels->min = channels->max = + tdm_rx_cfg[TDM_QUAT][TDM_4].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_QUAT][TDM_4].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_QUAT][TDM_4].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_5: + channels->min = channels->max = + tdm_rx_cfg[TDM_QUAT][TDM_5].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_QUAT][TDM_5].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_QUAT][TDM_5].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_6: + channels->min = channels->max = + tdm_rx_cfg[TDM_QUAT][TDM_6].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_QUAT][TDM_6].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_QUAT][TDM_6].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_7: + channels->min = channels->max = + tdm_rx_cfg[TDM_QUAT][TDM_7].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_rx_cfg[TDM_QUAT][TDM_7].bit_format); + rate->min = rate->max = + tdm_rx_cfg[TDM_QUAT][TDM_7].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX: + channels->min = channels->max = + tdm_tx_cfg[TDM_QUAT][TDM_0].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_QUAT][TDM_0].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_QUAT][TDM_0].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_1: + channels->min = channels->max = + tdm_tx_cfg[TDM_QUAT][TDM_1].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_QUAT][TDM_1].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_QUAT][TDM_1].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_2: + channels->min = channels->max = + tdm_tx_cfg[TDM_QUAT][TDM_2].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_QUAT][TDM_2].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_QUAT][TDM_2].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_3: + channels->min = channels->max = + tdm_tx_cfg[TDM_QUAT][TDM_3].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_QUAT][TDM_3].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_QUAT][TDM_3].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_4: + channels->min = channels->max = + tdm_tx_cfg[TDM_QUAT][TDM_4].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_QUAT][TDM_4].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_QUAT][TDM_4].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_5: + channels->min = channels->max = + tdm_tx_cfg[TDM_QUAT][TDM_5].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_QUAT][TDM_5].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_QUAT][TDM_5].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_6: + channels->min = channels->max = + tdm_tx_cfg[TDM_QUAT][TDM_6].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_QUAT][TDM_6].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_QUAT][TDM_6].sample_rate; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_7: + channels->min = channels->max = + tdm_tx_cfg[TDM_QUAT][TDM_7].channels; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + tdm_tx_cfg[TDM_QUAT][TDM_7].bit_format); + rate->min = rate->max = + tdm_tx_cfg[TDM_QUAT][TDM_7].sample_rate; + break; + default: pr_err("%s: dai id 0x%x not supported\n", __func__, cpu_dai->id); return -EINVAL; @@ -4505,25 +5663,411 @@ static int msm_tdm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static unsigned int tdm_param_set_slot_mask(int slots) +{ + unsigned int slot_mask = 0; + int i = 0; + + if ((slots <= 0) || (slots > 32)) { + pr_err("%s: invalid slot number %d\n", __func__, slots); + return -EINVAL; + } + + for (i = 0; i < slots ; i++) + slot_mask |= 1 << i; + + return slot_mask; +} + static int msm8998_tdm_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret = 0; - int channels, slot_width, slots; + int channels, slot_width, slots, rate, format; unsigned int slot_mask; - unsigned int slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28}; + unsigned int *slot_offset; + int offset_channels = 0; + int i; + int clk_freq; pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id); - slots = tdm_rx_cfg[TDM_QUAT][TDM_0].channels; - /*2 slot config - bits 0 and 1 set for the first two slots */ - slot_mask = 0x0000FFFF >> (16-slots); - slot_width = 32; - channels = slots; + channels = params_channels(params); + if (channels < 1 || channels > 32) { + pr_err("%s: invalid param channels %d\n", + __func__, channels); + return -EINVAL; + } + + format = params_format(params); + if (format != SNDRV_PCM_FORMAT_S32_LE && + format != SNDRV_PCM_FORMAT_S24_LE && + format != SNDRV_PCM_FORMAT_S16_LE) { + /* + * Up to 8 channel HW configuration should + * use 32 bit slot width for max support of + * stream bit width. (slot_width > bit_width) + */ + pr_err("%s: invalid param format 0x%x\n", + __func__, format); + return -EINVAL; + } + + switch (cpu_dai->id) { + case AFE_PORT_ID_PRIMARY_TDM_RX: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_rx_slot_offset[TDM_PRI][TDM_0]; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_1: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_rx_slot_offset[TDM_PRI][TDM_1]; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_2: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_rx_slot_offset[TDM_PRI][TDM_2]; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_3: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_rx_slot_offset[TDM_PRI][TDM_3]; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_4: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_rx_slot_offset[TDM_PRI][TDM_4]; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_5: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_rx_slot_offset[TDM_PRI][TDM_5]; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_6: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_rx_slot_offset[TDM_PRI][TDM_6]; + break; + case AFE_PORT_ID_PRIMARY_TDM_RX_7: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_rx_slot_offset[TDM_PRI][TDM_7]; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_tx_slot_offset[TDM_PRI][TDM_0]; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_1: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_tx_slot_offset[TDM_PRI][TDM_1]; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_2: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_tx_slot_offset[TDM_PRI][TDM_2]; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_3: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_tx_slot_offset[TDM_PRI][TDM_3]; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_4: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_tx_slot_offset[TDM_PRI][TDM_4]; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_5: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_tx_slot_offset[TDM_PRI][TDM_5]; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_6: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_tx_slot_offset[TDM_PRI][TDM_6]; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX_7: + slots = tdm_slot[TDM_PRI].num; + slot_width = tdm_slot[TDM_PRI].width; + slot_offset = tdm_tx_slot_offset[TDM_PRI][TDM_7]; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_rx_slot_offset[TDM_SEC][TDM_0]; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_1: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_rx_slot_offset[TDM_SEC][TDM_1]; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_2: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_rx_slot_offset[TDM_SEC][TDM_2]; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_3: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_rx_slot_offset[TDM_SEC][TDM_3]; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_4: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_rx_slot_offset[TDM_SEC][TDM_4]; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_5: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_rx_slot_offset[TDM_SEC][TDM_5]; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_6: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_rx_slot_offset[TDM_SEC][TDM_6]; + break; + case AFE_PORT_ID_SECONDARY_TDM_RX_7: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_rx_slot_offset[TDM_SEC][TDM_7]; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_tx_slot_offset[TDM_SEC][TDM_0]; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_1: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_tx_slot_offset[TDM_SEC][TDM_1]; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_2: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_tx_slot_offset[TDM_SEC][TDM_2]; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_3: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_tx_slot_offset[TDM_SEC][TDM_3]; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_4: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_tx_slot_offset[TDM_SEC][TDM_4]; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_5: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_tx_slot_offset[TDM_SEC][TDM_5]; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_6: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_tx_slot_offset[TDM_SEC][TDM_6]; + break; + case AFE_PORT_ID_SECONDARY_TDM_TX_7: + slots = tdm_slot[TDM_SEC].num; + slot_width = tdm_slot[TDM_SEC].width; + slot_offset = tdm_tx_slot_offset[TDM_SEC][TDM_7]; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_rx_slot_offset[TDM_TERT][TDM_0]; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_1: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_rx_slot_offset[TDM_TERT][TDM_1]; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_2: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_rx_slot_offset[TDM_TERT][TDM_2]; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_3: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_rx_slot_offset[TDM_TERT][TDM_3]; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_4: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_rx_slot_offset[TDM_TERT][TDM_4]; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_5: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_rx_slot_offset[TDM_TERT][TDM_5]; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_6: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_rx_slot_offset[TDM_TERT][TDM_6]; + break; + case AFE_PORT_ID_TERTIARY_TDM_RX_7: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_rx_slot_offset[TDM_TERT][TDM_7]; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_tx_slot_offset[TDM_TERT][TDM_0]; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_1: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_tx_slot_offset[TDM_TERT][TDM_1]; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_2: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_tx_slot_offset[TDM_TERT][TDM_2]; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_3: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_tx_slot_offset[TDM_TERT][TDM_3]; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_4: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_tx_slot_offset[TDM_TERT][TDM_4]; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_5: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_tx_slot_offset[TDM_TERT][TDM_5]; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_6: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_tx_slot_offset[TDM_TERT][TDM_6]; + break; + case AFE_PORT_ID_TERTIARY_TDM_TX_7: + slots = tdm_slot[TDM_TERT].num; + slot_width = tdm_slot[TDM_TERT].width; + slot_offset = tdm_tx_slot_offset[TDM_TERT][TDM_7]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_rx_slot_offset[TDM_QUAT][TDM_0]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_1: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_rx_slot_offset[TDM_QUAT][TDM_1]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_2: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_rx_slot_offset[TDM_QUAT][TDM_2]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_3: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_rx_slot_offset[TDM_QUAT][TDM_3]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_4: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_rx_slot_offset[TDM_QUAT][TDM_4]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_5: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_rx_slot_offset[TDM_QUAT][TDM_5]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_6: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_rx_slot_offset[TDM_QUAT][TDM_6]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_RX_7: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_rx_slot_offset[TDM_QUAT][TDM_7]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_tx_slot_offset[TDM_QUAT][TDM_0]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_1: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_tx_slot_offset[TDM_QUAT][TDM_1]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_2: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_tx_slot_offset[TDM_QUAT][TDM_2]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_3: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_tx_slot_offset[TDM_QUAT][TDM_3]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_4: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_tx_slot_offset[TDM_QUAT][TDM_4]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_5: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_tx_slot_offset[TDM_QUAT][TDM_5]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_6: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_tx_slot_offset[TDM_QUAT][TDM_6]; + break; + case AFE_PORT_ID_QUATERNARY_TDM_TX_7: + slots = tdm_slot[TDM_QUAT].num; + slot_width = tdm_slot[TDM_QUAT].width; + slot_offset = tdm_tx_slot_offset[TDM_QUAT][TDM_7]; + break; + default: + pr_err("%s: dai id 0x%x not supported\n", + __func__, cpu_dai->id); + return -EINVAL; + } + + for (i = 0; i < TDM_SLOT_OFFSET_MAX; i++) { + if (slot_offset[i] != AFE_SLOT_MAPPING_OFFSET_INVALID) + offset_channels++; + else + break; + } + + if (offset_channels == 0) { + pr_err("%s: invalid offset_channels %d\n", + __func__, offset_channels); + return -EINVAL; + } + + if (channels > offset_channels) { + pr_err("%s: channels %d exceed offset_channels %d\n", + __func__, channels, offset_channels); + return -EINVAL; + } + + slot_mask = tdm_param_set_slot_mask(slots); + if (!slot_mask) { + pr_err("%s: invalid slot_mask 0x%x\n", + __func__, slot_mask); + return -EINVAL; + } - pr_debug("%s: slot_width %d slots %d\n", __func__, slot_width, slots); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { pr_debug("%s: slot_width %d\n", __func__, slot_width); ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, slot_mask, @@ -4541,9 +6085,35 @@ static int msm8998_tdm_snd_hw_params(struct snd_pcm_substream *substream, __func__, ret); goto end; } + } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + ret = snd_soc_dai_set_tdm_slot(cpu_dai, slot_mask, 0, + slots, slot_width); + if (ret < 0) { + pr_err("%s: failed to set tdm slot, err:%d\n", + __func__, ret); + goto end; + } + + ret = snd_soc_dai_set_channel_map(cpu_dai, + channels, slot_offset, 0, NULL); + if (ret < 0) { + pr_err("%s: failed to set channel map, err:%d\n", + __func__, ret); + goto end; + } } else { + ret = -EINVAL; pr_err("%s: invalid use case, err:%d\n", __func__, ret); + goto end; + } + + 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) { + pr_err("%s: failed to set tdm clk, err:%d\n", + __func__, ret); } end: @@ -4560,7 +6130,7 @@ static int msm8998_tdm_snd_startup(struct snd_pcm_substream *substream) ret = msm_set_pinctrl(pinctrl_info, STATE_TDM_ACTIVE); if (ret) - pr_err("%s: MI2S TLMM pinctrl set failed with %d\n", + pr_err("%s: TDM TLMM pinctrl set failed with %d\n", __func__, ret); return ret; @@ -4576,7 +6146,7 @@ static void msm8998_tdm_snd_shutdown(struct snd_pcm_substream *substream) ret = msm_set_pinctrl(pinctrl_info, STATE_DISABLE); if (ret) - pr_err("%s: MI2S TLMM pinctrl set failed with %d\n", + pr_err("%s: TDM TLMM pinctrl set failed with %d\n", __func__, ret); } @@ -4712,28 +6282,6 @@ static struct snd_soc_ops msm_aux_pcm_be_ops = { .shutdown = msm_aux_pcm_snd_shutdown, }; -static unsigned int tdm_param_set_slot_mask(u16 port_id, int slot_width, - int slots) -{ - unsigned int slot_mask = 0; - int i, j; - unsigned int *slot_offset; - - for (i = TDM_0; i < TDM_PORT_MAX; i++) { - slot_offset = tdm_slot_offset[i]; - - for (j = 0; j < TDM_SLOT_OFFSET_MAX; j++) { - if (slot_offset[j] != AFE_SLOT_MAPPING_OFFSET_INVALID) - slot_mask |= - (1 << ((slot_offset[j] * 8) / slot_width)); - else - break; - } - } - - return slot_mask; -} - static int msm_tdm_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -4775,9 +6323,7 @@ static int msm_tdm_snd_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } slots = 8; - slot_mask = tdm_param_set_slot_mask(cpu_dai->id, - slot_width, - slots); + slot_mask = tdm_param_set_slot_mask(slots); if (!slot_mask) { pr_err("%s: invalid slot_mask 0x%x\n", __func__, slot_mask); @@ -5859,8 +7405,8 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = { .no_pcm = 1, .dpcm_playback = 1, .be_id = MSM_BACKEND_DAI_PRI_TDM_RX_0, - .be_hw_params_fixup = msm_be_hw_params_fixup, - .ops = &msm_tdm_be_ops, + .be_hw_params_fixup = msm_tdm_be_hw_params_fixup, + .ops = &msm8998_tdm_be_ops, .ignore_suspend = 1, }, { @@ -5873,8 +7419,8 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = { .no_pcm = 1, .dpcm_capture = 1, .be_id = MSM_BACKEND_DAI_PRI_TDM_TX_0, - .be_hw_params_fixup = msm_be_hw_params_fixup, - .ops = &msm_tdm_be_ops, + .be_hw_params_fixup = msm_tdm_be_hw_params_fixup, + .ops = &msm8998_tdm_be_ops, .ignore_suspend = 1, }, { @@ -5957,8 +7503,8 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = { .no_pcm = 1, .dpcm_capture = 1, .be_id = MSM_BACKEND_DAI_QUAT_TDM_TX_0, - .be_hw_params_fixup = msm_be_hw_params_fixup, - .ops = &msm_tdm_be_ops, + .be_hw_params_fixup = msm_tdm_be_hw_params_fixup, + .ops = &msm8998_tdm_be_ops, .ignore_suspend = 1, }, };