diff options
Diffstat (limited to 'sound/soc/blackfin')
-rw-r--r-- | sound/soc/blackfin/Kconfig | 22 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ac97-pcm.c | 113 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ac97.c | 178 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ac97.h | 35 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ad1980.c | 8 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ad73311.c | 10 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-i2s-pcm.c | 12 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-i2s.c | 31 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-sport.h | 2 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ssm2602.c | 14 |
10 files changed, 267 insertions, 158 deletions
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index dc006206f622..0a2f8f9eff53 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config SND_BF5XX_I2S | 1 | config SND_BF5XX_I2S |
2 | tristate "SoC I2S Audio for the ADI BF5xx chip" | 2 | tristate "SoC I2S Audio for the ADI BF5xx chip" |
3 | depends on BLACKFIN && SND_SOC | 3 | depends on BLACKFIN |
4 | help | 4 | help |
5 | Say Y or M if you want to add support for codecs attached to | 5 | Say Y or M if you want to add support for codecs attached to |
6 | the Blackfin SPORT (synchronous serial ports) interface in I2S | 6 | the Blackfin SPORT (synchronous serial ports) interface in I2S |
@@ -13,7 +13,6 @@ config SND_BF5XX_SOC_SSM2602 | |||
13 | select SND_BF5XX_SOC_I2S | 13 | select SND_BF5XX_SOC_I2S |
14 | select SND_SOC_SSM2602 | 14 | select SND_SOC_SSM2602 |
15 | select I2C | 15 | select I2C |
16 | select I2C_BLACKFIN_TWI | ||
17 | help | 16 | help |
18 | Say Y if you want to add support for SoC audio on BF527-EZKIT. | 17 | Say Y if you want to add support for SoC audio on BF527-EZKIT. |
19 | 18 | ||
@@ -35,7 +34,7 @@ config SND_BFIN_AD73311_SE | |||
35 | 34 | ||
36 | config SND_BF5XX_AC97 | 35 | config SND_BF5XX_AC97 |
37 | tristate "SoC AC97 Audio for the ADI BF5xx chip" | 36 | tristate "SoC AC97 Audio for the ADI BF5xx chip" |
38 | depends on BLACKFIN && SND_SOC | 37 | depends on BLACKFIN |
39 | help | 38 | help |
40 | Say Y or M if you want to add support for codecs attached to | 39 | Say Y or M if you want to add support for codecs attached to |
41 | the Blackfin SPORT (synchronous serial ports) interface in slot 16 | 40 | the Blackfin SPORT (synchronous serial ports) interface in slot 16 |
@@ -47,7 +46,7 @@ config SND_BF5XX_AC97 | |||
47 | properly with this driver. This driver is known to work with the | 46 | properly with this driver. This driver is known to work with the |
48 | Analog Devices line of AC97 codecs. | 47 | Analog Devices line of AC97 codecs. |
49 | 48 | ||
50 | config SND_MMAP_SUPPORT | 49 | config SND_BF5XX_MMAP_SUPPORT |
51 | bool "Enable MMAP Support" | 50 | bool "Enable MMAP Support" |
52 | depends on SND_BF5XX_AC97 | 51 | depends on SND_BF5XX_AC97 |
53 | default y | 52 | default y |
@@ -55,9 +54,17 @@ config SND_MMAP_SUPPORT | |||
55 | Say y if you want AC97 driver to support mmap mode. | 54 | Say y if you want AC97 driver to support mmap mode. |
56 | We introduce an intermediate buffer to simulate mmap. | 55 | We introduce an intermediate buffer to simulate mmap. |
57 | 56 | ||
57 | config SND_BF5XX_MULTICHAN_SUPPORT | ||
58 | bool "Enable Multichannel Support" | ||
59 | depends on SND_BF5XX_AC97 | ||
60 | default n | ||
61 | help | ||
62 | Say y if you want AC97 driver to support up to 5.1 channel audio. | ||
63 | this mode will consume much more memory for DMA. | ||
64 | |||
58 | config SND_BF5XX_SOC_SPORT | 65 | config SND_BF5XX_SOC_SPORT |
59 | tristate | 66 | tristate |
60 | 67 | ||
61 | config SND_BF5XX_SOC_I2S | 68 | config SND_BF5XX_SOC_I2S |
62 | tristate | 69 | tristate |
63 | select SND_BF5XX_SOC_SPORT | 70 | select SND_BF5XX_SOC_SPORT |
@@ -80,7 +87,7 @@ config SND_BF5XX_SPORT_NUM | |||
80 | int "Set a SPORT for Sound chip" | 87 | int "Set a SPORT for Sound chip" |
81 | depends on (SND_BF5XX_I2S || SND_BF5XX_AC97) | 88 | depends on (SND_BF5XX_I2S || SND_BF5XX_AC97) |
82 | range 0 3 if BF54x | 89 | range 0 3 if BF54x |
83 | range 0 1 if (BF53x || BF561) | 90 | range 0 1 if !BF54x |
84 | default 0 | 91 | default 0 |
85 | help | 92 | help |
86 | Set the correct SPORT for sound chip. | 93 | Set the correct SPORT for sound chip. |
@@ -90,12 +97,13 @@ config SND_BF5XX_HAVE_COLD_RESET | |||
90 | depends on SND_BF5XX_AC97 | 97 | depends on SND_BF5XX_AC97 |
91 | default y if BFIN548_EZKIT | 98 | default y if BFIN548_EZKIT |
92 | default n if !BFIN548_EZKIT | 99 | default n if !BFIN548_EZKIT |
93 | 100 | ||
94 | config SND_BF5XX_RESET_GPIO_NUM | 101 | config SND_BF5XX_RESET_GPIO_NUM |
95 | int "Set a GPIO for cold reset" | 102 | int "Set a GPIO for cold reset" |
96 | depends on SND_BF5XX_HAVE_COLD_RESET | 103 | depends on SND_BF5XX_HAVE_COLD_RESET |
97 | range 0 159 | 104 | range 0 159 |
98 | default 19 if BFIN548_EZKIT | 105 | default 19 if BFIN548_EZKIT |
99 | default 5 if BFIN537_STAMP | 106 | default 5 if BFIN537_STAMP |
107 | default 0 | ||
100 | help | 108 | help |
101 | Set the correct GPIO for RESET the sound chip. | 109 | Set the correct GPIO for RESET the sound chip. |
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 25e50d2ea1ec..8067cfafa3a7 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,17 +100,14 @@ 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 | ||
94 | static const struct snd_pcm_hardware bf5xx_pcm_hardware = { | 103 | static const struct snd_pcm_hardware bf5xx_pcm_hardware = { |
95 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 104 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
105 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) | ||
96 | SNDRV_PCM_INFO_MMAP | | 106 | SNDRV_PCM_INFO_MMAP | |
97 | SNDRV_PCM_INFO_MMAP_VALID | | 107 | SNDRV_PCM_INFO_MMAP_VALID | |
98 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
99 | #else | ||
100 | static const struct snd_pcm_hardware bf5xx_pcm_hardware = { | ||
101 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
102 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
103 | #endif | 108 | #endif |
109 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
110 | |||
104 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 111 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
105 | .period_bytes_min = 32, | 112 | .period_bytes_min = 32, |
106 | .period_bytes_max = 0x10000, | 113 | .period_bytes_max = 0x10000, |
@@ -123,10 +130,20 @@ static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
123 | 130 | ||
124 | static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) | 131 | static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) |
125 | { | 132 | { |
133 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) | ||
126 | struct snd_pcm_runtime *runtime = substream->runtime; | 134 | struct snd_pcm_runtime *runtime = substream->runtime; |
135 | struct sport_device *sport = runtime->private_data; | ||
127 | 136 | ||
128 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 137 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
129 | memset(runtime->dma_area, 0, runtime->buffer_size); | 138 | sport->once = 0; |
139 | if (runtime->dma_area) | ||
140 | memset(runtime->dma_area, 0, runtime->buffer_size); | ||
141 | memset(sport->tx_dma_buf, 0, runtime->buffer_size * | ||
142 | sizeof(struct ac97_frame)); | ||
143 | } else | ||
144 | memset(sport->rx_dma_buf, 0, runtime->buffer_size * | ||
145 | sizeof(struct ac97_frame)); | ||
146 | #endif | ||
130 | snd_pcm_lib_free_pages(substream); | 147 | snd_pcm_lib_free_pages(substream); |
131 | return 0; | 148 | return 0; |
132 | } | 149 | } |
@@ -139,7 +156,7 @@ static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) | |||
139 | /* An intermediate buffer is introduced for implementing mmap for | 156 | /* An intermediate buffer is introduced for implementing mmap for |
140 | * SPORT working in TMD mode(include AC97). | 157 | * SPORT working in TMD mode(include AC97). |
141 | */ | 158 | */ |
142 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 159 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
143 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 160 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
144 | sport_set_tx_callback(sport, bf5xx_dma_irq, substream); | 161 | sport_set_tx_callback(sport, bf5xx_dma_irq, substream); |
145 | sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods, | 162 | sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods, |
@@ -173,24 +190,24 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
173 | switch (cmd) { | 190 | switch (cmd) { |
174 | case SNDRV_PCM_TRIGGER_START: | 191 | case SNDRV_PCM_TRIGGER_START: |
175 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 192 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
193 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) | ||
176 | bf5xx_mmap_copy(substream, runtime->period_size); | 194 | bf5xx_mmap_copy(substream, runtime->period_size); |
177 | snd_pcm_period_elapsed(substream); | ||
178 | sport->tx_delay_pos = 0; | 195 | sport->tx_delay_pos = 0; |
196 | #endif | ||
179 | sport_tx_start(sport); | 197 | sport_tx_start(sport); |
180 | } | 198 | } else |
181 | else | ||
182 | sport_rx_start(sport); | 199 | sport_rx_start(sport); |
183 | break; | 200 | break; |
184 | case SNDRV_PCM_TRIGGER_STOP: | 201 | case SNDRV_PCM_TRIGGER_STOP: |
185 | case SNDRV_PCM_TRIGGER_SUSPEND: | 202 | case SNDRV_PCM_TRIGGER_SUSPEND: |
186 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 203 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
187 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 204 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
188 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 205 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
189 | sport->tx_pos = 0; | 206 | sport->tx_pos = 0; |
190 | #endif | 207 | #endif |
191 | sport_tx_stop(sport); | 208 | sport_tx_stop(sport); |
192 | } else { | 209 | } else { |
193 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 210 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
194 | sport->rx_pos = 0; | 211 | sport->rx_pos = 0; |
195 | #endif | 212 | #endif |
196 | sport_rx_stop(sport); | 213 | sport_rx_stop(sport); |
@@ -208,7 +225,7 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
208 | struct sport_device *sport = runtime->private_data; | 225 | struct sport_device *sport = runtime->private_data; |
209 | unsigned int curr; | 226 | unsigned int curr; |
210 | 227 | ||
211 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 228 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
212 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 229 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
213 | curr = sport->tx_delay_pos; | 230 | curr = sport->tx_delay_pos; |
214 | else | 231 | else |
@@ -249,22 +266,7 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | |||
249 | return ret; | 266 | return ret; |
250 | } | 267 | } |
251 | 268 | ||
252 | static int bf5xx_pcm_close(struct snd_pcm_substream *substream) | 269 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
253 | { | ||
254 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
255 | struct sport_device *sport = runtime->private_data; | ||
256 | |||
257 | pr_debug("%s enter\n", __func__); | ||
258 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
259 | sport->once = 0; | ||
260 | memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame)); | ||
261 | } else | ||
262 | memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame)); | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | #ifdef CONFIG_SND_MMAP_SUPPORT | ||
268 | static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, | 270 | static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, |
269 | struct vm_area_struct *vma) | 271 | struct vm_area_struct *vma) |
270 | { | 272 | { |
@@ -281,32 +283,29 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, | |||
281 | void __user *buf, snd_pcm_uframes_t count) | 283 | void __user *buf, snd_pcm_uframes_t count) |
282 | { | 284 | { |
283 | struct snd_pcm_runtime *runtime = substream->runtime; | 285 | struct snd_pcm_runtime *runtime = substream->runtime; |
284 | 286 | unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1]; | |
285 | pr_debug("%s copy pos:0x%lx count:0x%lx\n", | 287 | pr_debug("%s copy pos:0x%lx count:0x%lx\n", |
286 | substream->stream ? "Capture" : "Playback", pos, count); | 288 | substream->stream ? "Capture" : "Playback", pos, count); |
287 | 289 | ||
288 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 290 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
289 | bf5xx_pcm_to_ac97( | 291 | bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos, |
290 | (struct ac97_frame *)runtime->dma_area + pos, | 292 | (__u16 *)buf, count, chan_mask); |
291 | buf, count); | ||
292 | else | 293 | else |
293 | bf5xx_ac97_to_pcm( | 294 | bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos, |
294 | (struct ac97_frame *)runtime->dma_area + pos, | 295 | (__u16 *)buf, count); |
295 | buf, count); | ||
296 | return 0; | 296 | return 0; |
297 | } | 297 | } |
298 | #endif | 298 | #endif |
299 | 299 | ||
300 | struct snd_pcm_ops bf5xx_pcm_ac97_ops = { | 300 | struct snd_pcm_ops bf5xx_pcm_ac97_ops = { |
301 | .open = bf5xx_pcm_open, | 301 | .open = bf5xx_pcm_open, |
302 | .close = bf5xx_pcm_close, | ||
303 | .ioctl = snd_pcm_lib_ioctl, | 302 | .ioctl = snd_pcm_lib_ioctl, |
304 | .hw_params = bf5xx_pcm_hw_params, | 303 | .hw_params = bf5xx_pcm_hw_params, |
305 | .hw_free = bf5xx_pcm_hw_free, | 304 | .hw_free = bf5xx_pcm_hw_free, |
306 | .prepare = bf5xx_pcm_prepare, | 305 | .prepare = bf5xx_pcm_prepare, |
307 | .trigger = bf5xx_pcm_trigger, | 306 | .trigger = bf5xx_pcm_trigger, |
308 | .pointer = bf5xx_pcm_pointer, | 307 | .pointer = bf5xx_pcm_pointer, |
309 | #ifdef CONFIG_SND_MMAP_SUPPORT | 308 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
310 | .mmap = bf5xx_pcm_mmap, | 309 | .mmap = bf5xx_pcm_mmap, |
311 | #else | 310 | #else |
312 | .copy = bf5xx_pcm_copy, | 311 | .copy = bf5xx_pcm_copy, |
@@ -344,7 +343,7 @@ static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | |||
344 | * Need to allocate local buffer when enable | 343 | * Need to allocate local buffer when enable |
345 | * MMAP for SPORT working in TMD mode (include AC97). | 344 | * MMAP for SPORT working in TMD mode (include AC97). |
346 | */ | 345 | */ |
347 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 346 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
348 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 347 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
349 | if (!sport_handle->tx_dma_buf) { | 348 | if (!sport_handle->tx_dma_buf) { |
350 | sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \ | 349 | sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \ |
@@ -381,7 +380,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
381 | struct snd_pcm_substream *substream; | 380 | struct snd_pcm_substream *substream; |
382 | struct snd_dma_buffer *buf; | 381 | struct snd_dma_buffer *buf; |
383 | int stream; | 382 | int stream; |
384 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 383 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
385 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max * | 384 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max * |
386 | sizeof(struct ac97_frame) / 4; | 385 | sizeof(struct ac97_frame) / 4; |
387 | #endif | 386 | #endif |
@@ -395,7 +394,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
395 | continue; | 394 | continue; |
396 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); | 395 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); |
397 | buf->area = NULL; | 396 | buf->area = NULL; |
398 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 397 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
399 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 398 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
400 | if (sport_handle->tx_dma_buf) | 399 | if (sport_handle->tx_dma_buf) |
401 | dma_free_coherent(NULL, size, \ | 400 | dma_free_coherent(NULL, size, \ |
@@ -452,6 +451,18 @@ struct snd_soc_platform bf5xx_ac97_soc_platform = { | |||
452 | }; | 451 | }; |
453 | EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform); | 452 | EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform); |
454 | 453 | ||
454 | static int __init bfin_ac97_init(void) | ||
455 | { | ||
456 | return snd_soc_register_platform(&bf5xx_ac97_soc_platform); | ||
457 | } | ||
458 | module_init(bfin_ac97_init); | ||
459 | |||
460 | static void __exit bfin_ac97_exit(void) | ||
461 | { | ||
462 | snd_soc_unregister_platform(&bf5xx_ac97_soc_platform); | ||
463 | } | ||
464 | module_exit(bfin_ac97_exit); | ||
465 | |||
455 | MODULE_AUTHOR("Cliff Cai"); | 466 | MODULE_AUTHOR("Cliff Cai"); |
456 | MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module"); | 467 | MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module"); |
457 | MODULE_LICENSE("GPL"); | 468 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index 5e5aafb6485f..3be2be60576d 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]); |
@@ -237,8 +269,7 @@ struct snd_ac97_bus_ops soc_ac97_ops = { | |||
237 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | 269 | EXPORT_SYMBOL_GPL(soc_ac97_ops); |
238 | 270 | ||
239 | #ifdef CONFIG_PM | 271 | #ifdef CONFIG_PM |
240 | static int bf5xx_ac97_suspend(struct platform_device *pdev, | 272 | static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) |
241 | struct snd_soc_dai *dai) | ||
242 | { | 273 | { |
243 | struct sport_device *sport = | 274 | struct sport_device *sport = |
244 | (struct sport_device *)dai->private_data; | 275 | (struct sport_device *)dai->private_data; |
@@ -253,8 +284,7 @@ static int bf5xx_ac97_suspend(struct platform_device *pdev, | |||
253 | return 0; | 284 | return 0; |
254 | } | 285 | } |
255 | 286 | ||
256 | static int bf5xx_ac97_resume(struct platform_device *pdev, | 287 | static int bf5xx_ac97_resume(struct snd_soc_dai *dai) |
257 | struct snd_soc_dai *dai) | ||
258 | { | 288 | { |
259 | int ret; | 289 | int ret; |
260 | struct sport_device *sport = | 290 | struct sport_device *sport = |
@@ -297,20 +327,15 @@ static int bf5xx_ac97_resume(struct platform_device *pdev, | |||
297 | static int bf5xx_ac97_probe(struct platform_device *pdev, | 327 | static int bf5xx_ac97_probe(struct platform_device *pdev, |
298 | struct snd_soc_dai *dai) | 328 | struct snd_soc_dai *dai) |
299 | { | 329 | { |
300 | int ret; | 330 | 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); | 331 | cmd_count = (int *)get_zeroed_page(GFP_KERNEL); |
308 | if (cmd_count == NULL) | 332 | if (cmd_count == NULL) |
309 | return -ENOMEM; | 333 | return -ENOMEM; |
310 | 334 | ||
311 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { | 335 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { |
312 | pr_err("Requesting Peripherals failed\n"); | 336 | pr_err("Requesting Peripherals failed\n"); |
313 | return -EFAULT; | 337 | ret = -EFAULT; |
338 | goto peripheral_err; | ||
314 | } | 339 | } |
315 | 340 | ||
316 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 341 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
@@ -318,54 +343,54 @@ static int bf5xx_ac97_probe(struct platform_device *pdev, | |||
318 | if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) { | 343 | if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) { |
319 | pr_err("Failed to request GPIO_%d for reset\n", | 344 | pr_err("Failed to request GPIO_%d for reset\n", |
320 | CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 345 | CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
321 | peripheral_free_list(&sport_req[sport_num][0]); | 346 | ret = -1; |
322 | return -1; | 347 | goto gpio_err; |
323 | } | 348 | } |
324 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); | 349 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); |
325 | #endif | 350 | #endif |
326 | sport_handle = sport_init(&sport_params[sport_num], 2, \ | 351 | sport_handle = sport_init(&sport_params[sport_num], 2, \ |
327 | sizeof(struct ac97_frame), NULL); | 352 | sizeof(struct ac97_frame), NULL); |
328 | if (!sport_handle) { | 353 | if (!sport_handle) { |
329 | peripheral_free_list(&sport_req[sport_num][0]); | 354 | ret = -ENODEV; |
330 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 355 | goto sport_err; |
331 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
332 | #endif | ||
333 | return -ENODEV; | ||
334 | } | 356 | } |
335 | /*SPORT works in TDM mode to simulate AC97 transfers*/ | 357 | /*SPORT works in TDM mode to simulate AC97 transfers*/ |
336 | ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); | 358 | ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); |
337 | if (ret) { | 359 | if (ret) { |
338 | pr_err("SPORT is busy!\n"); | 360 | pr_err("SPORT is busy!\n"); |
339 | kfree(sport_handle); | 361 | ret = -EBUSY; |
340 | peripheral_free_list(&sport_req[sport_num][0]); | 362 | 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 | } | 363 | } |
346 | 364 | ||
347 | ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1)); | 365 | ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1)); |
348 | if (ret) { | 366 | if (ret) { |
349 | pr_err("SPORT is busy!\n"); | 367 | pr_err("SPORT is busy!\n"); |
350 | kfree(sport_handle); | 368 | ret = -EBUSY; |
351 | peripheral_free_list(&sport_req[sport_num][0]); | 369 | 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 | } | 370 | } |
357 | 371 | ||
358 | ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1)); | 372 | ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1)); |
359 | if (ret) { | 373 | if (ret) { |
360 | pr_err("SPORT is busy!\n"); | 374 | pr_err("SPORT is busy!\n"); |
361 | kfree(sport_handle); | 375 | ret = -EBUSY; |
362 | peripheral_free_list(&sport_req[sport_num][0]); | 376 | goto sport_config_err; |
363 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | ||
364 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
365 | #endif | ||
366 | return -EBUSY; | ||
367 | } | 377 | } |
378 | |||
368 | return 0; | 379 | return 0; |
380 | |||
381 | sport_config_err: | ||
382 | kfree(sport_handle); | ||
383 | sport_err: | ||
384 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | ||
385 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
386 | #endif | ||
387 | gpio_err: | ||
388 | peripheral_free_list(&sport_req[sport_num][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 |
@@ -381,7 +407,7 @@ static void bf5xx_ac97_remove(struct platform_device *pdev, | |||
381 | struct snd_soc_dai bfin_ac97_dai = { | 407 | struct snd_soc_dai bfin_ac97_dai = { |
382 | .name = "bf5xx-ac97", | 408 | .name = "bf5xx-ac97", |
383 | .id = 0, | 409 | .id = 0, |
384 | .type = SND_SOC_DAI_AC97, | 410 | .ac97_control = 1, |
385 | .probe = bf5xx_ac97_probe, | 411 | .probe = bf5xx_ac97_probe, |
386 | .remove = bf5xx_ac97_remove, | 412 | .remove = bf5xx_ac97_remove, |
387 | .suspend = bf5xx_ac97_suspend, | 413 | .suspend = bf5xx_ac97_suspend, |
@@ -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 = { |
@@ -401,6 +431,18 @@ struct snd_soc_dai bfin_ac97_dai = { | |||
401 | }; | 431 | }; |
402 | EXPORT_SYMBOL_GPL(bfin_ac97_dai); | 432 | EXPORT_SYMBOL_GPL(bfin_ac97_dai); |
403 | 433 | ||
434 | static int __init bfin_ac97_init(void) | ||
435 | { | ||
436 | return snd_soc_register_dai(&bfin_ac97_dai); | ||
437 | } | ||
438 | module_init(bfin_ac97_init); | ||
439 | |||
440 | static void __exit bfin_ac97_exit(void) | ||
441 | { | ||
442 | snd_soc_unregister_dai(&bfin_ac97_dai); | ||
443 | } | ||
444 | module_exit(bfin_ac97_exit); | ||
445 | |||
404 | MODULE_AUTHOR("Roy Huang"); | 446 | MODULE_AUTHOR("Roy Huang"); |
405 | MODULE_DESCRIPTION("AC97 driver for ADI Blackfin"); | 447 | MODULE_DESCRIPTION("AC97 driver for ADI Blackfin"); |
406 | MODULE_LICENSE("GPL"); | 448 | MODULE_LICENSE("GPL"); |
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-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c index 124425d22320..d8f591273778 100644 --- a/sound/soc/blackfin/bf5xx-ad1980.c +++ b/sound/soc/blackfin/bf5xx-ad1980.c | |||
@@ -43,7 +43,7 @@ | |||
43 | #include "bf5xx-ac97-pcm.h" | 43 | #include "bf5xx-ac97-pcm.h" |
44 | #include "bf5xx-ac97.h" | 44 | #include "bf5xx-ac97.h" |
45 | 45 | ||
46 | static struct snd_soc_machine bf5xx_board; | 46 | static struct snd_soc_card bf5xx_board; |
47 | 47 | ||
48 | static int bf5xx_board_startup(struct snd_pcm_substream *substream) | 48 | static int bf5xx_board_startup(struct snd_pcm_substream *substream) |
49 | { | 49 | { |
@@ -67,15 +67,15 @@ static struct snd_soc_dai_link bf5xx_board_dai = { | |||
67 | .ops = &bf5xx_board_ops, | 67 | .ops = &bf5xx_board_ops, |
68 | }; | 68 | }; |
69 | 69 | ||
70 | static struct snd_soc_machine bf5xx_board = { | 70 | static struct snd_soc_card bf5xx_board = { |
71 | .name = "bf5xx-board", | 71 | .name = "bf5xx-board", |
72 | .platform = &bf5xx_ac97_soc_platform, | ||
72 | .dai_link = &bf5xx_board_dai, | 73 | .dai_link = &bf5xx_board_dai, |
73 | .num_links = 1, | 74 | .num_links = 1, |
74 | }; | 75 | }; |
75 | 76 | ||
76 | static struct snd_soc_device bf5xx_board_snd_devdata = { | 77 | static struct snd_soc_device bf5xx_board_snd_devdata = { |
77 | .machine = &bf5xx_board, | 78 | .card = &bf5xx_board, |
78 | .platform = &bf5xx_ac97_soc_platform, | ||
79 | .codec_dev = &soc_codec_dev_ad1980, | 79 | .codec_dev = &soc_codec_dev_ad1980, |
80 | }; | 80 | }; |
81 | 81 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c index 622c9b909532..7f2a5e199075 100644 --- a/sound/soc/blackfin/bf5xx-ad73311.c +++ b/sound/soc/blackfin/bf5xx-ad73311.c | |||
@@ -65,7 +65,7 @@ | |||
65 | 65 | ||
66 | #define GPIO_SE CONFIG_SND_BFIN_AD73311_SE | 66 | #define GPIO_SE CONFIG_SND_BFIN_AD73311_SE |
67 | 67 | ||
68 | static struct snd_soc_machine bf5xx_ad73311; | 68 | static struct snd_soc_card bf5xx_ad73311; |
69 | 69 | ||
70 | static int snd_ad73311_startup(void) | 70 | static int snd_ad73311_startup(void) |
71 | { | 71 | { |
@@ -168,7 +168,7 @@ static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream, | |||
168 | params_format(params)); | 168 | params_format(params)); |
169 | 169 | ||
170 | /* set cpu DAI configuration */ | 170 | /* set cpu DAI configuration */ |
171 | ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | | 171 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | |
172 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | 172 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); |
173 | if (ret < 0) | 173 | if (ret < 0) |
174 | return ret; | 174 | return ret; |
@@ -190,16 +190,16 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai = { | |||
190 | .ops = &bf5xx_ad73311_ops, | 190 | .ops = &bf5xx_ad73311_ops, |
191 | }; | 191 | }; |
192 | 192 | ||
193 | static struct snd_soc_machine bf5xx_ad73311 = { | 193 | static struct snd_soc_card bf5xx_ad73311 = { |
194 | .name = "bf5xx_ad73311", | 194 | .name = "bf5xx_ad73311", |
195 | .platform = &bf5xx_i2s_soc_platform, | ||
195 | .probe = bf5xx_probe, | 196 | .probe = bf5xx_probe, |
196 | .dai_link = &bf5xx_ad73311_dai, | 197 | .dai_link = &bf5xx_ad73311_dai, |
197 | .num_links = 1, | 198 | .num_links = 1, |
198 | }; | 199 | }; |
199 | 200 | ||
200 | static struct snd_soc_device bf5xx_ad73311_snd_devdata = { | 201 | static struct snd_soc_device bf5xx_ad73311_snd_devdata = { |
201 | .machine = &bf5xx_ad73311, | 202 | .card = &bf5xx_ad73311, |
202 | .platform = &bf5xx_i2s_soc_platform, | ||
203 | .codec_dev = &soc_codec_dev_ad73311, | 203 | .codec_dev = &soc_codec_dev_ad73311, |
204 | }; | 204 | }; |
205 | 205 | ||
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 61fccf925192..53d290b3ea47 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -283,6 +283,18 @@ struct snd_soc_platform bf5xx_i2s_soc_platform = { | |||
283 | }; | 283 | }; |
284 | EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform); | 284 | EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform); |
285 | 285 | ||
286 | static int __init bfin_i2s_init(void) | ||
287 | { | ||
288 | return snd_soc_register_platform(&bf5xx_i2s_soc_platform); | ||
289 | } | ||
290 | module_init(bfin_i2s_init); | ||
291 | |||
292 | static void __exit bfin_i2s_exit(void) | ||
293 | { | ||
294 | snd_soc_unregister_platform(&bf5xx_i2s_soc_platform); | ||
295 | } | ||
296 | module_exit(bfin_i2s_exit); | ||
297 | |||
286 | MODULE_AUTHOR("Cliff Cai"); | 298 | MODULE_AUTHOR("Cliff Cai"); |
287 | MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); | 299 | MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); |
288 | MODULE_LICENSE("GPL"); | 300 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index e020c160ee44..d1d95d2393fe 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c | |||
@@ -132,7 +132,8 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
132 | return ret; | 132 | return ret; |
133 | } | 133 | } |
134 | 134 | ||
135 | static int bf5xx_i2s_startup(struct snd_pcm_substream *substream) | 135 | static int bf5xx_i2s_startup(struct snd_pcm_substream *substream, |
136 | struct snd_soc_dai *dai) | ||
136 | { | 137 | { |
137 | pr_debug("%s enter\n", __func__); | 138 | pr_debug("%s enter\n", __func__); |
138 | 139 | ||
@@ -142,7 +143,8 @@ static int bf5xx_i2s_startup(struct snd_pcm_substream *substream) | |||
142 | } | 143 | } |
143 | 144 | ||
144 | static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, | 145 | static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, |
145 | struct snd_pcm_hw_params *params) | 146 | struct snd_pcm_hw_params *params, |
147 | struct snd_soc_dai *dai) | ||
146 | { | 148 | { |
147 | int ret = 0; | 149 | int ret = 0; |
148 | 150 | ||
@@ -193,7 +195,8 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
193 | return 0; | 195 | return 0; |
194 | } | 196 | } |
195 | 197 | ||
196 | static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream) | 198 | static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream, |
199 | struct snd_soc_dai *dai) | ||
197 | { | 200 | { |
198 | pr_debug("%s enter\n", __func__); | 201 | pr_debug("%s enter\n", __func__); |
199 | bf5xx_i2s.counter--; | 202 | bf5xx_i2s.counter--; |
@@ -219,16 +222,14 @@ static int bf5xx_i2s_probe(struct platform_device *pdev, | |||
219 | return 0; | 222 | return 0; |
220 | } | 223 | } |
221 | 224 | ||
222 | static void bf5xx_i2s_remove(struct platform_device *pdev, | 225 | static void bf5xx_i2s_remove(struct snd_soc_dai *dai) |
223 | struct snd_soc_dai *dai) | ||
224 | { | 226 | { |
225 | pr_debug("%s enter\n", __func__); | 227 | pr_debug("%s enter\n", __func__); |
226 | peripheral_free_list(&sport_req[sport_num][0]); | 228 | peripheral_free_list(&sport_req[sport_num][0]); |
227 | } | 229 | } |
228 | 230 | ||
229 | #ifdef CONFIG_PM | 231 | #ifdef CONFIG_PM |
230 | static int bf5xx_i2s_suspend(struct platform_device *dev, | 232 | static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) |
231 | struct snd_soc_dai *dai) | ||
232 | { | 233 | { |
233 | struct sport_device *sport = | 234 | struct sport_device *sport = |
234 | (struct sport_device *)dai->private_data; | 235 | (struct sport_device *)dai->private_data; |
@@ -289,7 +290,6 @@ static int bf5xx_i2s_resume(struct platform_device *pdev, | |||
289 | struct snd_soc_dai bf5xx_i2s_dai = { | 290 | struct snd_soc_dai bf5xx_i2s_dai = { |
290 | .name = "bf5xx-i2s", | 291 | .name = "bf5xx-i2s", |
291 | .id = 0, | 292 | .id = 0, |
292 | .type = SND_SOC_DAI_I2S, | ||
293 | .probe = bf5xx_i2s_probe, | 293 | .probe = bf5xx_i2s_probe, |
294 | .remove = bf5xx_i2s_remove, | 294 | .remove = bf5xx_i2s_remove, |
295 | .suspend = bf5xx_i2s_suspend, | 295 | .suspend = bf5xx_i2s_suspend, |
@@ -307,13 +307,24 @@ struct snd_soc_dai bf5xx_i2s_dai = { | |||
307 | .ops = { | 307 | .ops = { |
308 | .startup = bf5xx_i2s_startup, | 308 | .startup = bf5xx_i2s_startup, |
309 | .shutdown = bf5xx_i2s_shutdown, | 309 | .shutdown = bf5xx_i2s_shutdown, |
310 | .hw_params = bf5xx_i2s_hw_params,}, | 310 | .hw_params = bf5xx_i2s_hw_params, |
311 | .dai_ops = { | ||
312 | .set_fmt = bf5xx_i2s_set_dai_fmt, | 311 | .set_fmt = bf5xx_i2s_set_dai_fmt, |
313 | }, | 312 | }, |
314 | }; | 313 | }; |
315 | EXPORT_SYMBOL_GPL(bf5xx_i2s_dai); | 314 | EXPORT_SYMBOL_GPL(bf5xx_i2s_dai); |
316 | 315 | ||
316 | static int __init bfin_i2s_init(void) | ||
317 | { | ||
318 | return snd_soc_register_dai(&bf5xx_i2s_dai); | ||
319 | } | ||
320 | module_init(bfin_i2s_init); | ||
321 | |||
322 | static void __exit bfin_i2s_exit(void) | ||
323 | { | ||
324 | snd_soc_unregister_dai(&bf5xx_i2s_dai); | ||
325 | } | ||
326 | module_exit(bfin_i2s_exit); | ||
327 | |||
317 | /* Module information */ | 328 | /* Module information */ |
318 | MODULE_AUTHOR("Cliff Cai"); | 329 | MODULE_AUTHOR("Cliff Cai"); |
319 | MODULE_DESCRIPTION("I2S driver for ADI Blackfin"); | 330 | MODULE_DESCRIPTION("I2S driver for ADI Blackfin"); |
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*/ |
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c index e15f67fd7769..bc0cdded7116 100644 --- a/sound/soc/blackfin/bf5xx-ssm2602.c +++ b/sound/soc/blackfin/bf5xx-ssm2602.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include "bf5xx-i2s-pcm.h" | 44 | #include "bf5xx-i2s-pcm.h" |
45 | #include "bf5xx-i2s.h" | 45 | #include "bf5xx-i2s.h" |
46 | 46 | ||
47 | static struct snd_soc_machine bf5xx_ssm2602; | 47 | static struct snd_soc_card bf5xx_ssm2602; |
48 | 48 | ||
49 | static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) | 49 | static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) |
50 | { | 50 | { |
@@ -92,17 +92,17 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
92 | */ | 92 | */ |
93 | 93 | ||
94 | /* set codec DAI configuration */ | 94 | /* set codec DAI configuration */ |
95 | ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | 95 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | |
96 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | 96 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); |
97 | if (ret < 0) | 97 | if (ret < 0) |
98 | return ret; | 98 | return ret; |
99 | /* set cpu DAI configuration */ | 99 | /* set cpu DAI configuration */ |
100 | ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | 100 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | |
101 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | 101 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); |
102 | if (ret < 0) | 102 | if (ret < 0) |
103 | return ret; | 103 | return ret; |
104 | 104 | ||
105 | ret = codec_dai->dai_ops.set_sysclk(codec_dai, SSM2602_SYSCLK, clk, | 105 | ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk, |
106 | SND_SOC_CLOCK_IN); | 106 | SND_SOC_CLOCK_IN); |
107 | if (ret < 0) | 107 | if (ret < 0) |
108 | return ret; | 108 | return ret; |
@@ -135,15 +135,15 @@ static struct ssm2602_setup_data bf5xx_ssm2602_setup = { | |||
135 | .i2c_address = 0x1b, | 135 | .i2c_address = 0x1b, |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static struct snd_soc_machine bf5xx_ssm2602 = { | 138 | static struct snd_soc_card bf5xx_ssm2602 = { |
139 | .name = "bf5xx_ssm2602", | 139 | .name = "bf5xx_ssm2602", |
140 | .platform = &bf5xx_i2s_soc_platform, | ||
140 | .dai_link = &bf5xx_ssm2602_dai, | 141 | .dai_link = &bf5xx_ssm2602_dai, |
141 | .num_links = 1, | 142 | .num_links = 1, |
142 | }; | 143 | }; |
143 | 144 | ||
144 | static struct snd_soc_device bf5xx_ssm2602_snd_devdata = { | 145 | static struct snd_soc_device bf5xx_ssm2602_snd_devdata = { |
145 | .machine = &bf5xx_ssm2602, | 146 | .card = &bf5xx_ssm2602, |
146 | .platform = &bf5xx_i2s_soc_platform, | ||
147 | .codec_dev = &soc_codec_dev_ssm2602, | 147 | .codec_dev = &soc_codec_dev_ssm2602, |
148 | .codec_data = &bf5xx_ssm2602_setup, | 148 | .codec_data = &bf5xx_ssm2602_setup, |
149 | }; | 149 | }; |