aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/sh_fsi.h32
-rw-r--r--sound/soc/sh/fsi.c98
2 files changed, 124 insertions, 6 deletions
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
index 3ecdb965b89..2c6237e6c04 100644
--- a/include/sound/sh_fsi.h
+++ b/include/sound/sh_fsi.h
@@ -72,9 +72,41 @@
72#define SH_FSI_OFMT_TDM_DELAY_CH(x) \ 72#define SH_FSI_OFMT_TDM_DELAY_CH(x) \
73 (SH_FSI_OFMT(TDM_DELAY) | SH_FSI_SET_CH_O(x)) 73 (SH_FSI_OFMT(TDM_DELAY) | SH_FSI_SET_CH_O(x))
74 74
75
76/*
77 * set_rate return value
78 *
79 * see ACKMD/BPFMD on
80 * ACK_MD (FSI2)
81 * CKG1 (FSI)
82 *
83 * err: return value < 0
84 *
85 * 0x-00000AB
86 *
87 * A: ACKMD value
88 * B: BPFMD value
89 */
90
91#define SH_FSI_ACKMD_MASK (0xF << 0)
92#define SH_FSI_ACKMD_512 (1 << 0)
93#define SH_FSI_ACKMD_256 (2 << 0)
94#define SH_FSI_ACKMD_128 (3 << 0)
95#define SH_FSI_ACKMD_64 (4 << 0)
96#define SH_FSI_ACKMD_32 (5 << 0)
97
98#define SH_FSI_BPFMD_MASK (0xF << 4)
99#define SH_FSI_BPFMD_512 (1 << 4)
100#define SH_FSI_BPFMD_256 (2 << 4)
101#define SH_FSI_BPFMD_128 (3 << 4)
102#define SH_FSI_BPFMD_64 (4 << 4)
103#define SH_FSI_BPFMD_32 (5 << 4)
104#define SH_FSI_BPFMD_16 (6 << 4)
105
75struct sh_fsi_platform_info { 106struct sh_fsi_platform_info {
76 unsigned long porta_flags; 107 unsigned long porta_flags;
77 unsigned long portb_flags; 108 unsigned long portb_flags;
109 int (*set_rate)(int is_porta, int rate); /* for master mode */
78}; 110};
79 111
80extern struct snd_soc_dai fsi_soc_dai[2]; 112extern struct snd_soc_dai fsi_soc_dai[2];
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index e551ca45f03..a1ce6089177 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
787static 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
789static struct snd_soc_dai_ops fsi_dai_ops = { 874static 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/************************************************************************