diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h index 382052b2d46..90872c9781e 100644 --- a/include/sound/apr_audio.h +++ b/include/sound/apr_audio.h @@ -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)); diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h index 55e71ee7685..4021d487a2e 100644 --- a/include/sound/q6asm.h +++ b/include/sound/q6asm.h @@ -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); diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c index 88b6dbafcb5..b76160e28ff 100644 --- a/sound/soc/msm/msm-compr-q6.c +++ b/sound/soc/msm/msm-compr-q6.c @@ -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"); diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c index 9b8a4bdaf3e..a3dcde38553 100644 --- a/sound/soc/msm/qdsp6/q6asm.c +++ b/sound/soc/msm/qdsp6/q6asm.c @@ -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;