SoC: msm: qdsp6v2: Add TDM changes in dai driver
Update dai driver with TDM dai related changes. Add
a property to help not configure the AFE EBIT on platforms
where it is not supported.
Change-Id: Ic10cbb58f31698ceb03a07d94c8834515e828a93
Signed-off-by: Yeleswarapu Nagaradhesh <nagaradh@codeaurora.org>
Signed-off-by: Ashish Jain <ashishj@codeaurora.org>
diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c
index 27d8bf3..85d5f94 100644
--- a/asoc/msm-dai-q6-v2.c
+++ b/asoc/msm-dai-q6-v2.c
@@ -234,17 +234,22 @@
struct msm_dai_q6_dai_data bdai_data; /* incoporate base DAI data */
};
+static union afe_port_group_config group_cfg_tx;
+
struct msm_dai_q6_tdm_dai_data {
DECLARE_BITMAP(status_mask, STATUS_MAX);
u32 rate;
u32 channels;
u32 bitwidth;
u32 num_group_ports;
+ bool afe_ebit_unsupported;
struct afe_clk_set clk_set; /* hold LPASS clock config. */
union afe_port_group_config group_cfg; /* hold tdm group config */
struct afe_tdm_port_config port_cfg; /* hold tdm config */
};
+static bool afe_ebit_unsupported;
+
/* MI2S format field for AFE_PORT_CMD_I2S_CONFIG command
* 0: linear PCM
* 1: non-linear PCM
@@ -5389,6 +5394,11 @@
goto rtn;
}
+ afe_ebit_unsupported = of_property_read_bool(pdev->dev.of_node,
+ "qcom,msm-cpudai-tdm-afe-ebit-unsupported");
+
+ dev_dbg(&pdev->dev, "afe_ebit_unsupported %d\n", afe_ebit_unsupported);
+
/* other initializations within device group */
group_idx = msm_dai_q6_get_group_idx(tdm_group_cfg.group_id);
if (group_idx < 0) {
@@ -6344,6 +6354,10 @@
{
int rc = 0;
+ pr_debug("dai_data->group_cfg.tdm_cfg.group_id = %d : %d\n",
+ dai_data->group_cfg.tdm_cfg.group_id,
+ dai_data->clk_set.clk_freq_in_hz);
+
dai_data->clk_set.enable = enable;
rc = afe_set_lpass_clock_v2(port_id,
@@ -6570,6 +6584,11 @@
tdm_group->nslots_per_frame = slots;
tdm_group->slot_width = slot_width;
tdm_group->slot_mask = rx_mask & cap_mask;
+ dev_dbg(dai->dev, "%s:Rx:tdm_group->nslots_per_frame %d\n"
+ "tdm_group->slot_width %d\n"
+ "tdm_group->slot_mask %d\n", __func__,
+ tdm_group->nslots_per_frame,
+ tdm_group->slot_width, tdm_group->slot_mask);
break;
case AFE_PORT_ID_PRIMARY_TDM_TX:
case AFE_PORT_ID_PRIMARY_TDM_TX_1:
@@ -6614,6 +6633,10 @@
tdm_group->nslots_per_frame = slots;
tdm_group->slot_width = slot_width;
tdm_group->slot_mask = tx_mask & cap_mask;
+ dev_dbg(dai->dev, "%s:Tx:tdm_group->nslots_per_frame %d\n"
+ "tdm_group->slot_width %d,tdm_group->slot_mask %d\n"
+ "tx%d\n", __func__, tdm_group->nslots_per_frame,
+ tdm_group->slot_width, tdm_group->slot_mask, tx_mask);
break;
default:
dev_err(dai->dev, "%s: invalid dai id 0x%x\n",
@@ -6946,6 +6969,23 @@
custom_tdm_header->header[7]);
}
+ memcpy(&group_cfg_tx.group_cfg, &dai_data->group_cfg.group_cfg,
+ sizeof(dai_data->group_cfg.group_cfg));
+ memcpy(&group_cfg_tx.group_enable, &dai_data->group_cfg.group_enable,
+ sizeof(dai_data->group_cfg.group_enable));
+ memcpy(&group_cfg_tx.tdm_cfg, &dai_data->group_cfg.tdm_cfg,
+ sizeof(dai_data->group_cfg.tdm_cfg));
+ pr_debug("%s: TDM GROUP:\n"
+ "num_channels=%d sample_rate=%d bit_width=%d\n"
+ "nslots_per_frame=%d slot_width=%d slot_mask=0x%x\n",
+ __func__,
+ group_cfg_tx.tdm_cfg.num_channels,
+ group_cfg_tx.tdm_cfg.sample_rate,
+ group_cfg_tx.tdm_cfg.bit_width,
+ group_cfg_tx.tdm_cfg.nslots_per_frame,
+ group_cfg_tx.tdm_cfg.slot_width,
+ group_cfg_tx.tdm_cfg.slot_mask);
+
return 0;
}
@@ -6957,6 +6997,8 @@
dev_get_drvdata(dai->dev);
u16 group_id = dai_data->group_cfg.tdm_cfg.group_id;
int group_idx = 0;
+ u16 prim_port_id = 0;
+ u16 sec_port_id = 0;
atomic_t *group_ref = NULL;
group_idx = msm_dai_q6_get_group_idx(dai->id);
@@ -6979,12 +7021,16 @@
* AFE clk is enabled per group to simplify the logic.
* DSP will monitor the clk count.
*/
- rc = msm_dai_q6_tdm_set_clk(dai_data,
- dai->id, true);
- if (rc < 0) {
- dev_err(dai->dev, "%s: fail to enable AFE clk 0x%x\n",
- __func__, dai->id);
- goto rtn;
+ if (!(dai_data->afe_ebit_unsupported &&
+ !dai_data->clk_set.clk_freq_in_hz)) {
+
+ rc = msm_dai_q6_tdm_set_clk(dai_data,
+ dai->id, true);
+ if (rc < 0) {
+ dev_err(dai->dev, "%s: fail to enable AFE clk 0x%x\n",
+ __func__, dai->id);
+ goto rtn;
+ }
}
/*
@@ -6992,32 +7038,95 @@
* is no group need for only one port
*/
if (dai_data->num_group_ports > 1) {
+ dev_dbg(dai->dev, "%s:enable RX afe group\n",
+ __func__);
rc = afe_port_group_enable(group_id,
&dai_data->group_cfg, true);
if (rc < 0) {
dev_err(dai->dev,
- "%s: fail to enable AFE group 0x%x\n",
+ "%s: fail to enable grp %x\n",
__func__, group_id);
goto rtn;
}
}
}
- rc = afe_tdm_port_start(dai->id, &dai_data->port_cfg,
+ /*
+ * 8909 HW has a dependency where for Rx/Tx to work in TDM mode
+ * We need to start a Tx or Rx port in the same group.
+ * Hence for BG use TDM_TX when a RX session is requested and
+ * use TDM_RX port when a TX session is requested as these ports
+ * are unused as of now.
+ */
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ prim_port_id = dai->id;
+ if (dai_data->afe_ebit_unsupported)
+ sec_port_id = AFE_PORT_ID_PRIMARY_TDM_TX;
+ } else {
+ prim_port_id = dai->id;
+ if (dai_data->afe_ebit_unsupported)
+ sec_port_id = AFE_PORT_ID_PRIMARY_TDM_RX;
+ }
+ dev_dbg(dai->dev, "\n%s:open prim port id %d TDM rate: %d\n"
+ "dai_data->port_cfg.tdm.slot_mask %x\n"
+ "dai_data->port_cfg.tdm.nslots_per_frame:%x\n",
+ __func__, prim_port_id,
+ dai_data->port_cfg.tdm.num_channels,
+ dai_data->port_cfg.tdm.slot_mask,
+ dai_data->port_cfg.tdm.nslots_per_frame);
+
+ rc = afe_tdm_port_start(prim_port_id, &dai_data->port_cfg,
dai_data->rate, dai_data->num_group_ports);
+
if (rc < 0) {
if (atomic_read(group_ref) == 0) {
afe_port_group_enable(group_id,
NULL, false);
- msm_dai_q6_tdm_set_clk(dai_data,
- dai->id, false);
+ if (!(dai_data->afe_ebit_unsupported &&
+ !dai_data->clk_set.clk_freq_in_hz))
+ msm_dai_q6_tdm_set_clk(dai_data,
+ dai->id, false);
}
- dev_err(dai->dev, "%s: fail to open AFE port 0x%x\n",
- __func__, dai->id);
+ dev_err(dai->dev, "%s: open AFE port 0x%x\n",
+ __func__, prim_port_id);
} else {
set_bit(STATUS_PORT_STARTED,
dai_data->status_mask);
atomic_inc(group_ref);
+
+ }
+
+ dai_data->port_cfg.tdm.num_channels = 1;
+ dai_data->port_cfg.tdm.slot_mask = 1;
+ dai_data->port_cfg.tdm.nslots_per_frame = 4;
+
+ dev_dbg(dai->dev, "\n%s:open sec port id %d TDM rate: %d\n"
+ "dai_data->port_cfg.tdm.slot_mask %x\n"
+ "dai_data->port_cfg.tdm.nslotsper_frame:%x\n", __func__,
+ sec_port_id, dai_data->port_cfg.tdm.num_channels,
+ dai_data->port_cfg.tdm.slot_mask,
+ dai_data->port_cfg.tdm.nslots_per_frame);
+
+ if (sec_port_id != 0) {
+ rc = afe_tdm_port_start(sec_port_id,
+ &dai_data->port_cfg,
+ dai_data->rate, 4);
+ if (IS_ERR_VALUE(rc)) {
+ if (atomic_read(group_ref) == 0) {
+ afe_port_group_enable(group_id,
+ NULL, false);
+ msm_dai_q6_tdm_set_clk(dai_data,
+ dai->id, false);
+ }
+ dev_err(dai->dev, "%s: fail AFE port 0x%x\n",
+ __func__, sec_port_id);
+ } else {
+ set_bit(STATUS_PORT_STARTED,
+ dai_data->status_mask);
+ atomic_inc(group_ref);
+ }
+
}
/* TODO: need to monitor PCM/MI2S/TDM HW status */
@@ -7038,6 +7147,8 @@
dev_get_drvdata(dai->dev);
u16 group_id = dai_data->group_cfg.tdm_cfg.group_id;
int group_idx = 0;
+ u16 prim_port_id = 0;
+ u16 sec_port_id = 0;
atomic_t *group_ref = NULL;
group_idx = msm_dai_q6_get_group_idx(dai->id);
@@ -7052,11 +7163,30 @@
group_ref = &tdm_group_ref[group_idx];
if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
- rc = afe_close(dai->id);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ prim_port_id = dai->id;
+ if (dai_data->afe_ebit_unsupported)
+ sec_port_id = AFE_PORT_ID_PRIMARY_TDM_TX;
+ } else {
+ prim_port_id = dai->id;
+ if (dai_data->afe_ebit_unsupported)
+ sec_port_id = AFE_PORT_ID_PRIMARY_TDM_RX;
+ }
+
+ rc = afe_close(prim_port_id);
if (rc < 0) {
dev_err(dai->dev, "%s: fail to close AFE port 0x%x\n",
- __func__, dai->id);
+ __func__, prim_port_id);
}
+
+ if (sec_port_id != 0) {
+ rc = afe_close(sec_port_id);
+ if (IS_ERR_VALUE(rc)) {
+ dev_err(dai->dev, "%s: fail AFE port 0x%x\n",
+ __func__, sec_port_id);
+ }
+ }
+
atomic_dec(group_ref);
clear_bit(STATUS_PORT_STARTED,
dai_data->status_mask);
@@ -7065,13 +7195,15 @@
rc = afe_port_group_enable(group_id,
NULL, false);
if (rc < 0) {
- dev_err(dai->dev, "%s: fail to disable AFE group 0x%x\n",
+ dev_err(dai->dev,
+ "%s: fail to disable grp 0x%x\n",
__func__, group_id);
}
rc = msm_dai_q6_tdm_set_clk(dai_data,
dai->id, false);
if (rc < 0) {
- dev_err(dai->dev, "%s: fail to disable AFE clk 0x%x\n",
+ dev_err(dai->dev,
+ "%s: fail to disable AFE clk 0x%x\n",
__func__, dai->id);
}
}
@@ -8886,6 +9018,34 @@
dai_data->num_group_ports = num_tdm_group_ports;
+
+
+ dev_dbg(&pdev->dev, "TX group configuration tdm_dev_id 0x%x\n",
+ tdm_dev_id);
+
+ dai_data->afe_ebit_unsupported = afe_ebit_unsupported;
+
+ if (tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_TX ||
+ tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_TX_1 ||
+ tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_TX_2 ||
+ tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_TX_3) {
+ dev_dbg(&pdev->dev, "Copy TX group config id %d\n", tdm_dev_id);
+ /*memcpy (&group_cfg_tx,&dai_data->group_cfg ,
+ sizeof(dai_data->group_cfg));*/
+ memcpy(&group_cfg_tx.group_cfg,
+ &dai_data->group_cfg.group_cfg,
+ sizeof(dai_data->group_cfg.group_cfg));
+ memcpy(&group_cfg_tx.group_enable,
+ &dai_data->group_cfg.group_enable,
+ sizeof(dai_data->group_cfg.group_enable));
+ memcpy(&group_cfg_tx.tdm_cfg,
+ &dai_data->group_cfg.tdm_cfg,
+ sizeof(dai_data->group_cfg.tdm_cfg));
+ dev_dbg(&pdev->dev,
+ "Copy TX group configuration Successfully tdm_id %d\n",
+ tdm_dev_id);
+ }
+
dev_set_drvdata(&pdev->dev, dai_data);
port_idx = msm_dai_q6_get_port_idx(tdm_dev_id);