Loading asoc/kona.c +242 −51 Original line number Diff line number Diff line Loading @@ -75,6 +75,12 @@ #define WCN_CDC_SLIM_TX_CH_MAX 2 #define WCN_CDC_SLIM_TX_CH_MAX_LITO 3 enum { RX_PATH = 0, TX_PATH, MAX_PATH, }; enum { TDM_0 = 0, TDM_1, Loading @@ -87,6 +93,9 @@ enum { TDM_PORT_MAX, }; #define TDM_MAX_SLOTS 8 #define TDM_SLOT_WIDTH_BITS 32 enum { TDM_PRI = 0, TDM_SEC, Loading Loading @@ -176,6 +185,10 @@ struct tdm_port { u32 channel; }; struct tdm_dev_config { unsigned int tdm_slot_offset[TDM_MAX_SLOTS]; }; enum { EXT_DISP_RX_IDX_DP = 0, EXT_DISP_RX_IDX_DP1, Loading Loading @@ -462,6 +475,153 @@ static struct dev_config mi2s_tx_cfg[] = { [SEN_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, }; static struct tdm_dev_config pri_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = { { /* PRI TDM */ { {0, 4, 0xFFFF} }, /* RX_0 */ { {8, 12, 0xFFFF} }, /* RX_1 */ { {16, 20, 0xFFFF} }, /* RX_2 */ { {24, 28, 0xFFFF} }, /* RX_3 */ { {0xFFFF} }, /* RX_4 */ { {0xFFFF} }, /* RX_5 */ { {0xFFFF} }, /* RX_6 */ { {0xFFFF} }, /* RX_7 */ }, { { {0, 4, 8, 12, 0xFFFF} }, /* TX_0 */ { {8, 12, 0xFFFF} }, /* TX_1 */ { {16, 20, 0xFFFF} }, /* TX_2 */ { {24, 28, 0xFFFF} }, /* TX_3 */ { {0xFFFF} }, /* TX_4 */ { {0xFFFF} }, /* TX_5 */ { {0xFFFF} }, /* TX_6 */ { {0xFFFF} }, /* TX_7 */ }, }; static struct tdm_dev_config sec_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = { { /* SEC TDM */ { {0, 4, 0xFFFF} }, /* RX_0 */ { {8, 12, 0xFFFF} }, /* RX_1 */ { {16, 20, 0xFFFF} }, /* RX_2 */ { {24, 28, 0xFFFF} }, /* RX_3 */ { {0xFFFF} }, /* RX_4 */ { {0xFFFF} }, /* RX_5 */ { {0xFFFF} }, /* RX_6 */ { {0xFFFF} }, /* RX_7 */ }, { { {0, 4, 0xFFFF} }, /* TX_0 */ { {8, 12, 0xFFFF} }, /* TX_1 */ { {16, 20, 0xFFFF} }, /* TX_2 */ { {24, 28, 0xFFFF} }, /* TX_3 */ { {0xFFFF} }, /* TX_4 */ { {0xFFFF} }, /* TX_5 */ { {0xFFFF} }, /* TX_6 */ { {0xFFFF} }, /* TX_7 */ }, }; static struct tdm_dev_config tert_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = { { /* TERT TDM */ { {0, 4, 0xFFFF} }, /* RX_0 */ { {8, 12, 0xFFFF} }, /* RX_1 */ { {16, 20, 0xFFFF} }, /* RX_2 */ { {24, 28, 0xFFFF} }, /* RX_3 */ { {0xFFFF} }, /* RX_4 */ { {0xFFFF} }, /* RX_5 */ { {0xFFFF} }, /* RX_6 */ { {0xFFFF} }, /* RX_7 */ }, { { {0, 4, 0xFFFF} }, /* TX_0 */ { {8, 12, 0xFFFF} }, /* TX_1 */ { {16, 20, 0xFFFF} }, /* TX_2 */ { {24, 28, 0xFFFF} }, /* TX_3 */ { {0xFFFF} }, /* TX_4 */ { {0xFFFF} }, /* TX_5 */ { {0xFFFF} }, /* TX_6 */ { {0xFFFF} }, /* TX_7 */ }, }; static struct tdm_dev_config quat_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = { { /* QUAT TDM */ { {0, 4, 0xFFFF} }, /* RX_0 */ { {8, 12, 0xFFFF} }, /* RX_1 */ { {16, 20, 0xFFFF} }, /* RX_2 */ { {24, 28, 0xFFFF} }, /* RX_3 */ { {0xFFFF} }, /* RX_4 */ { {0xFFFF} }, /* RX_5 */ { {0xFFFF} }, /* RX_6 */ { {0xFFFF} }, /* RX_7 */ }, { { {0, 4, 0xFFFF} }, /* TX_0 */ { {8, 12, 0xFFFF} }, /* TX_1 */ { {16, 20, 0xFFFF} }, /* TX_2 */ { {24, 28, 0xFFFF} }, /* TX_3 */ { {0xFFFF} }, /* TX_4 */ { {0xFFFF} }, /* TX_5 */ { {0xFFFF} }, /* TX_6 */ { {0xFFFF} }, /* TX_7 */ }, }; static struct tdm_dev_config quin_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = { { /* QUIN TDM */ { {0, 4, 0xFFFF} }, /* RX_0 */ { {8, 12, 0xFFFF} }, /* RX_1 */ { {16, 20, 0xFFFF} }, /* RX_2 */ { {24, 28, 0xFFFF} }, /* RX_3 */ { {0xFFFF} }, /* RX_4 */ { {0xFFFF} }, /* RX_5 */ { {0xFFFF} }, /* RX_6 */ { {0xFFFF} }, /* RX_7 */ }, { { {0, 4, 0xFFFF} }, /* TX_0 */ { {8, 12, 0xFFFF} }, /* TX_1 */ { {16, 20, 0xFFFF} }, /* TX_2 */ { {24, 28, 0xFFFF} }, /* TX_3 */ { {0xFFFF} }, /* TX_4 */ { {0xFFFF} }, /* TX_5 */ { {0xFFFF} }, /* TX_6 */ { {0xFFFF} }, /* TX_7 */ }, }; static struct tdm_dev_config sen_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = { { /* SEN TDM */ { {0, 4, 0xFFFF} }, /* RX_0 */ { {8, 12, 0xFFFF} }, /* RX_1 */ { {16, 20, 0xFFFF} }, /* RX_2 */ { {24, 28, 0xFFFF} }, /* RX_3 */ { {0xFFFF} }, /* RX_4 */ { {0xFFFF} }, /* RX_5 */ { {0xFFFF} }, /* RX_6 */ { {0xFFFF} }, /* RX_7 */ }, { { {0, 4, 0xFFFF} }, /* TX_0 */ { {8, 12, 0xFFFF} }, /* TX_1 */ { {16, 20, 0xFFFF} }, /* TX_2 */ { {24, 28, 0xFFFF} }, /* TX_3 */ { {0xFFFF} }, /* TX_4 */ { {0xFFFF} }, /* TX_5 */ { {0xFFFF} }, /* TX_6 */ { {0xFFFF} }, /* TX_7 */ }, }; static void *tdm_cfg[TDM_INTERFACE_MAX] = { pri_tdm_dev_config, sec_tdm_dev_config, tert_tdm_dev_config, quat_tdm_dev_config, quin_tdm_dev_config, sen_tdm_dev_config, }; /* Default configuration of Codec DMA Interface RX */ static struct dev_config cdc_dma_rx_cfg[] = { [WSA_CDC_DMA_RX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, Loading Loading @@ -1789,6 +1949,45 @@ static int tdm_tx_ch_put(struct snd_kcontrol *kcontrol, return ret; } static int tdm_slot_map_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int slot_index = 0; int interface = ucontrol->value.integer.value[0]; int channel = ucontrol->value.integer.value[1]; unsigned int offset_val = 0; unsigned int *slot_offset = NULL; struct tdm_dev_config *config = NULL; if (interface < 0 || interface >= (TDM_INTERFACE_MAX * MAX_PATH)) { pr_err("%s: incorrect interface = %d\n", __func__, interface); return -EINVAL; } if (channel < 0 || channel >= TDM_PORT_MAX) { pr_err("%s: incorrect channel = %d\n", __func__, channel); return -EINVAL; } pr_debug("%s: interface = %d, channel = %d\n", __func__, interface, channel); config = ((struct tdm_dev_config *) tdm_cfg[interface / MAX_PATH]) + ((interface % MAX_PATH) * TDM_PORT_MAX) + channel; slot_offset = config->tdm_slot_offset; for (slot_index = 0; slot_index < TDM_MAX_SLOTS; slot_index++) { offset_val = ucontrol->value.integer.value[MAX_PATH + slot_index]; /* Offset value can only be 0, 4, 8, ..28 */ if (offset_val % 4 == 0 && offset_val <= 28) slot_offset[slot_index] = offset_val; pr_debug("%s: slot offset[%d] = %d\n", __func__, slot_index, slot_offset[slot_index]); } return 0; } static int aux_pcm_get_port_idx(struct snd_kcontrol *kcontrol) { int idx = 0; Loading Loading @@ -3744,6 +3943,8 @@ static const struct snd_kcontrol_new msm_common_snd_controls[] = { afe_loopback_tx_ch_get, afe_loopback_tx_ch_put), SOC_ENUM_EXT("VI_FEED_TX Channels", vi_feed_tx_chs, msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put), SOC_SINGLE_MULTI_EXT("TDM Slot Map", SND_SOC_NOPM, 0, 255, 0, TDM_MAX_SLOTS + MAX_PATH, NULL, tdm_slot_map_put), }; static const struct snd_kcontrol_new msm_snd_controls[] = { Loading Loading @@ -3813,8 +4014,9 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, SNDRV_PCM_HW_PARAM_CHANNELS); int idx = 0, rc = 0; pr_debug("%s: format = %d, rate = %d\n", __func__, params_format(params), params_rate(params)); pr_debug("%s: dai_id= %d, format = %d, rate = %d\n", __func__, dai_link->id, params_format(params), params_rate(params)); switch (dai_link->id) { case MSM_BACKEND_DAI_USB_RX: Loading Loading @@ -4280,65 +4482,51 @@ static int kona_tdm_snd_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret = 0; int slot_width = 32; int channels, slots; int slot_width = TDM_SLOT_WIDTH_BITS; int channels, slots = TDM_MAX_SLOTS; unsigned int slot_mask, rate, clk_freq; unsigned int slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28}; unsigned int *slot_offset; struct tdm_dev_config *config; unsigned int path_dir = 0, interface = 0, channel_interface = 0; pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id); /* currently only supporting TDM_RX_0 and TDM_TX_0 */ switch (cpu_dai->id) { case AFE_PORT_ID_PRIMARY_TDM_RX: slots = tdm_rx_cfg[TDM_PRI][TDM_0].channels; break; case AFE_PORT_ID_SECONDARY_TDM_RX: slots = tdm_rx_cfg[TDM_SEC][TDM_0].channels; break; case AFE_PORT_ID_TERTIARY_TDM_RX: slots = tdm_rx_cfg[TDM_TERT][TDM_0].channels; break; case AFE_PORT_ID_QUATERNARY_TDM_RX: slots = tdm_rx_cfg[TDM_QUAT][TDM_0].channels; break; case AFE_PORT_ID_QUINARY_TDM_RX: slots = tdm_rx_cfg[TDM_QUIN][TDM_0].channels; break; case AFE_PORT_ID_SENARY_TDM_RX: slots = tdm_rx_cfg[TDM_SEN][TDM_0].channels; break; case AFE_PORT_ID_PRIMARY_TDM_TX: slots = tdm_tx_cfg[TDM_PRI][TDM_0].channels; break; case AFE_PORT_ID_SECONDARY_TDM_TX: slots = tdm_tx_cfg[TDM_SEC][TDM_0].channels; break; case AFE_PORT_ID_TERTIARY_TDM_TX: slots = tdm_tx_cfg[TDM_TERT][TDM_0].channels; break; case AFE_PORT_ID_QUATERNARY_TDM_TX: slots = tdm_tx_cfg[TDM_QUAT][TDM_0].channels; break; case AFE_PORT_ID_QUINARY_TDM_TX: slots = tdm_tx_cfg[TDM_QUIN][TDM_0].channels; break; case AFE_PORT_ID_SENARY_TDM_TX: slots = tdm_tx_cfg[TDM_SEN][TDM_0].channels; break; default: if (cpu_dai->id < AFE_PORT_ID_TDM_PORT_RANGE_START) { pr_err("%s: dai id 0x%x not supported\n", __func__, cpu_dai->id); return -EINVAL; } /* RX or TX */ path_dir = cpu_dai->id % MAX_PATH; /* PRI, SEC, TERT, QUAT, QUIN, ... */ interface = (cpu_dai->id - AFE_PORT_ID_TDM_PORT_RANGE_START) / (MAX_PATH * TDM_PORT_MAX); /* 0, 1, 2, .. 7 */ channel_interface = ((cpu_dai->id - AFE_PORT_ID_TDM_PORT_RANGE_START) / MAX_PATH) % TDM_PORT_MAX; pr_debug("%s: path dir: %u, interface %u, channel interface %u\n", __func__, path_dir, interface, channel_interface); config = ((struct tdm_dev_config *) tdm_cfg[interface]) + (path_dir * TDM_PORT_MAX) + channel_interface; slot_offset = config->tdm_slot_offset; if (path_dir) channels = tdm_tx_cfg[interface][channel_interface].channels; else channels = tdm_rx_cfg[interface][channel_interface].channels; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { /*2 slot config - bits 0 and 1 set for the first two slots */ slot_mask = 0x0000FFFF >> (16 - slots); channels = slots; pr_debug("%s: tdm rx slot_width %d slots %d\n", __func__, slot_width, slots); pr_debug("%s: tdm rx slot_width %d slots %d slot_mask %x\n", __func__, slot_width, slots, slot_mask); ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, slot_mask, slots, slot_width); Loading @@ -4348,6 +4536,8 @@ static int kona_tdm_snd_hw_params(struct snd_pcm_substream *substream, goto end; } pr_debug("%s: tdm rx channels: %d\n", __func__, channels); ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL, channels, slot_offset); if (ret < 0) { Loading @@ -4358,10 +4548,9 @@ static int kona_tdm_snd_hw_params(struct snd_pcm_substream *substream, } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { /*2 slot config - bits 0 and 1 set for the first two slots */ slot_mask = 0x0000FFFF >> (16 - slots); channels = slots; pr_debug("%s: tdm tx slot_width %d slots %d\n", __func__, slot_width, slots); pr_debug("%s: tdm tx slot_width %d slots %d slot_mask %x\n", __func__, slot_width, slots, slot_mask); ret = snd_soc_dai_set_tdm_slot(cpu_dai, slot_mask, 0, slots, slot_width); Loading @@ -4371,6 +4560,8 @@ static int kona_tdm_snd_hw_params(struct snd_pcm_substream *substream, goto end; } pr_debug("%s: tdm tx channels: %d\n", __func__, channels); ret = snd_soc_dai_set_channel_map(cpu_dai, channels, slot_offset, 0, NULL); if (ret < 0) { Loading asoc/msm-dai-q6-v2.c +34 −1 Original line number Diff line number Diff line Loading @@ -9301,6 +9301,37 @@ static int msm_dai_q6_tdm_set_channel_map(struct snd_soc_dai *dai, return rc; } static unsigned int tdm_param_set_slot_mask(u16 *slot_offset, int slot_width, int slots_per_frame) { unsigned int i = 0; unsigned int slot_index = 0; unsigned long slot_mask = 0; unsigned int slot_width_bytes = slot_width / 8; if (slot_width_bytes == 0) { pr_err("%s: slot width is zero\n", __func__); return slot_mask; } for (i = 0; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++) { if (slot_offset[i] != AFE_SLOT_MAPPING_OFFSET_INVALID) { slot_index = slot_offset[i] / slot_width_bytes; if (slot_index < slots_per_frame) set_bit(slot_index, &slot_mask); else { pr_err("%s: invalid slot map setting\n", __func__); return 0; } } else { break; } } return slot_mask; } static int msm_dai_q6_tdm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) Loading Loading @@ -9405,7 +9436,9 @@ static int msm_dai_q6_tdm_hw_params(struct snd_pcm_substream *substream, */ tdm->nslots_per_frame = tdm_group->nslots_per_frame; tdm->slot_width = tdm_group->slot_width; tdm->slot_mask = tdm_group->slot_mask; tdm->slot_mask = tdm_param_set_slot_mask(slot_mapping->offset, tdm_group->slot_width, tdm_group->nslots_per_frame); pr_debug("%s: TDM:\n" "num_channels=%d sample_rate=%d bit_width=%d\n" Loading Loading
asoc/kona.c +242 −51 Original line number Diff line number Diff line Loading @@ -75,6 +75,12 @@ #define WCN_CDC_SLIM_TX_CH_MAX 2 #define WCN_CDC_SLIM_TX_CH_MAX_LITO 3 enum { RX_PATH = 0, TX_PATH, MAX_PATH, }; enum { TDM_0 = 0, TDM_1, Loading @@ -87,6 +93,9 @@ enum { TDM_PORT_MAX, }; #define TDM_MAX_SLOTS 8 #define TDM_SLOT_WIDTH_BITS 32 enum { TDM_PRI = 0, TDM_SEC, Loading Loading @@ -176,6 +185,10 @@ struct tdm_port { u32 channel; }; struct tdm_dev_config { unsigned int tdm_slot_offset[TDM_MAX_SLOTS]; }; enum { EXT_DISP_RX_IDX_DP = 0, EXT_DISP_RX_IDX_DP1, Loading Loading @@ -462,6 +475,153 @@ static struct dev_config mi2s_tx_cfg[] = { [SEN_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, }; static struct tdm_dev_config pri_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = { { /* PRI TDM */ { {0, 4, 0xFFFF} }, /* RX_0 */ { {8, 12, 0xFFFF} }, /* RX_1 */ { {16, 20, 0xFFFF} }, /* RX_2 */ { {24, 28, 0xFFFF} }, /* RX_3 */ { {0xFFFF} }, /* RX_4 */ { {0xFFFF} }, /* RX_5 */ { {0xFFFF} }, /* RX_6 */ { {0xFFFF} }, /* RX_7 */ }, { { {0, 4, 8, 12, 0xFFFF} }, /* TX_0 */ { {8, 12, 0xFFFF} }, /* TX_1 */ { {16, 20, 0xFFFF} }, /* TX_2 */ { {24, 28, 0xFFFF} }, /* TX_3 */ { {0xFFFF} }, /* TX_4 */ { {0xFFFF} }, /* TX_5 */ { {0xFFFF} }, /* TX_6 */ { {0xFFFF} }, /* TX_7 */ }, }; static struct tdm_dev_config sec_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = { { /* SEC TDM */ { {0, 4, 0xFFFF} }, /* RX_0 */ { {8, 12, 0xFFFF} }, /* RX_1 */ { {16, 20, 0xFFFF} }, /* RX_2 */ { {24, 28, 0xFFFF} }, /* RX_3 */ { {0xFFFF} }, /* RX_4 */ { {0xFFFF} }, /* RX_5 */ { {0xFFFF} }, /* RX_6 */ { {0xFFFF} }, /* RX_7 */ }, { { {0, 4, 0xFFFF} }, /* TX_0 */ { {8, 12, 0xFFFF} }, /* TX_1 */ { {16, 20, 0xFFFF} }, /* TX_2 */ { {24, 28, 0xFFFF} }, /* TX_3 */ { {0xFFFF} }, /* TX_4 */ { {0xFFFF} }, /* TX_5 */ { {0xFFFF} }, /* TX_6 */ { {0xFFFF} }, /* TX_7 */ }, }; static struct tdm_dev_config tert_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = { { /* TERT TDM */ { {0, 4, 0xFFFF} }, /* RX_0 */ { {8, 12, 0xFFFF} }, /* RX_1 */ { {16, 20, 0xFFFF} }, /* RX_2 */ { {24, 28, 0xFFFF} }, /* RX_3 */ { {0xFFFF} }, /* RX_4 */ { {0xFFFF} }, /* RX_5 */ { {0xFFFF} }, /* RX_6 */ { {0xFFFF} }, /* RX_7 */ }, { { {0, 4, 0xFFFF} }, /* TX_0 */ { {8, 12, 0xFFFF} }, /* TX_1 */ { {16, 20, 0xFFFF} }, /* TX_2 */ { {24, 28, 0xFFFF} }, /* TX_3 */ { {0xFFFF} }, /* TX_4 */ { {0xFFFF} }, /* TX_5 */ { {0xFFFF} }, /* TX_6 */ { {0xFFFF} }, /* TX_7 */ }, }; static struct tdm_dev_config quat_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = { { /* QUAT TDM */ { {0, 4, 0xFFFF} }, /* RX_0 */ { {8, 12, 0xFFFF} }, /* RX_1 */ { {16, 20, 0xFFFF} }, /* RX_2 */ { {24, 28, 0xFFFF} }, /* RX_3 */ { {0xFFFF} }, /* RX_4 */ { {0xFFFF} }, /* RX_5 */ { {0xFFFF} }, /* RX_6 */ { {0xFFFF} }, /* RX_7 */ }, { { {0, 4, 0xFFFF} }, /* TX_0 */ { {8, 12, 0xFFFF} }, /* TX_1 */ { {16, 20, 0xFFFF} }, /* TX_2 */ { {24, 28, 0xFFFF} }, /* TX_3 */ { {0xFFFF} }, /* TX_4 */ { {0xFFFF} }, /* TX_5 */ { {0xFFFF} }, /* TX_6 */ { {0xFFFF} }, /* TX_7 */ }, }; static struct tdm_dev_config quin_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = { { /* QUIN TDM */ { {0, 4, 0xFFFF} }, /* RX_0 */ { {8, 12, 0xFFFF} }, /* RX_1 */ { {16, 20, 0xFFFF} }, /* RX_2 */ { {24, 28, 0xFFFF} }, /* RX_3 */ { {0xFFFF} }, /* RX_4 */ { {0xFFFF} }, /* RX_5 */ { {0xFFFF} }, /* RX_6 */ { {0xFFFF} }, /* RX_7 */ }, { { {0, 4, 0xFFFF} }, /* TX_0 */ { {8, 12, 0xFFFF} }, /* TX_1 */ { {16, 20, 0xFFFF} }, /* TX_2 */ { {24, 28, 0xFFFF} }, /* TX_3 */ { {0xFFFF} }, /* TX_4 */ { {0xFFFF} }, /* TX_5 */ { {0xFFFF} }, /* TX_6 */ { {0xFFFF} }, /* TX_7 */ }, }; static struct tdm_dev_config sen_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = { { /* SEN TDM */ { {0, 4, 0xFFFF} }, /* RX_0 */ { {8, 12, 0xFFFF} }, /* RX_1 */ { {16, 20, 0xFFFF} }, /* RX_2 */ { {24, 28, 0xFFFF} }, /* RX_3 */ { {0xFFFF} }, /* RX_4 */ { {0xFFFF} }, /* RX_5 */ { {0xFFFF} }, /* RX_6 */ { {0xFFFF} }, /* RX_7 */ }, { { {0, 4, 0xFFFF} }, /* TX_0 */ { {8, 12, 0xFFFF} }, /* TX_1 */ { {16, 20, 0xFFFF} }, /* TX_2 */ { {24, 28, 0xFFFF} }, /* TX_3 */ { {0xFFFF} }, /* TX_4 */ { {0xFFFF} }, /* TX_5 */ { {0xFFFF} }, /* TX_6 */ { {0xFFFF} }, /* TX_7 */ }, }; static void *tdm_cfg[TDM_INTERFACE_MAX] = { pri_tdm_dev_config, sec_tdm_dev_config, tert_tdm_dev_config, quat_tdm_dev_config, quin_tdm_dev_config, sen_tdm_dev_config, }; /* Default configuration of Codec DMA Interface RX */ static struct dev_config cdc_dma_rx_cfg[] = { [WSA_CDC_DMA_RX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, Loading Loading @@ -1789,6 +1949,45 @@ static int tdm_tx_ch_put(struct snd_kcontrol *kcontrol, return ret; } static int tdm_slot_map_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int slot_index = 0; int interface = ucontrol->value.integer.value[0]; int channel = ucontrol->value.integer.value[1]; unsigned int offset_val = 0; unsigned int *slot_offset = NULL; struct tdm_dev_config *config = NULL; if (interface < 0 || interface >= (TDM_INTERFACE_MAX * MAX_PATH)) { pr_err("%s: incorrect interface = %d\n", __func__, interface); return -EINVAL; } if (channel < 0 || channel >= TDM_PORT_MAX) { pr_err("%s: incorrect channel = %d\n", __func__, channel); return -EINVAL; } pr_debug("%s: interface = %d, channel = %d\n", __func__, interface, channel); config = ((struct tdm_dev_config *) tdm_cfg[interface / MAX_PATH]) + ((interface % MAX_PATH) * TDM_PORT_MAX) + channel; slot_offset = config->tdm_slot_offset; for (slot_index = 0; slot_index < TDM_MAX_SLOTS; slot_index++) { offset_val = ucontrol->value.integer.value[MAX_PATH + slot_index]; /* Offset value can only be 0, 4, 8, ..28 */ if (offset_val % 4 == 0 && offset_val <= 28) slot_offset[slot_index] = offset_val; pr_debug("%s: slot offset[%d] = %d\n", __func__, slot_index, slot_offset[slot_index]); } return 0; } static int aux_pcm_get_port_idx(struct snd_kcontrol *kcontrol) { int idx = 0; Loading Loading @@ -3744,6 +3943,8 @@ static const struct snd_kcontrol_new msm_common_snd_controls[] = { afe_loopback_tx_ch_get, afe_loopback_tx_ch_put), SOC_ENUM_EXT("VI_FEED_TX Channels", vi_feed_tx_chs, msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put), SOC_SINGLE_MULTI_EXT("TDM Slot Map", SND_SOC_NOPM, 0, 255, 0, TDM_MAX_SLOTS + MAX_PATH, NULL, tdm_slot_map_put), }; static const struct snd_kcontrol_new msm_snd_controls[] = { Loading Loading @@ -3813,8 +4014,9 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, SNDRV_PCM_HW_PARAM_CHANNELS); int idx = 0, rc = 0; pr_debug("%s: format = %d, rate = %d\n", __func__, params_format(params), params_rate(params)); pr_debug("%s: dai_id= %d, format = %d, rate = %d\n", __func__, dai_link->id, params_format(params), params_rate(params)); switch (dai_link->id) { case MSM_BACKEND_DAI_USB_RX: Loading Loading @@ -4280,65 +4482,51 @@ static int kona_tdm_snd_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret = 0; int slot_width = 32; int channels, slots; int slot_width = TDM_SLOT_WIDTH_BITS; int channels, slots = TDM_MAX_SLOTS; unsigned int slot_mask, rate, clk_freq; unsigned int slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28}; unsigned int *slot_offset; struct tdm_dev_config *config; unsigned int path_dir = 0, interface = 0, channel_interface = 0; pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id); /* currently only supporting TDM_RX_0 and TDM_TX_0 */ switch (cpu_dai->id) { case AFE_PORT_ID_PRIMARY_TDM_RX: slots = tdm_rx_cfg[TDM_PRI][TDM_0].channels; break; case AFE_PORT_ID_SECONDARY_TDM_RX: slots = tdm_rx_cfg[TDM_SEC][TDM_0].channels; break; case AFE_PORT_ID_TERTIARY_TDM_RX: slots = tdm_rx_cfg[TDM_TERT][TDM_0].channels; break; case AFE_PORT_ID_QUATERNARY_TDM_RX: slots = tdm_rx_cfg[TDM_QUAT][TDM_0].channels; break; case AFE_PORT_ID_QUINARY_TDM_RX: slots = tdm_rx_cfg[TDM_QUIN][TDM_0].channels; break; case AFE_PORT_ID_SENARY_TDM_RX: slots = tdm_rx_cfg[TDM_SEN][TDM_0].channels; break; case AFE_PORT_ID_PRIMARY_TDM_TX: slots = tdm_tx_cfg[TDM_PRI][TDM_0].channels; break; case AFE_PORT_ID_SECONDARY_TDM_TX: slots = tdm_tx_cfg[TDM_SEC][TDM_0].channels; break; case AFE_PORT_ID_TERTIARY_TDM_TX: slots = tdm_tx_cfg[TDM_TERT][TDM_0].channels; break; case AFE_PORT_ID_QUATERNARY_TDM_TX: slots = tdm_tx_cfg[TDM_QUAT][TDM_0].channels; break; case AFE_PORT_ID_QUINARY_TDM_TX: slots = tdm_tx_cfg[TDM_QUIN][TDM_0].channels; break; case AFE_PORT_ID_SENARY_TDM_TX: slots = tdm_tx_cfg[TDM_SEN][TDM_0].channels; break; default: if (cpu_dai->id < AFE_PORT_ID_TDM_PORT_RANGE_START) { pr_err("%s: dai id 0x%x not supported\n", __func__, cpu_dai->id); return -EINVAL; } /* RX or TX */ path_dir = cpu_dai->id % MAX_PATH; /* PRI, SEC, TERT, QUAT, QUIN, ... */ interface = (cpu_dai->id - AFE_PORT_ID_TDM_PORT_RANGE_START) / (MAX_PATH * TDM_PORT_MAX); /* 0, 1, 2, .. 7 */ channel_interface = ((cpu_dai->id - AFE_PORT_ID_TDM_PORT_RANGE_START) / MAX_PATH) % TDM_PORT_MAX; pr_debug("%s: path dir: %u, interface %u, channel interface %u\n", __func__, path_dir, interface, channel_interface); config = ((struct tdm_dev_config *) tdm_cfg[interface]) + (path_dir * TDM_PORT_MAX) + channel_interface; slot_offset = config->tdm_slot_offset; if (path_dir) channels = tdm_tx_cfg[interface][channel_interface].channels; else channels = tdm_rx_cfg[interface][channel_interface].channels; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { /*2 slot config - bits 0 and 1 set for the first two slots */ slot_mask = 0x0000FFFF >> (16 - slots); channels = slots; pr_debug("%s: tdm rx slot_width %d slots %d\n", __func__, slot_width, slots); pr_debug("%s: tdm rx slot_width %d slots %d slot_mask %x\n", __func__, slot_width, slots, slot_mask); ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, slot_mask, slots, slot_width); Loading @@ -4348,6 +4536,8 @@ static int kona_tdm_snd_hw_params(struct snd_pcm_substream *substream, goto end; } pr_debug("%s: tdm rx channels: %d\n", __func__, channels); ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL, channels, slot_offset); if (ret < 0) { Loading @@ -4358,10 +4548,9 @@ static int kona_tdm_snd_hw_params(struct snd_pcm_substream *substream, } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { /*2 slot config - bits 0 and 1 set for the first two slots */ slot_mask = 0x0000FFFF >> (16 - slots); channels = slots; pr_debug("%s: tdm tx slot_width %d slots %d\n", __func__, slot_width, slots); pr_debug("%s: tdm tx slot_width %d slots %d slot_mask %x\n", __func__, slot_width, slots, slot_mask); ret = snd_soc_dai_set_tdm_slot(cpu_dai, slot_mask, 0, slots, slot_width); Loading @@ -4371,6 +4560,8 @@ static int kona_tdm_snd_hw_params(struct snd_pcm_substream *substream, goto end; } pr_debug("%s: tdm tx channels: %d\n", __func__, channels); ret = snd_soc_dai_set_channel_map(cpu_dai, channels, slot_offset, 0, NULL); if (ret < 0) { Loading
asoc/msm-dai-q6-v2.c +34 −1 Original line number Diff line number Diff line Loading @@ -9301,6 +9301,37 @@ static int msm_dai_q6_tdm_set_channel_map(struct snd_soc_dai *dai, return rc; } static unsigned int tdm_param_set_slot_mask(u16 *slot_offset, int slot_width, int slots_per_frame) { unsigned int i = 0; unsigned int slot_index = 0; unsigned long slot_mask = 0; unsigned int slot_width_bytes = slot_width / 8; if (slot_width_bytes == 0) { pr_err("%s: slot width is zero\n", __func__); return slot_mask; } for (i = 0; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++) { if (slot_offset[i] != AFE_SLOT_MAPPING_OFFSET_INVALID) { slot_index = slot_offset[i] / slot_width_bytes; if (slot_index < slots_per_frame) set_bit(slot_index, &slot_mask); else { pr_err("%s: invalid slot map setting\n", __func__); return 0; } } else { break; } } return slot_mask; } static int msm_dai_q6_tdm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) Loading Loading @@ -9405,7 +9436,9 @@ static int msm_dai_q6_tdm_hw_params(struct snd_pcm_substream *substream, */ tdm->nslots_per_frame = tdm_group->nslots_per_frame; tdm->slot_width = tdm_group->slot_width; tdm->slot_mask = tdm_group->slot_mask; tdm->slot_mask = tdm_param_set_slot_mask(slot_mapping->offset, tdm_group->slot_width, tdm_group->nslots_per_frame); pr_debug("%s: TDM:\n" "num_channels=%d sample_rate=%d bit_width=%d\n" Loading