diff options
-rw-r--r-- | include/sound/sh_fsi.h | 32 | ||||
-rw-r--r-- | sound/soc/sh/fsi.c | 98 |
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 | |||
75 | struct sh_fsi_platform_info { | 106 | struct 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 | ||
80 | extern struct snd_soc_dai fsi_soc_dai[2]; | 112 | extern 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 | ||
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 | /************************************************************************ |