diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2010-07-12 23:13:14 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-07-13 07:35:39 -0400 |
commit | ccad7b44ccdc8341c1449bc5b864b42b197f8c2e (patch) | |
tree | 108725d49aaafe94b2b2be94e29b96d36b7ae637 /sound/soc/sh | |
parent | d78541473d6c6126616bca2552282660faa41d43 (diff) |
ASoC: fsi: Fixup for master mode
This patch add hw_params to snd_soc_dai_ops,
because board specific set_rate is needed
when FSI was used as master mode.
This patch remove fsi_clk_ctrl from fsi_dai_startup,
because clock should be disabled before set_rate.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/sh')
-rw-r--r-- | sound/soc/sh/fsi.c | 98 |
1 files changed, 92 insertions, 6 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index e551ca45f03e..a1ce6089177c 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -65,6 +65,10 @@ | |||
65 | #define ERR_UNDER 0x00000001 | 65 | #define ERR_UNDER 0x00000001 |
66 | #define ST_ERR (ERR_OVER | ERR_UNDER) | 66 | #define ST_ERR (ERR_OVER | ERR_UNDER) |
67 | 67 | ||
68 | /* CKG1 */ | ||
69 | #define ACKMD_MASK 0x00007000 | ||
70 | #define BPFMD_MASK 0x00000700 | ||
71 | |||
68 | /* CLK_RST */ | 72 | /* CLK_RST */ |
69 | #define B_CLK 0x00000010 | 73 | #define B_CLK 0x00000010 |
70 | #define A_CLK 0x00000001 | 74 | #define A_CLK 0x00000001 |
@@ -734,12 +738,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
734 | } | 738 | } |
735 | fsi_reg_write(fsi, reg, data); | 739 | fsi_reg_write(fsi, reg, data); |
736 | 740 | ||
737 | /* | ||
738 | * clear clk reset if master mode | ||
739 | */ | ||
740 | if (is_master) | ||
741 | fsi_clk_ctrl(fsi, 1); | ||
742 | |||
743 | /* irq clear */ | 741 | /* irq clear */ |
744 | fsi_irq_disable(fsi, is_play); | 742 | fsi_irq_disable(fsi, is_play); |
745 | fsi_irq_clear_status(fsi); | 743 | fsi_irq_clear_status(fsi); |
@@ -786,10 +784,98 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
786 | return ret; | 784 | return ret; |
787 | } | 785 | } |
788 | 786 | ||
787 | static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | ||
788 | struct snd_pcm_hw_params *params, | ||
789 | struct snd_soc_dai *dai) | ||
790 | { | ||
791 | struct fsi_priv *fsi = fsi_get_priv(substream); | ||
792 | struct fsi_master *master = fsi_get_master(fsi); | ||
793 | int (*set_rate)(int is_porta, int rate) = master->info->set_rate; | ||
794 | int fsi_ver = master->core->ver; | ||
795 | int is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); | ||
796 | int ret; | ||
797 | |||
798 | /* if slave mode, set_rate is not needed */ | ||
799 | if (!fsi_is_master_mode(fsi, is_play)) | ||
800 | return 0; | ||
801 | |||
802 | /* it is error if no set_rate */ | ||
803 | if (!set_rate) | ||
804 | return -EIO; | ||
805 | |||
806 | /* clock stop */ | ||
807 | pm_runtime_put_sync(dai->dev); | ||
808 | fsi_clk_ctrl(fsi, 0); | ||
809 | |||
810 | ret = set_rate(fsi_is_port_a(fsi), params_rate(params)); | ||
811 | if (ret > 0) { | ||
812 | u32 data = 0; | ||
813 | |||
814 | switch (ret & SH_FSI_ACKMD_MASK) { | ||
815 | default: | ||
816 | /* FALL THROUGH */ | ||
817 | case SH_FSI_ACKMD_512: | ||
818 | data |= (0x0 << 12); | ||
819 | break; | ||
820 | case SH_FSI_ACKMD_256: | ||
821 | data |= (0x1 << 12); | ||
822 | break; | ||
823 | case SH_FSI_ACKMD_128: | ||
824 | data |= (0x2 << 12); | ||
825 | break; | ||
826 | case SH_FSI_ACKMD_64: | ||
827 | data |= (0x3 << 12); | ||
828 | break; | ||
829 | case SH_FSI_ACKMD_32: | ||
830 | if (fsi_ver < 2) | ||
831 | dev_err(dai->dev, "unsupported ACKMD\n"); | ||
832 | else | ||
833 | data |= (0x4 << 12); | ||
834 | break; | ||
835 | } | ||
836 | |||
837 | switch (ret & SH_FSI_BPFMD_MASK) { | ||
838 | default: | ||
839 | /* FALL THROUGH */ | ||
840 | case SH_FSI_BPFMD_32: | ||
841 | data |= (0x0 << 8); | ||
842 | break; | ||
843 | case SH_FSI_BPFMD_64: | ||
844 | data |= (0x1 << 8); | ||
845 | break; | ||
846 | case SH_FSI_BPFMD_128: | ||
847 | data |= (0x2 << 8); | ||
848 | break; | ||
849 | case SH_FSI_BPFMD_256: | ||
850 | data |= (0x3 << 8); | ||
851 | break; | ||
852 | case SH_FSI_BPFMD_512: | ||
853 | data |= (0x4 << 8); | ||
854 | break; | ||
855 | case SH_FSI_BPFMD_16: | ||
856 | if (fsi_ver < 2) | ||
857 | dev_err(dai->dev, "unsupported ACKMD\n"); | ||
858 | else | ||
859 | data |= (0x7 << 8); | ||
860 | break; | ||
861 | } | ||
862 | |||
863 | fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); | ||
864 | udelay(10); | ||
865 | fsi_clk_ctrl(fsi, 1); | ||
866 | ret = 0; | ||
867 | } | ||
868 | pm_runtime_get_sync(dai->dev); | ||
869 | |||
870 | return ret; | ||
871 | |||
872 | } | ||
873 | |||
789 | static struct snd_soc_dai_ops fsi_dai_ops = { | 874 | static struct snd_soc_dai_ops fsi_dai_ops = { |
790 | .startup = fsi_dai_startup, | 875 | .startup = fsi_dai_startup, |
791 | .shutdown = fsi_dai_shutdown, | 876 | .shutdown = fsi_dai_shutdown, |
792 | .trigger = fsi_dai_trigger, | 877 | .trigger = fsi_dai_trigger, |
878 | .hw_params = fsi_dai_hw_params, | ||
793 | }; | 879 | }; |
794 | 880 | ||
795 | /************************************************************************ | 881 | /************************************************************************ |