diff options
author | Vinod Koul <vinod.koul@intel.com> | 2015-05-06 12:36:43 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-05-06 14:50:22 -0400 |
commit | 0b44e345495ad97d533461e53a9218de8039d20b (patch) | |
tree | 72a521e3c7be4e56572b79e57f7af018c5f4071e | |
parent | 711bc9476bfaeba279259978aadcaa826a77e170 (diff) |
ASoC: intel: add support for specifying PCM format
With this machines can configure the PCM format applied on SSP port using
the set_fmt API
Signed-off-by: Praveen Diwakar <praveen.diwakar@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/intel/atom/sst-atom-controls.c | 99 | ||||
-rw-r--r-- | sound/soc/intel/atom/sst-atom-controls.h | 1 | ||||
-rw-r--r-- | sound/soc/intel/atom/sst-mfld-platform-pcm.c | 15 |
3 files changed, 115 insertions, 0 deletions
diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index 93c6c8b5fbc6..e024d98948fa 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c | |||
@@ -774,8 +774,107 @@ int sst_handle_vb_timer(struct snd_soc_dai *dai, bool enable) | |||
774 | return ret; | 774 | return ret; |
775 | } | 775 | } |
776 | 776 | ||
777 | static int sst_get_frame_sync_polarity(struct snd_soc_dai *dai, | ||
778 | unsigned int fmt) | ||
779 | { | ||
780 | int format; | ||
781 | |||
782 | format = fmt & SND_SOC_DAIFMT_INV_MASK; | ||
783 | dev_dbg(dai->dev, "Enter:%s, format=%x\n", __func__, format); | ||
784 | |||
785 | switch (format) { | ||
786 | case SND_SOC_DAIFMT_NB_NF: | ||
787 | return SSP_FS_ACTIVE_LOW; | ||
788 | case SND_SOC_DAIFMT_NB_IF: | ||
789 | return SSP_FS_ACTIVE_HIGH; | ||
790 | case SND_SOC_DAIFMT_IB_IF: | ||
791 | return SSP_FS_ACTIVE_LOW; | ||
792 | case SND_SOC_DAIFMT_IB_NF: | ||
793 | return SSP_FS_ACTIVE_HIGH; | ||
794 | default: | ||
795 | dev_err(dai->dev, "Invalid frame sync polarity %d\n", format); | ||
796 | } | ||
797 | |||
798 | return -EINVAL; | ||
799 | } | ||
800 | |||
801 | static int sst_get_ssp_mode(struct snd_soc_dai *dai, unsigned int fmt) | ||
802 | { | ||
803 | int format; | ||
804 | |||
805 | format = (fmt & SND_SOC_DAIFMT_MASTER_MASK); | ||
806 | dev_dbg(dai->dev, "Enter:%s, format=%x\n", __func__, format); | ||
807 | |||
808 | switch (format) { | ||
809 | case SND_SOC_DAIFMT_CBS_CFS: | ||
810 | return SSP_MODE_MASTER; | ||
811 | case SND_SOC_DAIFMT_CBM_CFM: | ||
812 | return SSP_MODE_SLAVE; | ||
813 | default: | ||
814 | dev_err(dai->dev, "Invalid ssp protocol: %d\n", format); | ||
815 | } | ||
816 | |||
817 | return -EINVAL; | ||
818 | } | ||
819 | |||
820 | |||
821 | int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt) | ||
822 | { | ||
823 | unsigned int mode; | ||
824 | int fs_polarity; | ||
825 | struct sst_data *ctx = snd_soc_dai_get_drvdata(dai); | ||
826 | |||
827 | mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | ||
828 | |||
829 | switch (mode) { | ||
830 | case SND_SOC_DAIFMT_DSP_B: | ||
831 | ctx->ssp_cmd.ssp_protocol = SSP_MODE_PCM; | ||
832 | ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NETWORK << 1); | ||
833 | ctx->ssp_cmd.start_delay = 0; | ||
834 | ctx->ssp_cmd.data_polarity = 1; | ||
835 | ctx->ssp_cmd.frame_sync_width = 1; | ||
836 | break; | ||
837 | |||
838 | case SND_SOC_DAIFMT_DSP_A: | ||
839 | ctx->ssp_cmd.ssp_protocol = SSP_MODE_PCM; | ||
840 | ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NETWORK << 1); | ||
841 | ctx->ssp_cmd.start_delay = 1; | ||
842 | ctx->ssp_cmd.data_polarity = 1; | ||
843 | ctx->ssp_cmd.frame_sync_width = 1; | ||
844 | break; | ||
845 | |||
846 | case SND_SOC_DAIFMT_I2S: | ||
847 | ctx->ssp_cmd.ssp_protocol = SSP_MODE_I2S; | ||
848 | ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NORMAL << 1); | ||
849 | ctx->ssp_cmd.start_delay = 1; | ||
850 | ctx->ssp_cmd.data_polarity = 0; | ||
851 | ctx->ssp_cmd.frame_sync_width = ctx->ssp_cmd.nb_bits_per_slots; | ||
852 | break; | ||
853 | |||
854 | case SND_SOC_DAIFMT_LEFT_J: | ||
855 | ctx->ssp_cmd.ssp_protocol = SSP_MODE_I2S; | ||
856 | ctx->ssp_cmd.mode = sst_get_ssp_mode(dai, fmt) | (SSP_PCM_MODE_NORMAL << 1); | ||
857 | ctx->ssp_cmd.start_delay = 0; | ||
858 | ctx->ssp_cmd.data_polarity = 0; | ||
859 | ctx->ssp_cmd.frame_sync_width = ctx->ssp_cmd.nb_bits_per_slots; | ||
860 | break; | ||
861 | |||
862 | default: | ||
863 | dev_dbg(dai->dev, "using default ssp configs\n"); | ||
864 | } | ||
865 | |||
866 | fs_polarity = sst_get_frame_sync_polarity(dai, fmt); | ||
867 | if (fs_polarity < 0) | ||
868 | return fs_polarity; | ||
869 | |||
870 | ctx->ssp_cmd.frame_sync_polarity = fs_polarity; | ||
871 | |||
872 | return 0; | ||
873 | } | ||
874 | |||
777 | /** | 875 | /** |
778 | * sst_ssp_config - contains SSP configuration for media UC | 876 | * sst_ssp_config - contains SSP configuration for media UC |
877 | * this can be overwritten by set_dai_xxx APIs | ||
779 | */ | 878 | */ |
780 | static const struct sst_ssp_config sst_ssp_configs = { | 879 | static const struct sst_ssp_config sst_ssp_configs = { |
781 | .ssp_id = SSP_CODEC, | 880 | .ssp_id = SSP_CODEC, |
diff --git a/sound/soc/intel/atom/sst-atom-controls.h b/sound/soc/intel/atom/sst-atom-controls.h index da13f6fa7d1c..53551a657b51 100644 --- a/sound/soc/intel/atom/sst-atom-controls.h +++ b/sound/soc/intel/atom/sst-atom-controls.h | |||
@@ -869,6 +869,7 @@ struct sst_enum { | |||
869 | SOC_DAPM_ENUM(SST_MUX_CTL_NAME(xpname, xinstance), \ | 869 | SOC_DAPM_ENUM(SST_MUX_CTL_NAME(xpname, xinstance), \ |
870 | SST_SSP_MUX_ENUM(xreg, xshift, xtexts)) | 870 | SST_SSP_MUX_ENUM(xreg, xshift, xtexts)) |
871 | 871 | ||
872 | int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt); | ||
872 | void sst_fill_ssp_defaults(struct snd_soc_dai *dai); | 873 | void sst_fill_ssp_defaults(struct snd_soc_dai *dai); |
873 | 874 | ||
874 | #endif | 875 | #endif |
diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 1fb2448e0fed..580f5e92580e 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c | |||
@@ -450,6 +450,20 @@ static int sst_be_hw_params(struct snd_pcm_substream *substream, | |||
450 | return ret; | 450 | return ret; |
451 | } | 451 | } |
452 | 452 | ||
453 | static int sst_set_format(struct snd_soc_dai *dai, unsigned int fmt) | ||
454 | { | ||
455 | int ret = 0; | ||
456 | |||
457 | if (!dai->active) | ||
458 | return 0; | ||
459 | |||
460 | ret = sst_fill_ssp_config(dai, fmt); | ||
461 | if (ret < 0) | ||
462 | dev_err(dai->dev, "sst_set_format failed..\n"); | ||
463 | |||
464 | return ret; | ||
465 | } | ||
466 | |||
453 | static void sst_disable_ssp(struct snd_pcm_substream *substream, | 467 | static void sst_disable_ssp(struct snd_pcm_substream *substream, |
454 | struct snd_soc_dai *dai) | 468 | struct snd_soc_dai *dai) |
455 | { | 469 | { |
@@ -475,6 +489,7 @@ static struct snd_soc_dai_ops sst_compr_dai_ops = { | |||
475 | static struct snd_soc_dai_ops sst_be_dai_ops = { | 489 | static struct snd_soc_dai_ops sst_be_dai_ops = { |
476 | .startup = sst_enable_ssp, | 490 | .startup = sst_enable_ssp, |
477 | .hw_params = sst_be_hw_params, | 491 | .hw_params = sst_be_hw_params, |
492 | .set_fmt = sst_set_format, | ||
478 | .shutdown = sst_disable_ssp, | 493 | .shutdown = sst_disable_ssp, |
479 | }; | 494 | }; |
480 | 495 | ||