diff options
Diffstat (limited to 'sound/soc/qcom/qdsp6/q6asm-dai.c')
-rw-r--r-- | sound/soc/qcom/qdsp6/q6asm-dai.c | 143 |
1 files changed, 138 insertions, 5 deletions
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index 8b48815ff918..f6c7cddf08e8 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -41,6 +41,9 @@ #define Q6ASM_DAI_TX 1 #define Q6ASM_DAI_RX 2 +#define ALAC_CH_LAYOUT_MONO ((101 << 16) | 1) +#define ALAC_CH_LAYOUT_STEREO ((101 << 16) | 2) + enum stream_state { Q6ASM_STREAM_IDLE = 0, Q6ASM_STREAM_STOPPED, @@ -252,7 +255,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM, - prtd->bits_per_sample); + 0, prtd->bits_per_sample); } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM, prtd->bits_per_sample); @@ -330,7 +333,7 @@ static int q6asm_dai_open(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; - struct snd_soc_dai *cpu_dai = soc_prtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_prtd, 0); struct q6asm_dai_rtd *prtd; struct q6asm_dai_data *pdata; struct device *dev = component->dev; @@ -542,7 +545,7 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream) struct snd_soc_pcm_runtime *rtd = stream->private_data; struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME); struct snd_compr_runtime *runtime = stream->runtime; - struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct q6asm_dai_data *pdata; struct device *dev = c->dev; struct q6asm_dai_rtd *prtd; @@ -629,10 +632,17 @@ static int q6asm_dai_compr_set_params(struct snd_compr_stream *stream, int dir = stream->direction; struct q6asm_dai_data *pdata; struct q6asm_flac_cfg flac_cfg; + struct q6asm_wma_cfg wma_cfg; + struct q6asm_alac_cfg alac_cfg; + struct q6asm_ape_cfg ape_cfg; + unsigned int wma_v9 = 0; struct device *dev = c->dev; int ret; union snd_codec_options *codec_options; struct snd_dec_flac *flac; + struct snd_dec_wma *wma; + struct snd_dec_alac *alac; + struct snd_dec_ape *ape; codec_options = &(prtd->codec_param.codec.options); @@ -654,7 +664,7 @@ static int q6asm_dai_compr_set_params(struct snd_compr_stream *stream, prtd->bits_per_sample = 16; if (dir == SND_COMPRESS_PLAYBACK) { ret = q6asm_open_write(prtd->audio_client, params->codec.id, - prtd->bits_per_sample); + params->codec.profile, prtd->bits_per_sample); if (ret < 0) { dev_err(dev, "q6asm_open_write failed\n"); @@ -694,6 +704,126 @@ static int q6asm_dai_compr_set_params(struct snd_compr_stream *stream, return -EIO; } break; + + case SND_AUDIOCODEC_WMA: + wma = &codec_options->wma_d; + + memset(&wma_cfg, 0x0, sizeof(struct q6asm_wma_cfg)); + + wma_cfg.sample_rate = params->codec.sample_rate; + wma_cfg.num_channels = params->codec.ch_in; + wma_cfg.bytes_per_sec = params->codec.bit_rate / 8; + wma_cfg.block_align = params->codec.align; + wma_cfg.bits_per_sample = prtd->bits_per_sample; + wma_cfg.enc_options = wma->encoder_option; + wma_cfg.adv_enc_options = wma->adv_encoder_option; + wma_cfg.adv_enc_options2 = wma->adv_encoder_option2; + + if (wma_cfg.num_channels == 1) + wma_cfg.channel_mask = 4; /* Mono Center */ + else if (wma_cfg.num_channels == 2) + wma_cfg.channel_mask = 3; /* Stereo FL/FR */ + else + return -EINVAL; + + /* check the codec profile */ + switch (params->codec.profile) { + case SND_AUDIOPROFILE_WMA9: + wma_cfg.fmtag = 0x161; + wma_v9 = 1; + break; + + case SND_AUDIOPROFILE_WMA10: + wma_cfg.fmtag = 0x166; + break; + + case SND_AUDIOPROFILE_WMA9_PRO: + wma_cfg.fmtag = 0x162; + break; + + case SND_AUDIOPROFILE_WMA9_LOSSLESS: + wma_cfg.fmtag = 0x163; + break; + + case SND_AUDIOPROFILE_WMA10_LOSSLESS: + wma_cfg.fmtag = 0x167; + break; + + default: + dev_err(dev, "Unknown WMA profile:%x\n", + params->codec.profile); + return -EIO; + } + + if (wma_v9) + ret = q6asm_stream_media_format_block_wma_v9( + prtd->audio_client, &wma_cfg); + else + ret = q6asm_stream_media_format_block_wma_v10( + prtd->audio_client, &wma_cfg); + if (ret < 0) { + dev_err(dev, "WMA9 CMD failed:%d\n", ret); + return -EIO; + } + break; + + case SND_AUDIOCODEC_ALAC: + memset(&alac_cfg, 0x0, sizeof(alac_cfg)); + alac = &codec_options->alac_d; + + alac_cfg.sample_rate = params->codec.sample_rate; + alac_cfg.avg_bit_rate = params->codec.bit_rate; + alac_cfg.bit_depth = prtd->bits_per_sample; + alac_cfg.num_channels = params->codec.ch_in; + + alac_cfg.frame_length = alac->frame_length; + alac_cfg.pb = alac->pb; + alac_cfg.mb = alac->mb; + alac_cfg.kb = alac->kb; + alac_cfg.max_run = alac->max_run; + alac_cfg.compatible_version = alac->compatible_version; + alac_cfg.max_frame_bytes = alac->max_frame_bytes; + + switch (params->codec.ch_in) { + case 1: + alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_MONO; + break; + case 2: + alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_STEREO; + break; + } + ret = q6asm_stream_media_format_block_alac(prtd->audio_client, + &alac_cfg); + if (ret < 0) { + dev_err(dev, "ALAC CMD Format block failed:%d\n", ret); + return -EIO; + } + break; + + case SND_AUDIOCODEC_APE: + memset(&ape_cfg, 0x0, sizeof(ape_cfg)); + ape = &codec_options->ape_d; + + ape_cfg.sample_rate = params->codec.sample_rate; + ape_cfg.num_channels = params->codec.ch_in; + ape_cfg.bits_per_sample = prtd->bits_per_sample; + + ape_cfg.compatible_version = ape->compatible_version; + ape_cfg.compression_level = ape->compression_level; + ape_cfg.format_flags = ape->format_flags; + ape_cfg.blocks_per_frame = ape->blocks_per_frame; + ape_cfg.final_frame_blocks = ape->final_frame_blocks; + ape_cfg.total_frames = ape->total_frames; + ape_cfg.seek_table_present = ape->seek_table_present; + + ret = q6asm_stream_media_format_block_ape(prtd->audio_client, + &ape_cfg); + if (ret < 0) { + dev_err(dev, "APE CMD Format block failed:%d\n", ret); + return -EIO; + } + break; + default: break; } @@ -793,9 +923,12 @@ static int q6asm_dai_compr_get_caps(struct snd_compr_stream *stream, caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE; caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS; caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS; - caps->num_codecs = 2; + caps->num_codecs = 5; caps->codecs[0] = SND_AUDIOCODEC_MP3; caps->codecs[1] = SND_AUDIOCODEC_FLAC; + caps->codecs[2] = SND_AUDIOCODEC_WMA; + caps->codecs[3] = SND_AUDIOCODEC_ALAC; + caps->codecs[4] = SND_AUDIOCODEC_APE; return 0; } |