ASoc: msm: Add amr-wb/wb+ tunnel playback support

Update compress audio platform driver
to support amr-wb/wb+ tunnel mode playback.

Change-Id: I98d087db490441c57c8e2d4fe03a7e91b28e67fc
Signed-off-by: Ajit Khare <ajitk@codeaurora.org>
This commit is contained in:
Ajit Khare
2012-08-07 13:19:44 -07:00
committed by Stephen Boyd
parent 3fb13a4e2c
commit 9ebff212cd
4 changed files with 107 additions and 4 deletions

View File

@@ -978,6 +978,16 @@ struct asm_aac_cfg {
u32 sample_rate;
};
struct asm_amrwbplus_cfg {
u32 size_bytes;
u32 version;
u32 num_channels;
u32 amr_band_mode;
u32 amr_dtx_mode;
u32 amr_frame_fmt;
u32 amr_lsf_idx;
};
struct asm_flac_cfg {
u16 stream_info_present;
u16 min_blk_size;
@@ -1398,6 +1408,7 @@ struct asm_stream_media_format_update{
struct asm_flac_cfg flac_cfg;
struct asm_vorbis_cfg vorbis_cfg;
struct asm_multi_channel_pcm_fmt_blk multi_ch_pcm_cfg;
struct asm_amrwbplus_cfg amrwbplus_cfg;
} __attribute__((packed)) write_cfg;
} __attribute__((packed));

View File

@@ -288,6 +288,9 @@ int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
int q6asm_media_format_block_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg);
int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
struct asm_amrwbplus_cfg *cfg);
int q6asm_media_format_block_multi_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg);

View File

@@ -86,10 +86,10 @@ static struct snd_pcm_hardware msm_compr_hardware_playback = {
.channels_min = 1,
.channels_max = 8,
.buffer_bytes_max = 1200 * 1024 * 2,
.period_bytes_min = 4800,
.period_bytes_min = 2400,
.period_bytes_max = 1200 * 1024,
.periods_min = 2,
.periods_max = 512,
.periods_max = 1024,
.fifo_size = 0,
};
@@ -336,6 +336,7 @@ static int msm_compr_playback_prepare(struct snd_pcm_substream *substream)
struct asm_aac_cfg aac_cfg;
struct asm_wma_cfg wma_cfg;
struct asm_wmapro_cfg wma_pro_cfg;
struct asm_amrwbplus_cfg amrwb_cfg;
int ret;
pr_debug("compressed stream prepare\n");
@@ -433,6 +434,27 @@ static int msm_compr_playback_prepare(struct snd_pcm_substream *substream)
return ret;
}
break;
case SND_AUDIOCODEC_AMRWB:
pr_debug("SND_AUDIOCODEC_AMRWB\n");
ret = q6asm_media_format_block(prtd->audio_client,
compr->codec);
if (ret < 0) {
pr_err("%s: CMD Format block failed\n", __func__);
return ret;
}
break;
case SND_AUDIOCODEC_AMRWBPLUS:
pr_debug("SND_AUDIOCODEC_AMRWBPLUS\n");
memset(&amrwb_cfg, 0x0, sizeof(struct asm_amrwbplus_cfg));
amrwb_cfg.size_bytes = sizeof(struct asm_amrwbplus_cfg);
pr_debug("calling q6asm_media_format_block_amrwbplus");
ret = q6asm_media_format_block_amrwbplus(prtd->audio_client,
&amrwb_cfg);
if (ret < 0) {
pr_err("%s: CMD Format block failed\n", __func__);
return ret;
}
break;
default:
return -EINVAL;
}
@@ -595,7 +617,7 @@ static void populate_codec_list(struct compr_audio *compr,
{
pr_debug("%s\n", __func__);
/* MP3 Block */
compr->info.compr_cap.num_codecs = 1;
compr->info.compr_cap.num_codecs = 10;
compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
@@ -608,7 +630,6 @@ static void populate_codec_list(struct compr_audio *compr,
compr->info.compr_cap.codecs[5] = SND_AUDIOCODEC_DTS;
compr->info.compr_cap.codecs[6] = SND_AUDIOCODEC_DTS_LBR;
compr->info.compr_cap.codecs[7] = SND_AUDIOCODEC_DTS_PASS_THROUGH;
/* Add new codecs here */
compr->info.compr_cap.codecs[8] = SND_AUDIOCODEC_AMRWB;
compr->info.compr_cap.codecs[9] = SND_AUDIOCODEC_AMRWBPLUS;
/* Add new codecs here and update num_codecs*/
@@ -1031,6 +1052,14 @@ static int msm_compr_ioctl(struct snd_pcm_substream *substream,
pr_debug("SND_AUDIOCODEC_DTS\n");
compr->codec = FORMAT_DTS_LBR;
break;
case SND_AUDIOCODEC_AMRWB:
pr_debug("msm_compr_ioctl SND_AUDIOCODEC_AMRWB\n");
compr->codec = FORMAT_AMRWB;
break;
case SND_AUDIOCODEC_AMRWBPLUS:
pr_debug("msm_compr_ioctl SND_AUDIOCODEC_AMRWBPLUS\n");
compr->codec = FORMAT_AMR_WB_PLUS;
break;
default:
/*Needed for the HDMI IN compressed use case*/
pr_debug("FORMAT_LINEAR_PCM\n");

View File

@@ -1547,6 +1547,14 @@ int q6asm_open_write(struct audio_client *ac, uint32_t format)
case FORMAT_DTS_LBR:
open.format = DTS_LBR;
break;
case FORMAT_AMRWB:
open.format = AMRWB_FS;
pr_debug("q6asm_open_write FORMAT_AMRWB");
break;
case FORMAT_AMR_WB_PLUS:
open.format = AMR_WB_PLUS;
pr_debug("q6asm_open_write FORMAT_AMR_WB_PLUS");
break;
default:
pr_err("%s: Invalid format[%d]\n", __func__, format);
goto fail_cmd;
@@ -2430,7 +2438,56 @@ fail_cmd:
return -EINVAL;
}
int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
struct asm_amrwbplus_cfg *cfg)
{
struct asm_stream_media_format_update fmt;
int rc = 0;
pr_debug("q6asm_media_format_block_amrwbplus");
pr_debug("%s:session[%d]band-mode[%d]frame-fmt[%d]ch[%d]\n",
__func__,
ac->session,
cfg->amr_band_mode,
cfg->amr_frame_fmt,
cfg->num_channels);
q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
fmt.format = AMR_WB_PLUS;
fmt.cfg_size = cfg->size_bytes;
fmt.write_cfg.amrwbplus_cfg.size_bytes = cfg->size_bytes;
fmt.write_cfg.amrwbplus_cfg.version = cfg->version;
fmt.write_cfg.amrwbplus_cfg.num_channels = cfg->num_channels;
fmt.write_cfg.amrwbplus_cfg.amr_band_mode = cfg->amr_band_mode;
fmt.write_cfg.amrwbplus_cfg.amr_dtx_mode = cfg->amr_dtx_mode;
fmt.write_cfg.amrwbplus_cfg.amr_frame_fmt = cfg->amr_frame_fmt;
fmt.write_cfg.amrwbplus_cfg.amr_lsf_idx = cfg->amr_lsf_idx;
pr_debug("%s: num_channels=%x amr_band_mode=%d amr_frame_fmt=%d\n",
__func__,
cfg->num_channels,
cfg->amr_band_mode,
cfg->amr_frame_fmt);
rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
if (rc < 0) {
pr_err("%s:Comamnd media format update failed..\n", __func__);
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 FORMAT_UPDATE\n", __func__);
goto fail_cmd;
}
return 0;
fail_cmd:
return -EINVAL;
}
int q6asm_media_format_block_multi_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg)
{
@@ -2502,6 +2559,9 @@ int q6asm_media_format_block(struct audio_client *ac, uint32_t format)
case FORMAT_AMRWB:
fmt.format = AMRWB_FS;
break;
case FORMAT_AMR_WB_PLUS:
fmt.format = AMR_WB_PLUS;
break;
case FORMAT_AMRNB:
fmt.format = AMRNB_FS;
break;