mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
ASoC: msm: Add compressed TX support
There is use case that the HDMI input goes through MI2S TX interface to ADSP. Add compressed TX support for this use case. Change-Id: I510e3e63b68ea1887e4c99ebf1c6f76112abbed5 Signed-off-by: Subhash Chandra Bose Naripeddy <snariped@codeaurora.org>
This commit is contained in:
parent
311882694b
commit
1cd3eb87ac
9 changed files with 403 additions and 68 deletions
|
@ -1145,6 +1145,13 @@ struct asm_stream_cmd_open_read {
|
|||
#define ASM_ENCDEC_IMMDIATE_DECODE 0x00010C14
|
||||
#define ASM_ENCDEC_CFG_BLK 0x00010C2C
|
||||
|
||||
#define ASM_STREAM_CMD_OPEN_READ_COMPRESSED 0x00010D95
|
||||
struct asm_stream_cmd_open_read_compressed {
|
||||
struct apr_hdr hdr;
|
||||
u32 uMode;
|
||||
u32 frame_per_buf;
|
||||
} __packed;
|
||||
|
||||
#define ASM_STREAM_CMD_OPEN_WRITE 0x00010BCA
|
||||
struct asm_stream_cmd_open_write {
|
||||
struct apr_hdr hdr;
|
||||
|
@ -1185,6 +1192,17 @@ struct adm_cmd_connect_afe_port {
|
|||
u16 afe_port_id;
|
||||
} __packed;
|
||||
|
||||
#define ADM_CMD_CONNECT_AFE_PORT_V2 0x00010332
|
||||
|
||||
struct adm_cmd_connect_afe_port_v2 {
|
||||
struct apr_hdr hdr;
|
||||
u8 mode; /*mode represent the interface is for RX or TX*/
|
||||
u8 session_id; /*ASM session ID*/
|
||||
u16 afe_port_id;
|
||||
u32 num_channels;
|
||||
u32 sampleing_rate;
|
||||
} __packed;
|
||||
|
||||
#define ASM_STREAM_CMD_SET_ENCDEC_PARAM 0x00010C10
|
||||
#define ASM_STREAM_CMD_GET_ENCDEC_PARAM 0x00010C11
|
||||
#define ASM_ENCDEC_CFG_BLK_ID 0x00010C2C
|
||||
|
|
|
@ -122,6 +122,16 @@ struct snd_compr_codec_caps {
|
|||
struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct snd_compr_audio_info: compressed input audio information
|
||||
* @frame_size: legth of the encoded frame with valid data
|
||||
* @reserved: reserved for furture use
|
||||
*/
|
||||
struct snd_compr_audio_info {
|
||||
uint32_t frame_size;
|
||||
uint32_t reserved[15];
|
||||
};
|
||||
|
||||
/**
|
||||
* compress path ioctl definitions
|
||||
* SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
|
||||
|
|
|
@ -180,6 +180,8 @@ int q6asm_audio_client_buf_free_contiguous(unsigned int dir,
|
|||
|
||||
int q6asm_open_read(struct audio_client *ac, uint32_t format);
|
||||
|
||||
int q6asm_open_read_compressed(struct audio_client *ac, uint32_t format);
|
||||
|
||||
int q6asm_open_write(struct audio_client *ac, uint32_t format);
|
||||
|
||||
int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format);
|
||||
|
|
|
@ -850,7 +850,7 @@ static int msm_mi2s_free_gpios(void)
|
|||
static void msm_mi2s_shutdown(struct snd_pcm_substream *substream)
|
||||
{
|
||||
if (mi2s_bit_clk) {
|
||||
clk_disable(mi2s_bit_clk);
|
||||
clk_disable_unprepare(mi2s_bit_clk);
|
||||
clk_put(mi2s_bit_clk);
|
||||
mi2s_bit_clk = NULL;
|
||||
}
|
||||
|
@ -892,7 +892,7 @@ static int msm_mi2s_startup(struct snd_pcm_substream *substream)
|
|||
if (IS_ERR(mi2s_bit_clk))
|
||||
return PTR_ERR(mi2s_bit_clk);
|
||||
clk_set_rate(mi2s_bit_clk, 0);
|
||||
ret = clk_enable(mi2s_bit_clk);
|
||||
ret = clk_prepare_enable(mi2s_bit_clk);
|
||||
if (IS_ERR_VALUE(ret)) {
|
||||
pr_err("Unable to enable mi2s_bit_clk\n");
|
||||
clk_put(mi2s_bit_clk);
|
||||
|
|
|
@ -34,6 +34,13 @@
|
|||
#include "msm-compr-q6.h"
|
||||
#include "msm-pcm-routing.h"
|
||||
|
||||
#define COMPRE_CAPTURE_NUM_PERIODS 16
|
||||
/* Allocate the worst case frame size for compressed audio */
|
||||
#define COMPRE_CAPTURE_HEADER_SIZE (sizeof(struct snd_compr_audio_info))
|
||||
#define COMPRE_CAPTURE_MAX_FRAME_SIZE (6144)
|
||||
#define COMPRE_CAPTURE_PERIOD_SIZE (COMPRE_CAPTURE_MAX_FRAME_SIZE + \
|
||||
COMPRE_CAPTURE_HEADER_SIZE)
|
||||
|
||||
struct snd_msm {
|
||||
struct msm_audio *prtd;
|
||||
unsigned volume;
|
||||
|
@ -42,6 +49,27 @@ static struct snd_msm compressed_audio = {NULL, 0x2000} ;
|
|||
|
||||
static struct audio_locks the_locks;
|
||||
|
||||
static struct snd_pcm_hardware msm_compr_hardware_capture = {
|
||||
.info = (SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 48000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 8,
|
||||
.buffer_bytes_max =
|
||||
COMPRE_CAPTURE_PERIOD_SIZE * COMPRE_CAPTURE_NUM_PERIODS ,
|
||||
.period_bytes_min = COMPRE_CAPTURE_PERIOD_SIZE,
|
||||
.period_bytes_max = COMPRE_CAPTURE_PERIOD_SIZE,
|
||||
.periods_min = COMPRE_CAPTURE_NUM_PERIODS,
|
||||
.periods_max = COMPRE_CAPTURE_NUM_PERIODS,
|
||||
.fifo_size = 0,
|
||||
};
|
||||
|
||||
static struct snd_pcm_hardware msm_compr_hardware_playback = {
|
||||
.info = (SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
|
@ -81,7 +109,9 @@ static void compr_event_handler(uint32_t opcode,
|
|||
struct snd_pcm_substream *substream = prtd->substream;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct audio_aio_write_param param;
|
||||
struct audio_aio_read_param read_param;
|
||||
struct audio_buffer *buf = NULL;
|
||||
uint32_t *ptrmem = (uint32_t *)payload;
|
||||
int i = 0;
|
||||
|
||||
pr_debug("%s opcode =%08x\n", __func__, opcode);
|
||||
|
@ -138,9 +168,53 @@ static void compr_event_handler(uint32_t opcode,
|
|||
prtd->cmd_ack = 1;
|
||||
wake_up(&the_locks.eos_wait);
|
||||
break;
|
||||
case ASM_DATA_EVENT_READ_DONE: {
|
||||
pr_debug("ASM_DATA_EVENT_READ_DONE\n");
|
||||
pr_debug("buf = %p, data = 0x%X, *data = %p,\n"
|
||||
"prtd->pcm_irq_pos = %d\n",
|
||||
prtd->audio_client->port[OUT].buf,
|
||||
*(uint32_t *)prtd->audio_client->port[OUT].buf->data,
|
||||
prtd->audio_client->port[OUT].buf->data,
|
||||
prtd->pcm_irq_pos);
|
||||
|
||||
memcpy(prtd->audio_client->port[OUT].buf->data +
|
||||
prtd->pcm_irq_pos, (ptrmem + 2),
|
||||
COMPRE_CAPTURE_HEADER_SIZE);
|
||||
pr_debug("buf = %p, updated data = 0x%X, *data = %p\n",
|
||||
prtd->audio_client->port[OUT].buf,
|
||||
*(uint32_t *)(prtd->audio_client->port[OUT].buf->data +
|
||||
prtd->pcm_irq_pos),
|
||||
prtd->audio_client->port[OUT].buf->data);
|
||||
if (!atomic_read(&prtd->start))
|
||||
break;
|
||||
pr_debug("frame size=%d, buffer = 0x%X\n", ptrmem[2],
|
||||
ptrmem[1]);
|
||||
if (ptrmem[2] > COMPRE_CAPTURE_MAX_FRAME_SIZE) {
|
||||
pr_err("Frame length exceeded the max length");
|
||||
break;
|
||||
}
|
||||
buf = prtd->audio_client->port[OUT].buf;
|
||||
pr_debug("pcm_irq_pos=%d, buf[0].phys = 0x%X\n",
|
||||
prtd->pcm_irq_pos, (uint32_t)buf[0].phys);
|
||||
read_param.len = prtd->pcm_count - COMPRE_CAPTURE_HEADER_SIZE ;
|
||||
read_param.paddr = (unsigned long)(buf[0].phys) +
|
||||
prtd->pcm_irq_pos + COMPRE_CAPTURE_HEADER_SIZE;
|
||||
prtd->pcm_irq_pos += prtd->pcm_count;
|
||||
|
||||
if (atomic_read(&prtd->start))
|
||||
snd_pcm_period_elapsed(substream);
|
||||
|
||||
q6asm_async_read(prtd->audio_client, &read_param);
|
||||
break;
|
||||
}
|
||||
case APR_BASIC_RSP_RESULT: {
|
||||
switch (payload[0]) {
|
||||
case ASM_SESSION_CMD_RUN: {
|
||||
if (substream->stream
|
||||
!= SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
atomic_set(&prtd->start, 1);
|
||||
break;
|
||||
}
|
||||
if (!atomic_read(&prtd->pending_buffer))
|
||||
break;
|
||||
pr_debug("%s:writing %d bytes"
|
||||
|
@ -286,6 +360,44 @@ static int msm_compr_playback_prepare(struct snd_pcm_substream *substream)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int msm_compr_capture_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct compr_audio *compr = runtime->private_data;
|
||||
struct msm_audio *prtd = &compr->prtd;
|
||||
struct audio_buffer *buf = prtd->audio_client->port[OUT].buf;
|
||||
struct audio_aio_read_param read_param;
|
||||
int ret = 0;
|
||||
int i;
|
||||
prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
|
||||
prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
|
||||
prtd->pcm_irq_pos = 0;
|
||||
|
||||
/* rate and channels are sent to audio driver */
|
||||
prtd->samp_rate = runtime->rate;
|
||||
prtd->channel_mode = runtime->channels;
|
||||
|
||||
if (prtd->enabled)
|
||||
return ret;
|
||||
read_param.len = prtd->pcm_count - COMPRE_CAPTURE_HEADER_SIZE;
|
||||
pr_debug("%s: Samp_rate = %d, Channel = %d, pcm_size = %d,\n"
|
||||
"pcm_count = %d, periods = %d\n",
|
||||
__func__, prtd->samp_rate, prtd->channel_mode,
|
||||
prtd->pcm_size, prtd->pcm_count, runtime->periods);
|
||||
|
||||
for (i = 0; i < runtime->periods; i++) {
|
||||
read_param.uid = i;
|
||||
read_param.paddr = ((unsigned long)(buf[i].phys) +
|
||||
COMPRE_CAPTURE_HEADER_SIZE);
|
||||
q6asm_async_read(prtd->audio_client, &read_param);
|
||||
}
|
||||
prtd->periods = runtime->periods;
|
||||
|
||||
prtd->enabled = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_compr_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -298,8 +410,15 @@ static int msm_compr_trigger(struct snd_pcm_substream *substream, int cmd)
|
|||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
prtd->pcm_irq_pos = 0;
|
||||
if (compr->info.codec_param.codec.id ==
|
||||
SND_AUDIOCODEC_AC3_PASS_THROUGH) {
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
if (compr->info.codec_param.codec.id ==
|
||||
SND_AUDIOCODEC_AC3_PASS_THROUGH) {
|
||||
msm_pcm_routing_reg_psthr_stream(
|
||||
soc_prtd->dai_link->be_id,
|
||||
prtd->session_id, substream->stream,
|
||||
1);
|
||||
}
|
||||
} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
msm_pcm_routing_reg_psthr_stream(
|
||||
soc_prtd->dai_link->be_id,
|
||||
prtd->session_id, substream->stream, 1);
|
||||
|
@ -312,11 +431,19 @@ static int msm_compr_trigger(struct snd_pcm_substream *substream, int cmd)
|
|||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
|
||||
if (compr->info.codec_param.codec.id ==
|
||||
SND_AUDIOCODEC_AC3_PASS_THROUGH) {
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
if (compr->info.codec_param.codec.id ==
|
||||
SND_AUDIOCODEC_AC3_PASS_THROUGH) {
|
||||
msm_pcm_routing_reg_psthr_stream(
|
||||
soc_prtd->dai_link->be_id,
|
||||
prtd->session_id, substream->stream,
|
||||
0);
|
||||
}
|
||||
} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
msm_pcm_routing_reg_psthr_stream(
|
||||
soc_prtd->dai_link->be_id,
|
||||
prtd->session_id, substream->stream, 0);
|
||||
prtd->session_id, substream->stream,
|
||||
0);
|
||||
}
|
||||
atomic_set(&prtd->start, 0);
|
||||
break;
|
||||
|
@ -370,10 +497,6 @@ static int msm_compr_open(struct snd_pcm_substream *substream)
|
|||
.rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
|
||||
};
|
||||
|
||||
/* Capture path */
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
return -EINVAL;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
compr = kzalloc(sizeof(struct compr_audio), GFP_KERNEL);
|
||||
if (compr == NULL) {
|
||||
|
@ -389,13 +512,18 @@ static int msm_compr_open(struct snd_pcm_substream *substream)
|
|||
kfree(prtd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
runtime->hw = msm_compr_hardware_playback;
|
||||
|
||||
pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session);
|
||||
|
||||
prtd->session_id = prtd->audio_client->session;
|
||||
|
||||
prtd->cmd_ack = 1;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
runtime->hw = msm_compr_hardware_playback;
|
||||
prtd->cmd_ack = 1;
|
||||
} else {
|
||||
runtime->hw = msm_compr_hardware_capture;
|
||||
}
|
||||
|
||||
|
||||
ret = snd_pcm_hw_constraint_list(runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_RATE,
|
||||
|
@ -410,7 +538,8 @@ static int msm_compr_open(struct snd_pcm_substream *substream)
|
|||
|
||||
prtd->dsp_cnt = 0;
|
||||
atomic_set(&prtd->pending_buffer, 1);
|
||||
compr->codec = FORMAT_MP3;
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
compr->codec = FORMAT_MP3;
|
||||
populate_codec_list(compr, runtime);
|
||||
runtime->private_data = compr;
|
||||
compressed_audio.prtd = &compr->prtd;
|
||||
|
@ -473,6 +602,27 @@ static int msm_compr_playback_close(struct snd_pcm_substream *substream)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int msm_compr_capture_close(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
|
||||
struct compr_audio *compr = runtime->private_data;
|
||||
struct msm_audio *prtd = &compr->prtd;
|
||||
int dir = OUT;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
atomic_set(&prtd->pending_buffer, 0);
|
||||
q6asm_cmd(prtd->audio_client, CMD_CLOSE);
|
||||
q6asm_audio_client_buf_free_contiguous(dir,
|
||||
prtd->audio_client);
|
||||
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
|
||||
SNDRV_PCM_STREAM_CAPTURE);
|
||||
q6asm_audio_client_free(prtd->audio_client);
|
||||
kfree(prtd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_compr_close(struct snd_pcm_substream *substream)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -480,7 +630,7 @@ static int msm_compr_close(struct snd_pcm_substream *substream)
|
|||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
ret = msm_compr_playback_close(substream);
|
||||
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
ret = EINVAL;
|
||||
ret = msm_compr_capture_close(substream);
|
||||
return ret;
|
||||
}
|
||||
static int msm_compr_prepare(struct snd_pcm_substream *substream)
|
||||
|
@ -490,7 +640,7 @@ static int msm_compr_prepare(struct snd_pcm_substream *substream)
|
|||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
ret = msm_compr_playback_prepare(substream);
|
||||
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
ret = EINVAL;
|
||||
ret = msm_compr_capture_prepare(substream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -504,7 +654,10 @@ static snd_pcm_uframes_t msm_compr_pointer(struct snd_pcm_substream *substream)
|
|||
if (prtd->pcm_irq_pos >= prtd->pcm_size)
|
||||
prtd->pcm_irq_pos = 0;
|
||||
|
||||
pr_debug("pcm_irq_pos = %d\n", prtd->pcm_irq_pos);
|
||||
pr_debug("%s: pcm_irq_pos = %d, pcm_size = %d, sample_bits = %d,\n"
|
||||
"frame_bits = %d\n", __func__, prtd->pcm_irq_pos,
|
||||
prtd->pcm_size, runtime->sample_bits,
|
||||
runtime->frame_bits);
|
||||
return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
|
||||
}
|
||||
|
||||
|
@ -546,28 +699,44 @@ static int msm_compr_hw_params(struct snd_pcm_substream *substream,
|
|||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
dir = IN;
|
||||
else
|
||||
return -EINVAL;
|
||||
dir = OUT;
|
||||
|
||||
switch (compr->info.codec_param.codec.id) {
|
||||
case SND_AUDIOCODEC_AC3_PASS_THROUGH:
|
||||
ret = q6asm_open_write_compressed(prtd->audio_client,
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
switch (compr->info.codec_param.codec.id) {
|
||||
case SND_AUDIOCODEC_AC3_PASS_THROUGH:
|
||||
ret = q6asm_open_write_compressed(prtd->audio_client,
|
||||
compr->codec);
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Session out open failed\n",
|
||||
__func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = q6asm_open_write(prtd->audio_client,
|
||||
compr->codec);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Session out open failed\n",
|
||||
__func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
msm_pcm_routing_reg_phy_stream(
|
||||
soc_prtd->dai_link->be_id,
|
||||
prtd->session_id, substream->stream);
|
||||
|
||||
break;
|
||||
}
|
||||
} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
ret = q6asm_open_read_compressed(prtd->audio_client,
|
||||
compr->codec);
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("%s: compressed Session out open failed\n",
|
||||
__func__);
|
||||
__func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = q6asm_open_write(prtd->audio_client, compr->codec);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Session out open failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
|
||||
prtd->session_id, substream->stream);
|
||||
|
||||
break;
|
||||
}
|
||||
ret = q6asm_set_io_mode(prtd->audio_client, ASYNC_IO_MODE);
|
||||
if (ret < 0) {
|
||||
|
@ -586,13 +755,17 @@ static int msm_compr_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
buf = prtd->audio_client->port[dir].buf;
|
||||
|
||||
pr_debug("%s:buf = %p\n", __func__, buf);
|
||||
dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
|
||||
dma_buf->dev.dev = substream->pcm->card->dev;
|
||||
dma_buf->private_data = NULL;
|
||||
dma_buf->area = buf[0].data;
|
||||
dma_buf->addr = buf[0].phys;
|
||||
dma_buf->bytes = runtime->hw.buffer_bytes_max;
|
||||
|
||||
pr_debug("%s: buf[%p]dma_buf->area[%p]dma_buf->addr[%p]\n"
|
||||
"dma_buf->bytes[%d]\n", __func__,
|
||||
(void *)buf, (void *)dma_buf->area,
|
||||
(void *)dma_buf->addr, dma_buf->bytes);
|
||||
if (!dma_buf->area)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -176,6 +176,17 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
|
|||
.rate_min = 8000,
|
||||
.rate_max = 48000,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "MultiMedia4 Capture",
|
||||
.aif_name = "MM_UL4",
|
||||
.rates = (SNDRV_PCM_RATE_8000_48000|
|
||||
SNDRV_PCM_RATE_KNOT),
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
.channels_min = 1,
|
||||
.channels_max = 8,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 48000,
|
||||
},
|
||||
.ops = &msm_fe_Multimedia_dai_ops,
|
||||
.name = "MultiMedia4",
|
||||
},
|
||||
|
|
|
@ -40,9 +40,14 @@ struct msm_dai_q6_dai_data {
|
|||
union afe_port_config port_config;
|
||||
};
|
||||
|
||||
struct msm_dai_q6_mi2s_dai_config {
|
||||
u16 pdata_mi2s_lines;
|
||||
struct msm_dai_q6_dai_data mi2s_dai_data;
|
||||
};
|
||||
|
||||
struct msm_dai_q6_mi2s_dai_data {
|
||||
struct msm_dai_q6_dai_data tx_dai;
|
||||
struct msm_dai_q6_dai_data rx_dai;
|
||||
struct msm_dai_q6_mi2s_dai_config tx_dai;
|
||||
struct msm_dai_q6_mi2s_dai_config rx_dai;
|
||||
struct snd_pcm_hw_constraint_list rate_constraint;
|
||||
struct snd_pcm_hw_constraint_list bitwidth_constraint;
|
||||
};
|
||||
|
@ -86,8 +91,8 @@ static int msm_dai_q6_mi2s_format_get(struct snd_kcontrol *kcontrol,
|
|||
static const char *mi2s_format[] = {
|
||||
"LPCM",
|
||||
"Compr",
|
||||
"60958-LPCM",
|
||||
"60958-Compr"};
|
||||
"LPCM-60958",
|
||||
"Compr-60958"};
|
||||
|
||||
static const struct soc_enum mi2s_config_enum[] = {
|
||||
SOC_ENUM_SINGLE_EXT(4, mi2s_format),
|
||||
|
@ -143,21 +148,63 @@ static int msm_dai_q6_mi2s_hw_params(struct snd_pcm_substream *substream,
|
|||
{
|
||||
struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
|
||||
dev_get_drvdata(dai->dev);
|
||||
struct msm_dai_q6_dai_data *dai_data =
|
||||
struct msm_dai_q6_mi2s_dai_config *mi2s_dai_config =
|
||||
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
|
||||
&mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
|
||||
struct msm_dai_q6_dai_data *dai_data = &mi2s_dai_config->mi2s_dai_data;
|
||||
|
||||
dai_data->channels = params_channels(params);
|
||||
switch (dai_data->channels) {
|
||||
case 2:
|
||||
dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
|
||||
case 8:
|
||||
case 7:
|
||||
if (mi2s_dai_config->pdata_mi2s_lines < AFE_I2S_8CHS)
|
||||
goto error_invalid_data;
|
||||
dai_data->port_config.mi2s.line = AFE_I2S_8CHS;
|
||||
break;
|
||||
case 6:
|
||||
case 5:
|
||||
if (mi2s_dai_config->pdata_mi2s_lines < AFE_I2S_6CHS)
|
||||
goto error_invalid_data;
|
||||
dai_data->port_config.mi2s.line = AFE_I2S_6CHS;
|
||||
break;
|
||||
case 4:
|
||||
case 3:
|
||||
if (mi2s_dai_config->pdata_mi2s_lines < AFE_I2S_QUAD01)
|
||||
goto error_invalid_data;
|
||||
if (mi2s_dai_config->pdata_mi2s_lines == AFE_I2S_QUAD23)
|
||||
dai_data->port_config.mi2s.line =
|
||||
mi2s_dai_config->pdata_mi2s_lines;
|
||||
else
|
||||
dai_data->port_config.mi2s.line = AFE_I2S_QUAD01;
|
||||
break;
|
||||
case 2:
|
||||
case 1:
|
||||
dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
|
||||
if (mi2s_dai_config->pdata_mi2s_lines < AFE_I2S_SD0)
|
||||
goto error_invalid_data;
|
||||
switch (mi2s_dai_config->pdata_mi2s_lines) {
|
||||
case AFE_I2S_SD0:
|
||||
case AFE_I2S_SD1:
|
||||
case AFE_I2S_SD2:
|
||||
case AFE_I2S_SD3:
|
||||
dai_data->port_config.mi2s.line =
|
||||
mi2s_dai_config->pdata_mi2s_lines;
|
||||
break;
|
||||
case AFE_I2S_QUAD01:
|
||||
case AFE_I2S_6CHS:
|
||||
case AFE_I2S_8CHS:
|
||||
dai_data->port_config.mi2s.line = AFE_I2S_SD0;
|
||||
break;
|
||||
case AFE_I2S_QUAD23:
|
||||
dai_data->port_config.mi2s.line = AFE_I2S_SD2;
|
||||
break;
|
||||
}
|
||||
if (dai_data->channels == 2)
|
||||
dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
|
||||
else
|
||||
dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
|
||||
break;
|
||||
default:
|
||||
pr_warn("greater than stereo has not been validated");
|
||||
break;
|
||||
goto error_invalid_data;
|
||||
}
|
||||
dai_data->rate = params_rate(params);
|
||||
dai_data->port_config.mi2s.bitwidth = 16;
|
||||
|
@ -166,7 +213,14 @@ static int msm_dai_q6_mi2s_hw_params(struct snd_pcm_substream *substream,
|
|||
mi2s_dai_data->rate_constraint.list = &dai_data->rate;
|
||||
mi2s_dai_data->bitwidth_constraint.list = &dai_data->bitwidth;
|
||||
}
|
||||
|
||||
pr_debug("%s: dai_data->channels = %d, line = %d\n", __func__,
|
||||
dai_data->channels, dai_data->port_config.mi2s.line);
|
||||
return 0;
|
||||
error_invalid_data:
|
||||
pr_err("%s: dai_data->channels = %d, line = %d\n", __func__,
|
||||
dai_data->channels, dai_data->port_config.mi2s.line);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int msm_dai_q6_mi2s_get_lineconfig(u16 sd_lines, u16 *config_ptr,
|
||||
|
@ -276,7 +330,9 @@ static int msm_dai_q6_mi2s_platform_data_validation(
|
|||
}
|
||||
|
||||
if (ch_cnt) {
|
||||
dai_data->rx_dai.port_config.mi2s.line = sdline_config;
|
||||
dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.line =
|
||||
sdline_config;
|
||||
dai_data->rx_dai.pdata_mi2s_lines = sdline_config;
|
||||
dai_driver->playback.channels_min = 1;
|
||||
dai_driver->playback.channels_max = ch_cnt << 1;
|
||||
} else {
|
||||
|
@ -292,7 +348,9 @@ static int msm_dai_q6_mi2s_platform_data_validation(
|
|||
}
|
||||
|
||||
if (ch_cnt) {
|
||||
dai_data->tx_dai.port_config.mi2s.line = sdline_config;
|
||||
dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.line =
|
||||
sdline_config;
|
||||
dai_data->tx_dai.pdata_mi2s_lines = sdline_config;
|
||||
dai_driver->capture.channels_min = 1;
|
||||
dai_driver->capture.channels_max = ch_cnt << 1;
|
||||
} else {
|
||||
|
@ -301,8 +359,8 @@ static int msm_dai_q6_mi2s_platform_data_validation(
|
|||
}
|
||||
|
||||
dev_info(&pdev->dev, "%s: playback sdline %x capture sdline %x\n",
|
||||
__func__, dai_data->rx_dai.port_config.mi2s.line,
|
||||
dai_data->tx_dai.port_config.mi2s.line);
|
||||
__func__, dai_data->rx_dai.pdata_mi2s_lines,
|
||||
dai_data->tx_dai.pdata_mi2s_lines);
|
||||
dev_info(&pdev->dev, "%s: playback ch_max %d capture ch_mx %d\n",
|
||||
__func__, dai_driver->playback.channels_max,
|
||||
dai_driver->capture.channels_max);
|
||||
|
@ -315,8 +373,10 @@ static int msm_dai_q6_mi2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
|||
struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
|
||||
dev_get_drvdata(dai->dev);
|
||||
|
||||
if (test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask) ||
|
||||
test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask)) {
|
||||
if (test_bit(STATUS_PORT_STARTED,
|
||||
mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask) ||
|
||||
test_bit(STATUS_PORT_STARTED,
|
||||
mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask)) {
|
||||
dev_err(dai->dev, "%s: err chg i2s mode while dai running",
|
||||
__func__);
|
||||
return -EPERM;
|
||||
|
@ -324,12 +384,12 @@ static int msm_dai_q6_mi2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
|||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
mi2s_dai_data->rx_dai.port_config.mi2s.ws = 1;
|
||||
mi2s_dai_data->tx_dai.port_config.mi2s.ws = 1;
|
||||
mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.ws = 1;
|
||||
mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.ws = 1;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
mi2s_dai_data->rx_dai.port_config.mi2s.ws = 0;
|
||||
mi2s_dai_data->tx_dai.port_config.mi2s.ws = 0;
|
||||
mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.ws = 0;
|
||||
mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.ws = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -345,7 +405,8 @@ static int msm_dai_q6_mi2s_prepare(struct snd_pcm_substream *substream,
|
|||
dev_get_drvdata(dai->dev);
|
||||
struct msm_dai_q6_dai_data *dai_data =
|
||||
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
|
||||
&mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
|
||||
&mi2s_dai_data->rx_dai.mi2s_dai_data :
|
||||
&mi2s_dai_data->tx_dai.mi2s_dai_data);
|
||||
int rc = 0;
|
||||
|
||||
if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
|
||||
|
@ -364,7 +425,8 @@ static int msm_dai_q6_mi2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||
dev_get_drvdata(dai->dev);
|
||||
struct msm_dai_q6_dai_data *dai_data =
|
||||
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
|
||||
&mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
|
||||
&mi2s_dai_data->rx_dai.mi2s_dai_data :
|
||||
&mi2s_dai_data->tx_dai.mi2s_dai_data);
|
||||
u16 port_id = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
|
||||
MI2S_RX : MI2S_TX);
|
||||
int rc = 0;
|
||||
|
@ -406,7 +468,8 @@ static void msm_dai_q6_mi2s_shutdown(struct snd_pcm_substream *substream,
|
|||
dev_get_drvdata(dai->dev);
|
||||
struct msm_dai_q6_dai_data *dai_data =
|
||||
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
|
||||
&mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
|
||||
&mi2s_dai_data->rx_dai.mi2s_dai_data :
|
||||
&mi2s_dai_data->tx_dai.mi2s_dai_data);
|
||||
u16 port_id = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
|
||||
MI2S_RX : MI2S_TX);
|
||||
int rc = 0;
|
||||
|
@ -418,8 +481,10 @@ static void msm_dai_q6_mi2s_shutdown(struct snd_pcm_substream *substream,
|
|||
clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
|
||||
}
|
||||
|
||||
if (!test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask) &&
|
||||
!test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask)) {
|
||||
if (!test_bit(STATUS_PORT_STARTED,
|
||||
mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask) &&
|
||||
!test_bit(STATUS_PORT_STARTED,
|
||||
mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask)) {
|
||||
mi2s_dai_data->rate_constraint.list = NULL;
|
||||
mi2s_dai_data->bitwidth_constraint.list = NULL;
|
||||
}
|
||||
|
@ -1268,9 +1333,9 @@ static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
|
|||
struct snd_kcontrol *kcontrol = NULL;
|
||||
int rc = 0;
|
||||
|
||||
if (mi2s_dai_data->rx_dai.port_config.mi2s.line) {
|
||||
if (mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.line) {
|
||||
kcontrol = snd_ctl_new1(&mi2s_config_controls[0],
|
||||
&mi2s_dai_data->rx_dai);
|
||||
&mi2s_dai_data->rx_dai.mi2s_dai_data);
|
||||
rc = snd_ctl_add(dai->card->snd_card, kcontrol);
|
||||
|
||||
if (IS_ERR_VALUE(rc)) {
|
||||
|
@ -1279,10 +1344,10 @@ static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
|
|||
}
|
||||
}
|
||||
|
||||
if (mi2s_dai_data->tx_dai.port_config.mi2s.line) {
|
||||
if (mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.line) {
|
||||
rc = snd_ctl_add(dai->card->snd_card,
|
||||
snd_ctl_new1(&mi2s_config_controls[2],
|
||||
&mi2s_dai_data->tx_dai));
|
||||
snd_ctl_new1(&mi2s_config_controls[2],
|
||||
&mi2s_dai_data->tx_dai.mi2s_dai_data));
|
||||
|
||||
if (IS_ERR_VALUE(rc)) {
|
||||
if (kcontrol)
|
||||
|
@ -1302,19 +1367,21 @@ static int msm_dai_q6_dai_mi2s_remove(struct snd_soc_dai *dai)
|
|||
int rc;
|
||||
|
||||
/* If AFE port is still up, close it */
|
||||
if (test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask)) {
|
||||
if (test_bit(STATUS_PORT_STARTED,
|
||||
mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask)) {
|
||||
rc = afe_close(MI2S_RX); /* can block */
|
||||
if (IS_ERR_VALUE(rc))
|
||||
dev_err(dai->dev, "fail to close MI2S_RX port\n");
|
||||
clear_bit(STATUS_PORT_STARTED,
|
||||
mi2s_dai_data->rx_dai.status_mask);
|
||||
mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask);
|
||||
}
|
||||
if (test_bit(STATUS_PORT_STARTED, mi2s_dai_data->tx_dai.status_mask)) {
|
||||
if (test_bit(STATUS_PORT_STARTED,
|
||||
mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask)) {
|
||||
rc = afe_close(MI2S_TX); /* can block */
|
||||
if (IS_ERR_VALUE(rc))
|
||||
dev_err(dai->dev, "fail to close MI2S_TX port\n");
|
||||
clear_bit(STATUS_PORT_STARTED,
|
||||
mi2s_dai_data->tx_dai.status_mask);
|
||||
mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask);
|
||||
}
|
||||
kfree(mi2s_dai_data);
|
||||
snd_soc_unregister_dai(dai->dev);
|
||||
|
@ -1966,6 +2033,8 @@ static __devinit int msm_dai_q6_mi2s_dev_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err_pdata:
|
||||
|
||||
dev_err(&pdev->dev, "fail to msm_dai_q6_mi2s_dev_probe\n");
|
||||
kfree(dai_data);
|
||||
rtn:
|
||||
return rc;
|
||||
|
|
|
@ -1352,6 +1352,13 @@ static const struct snd_kcontrol_new mmul2_mixer_controls[] = {
|
|||
msm_routing_put_audio_mixer),
|
||||
};
|
||||
|
||||
|
||||
static const struct snd_kcontrol_new mmul4_mixer_controls[] = {
|
||||
SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_MI2S_TX,
|
||||
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
|
||||
msm_routing_put_audio_mixer),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
|
||||
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX,
|
||||
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
|
||||
|
@ -1983,6 +1990,7 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
|
|||
SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, 0, 0, 0),
|
||||
SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
|
||||
SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
|
||||
SND_SOC_DAPM_AIF_IN("VoLTE_DL", "VoLTE Playback", 0, 0, 0, 0),
|
||||
|
@ -2080,6 +2088,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
|
|||
mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)),
|
||||
SND_SOC_DAPM_MIXER("MultiMedia2 Mixer", SND_SOC_NOPM, 0, 0,
|
||||
mmul2_mixer_controls, ARRAY_SIZE(mmul2_mixer_controls)),
|
||||
SND_SOC_DAPM_MIXER("MultiMedia4 Mixer", SND_SOC_NOPM, 0, 0,
|
||||
mmul4_mixer_controls, ARRAY_SIZE(mmul4_mixer_controls)),
|
||||
SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
|
||||
auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)),
|
||||
SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
|
||||
|
@ -2247,6 +2257,7 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
{"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
|
||||
{"MultiMedia1 Mixer", "MI2S_TX", "MI2S_TX"},
|
||||
{"MultiMedia2 Mixer", "MI2S_TX", "MI2S_TX"},
|
||||
{"MultiMedia4 Mixer", "MI2S_TX", "MI2S_TX"},
|
||||
{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
|
||||
{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
|
||||
{"MultiMedia1 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
|
||||
|
@ -2276,6 +2287,7 @@ static const struct snd_soc_dapm_route intercon[] = {
|
|||
{"MM_UL1", NULL, "MultiMedia1 Mixer"},
|
||||
{"MultiMedia2 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
|
||||
{"MM_UL2", NULL, "MultiMedia2 Mixer"},
|
||||
{"MM_UL4", NULL, "MultiMedia4 Mixer"},
|
||||
|
||||
{"AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
|
||||
{"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
|
||||
|
|
|
@ -737,6 +737,9 @@ int q6asm_audio_client_buf_alloc_contiguous(unsigned int dir,
|
|||
cnt++;
|
||||
}
|
||||
ac->port[dir].max_buf_cnt = cnt;
|
||||
|
||||
pr_debug("%s ac->port[%d].max_buf_cnt[%d]\n", __func__, dir,
|
||||
ac->port[dir].max_buf_cnt);
|
||||
mutex_unlock(&ac->cmd_lock);
|
||||
rc = q6asm_memory_map(ac, buf[0].phys, dir, bufsz, cnt);
|
||||
if (rc < 0) {
|
||||
|
@ -857,6 +860,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
|
|||
case ASM_DATA_CMD_MEDIA_FORMAT_UPDATE:
|
||||
case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
|
||||
case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
|
||||
case ASM_STREAM_CMD_OPEN_READ_COMPRESSED:
|
||||
if (atomic_read(&ac->cmd_state)) {
|
||||
atomic_set(&ac->cmd_state, 0);
|
||||
wake_up(&ac->cmd_wait);
|
||||
|
@ -1260,6 +1264,42 @@ fail_cmd:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
int q6asm_open_read_compressed(struct audio_client *ac, uint32_t format)
|
||||
{
|
||||
int rc = 0x00;
|
||||
struct asm_stream_cmd_open_read_compressed open;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
in_cont_index = 0;
|
||||
#endif
|
||||
if ((ac == NULL) || (ac->apr == NULL)) {
|
||||
pr_err("%s: APR handle NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
pr_debug("%s:session[%d]", __func__, ac->session);
|
||||
|
||||
q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
|
||||
open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ_COMPRESSED;
|
||||
/* hardcoded as following*/
|
||||
open.frame_per_buf = 1;
|
||||
open.uMode = 0;
|
||||
|
||||
rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
|
||||
if (rc < 0) {
|
||||
pr_err("open failed op[0x%x]rc[%d]\n", open.hdr.opcode, rc);
|
||||
goto fail_cmd;
|
||||
}
|
||||
rc = wait_event_timeout(ac->cmd_wait,
|
||||
(atomic_read(&ac->cmd_state) == 0), 5*HZ);
|
||||
if (!rc) {
|
||||
pr_err("%s: timeout. waited for OPEN_READ_COMPRESSED rc[%d]\n",
|
||||
__func__, rc);
|
||||
goto fail_cmd;
|
||||
}
|
||||
return 0;
|
||||
fail_cmd:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format)
|
||||
{
|
||||
int rc = 0x00;
|
||||
|
|
Loading…
Reference in a new issue