mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 20:33:58 -04:00
Merge "asoc: enables paired rx port to address tdm slot shift issue"
This commit is contained in:
commit
dd2d4b6317
3 changed files with 558 additions and 4 deletions
|
|
@ -2858,7 +2858,7 @@ static int msm_dai_q6_cdc_hw_params(struct snd_pcm_hw_params *params,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u16 num_of_bits_set(u16 sd_line_mask)
|
||||
u16 num_of_bits_set(u16 sd_line_mask)
|
||||
{
|
||||
u8 num_bits_set = 0;
|
||||
|
||||
|
|
@ -2868,6 +2868,7 @@ static u16 num_of_bits_set(u16 sd_line_mask)
|
|||
}
|
||||
return num_bits_set;
|
||||
}
|
||||
EXPORT_SYMBOL(num_of_bits_set);
|
||||
|
||||
static int msm_dai_q6_i2s_hw_params(struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai, int stream)
|
||||
|
|
@ -11663,6 +11664,7 @@ static int msm_dai_q6_tdm_prepare(struct snd_pcm_substream *substream,
|
|||
u16 group_id = dai_data->group_cfg.tdm_cfg.group_id;
|
||||
int group_idx = 0;
|
||||
atomic_t *group_ref = NULL;
|
||||
int intf_idx = PORT_ID_TO_INTF_IDX(dai->id);
|
||||
|
||||
dev_dbg(dai->dev, "%s: dev_name: %s dev_id: 0x%x group_id: 0x%x\n",
|
||||
__func__, dev_name(dai->dev), dai->dev->id, group_id);
|
||||
|
|
@ -11683,7 +11685,6 @@ static int msm_dai_q6_tdm_prepare(struct snd_pcm_substream *substream,
|
|||
group_ref = &tdm_group_ref[group_idx];
|
||||
|
||||
if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
|
||||
|
||||
if (msm_dai_q6_get_tdm_clk_ref(group_idx) == 0) {
|
||||
/* TX and RX share the same clk. So enable the clk
|
||||
* per TDM interface. */
|
||||
|
|
@ -11695,7 +11696,18 @@ static int msm_dai_q6_tdm_prepare(struct snd_pcm_substream *substream,
|
|||
goto rtn;
|
||||
}
|
||||
}
|
||||
|
||||
/* Paired Rx Port Start */
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
rc = afe_paired_rx_tdm_port_ops(intf_idx, true, tdm_group_ref);
|
||||
if (rc < 0) {
|
||||
pr_debug("%s:Paired Rx Port failed to start\n",__func__);
|
||||
if (msm_dai_q6_get_tdm_clk_ref(group_idx) == 0) {
|
||||
msm_dai_q6_tdm_set_clk(dai_data,
|
||||
dai->id, false);
|
||||
}
|
||||
goto rtn;
|
||||
}
|
||||
}
|
||||
/* PORT START should be set if prepare called
|
||||
* in active state.
|
||||
*/
|
||||
|
|
@ -11720,6 +11732,9 @@ static int msm_dai_q6_tdm_prepare(struct snd_pcm_substream *substream,
|
|||
rc = afe_tdm_port_start(dai->id, &dai_data->port_cfg,
|
||||
dai_data->rate, dai_data->num_group_ports);
|
||||
if (rc < 0) {
|
||||
rc = afe_paired_rx_tdm_port_ops(intf_idx, false, tdm_group_ref);
|
||||
if (rc < 0)
|
||||
pr_err("%s:Unable to close Paired Rx due to tx usecase start failure", __func__);
|
||||
if (atomic_read(group_ref) == 0) {
|
||||
afe_port_group_enable(group_id,
|
||||
NULL, false, NULL);
|
||||
|
|
@ -11734,6 +11749,7 @@ static int msm_dai_q6_tdm_prepare(struct snd_pcm_substream *substream,
|
|||
set_bit(STATUS_PORT_STARTED,
|
||||
dai_data->status_mask);
|
||||
atomic_inc(group_ref);
|
||||
pr_debug("%s: Group ref count: group_ref : %d", __func__, group_ref->counter);
|
||||
}
|
||||
|
||||
/* TODO: need to monitor PCM/MI2S/TDM HW status */
|
||||
|
|
@ -11755,6 +11771,7 @@ static void msm_dai_q6_tdm_shutdown(struct snd_pcm_substream *substream,
|
|||
u16 group_id = dai_data->group_cfg.tdm_cfg.group_id;
|
||||
int group_idx = 0;
|
||||
atomic_t *group_ref = NULL;
|
||||
int intf_idx = PORT_ID_TO_INTF_IDX(dai->id);
|
||||
|
||||
group_idx = msm_dai_q6_get_group_idx(dai->id);
|
||||
if (group_idx < 0) {
|
||||
|
|
@ -11774,6 +11791,7 @@ static void msm_dai_q6_tdm_shutdown(struct snd_pcm_substream *substream,
|
|||
__func__, dai->id);
|
||||
}
|
||||
atomic_dec(group_ref);
|
||||
pr_debug("%s: group_ref : %d \n",__func__, group_ref->counter);
|
||||
clear_bit(STATUS_PORT_STARTED,
|
||||
dai_data->status_mask);
|
||||
|
||||
|
|
@ -11785,7 +11803,17 @@ static void msm_dai_q6_tdm_shutdown(struct snd_pcm_substream *substream,
|
|||
__func__, group_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Paired Rx Stop */
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
rc = afe_paired_rx_tdm_port_ops(intf_idx, false, tdm_group_ref);
|
||||
if (rc < 0){
|
||||
if (msm_dai_q6_get_tdm_clk_ref(group_idx) == 0) {
|
||||
msm_dai_q6_tdm_set_clk(dai_data,
|
||||
dai->id, false);
|
||||
}
|
||||
pr_err("%s:AFE Paired Rx Port Not disabled");
|
||||
}
|
||||
}
|
||||
if (msm_dai_q6_get_tdm_clk_ref(group_idx) == 0) {
|
||||
rc = msm_dai_q6_tdm_set_clk(dai_data,
|
||||
dai->id, false);
|
||||
|
|
|
|||
263
asoc/sa6155.c
263
asoc/sa6155.c
|
|
@ -660,6 +660,27 @@ static const char *const mi2s_ch_text[] = {"One", "Two", "Three", "Four",
|
|||
"Eight"};
|
||||
static const char *const qos_text[] = {"Disable", "Enable"};
|
||||
|
||||
static char const *tdm_pair_rx_format[] = {"PRI_TDM_RX_0", "PRI_TDM_RX_1",
|
||||
"PRI_TDM_RX_2", "PRI_TDM_RX_3",
|
||||
"PRI_TDM_RX_4", "PRI_TDM_RX_5",
|
||||
"PRI_TDM_RX_6", "PRI_TDM_RX_7",
|
||||
"SEC_TDM_RX_0", "SEC_TDM_RX_1",
|
||||
"SEC_TDM_RX_2", "SEC_TDM_RX_3",
|
||||
"SEC_TDM_RX_4", "SEC_TDM_RX_5",
|
||||
"SEC_TDM_RX_6", "SEC_TDM_RX_7",
|
||||
"TERT_TDM_RX_0", "TERT_TDM_RX_1",
|
||||
"TERT_TDM_RX_2", "TERT_TDM_RX_3",
|
||||
"TERT_TDM_RX_4", "TERT_TDM_RX_5",
|
||||
"TERT_TDM_RX_6", "TERT_TDM_RX_7",
|
||||
"QUAT_TDM_RX_0", "QUAT_TDM_RX_1",
|
||||
"QUAT_TDM_RX_2", "QUAT_TDM_RX_3",
|
||||
"QUAT_TDM_RX_4", "QUAT_TDM_RX_5",
|
||||
"QUAT_TDM_RX_6", "QUAT_TDM_RX_7",
|
||||
"QUIN_TDM_RX_0", "QUIN_TDM_RX_1",
|
||||
"QUIN_TDM_RX_2", "QUIN_TDM_RX_3",
|
||||
"QUIN_TDM_RX_4", "QUIN_TDM_RX_5",
|
||||
"QUIN_TDM_RX_6", "QUIN_TDM_RX_7"};
|
||||
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_chs, usb_ch_text);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_chs, usb_ch_text);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(ext_disp_rx_chs, ch_text);
|
||||
|
|
@ -713,6 +734,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(mi2s_rx_format, bit_format_text);
|
|||
static SOC_ENUM_SINGLE_EXT_DECL(mi2s_tx_format, bit_format_text);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_rx_format, bit_format_text);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_tx_format, bit_format_text);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(tdm_paired_rx_format, tdm_pair_rx_format);
|
||||
|
||||
static struct afe_clk_set internal_mclk[MCLK_MAX] = {
|
||||
{
|
||||
|
|
@ -2123,6 +2145,237 @@ static int tdm_tx_slot_mapping_put(struct snd_kcontrol *kcontrol,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int tdm_paired_rx_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int ret = 0;
|
||||
int mode = tdm_get_mode(kcontrol);
|
||||
/*
|
||||
*mode gets the TDM interface value
|
||||
*0: Primary , 1: secondary, 2: Tertiary, 3: Quaternary, 4: QUINARY
|
||||
*/
|
||||
if (mode < 0) {
|
||||
pr_err("%s: unsupported control: %s\n", __func__, kcontrol->id.name);
|
||||
return -EINVAL;
|
||||
}
|
||||
ucontrol->value.enumerated.item[0] = AFE_PORT_ID_INVALID;
|
||||
pr_debug("%s:Port Channel = %d", __func__, ucontrol->value.enumerated.item[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tdm_paired_rx_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int val = -1;
|
||||
int intf_idx = -1;
|
||||
int port_idx = -1;
|
||||
int index;
|
||||
int slot_array_index = 0;
|
||||
struct afe_tdm_port_config tdm_port;
|
||||
union afe_port_group_config tdm_group;
|
||||
struct afe_param_id_tdm_lane_cfg tdm_lane;
|
||||
int i = 0;
|
||||
int rc = 0;
|
||||
u16 num_bits_set = 0;
|
||||
int mode = tdm_get_mode(kcontrol);
|
||||
struct device_node *node = NULL;
|
||||
const uint32_t *port_id_array = NULL;
|
||||
uint32_t array_length = 0;
|
||||
static u32 num_tdm_group_ports;
|
||||
|
||||
if (mode < 0) {
|
||||
pr_err("%s: unsupported control: %s\n", __func__, kcontrol->id.name);
|
||||
return -EINVAL;
|
||||
} else {
|
||||
memset(&tdm_port, 0, sizeof(tdm_port));
|
||||
memset(&tdm_group, 0, sizeof(tdm_group));
|
||||
memset(&tdm_lane, 0, sizeof(tdm_lane));
|
||||
|
||||
val = ucontrol->value.enumerated.item[0];
|
||||
intf_idx = val / MAX_PORTS_PER_INTF;
|
||||
port_idx = val % MAX_PORTS_PER_INTF;
|
||||
if (mode != intf_idx) {
|
||||
pr_err("%s:Wrong value given for TDM Interface %d", __func__, intf_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
pr_debug("%s:Port Channel = %d Interface = %d", __func__, port_idx, intf_idx);
|
||||
while (tdm_rx_slot_offset[intf_idx][port_idx][slot_array_index] != AFE_SLOT_MAPPING_OFFSET_INVALID)
|
||||
slot_array_index++;
|
||||
switch (intf_idx) {
|
||||
case TDM_PRI:
|
||||
node = of_find_node_by_path("/soc/qcom,msm-dai-tdm-pri-rx");
|
||||
break;
|
||||
case TDM_SEC:
|
||||
node = of_find_node_by_path("/soc/qcom,msm-dai-tdm-sec-rx");
|
||||
break;
|
||||
case TDM_TERT:
|
||||
node = of_find_node_by_path("/soc/qcom,msm-dai-tdm-tert-rx");
|
||||
break;
|
||||
case TDM_QUAT:
|
||||
node = of_find_node_by_path("/soc/qcom,msm-dai-tdm-quat-rx");
|
||||
break;
|
||||
case TDM_QUIN:
|
||||
node = of_find_node_by_path("/soc/qcom,msm-dai-tdm-quin-rx");
|
||||
break;
|
||||
default:
|
||||
pr_err("%s:Wrong interface present", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Group Cfg */
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-group-id",(u32 *)&tdm_group.tdm_cfg.group_id);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired Rx Group Id not in DT File %s\n",__func__,"qcom,msm-cpudai-tdm-group-id");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-group-num-ports",&num_tdm_group_ports);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired Rx Group Num Ports from DT file %s\n",__func__, "qcom,msm-cpudai-tdm-group-num-ports");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (num_tdm_group_ports > AFE_GROUP_DEVICE_NUM_PORTS) {
|
||||
pr_err("%s:Paired Rx Group Num Ports %d greater than Max %d\n",__func__, num_tdm_group_ports,
|
||||
AFE_GROUP_DEVICE_NUM_PORTS);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
*Will get the array of afe ports associated with the group id. and then are
|
||||
*converted from big endian to cpu's byte order values using be32_to_cpu function.
|
||||
*/
|
||||
port_id_array = of_get_property(node,"qcom,msm-cpudai-tdm-group-port-id",&array_length);
|
||||
if (port_id_array == NULL) {
|
||||
pr_err("%s:Paired rx port_id_array is not valid\n",__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (array_length != sizeof(uint32_t) * num_tdm_group_ports) {
|
||||
pr_err("%s:paired rx array_length is %d, expected is %zd\n",
|
||||
__func__, array_length,
|
||||
sizeof(uint32_t) * num_tdm_group_ports);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < AFE_GROUP_DEVICE_NUM_PORTS; i++)
|
||||
tdm_group.tdm_cfg.port_id[i] = AFE_PORT_INVALID;
|
||||
|
||||
for (i = 0; i < num_tdm_group_ports; i++) {
|
||||
index = (((u16)be32_to_cpu(port_id_array[i]))/2)% MAX_PORTS_PER_INTF;
|
||||
tdm_group.tdm_cfg.port_id[index] =
|
||||
(u16)be32_to_cpu(port_id_array[i]);
|
||||
pr_debug("%s:Paired rx group port id is 0x%x",__func__,tdm_group.tdm_cfg.port_id[index]);
|
||||
}
|
||||
|
||||
tdm_group.tdm_cfg.group_device_cfg_minor_version = AFE_API_VERSION_GROUP_DEVICE_TDM_CONFIG;
|
||||
tdm_group.tdm_cfg.reserved = 0;
|
||||
tdm_group.tdm_cfg.nslots_per_frame = tdm_slot[intf_idx].num;
|
||||
tdm_group.tdm_cfg.sample_rate = tdm_rx_cfg[intf_idx][port_idx].sample_rate;
|
||||
tdm_group.tdm_cfg.slot_width = tdm_slot[intf_idx].width;
|
||||
tdm_group.tdm_cfg.bit_width = tdm_group.tdm_cfg.slot_width;
|
||||
|
||||
/* Lane Cfg */
|
||||
tdm_lane.port_id = tdm_group.group_cfg.group_id;
|
||||
tdm_lane.lane_mask = AFE_LANE_MASK_INVALID;
|
||||
if (of_find_property(node,"qcom,msm-cpudai-tdm-lane-mask", NULL)) {
|
||||
rc = of_property_read_u16(node,"qcom,msm-cpudai-tdm-lane-mask",&tdm_lane.lane_mask);
|
||||
if (rc) {
|
||||
pr_err("%s: value for tdm lane mask not found %s\n",__func__, "qcom,msm-cpudai-tdm-lane-mask");
|
||||
return -EINVAL;
|
||||
}
|
||||
pr_debug("%s: tdm lane mask from DT file %d\n",__func__, tdm_lane.lane_mask);
|
||||
} else
|
||||
pr_debug("%s: tdm lane mask not found\n", __func__);
|
||||
if (tdm_lane.lane_mask != AFE_LANE_MASK_INVALID) {
|
||||
num_bits_set = num_of_bits_set(tdm_lane.lane_mask);
|
||||
tdm_group.tdm_cfg.num_channels = tdm_group.tdm_cfg.nslots_per_frame * num_bits_set;
|
||||
} else {
|
||||
tdm_group.tdm_cfg.num_channels = tdm_group.tdm_cfg.nslots_per_frame;
|
||||
}
|
||||
|
||||
/* TDM Cfg */
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-sync-mode",(u32 *)&tdm_port.tdm.sync_mode);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired rx Sync Mode from DT file %s\n",__func__, "qcom,msm-cpudai-tdm-sync-mode");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-sync-src",(u32 *)&tdm_port.tdm.sync_src);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired rx Sync Src from DT file %s\n",__func__, "qcom,msm-cpudai-tdm-sync-src");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-data-out",(u32 *)&tdm_port.tdm.ctrl_data_out_enable);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired rx Data Out from DT file %s\n",__func__, "qcom,msm-cpudai-tdm-data-out");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-invert-sync",(u32 *)&tdm_port.tdm.ctrl_invert_sync_pulse);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired rx Invert Sync from DT file %s\n",
|
||||
__func__, "qcom,msm-cpudai-tdm-invert-sync");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-data-delay",(u32 *)&tdm_port.tdm.ctrl_sync_data_delay);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired rx Data Delay from DT file %s\n",__func__, "qcom,msm-cpudai-tdm-data-delay");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* TDM Cfg */
|
||||
tdm_port.tdm.data_format = AFE_LINEAR_PCM_DATA;
|
||||
tdm_port.tdm.tdm_cfg_minor_version = AFE_API_VERSION_TDM_CONFIG;
|
||||
tdm_port.tdm.num_channels = tdm_rx_cfg[intf_idx][port_idx].channels;
|
||||
tdm_port.tdm.sample_rate = tdm_rx_cfg[intf_idx][port_idx].sample_rate;
|
||||
tdm_port.tdm.bit_width = tdm_slot[intf_idx].width;
|
||||
tdm_port.tdm.nslots_per_frame = tdm_slot[intf_idx].num;
|
||||
tdm_port.tdm.slot_width = tdm_slot[intf_idx].width;
|
||||
|
||||
/* Slot Mapping Cfg */
|
||||
tdm_port.slot_mapping.num_channel = tdm_rx_cfg[intf_idx][port_idx].channels;
|
||||
tdm_port.slot_mapping.bitwidth = tdm_slot[intf_idx].width;
|
||||
tdm_port.slot_mapping.data_align_type = AFE_SLOT_MAPPING_DATA_ALIGN_MSB;
|
||||
tdm_port.slot_mapping.minor_version = AFE_API_VERSION_SLOT_MAPPING_CONFIG;
|
||||
|
||||
/* Slot Mapping v2 Cfg */
|
||||
tdm_port.slot_mapping_v2.num_channel = tdm_rx_cfg[intf_idx][port_idx].channels;
|
||||
tdm_port.slot_mapping_v2.bitwidth = tdm_slot[intf_idx].width;
|
||||
tdm_port.slot_mapping_v2.data_align_type = AFE_SLOT_MAPPING_DATA_ALIGN_MSB;
|
||||
tdm_port.slot_mapping_v2.minor_version = AFE_API_VERSION_SLOT_MAPPING_CONFIG_V2;
|
||||
|
||||
for (i = 0; (i < slot_array_index) && (i < AFE_PORT_MAX_AUDIO_CHAN_CNT); i++)
|
||||
tdm_port.slot_mapping.offset[i] = tdm_rx_slot_offset[intf_idx][port_idx][i];
|
||||
|
||||
for (i = slot_array_index; i < AFE_PORT_MAX_AUDIO_CHAN_CNT ; i++)
|
||||
tdm_port.slot_mapping.offset[i] = AFE_SLOT_MAPPING_OFFSET_INVALID;
|
||||
|
||||
for (i = 0; (i < slot_array_index) && (i < AFE_PORT_MAX_AUDIO_CHAN_CNT_V2) ; i++)
|
||||
tdm_port.slot_mapping_v2.offset[i] = tdm_rx_slot_offset[intf_idx][port_idx][i];
|
||||
|
||||
for (i = slot_array_index; i < AFE_PORT_MAX_AUDIO_CHAN_CNT_V2 ; i++)
|
||||
tdm_port.slot_mapping_v2.offset[i] = AFE_SLOT_MAPPING_OFFSET_INVALID;
|
||||
|
||||
for (i = 0; i < tdm_slot[intf_idx].num ; i++)
|
||||
tdm_port.tdm.slot_mask |= 1 << i;
|
||||
|
||||
tdm_port.custom_tdm_header.minor_version = AFE_API_VERSION_CUSTOM_TDM_HEADER_CONFIG;
|
||||
tdm_port.custom_tdm_header.header_type = AFE_CUSTOM_TDM_HEADER_TYPE_INVALID;
|
||||
|
||||
tdm_group.tdm_cfg.slot_mask = tdm_port.tdm.slot_mask;
|
||||
|
||||
pr_debug("%s:Paired Rx Info\n"
|
||||
"Group Id: 0x%x, Group Num Ports: 0x%x, Sync Mode: 0x%x\n"
|
||||
"Sync Src: 0x%x, Data Out: 0x%x, Invert Sync: 0x%x, Data Delay: 0x%x\n",
|
||||
__func__, tdm_group.tdm_cfg.group_id, num_tdm_group_ports,
|
||||
tdm_port.tdm.sync_mode, tdm_port.tdm.sync_src,
|
||||
tdm_port.tdm.ctrl_data_out_enable, tdm_port.tdm.ctrl_invert_sync_pulse,
|
||||
tdm_port.tdm.ctrl_sync_data_delay);
|
||||
afe_tdm_paired_rx_cfg_val(intf_idx, tdm_group.tdm_cfg.port_id[port_idx], tdm_group, tdm_port, tdm_lane);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aux_pcm_get_port_idx(struct snd_kcontrol *kcontrol)
|
||||
{
|
||||
int idx;
|
||||
|
|
@ -3326,6 +3579,16 @@ static const struct snd_kcontrol_new msm_snd_controls[] = {
|
|||
msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
|
||||
SOC_ENUM_EXT("QUIN_AUX_PCM_TX Format", aux_pcm_tx_format,
|
||||
msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
|
||||
SOC_ENUM_EXT("PRI_TDM Paired_Rx", tdm_paired_rx_format,
|
||||
tdm_paired_rx_get, tdm_paired_rx_put),
|
||||
SOC_ENUM_EXT("SEC_TDM Paired_Rx", tdm_paired_rx_format,
|
||||
tdm_paired_rx_get, tdm_paired_rx_put),
|
||||
SOC_ENUM_EXT("TERT_TDM Paired_Rx", tdm_paired_rx_format,
|
||||
tdm_paired_rx_get, tdm_paired_rx_put),
|
||||
SOC_ENUM_EXT("QUAT_TDM Paired_Rx", tdm_paired_rx_format,
|
||||
tdm_paired_rx_get, tdm_paired_rx_put),
|
||||
SOC_ENUM_EXT("QUIN_TDM Paired_Rx", tdm_paired_rx_format,
|
||||
tdm_paired_rx_get, tdm_paired_rx_put),
|
||||
};
|
||||
|
||||
static inline int param_is_mask(int p)
|
||||
|
|
|
|||
263
asoc/sa8155.c
263
asoc/sa8155.c
|
|
@ -892,6 +892,27 @@ static const char *const mi2s_ch_text[] = {"One", "Two", "Three", "Four",
|
|||
"Eight"};
|
||||
static const char *const qos_text[] = {"Disable", "Enable"};
|
||||
|
||||
static char const *tdm_pair_rx_format[] = {"PRI_TDM_RX_0", "PRI_TDM_RX_1",
|
||||
"PRI_TDM_RX_2", "PRI_TDM_RX_3",
|
||||
"PRI_TDM_RX_4", "PRI_TDM_RX_5",
|
||||
"PRI_TDM_RX_6", "PRI_TDM_RX_7",
|
||||
"SEC_TDM_RX_0", "SEC_TDM_RX_1",
|
||||
"SEC_TDM_RX_2", "SEC_TDM_RX_3",
|
||||
"SEC_TDM_RX_4", "SEC_TDM_RX_5",
|
||||
"SEC_TDM_RX_6", "SEC_TDM_RX_7",
|
||||
"TERT_TDM_RX_0", "TERT_TDM_RX_1",
|
||||
"TERT_TDM_RX_2", "TERT_TDM_RX_3",
|
||||
"TERT_TDM_RX_4", "TERT_TDM_RX_5",
|
||||
"TERT_TDM_RX_6", "TERT_TDM_RX_7",
|
||||
"QUAT_TDM_RX_0", "QUAT_TDM_RX_1",
|
||||
"QUAT_TDM_RX_2", "QUAT_TDM_RX_3",
|
||||
"QUAT_TDM_RX_4", "QUAT_TDM_RX_5",
|
||||
"QUAT_TDM_RX_6", "QUAT_TDM_RX_7",
|
||||
"QUIN_TDM_RX_0", "QUIN_TDM_RX_1",
|
||||
"QUIN_TDM_RX_2", "QUIN_TDM_RX_3",
|
||||
"QUIN_TDM_RX_4", "QUIN_TDM_RX_5",
|
||||
"QUIN_TDM_RX_6", "QUIN_TDM_RX_7"};
|
||||
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_chs, usb_ch_text);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_chs, usb_ch_text);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(ext_disp_rx_chs, ch_text);
|
||||
|
|
@ -946,6 +967,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(mi2s_rx_format, bit_format_text);
|
|||
static SOC_ENUM_SINGLE_EXT_DECL(mi2s_tx_format, bit_format_text);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_rx_format, bit_format_text);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_tx_format, bit_format_text);
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(tdm_paired_rx_format, tdm_pair_rx_format);
|
||||
|
||||
static struct afe_clk_set internal_mclk[MCLK_MAX] = {
|
||||
{
|
||||
|
|
@ -2392,6 +2414,237 @@ static int tdm_tx_slot_mapping_put(struct snd_kcontrol *kcontrol,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int tdm_paired_rx_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int ret = 0;
|
||||
int mode = tdm_get_mode(kcontrol);
|
||||
/*
|
||||
*mode gets the TDM interface value
|
||||
*0: Primary , 1: secondary, 2: Tertiary, 3: Quaternary, 4: QUINARY
|
||||
*/
|
||||
if (mode < 0) {
|
||||
pr_err("%s: unsupported control: %s\n", __func__, kcontrol->id.name);
|
||||
return -EINVAL;
|
||||
}
|
||||
ucontrol->value.enumerated.item[0] = AFE_PORT_ID_INVALID;
|
||||
pr_debug("%s:Port Channel = %d", __func__, ucontrol->value.enumerated.item[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tdm_paired_rx_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int val = -1;
|
||||
int intf_idx = -1;
|
||||
int port_idx = -1;
|
||||
int index;
|
||||
int slot_array_index = 0;
|
||||
struct afe_tdm_port_config tdm_port;
|
||||
union afe_port_group_config tdm_group;
|
||||
struct afe_param_id_tdm_lane_cfg tdm_lane;
|
||||
int i = 0;
|
||||
int rc = 0;
|
||||
u16 num_bits_set = 0;
|
||||
int mode = tdm_get_mode(kcontrol);
|
||||
struct device_node *node = NULL;
|
||||
const uint32_t *port_id_array = NULL;
|
||||
uint32_t array_length = 0;
|
||||
static u32 num_tdm_group_ports;
|
||||
|
||||
if (mode < 0) {
|
||||
pr_err("%s: unsupported control: %s\n", __func__, kcontrol->id.name);
|
||||
return -EINVAL;
|
||||
} else {
|
||||
memset(&tdm_port, 0, sizeof(tdm_port));
|
||||
memset(&tdm_group, 0, sizeof(tdm_group));
|
||||
memset(&tdm_lane, 0, sizeof(tdm_lane));
|
||||
|
||||
val = ucontrol->value.enumerated.item[0];
|
||||
intf_idx = val / MAX_PORTS_PER_INTF;
|
||||
port_idx = val % MAX_PORTS_PER_INTF;
|
||||
if (mode != intf_idx) {
|
||||
pr_err("%s:Wrong value given for TDM Interface %d", __func__, intf_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
pr_debug("%s:Port Channel = %d Interface = %d", __func__, port_idx, intf_idx);
|
||||
while (tdm_rx_slot_offset[intf_idx][port_idx][slot_array_index] != AFE_SLOT_MAPPING_OFFSET_INVALID)
|
||||
slot_array_index++;
|
||||
switch (intf_idx) {
|
||||
case TDM_PRI:
|
||||
node = of_find_node_by_path("/soc/qcom,msm-dai-tdm-pri-rx");
|
||||
break;
|
||||
case TDM_SEC:
|
||||
node = of_find_node_by_path("/soc/qcom,msm-dai-tdm-sec-rx");
|
||||
break;
|
||||
case TDM_TERT:
|
||||
node = of_find_node_by_path("/soc/qcom,msm-dai-tdm-tert-rx");
|
||||
break;
|
||||
case TDM_QUAT:
|
||||
node = of_find_node_by_path("/soc/qcom,msm-dai-tdm-quat-rx");
|
||||
break;
|
||||
case TDM_QUIN:
|
||||
node = of_find_node_by_path("/soc/qcom,msm-dai-tdm-quin-rx");
|
||||
break;
|
||||
default:
|
||||
pr_err("%s:Wrong interface present", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Group Cfg */
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-group-id",(u32 *)&tdm_group.tdm_cfg.group_id);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired Rx Group Id not in DT File %s\n",__func__,"qcom,msm-cpudai-tdm-group-id");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-group-num-ports",&num_tdm_group_ports);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired Rx Group Num Ports from DT file %s\n",__func__, "qcom,msm-cpudai-tdm-group-num-ports");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (num_tdm_group_ports > AFE_GROUP_DEVICE_NUM_PORTS) {
|
||||
pr_err("%s:Paired Rx Group Num Ports %d greater than Max %d\n",__func__, num_tdm_group_ports,
|
||||
AFE_GROUP_DEVICE_NUM_PORTS);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
*Will get the array of afe ports associated with the group id. and then are
|
||||
*converted from big endian to cpu's byte order values using be32_to_cpu function.
|
||||
*/
|
||||
port_id_array = of_get_property(node,"qcom,msm-cpudai-tdm-group-port-id",&array_length);
|
||||
if (port_id_array == NULL) {
|
||||
pr_err("%s:Paired rx port_id_array is not valid\n",__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (array_length != sizeof(uint32_t) * num_tdm_group_ports) {
|
||||
pr_err("%s:paired rx array_length is %d, expected is %zd\n",
|
||||
__func__, array_length,
|
||||
sizeof(uint32_t) * num_tdm_group_ports);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < AFE_GROUP_DEVICE_NUM_PORTS; i++)
|
||||
tdm_group.tdm_cfg.port_id[i] = AFE_PORT_INVALID;
|
||||
|
||||
for (i = 0; i < num_tdm_group_ports; i++) {
|
||||
index = (((u16)be32_to_cpu(port_id_array[i]))/2)% MAX_PORTS_PER_INTF;
|
||||
tdm_group.tdm_cfg.port_id[index] =
|
||||
(u16)be32_to_cpu(port_id_array[i]);
|
||||
pr_debug("%s:Paired rx group port id is 0x%x",__func__,tdm_group.tdm_cfg.port_id[index]);
|
||||
}
|
||||
|
||||
tdm_group.tdm_cfg.group_device_cfg_minor_version = AFE_API_VERSION_GROUP_DEVICE_TDM_CONFIG;
|
||||
tdm_group.tdm_cfg.reserved = 0;
|
||||
tdm_group.tdm_cfg.nslots_per_frame = tdm_slot[intf_idx].num;
|
||||
tdm_group.tdm_cfg.sample_rate = tdm_rx_cfg[intf_idx][port_idx].sample_rate;
|
||||
tdm_group.tdm_cfg.slot_width = tdm_slot[intf_idx].width;
|
||||
tdm_group.tdm_cfg.bit_width = tdm_group.tdm_cfg.slot_width;
|
||||
|
||||
/* Lane Cfg */
|
||||
tdm_lane.port_id = tdm_group.group_cfg.group_id;
|
||||
tdm_lane.lane_mask = AFE_LANE_MASK_INVALID;
|
||||
if (of_find_property(node,"qcom,msm-cpudai-tdm-lane-mask", NULL)) {
|
||||
rc = of_property_read_u16(node,"qcom,msm-cpudai-tdm-lane-mask",&tdm_lane.lane_mask);
|
||||
if (rc) {
|
||||
pr_err("%s: value for tdm lane mask not found %s\n",__func__, "qcom,msm-cpudai-tdm-lane-mask");
|
||||
return -EINVAL;
|
||||
}
|
||||
pr_debug("%s: tdm lane mask from DT file %d\n",__func__, tdm_lane.lane_mask);
|
||||
} else
|
||||
pr_debug("%s: tdm lane mask not found\n", __func__);
|
||||
if (tdm_lane.lane_mask != AFE_LANE_MASK_INVALID) {
|
||||
num_bits_set = num_of_bits_set(tdm_lane.lane_mask);
|
||||
tdm_group.tdm_cfg.num_channels = tdm_group.tdm_cfg.nslots_per_frame * num_bits_set;
|
||||
} else {
|
||||
tdm_group.tdm_cfg.num_channels = tdm_group.tdm_cfg.nslots_per_frame;
|
||||
}
|
||||
|
||||
/* TDM Cfg */
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-sync-mode",(u32 *)&tdm_port.tdm.sync_mode);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired rx Sync Mode from DT file %s\n",__func__, "qcom,msm-cpudai-tdm-sync-mode");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-sync-src",(u32 *)&tdm_port.tdm.sync_src);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired rx Sync Src from DT file %s\n",__func__, "qcom,msm-cpudai-tdm-sync-src");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-data-out",(u32 *)&tdm_port.tdm.ctrl_data_out_enable);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired rx Data Out from DT file %s\n",__func__, "qcom,msm-cpudai-tdm-data-out");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-invert-sync",(u32 *)&tdm_port.tdm.ctrl_invert_sync_pulse);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired rx Invert Sync from DT file %s\n",
|
||||
__func__, "qcom,msm-cpudai-tdm-invert-sync");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(node,"qcom,msm-cpudai-tdm-data-delay",(u32 *)&tdm_port.tdm.ctrl_sync_data_delay);
|
||||
if (rc) {
|
||||
pr_err("%s:Paired rx Data Delay from DT file %s\n",__func__, "qcom,msm-cpudai-tdm-data-delay");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* TDM Cfg */
|
||||
tdm_port.tdm.data_format = AFE_LINEAR_PCM_DATA;
|
||||
tdm_port.tdm.tdm_cfg_minor_version = AFE_API_VERSION_TDM_CONFIG;
|
||||
tdm_port.tdm.num_channels = tdm_rx_cfg[intf_idx][port_idx].channels;
|
||||
tdm_port.tdm.sample_rate = tdm_rx_cfg[intf_idx][port_idx].sample_rate;
|
||||
tdm_port.tdm.bit_width = tdm_slot[intf_idx].width;
|
||||
tdm_port.tdm.nslots_per_frame = tdm_slot[intf_idx].num;
|
||||
tdm_port.tdm.slot_width = tdm_slot[intf_idx].width;
|
||||
|
||||
/* Slot Mapping Cfg */
|
||||
tdm_port.slot_mapping.num_channel = tdm_rx_cfg[intf_idx][port_idx].channels;
|
||||
tdm_port.slot_mapping.bitwidth = tdm_slot[intf_idx].width;
|
||||
tdm_port.slot_mapping.data_align_type = AFE_SLOT_MAPPING_DATA_ALIGN_MSB;
|
||||
tdm_port.slot_mapping.minor_version = AFE_API_VERSION_SLOT_MAPPING_CONFIG;
|
||||
|
||||
/* Slot Mapping v2 Cfg */
|
||||
tdm_port.slot_mapping_v2.num_channel = tdm_rx_cfg[intf_idx][port_idx].channels;
|
||||
tdm_port.slot_mapping_v2.bitwidth = tdm_slot[intf_idx].width;
|
||||
tdm_port.slot_mapping_v2.data_align_type = AFE_SLOT_MAPPING_DATA_ALIGN_MSB;
|
||||
tdm_port.slot_mapping_v2.minor_version = AFE_API_VERSION_SLOT_MAPPING_CONFIG_V2;
|
||||
|
||||
for (i = 0; (i < slot_array_index) && (i < AFE_PORT_MAX_AUDIO_CHAN_CNT); i++)
|
||||
tdm_port.slot_mapping.offset[i] = tdm_rx_slot_offset[intf_idx][port_idx][i];
|
||||
|
||||
for (i = slot_array_index; i < AFE_PORT_MAX_AUDIO_CHAN_CNT ; i++)
|
||||
tdm_port.slot_mapping.offset[i] = AFE_SLOT_MAPPING_OFFSET_INVALID;
|
||||
|
||||
for (i = 0; (i < slot_array_index) && (i < AFE_PORT_MAX_AUDIO_CHAN_CNT_V2) ; i++)
|
||||
tdm_port.slot_mapping_v2.offset[i] = tdm_rx_slot_offset[intf_idx][port_idx][i];
|
||||
|
||||
for (i = slot_array_index; i < AFE_PORT_MAX_AUDIO_CHAN_CNT_V2 ; i++)
|
||||
tdm_port.slot_mapping_v2.offset[i] = AFE_SLOT_MAPPING_OFFSET_INVALID;
|
||||
|
||||
for (i = 0; i < tdm_slot[intf_idx].num ; i++)
|
||||
tdm_port.tdm.slot_mask |= 1 << i;
|
||||
|
||||
tdm_port.custom_tdm_header.minor_version = AFE_API_VERSION_CUSTOM_TDM_HEADER_CONFIG;
|
||||
tdm_port.custom_tdm_header.header_type = AFE_CUSTOM_TDM_HEADER_TYPE_INVALID;
|
||||
|
||||
tdm_group.tdm_cfg.slot_mask = tdm_port.tdm.slot_mask;
|
||||
|
||||
pr_debug("%s:Paired Rx Info\n"
|
||||
"Group Id: 0x%x, Group Num Ports: 0x%x, Sync Mode: 0x%x\n"
|
||||
"Sync Src: 0x%x, Data Out: 0x%x, Invert Sync: 0x%x, Data Delay: 0x%x\n",
|
||||
__func__, tdm_group.tdm_cfg.group_id, num_tdm_group_ports,
|
||||
tdm_port.tdm.sync_mode, tdm_port.tdm.sync_src,
|
||||
tdm_port.tdm.ctrl_data_out_enable, tdm_port.tdm.ctrl_invert_sync_pulse,
|
||||
tdm_port.tdm.ctrl_sync_data_delay);
|
||||
afe_tdm_paired_rx_cfg_val(intf_idx, tdm_group.tdm_cfg.port_id[port_idx], tdm_group, tdm_port, tdm_lane);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aux_pcm_get_port_idx(struct snd_kcontrol *kcontrol)
|
||||
{
|
||||
int idx;
|
||||
|
|
@ -3597,6 +3850,16 @@ static const struct snd_kcontrol_new msm_common_snd_controls[] = {
|
|||
msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
|
||||
SOC_ENUM_EXT("QUIN_AUX_PCM_TX Format", aux_pcm_tx_format,
|
||||
msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
|
||||
SOC_ENUM_EXT("PRI_TDM Paired_Rx", tdm_paired_rx_format,
|
||||
tdm_paired_rx_get, tdm_paired_rx_put),
|
||||
SOC_ENUM_EXT("SEC_TDM Paired_Rx", tdm_paired_rx_format,
|
||||
tdm_paired_rx_get, tdm_paired_rx_put),
|
||||
SOC_ENUM_EXT("TERT_TDM Paired_Rx", tdm_paired_rx_format,
|
||||
tdm_paired_rx_get, tdm_paired_rx_put),
|
||||
SOC_ENUM_EXT("QUAT_TDM Paired_Rx", tdm_paired_rx_format,
|
||||
tdm_paired_rx_get, tdm_paired_rx_put),
|
||||
SOC_ENUM_EXT("QUIN_TDM Paired_Rx", tdm_paired_rx_format,
|
||||
tdm_paired_rx_get, tdm_paired_rx_put),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new sa8295_msm_snd_controls[] = {
|
||||
|
|
|
|||
Loading…
Reference in a new issue