aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/blackfin/bf5xx-i2s.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/blackfin/bf5xx-i2s.c')
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c69
1 files changed, 49 insertions, 20 deletions
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 43a4092eeb89..e020c160ee44 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -70,6 +70,25 @@ static struct sport_param sport_params[2] = {
70 } 70 }
71}; 71};
72 72
73/*
74 * Setting the TFS pin selector for SPORT 0 based on whether the selected
75 * port id F or G. If the port is F then no conflict should exist for the
76 * TFS. When Port G is selected and EMAC then there is a conflict between
77 * the PHY interrupt line and TFS. Current settings prevent the conflict
78 * by ignoring the TFS pin when Port G is selected. This allows both
79 * ssm2602 using Port G and EMAC concurrently.
80 */
81#ifdef CONFIG_BF527_SPORT0_PORTF
82#define LOCAL_SPORT0_TFS (P_SPORT0_TFS)
83#else
84#define LOCAL_SPORT0_TFS (0)
85#endif
86
87static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
88 P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0},
89 {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI,
90 P_SPORT1_RSCLK, P_SPORT1_TFS, 0} };
91
73static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, 92static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
74 unsigned int fmt) 93 unsigned int fmt)
75{ 94{
@@ -78,28 +97,34 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
78 /* interface format:support I2S,slave mode */ 97 /* interface format:support I2S,slave mode */
79 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 98 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
80 case SND_SOC_DAIFMT_I2S: 99 case SND_SOC_DAIFMT_I2S:
100 bf5xx_i2s.tcr1 |= TFSR | TCKFE;
101 bf5xx_i2s.rcr1 |= RFSR | RCKFE;
102 bf5xx_i2s.tcr2 |= TSFSE;
103 bf5xx_i2s.rcr2 |= RSFSE;
104 break;
105 case SND_SOC_DAIFMT_DSP_A:
106 bf5xx_i2s.tcr1 |= TFSR;
107 bf5xx_i2s.rcr1 |= RFSR;
81 break; 108 break;
82 case SND_SOC_DAIFMT_LEFT_J: 109 case SND_SOC_DAIFMT_LEFT_J:
83 ret = -EINVAL; 110 ret = -EINVAL;
84 break; 111 break;
85 default: 112 default:
113 printk(KERN_ERR "%s: Unknown DAI format type\n", __func__);
86 ret = -EINVAL; 114 ret = -EINVAL;
87 break; 115 break;
88 } 116 }
89 117
90 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 118 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
91 case SND_SOC_DAIFMT_CBS_CFS:
92 ret = -EINVAL;
93 break;
94 case SND_SOC_DAIFMT_CBM_CFS:
95 ret = -EINVAL;
96 break;
97 case SND_SOC_DAIFMT_CBM_CFM: 119 case SND_SOC_DAIFMT_CBM_CFM:
98 break; 120 break;
121 case SND_SOC_DAIFMT_CBS_CFS:
122 case SND_SOC_DAIFMT_CBM_CFS:
99 case SND_SOC_DAIFMT_CBS_CFM: 123 case SND_SOC_DAIFMT_CBS_CFM:
100 ret = -EINVAL; 124 ret = -EINVAL;
101 break; 125 break;
102 default: 126 default:
127 printk(KERN_ERR "%s: Unknown DAI master type\n", __func__);
103 ret = -EINVAL; 128 ret = -EINVAL;
104 break; 129 break;
105 } 130 }
@@ -127,14 +152,17 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
127 case SNDRV_PCM_FORMAT_S16_LE: 152 case SNDRV_PCM_FORMAT_S16_LE:
128 bf5xx_i2s.tcr2 |= 15; 153 bf5xx_i2s.tcr2 |= 15;
129 bf5xx_i2s.rcr2 |= 15; 154 bf5xx_i2s.rcr2 |= 15;
155 sport_handle->wdsize = 2;
130 break; 156 break;
131 case SNDRV_PCM_FORMAT_S24_LE: 157 case SNDRV_PCM_FORMAT_S24_LE:
132 bf5xx_i2s.tcr2 |= 23; 158 bf5xx_i2s.tcr2 |= 23;
133 bf5xx_i2s.rcr2 |= 23; 159 bf5xx_i2s.rcr2 |= 23;
160 sport_handle->wdsize = 3;
134 break; 161 break;
135 case SNDRV_PCM_FORMAT_S32_LE: 162 case SNDRV_PCM_FORMAT_S32_LE:
136 bf5xx_i2s.tcr2 |= 31; 163 bf5xx_i2s.tcr2 |= 31;
137 bf5xx_i2s.rcr2 |= 31; 164 bf5xx_i2s.rcr2 |= 31;
165 sport_handle->wdsize = 4;
138 break; 166 break;
139 } 167 }
140 168
@@ -145,17 +173,17 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
145 * need to configure both of them at the time when the first 173 * need to configure both of them at the time when the first
146 * stream is opened. 174 * stream is opened.
147 * 175 *
148 * CPU DAI format:I2S, slave mode. 176 * CPU DAI:slave mode.
149 */ 177 */
150 ret = sport_config_rx(sport_handle, RFSR | RCKFE, 178 ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
151 RSFSE|bf5xx_i2s.rcr2, 0, 0); 179 bf5xx_i2s.rcr2, 0, 0);
152 if (ret) { 180 if (ret) {
153 pr_err("SPORT is busy!\n"); 181 pr_err("SPORT is busy!\n");
154 return -EBUSY; 182 return -EBUSY;
155 } 183 }
156 184
157 ret = sport_config_tx(sport_handle, TFSR | TCKFE, 185 ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
158 TSFSE|bf5xx_i2s.tcr2, 0, 0); 186 bf5xx_i2s.tcr2, 0, 0);
159 if (ret) { 187 if (ret) {
160 pr_err("SPORT is busy!\n"); 188 pr_err("SPORT is busy!\n");
161 return -EBUSY; 189 return -EBUSY;
@@ -174,13 +202,6 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream)
174static int bf5xx_i2s_probe(struct platform_device *pdev, 202static int bf5xx_i2s_probe(struct platform_device *pdev,
175 struct snd_soc_dai *dai) 203 struct snd_soc_dai *dai)
176{ 204{
177 u16 sport_req[][7] = {
178 { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
179 P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0},
180 { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
181 P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0},
182 };
183
184 pr_debug("%s enter\n", __func__); 205 pr_debug("%s enter\n", __func__);
185 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { 206 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
186 pr_err("Requesting Peripherals failed\n"); 207 pr_err("Requesting Peripherals failed\n");
@@ -198,6 +219,13 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
198 return 0; 219 return 0;
199} 220}
200 221
222static void bf5xx_i2s_remove(struct platform_device *pdev,
223 struct snd_soc_dai *dai)
224{
225 pr_debug("%s enter\n", __func__);
226 peripheral_free_list(&sport_req[sport_num][0]);
227}
228
201#ifdef CONFIG_PM 229#ifdef CONFIG_PM
202static int bf5xx_i2s_suspend(struct platform_device *dev, 230static int bf5xx_i2s_suspend(struct platform_device *dev,
203 struct snd_soc_dai *dai) 231 struct snd_soc_dai *dai)
@@ -263,15 +291,16 @@ struct snd_soc_dai bf5xx_i2s_dai = {
263 .id = 0, 291 .id = 0,
264 .type = SND_SOC_DAI_I2S, 292 .type = SND_SOC_DAI_I2S,
265 .probe = bf5xx_i2s_probe, 293 .probe = bf5xx_i2s_probe,
294 .remove = bf5xx_i2s_remove,
266 .suspend = bf5xx_i2s_suspend, 295 .suspend = bf5xx_i2s_suspend,
267 .resume = bf5xx_i2s_resume, 296 .resume = bf5xx_i2s_resume,
268 .playback = { 297 .playback = {
269 .channels_min = 2, 298 .channels_min = 1,
270 .channels_max = 2, 299 .channels_max = 2,
271 .rates = BF5XX_I2S_RATES, 300 .rates = BF5XX_I2S_RATES,
272 .formats = BF5XX_I2S_FORMATS,}, 301 .formats = BF5XX_I2S_FORMATS,},
273 .capture = { 302 .capture = {
274 .channels_min = 2, 303 .channels_min = 1,
275 .channels_max = 2, 304 .channels_max = 2,
276 .rates = BF5XX_I2S_RATES, 305 .rates = BF5XX_I2S_RATES,
277 .formats = BF5XX_I2S_FORMATS,}, 306 .formats = BF5XX_I2S_FORMATS,},