diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/blackfin/Kconfig | 14 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ac97-pcm.c | 80 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ac97.c | 156 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ac97.h | 35 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-sport.h | 2 |
5 files changed, 184 insertions, 103 deletions
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 3fce18788b77..43d89fc253ae 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig | |||
@@ -47,7 +47,7 @@ config SND_BF5XX_AC97 | |||
47 | properly with this driver. This driver is known to work with the | 47 | properly with this driver. This driver is known to work with the |
48 | Analog Devices line of AC97 codecs. | 48 | Analog Devices line of AC97 codecs. |
49 | 49 | ||
50 | config SND_MMAP_SUPPORT | 50 | config SND_BF5XX_MMAP_SUPPORT |
51 | bool "Enable MMAP Support" | 51 | bool "Enable MMAP Support" |
52 | depends on SND_BF5XX_AC97 | 52 | depends on SND_BF5XX_AC97 |
53 | default y | 53 | default y |
@@ -55,9 +55,17 @@ config SND_MMAP_SUPPORT | |||
55 | Say y if you want AC97 driver to support mmap mode. | 55 | Say y if you want AC97 driver to support mmap mode. |
56 | We introduce an intermediate buffer to simulate mmap. | 56 | We introduce an intermediate buffer to simulate mmap. |
57 | 57 | ||
58 | config SND_BF5XX_MULTICHAN_SUPPORT | ||
59 | bool "Enable Multichannel Support" | ||
60 | depends on SND_BF5XX_AC97 | ||
61 | default n | ||
62 | help | ||
63 | Say y if you want AC97 driver to support up to 5.1 channel audio. | ||
64 | this mode will consume much more memory for DMA. | ||
65 | |||
58 | config SND_BF5XX_SOC_SPORT | 66 | config SND_BF5XX_SOC_SPORT |
59 | tristate | 67 | tristate |
60 | 68 | ||
61 | config SND_BF5XX_SOC_I2S | 69 | config SND_BF5XX_SOC_I2S |
62 | tristate | 70 | tristate |
63 | select SND_BF5XX_SOC_SPORT | 71 | select SND_BF5XX_SOC_SPORT |
@@ -90,7 +98,7 @@ config SND_BF5XX_HAVE_COLD_RESET | |||
90 | depends on SND_BF5XX_AC97 | 98 | depends on SND_BF5XX_AC97 |
91 | default y if BFIN548_EZKIT | 99 | default y if BFIN548_EZKIT |
92 | default n if !BFIN548_EZKIT | 100 | default n if !BFIN548_EZKIT |
93 | 101 | ||
94 | config SND_BF5XX_RESET_GPIO_NUM | 102 | config SND_BF5XX_RESET_GPIO_NUM |
95 | int "Set a GPIO for cold reset" | 103 | int "Set a GPIO for cold reset" |
96 | depends on SND_BF5XX_HAVE_COLD_RESET | 104 | depends on SND_BF5XX_HAVE_COLD_RESET |
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 25e50d2ea1ec..4be1a490f4fb 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c | |||
@@ -43,24 +43,34 @@ | |||
43 | #include "bf5xx-ac97.h" | 43 | #include "bf5xx-ac97.h" |
44 | #include "bf5xx-sport.h" | 44 | #include "bf5xx-sport.h" |
45 | 45 | ||
46 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 46 | static unsigned int ac97_chan_mask[] = { |
47 | SP_FL, /* Mono */ | ||
48 | SP_STEREO, /* Stereo */ | ||
49 | SP_2DOT1, /* 2.1*/ | ||
50 | SP_QUAD,/*Quadraquic*/ | ||
51 | SP_FL | SP_FR | SP_FC | SP_SL | SP_SR,/*5 channels */ | ||
52 | SP_5DOT1, /* 5.1 */ | ||
53 | }; | ||
54 | |||
55 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) | ||
47 | static void bf5xx_mmap_copy(struct snd_pcm_substream *substream, | 56 | static void bf5xx_mmap_copy(struct snd_pcm_substream *substream, |
48 | snd_pcm_uframes_t count) | 57 | snd_pcm_uframes_t count) |
49 | { | 58 | { |
50 | struct snd_pcm_runtime *runtime = substream->runtime; | 59 | struct snd_pcm_runtime *runtime = substream->runtime; |
51 | struct sport_device *sport = runtime->private_data; | 60 | struct sport_device *sport = runtime->private_data; |
61 | unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1]; | ||
52 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 62 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
53 | bf5xx_pcm_to_ac97( | 63 | bf5xx_pcm_to_ac97((struct ac97_frame *)sport->tx_dma_buf + |
54 | (struct ac97_frame *)sport->tx_dma_buf + sport->tx_pos, | 64 | sport->tx_pos, (__u16 *)runtime->dma_area + sport->tx_pos * |
55 | (__u32 *)runtime->dma_area + sport->tx_pos, count); | 65 | runtime->channels, count, chan_mask); |
56 | sport->tx_pos += runtime->period_size; | 66 | sport->tx_pos += runtime->period_size; |
57 | if (sport->tx_pos >= runtime->buffer_size) | 67 | if (sport->tx_pos >= runtime->buffer_size) |
58 | sport->tx_pos %= runtime->buffer_size; | 68 | sport->tx_pos %= runtime->buffer_size; |
59 | sport->tx_delay_pos = sport->tx_pos; | 69 | sport->tx_delay_pos = sport->tx_pos; |
60 | } else { | 70 | } else { |
61 | bf5xx_ac97_to_pcm( | 71 | bf5xx_ac97_to_pcm((struct ac97_frame *)sport->rx_dma_buf + |
62 | (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos, | 72 | sport->rx_pos, (__u16 *)runtime->dma_area + sport->rx_pos * |
63 | (__u32 *)runtime->dma_area + sport->rx_pos, count); | 73 | runtime->channels, count); |
64 | sport->rx_pos += runtime->period_size; | 74 | sport->rx_pos += runtime->period_size; |
65 | if (sport->rx_pos >= runtime->buffer_size) | 75 | if (sport->rx_pos >= runtime->buffer_size) |
66 | sport->rx_pos %= runtime->buffer_size; | 76 | sport->rx_pos %= runtime->buffer_size; |
@@ -71,7 +81,7 @@ static void bf5xx_mmap_copy(struct snd_pcm_substream *substream, | |||
71 | static void bf5xx_dma_irq(void *data) | 81 | static void bf5xx_dma_irq(void *data) |
72 | { | 82 | { |
73 | struct snd_pcm_substream *pcm = data; | 83 | struct snd_pcm_substream *pcm = data; |
74 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 84 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
75 | struct snd_pcm_runtime *runtime = pcm->runtime; | 85 | struct snd_pcm_runtime *runtime = pcm->runtime; |
76 | struct sport_device *sport = runtime->private_data; | 86 | struct sport_device *sport = runtime->private_data; |
77 | bf5xx_mmap_copy(pcm, runtime->period_size); | 87 | bf5xx_mmap_copy(pcm, runtime->period_size); |
@@ -90,7 +100,7 @@ static void bf5xx_dma_irq(void *data) | |||
90 | * The total rx/tx buffer is for ac97 frame to hold all pcm data | 100 | * The total rx/tx buffer is for ac97 frame to hold all pcm data |
91 | * is 0x20000 * sizeof(struct ac97_frame) / 4. | 101 | * is 0x20000 * sizeof(struct ac97_frame) / 4. |
92 | */ | 102 | */ |
93 | #ifdef CONFIG_SND_MMAP_SUPPORT | 103 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
94 | static const struct snd_pcm_hardware bf5xx_pcm_hardware = { | 104 | static const struct snd_pcm_hardware bf5xx_pcm_hardware = { |
95 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 105 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
96 | SNDRV_PCM_INFO_MMAP | | 106 | SNDRV_PCM_INFO_MMAP | |
@@ -123,10 +133,20 @@ static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
123 | 133 | ||
124 | static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) | 134 | static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) |
125 | { | 135 | { |
136 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) | ||
126 | struct snd_pcm_runtime *runtime = substream->runtime; | 137 | struct snd_pcm_runtime *runtime = substream->runtime; |
138 | struct sport_device *sport = runtime->private_data; | ||
127 | 139 | ||
128 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 140 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
129 | memset(runtime->dma_area, 0, runtime->buffer_size); | 141 | sport->once = 0; |
142 | if (runtime->dma_area) | ||
143 | memset(runtime->dma_area, 0, runtime->buffer_size); | ||
144 | memset(sport->tx_dma_buf, 0, runtime->buffer_size * | ||
145 | sizeof(struct ac97_frame)); | ||
146 | } else | ||
147 | memset(sport->rx_dma_buf, 0, runtime->buffer_size * | ||
148 | sizeof(struct ac97_frame)); | ||
149 | #endif | ||
130 | snd_pcm_lib_free_pages(substream); | 150 | snd_pcm_lib_free_pages(substream); |
131 | return 0; | 151 | return 0; |
132 | } | 152 | } |
@@ -139,7 +159,7 @@ static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) | |||
139 | /* An intermediate buffer is introduced for implementing mmap for | 159 | /* An intermediate buffer is introduced for implementing mmap for |
140 | * SPORT working in TMD mode(include AC97). | 160 | * SPORT working in TMD mode(include AC97). |
141 | */ | 161 | */ |
142 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 162 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
143 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 163 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
144 | sport_set_tx_callback(sport, bf5xx_dma_irq, substream); | 164 | sport_set_tx_callback(sport, bf5xx_dma_irq, substream); |
145 | sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods, | 165 | sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods, |
@@ -174,23 +194,21 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
174 | case SNDRV_PCM_TRIGGER_START: | 194 | case SNDRV_PCM_TRIGGER_START: |
175 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 195 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
176 | bf5xx_mmap_copy(substream, runtime->period_size); | 196 | bf5xx_mmap_copy(substream, runtime->period_size); |
177 | snd_pcm_period_elapsed(substream); | ||
178 | sport->tx_delay_pos = 0; | 197 | sport->tx_delay_pos = 0; |
179 | sport_tx_start(sport); | 198 | sport_tx_start(sport); |
180 | } | 199 | } else |
181 | else | ||
182 | sport_rx_start(sport); | 200 | sport_rx_start(sport); |
183 | break; | 201 | break; |
184 | case SNDRV_PCM_TRIGGER_STOP: | 202 | case SNDRV_PCM_TRIGGER_STOP: |
185 | case SNDRV_PCM_TRIGGER_SUSPEND: | 203 | case SNDRV_PCM_TRIGGER_SUSPEND: |
186 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 204 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
187 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 205 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
188 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 206 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
189 | sport->tx_pos = 0; | 207 | sport->tx_pos = 0; |
190 | #endif | 208 | #endif |
191 | sport_tx_stop(sport); | 209 | sport_tx_stop(sport); |
192 | } else { | 210 | } else { |
193 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 211 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
194 | sport->rx_pos = 0; | 212 | sport->rx_pos = 0; |
195 | #endif | 213 | #endif |
196 | sport_rx_stop(sport); | 214 | sport_rx_stop(sport); |
@@ -208,7 +226,7 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
208 | struct sport_device *sport = runtime->private_data; | 226 | struct sport_device *sport = runtime->private_data; |
209 | unsigned int curr; | 227 | unsigned int curr; |
210 | 228 | ||
211 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 229 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
212 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 230 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
213 | curr = sport->tx_delay_pos; | 231 | curr = sport->tx_delay_pos; |
214 | else | 232 | else |
@@ -257,14 +275,16 @@ static int bf5xx_pcm_close(struct snd_pcm_substream *substream) | |||
257 | pr_debug("%s enter\n", __func__); | 275 | pr_debug("%s enter\n", __func__); |
258 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 276 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
259 | sport->once = 0; | 277 | sport->once = 0; |
260 | memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame)); | 278 | memset(sport->tx_dma_buf, 0, runtime->buffer_size * |
279 | sizeof(struct ac97_frame)); | ||
261 | } else | 280 | } else |
262 | memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame)); | 281 | memset(sport->rx_dma_buf, 0, runtime->buffer_size * |
282 | sizeof(struct ac97_frame)); | ||
263 | 283 | ||
264 | return 0; | 284 | return 0; |
265 | } | 285 | } |
266 | 286 | ||
267 | #ifdef CONFIG_SND_MMAP_SUPPORT | 287 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
268 | static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, | 288 | static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, |
269 | struct vm_area_struct *vma) | 289 | struct vm_area_struct *vma) |
270 | { | 290 | { |
@@ -286,13 +306,11 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, | |||
286 | substream->stream ? "Capture" : "Playback", pos, count); | 306 | substream->stream ? "Capture" : "Playback", pos, count); |
287 | 307 | ||
288 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 308 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
289 | bf5xx_pcm_to_ac97( | 309 | bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos, |
290 | (struct ac97_frame *)runtime->dma_area + pos, | 310 | (__u16 *)buf, count, chan_mask); |
291 | buf, count); | ||
292 | else | 311 | else |
293 | bf5xx_ac97_to_pcm( | 312 | bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos, |
294 | (struct ac97_frame *)runtime->dma_area + pos, | 313 | (__u16 *)buf, count); |
295 | buf, count); | ||
296 | return 0; | 314 | return 0; |
297 | } | 315 | } |
298 | #endif | 316 | #endif |
@@ -306,7 +324,7 @@ struct snd_pcm_ops bf5xx_pcm_ac97_ops = { | |||
306 | .prepare = bf5xx_pcm_prepare, | 324 | .prepare = bf5xx_pcm_prepare, |
307 | .trigger = bf5xx_pcm_trigger, | 325 | .trigger = bf5xx_pcm_trigger, |
308 | .pointer = bf5xx_pcm_pointer, | 326 | .pointer = bf5xx_pcm_pointer, |
309 | #ifdef CONFIG_SND_MMAP_SUPPORT | 327 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
310 | .mmap = bf5xx_pcm_mmap, | 328 | .mmap = bf5xx_pcm_mmap, |
311 | #else | 329 | #else |
312 | .copy = bf5xx_pcm_copy, | 330 | .copy = bf5xx_pcm_copy, |
@@ -344,7 +362,7 @@ static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | |||
344 | * Need to allocate local buffer when enable | 362 | * Need to allocate local buffer when enable |
345 | * MMAP for SPORT working in TMD mode (include AC97). | 363 | * MMAP for SPORT working in TMD mode (include AC97). |
346 | */ | 364 | */ |
347 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 365 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
348 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 366 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
349 | if (!sport_handle->tx_dma_buf) { | 367 | if (!sport_handle->tx_dma_buf) { |
350 | sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \ | 368 | sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \ |
@@ -381,7 +399,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
381 | struct snd_pcm_substream *substream; | 399 | struct snd_pcm_substream *substream; |
382 | struct snd_dma_buffer *buf; | 400 | struct snd_dma_buffer *buf; |
383 | int stream; | 401 | int stream; |
384 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 402 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
385 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max * | 403 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max * |
386 | sizeof(struct ac97_frame) / 4; | 404 | sizeof(struct ac97_frame) / 4; |
387 | #endif | 405 | #endif |
@@ -395,7 +413,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
395 | continue; | 413 | continue; |
396 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); | 414 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); |
397 | buf->area = NULL; | 415 | buf->area = NULL; |
398 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 416 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
399 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 417 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
400 | if (sport_handle->tx_dma_buf) | 418 | if (sport_handle->tx_dma_buf) |
401 | dma_free_coherent(NULL, size, \ | 419 | dma_free_coherent(NULL, size, \ |
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index 5e5aafb6485f..65c162c4bfad 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c | |||
@@ -54,71 +54,103 @@ | |||
54 | static int *cmd_count; | 54 | static int *cmd_count; |
55 | static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; | 55 | static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; |
56 | 56 | ||
57 | #if defined(CONFIG_BF54x) | 57 | static u16 sport_req[][7] = { |
58 | PIN_REQ_SPORT_0, | ||
59 | #ifdef PIN_REQ_SPORT_1 | ||
60 | PIN_REQ_SPORT_1, | ||
61 | #endif | ||
62 | #ifdef PIN_REQ_SPORT_2 | ||
63 | PIN_REQ_SPORT_2, | ||
64 | #endif | ||
65 | #ifdef PIN_REQ_SPORT_3 | ||
66 | PIN_REQ_SPORT_3, | ||
67 | #endif | ||
68 | }; | ||
69 | |||
58 | static struct sport_param sport_params[4] = { | 70 | static struct sport_param sport_params[4] = { |
59 | { | 71 | { |
60 | .dma_rx_chan = CH_SPORT0_RX, | 72 | .dma_rx_chan = CH_SPORT0_RX, |
61 | .dma_tx_chan = CH_SPORT0_TX, | 73 | .dma_tx_chan = CH_SPORT0_TX, |
62 | .err_irq = IRQ_SPORT0_ERR, | 74 | .err_irq = IRQ_SPORT0_ERROR, |
63 | .regs = (struct sport_register *)SPORT0_TCR1, | 75 | .regs = (struct sport_register *)SPORT0_TCR1, |
64 | }, | 76 | }, |
77 | #ifdef PIN_REQ_SPORT_1 | ||
65 | { | 78 | { |
66 | .dma_rx_chan = CH_SPORT1_RX, | 79 | .dma_rx_chan = CH_SPORT1_RX, |
67 | .dma_tx_chan = CH_SPORT1_TX, | 80 | .dma_tx_chan = CH_SPORT1_TX, |
68 | .err_irq = IRQ_SPORT1_ERR, | 81 | .err_irq = IRQ_SPORT1_ERROR, |
69 | .regs = (struct sport_register *)SPORT1_TCR1, | 82 | .regs = (struct sport_register *)SPORT1_TCR1, |
70 | }, | 83 | }, |
84 | #endif | ||
85 | #ifdef PIN_REQ_SPORT_2 | ||
71 | { | 86 | { |
72 | .dma_rx_chan = CH_SPORT2_RX, | 87 | .dma_rx_chan = CH_SPORT2_RX, |
73 | .dma_tx_chan = CH_SPORT2_TX, | 88 | .dma_tx_chan = CH_SPORT2_TX, |
74 | .err_irq = IRQ_SPORT2_ERR, | 89 | .err_irq = IRQ_SPORT2_ERROR, |
75 | .regs = (struct sport_register *)SPORT2_TCR1, | 90 | .regs = (struct sport_register *)SPORT2_TCR1, |
76 | }, | 91 | }, |
92 | #endif | ||
93 | #ifdef PIN_REQ_SPORT_3 | ||
77 | { | 94 | { |
78 | .dma_rx_chan = CH_SPORT3_RX, | 95 | .dma_rx_chan = CH_SPORT3_RX, |
79 | .dma_tx_chan = CH_SPORT3_TX, | 96 | .dma_tx_chan = CH_SPORT3_TX, |
80 | .err_irq = IRQ_SPORT3_ERR, | 97 | .err_irq = IRQ_SPORT3_ERROR, |
81 | .regs = (struct sport_register *)SPORT3_TCR1, | 98 | .regs = (struct sport_register *)SPORT3_TCR1, |
82 | } | 99 | } |
83 | }; | ||
84 | #else | ||
85 | static struct sport_param sport_params[2] = { | ||
86 | { | ||
87 | .dma_rx_chan = CH_SPORT0_RX, | ||
88 | .dma_tx_chan = CH_SPORT0_TX, | ||
89 | .err_irq = IRQ_SPORT0_ERROR, | ||
90 | .regs = (struct sport_register *)SPORT0_TCR1, | ||
91 | }, | ||
92 | { | ||
93 | .dma_rx_chan = CH_SPORT1_RX, | ||
94 | .dma_tx_chan = CH_SPORT1_TX, | ||
95 | .err_irq = IRQ_SPORT1_ERROR, | ||
96 | .regs = (struct sport_register *)SPORT1_TCR1, | ||
97 | } | ||
98 | }; | ||
99 | #endif | 100 | #endif |
101 | }; | ||
100 | 102 | ||
101 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \ | 103 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, |
102 | size_t count) | 104 | size_t count, unsigned int chan_mask) |
103 | { | 105 | { |
104 | while (count--) { | 106 | while (count--) { |
105 | dst->ac97_tag = TAG_VALID | TAG_PCM; | 107 | dst->ac97_tag = TAG_VALID; |
106 | (dst++)->ac97_pcm = *src++; | 108 | if (chan_mask & SP_FL) { |
109 | dst->ac97_pcm_r = *src++; | ||
110 | dst->ac97_tag |= TAG_PCM_RIGHT; | ||
111 | } | ||
112 | if (chan_mask & SP_FR) { | ||
113 | dst->ac97_pcm_l = *src++; | ||
114 | dst->ac97_tag |= TAG_PCM_LEFT; | ||
115 | |||
116 | } | ||
117 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | ||
118 | if (chan_mask & SP_SR) { | ||
119 | dst->ac97_sl = *src++; | ||
120 | dst->ac97_tag |= TAG_PCM_SL; | ||
121 | } | ||
122 | if (chan_mask & SP_SL) { | ||
123 | dst->ac97_sr = *src++; | ||
124 | dst->ac97_tag |= TAG_PCM_SR; | ||
125 | } | ||
126 | if (chan_mask & SP_LFE) { | ||
127 | dst->ac97_lfe = *src++; | ||
128 | dst->ac97_tag |= TAG_PCM_LFE; | ||
129 | } | ||
130 | if (chan_mask & SP_FC) { | ||
131 | dst->ac97_center = *src++; | ||
132 | dst->ac97_tag |= TAG_PCM_CENTER; | ||
133 | } | ||
134 | #endif | ||
135 | dst++; | ||
107 | } | 136 | } |
108 | } | 137 | } |
109 | EXPORT_SYMBOL(bf5xx_pcm_to_ac97); | 138 | EXPORT_SYMBOL(bf5xx_pcm_to_ac97); |
110 | 139 | ||
111 | void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \ | 140 | void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst, |
112 | size_t count) | 141 | size_t count) |
113 | { | 142 | { |
114 | while (count--) | 143 | while (count--) { |
115 | *(dst++) = (src++)->ac97_pcm; | 144 | *(dst++) = src->ac97_pcm_l; |
145 | *(dst++) = src->ac97_pcm_r; | ||
146 | src++; | ||
147 | } | ||
116 | } | 148 | } |
117 | EXPORT_SYMBOL(bf5xx_ac97_to_pcm); | 149 | EXPORT_SYMBOL(bf5xx_ac97_to_pcm); |
118 | 150 | ||
119 | static unsigned int sport_tx_curr_frag(struct sport_device *sport) | 151 | static unsigned int sport_tx_curr_frag(struct sport_device *sport) |
120 | { | 152 | { |
121 | return sport->tx_curr_frag = sport_curr_offset_tx(sport) / \ | 153 | return sport->tx_curr_frag = sport_curr_offset_tx(sport) / |
122 | sport->tx_fragsize; | 154 | sport->tx_fragsize; |
123 | } | 155 | } |
124 | 156 | ||
@@ -130,7 +162,7 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data) | |||
130 | 162 | ||
131 | sport_incfrag(sport, &nextfrag, 1); | 163 | sport_incfrag(sport, &nextfrag, 1); |
132 | 164 | ||
133 | nextwrite = (struct ac97_frame *)(sport->tx_buf + \ | 165 | nextwrite = (struct ac97_frame *)(sport->tx_buf + |
134 | nextfrag * sport->tx_fragsize); | 166 | nextfrag * sport->tx_fragsize); |
135 | pr_debug("sport->tx_buf:%p, nextfrag:0x%x nextwrite:%p, cmd_count:%d\n", | 167 | pr_debug("sport->tx_buf:%p, nextfrag:0x%x nextwrite:%p, cmd_count:%d\n", |
136 | sport->tx_buf, nextfrag, nextwrite, cmd_count[nextfrag]); | 168 | sport->tx_buf, nextfrag, nextwrite, cmd_count[nextfrag]); |
@@ -297,20 +329,15 @@ static int bf5xx_ac97_resume(struct platform_device *pdev, | |||
297 | static int bf5xx_ac97_probe(struct platform_device *pdev, | 329 | static int bf5xx_ac97_probe(struct platform_device *pdev, |
298 | struct snd_soc_dai *dai) | 330 | struct snd_soc_dai *dai) |
299 | { | 331 | { |
300 | int ret; | 332 | int ret = 0; |
301 | #if defined(CONFIG_BF54x) | ||
302 | u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1, | ||
303 | PIN_REQ_SPORT_2, PIN_REQ_SPORT_3}; | ||
304 | #else | ||
305 | u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1}; | ||
306 | #endif | ||
307 | cmd_count = (int *)get_zeroed_page(GFP_KERNEL); | 333 | cmd_count = (int *)get_zeroed_page(GFP_KERNEL); |
308 | if (cmd_count == NULL) | 334 | if (cmd_count == NULL) |
309 | return -ENOMEM; | 335 | return -ENOMEM; |
310 | 336 | ||
311 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { | 337 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { |
312 | pr_err("Requesting Peripherals failed\n"); | 338 | pr_err("Requesting Peripherals failed\n"); |
313 | return -EFAULT; | 339 | ret = -EFAULT; |
340 | goto peripheral_err; | ||
314 | } | 341 | } |
315 | 342 | ||
316 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 343 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
@@ -318,54 +345,52 @@ static int bf5xx_ac97_probe(struct platform_device *pdev, | |||
318 | if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) { | 345 | if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) { |
319 | pr_err("Failed to request GPIO_%d for reset\n", | 346 | pr_err("Failed to request GPIO_%d for reset\n", |
320 | CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 347 | CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
321 | peripheral_free_list(&sport_req[sport_num][0]); | 348 | ret = -1; |
322 | return -1; | 349 | goto gpio_err; |
323 | } | 350 | } |
324 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); | 351 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); |
325 | #endif | 352 | #endif |
326 | sport_handle = sport_init(&sport_params[sport_num], 2, \ | 353 | sport_handle = sport_init(&sport_params[sport_num], 2, \ |
327 | sizeof(struct ac97_frame), NULL); | 354 | sizeof(struct ac97_frame), NULL); |
328 | if (!sport_handle) { | 355 | if (!sport_handle) { |
329 | peripheral_free_list(&sport_req[sport_num][0]); | 356 | ret = -ENODEV; |
330 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 357 | goto sport_err; |
331 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
332 | #endif | ||
333 | return -ENODEV; | ||
334 | } | 358 | } |
335 | /*SPORT works in TDM mode to simulate AC97 transfers*/ | 359 | /*SPORT works in TDM mode to simulate AC97 transfers*/ |
336 | ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); | 360 | ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); |
337 | if (ret) { | 361 | if (ret) { |
338 | pr_err("SPORT is busy!\n"); | 362 | pr_err("SPORT is busy!\n"); |
339 | kfree(sport_handle); | 363 | ret = -EBUSY; |
340 | peripheral_free_list(&sport_req[sport_num][0]); | 364 | goto sport_config_err; |
341 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | ||
342 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
343 | #endif | ||
344 | return -EBUSY; | ||
345 | } | 365 | } |
346 | 366 | ||
347 | ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1)); | 367 | ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1)); |
348 | if (ret) { | 368 | if (ret) { |
349 | pr_err("SPORT is busy!\n"); | 369 | pr_err("SPORT is busy!\n"); |
350 | kfree(sport_handle); | 370 | ret = -EBUSY; |
351 | peripheral_free_list(&sport_req[sport_num][0]); | 371 | goto sport_config_err; |
352 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | ||
353 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
354 | #endif | ||
355 | return -EBUSY; | ||
356 | } | 372 | } |
357 | 373 | ||
358 | ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1)); | 374 | ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1)); |
359 | if (ret) { | 375 | if (ret) { |
360 | pr_err("SPORT is busy!\n"); | 376 | pr_err("SPORT is busy!\n"); |
361 | kfree(sport_handle); | 377 | ret = -EBUSY; |
362 | peripheral_free_list(&sport_req[sport_num][0]); | 378 | goto sport_config_err; |
379 | } | ||
380 | |||
381 | sport_config_err: | ||
382 | kfree(sport_handle); | ||
383 | sport_err: | ||
363 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 384 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
364 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 385 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
365 | #endif | 386 | #endif |
366 | return -EBUSY; | 387 | gpio_err: |
367 | } | 388 | peripheral_free_list(&sport_req[sport_num][0]); |
368 | return 0; | 389 | peripheral_err: |
390 | free_page((unsigned long)cmd_count); | ||
391 | cmd_count = NULL; | ||
392 | |||
393 | return ret; | ||
369 | } | 394 | } |
370 | 395 | ||
371 | static void bf5xx_ac97_remove(struct platform_device *pdev, | 396 | static void bf5xx_ac97_remove(struct platform_device *pdev, |
@@ -373,6 +398,7 @@ static void bf5xx_ac97_remove(struct platform_device *pdev, | |||
373 | { | 398 | { |
374 | free_page((unsigned long)cmd_count); | 399 | free_page((unsigned long)cmd_count); |
375 | cmd_count = NULL; | 400 | cmd_count = NULL; |
401 | peripheral_free_list(&sport_req[sport_num][0]); | ||
376 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 402 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
377 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 403 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
378 | #endif | 404 | #endif |
@@ -389,7 +415,11 @@ struct snd_soc_dai bfin_ac97_dai = { | |||
389 | .playback = { | 415 | .playback = { |
390 | .stream_name = "AC97 Playback", | 416 | .stream_name = "AC97 Playback", |
391 | .channels_min = 2, | 417 | .channels_min = 2, |
418 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | ||
419 | .channels_max = 6, | ||
420 | #else | ||
392 | .channels_max = 2, | 421 | .channels_max = 2, |
422 | #endif | ||
393 | .rates = SNDRV_PCM_RATE_48000, | 423 | .rates = SNDRV_PCM_RATE_48000, |
394 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | 424 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, |
395 | .capture = { | 425 | .capture = { |
diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h index 3f77cc558dc0..3f2a911fe0cb 100644 --- a/sound/soc/blackfin/bf5xx-ac97.h +++ b/sound/soc/blackfin/bf5xx-ac97.h | |||
@@ -16,21 +16,46 @@ struct ac97_frame { | |||
16 | u16 ac97_tag; /* slot 0 */ | 16 | u16 ac97_tag; /* slot 0 */ |
17 | u16 ac97_addr; /* slot 1 */ | 17 | u16 ac97_addr; /* slot 1 */ |
18 | u16 ac97_data; /* slot 2 */ | 18 | u16 ac97_data; /* slot 2 */ |
19 | u32 ac97_pcm; /* slot 3 and 4: left and right pcm data */ | 19 | u16 ac97_pcm_l; /*slot 3:front left*/ |
20 | u16 ac97_pcm_r; /*slot 4:front left*/ | ||
21 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | ||
22 | u16 ac97_mdm_l1; | ||
23 | u16 ac97_center; /*slot 6:center*/ | ||
24 | u16 ac97_sl; /*slot 7:surround left*/ | ||
25 | u16 ac97_sr; /*slot 8:surround right*/ | ||
26 | u16 ac97_lfe; /*slot 9:lfe*/ | ||
27 | #endif | ||
20 | } __attribute__ ((packed)); | 28 | } __attribute__ ((packed)); |
21 | 29 | ||
30 | /* Speaker location */ | ||
31 | #define SP_FL 0x0001 | ||
32 | #define SP_FR 0x0010 | ||
33 | #define SP_FC 0x0002 | ||
34 | #define SP_LFE 0x0020 | ||
35 | #define SP_SL 0x0004 | ||
36 | #define SP_SR 0x0040 | ||
37 | |||
38 | #define SP_STEREO (SP_FL | SP_FR) | ||
39 | #define SP_2DOT1 (SP_FL | SP_FR | SP_LFE) | ||
40 | #define SP_QUAD (SP_FL | SP_FR | SP_SL | SP_SR) | ||
41 | #define SP_5DOT1 (SP_FL | SP_FR | SP_FC | SP_LFE | SP_SL | SP_SR) | ||
42 | |||
22 | #define TAG_VALID 0x8000 | 43 | #define TAG_VALID 0x8000 |
23 | #define TAG_CMD 0x6000 | 44 | #define TAG_CMD 0x6000 |
24 | #define TAG_PCM_LEFT 0x1000 | 45 | #define TAG_PCM_LEFT 0x1000 |
25 | #define TAG_PCM_RIGHT 0x0800 | 46 | #define TAG_PCM_RIGHT 0x0800 |
26 | #define TAG_PCM (TAG_PCM_LEFT | TAG_PCM_RIGHT) | 47 | #define TAG_PCM_MDM_L1 0x0400 |
48 | #define TAG_PCM_CENTER 0x0200 | ||
49 | #define TAG_PCM_SL 0x0100 | ||
50 | #define TAG_PCM_SR 0x0080 | ||
51 | #define TAG_PCM_LFE 0x0040 | ||
27 | 52 | ||
28 | extern struct snd_soc_dai bfin_ac97_dai; | 53 | extern struct snd_soc_dai bfin_ac97_dai; |
29 | 54 | ||
30 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \ | 55 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \ |
31 | size_t count); | 56 | size_t count, unsigned int chan_mask); |
32 | 57 | ||
33 | void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \ | 58 | void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst, \ |
34 | size_t count); | 59 | size_t count); |
35 | 60 | ||
36 | #endif | 61 | #endif |
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h index fcadcc081f7f..2e63dea73e9c 100644 --- a/sound/soc/blackfin/bf5xx-sport.h +++ b/sound/soc/blackfin/bf5xx-sport.h | |||
@@ -116,7 +116,7 @@ struct sport_device { | |||
116 | void *err_data; | 116 | void *err_data; |
117 | unsigned char *tx_dma_buf; | 117 | unsigned char *tx_dma_buf; |
118 | unsigned char *rx_dma_buf; | 118 | unsigned char *rx_dma_buf; |
119 | #ifdef CONFIG_SND_MMAP_SUPPORT | 119 | #ifdef CONFIG_SND_BF5XX_MMAP_SUPPORT |
120 | dma_addr_t tx_dma_phy; | 120 | dma_addr_t tx_dma_phy; |
121 | dma_addr_t rx_dma_phy; | 121 | dma_addr_t rx_dma_phy; |
122 | int tx_pos;/*pcm sample count*/ | 122 | int tx_pos;/*pcm sample count*/ |