diff options
-rw-r--r-- | sound/soc/sh/fsi.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 23c0e83d4c19..5a2fdf3b84b9 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -146,10 +146,12 @@ struct fsi_priv { | |||
146 | void __iomem *base; | 146 | void __iomem *base; |
147 | struct fsi_master *master; | 147 | struct fsi_master *master; |
148 | 148 | ||
149 | int chan_num; | ||
150 | struct fsi_stream playback; | 149 | struct fsi_stream playback; |
151 | struct fsi_stream capture; | 150 | struct fsi_stream capture; |
152 | 151 | ||
152 | int chan_num:16; | ||
153 | int clk_master:1; | ||
154 | |||
153 | long rate; | 155 | long rate; |
154 | }; | 156 | }; |
155 | 157 | ||
@@ -244,6 +246,11 @@ static struct fsi_master *fsi_get_master(struct fsi_priv *fsi) | |||
244 | return fsi->master; | 246 | return fsi->master; |
245 | } | 247 | } |
246 | 248 | ||
249 | static int fsi_is_clk_master(struct fsi_priv *fsi) | ||
250 | { | ||
251 | return fsi->clk_master; | ||
252 | } | ||
253 | |||
247 | static int fsi_is_port_a(struct fsi_priv *fsi) | 254 | static int fsi_is_port_a(struct fsi_priv *fsi) |
248 | { | 255 | { |
249 | return fsi->master->base == fsi->base; | 256 | return fsi->master->base == fsi->base; |
@@ -793,14 +800,15 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | |||
793 | struct fsi_priv *fsi = fsi_get_priv(substream); | 800 | struct fsi_priv *fsi = fsi_get_priv(substream); |
794 | int is_play = fsi_is_play(substream); | 801 | int is_play = fsi_is_play(substream); |
795 | struct fsi_master *master = fsi_get_master(fsi); | 802 | struct fsi_master *master = fsi_get_master(fsi); |
796 | set_rate_func set_rate; | 803 | set_rate_func set_rate = fsi_get_info_set_rate(master); |
797 | 804 | ||
798 | fsi_irq_disable(fsi, is_play); | 805 | fsi_irq_disable(fsi, is_play); |
799 | fsi_clk_ctrl(fsi, 0); | ||
800 | 806 | ||
801 | set_rate = fsi_get_info_set_rate(master); | 807 | if (fsi_is_clk_master(fsi)) { |
802 | if (set_rate && fsi->rate) | 808 | fsi_clk_ctrl(fsi, 0); |
803 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); | 809 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); |
810 | } | ||
811 | |||
804 | fsi->rate = 0; | 812 | fsi->rate = 0; |
805 | 813 | ||
806 | pm_runtime_put_sync(dai->dev); | 814 | pm_runtime_put_sync(dai->dev); |
@@ -876,6 +884,8 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi) | |||
876 | static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | 884 | static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
877 | { | 885 | { |
878 | struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai); | 886 | struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai); |
887 | struct fsi_master *master = fsi_get_master(fsi); | ||
888 | set_rate_func set_rate = fsi_get_info_set_rate(master); | ||
879 | u32 flags = fsi_get_info_flags(fsi); | 889 | u32 flags = fsi_get_info_flags(fsi); |
880 | u32 data = 0; | 890 | u32 data = 0; |
881 | int ret; | 891 | int ret; |
@@ -886,6 +896,7 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
886 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 896 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
887 | case SND_SOC_DAIFMT_CBM_CFM: | 897 | case SND_SOC_DAIFMT_CBM_CFM: |
888 | data = DIMD | DOMD; | 898 | data = DIMD | DOMD; |
899 | fsi->clk_master = 1; | ||
889 | break; | 900 | break; |
890 | case SND_SOC_DAIFMT_CBS_CFS: | 901 | case SND_SOC_DAIFMT_CBS_CFS: |
891 | break; | 902 | break; |
@@ -893,6 +904,13 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
893 | ret = -EINVAL; | 904 | ret = -EINVAL; |
894 | goto set_fmt_exit; | 905 | goto set_fmt_exit; |
895 | } | 906 | } |
907 | |||
908 | if (fsi_is_clk_master(fsi) && !set_rate) { | ||
909 | dev_err(dai->dev, "platform doesn't have set_rate\n"); | ||
910 | ret = -EINVAL; | ||
911 | goto set_fmt_exit; | ||
912 | } | ||
913 | |||
896 | fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); | 914 | fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); |
897 | 915 | ||
898 | /* set format */ | 916 | /* set format */ |
@@ -919,13 +937,12 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | |||
919 | { | 937 | { |
920 | struct fsi_priv *fsi = fsi_get_priv(substream); | 938 | struct fsi_priv *fsi = fsi_get_priv(substream); |
921 | struct fsi_master *master = fsi_get_master(fsi); | 939 | struct fsi_master *master = fsi_get_master(fsi); |
922 | set_rate_func set_rate; | 940 | set_rate_func set_rate = fsi_get_info_set_rate(master); |
923 | int fsi_ver = master->core->ver; | 941 | int fsi_ver = master->core->ver; |
924 | long rate = params_rate(params); | 942 | long rate = params_rate(params); |
925 | int ret; | 943 | int ret; |
926 | 944 | ||
927 | set_rate = fsi_get_info_set_rate(master); | 945 | if (!fsi_is_clk_master(fsi)) |
928 | if (!set_rate) | ||
929 | return 0; | 946 | return 0; |
930 | 947 | ||
931 | ret = set_rate(dai->dev, fsi_is_port_a(fsi), rate, 1); | 948 | ret = set_rate(dai->dev, fsi_is_port_a(fsi), rate, 1); |