msm: q6dspv2: Add slimbus data path support
Register slimbus CPU dai link to support slimbus data path. Change-Id: I3584306ac1e0ad6561a19cecfe71f2a63aadafa9 Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org>
This commit is contained in:
committed by
Stephen Boyd
parent
0e33cbb772
commit
1238a07489
@@ -1,4 +1,4 @@
|
||||
Qualcomm audio devices for ALSA sound soc
|
||||
Qualcomm audio devices for ALSA sound SoC
|
||||
|
||||
* msm-pcm
|
||||
|
||||
@@ -42,6 +42,22 @@ Required properties:
|
||||
|
||||
- compatible : "qcom,msm-dai-fe"
|
||||
|
||||
* msm-dai-q6
|
||||
|
||||
[First Level Nodes]
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "msm-dai-q6"
|
||||
|
||||
[Second Level Nodes]
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "qcom,msm-dai-q6-dev"
|
||||
- qcom,msm-dai-q6-dev-id : The slimbus multi channel port ID
|
||||
Value is from 16384 to 16393
|
||||
|
||||
* msm-auxpcm
|
||||
|
||||
[First Level Nodes]
|
||||
@@ -117,6 +133,19 @@ Example:
|
||||
compatible = "qcom,msm-dai-fe";
|
||||
};
|
||||
|
||||
qcom,msm-dai-q6 {
|
||||
compatible = "qcom,msm-dai-q6";
|
||||
qcom,msm-dai-q6-sb-0-rx {
|
||||
compatible = "qcom,msm-dai-q6-dev";
|
||||
qcom,msm-dai-q6-dev-id = <16384>;
|
||||
};
|
||||
|
||||
qcom,msm-dai-q6-sb-0-tx {
|
||||
compatible = "qcom,msm-dai-q6-dev";
|
||||
qcom,msm-dai-q6-dev-id = <16385>;
|
||||
};
|
||||
};
|
||||
|
||||
qcom,msm-auxpcm {
|
||||
compatible = "qcom,msm-auxpcm-resource";
|
||||
qcom,msm-cpudai-auxpcm-clk = "pcm_clk";
|
||||
|
||||
@@ -400,6 +400,19 @@
|
||||
compatible = "qcom,msm-dai-fe";
|
||||
};
|
||||
|
||||
qcom,msm-dai-q6 {
|
||||
compatible = "qcom,msm-dai-q6";
|
||||
qcom,msm-dai-q6-sb-0-rx {
|
||||
compatible = "qcom,msm-dai-q6-dev";
|
||||
qcom,msm-dai-q6-dev-id = <16384>;
|
||||
};
|
||||
|
||||
qcom,msm-dai-q6-sb-0-tx {
|
||||
compatible = "qcom,msm-dai-q6-dev";
|
||||
qcom,msm-dai-q6-dev-id = <16385>;
|
||||
};
|
||||
};
|
||||
|
||||
qcom,msm-auxpcm {
|
||||
compatible = "qcom,msm-auxpcm-resource";
|
||||
qcom,msm-cpudai-auxpcm-clk = "pcm_clk";
|
||||
|
||||
@@ -573,6 +573,7 @@ struct adm_cmd_matrix_mute_v5 {
|
||||
|
||||
/* Payload of the #ADM_CMD_CONNECT_AFE_PORT_V5 command.*/
|
||||
struct adm_cmd_connect_afe_port_v5 {
|
||||
struct apr_hdr hdr;
|
||||
u8 mode;
|
||||
/* ID of the stream router (RX/TX). Use the
|
||||
* ADM_STRTR_ID_RX or ADM_STRTR_IDX macros
|
||||
|
||||
@@ -77,6 +77,7 @@ int afe_loopback(u16 enable, u16 rx_port, u16 tx_port);
|
||||
int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain);
|
||||
int afe_loopback_gain(u16 port_id, u16 volume);
|
||||
int afe_validate_port(u16 port_id);
|
||||
int afe_get_port_index(u16 port_id);
|
||||
int afe_start_pseudo_port(u16 port_id);
|
||||
int afe_stop_pseudo_port(u16 port_id);
|
||||
int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz);
|
||||
|
||||
@@ -325,6 +325,494 @@ static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_tx_dai = {
|
||||
.remove = msm_dai_q6_dai_auxpcm_remove,
|
||||
};
|
||||
|
||||
static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
|
||||
int rc = 0;
|
||||
|
||||
if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
|
||||
/* PORT START should be set if prepare called in active state */
|
||||
rc = afe_q6_interface_prepare();
|
||||
if (IS_ERR_VALUE(rc))
|
||||
dev_err(dai->dev, "fail to open AFE APR\n");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_dai_q6_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
|
||||
int rc = 0;
|
||||
|
||||
/*
|
||||
* Start/stop port without waiting for Q6 AFE response. Need to have
|
||||
* native q6 AFE driver propagates AFE response in order to handle
|
||||
* port start/stop command error properly if error does arise.
|
||||
*/
|
||||
pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
|
||||
__func__, dai->id, cmd, *dai_data->status_mask);
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
|
||||
switch (dai->id) {
|
||||
case VOICE_PLAYBACK_TX:
|
||||
case VOICE_RECORD_TX:
|
||||
case VOICE_RECORD_RX:
|
||||
afe_pseudo_port_start_nowait(dai->id);
|
||||
break;
|
||||
default:
|
||||
afe_port_start_nowait(dai->id,
|
||||
&dai_data->port_config, dai_data->rate);
|
||||
break;
|
||||
}
|
||||
set_bit(STATUS_PORT_STARTED,
|
||||
dai_data->status_mask);
|
||||
}
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
|
||||
switch (dai->id) {
|
||||
case VOICE_PLAYBACK_TX:
|
||||
case VOICE_RECORD_TX:
|
||||
case VOICE_RECORD_RX:
|
||||
afe_pseudo_port_stop_nowait(dai->id);
|
||||
break;
|
||||
default:
|
||||
afe_port_stop_nowait(dai->id);
|
||||
break;
|
||||
}
|
||||
clear_bit(STATUS_PORT_STARTED,
|
||||
dai_data->status_mask);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_dai_q6_cdc_hw_params(struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai, int stream)
|
||||
{
|
||||
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
|
||||
|
||||
dai_data->channels = params_channels(params);
|
||||
switch (dai_data->channels) {
|
||||
case 2:
|
||||
dai_data->port_config.i2s.mono_stereo = MSM_AFE_STEREO;
|
||||
break;
|
||||
case 1:
|
||||
dai_data->port_config.i2s.mono_stereo = MSM_AFE_MONO;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
dai_data->rate = params_rate(params);
|
||||
dai_data->port_config.i2s.sample_rate = dai_data->rate;
|
||||
dai_data->port_config.i2s.i2s_cfg_minor_version =
|
||||
AFE_API_VERSION_I2S_CONFIG;
|
||||
dai_data->port_config.i2s.data_format = AFE_LINEAR_PCM_DATA;
|
||||
dev_dbg(dai->dev, " channel %d sample rate %d entered\n",
|
||||
dai_data->channels, dai_data->rate);
|
||||
|
||||
/* Q6 only supports 16 as now */
|
||||
dai_data->port_config.i2s.bit_width = 16;
|
||||
dai_data->port_config.i2s.channel_mode = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 num_of_bits_set(u8 sd_line_mask)
|
||||
{
|
||||
u8 num_bits_set = 0;
|
||||
|
||||
while (sd_line_mask) {
|
||||
num_bits_set++;
|
||||
sd_line_mask = sd_line_mask & (sd_line_mask - 1);
|
||||
}
|
||||
return num_bits_set;
|
||||
}
|
||||
|
||||
static int msm_dai_q6_i2s_hw_params(struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai, int stream)
|
||||
{
|
||||
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
|
||||
struct msm_i2s_data *i2s_pdata =
|
||||
(struct msm_i2s_data *) dai->dev->platform_data;
|
||||
|
||||
dai_data->channels = params_channels(params);
|
||||
if (num_of_bits_set(i2s_pdata->sd_lines) == 1) {
|
||||
switch (dai_data->channels) {
|
||||
case 2:
|
||||
dai_data->port_config.i2s.mono_stereo = MSM_AFE_STEREO;
|
||||
break;
|
||||
case 1:
|
||||
dai_data->port_config.i2s.mono_stereo = MSM_AFE_MONO;
|
||||
break;
|
||||
default:
|
||||
pr_warn("greater than stereo has not been validated");
|
||||
break;
|
||||
}
|
||||
}
|
||||
dai_data->rate = params_rate(params);
|
||||
dai_data->port_config.i2s.sample_rate = dai_data->rate;
|
||||
dai_data->port_config.i2s.i2s_cfg_minor_version =
|
||||
AFE_API_VERSION_I2S_CONFIG;
|
||||
dai_data->port_config.i2s.data_format = AFE_LINEAR_PCM_DATA;
|
||||
/* Q6 only supports 16 as now */
|
||||
dai_data->port_config.i2s.bit_width = 16;
|
||||
dai_data->port_config.i2s.channel_mode = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_dai_q6_slim_bus_hw_params(struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai, int stream)
|
||||
{
|
||||
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
|
||||
|
||||
dai_data->channels = params_channels(params);
|
||||
dai_data->rate = params_rate(params);
|
||||
|
||||
/* Q6 only supports 16 as now */
|
||||
dai_data->port_config.slim_sch.sb_cfg_minor_version =
|
||||
AFE_API_VERSION_SLIMBUS_CONFIG;
|
||||
dai_data->port_config.slim_sch.bit_width = 16;
|
||||
dai_data->port_config.slim_sch.data_format = 0;
|
||||
dai_data->port_config.slim_sch.num_channels = dai_data->channels;
|
||||
dai_data->port_config.slim_sch.sample_rate = dai_data->rate;
|
||||
|
||||
dev_dbg(dai->dev, "%s:slimbus_dev_id[%hu] bit_wd[%hu] format[%hu]\n"
|
||||
"num_channel %hu shared_ch_mapping[0] %hu\n"
|
||||
"slave_port_mapping[1] %hu slave_port_mapping[2] %hu\n"
|
||||
"sample_rate %d\n", __func__,
|
||||
dai_data->port_config.slim_sch.slimbus_dev_id,
|
||||
dai_data->port_config.slim_sch.bit_width,
|
||||
dai_data->port_config.slim_sch.data_format,
|
||||
dai_data->port_config.slim_sch.num_channels,
|
||||
dai_data->port_config.slim_sch.shared_ch_mapping[0],
|
||||
dai_data->port_config.slim_sch.shared_ch_mapping[1],
|
||||
dai_data->port_config.slim_sch.shared_ch_mapping[2],
|
||||
dai_data->rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_dai_q6_bt_fm_hw_params(struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai, int stream)
|
||||
{
|
||||
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
|
||||
|
||||
dai_data->channels = params_channels(params);
|
||||
dai_data->rate = params_rate(params);
|
||||
|
||||
dev_dbg(dai->dev, "channels %d sample rate %d entered\n",
|
||||
dai_data->channels, dai_data->rate);
|
||||
|
||||
memset(&dai_data->port_config, 0, sizeof(dai_data->port_config));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_dai_q6_afe_rtproxy_hw_params(struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
|
||||
|
||||
dai_data->rate = params_rate(params);
|
||||
dai_data->port_config.rtproxy.num_channels = params_channels(params);
|
||||
dai_data->port_config.rtproxy.sample_rate = params_rate(params);
|
||||
|
||||
pr_debug("channel %d entered,dai_id: %d,rate: %d\n",
|
||||
dai_data->port_config.rtproxy.num_channels, dai->id, dai_data->rate);
|
||||
|
||||
dai_data->port_config.rtproxy.rt_proxy_cfg_minor_version =
|
||||
AFE_API_VERSION_RT_PROXY_CONFIG;
|
||||
dai_data->port_config.rtproxy.bit_width = 16; /* Q6 only supports 16 */
|
||||
dai_data->port_config.rtproxy.interleaved = 1;
|
||||
dai_data->port_config.rtproxy.frame_size = params_period_bytes(params);
|
||||
dai_data->port_config.rtproxy.jitter_allowance =
|
||||
dai_data->port_config.rtproxy.frame_size/2;
|
||||
dai_data->port_config.rtproxy.low_water_mark = 0;
|
||||
dai_data->port_config.rtproxy.high_water_mark = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Current implementation assumes hw_param is called once
|
||||
* This may not be the case but what to do when ADM and AFE
|
||||
* port are already opened and parameter changes
|
||||
*/
|
||||
static int msm_dai_q6_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch (dai->id) {
|
||||
case PRIMARY_I2S_TX:
|
||||
case PRIMARY_I2S_RX:
|
||||
case SECONDARY_I2S_RX:
|
||||
rc = msm_dai_q6_cdc_hw_params(params, dai, substream->stream);
|
||||
break;
|
||||
case MI2S_RX:
|
||||
rc = msm_dai_q6_i2s_hw_params(params, dai, substream->stream);
|
||||
break;
|
||||
case SLIMBUS_0_RX:
|
||||
case SLIMBUS_1_RX:
|
||||
case SLIMBUS_0_TX:
|
||||
case SLIMBUS_1_TX:
|
||||
rc = msm_dai_q6_slim_bus_hw_params(params, dai,
|
||||
substream->stream);
|
||||
break;
|
||||
case INT_BT_SCO_RX:
|
||||
case INT_BT_SCO_TX:
|
||||
case INT_FM_RX:
|
||||
case INT_FM_TX:
|
||||
rc = msm_dai_q6_bt_fm_hw_params(params, dai, substream->stream);
|
||||
break;
|
||||
case RT_PROXY_DAI_001_TX:
|
||||
case RT_PROXY_DAI_001_RX:
|
||||
case RT_PROXY_DAI_002_TX:
|
||||
case RT_PROXY_DAI_002_RX:
|
||||
rc = msm_dai_q6_afe_rtproxy_hw_params(params, dai);
|
||||
break;
|
||||
case VOICE_PLAYBACK_TX:
|
||||
case VOICE_RECORD_RX:
|
||||
case VOICE_RECORD_TX:
|
||||
rc = 0;
|
||||
break;
|
||||
default:
|
||||
dev_err(dai->dev, "invalid AFE port ID\n");
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void msm_dai_q6_shutdown(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
|
||||
int rc = 0;
|
||||
|
||||
if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
|
||||
switch (dai->id) {
|
||||
case VOICE_PLAYBACK_TX:
|
||||
case VOICE_RECORD_TX:
|
||||
case VOICE_RECORD_RX:
|
||||
pr_debug("%s, stop pseudo port:%d\n",
|
||||
__func__, dai->id);
|
||||
rc = afe_stop_pseudo_port(dai->id);
|
||||
break;
|
||||
default:
|
||||
rc = afe_close(dai->id); /* can block */
|
||||
break;
|
||||
}
|
||||
if (IS_ERR_VALUE(rc))
|
||||
dev_err(dai->dev, "fail to close AFE port\n");
|
||||
pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
|
||||
*dai_data->status_mask);
|
||||
clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
|
||||
}
|
||||
}
|
||||
|
||||
static int msm_dai_q6_cdc_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
{
|
||||
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
dai_data->port_config.i2s.ws_src = 1; /* CPU is master */
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
dai_data->port_config.i2s.ws_src = 0; /* CPU is slave */
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_dai_q6_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
dev_dbg(dai->dev, "enter %s, id = %d fmt[%d]\n", __func__,
|
||||
dai->id, fmt);
|
||||
switch (dai->id) {
|
||||
case PRIMARY_I2S_TX:
|
||||
case PRIMARY_I2S_RX:
|
||||
case MI2S_RX:
|
||||
case SECONDARY_I2S_RX:
|
||||
rc = msm_dai_q6_cdc_set_fmt(dai, fmt);
|
||||
break;
|
||||
default:
|
||||
dev_err(dai->dev, "invalid cpu_dai set_fmt\n");
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai,
|
||||
unsigned int tx_num, unsigned int *tx_slot,
|
||||
unsigned int rx_num, unsigned int *rx_slot)
|
||||
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
|
||||
unsigned int i = 0;
|
||||
|
||||
dev_dbg(dai->dev, "enter %s, id = %d\n", __func__, dai->id);
|
||||
switch (dai->id) {
|
||||
case SLIMBUS_0_RX:
|
||||
case SLIMBUS_1_RX:
|
||||
/*
|
||||
* channel number to be between 128 and 255.
|
||||
* For RX port use channel numbers
|
||||
* from 138 to 144 for pre-Taiko
|
||||
* from 144 to 159 for Taiko
|
||||
*/
|
||||
if (!rx_slot)
|
||||
return -EINVAL;
|
||||
for (i = 0; i < rx_num; i++) {
|
||||
dai_data->port_config.slim_sch.shared_ch_mapping[i] =
|
||||
rx_slot[i];
|
||||
pr_err("%s: find number of channels[%d] ch[%d]\n",
|
||||
__func__, i, rx_slot[i]);
|
||||
}
|
||||
dai_data->port_config.slim_sch.num_channels = rx_num;
|
||||
pr_debug("%s:SLIMBUS_0_RX cnt[%d] ch[%d %d]\n", __func__,
|
||||
rx_num, dai_data->port_config.slim_sch.shared_ch_mapping[0],
|
||||
dai_data->port_config.slim_sch.shared_ch_mapping[1]);
|
||||
|
||||
break;
|
||||
case SLIMBUS_0_TX:
|
||||
case SLIMBUS_1_TX:
|
||||
/*
|
||||
* channel number to be between 128 and 255.
|
||||
* For TX port use channel numbers
|
||||
* from 128 to 137 for pre-Taiko
|
||||
* from 128 to 143 for Taiko
|
||||
*/
|
||||
if (!tx_slot)
|
||||
return -EINVAL;
|
||||
for (i = 0; i < tx_num; i++) {
|
||||
dai_data->port_config.slim_sch.shared_ch_mapping[i] =
|
||||
tx_slot[i];
|
||||
pr_debug("%s: find number of channels[%d] ch[%d]\n",
|
||||
__func__, i, tx_slot[i]);
|
||||
}
|
||||
dai_data->port_config.slim_sch.num_channels = tx_num;
|
||||
pr_debug("%s:SLIMBUS_0_TX cnt[%d] ch[%d %d]\n", __func__,
|
||||
tx_num,
|
||||
dai_data->port_config.slim_sch.shared_ch_mapping[0],
|
||||
dai_data->port_config.slim_sch.shared_ch_mapping[1]);
|
||||
break;
|
||||
default:
|
||||
dev_err(dai->dev, "invalid cpu_dai id %d\n", dai->id);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_ops msm_dai_q6_ops = {
|
||||
.prepare = msm_dai_q6_prepare,
|
||||
.trigger = msm_dai_q6_trigger,
|
||||
.hw_params = msm_dai_q6_hw_params,
|
||||
.shutdown = msm_dai_q6_shutdown,
|
||||
.set_fmt = msm_dai_q6_set_fmt,
|
||||
.set_channel_map = msm_dai_q6_set_channel_map,
|
||||
};
|
||||
|
||||
static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct msm_dai_q6_dai_data *dai_data;
|
||||
int rc = 0;
|
||||
|
||||
dai_data = kzalloc(sizeof(struct msm_dai_q6_dai_data), GFP_KERNEL);
|
||||
|
||||
if (!dai_data) {
|
||||
dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
|
||||
dai->id);
|
||||
rc = -ENOMEM;
|
||||
} else
|
||||
dev_set_drvdata(dai->dev, dai_data);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct msm_dai_q6_dai_data *dai_data;
|
||||
int rc;
|
||||
|
||||
dai_data = dev_get_drvdata(dai->dev);
|
||||
|
||||
/* If AFE port is still up, close it */
|
||||
if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
|
||||
switch (dai->id) {
|
||||
case VOICE_PLAYBACK_TX:
|
||||
case VOICE_RECORD_TX:
|
||||
case VOICE_RECORD_RX:
|
||||
pr_debug("%s, stop pseudo port:%d\n",
|
||||
__func__, dai->id);
|
||||
rc = afe_stop_pseudo_port(dai->id);
|
||||
break;
|
||||
default:
|
||||
rc = afe_close(dai->id); /* can block */
|
||||
}
|
||||
if (IS_ERR_VALUE(rc))
|
||||
dev_err(dai->dev, "fail to close AFE port\n");
|
||||
clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
|
||||
}
|
||||
kfree(dai_data);
|
||||
snd_soc_unregister_dai(dai->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
|
||||
.playback = {
|
||||
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.channels_min = 1,
|
||||
.channels_max = 1,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 16000,
|
||||
},
|
||||
.ops = &msm_dai_q6_ops,
|
||||
.probe = msm_dai_q6_dai_probe,
|
||||
.remove = msm_dai_q6_dai_remove,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_tx_dai = {
|
||||
.capture = {
|
||||
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.channels_min = 1,
|
||||
.channels_max = 1,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 16000,
|
||||
},
|
||||
.ops = &msm_dai_q6_ops,
|
||||
.probe = msm_dai_q6_dai_probe,
|
||||
.remove = msm_dai_q6_dai_remove,
|
||||
};
|
||||
|
||||
static int msm_auxpcm_dev_probe(struct platform_device *pdev)
|
||||
{
|
||||
int id;
|
||||
@@ -512,6 +1000,135 @@ static struct platform_driver msm_auxpcm_resource = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver msm_dai_q6_slimbus_rx_dai = {
|
||||
.playback = {
|
||||
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
|
||||
SNDRV_PCM_RATE_16000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 48000,
|
||||
},
|
||||
.ops = &msm_dai_q6_ops,
|
||||
.probe = msm_dai_q6_dai_probe,
|
||||
.remove = msm_dai_q6_dai_remove,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai = {
|
||||
.capture = {
|
||||
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
|
||||
SNDRV_PCM_RATE_16000,
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 48000,
|
||||
},
|
||||
.ops = &msm_dai_q6_ops,
|
||||
.probe = msm_dai_q6_dai_probe,
|
||||
.remove = msm_dai_q6_dai_remove,
|
||||
};
|
||||
|
||||
static int msm_dai_q6_dev_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc, id;
|
||||
const char *q6_dev_id = "qcom,msm-dai-q6-dev-id";
|
||||
|
||||
rc = of_property_read_u32(pdev->dev.of_node, q6_dev_id, &id);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev,
|
||||
"%s: missing %s in dt node\n", __func__, q6_dev_id);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pdev->id = id;
|
||||
dev_set_name(&pdev->dev, "%s.%d", "msm-dai-q6-dev", id);
|
||||
|
||||
pr_debug("%s: dev name %s, id:%d\n", __func__,
|
||||
dev_name(&pdev->dev), pdev->id);
|
||||
|
||||
switch (id) {
|
||||
case SLIMBUS_0_RX:
|
||||
rc = snd_soc_register_dai(&pdev->dev,
|
||||
&msm_dai_q6_slimbus_rx_dai);
|
||||
break;
|
||||
case SLIMBUS_0_TX:
|
||||
rc = snd_soc_register_dai(&pdev->dev,
|
||||
&msm_dai_q6_slimbus_tx_dai);
|
||||
break;
|
||||
case SLIMBUS_1_RX:
|
||||
rc = snd_soc_register_dai(&pdev->dev,
|
||||
&msm_dai_q6_slimbus_1_rx_dai);
|
||||
break;
|
||||
case SLIMBUS_1_TX:
|
||||
rc = snd_soc_register_dai(&pdev->dev,
|
||||
&msm_dai_q6_slimbus_1_tx_dai);
|
||||
break;
|
||||
default:
|
||||
rc = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_dai_q6_dev_remove(struct platform_device *pdev)
|
||||
{
|
||||
snd_soc_unregister_dai(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id msm_dai_q6_dev_dt_match[] = {
|
||||
{ .compatible = "qcom,msm-dai-q6-dev", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, msm_dai_q6_dev_dt_match);
|
||||
|
||||
static struct platform_driver msm_dai_q6_dev = {
|
||||
.probe = msm_dai_q6_dev_probe,
|
||||
.remove = msm_dai_q6_dev_remove,
|
||||
.driver = {
|
||||
.name = "msm-dai-q6-dev",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = msm_dai_q6_dev_dt_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int msm_dai_q6_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc;
|
||||
pr_debug("%s: dev name %s, id:%d\n", __func__,
|
||||
dev_name(&pdev->dev), pdev->id);
|
||||
rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n",
|
||||
__func__, rc);
|
||||
} else
|
||||
dev_dbg(&pdev->dev, "%s: added child node\n", __func__);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_dai_q6_remove(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id msm_dai_q6_dt_match[] = {
|
||||
{ .compatible = "qcom,msm-dai-q6", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, msm_dai_q6_dt_match);
|
||||
static struct platform_driver msm_dai_q6 = {
|
||||
.probe = msm_dai_q6_probe,
|
||||
.remove = msm_dai_q6_remove,
|
||||
.driver = {
|
||||
.name = "msm-dai-q6",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = msm_dai_q6_dt_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init msm_dai_q6_init(void)
|
||||
{
|
||||
@@ -522,10 +1139,27 @@ static int __init msm_dai_q6_init(void)
|
||||
goto fail;
|
||||
|
||||
rc = platform_driver_register(&msm_auxpcm_resource);
|
||||
|
||||
if (rc) {
|
||||
pr_err("%s: fail to register cpu dai driver\n", __func__);
|
||||
platform_driver_unregister(&msm_auxpcm_dev);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = platform_driver_register(&msm_dai_q6);
|
||||
if (rc) {
|
||||
pr_err("%s: fail to register dai q6 driver", __func__);
|
||||
platform_driver_unregister(&msm_auxpcm_dev);
|
||||
platform_driver_unregister(&msm_auxpcm_resource);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = platform_driver_register(&msm_dai_q6_dev);
|
||||
if (rc) {
|
||||
pr_err("%s: fail to register dai q6 dev driver", __func__);
|
||||
platform_driver_unregister(&msm_dai_q6);
|
||||
platform_driver_unregister(&msm_auxpcm_dev);
|
||||
platform_driver_unregister(&msm_auxpcm_resource);
|
||||
goto fail;
|
||||
}
|
||||
fail:
|
||||
return rc;
|
||||
@@ -534,6 +1168,8 @@ module_init(msm_dai_q6_init);
|
||||
|
||||
static void __exit msm_dai_q6_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&msm_dai_q6_dev);
|
||||
platform_driver_unregister(&msm_dai_q6);
|
||||
platform_driver_unregister(&msm_auxpcm_dev);
|
||||
platform_driver_unregister(&msm_auxpcm_resource);
|
||||
}
|
||||
|
||||
@@ -217,11 +217,12 @@ void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id,
|
||||
fe_dai_map[fedai_id][session_type] = dspst_id;
|
||||
for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
|
||||
if (!is_be_dai_extproc(i) &&
|
||||
(afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
|
||||
(msm_bedais[i].active) &&
|
||||
(test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
|
||||
(afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
|
||||
(msm_bedais[i].active) &&
|
||||
(test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
|
||||
mode = afe_get_port_type(msm_bedais[i].port_id);
|
||||
/*adm_connect_afe_port needs to be called*/
|
||||
adm_connect_afe_port(mode, dspst_id,
|
||||
msm_bedais[i].port_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/atomic.h>
|
||||
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include <mach/qdsp6v2/audio_acdb.h>
|
||||
#include <mach/qdsp6v2/rtac.h>
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <mach/qdsp6v2/apr.h>
|
||||
#include <sound/q6adm-v2.h>
|
||||
#include <sound/q6audio-v2.h>
|
||||
|
||||
#include <sound/q6afe-v2.h>
|
||||
|
||||
#define TIMEOUT_MS 1000
|
||||
|
||||
@@ -78,7 +78,7 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
|
||||
return 0;
|
||||
}
|
||||
if (data->opcode == APR_BASIC_RSP_RESULT) {
|
||||
pr_debug("APR_BASIC_RSP_RESULT\n");
|
||||
pr_debug("APR_BASIC_RSP_RESULT id %x\n", payload[0]);
|
||||
switch (payload[0]) {
|
||||
case ADM_CMD_SET_PP_PARAMS_V5:
|
||||
if (rtac_make_adm_callback(
|
||||
@@ -142,6 +142,76 @@ static void send_adm_cal(int port_id, int path)
|
||||
pr_debug("%s\n", __func__);
|
||||
}
|
||||
|
||||
int adm_connect_afe_port(int mode, int session_id, int port_id)
|
||||
{
|
||||
struct adm_cmd_connect_afe_port_v5 cmd;
|
||||
int ret = 0;
|
||||
int index;
|
||||
|
||||
pr_debug("%s: port %d session id:%d mode:%d\n", __func__,
|
||||
port_id, session_id, mode);
|
||||
|
||||
port_id = afe_convert_virtual_to_portid(port_id);
|
||||
|
||||
if (afe_validate_port(port_id) < 0) {
|
||||
pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (this_adm.apr == NULL) {
|
||||
this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
|
||||
0xFFFFFFFF, &this_adm);
|
||||
if (this_adm.apr == NULL) {
|
||||
pr_err("%s: Unable to register ADM\n", __func__);
|
||||
ret = -ENODEV;
|
||||
return ret;
|
||||
}
|
||||
rtac_set_adm_handle(this_adm.apr);
|
||||
}
|
||||
index = afe_get_port_index(port_id);
|
||||
pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
|
||||
|
||||
cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
||||
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
|
||||
cmd.hdr.pkt_size = sizeof(cmd);
|
||||
cmd.hdr.src_svc = APR_SVC_ADM;
|
||||
cmd.hdr.src_domain = APR_DOMAIN_APPS;
|
||||
cmd.hdr.src_port = port_id;
|
||||
cmd.hdr.dest_svc = APR_SVC_ADM;
|
||||
cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
|
||||
cmd.hdr.dest_port = port_id;
|
||||
cmd.hdr.token = port_id;
|
||||
cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT_V5;
|
||||
|
||||
cmd.mode = mode;
|
||||
cmd.session_id = session_id;
|
||||
cmd.afe_port_id = port_id;
|
||||
|
||||
atomic_set(&this_adm.copp_stat[index], 0);
|
||||
ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
|
||||
if (ret < 0) {
|
||||
pr_err("%s:ADM enable for port %d failed\n",
|
||||
__func__, port_id);
|
||||
ret = -EINVAL;
|
||||
goto fail_cmd;
|
||||
}
|
||||
/* Wait for the callback with copp id */
|
||||
ret = wait_event_timeout(this_adm.wait[index],
|
||||
atomic_read(&this_adm.copp_stat[index]),
|
||||
msecs_to_jiffies(TIMEOUT_MS));
|
||||
if (!ret) {
|
||||
pr_err("%s ADM connect AFE failed for port %d\n", __func__,
|
||||
port_id);
|
||||
ret = -EINVAL;
|
||||
goto fail_cmd;
|
||||
}
|
||||
atomic_inc(&this_adm.copp_cnt[index]);
|
||||
return 0;
|
||||
|
||||
fail_cmd:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int adm_open(int port_id, int path, int rate, int channel_mode, int topology)
|
||||
{
|
||||
struct adm_cmd_device_open_v5 open;
|
||||
|
||||
@@ -144,6 +144,9 @@ int afe_get_port_type(u16 port_id)
|
||||
case HDMI_RX:
|
||||
case SLIMBUS_0_RX:
|
||||
case SLIMBUS_1_RX:
|
||||
case SLIMBUS_2_RX:
|
||||
case SLIMBUS_3_RX:
|
||||
case SLIMBUS_4_RX:
|
||||
case INT_BT_SCO_RX:
|
||||
case INT_BT_A2DP_RX:
|
||||
case INT_FM_RX:
|
||||
@@ -160,6 +163,9 @@ int afe_get_port_type(u16 port_id)
|
||||
case VOICE_RECORD_TX:
|
||||
case SLIMBUS_0_TX:
|
||||
case SLIMBUS_1_TX:
|
||||
case SLIMBUS_2_TX:
|
||||
case SLIMBUS_3_TX:
|
||||
case SLIMBUS_4_TX:
|
||||
case INT_FM_TX:
|
||||
case VOICE_RECORD_RX:
|
||||
case INT_BT_SCO_TX:
|
||||
@@ -168,6 +174,7 @@ int afe_get_port_type(u16 port_id)
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_ON(1);
|
||||
pr_err("%s: invalid port id %d\n", __func__, port_id);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
@@ -255,7 +262,6 @@ int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
pr_err("%s: %d %d\n", __func__, port_id, rate);
|
||||
index = q6audio_get_port_index(port_id);
|
||||
if (q6audio_validate_port(port_id) < 0)
|
||||
return -EINVAL;
|
||||
@@ -279,11 +285,11 @@ int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
|
||||
|
||||
config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
|
||||
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
|
||||
config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
|
||||
config.hdr.pkt_size = sizeof(config);
|
||||
config.hdr.src_port = 0;
|
||||
config.hdr.dest_port = 0;
|
||||
|
||||
config.hdr.token = index;
|
||||
|
||||
switch (port_id) {
|
||||
case PRIMARY_I2S_RX:
|
||||
case PRIMARY_I2S_TX:
|
||||
@@ -320,15 +326,15 @@ int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
|
||||
goto fail_cmd;
|
||||
}
|
||||
config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
|
||||
config.param.port_id = port_id;
|
||||
config.param.payload_size = (afe_sizeof_cfg_cmd(port_id) +
|
||||
sizeof(struct afe_port_param_data_v2));
|
||||
config.param.port_id = q6audio_get_port_id(port_id);
|
||||
config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
|
||||
sizeof(config.param);
|
||||
config.param.payload_address_lsw = 0x00;
|
||||
config.param.payload_address_msw = 0x00;
|
||||
config.param.mem_map_handle = 0x00;
|
||||
config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
|
||||
config.pdata.param_id = cfg_type;
|
||||
config.pdata.param_size = afe_sizeof_cfg_cmd(port_id);
|
||||
config.pdata.param_size = sizeof(config.port);
|
||||
|
||||
config.port = *afe_config;
|
||||
|
||||
@@ -348,9 +354,11 @@ int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
|
||||
start.hdr.pkt_size = sizeof(start);
|
||||
start.hdr.src_port = 0;
|
||||
start.hdr.dest_port = 0;
|
||||
start.hdr.token = 0;
|
||||
start.hdr.token = index;
|
||||
start.hdr.opcode = AFE_PORT_CMD_DEVICE_START;
|
||||
start.port_id = port_id;
|
||||
start.port_id = q6audio_get_port_id(port_id);
|
||||
pr_debug("%s: cmd device start opcode[0x%x] port id[0x%x]\n",
|
||||
__func__, start.hdr.opcode, start.port_id);
|
||||
|
||||
ret = apr_send_pkt(this_afe.apr, (uint32_t *) &start);
|
||||
|
||||
@@ -367,6 +375,45 @@ fail_cmd:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int afe_get_port_index(u16 port_id)
|
||||
{
|
||||
switch (port_id) {
|
||||
case PRIMARY_I2S_RX: return IDX_PRIMARY_I2S_RX;
|
||||
case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
|
||||
case PCM_RX: return IDX_PCM_RX;
|
||||
case PCM_TX: return IDX_PCM_TX;
|
||||
case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
|
||||
case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
|
||||
case MI2S_RX: return IDX_MI2S_RX;
|
||||
case MI2S_TX: return IDX_MI2S_TX;
|
||||
case HDMI_RX: return IDX_HDMI_RX;
|
||||
case RSVD_2: return IDX_RSVD_2;
|
||||
case RSVD_3: return IDX_RSVD_3;
|
||||
case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
|
||||
case VOICE_RECORD_RX: return IDX_VOICE_RECORD_RX;
|
||||
case VOICE_RECORD_TX: return IDX_VOICE_RECORD_TX;
|
||||
case VOICE_PLAYBACK_TX: return IDX_VOICE_PLAYBACK_TX;
|
||||
case SLIMBUS_0_RX: return IDX_SLIMBUS_0_RX;
|
||||
case SLIMBUS_0_TX: return IDX_SLIMBUS_0_TX;
|
||||
case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
|
||||
case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
|
||||
case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
|
||||
case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
|
||||
case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
|
||||
case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
|
||||
case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
|
||||
case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
|
||||
case INT_FM_RX: return IDX_INT_FM_RX;
|
||||
case INT_FM_TX: return IDX_INT_FM_TX;
|
||||
case RT_PROXY_PORT_001_RX: return IDX_RT_PROXY_PORT_001_RX;
|
||||
case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX;
|
||||
case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX;
|
||||
case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
|
||||
|
||||
default: return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int afe_open(u16 port_id,
|
||||
union afe_port_config *afe_config, int rate)
|
||||
{
|
||||
@@ -1469,6 +1516,75 @@ fail_cmd:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int afe_validate_port(u16 port_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (port_id) {
|
||||
case PRIMARY_I2S_RX:
|
||||
case PRIMARY_I2S_TX:
|
||||
case PCM_RX:
|
||||
case PCM_TX:
|
||||
case SECONDARY_I2S_RX:
|
||||
case SECONDARY_I2S_TX:
|
||||
case MI2S_RX:
|
||||
case MI2S_TX:
|
||||
case HDMI_RX:
|
||||
case RSVD_2:
|
||||
case RSVD_3:
|
||||
case DIGI_MIC_TX:
|
||||
case VOICE_RECORD_RX:
|
||||
case VOICE_RECORD_TX:
|
||||
case VOICE_PLAYBACK_TX:
|
||||
case SLIMBUS_0_RX:
|
||||
case SLIMBUS_0_TX:
|
||||
case SLIMBUS_1_RX:
|
||||
case SLIMBUS_1_TX:
|
||||
case SLIMBUS_2_RX:
|
||||
case SLIMBUS_2_TX:
|
||||
case SLIMBUS_3_RX:
|
||||
case INT_BT_SCO_RX:
|
||||
case INT_BT_SCO_TX:
|
||||
case INT_BT_A2DP_RX:
|
||||
case INT_FM_RX:
|
||||
case INT_FM_TX:
|
||||
case RT_PROXY_PORT_001_RX:
|
||||
case RT_PROXY_PORT_001_TX:
|
||||
case SLIMBUS_4_RX:
|
||||
case SLIMBUS_4_TX:
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int afe_convert_virtual_to_portid(u16 port_id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* if port_id is virtual, convert to physical..
|
||||
* if port_id is already physical, return physical
|
||||
*/
|
||||
if (afe_validate_port(port_id) < 0) {
|
||||
if (port_id == RT_PROXY_DAI_001_RX ||
|
||||
port_id == RT_PROXY_DAI_001_TX ||
|
||||
port_id == RT_PROXY_DAI_002_RX ||
|
||||
port_id == RT_PROXY_DAI_002_TX)
|
||||
ret = VIRTUAL_ID_TO_PORTID(port_id);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
} else
|
||||
ret = port_id;
|
||||
|
||||
return ret;
|
||||
}
|
||||
int afe_port_stop_nowait(int port_id)
|
||||
{
|
||||
struct afe_port_cmd_device_stop stop;
|
||||
|
||||
Reference in New Issue
Block a user