diff options
author | Barry Song <barry.song@analog.com> | 2011-03-28 01:45:10 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-03-29 18:20:05 -0400 |
commit | 2c66cb99d134d787827ed1cd93cc59351ab66a95 (patch) | |
tree | 4c67200205b224947e9500b17af9537e54254a65 /sound/soc/blackfin | |
parent | bfe4ee0a935dccf5980ecb5605c66fe50feb9056 (diff) |
ASoC: Blackfin: push down SPORT settings from global variables
Now that we have multi-component support, take the time to unify the
SPORT implementations a bit and make the setup dynamic. This kills
off the global sport_handle which was shared across all the Blackfin
machine drivers. The pin management aspect is off loaded to platform
resources, and now multiple SPORTs can be instantiated simultaneously.
Signed-off-by: Barry Song <barry.song@analog.com>
Signed-off-by: Scott Jiang <scott.jiang@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Acked-by: Liam Girdwood <lrg@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/blackfin')
-rw-r--r-- | sound/soc/blackfin/bf5xx-ac97-pcm.c | 11 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ac97.c | 166 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ad1836.c | 40 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ad193x.c | 40 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ad1980.c | 43 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ad73311.c | 40 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-i2s-pcm.c | 21 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-i2s.c | 159 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-sport.c | 159 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-sport.h | 16 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ssm2602.c | 40 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-tdm-pcm.c | 21 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-tdm.c | 110 |
13 files changed, 416 insertions, 450 deletions
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index e940d26048d0..98b44b316e78 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c | |||
@@ -243,6 +243,9 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
243 | 243 | ||
244 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | 244 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) |
245 | { | 245 | { |
246 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
247 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
248 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
246 | struct snd_pcm_runtime *runtime = substream->runtime; | 249 | struct snd_pcm_runtime *runtime = substream->runtime; |
247 | int ret; | 250 | int ret; |
248 | 251 | ||
@@ -314,6 +317,9 @@ static struct snd_pcm_ops bf5xx_pcm_ac97_ops = { | |||
314 | 317 | ||
315 | static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | 318 | static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) |
316 | { | 319 | { |
320 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; | ||
321 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
322 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
317 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | 323 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; |
318 | struct snd_dma_buffer *buf = &substream->dma_buffer; | 324 | struct snd_dma_buffer *buf = &substream->dma_buffer; |
319 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max | 325 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max |
@@ -377,6 +383,9 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
377 | struct snd_dma_buffer *buf; | 383 | struct snd_dma_buffer *buf; |
378 | int stream; | 384 | int stream; |
379 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) | 385 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
386 | struct snd_soc_pcm_runtime *rtd = pcm->private_data; | ||
387 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
388 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
380 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max * | 389 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max * |
381 | sizeof(struct ac97_frame) / 4; | 390 | sizeof(struct ac97_frame) / 4; |
382 | #endif | 391 | #endif |
@@ -405,8 +414,6 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
405 | } | 414 | } |
406 | #endif | 415 | #endif |
407 | } | 416 | } |
408 | if (sport_handle) | ||
409 | sport_done(sport_handle); | ||
410 | } | 417 | } |
411 | 418 | ||
412 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | 419 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); |
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index ffbac26b9bce..6d2162590889 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c | |||
@@ -41,48 +41,7 @@ | |||
41 | * anomaly does not affect blackfin sound drivers. | 41 | * anomaly does not affect blackfin sound drivers. |
42 | */ | 42 | */ |
43 | 43 | ||
44 | static int *cmd_count; | 44 | static struct sport_device *ac97_sport_handle; |
45 | static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; | ||
46 | |||
47 | #define SPORT_REQ(x) \ | ||
48 | [x] = {P_SPORT##x##_TFS, P_SPORT##x##_DTPRI, P_SPORT##x##_TSCLK, \ | ||
49 | P_SPORT##x##_RFS, P_SPORT##x##_DRPRI, P_SPORT##x##_RSCLK, 0} | ||
50 | static u16 sport_req[][7] = { | ||
51 | #ifdef SPORT0_TCR1 | ||
52 | SPORT_REQ(0), | ||
53 | #endif | ||
54 | #ifdef SPORT1_TCR1 | ||
55 | SPORT_REQ(1), | ||
56 | #endif | ||
57 | #ifdef SPORT2_TCR1 | ||
58 | SPORT_REQ(2), | ||
59 | #endif | ||
60 | #ifdef SPORT3_TCR1 | ||
61 | SPORT_REQ(3), | ||
62 | #endif | ||
63 | }; | ||
64 | |||
65 | #define SPORT_PARAMS(x) \ | ||
66 | [x] = { \ | ||
67 | .dma_rx_chan = CH_SPORT##x##_RX, \ | ||
68 | .dma_tx_chan = CH_SPORT##x##_TX, \ | ||
69 | .err_irq = IRQ_SPORT##x##_ERROR, \ | ||
70 | .regs = (struct sport_register *)SPORT##x##_TCR1, \ | ||
71 | } | ||
72 | static struct sport_param sport_params[4] = { | ||
73 | #ifdef SPORT0_TCR1 | ||
74 | SPORT_PARAMS(0), | ||
75 | #endif | ||
76 | #ifdef SPORT1_TCR1 | ||
77 | SPORT_PARAMS(1), | ||
78 | #endif | ||
79 | #ifdef SPORT2_TCR1 | ||
80 | SPORT_PARAMS(2), | ||
81 | #endif | ||
82 | #ifdef SPORT3_TCR1 | ||
83 | SPORT_PARAMS(3), | ||
84 | #endif | ||
85 | }; | ||
86 | 45 | ||
87 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, | 46 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, |
88 | size_t count, unsigned int chan_mask) | 47 | size_t count, unsigned int chan_mask) |
@@ -140,7 +99,8 @@ static unsigned int sport_tx_curr_frag(struct sport_device *sport) | |||
140 | 99 | ||
141 | static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data) | 100 | static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data) |
142 | { | 101 | { |
143 | struct sport_device *sport = sport_handle; | 102 | struct sport_device *sport = ac97_sport_handle; |
103 | int *cmd_count = sport->private_data; | ||
144 | int nextfrag = sport_tx_curr_frag(sport); | 104 | int nextfrag = sport_tx_curr_frag(sport); |
145 | struct ac97_frame *nextwrite; | 105 | struct ac97_frame *nextwrite; |
146 | 106 | ||
@@ -161,6 +121,7 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data) | |||
161 | static unsigned short bf5xx_ac97_read(struct snd_ac97 *ac97, | 121 | static unsigned short bf5xx_ac97_read(struct snd_ac97 *ac97, |
162 | unsigned short reg) | 122 | unsigned short reg) |
163 | { | 123 | { |
124 | struct sport_device *sport_handle = ac97_sport_handle; | ||
164 | struct ac97_frame out_frame[2], in_frame[2]; | 125 | struct ac97_frame out_frame[2], in_frame[2]; |
165 | 126 | ||
166 | pr_debug("%s enter 0x%x\n", __func__, reg); | 127 | pr_debug("%s enter 0x%x\n", __func__, reg); |
@@ -185,6 +146,8 @@ static unsigned short bf5xx_ac97_read(struct snd_ac97 *ac97, | |||
185 | void bf5xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | 146 | void bf5xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, |
186 | unsigned short val) | 147 | unsigned short val) |
187 | { | 148 | { |
149 | struct sport_device *sport_handle = ac97_sport_handle; | ||
150 | |||
188 | pr_debug("%s enter 0x%x:0x%04x\n", __func__, reg, val); | 151 | pr_debug("%s enter 0x%x:0x%04x\n", __func__, reg, val); |
189 | 152 | ||
190 | if (sport_handle->tx_run) { | 153 | if (sport_handle->tx_run) { |
@@ -203,28 +166,19 @@ void bf5xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | |||
203 | 166 | ||
204 | static void bf5xx_ac97_warm_reset(struct snd_ac97 *ac97) | 167 | static void bf5xx_ac97_warm_reset(struct snd_ac97 *ac97) |
205 | { | 168 | { |
206 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF561) || \ | 169 | struct sport_device *sport_handle = ac97_sport_handle; |
207 | (defined(BF537_FAMILY) && (CONFIG_SND_BF5XX_SPORT_NUM == 1)) | 170 | u16 gpio = P_IDENT(sport_handle->pin_req[3]); |
208 | |||
209 | #define CONCAT(a, b, c) a ## b ## c | ||
210 | #define BFIN_SPORT_RFS(x) CONCAT(P_SPORT, x, _RFS) | ||
211 | |||
212 | u16 per = BFIN_SPORT_RFS(CONFIG_SND_BF5XX_SPORT_NUM); | ||
213 | u16 gpio = P_IDENT(BFIN_SPORT_RFS(CONFIG_SND_BF5XX_SPORT_NUM)); | ||
214 | 171 | ||
215 | pr_debug("%s enter\n", __func__); | 172 | pr_debug("%s enter\n", __func__); |
216 | 173 | ||
217 | peripheral_free(per); | 174 | peripheral_free_list(sport_handle->pin_req); |
218 | gpio_request(gpio, "bf5xx-ac97"); | 175 | gpio_request(gpio, "bf5xx-ac97"); |
219 | gpio_direction_output(gpio, 1); | 176 | gpio_direction_output(gpio, 1); |
220 | udelay(2); | 177 | udelay(2); |
221 | gpio_set_value(gpio, 0); | 178 | gpio_set_value(gpio, 0); |
222 | udelay(1); | 179 | udelay(1); |
223 | gpio_free(gpio); | 180 | gpio_free(gpio); |
224 | peripheral_request(per, "soc-audio"); | 181 | peripheral_request_list(sport_handle->pin_req, "soc-audio"); |
225 | #else | ||
226 | pr_info("%s: Not implemented\n", __func__); | ||
227 | #endif | ||
228 | } | 182 | } |
229 | 183 | ||
230 | static void bf5xx_ac97_cold_reset(struct snd_ac97 *ac97) | 184 | static void bf5xx_ac97_cold_reset(struct snd_ac97 *ac97) |
@@ -306,18 +260,32 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai) | |||
306 | #define bf5xx_ac97_resume NULL | 260 | #define bf5xx_ac97_resume NULL |
307 | #endif | 261 | #endif |
308 | 262 | ||
309 | static int bf5xx_ac97_probe(struct snd_soc_dai *dai) | 263 | static struct snd_soc_dai_driver bfin_ac97_dai = { |
264 | .ac97_control = 1, | ||
265 | .suspend = bf5xx_ac97_suspend, | ||
266 | .resume = bf5xx_ac97_resume, | ||
267 | .playback = { | ||
268 | .stream_name = "AC97 Playback", | ||
269 | .channels_min = 2, | ||
270 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | ||
271 | .channels_max = 6, | ||
272 | #else | ||
273 | .channels_max = 2, | ||
274 | #endif | ||
275 | .rates = SNDRV_PCM_RATE_48000, | ||
276 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | ||
277 | .capture = { | ||
278 | .stream_name = "AC97 Capture", | ||
279 | .channels_min = 2, | ||
280 | .channels_max = 2, | ||
281 | .rates = SNDRV_PCM_RATE_48000, | ||
282 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | ||
283 | }; | ||
284 | |||
285 | static int __devinit asoc_bfin_ac97_probe(struct platform_device *pdev) | ||
310 | { | 286 | { |
311 | int ret = 0; | 287 | struct sport_device *sport_handle; |
312 | cmd_count = (int *)get_zeroed_page(GFP_KERNEL); | 288 | int ret; |
313 | if (cmd_count == NULL) | ||
314 | return -ENOMEM; | ||
315 | |||
316 | if (peripheral_request_list(sport_req[sport_num], "soc-audio")) { | ||
317 | pr_err("Requesting Peripherals failed\n"); | ||
318 | ret = -EFAULT; | ||
319 | goto peripheral_err; | ||
320 | } | ||
321 | 289 | ||
322 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 290 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
323 | /* Request PB3 as reset pin */ | 291 | /* Request PB3 as reset pin */ |
@@ -329,12 +297,14 @@ static int bf5xx_ac97_probe(struct snd_soc_dai *dai) | |||
329 | } | 297 | } |
330 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); | 298 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); |
331 | #endif | 299 | #endif |
332 | sport_handle = sport_init(&sport_params[sport_num], 2, \ | 300 | |
333 | sizeof(struct ac97_frame), NULL); | 301 | sport_handle = sport_init(pdev, 2, sizeof(struct ac97_frame), |
302 | PAGE_SIZE); | ||
334 | if (!sport_handle) { | 303 | if (!sport_handle) { |
335 | ret = -ENODEV; | 304 | ret = -ENODEV; |
336 | goto sport_err; | 305 | goto sport_err; |
337 | } | 306 | } |
307 | |||
338 | /*SPORT works in TDM mode to simulate AC97 transfers*/ | 308 | /*SPORT works in TDM mode to simulate AC97 transfers*/ |
339 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | 309 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) |
340 | ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 1); | 310 | ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 1); |
@@ -361,67 +331,37 @@ static int bf5xx_ac97_probe(struct snd_soc_dai *dai) | |||
361 | goto sport_config_err; | 331 | goto sport_config_err; |
362 | } | 332 | } |
363 | 333 | ||
334 | ret = snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai); | ||
335 | if (ret) { | ||
336 | pr_err("Failed to register DAI: %d\n", ret); | ||
337 | goto sport_config_err; | ||
338 | } | ||
339 | |||
340 | ac97_sport_handle = sport_handle; | ||
341 | |||
364 | return 0; | 342 | return 0; |
365 | 343 | ||
366 | sport_config_err: | 344 | sport_config_err: |
367 | kfree(sport_handle); | 345 | sport_done(sport_handle); |
368 | sport_err: | 346 | sport_err: |
369 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 347 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
370 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 348 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
371 | gpio_err: | 349 | gpio_err: |
372 | #endif | 350 | #endif |
373 | peripheral_free_list(sport_req[sport_num]); | ||
374 | peripheral_err: | ||
375 | free_page((unsigned long)cmd_count); | ||
376 | cmd_count = NULL; | ||
377 | 351 | ||
378 | return ret; | 352 | return ret; |
379 | } | 353 | } |
380 | 354 | ||
381 | static int bf5xx_ac97_remove(struct snd_soc_dai *dai) | 355 | static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev) |
382 | { | 356 | { |
383 | free_page((unsigned long)cmd_count); | 357 | struct sport_device *sport_handle = platform_get_drvdata(pdev); |
384 | cmd_count = NULL; | 358 | |
385 | peripheral_free_list(sport_req[sport_num]); | 359 | snd_soc_unregister_dai(&pdev->dev); |
360 | sport_done(sport_handle); | ||
386 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 361 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
387 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 362 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
388 | #endif | 363 | #endif |
389 | return 0; | ||
390 | } | ||
391 | |||
392 | struct snd_soc_dai_driver bfin_ac97_dai = { | ||
393 | .ac97_control = 1, | ||
394 | .probe = bf5xx_ac97_probe, | ||
395 | .remove = bf5xx_ac97_remove, | ||
396 | .suspend = bf5xx_ac97_suspend, | ||
397 | .resume = bf5xx_ac97_resume, | ||
398 | .playback = { | ||
399 | .stream_name = "AC97 Playback", | ||
400 | .channels_min = 2, | ||
401 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | ||
402 | .channels_max = 6, | ||
403 | #else | ||
404 | .channels_max = 2, | ||
405 | #endif | ||
406 | .rates = SNDRV_PCM_RATE_48000, | ||
407 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | ||
408 | .capture = { | ||
409 | .stream_name = "AC97 Capture", | ||
410 | .channels_min = 2, | ||
411 | .channels_max = 2, | ||
412 | .rates = SNDRV_PCM_RATE_48000, | ||
413 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | ||
414 | }; | ||
415 | EXPORT_SYMBOL_GPL(bfin_ac97_dai); | ||
416 | |||
417 | static __devinit int asoc_bfin_ac97_probe(struct platform_device *pdev) | ||
418 | { | ||
419 | return snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai); | ||
420 | } | ||
421 | 364 | ||
422 | static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev) | ||
423 | { | ||
424 | snd_soc_unregister_dai(&pdev->dev); | ||
425 | return 0; | 365 | return 0; |
426 | } | 366 | } |
427 | 367 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index 5d9d9e2805b8..ea4951cf5526 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c | |||
@@ -29,22 +29,12 @@ | |||
29 | #include <asm/portmux.h> | 29 | #include <asm/portmux.h> |
30 | 30 | ||
31 | #include "../codecs/ad1836.h" | 31 | #include "../codecs/ad1836.h" |
32 | #include "bf5xx-sport.h" | ||
33 | 32 | ||
34 | #include "bf5xx-tdm-pcm.h" | 33 | #include "bf5xx-tdm-pcm.h" |
35 | #include "bf5xx-tdm.h" | 34 | #include "bf5xx-tdm.h" |
36 | 35 | ||
37 | static struct snd_soc_card bf5xx_ad1836; | 36 | static struct snd_soc_card bf5xx_ad1836; |
38 | 37 | ||
39 | static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream) | ||
40 | { | ||
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
43 | |||
44 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, | 38 | static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, |
49 | struct snd_pcm_hw_params *params) | 39 | struct snd_pcm_hw_params *params) |
50 | { | 40 | { |
@@ -75,23 +65,33 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, | |||
75 | } | 65 | } |
76 | 66 | ||
77 | static struct snd_soc_ops bf5xx_ad1836_ops = { | 67 | static struct snd_soc_ops bf5xx_ad1836_ops = { |
78 | .startup = bf5xx_ad1836_startup, | ||
79 | .hw_params = bf5xx_ad1836_hw_params, | 68 | .hw_params = bf5xx_ad1836_hw_params, |
80 | }; | 69 | }; |
81 | 70 | ||
82 | static struct snd_soc_dai_link bf5xx_ad1836_dai = { | 71 | static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { |
83 | .name = "ad1836", | 72 | { |
84 | .stream_name = "AD1836", | 73 | .name = "ad1836", |
85 | .cpu_dai_name = "bfin-tdm", | 74 | .stream_name = "AD1836", |
86 | .codec_dai_name = "ad1836-hifi", | 75 | .cpu_dai_name = "bfin-tdm.0", |
87 | .platform_name = "bfin-tdm-pcm-audio", | 76 | .codec_dai_name = "ad1836-hifi", |
88 | .codec_name = "ad1836.0", | 77 | .platform_name = "bfin-tdm-pcm-audio", |
89 | .ops = &bf5xx_ad1836_ops, | 78 | .codec_name = "ad1836.0", |
79 | .ops = &bf5xx_ad1836_ops, | ||
80 | }, | ||
81 | { | ||
82 | .name = "ad1836", | ||
83 | .stream_name = "AD1836", | ||
84 | .cpu_dai_name = "bfin-tdm.1", | ||
85 | .codec_dai_name = "ad1836-hifi", | ||
86 | .platform_name = "bfin-tdm-pcm-audio", | ||
87 | .codec_name = "ad1836.0", | ||
88 | .ops = &bf5xx_ad1836_ops, | ||
89 | }, | ||
90 | }; | 90 | }; |
91 | 91 | ||
92 | static struct snd_soc_card bf5xx_ad1836 = { | 92 | static struct snd_soc_card bf5xx_ad1836 = { |
93 | .name = "bfin-ad1836", | 93 | .name = "bfin-ad1836", |
94 | .dai_link = &bf5xx_ad1836_dai, | 94 | .dai_link = &bf5xx_ad1836_dai[CONFIG_SND_BF5XX_SPORT_NUM], |
95 | .num_links = 1, | 95 | .num_links = 1, |
96 | }; | 96 | }; |
97 | 97 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c index 355094fad18a..d6651c033cb7 100644 --- a/sound/soc/blackfin/bf5xx-ad193x.c +++ b/sound/soc/blackfin/bf5xx-ad193x.c | |||
@@ -38,22 +38,12 @@ | |||
38 | #include <asm/portmux.h> | 38 | #include <asm/portmux.h> |
39 | 39 | ||
40 | #include "../codecs/ad193x.h" | 40 | #include "../codecs/ad193x.h" |
41 | #include "bf5xx-sport.h" | ||
42 | 41 | ||
43 | #include "bf5xx-tdm-pcm.h" | 42 | #include "bf5xx-tdm-pcm.h" |
44 | #include "bf5xx-tdm.h" | 43 | #include "bf5xx-tdm.h" |
45 | 44 | ||
46 | static struct snd_soc_card bf5xx_ad193x; | 45 | static struct snd_soc_card bf5xx_ad193x; |
47 | 46 | ||
48 | static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream) | ||
49 | { | ||
50 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
51 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
52 | |||
53 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, | 47 | static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, |
58 | struct snd_pcm_hw_params *params) | 48 | struct snd_pcm_hw_params *params) |
59 | { | 49 | { |
@@ -103,23 +93,33 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream, | |||
103 | } | 93 | } |
104 | 94 | ||
105 | static struct snd_soc_ops bf5xx_ad193x_ops = { | 95 | static struct snd_soc_ops bf5xx_ad193x_ops = { |
106 | .startup = bf5xx_ad193x_startup, | ||
107 | .hw_params = bf5xx_ad193x_hw_params, | 96 | .hw_params = bf5xx_ad193x_hw_params, |
108 | }; | 97 | }; |
109 | 98 | ||
110 | static struct snd_soc_dai_link bf5xx_ad193x_dai = { | 99 | static struct snd_soc_dai_link bf5xx_ad193x_dai[] = { |
111 | .name = "ad193x", | 100 | { |
112 | .stream_name = "AD193X", | 101 | .name = "ad193x", |
113 | .cpu_dai_name = "bfin-tdm", | 102 | .stream_name = "AD193X", |
114 | .codec_dai_name ="ad193x-hifi", | 103 | .cpu_dai_name = "bfin-tdm.0", |
115 | .platform_name = "bfin-tdm-pcm-audio", | 104 | .codec_dai_name ="ad193x-hifi", |
116 | .codec_name = "ad193x.5", | 105 | .platform_name = "bfin-tdm-pcm-audio", |
117 | .ops = &bf5xx_ad193x_ops, | 106 | .codec_name = "ad193x.5", |
107 | .ops = &bf5xx_ad193x_ops, | ||
108 | }, | ||
109 | { | ||
110 | .name = "ad193x", | ||
111 | .stream_name = "AD193X", | ||
112 | .cpu_dai_name = "bfin-tdm.1", | ||
113 | .codec_dai_name ="ad193x-hifi", | ||
114 | .platform_name = "bfin-tdm-pcm-audio", | ||
115 | .codec_name = "ad193x.5", | ||
116 | .ops = &bf5xx_ad193x_ops, | ||
117 | }, | ||
118 | }; | 118 | }; |
119 | 119 | ||
120 | static struct snd_soc_card bf5xx_ad193x = { | 120 | static struct snd_soc_card bf5xx_ad193x = { |
121 | .name = "bfin-ad193x", | 121 | .name = "bfin-ad193x", |
122 | .dai_link = &bf5xx_ad193x_dai, | 122 | .dai_link = &bf5xx_ad193x_dai[CONFIG_SND_BF5XX_SPORT_NUM], |
123 | .num_links = 1, | 123 | .num_links = 1, |
124 | }; | 124 | }; |
125 | 125 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c index a3812408c6a5..06a84b211b52 100644 --- a/sound/soc/blackfin/bf5xx-ad1980.c +++ b/sound/soc/blackfin/bf5xx-ad1980.c | |||
@@ -47,39 +47,34 @@ | |||
47 | #include <asm/portmux.h> | 47 | #include <asm/portmux.h> |
48 | 48 | ||
49 | #include "../codecs/ad1980.h" | 49 | #include "../codecs/ad1980.h" |
50 | #include "bf5xx-sport.h" | 50 | |
51 | #include "bf5xx-ac97-pcm.h" | 51 | #include "bf5xx-ac97-pcm.h" |
52 | #include "bf5xx-ac97.h" | 52 | #include "bf5xx-ac97.h" |
53 | 53 | ||
54 | static struct snd_soc_card bf5xx_board; | 54 | static struct snd_soc_card bf5xx_board; |
55 | 55 | ||
56 | static int bf5xx_board_startup(struct snd_pcm_substream *substream) | 56 | static struct snd_soc_dai_link bf5xx_board_dai[] = { |
57 | { | 57 | { |
58 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 58 | .name = "AC97", |
59 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 59 | .stream_name = "AC97 HiFi", |
60 | 60 | .cpu_dai_name = "bfin-ac97.0", | |
61 | pr_debug("%s enter\n", __func__); | 61 | .codec_dai_name = "ad1980-hifi", |
62 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); | 62 | .platform_name = "bfin-ac97-pcm-audio", |
63 | return 0; | 63 | .codec_name = "ad1980", |
64 | } | 64 | }, |
65 | 65 | { | |
66 | static struct snd_soc_ops bf5xx_board_ops = { | 66 | .name = "AC97", |
67 | .startup = bf5xx_board_startup, | 67 | .stream_name = "AC97 HiFi", |
68 | }; | 68 | .cpu_dai_name = "bfin-ac97.1", |
69 | 69 | .codec_dai_name = "ad1980-hifi", | |
70 | static struct snd_soc_dai_link bf5xx_board_dai = { | 70 | .platform_name = "bfin-ac97-pcm-audio", |
71 | .name = "AC97", | 71 | .codec_name = "ad1980", |
72 | .stream_name = "AC97 HiFi", | 72 | }, |
73 | .cpu_dai_name = "bfin-ac97", | ||
74 | .codec_dai_name = "ad1980-hifi", | ||
75 | .platform_name = "bfin-ac97-pcm-audio", | ||
76 | .codec_name = "ad1980", | ||
77 | .ops = &bf5xx_board_ops, | ||
78 | }; | 73 | }; |
79 | 74 | ||
80 | static struct snd_soc_card bf5xx_board = { | 75 | static struct snd_soc_card bf5xx_board = { |
81 | .name = "bfin-ad1980", | 76 | .name = "bfin-ad1980", |
82 | .dai_link = &bf5xx_board_dai, | 77 | .dai_link = &bf5xx_board_dai[CONFIG_SND_BF5XX_SPORT_NUM], |
83 | .num_links = 1, | 78 | .num_links = 1, |
84 | }; | 79 | }; |
85 | 80 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c index 9f0d4f3c590f..732a247f2527 100644 --- a/sound/soc/blackfin/bf5xx-ad73311.c +++ b/sound/soc/blackfin/bf5xx-ad73311.c | |||
@@ -145,16 +145,6 @@ static int bf5xx_probe(struct platform_device *pdev) | |||
145 | return 0; | 145 | return 0; |
146 | } | 146 | } |
147 | 147 | ||
148 | static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream) | ||
149 | { | ||
150 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
151 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
152 | |||
153 | pr_debug("%s enter\n", __func__); | ||
154 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream, | 148 | static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream, |
159 | struct snd_pcm_hw_params *params) | 149 | struct snd_pcm_hw_params *params) |
160 | { | 150 | { |
@@ -176,24 +166,34 @@ static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream, | |||
176 | 166 | ||
177 | 167 | ||
178 | static struct snd_soc_ops bf5xx_ad73311_ops = { | 168 | static struct snd_soc_ops bf5xx_ad73311_ops = { |
179 | .startup = bf5xx_ad73311_startup, | ||
180 | .hw_params = bf5xx_ad73311_hw_params, | 169 | .hw_params = bf5xx_ad73311_hw_params, |
181 | }; | 170 | }; |
182 | 171 | ||
183 | static struct snd_soc_dai_link bf5xx_ad73311_dai = { | 172 | static struct snd_soc_dai_link bf5xx_ad73311_dai[] = { |
184 | .name = "ad73311", | 173 | { |
185 | .stream_name = "AD73311", | 174 | .name = "ad73311", |
186 | .cpu_dai_name = "bfin-i2s", | 175 | .stream_name = "AD73311", |
187 | .codec_dai_name = "ad73311-hifi", | 176 | .cpu_dai_name = "bfin-i2s.0", |
188 | .platform_name = "bfin-i2s-pcm-audio", | 177 | .codec_dai_name = "ad73311-hifi", |
189 | .codec_name = "ad73311", | 178 | .platform_name = "bfin-i2s-pcm-audio", |
190 | .ops = &bf5xx_ad73311_ops, | 179 | .codec_name = "ad73311", |
180 | .ops = &bf5xx_ad73311_ops, | ||
181 | }, | ||
182 | { | ||
183 | .name = "ad73311", | ||
184 | .stream_name = "AD73311", | ||
185 | .cpu_dai_name = "bfin-i2s.1", | ||
186 | .codec_dai_name = "ad73311-hifi", | ||
187 | .platform_name = "bfin-i2s-pcm-audio", | ||
188 | .codec_name = "ad73311", | ||
189 | .ops = &bf5xx_ad73311_ops, | ||
190 | }, | ||
191 | }; | 191 | }; |
192 | 192 | ||
193 | static struct snd_soc_card bf5xx_ad73311 = { | 193 | static struct snd_soc_card bf5xx_ad73311 = { |
194 | .name = "bfin-ad73311", | 194 | .name = "bfin-ad73311", |
195 | .probe = bf5xx_probe, | 195 | .probe = bf5xx_probe, |
196 | .dai_link = &bf5xx_ad73311_dai, | 196 | .dai_link = &bf5xx_ad73311_dai[CONFIG_SND_BF5XX_SPORT_NUM], |
197 | .num_links = 1, | 197 | .num_links = 1, |
198 | }; | 198 | }; |
199 | 199 | ||
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 50b1df8c1416..b5101efd1c87 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -148,10 +148,15 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
148 | 148 | ||
149 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | 149 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) |
150 | { | 150 | { |
151 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
152 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
153 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
151 | struct snd_pcm_runtime *runtime = substream->runtime; | 154 | struct snd_pcm_runtime *runtime = substream->runtime; |
155 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
152 | int ret; | 156 | int ret; |
153 | 157 | ||
154 | pr_debug("%s enter\n", __func__); | 158 | pr_debug("%s enter\n", __func__); |
159 | |||
155 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); | 160 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); |
156 | 161 | ||
157 | ret = snd_pcm_hw_constraint_integer(runtime, \ | 162 | ret = snd_pcm_hw_constraint_integer(runtime, \ |
@@ -159,9 +164,14 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | |||
159 | if (ret < 0) | 164 | if (ret < 0) |
160 | goto out; | 165 | goto out; |
161 | 166 | ||
162 | if (sport_handle != NULL) | 167 | if (sport_handle != NULL) { |
168 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
169 | sport_handle->tx_buf = buf->area; | ||
170 | else | ||
171 | sport_handle->rx_buf = buf->area; | ||
172 | |||
163 | runtime->private_data = sport_handle; | 173 | runtime->private_data = sport_handle; |
164 | else { | 174 | } else { |
165 | pr_err("sport_handle is NULL\n"); | 175 | pr_err("sport_handle is NULL\n"); |
166 | return -1; | 176 | return -1; |
167 | } | 177 | } |
@@ -214,11 +224,6 @@ static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | |||
214 | pr_debug("%s, area:%p, size:0x%08lx\n", __func__, | 224 | pr_debug("%s, area:%p, size:0x%08lx\n", __func__, |
215 | buf->area, buf->bytes); | 225 | buf->area, buf->bytes); |
216 | 226 | ||
217 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
218 | sport_handle->tx_buf = buf->area; | ||
219 | else | ||
220 | sport_handle->rx_buf = buf->area; | ||
221 | |||
222 | return 0; | 227 | return 0; |
223 | } | 228 | } |
224 | 229 | ||
@@ -239,8 +244,6 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
239 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); | 244 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); |
240 | buf->area = NULL; | 245 | buf->area = NULL; |
241 | } | 246 | } |
242 | if (sport_handle) | ||
243 | sport_done(sport_handle); | ||
244 | } | 247 | } |
245 | 248 | ||
246 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | 249 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); |
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index dacd86c2ead4..00cc3e00b2fe 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c | |||
@@ -51,59 +51,24 @@ struct bf5xx_i2s_port { | |||
51 | int configured; | 51 | int configured; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static struct bf5xx_i2s_port bf5xx_i2s; | ||
55 | static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; | ||
56 | |||
57 | static struct sport_param sport_params[2] = { | ||
58 | { | ||
59 | .dma_rx_chan = CH_SPORT0_RX, | ||
60 | .dma_tx_chan = CH_SPORT0_TX, | ||
61 | .err_irq = IRQ_SPORT0_ERROR, | ||
62 | .regs = (struct sport_register *)SPORT0_TCR1, | ||
63 | }, | ||
64 | { | ||
65 | .dma_rx_chan = CH_SPORT1_RX, | ||
66 | .dma_tx_chan = CH_SPORT1_TX, | ||
67 | .err_irq = IRQ_SPORT1_ERROR, | ||
68 | .regs = (struct sport_register *)SPORT1_TCR1, | ||
69 | } | ||
70 | }; | ||
71 | |||
72 | /* | ||
73 | * Setting the TFS pin selector for SPORT 0 based on whether the selected | ||
74 | * port id F or G. If the port is F then no conflict should exist for the | ||
75 | * TFS. When Port G is selected and EMAC then there is a conflict between | ||
76 | * the PHY interrupt line and TFS. Current settings prevent the conflict | ||
77 | * by ignoring the TFS pin when Port G is selected. This allows both | ||
78 | * codecs and EMAC using Port G concurrently. | ||
79 | */ | ||
80 | #ifdef CONFIG_BF527_SPORT0_PORTG | ||
81 | #define LOCAL_SPORT0_TFS (0) | ||
82 | #else | ||
83 | #define LOCAL_SPORT0_TFS (P_SPORT0_TFS) | ||
84 | #endif | ||
85 | |||
86 | static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, | ||
87 | P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0}, | ||
88 | {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI, | ||
89 | P_SPORT1_RSCLK, P_SPORT1_TFS, 0} }; | ||
90 | |||
91 | static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 54 | static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
92 | unsigned int fmt) | 55 | unsigned int fmt) |
93 | { | 56 | { |
57 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
58 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | ||
94 | int ret = 0; | 59 | int ret = 0; |
95 | 60 | ||
96 | /* interface format:support I2S,slave mode */ | 61 | /* interface format:support I2S,slave mode */ |
97 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 62 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
98 | case SND_SOC_DAIFMT_I2S: | 63 | case SND_SOC_DAIFMT_I2S: |
99 | bf5xx_i2s.tcr1 |= TFSR | TCKFE; | 64 | bf5xx_i2s->tcr1 |= TFSR | TCKFE; |
100 | bf5xx_i2s.rcr1 |= RFSR | RCKFE; | 65 | bf5xx_i2s->rcr1 |= RFSR | RCKFE; |
101 | bf5xx_i2s.tcr2 |= TSFSE; | 66 | bf5xx_i2s->tcr2 |= TSFSE; |
102 | bf5xx_i2s.rcr2 |= RSFSE; | 67 | bf5xx_i2s->rcr2 |= RSFSE; |
103 | break; | 68 | break; |
104 | case SND_SOC_DAIFMT_DSP_A: | 69 | case SND_SOC_DAIFMT_DSP_A: |
105 | bf5xx_i2s.tcr1 |= TFSR; | 70 | bf5xx_i2s->tcr1 |= TFSR; |
106 | bf5xx_i2s.rcr1 |= RFSR; | 71 | bf5xx_i2s->rcr1 |= RFSR; |
107 | break; | 72 | break; |
108 | case SND_SOC_DAIFMT_LEFT_J: | 73 | case SND_SOC_DAIFMT_LEFT_J: |
109 | ret = -EINVAL; | 74 | ret = -EINVAL; |
@@ -135,33 +100,35 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
135 | struct snd_pcm_hw_params *params, | 100 | struct snd_pcm_hw_params *params, |
136 | struct snd_soc_dai *dai) | 101 | struct snd_soc_dai *dai) |
137 | { | 102 | { |
103 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
104 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | ||
138 | int ret = 0; | 105 | int ret = 0; |
139 | 106 | ||
140 | bf5xx_i2s.tcr2 &= ~0x1f; | 107 | bf5xx_i2s->tcr2 &= ~0x1f; |
141 | bf5xx_i2s.rcr2 &= ~0x1f; | 108 | bf5xx_i2s->rcr2 &= ~0x1f; |
142 | switch (params_format(params)) { | 109 | switch (params_format(params)) { |
143 | case SNDRV_PCM_FORMAT_S8: | 110 | case SNDRV_PCM_FORMAT_S8: |
144 | bf5xx_i2s->tcr2 |= 7; | 111 | bf5xx_i2s->tcr2 |= 7; |
145 | bf5xx_i2s->rcr2 |= 7; | 112 | bf5xx_i2s->rcr2 |= 7; |
146 | sport_handle->wdsize = 1; | 113 | sport_handle->wdsize = 1; |
147 | case SNDRV_PCM_FORMAT_S16_LE: | 114 | case SNDRV_PCM_FORMAT_S16_LE: |
148 | bf5xx_i2s.tcr2 |= 15; | 115 | bf5xx_i2s->tcr2 |= 15; |
149 | bf5xx_i2s.rcr2 |= 15; | 116 | bf5xx_i2s->rcr2 |= 15; |
150 | sport_handle->wdsize = 2; | 117 | sport_handle->wdsize = 2; |
151 | break; | 118 | break; |
152 | case SNDRV_PCM_FORMAT_S24_LE: | 119 | case SNDRV_PCM_FORMAT_S24_LE: |
153 | bf5xx_i2s.tcr2 |= 23; | 120 | bf5xx_i2s->tcr2 |= 23; |
154 | bf5xx_i2s.rcr2 |= 23; | 121 | bf5xx_i2s->rcr2 |= 23; |
155 | sport_handle->wdsize = 3; | 122 | sport_handle->wdsize = 3; |
156 | break; | 123 | break; |
157 | case SNDRV_PCM_FORMAT_S32_LE: | 124 | case SNDRV_PCM_FORMAT_S32_LE: |
158 | bf5xx_i2s.tcr2 |= 31; | 125 | bf5xx_i2s->tcr2 |= 31; |
159 | bf5xx_i2s.rcr2 |= 31; | 126 | bf5xx_i2s->rcr2 |= 31; |
160 | sport_handle->wdsize = 4; | 127 | sport_handle->wdsize = 4; |
161 | break; | 128 | break; |
162 | } | 129 | } |
163 | 130 | ||
164 | if (!bf5xx_i2s.configured) { | 131 | if (!bf5xx_i2s->configured) { |
165 | /* | 132 | /* |
166 | * TX and RX are not independent,they are enabled at the | 133 | * TX and RX are not independent,they are enabled at the |
167 | * same time, even if only one side is running. So, we | 134 | * same time, even if only one side is running. So, we |
@@ -170,16 +137,16 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
170 | * | 137 | * |
171 | * CPU DAI:slave mode. | 138 | * CPU DAI:slave mode. |
172 | */ | 139 | */ |
173 | bf5xx_i2s.configured = 1; | 140 | bf5xx_i2s->configured = 1; |
174 | ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1, | 141 | ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1, |
175 | bf5xx_i2s.rcr2, 0, 0); | 142 | bf5xx_i2s->rcr2, 0, 0); |
176 | if (ret) { | 143 | if (ret) { |
177 | pr_err("SPORT is busy!\n"); | 144 | pr_err("SPORT is busy!\n"); |
178 | return -EBUSY; | 145 | return -EBUSY; |
179 | } | 146 | } |
180 | 147 | ||
181 | ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1, | 148 | ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1, |
182 | bf5xx_i2s.tcr2, 0, 0); | 149 | bf5xx_i2s->tcr2, 0, 0); |
183 | if (ret) { | 150 | if (ret) { |
184 | pr_err("SPORT is busy!\n"); | 151 | pr_err("SPORT is busy!\n"); |
185 | return -EBUSY; | 152 | return -EBUSY; |
@@ -192,41 +159,19 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
192 | static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream, | 159 | static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream, |
193 | struct snd_soc_dai *dai) | 160 | struct snd_soc_dai *dai) |
194 | { | 161 | { |
162 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
163 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | ||
164 | |||
195 | pr_debug("%s enter\n", __func__); | 165 | pr_debug("%s enter\n", __func__); |
196 | /* No active stream, SPORT is allowed to be configured again. */ | 166 | /* No active stream, SPORT is allowed to be configured again. */ |
197 | if (!dai->active) | 167 | if (!dai->active) |
198 | bf5xx_i2s.configured = 0; | 168 | bf5xx_i2s->configured = 0; |
199 | } | ||
200 | |||
201 | static int bf5xx_i2s_probe(struct snd_soc_dai *dai) | ||
202 | { | ||
203 | pr_debug("%s enter\n", __func__); | ||
204 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { | ||
205 | pr_err("Requesting Peripherals failed\n"); | ||
206 | return -EFAULT; | ||
207 | } | ||
208 | |||
209 | /* request DMA for SPORT */ | ||
210 | sport_handle = sport_init(&sport_params[sport_num], 4, \ | ||
211 | 2 * sizeof(u32), NULL); | ||
212 | if (!sport_handle) { | ||
213 | peripheral_free_list(&sport_req[sport_num][0]); | ||
214 | return -ENODEV; | ||
215 | } | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int bf5xx_i2s_remove(struct snd_soc_dai *dai) | ||
221 | { | ||
222 | pr_debug("%s enter\n", __func__); | ||
223 | peripheral_free_list(&sport_req[sport_num][0]); | ||
224 | return 0; | ||
225 | } | 169 | } |
226 | 170 | ||
227 | #ifdef CONFIG_PM | 171 | #ifdef CONFIG_PM |
228 | static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) | 172 | static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) |
229 | { | 173 | { |
174 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
230 | 175 | ||
231 | pr_debug("%s : sport %d\n", __func__, dai->id); | 176 | pr_debug("%s : sport %d\n", __func__, dai->id); |
232 | 177 | ||
@@ -239,19 +184,21 @@ static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) | |||
239 | 184 | ||
240 | static int bf5xx_i2s_resume(struct snd_soc_dai *dai) | 185 | static int bf5xx_i2s_resume(struct snd_soc_dai *dai) |
241 | { | 186 | { |
187 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
188 | struct bf5xx_i2s_port *bf5xx_i2s = sport_handle->private_data; | ||
242 | int ret; | 189 | int ret; |
243 | 190 | ||
244 | pr_debug("%s : sport %d\n", __func__, dai->id); | 191 | pr_debug("%s : sport %d\n", __func__, dai->id); |
245 | 192 | ||
246 | ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1, | 193 | ret = sport_config_rx(sport_handle, bf5xx_i2s->rcr1, |
247 | bf5xx_i2s.rcr2, 0, 0); | 194 | bf5xx_i2s->rcr2, 0, 0); |
248 | if (ret) { | 195 | if (ret) { |
249 | pr_err("SPORT is busy!\n"); | 196 | pr_err("SPORT is busy!\n"); |
250 | return -EBUSY; | 197 | return -EBUSY; |
251 | } | 198 | } |
252 | 199 | ||
253 | ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1, | 200 | ret = sport_config_tx(sport_handle, bf5xx_i2s->tcr1, |
254 | bf5xx_i2s.tcr2, 0, 0); | 201 | bf5xx_i2s->tcr2, 0, 0); |
255 | if (ret) { | 202 | if (ret) { |
256 | pr_err("SPORT is busy!\n"); | 203 | pr_err("SPORT is busy!\n"); |
257 | return -EBUSY; | 204 | return -EBUSY; |
@@ -283,8 +230,6 @@ static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { | |||
283 | }; | 230 | }; |
284 | 231 | ||
285 | static struct snd_soc_dai_driver bf5xx_i2s_dai = { | 232 | static struct snd_soc_dai_driver bf5xx_i2s_dai = { |
286 | .probe = bf5xx_i2s_probe, | ||
287 | .remove = bf5xx_i2s_remove, | ||
288 | .suspend = bf5xx_i2s_suspend, | 233 | .suspend = bf5xx_i2s_suspend, |
289 | .resume = bf5xx_i2s_resume, | 234 | .resume = bf5xx_i2s_resume, |
290 | .playback = { | 235 | .playback = { |
@@ -300,21 +245,43 @@ static struct snd_soc_dai_driver bf5xx_i2s_dai = { | |||
300 | .ops = &bf5xx_i2s_dai_ops, | 245 | .ops = &bf5xx_i2s_dai_ops, |
301 | }; | 246 | }; |
302 | 247 | ||
303 | static int bfin_i2s_drv_probe(struct platform_device *pdev) | 248 | static int __devinit bf5xx_i2s_probe(struct platform_device *pdev) |
304 | { | 249 | { |
305 | return snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai); | 250 | struct sport_device *sport_handle; |
251 | int ret; | ||
252 | |||
253 | /* configure SPORT for I2S */ | ||
254 | sport_handle = sport_init(pdev, 4, 2 * sizeof(u32), | ||
255 | sizeof(struct bf5xx_i2s_port)); | ||
256 | if (!sport_handle) | ||
257 | return -ENODEV; | ||
258 | |||
259 | /* register with the ASoC layers */ | ||
260 | ret = snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai); | ||
261 | if (ret) { | ||
262 | pr_err("Failed to register DAI: %d\n", ret); | ||
263 | sport_done(sport_handle); | ||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | return 0; | ||
306 | } | 268 | } |
307 | 269 | ||
308 | static int __devexit bfin_i2s_drv_remove(struct platform_device *pdev) | 270 | static int __devexit bf5xx_i2s_remove(struct platform_device *pdev) |
309 | { | 271 | { |
272 | struct sport_device *sport_handle = platform_get_drvdata(pdev); | ||
273 | |||
274 | pr_debug("%s enter\n", __func__); | ||
275 | |||
310 | snd_soc_unregister_dai(&pdev->dev); | 276 | snd_soc_unregister_dai(&pdev->dev); |
277 | sport_done(sport_handle); | ||
278 | |||
311 | return 0; | 279 | return 0; |
312 | } | 280 | } |
313 | 281 | ||
314 | static struct platform_driver bfin_i2s_driver = { | 282 | static struct platform_driver bfin_i2s_driver = { |
315 | .probe = bfin_i2s_drv_probe, | 283 | .probe = bf5xx_i2s_probe, |
316 | .remove = __devexit_p(bfin_i2s_drv_remove), | 284 | .remove = __devexit_p(bf5xx_i2s_remove), |
317 | |||
318 | .driver = { | 285 | .driver = { |
319 | .name = "bfin-i2s", | 286 | .name = "bfin-i2s", |
320 | .owner = THIS_MODULE, | 287 | .owner = THIS_MODULE, |
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c index 99051ff0954e..a2d40349fcc4 100644 --- a/sound/soc/blackfin/bf5xx-sport.c +++ b/sound/soc/blackfin/bf5xx-sport.c | |||
@@ -42,8 +42,6 @@ | |||
42 | /* delay between frame sync pulse and first data bit in multichannel mode */ | 42 | /* delay between frame sync pulse and first data bit in multichannel mode */ |
43 | #define FRAME_DELAY (1<<12) | 43 | #define FRAME_DELAY (1<<12) |
44 | 44 | ||
45 | struct sport_device *sport_handle; | ||
46 | EXPORT_SYMBOL(sport_handle); | ||
47 | /* note: multichannel is in units of 8 channels, | 45 | /* note: multichannel is in units of 8 channels, |
48 | * tdm_count is # channels NOT / 8 ! */ | 46 | * tdm_count is # channels NOT / 8 ! */ |
49 | int sport_set_multichannel(struct sport_device *sport, | 47 | int sport_set_multichannel(struct sport_device *sport, |
@@ -798,86 +796,164 @@ int sport_set_err_callback(struct sport_device *sport, | |||
798 | } | 796 | } |
799 | EXPORT_SYMBOL(sport_set_err_callback); | 797 | EXPORT_SYMBOL(sport_set_err_callback); |
800 | 798 | ||
801 | struct sport_device *sport_init(struct sport_param *param, unsigned wdsize, | 799 | static int sport_config_pdev(struct platform_device *pdev, struct sport_param *param) |
802 | unsigned dummy_count, void *private_data) | ||
803 | { | 800 | { |
804 | int ret; | 801 | /* Extract settings from platform data */ |
802 | struct device *dev = &pdev->dev; | ||
803 | struct bfin_snd_platform_data *pdata = dev->platform_data; | ||
804 | struct resource *res; | ||
805 | |||
806 | param->num = pdev->id; | ||
807 | |||
808 | if (!pdata) { | ||
809 | dev_err(dev, "no platform_data\n"); | ||
810 | return -ENODEV; | ||
811 | } | ||
812 | param->pin_req = pdata->pin_req; | ||
813 | |||
814 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
815 | if (!res) { | ||
816 | dev_err(dev, "no MEM resource\n"); | ||
817 | return -ENODEV; | ||
818 | } | ||
819 | param->regs = (struct sport_register *)res->start; | ||
820 | |||
821 | /* first RX, then TX */ | ||
822 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
823 | if (!res) { | ||
824 | dev_err(dev, "no rx DMA resource\n"); | ||
825 | return -ENODEV; | ||
826 | } | ||
827 | param->dma_rx_chan = res->start; | ||
828 | |||
829 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
830 | if (!res) { | ||
831 | dev_err(dev, "no tx DMA resource\n"); | ||
832 | return -ENODEV; | ||
833 | } | ||
834 | param->dma_tx_chan = res->start; | ||
835 | |||
836 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
837 | if (!res) { | ||
838 | dev_err(dev, "no irq resource\n"); | ||
839 | return -ENODEV; | ||
840 | } | ||
841 | param->err_irq = res->start; | ||
842 | |||
843 | return 0; | ||
844 | } | ||
845 | |||
846 | struct sport_device *sport_init(struct platform_device *pdev, | ||
847 | unsigned int wdsize, unsigned int dummy_count, size_t priv_size) | ||
848 | { | ||
849 | struct device *dev = &pdev->dev; | ||
850 | struct sport_param param; | ||
805 | struct sport_device *sport; | 851 | struct sport_device *sport; |
806 | pr_debug("%s enter\n", __func__); | 852 | int ret; |
807 | BUG_ON(param == NULL); | 853 | |
808 | BUG_ON(wdsize == 0 || dummy_count == 0); | 854 | dev_dbg(dev, "%s enter\n", __func__); |
809 | sport = kmalloc(sizeof(struct sport_device), GFP_KERNEL); | 855 | |
810 | if (!sport) { | 856 | param.wdsize = wdsize; |
811 | pr_err("Failed to allocate for sport device\n"); | 857 | param.dummy_count = dummy_count; |
858 | BUG_ON(param.wdsize == 0 || param.dummy_count == 0); | ||
859 | |||
860 | ret = sport_config_pdev(pdev, ¶m); | ||
861 | if (ret) | ||
862 | return NULL; | ||
863 | |||
864 | if (peripheral_request_list(param.pin_req, "soc-audio")) { | ||
865 | dev_err(dev, "requesting Peripherals failed\n"); | ||
812 | return NULL; | 866 | return NULL; |
813 | } | 867 | } |
814 | 868 | ||
815 | memset(sport, 0, sizeof(struct sport_device)); | 869 | sport = kzalloc(sizeof(*sport), GFP_KERNEL); |
816 | sport->dma_rx_chan = param->dma_rx_chan; | 870 | if (!sport) { |
817 | sport->dma_tx_chan = param->dma_tx_chan; | 871 | dev_err(dev, "failed to allocate for sport device\n"); |
818 | sport->err_irq = param->err_irq; | 872 | goto __init_err0; |
819 | sport->regs = param->regs; | 873 | } |
820 | sport->private_data = private_data; | 874 | |
875 | sport->num = param.num; | ||
876 | sport->dma_rx_chan = param.dma_rx_chan; | ||
877 | sport->dma_tx_chan = param.dma_tx_chan; | ||
878 | sport->err_irq = param.err_irq; | ||
879 | sport->regs = param.regs; | ||
880 | sport->pin_req = param.pin_req; | ||
821 | 881 | ||
822 | if (request_dma(sport->dma_rx_chan, "SPORT RX Data") == -EBUSY) { | 882 | if (request_dma(sport->dma_rx_chan, "SPORT RX Data") == -EBUSY) { |
823 | pr_err("Failed to request RX dma %d\n", \ | 883 | dev_err(dev, "failed to request RX dma %d\n", sport->dma_rx_chan); |
824 | sport->dma_rx_chan); | ||
825 | goto __init_err1; | 884 | goto __init_err1; |
826 | } | 885 | } |
827 | if (set_dma_callback(sport->dma_rx_chan, rx_handler, sport) != 0) { | 886 | if (set_dma_callback(sport->dma_rx_chan, rx_handler, sport) != 0) { |
828 | pr_err("Failed to request RX irq %d\n", \ | 887 | dev_err(dev, "failed to request RX irq %d\n", sport->dma_rx_chan); |
829 | sport->dma_rx_chan); | ||
830 | goto __init_err2; | 888 | goto __init_err2; |
831 | } | 889 | } |
832 | 890 | ||
833 | if (request_dma(sport->dma_tx_chan, "SPORT TX Data") == -EBUSY) { | 891 | if (request_dma(sport->dma_tx_chan, "SPORT TX Data") == -EBUSY) { |
834 | pr_err("Failed to request TX dma %d\n", \ | 892 | dev_err(dev, "failed to request TX dma %d\n", sport->dma_tx_chan); |
835 | sport->dma_tx_chan); | ||
836 | goto __init_err2; | 893 | goto __init_err2; |
837 | } | 894 | } |
838 | 895 | ||
839 | if (set_dma_callback(sport->dma_tx_chan, tx_handler, sport) != 0) { | 896 | if (set_dma_callback(sport->dma_tx_chan, tx_handler, sport) != 0) { |
840 | pr_err("Failed to request TX irq %d\n", \ | 897 | dev_err(dev, "failed to request TX irq %d\n", sport->dma_tx_chan); |
841 | sport->dma_tx_chan); | ||
842 | goto __init_err3; | 898 | goto __init_err3; |
843 | } | 899 | } |
844 | 900 | ||
845 | if (request_irq(sport->err_irq, err_handler, IRQF_SHARED, "SPORT err", | 901 | if (request_irq(sport->err_irq, err_handler, IRQF_SHARED, "SPORT err", |
846 | sport) < 0) { | 902 | sport) < 0) { |
847 | pr_err("Failed to request err irq:%d\n", \ | 903 | dev_err(dev, "failed to request err irq %d\n", sport->err_irq); |
848 | sport->err_irq); | ||
849 | goto __init_err3; | 904 | goto __init_err3; |
850 | } | 905 | } |
851 | 906 | ||
852 | pr_err("dma rx:%d tx:%d, err irq:%d, regs:%p\n", | 907 | dev_info(dev, "dma rx:%d tx:%d, err irq:%d, regs:%p\n", |
853 | sport->dma_rx_chan, sport->dma_tx_chan, | 908 | sport->dma_rx_chan, sport->dma_tx_chan, |
854 | sport->err_irq, sport->regs); | 909 | sport->err_irq, sport->regs); |
855 | 910 | ||
856 | sport->wdsize = wdsize; | 911 | sport->wdsize = param.wdsize; |
857 | sport->dummy_count = dummy_count; | 912 | sport->dummy_count = param.dummy_count; |
913 | |||
914 | sport->private_data = kzalloc(priv_size, GFP_KERNEL); | ||
915 | if (!sport->private_data) { | ||
916 | dev_err(dev, "could not alloc priv data %zu bytes\n", priv_size); | ||
917 | goto __init_err4; | ||
918 | } | ||
858 | 919 | ||
859 | if (L1_DATA_A_LENGTH) | 920 | if (L1_DATA_A_LENGTH) |
860 | sport->dummy_buf = l1_data_sram_zalloc(dummy_count * 2); | 921 | sport->dummy_buf = l1_data_sram_zalloc(param.dummy_count * 2); |
861 | else | 922 | else |
862 | sport->dummy_buf = kzalloc(dummy_count * 2, GFP_KERNEL); | 923 | sport->dummy_buf = kzalloc(param.dummy_count * 2, GFP_KERNEL); |
863 | if (sport->dummy_buf == NULL) { | 924 | if (sport->dummy_buf == NULL) { |
864 | pr_err("Failed to allocate dummy buffer\n"); | 925 | dev_err(dev, "failed to allocate dummy buffer\n"); |
865 | goto __error; | 926 | goto __error1; |
866 | } | 927 | } |
867 | 928 | ||
868 | ret = sport_config_rx_dummy(sport); | 929 | ret = sport_config_rx_dummy(sport); |
869 | if (ret) { | 930 | if (ret) { |
870 | pr_err("Failed to config rx dummy ring\n"); | 931 | dev_err(dev, "failed to config rx dummy ring\n"); |
871 | goto __error; | 932 | goto __error2; |
872 | } | 933 | } |
873 | ret = sport_config_tx_dummy(sport); | 934 | ret = sport_config_tx_dummy(sport); |
874 | if (ret) { | 935 | if (ret) { |
875 | pr_err("Failed to config tx dummy ring\n"); | 936 | dev_err(dev, "failed to config tx dummy ring\n"); |
876 | goto __error; | 937 | goto __error3; |
877 | } | 938 | } |
878 | 939 | ||
940 | platform_set_drvdata(pdev, sport); | ||
941 | |||
879 | return sport; | 942 | return sport; |
880 | __error: | 943 | __error3: |
944 | if (L1_DATA_A_LENGTH) | ||
945 | l1_data_sram_free(sport->dummy_rx_desc); | ||
946 | else | ||
947 | dma_free_coherent(NULL, 2*sizeof(struct dmasg), | ||
948 | sport->dummy_rx_desc, 0); | ||
949 | __error2: | ||
950 | if (L1_DATA_A_LENGTH) | ||
951 | l1_data_sram_free(sport->dummy_buf); | ||
952 | else | ||
953 | kfree(sport->dummy_buf); | ||
954 | __error1: | ||
955 | kfree(sport->private_data); | ||
956 | __init_err4: | ||
881 | free_irq(sport->err_irq, sport); | 957 | free_irq(sport->err_irq, sport); |
882 | __init_err3: | 958 | __init_err3: |
883 | free_dma(sport->dma_tx_chan); | 959 | free_dma(sport->dma_tx_chan); |
@@ -885,6 +961,8 @@ __init_err2: | |||
885 | free_dma(sport->dma_rx_chan); | 961 | free_dma(sport->dma_rx_chan); |
886 | __init_err1: | 962 | __init_err1: |
887 | kfree(sport); | 963 | kfree(sport); |
964 | __init_err0: | ||
965 | peripheral_free_list(param.pin_req); | ||
888 | return NULL; | 966 | return NULL; |
889 | } | 967 | } |
890 | EXPORT_SYMBOL(sport_init); | 968 | EXPORT_SYMBOL(sport_init); |
@@ -917,8 +995,9 @@ void sport_done(struct sport_device *sport) | |||
917 | free_dma(sport->dma_tx_chan); | 995 | free_dma(sport->dma_tx_chan); |
918 | free_irq(sport->err_irq, sport); | 996 | free_irq(sport->err_irq, sport); |
919 | 997 | ||
998 | kfree(sport->private_data); | ||
999 | peripheral_free_list(sport->pin_req); | ||
920 | kfree(sport); | 1000 | kfree(sport); |
921 | sport = NULL; | ||
922 | } | 1001 | } |
923 | EXPORT_SYMBOL(sport_done); | 1002 | EXPORT_SYMBOL(sport_done); |
924 | 1003 | ||
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h index a86e8cc0b2d3..5ab60bd613ea 100644 --- a/sound/soc/blackfin/bf5xx-sport.h +++ b/sound/soc/blackfin/bf5xx-sport.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * File: bf5xx_ac97_sport.h | 2 | * File: bf5xx_sport.h |
3 | * Based on: | 3 | * Based on: |
4 | * Author: Roy Huang <roy.huang@analog.com> | 4 | * Author: Roy Huang <roy.huang@analog.com> |
5 | * | 5 | * |
@@ -33,15 +33,18 @@ | |||
33 | #include <linux/types.h> | 33 | #include <linux/types.h> |
34 | #include <linux/wait.h> | 34 | #include <linux/wait.h> |
35 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
36 | #include <linux/platform_device.h> | ||
36 | #include <asm/dma.h> | 37 | #include <asm/dma.h> |
37 | #include <asm/bfin_sport.h> | 38 | #include <asm/bfin_sport.h> |
38 | 39 | ||
39 | #define DESC_ELEMENT_COUNT 9 | 40 | #define DESC_ELEMENT_COUNT 9 |
40 | 41 | ||
41 | struct sport_device { | 42 | struct sport_device { |
43 | int num; | ||
42 | int dma_rx_chan; | 44 | int dma_rx_chan; |
43 | int dma_tx_chan; | 45 | int dma_tx_chan; |
44 | int err_irq; | 46 | int err_irq; |
47 | const unsigned short *pin_req; | ||
45 | struct sport_register *regs; | 48 | struct sport_register *regs; |
46 | 49 | ||
47 | unsigned char *rx_buf; | 50 | unsigned char *rx_buf; |
@@ -103,17 +106,20 @@ struct sport_device { | |||
103 | void *private_data; | 106 | void *private_data; |
104 | }; | 107 | }; |
105 | 108 | ||
106 | extern struct sport_device *sport_handle; | ||
107 | |||
108 | struct sport_param { | 109 | struct sport_param { |
110 | int num; | ||
109 | int dma_rx_chan; | 111 | int dma_rx_chan; |
110 | int dma_tx_chan; | 112 | int dma_tx_chan; |
111 | int err_irq; | 113 | int err_irq; |
114 | const unsigned short *pin_req; | ||
112 | struct sport_register *regs; | 115 | struct sport_register *regs; |
116 | unsigned int wdsize; | ||
117 | unsigned int dummy_count; | ||
118 | void *private_data; | ||
113 | }; | 119 | }; |
114 | 120 | ||
115 | struct sport_device *sport_init(struct sport_param *param, unsigned wdsize, | 121 | struct sport_device *sport_init(struct platform_device *pdev, |
116 | unsigned dummy_count, void *private_data); | 122 | unsigned int wdsize, unsigned int dummy_count, size_t priv_size); |
117 | 123 | ||
118 | void sport_done(struct sport_device *sport); | 124 | void sport_done(struct sport_device *sport); |
119 | 125 | ||
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c index 8a7b589a6fb3..767e772a815d 100644 --- a/sound/soc/blackfin/bf5xx-ssm2602.c +++ b/sound/soc/blackfin/bf5xx-ssm2602.c | |||
@@ -44,16 +44,6 @@ | |||
44 | 44 | ||
45 | static struct snd_soc_card bf5xx_ssm2602; | 45 | static struct snd_soc_card bf5xx_ssm2602; |
46 | 46 | ||
47 | static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) | ||
48 | { | ||
49 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
50 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
51 | |||
52 | pr_debug("%s enter\n", __func__); | ||
53 | snd_soc_dai_set_drvdata(cpu_dai, sport_handle); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream, | 47 | static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream, |
58 | struct snd_pcm_hw_params *params) | 48 | struct snd_pcm_hw_params *params) |
59 | { | 49 | { |
@@ -109,23 +99,33 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
109 | } | 99 | } |
110 | 100 | ||
111 | static struct snd_soc_ops bf5xx_ssm2602_ops = { | 101 | static struct snd_soc_ops bf5xx_ssm2602_ops = { |
112 | .startup = bf5xx_ssm2602_startup, | ||
113 | .hw_params = bf5xx_ssm2602_hw_params, | 102 | .hw_params = bf5xx_ssm2602_hw_params, |
114 | }; | 103 | }; |
115 | 104 | ||
116 | static struct snd_soc_dai_link bf5xx_ssm2602_dai = { | 105 | static struct snd_soc_dai_link bf5xx_ssm2602_dai[] = { |
117 | .name = "ssm2602", | 106 | { |
118 | .stream_name = "SSM2602", | 107 | .name = "ssm2602", |
119 | .cpu_dai_name = "bfin-i2s", | 108 | .stream_name = "SSM2602", |
120 | .codec_dai_name = "ssm2602-hifi", | 109 | .cpu_dai_name = "bfin-i2s.0", |
121 | .platform_name = "bfin-i2s-pcm-audio", | 110 | .codec_dai_name = "ssm2602-hifi", |
122 | .codec_name = "ssm2602.0-001b", | 111 | .platform_name = "bfin-i2s-pcm-audio", |
123 | .ops = &bf5xx_ssm2602_ops, | 112 | .codec_name = "ssm2602.0-001b", |
113 | .ops = &bf5xx_ssm2602_ops, | ||
114 | }, | ||
115 | { | ||
116 | .name = "ssm2602", | ||
117 | .stream_name = "SSM2602", | ||
118 | .cpu_dai_name = "bfin-i2s.1", | ||
119 | .codec_dai_name = "ssm2602-hifi", | ||
120 | .platform_name = "bfin-i2s-pcm-audio", | ||
121 | .codec_name = "ssm2602.0-001b", | ||
122 | .ops = &bf5xx_ssm2602_ops, | ||
123 | }, | ||
124 | }; | 124 | }; |
125 | 125 | ||
126 | static struct snd_soc_card bf5xx_ssm2602 = { | 126 | static struct snd_soc_card bf5xx_ssm2602 = { |
127 | .name = "bfin-ssm2602", | 127 | .name = "bfin-ssm2602", |
128 | .dai_link = &bf5xx_ssm2602_dai, | 128 | .dai_link = &bf5xx_ssm2602_dai[CONFIG_SND_BF5XX_SPORT_NUM], |
129 | .num_links = 1, | 129 | .num_links = 1, |
130 | }; | 130 | }; |
131 | 131 | ||
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c index d1bd745d72cf..07cfc7a9e49a 100644 --- a/sound/soc/blackfin/bf5xx-tdm-pcm.c +++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c | |||
@@ -154,7 +154,12 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
154 | 154 | ||
155 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | 155 | static int bf5xx_pcm_open(struct snd_pcm_substream *substream) |
156 | { | 156 | { |
157 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
158 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
159 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(cpu_dai); | ||
157 | struct snd_pcm_runtime *runtime = substream->runtime; | 160 | struct snd_pcm_runtime *runtime = substream->runtime; |
161 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
162 | |||
158 | int ret = 0; | 163 | int ret = 0; |
159 | 164 | ||
160 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); | 165 | snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); |
@@ -164,9 +169,14 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | |||
164 | if (ret < 0) | 169 | if (ret < 0) |
165 | goto out; | 170 | goto out; |
166 | 171 | ||
167 | if (sport_handle != NULL) | 172 | if (sport_handle != NULL) { |
173 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
174 | sport_handle->tx_buf = buf->area; | ||
175 | else | ||
176 | sport_handle->rx_buf = buf->area; | ||
177 | |||
168 | runtime->private_data = sport_handle; | 178 | runtime->private_data = sport_handle; |
169 | else { | 179 | } else { |
170 | pr_err("sport_handle is NULL\n"); | 180 | pr_err("sport_handle is NULL\n"); |
171 | ret = -ENODEV; | 181 | ret = -ENODEV; |
172 | } | 182 | } |
@@ -249,11 +259,6 @@ static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | |||
249 | } | 259 | } |
250 | buf->bytes = size; | 260 | buf->bytes = size; |
251 | 261 | ||
252 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
253 | sport_handle->tx_buf = buf->area; | ||
254 | else | ||
255 | sport_handle->rx_buf = buf->area; | ||
256 | |||
257 | return 0; | 262 | return 0; |
258 | } | 263 | } |
259 | 264 | ||
@@ -274,8 +279,6 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
274 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); | 279 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); |
275 | buf->area = NULL; | 280 | buf->area = NULL; |
276 | } | 281 | } |
277 | if (sport_handle) | ||
278 | sport_done(sport_handle); | ||
279 | } | 282 | } |
280 | 283 | ||
281 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); | 284 | static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); |
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c index 5515ac9e05c7..a822d1ee1380 100644 --- a/sound/soc/blackfin/bf5xx-tdm.c +++ b/sound/soc/blackfin/bf5xx-tdm.c | |||
@@ -46,43 +46,6 @@ | |||
46 | #include "bf5xx-sport.h" | 46 | #include "bf5xx-sport.h" |
47 | #include "bf5xx-tdm.h" | 47 | #include "bf5xx-tdm.h" |
48 | 48 | ||
49 | static struct bf5xx_tdm_port bf5xx_tdm; | ||
50 | static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; | ||
51 | |||
52 | static struct sport_param sport_params[2] = { | ||
53 | { | ||
54 | .dma_rx_chan = CH_SPORT0_RX, | ||
55 | .dma_tx_chan = CH_SPORT0_TX, | ||
56 | .err_irq = IRQ_SPORT0_ERROR, | ||
57 | .regs = (struct sport_register *)SPORT0_TCR1, | ||
58 | }, | ||
59 | { | ||
60 | .dma_rx_chan = CH_SPORT1_RX, | ||
61 | .dma_tx_chan = CH_SPORT1_TX, | ||
62 | .err_irq = IRQ_SPORT1_ERROR, | ||
63 | .regs = (struct sport_register *)SPORT1_TCR1, | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | /* | ||
68 | * Setting the TFS pin selector for SPORT 0 based on whether the selected | ||
69 | * port id F or G. If the port is F then no conflict should exist for the | ||
70 | * TFS. When Port G is selected and EMAC then there is a conflict between | ||
71 | * the PHY interrupt line and TFS. Current settings prevent the conflict | ||
72 | * by ignoring the TFS pin when Port G is selected. This allows both | ||
73 | * codecs and EMAC using Port G concurrently. | ||
74 | */ | ||
75 | #ifdef CONFIG_BF527_SPORT0_PORTG | ||
76 | #define LOCAL_SPORT0_TFS (0) | ||
77 | #else | ||
78 | #define LOCAL_SPORT0_TFS (P_SPORT0_TFS) | ||
79 | #endif | ||
80 | |||
81 | static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, | ||
82 | P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0}, | ||
83 | {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI, | ||
84 | P_SPORT1_RSCLK, P_SPORT1_TFS, 0} }; | ||
85 | |||
86 | static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 49 | static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
87 | unsigned int fmt) | 50 | unsigned int fmt) |
88 | { | 51 | { |
@@ -119,14 +82,16 @@ static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream, | |||
119 | struct snd_pcm_hw_params *params, | 82 | struct snd_pcm_hw_params *params, |
120 | struct snd_soc_dai *dai) | 83 | struct snd_soc_dai *dai) |
121 | { | 84 | { |
85 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
86 | struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data; | ||
122 | int ret = 0; | 87 | int ret = 0; |
123 | 88 | ||
124 | bf5xx_tdm.tcr2 &= ~0x1f; | 89 | bf5xx_tdm->tcr2 &= ~0x1f; |
125 | bf5xx_tdm.rcr2 &= ~0x1f; | 90 | bf5xx_tdm->rcr2 &= ~0x1f; |
126 | switch (params_format(params)) { | 91 | switch (params_format(params)) { |
127 | case SNDRV_PCM_FORMAT_S32_LE: | 92 | case SNDRV_PCM_FORMAT_S32_LE: |
128 | bf5xx_tdm.tcr2 |= 31; | 93 | bf5xx_tdm->tcr2 |= 31; |
129 | bf5xx_tdm.rcr2 |= 31; | 94 | bf5xx_tdm->rcr2 |= 31; |
130 | sport_handle->wdsize = 4; | 95 | sport_handle->wdsize = 4; |
131 | break; | 96 | break; |
132 | /* at present, we only support 32bit transfer */ | 97 | /* at present, we only support 32bit transfer */ |
@@ -136,7 +101,7 @@ static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream, | |||
136 | break; | 101 | break; |
137 | } | 102 | } |
138 | 103 | ||
139 | if (!bf5xx_tdm.configured) { | 104 | if (!bf5xx_tdm->configured) { |
140 | /* | 105 | /* |
141 | * TX and RX are not independent,they are enabled at the | 106 | * TX and RX are not independent,they are enabled at the |
142 | * same time, even if only one side is running. So, we | 107 | * same time, even if only one side is running. So, we |
@@ -145,21 +110,21 @@ static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream, | |||
145 | * | 110 | * |
146 | * CPU DAI:slave mode. | 111 | * CPU DAI:slave mode. |
147 | */ | 112 | */ |
148 | ret = sport_config_rx(sport_handle, bf5xx_tdm.rcr1, | 113 | ret = sport_config_rx(sport_handle, bf5xx_tdm->rcr1, |
149 | bf5xx_tdm.rcr2, 0, 0); | 114 | bf5xx_tdm->rcr2, 0, 0); |
150 | if (ret) { | 115 | if (ret) { |
151 | pr_err("SPORT is busy!\n"); | 116 | pr_err("SPORT is busy!\n"); |
152 | return -EBUSY; | 117 | return -EBUSY; |
153 | } | 118 | } |
154 | 119 | ||
155 | ret = sport_config_tx(sport_handle, bf5xx_tdm.tcr1, | 120 | ret = sport_config_tx(sport_handle, bf5xx_tdm->tcr1, |
156 | bf5xx_tdm.tcr2, 0, 0); | 121 | bf5xx_tdm->tcr2, 0, 0); |
157 | if (ret) { | 122 | if (ret) { |
158 | pr_err("SPORT is busy!\n"); | 123 | pr_err("SPORT is busy!\n"); |
159 | return -EBUSY; | 124 | return -EBUSY; |
160 | } | 125 | } |
161 | 126 | ||
162 | bf5xx_tdm.configured = 1; | 127 | bf5xx_tdm->configured = 1; |
163 | } | 128 | } |
164 | 129 | ||
165 | return 0; | 130 | return 0; |
@@ -168,15 +133,20 @@ static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream, | |||
168 | static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream, | 133 | static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream, |
169 | struct snd_soc_dai *dai) | 134 | struct snd_soc_dai *dai) |
170 | { | 135 | { |
136 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
137 | struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data; | ||
138 | |||
171 | /* No active stream, SPORT is allowed to be configured again. */ | 139 | /* No active stream, SPORT is allowed to be configured again. */ |
172 | if (!dai->active) | 140 | if (!dai->active) |
173 | bf5xx_tdm.configured = 0; | 141 | bf5xx_tdm->configured = 0; |
174 | } | 142 | } |
175 | 143 | ||
176 | static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai, | 144 | static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai, |
177 | unsigned int tx_num, unsigned int *tx_slot, | 145 | unsigned int tx_num, unsigned int *tx_slot, |
178 | unsigned int rx_num, unsigned int *rx_slot) | 146 | unsigned int rx_num, unsigned int *rx_slot) |
179 | { | 147 | { |
148 | struct sport_device *sport_handle = snd_soc_dai_get_drvdata(dai); | ||
149 | struct bf5xx_tdm_port *bf5xx_tdm = sport_handle->private_data; | ||
180 | int i; | 150 | int i; |
181 | unsigned int slot; | 151 | unsigned int slot; |
182 | unsigned int tx_mapped = 0, rx_mapped = 0; | 152 | unsigned int tx_mapped = 0, rx_mapped = 0; |
@@ -189,7 +159,7 @@ static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai, | |||
189 | slot = tx_slot[i]; | 159 | slot = tx_slot[i]; |
190 | if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && | 160 | if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && |
191 | (!(tx_mapped & (1 << slot)))) { | 161 | (!(tx_mapped & (1 << slot)))) { |
192 | bf5xx_tdm.tx_map[i] = slot; | 162 | bf5xx_tdm->tx_map[i] = slot; |
193 | tx_mapped |= 1 << slot; | 163 | tx_mapped |= 1 << slot; |
194 | } else | 164 | } else |
195 | return -EINVAL; | 165 | return -EINVAL; |
@@ -198,7 +168,7 @@ static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai, | |||
198 | slot = rx_slot[i]; | 168 | slot = rx_slot[i]; |
199 | if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && | 169 | if ((slot < BFIN_TDM_DAI_MAX_SLOTS) && |
200 | (!(rx_mapped & (1 << slot)))) { | 170 | (!(rx_mapped & (1 << slot)))) { |
201 | bf5xx_tdm.rx_map[i] = slot; | 171 | bf5xx_tdm->rx_map[i] = slot; |
202 | rx_mapped |= 1 << slot; | 172 | rx_mapped |= 1 << slot; |
203 | } else | 173 | } else |
204 | return -EINVAL; | 174 | return -EINVAL; |
@@ -212,12 +182,14 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) | |||
212 | { | 182 | { |
213 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); | 183 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); |
214 | 184 | ||
215 | if (!dai->active) | ||
216 | return 0; | ||
217 | if (dai->capture_active) | ||
218 | sport_rx_stop(sport); | ||
219 | if (dai->playback_active) | 185 | if (dai->playback_active) |
220 | sport_tx_stop(sport); | 186 | sport_tx_stop(sport); |
187 | if (dai->capture_active) | ||
188 | sport_rx_stop(sport); | ||
189 | |||
190 | /* isolate sync/clock pins from codec while sports resume */ | ||
191 | peripheral_free_list(sport->pin_req); | ||
192 | |||
221 | return 0; | 193 | return 0; |
222 | } | 194 | } |
223 | 195 | ||
@@ -226,9 +198,6 @@ static int bf5xx_tdm_resume(struct snd_soc_dai *dai) | |||
226 | int ret; | 198 | int ret; |
227 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); | 199 | struct sport_device *sport = snd_soc_dai_get_drvdata(dai); |
228 | 200 | ||
229 | if (!dai->active) | ||
230 | return 0; | ||
231 | |||
232 | ret = sport_set_multichannel(sport, 8, 0xFF, 1); | 201 | ret = sport_set_multichannel(sport, 8, 0xFF, 1); |
233 | if (ret) { | 202 | if (ret) { |
234 | pr_err("SPORT is busy!\n"); | 203 | pr_err("SPORT is busy!\n"); |
@@ -247,6 +216,8 @@ static int bf5xx_tdm_resume(struct snd_soc_dai *dai) | |||
247 | ret = -EBUSY; | 216 | ret = -EBUSY; |
248 | } | 217 | } |
249 | 218 | ||
219 | peripheral_request_list(sport->pin_req, "soc-audio"); | ||
220 | |||
250 | return 0; | 221 | return 0; |
251 | } | 222 | } |
252 | 223 | ||
@@ -280,20 +251,14 @@ static struct snd_soc_dai_driver bf5xx_tdm_dai = { | |||
280 | 251 | ||
281 | static int __devinit bfin_tdm_probe(struct platform_device *pdev) | 252 | static int __devinit bfin_tdm_probe(struct platform_device *pdev) |
282 | { | 253 | { |
283 | int ret = 0; | 254 | struct sport_device *sport_handle; |
284 | 255 | int ret; | |
285 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { | ||
286 | pr_err("Requesting Peripherals failed\n"); | ||
287 | return -EFAULT; | ||
288 | } | ||
289 | 256 | ||
290 | /* request DMA for SPORT */ | 257 | /* configure SPORT for TDM */ |
291 | sport_handle = sport_init(&sport_params[sport_num], 4, \ | 258 | sport_handle = sport_init(pdev, 4, 8 * sizeof(u32), |
292 | 8 * sizeof(u32), NULL); | 259 | sizeof(struct bf5xx_tdm_port)); |
293 | if (!sport_handle) { | 260 | if (!sport_handle) |
294 | peripheral_free_list(&sport_req[sport_num][0]); | ||
295 | return -ENODEV; | 261 | return -ENODEV; |
296 | } | ||
297 | 262 | ||
298 | /* SPORT works in TDM mode */ | 263 | /* SPORT works in TDM mode */ |
299 | ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1); | 264 | ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1); |
@@ -323,18 +288,19 @@ static int __devinit bfin_tdm_probe(struct platform_device *pdev) | |||
323 | goto sport_config_err; | 288 | goto sport_config_err; |
324 | } | 289 | } |
325 | 290 | ||
326 | sport_handle->private_data = &bf5xx_tdm; | ||
327 | return 0; | 291 | return 0; |
328 | 292 | ||
329 | sport_config_err: | 293 | sport_config_err: |
330 | peripheral_free_list(&sport_req[sport_num][0]); | 294 | sport_done(sport_handle); |
331 | return ret; | 295 | return ret; |
332 | } | 296 | } |
333 | 297 | ||
334 | static int __devexit bfin_tdm_remove(struct platform_device *pdev) | 298 | static int __devexit bfin_tdm_remove(struct platform_device *pdev) |
335 | { | 299 | { |
336 | peripheral_free_list(&sport_req[sport_num][0]); | 300 | struct sport_device *sport_handle = platform_get_drvdata(pdev); |
301 | |||
337 | snd_soc_unregister_dai(&pdev->dev); | 302 | snd_soc_unregister_dai(&pdev->dev); |
303 | sport_done(sport_handle); | ||
338 | 304 | ||
339 | return 0; | 305 | return 0; |
340 | } | 306 | } |