aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/blackfin
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/blackfin')
-rw-r--r--sound/soc/blackfin/Kconfig16
-rw-r--r--sound/soc/blackfin/Makefile3
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c42
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c1
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c240
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c47
-rw-r--r--sound/soc/blackfin/bf5xx-sport.h2
7 files changed, 328 insertions, 23 deletions
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index f98331d099e7..dc006206f622 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -17,6 +17,22 @@ config SND_BF5XX_SOC_SSM2602
17 help 17 help
18 Say Y if you want to add support for SoC audio on BF527-EZKIT. 18 Say Y if you want to add support for SoC audio on BF527-EZKIT.
19 19
20config SND_BF5XX_SOC_AD73311
21 tristate "SoC AD73311 Audio support for Blackfin"
22 depends on SND_BF5XX_I2S
23 select SND_BF5XX_SOC_I2S
24 select SND_SOC_AD73311
25 help
26 Say Y if you want to add support for AD73311 codec on Blackfin.
27
28config SND_BFIN_AD73311_SE
29 int "PF pin for AD73311L Chip Select"
30 depends on SND_BF5XX_SOC_AD73311
31 default 4
32 help
33 Enter the GPIO used to control AD73311's SE pin. Acceptable
34 values are 0 to 7
35
20config SND_BF5XX_AC97 36config SND_BF5XX_AC97
21 tristate "SoC AC97 Audio for the ADI BF5xx chip" 37 tristate "SoC AC97 Audio for the ADI BF5xx chip"
22 depends on BLACKFIN && SND_SOC 38 depends on BLACKFIN && SND_SOC
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
index 9ea8bd9e0ba3..97bb37a6359c 100644
--- a/sound/soc/blackfin/Makefile
+++ b/sound/soc/blackfin/Makefile
@@ -14,7 +14,8 @@ obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
14# Blackfin Machine Support 14# Blackfin Machine Support
15snd-ad1980-objs := bf5xx-ad1980.o 15snd-ad1980-objs := bf5xx-ad1980.o
16snd-ssm2602-objs := bf5xx-ssm2602.o 16snd-ssm2602-objs := bf5xx-ssm2602.o
17 17snd-ad73311-objs := bf5xx-ad73311.o
18 18
19obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o 19obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
20obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o 20obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
21obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 51f4907c4831..25e50d2ea1ec 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -56,6 +56,7 @@ static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
56 sport->tx_pos += runtime->period_size; 56 sport->tx_pos += runtime->period_size;
57 if (sport->tx_pos >= runtime->buffer_size) 57 if (sport->tx_pos >= runtime->buffer_size)
58 sport->tx_pos %= runtime->buffer_size; 58 sport->tx_pos %= runtime->buffer_size;
59 sport->tx_delay_pos = sport->tx_pos;
59 } else { 60 } else {
60 bf5xx_ac97_to_pcm( 61 bf5xx_ac97_to_pcm(
61 (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos, 62 (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos,
@@ -72,7 +73,15 @@ static void bf5xx_dma_irq(void *data)
72 struct snd_pcm_substream *pcm = data; 73 struct snd_pcm_substream *pcm = data;
73#if defined(CONFIG_SND_MMAP_SUPPORT) 74#if defined(CONFIG_SND_MMAP_SUPPORT)
74 struct snd_pcm_runtime *runtime = pcm->runtime; 75 struct snd_pcm_runtime *runtime = pcm->runtime;
76 struct sport_device *sport = runtime->private_data;
75 bf5xx_mmap_copy(pcm, runtime->period_size); 77 bf5xx_mmap_copy(pcm, runtime->period_size);
78 if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK) {
79 if (sport->once == 0) {
80 snd_pcm_period_elapsed(pcm);
81 bf5xx_mmap_copy(pcm, runtime->period_size);
82 sport->once = 1;
83 }
84 }
76#endif 85#endif
77 snd_pcm_period_elapsed(pcm); 86 snd_pcm_period_elapsed(pcm);
78} 87}
@@ -114,6 +123,10 @@ static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
114 123
115static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) 124static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
116{ 125{
126 struct snd_pcm_runtime *runtime = substream->runtime;
127
128 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
129 memset(runtime->dma_area, 0, runtime->buffer_size);
117 snd_pcm_lib_free_pages(substream); 130 snd_pcm_lib_free_pages(substream);
118 return 0; 131 return 0;
119} 132}
@@ -127,16 +140,11 @@ static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
127 * SPORT working in TMD mode(include AC97). 140 * SPORT working in TMD mode(include AC97).
128 */ 141 */
129#if defined(CONFIG_SND_MMAP_SUPPORT) 142#if defined(CONFIG_SND_MMAP_SUPPORT)
130 size_t size = bf5xx_pcm_hardware.buffer_bytes_max
131 * sizeof(struct ac97_frame) / 4;
132 /*clean up intermediate buffer*/
133 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 143 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
134 memset(sport->tx_dma_buf, 0, size);
135 sport_set_tx_callback(sport, bf5xx_dma_irq, substream); 144 sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
136 sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods, 145 sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods,
137 runtime->period_size * sizeof(struct ac97_frame)); 146 runtime->period_size * sizeof(struct ac97_frame));
138 } else { 147 } else {
139 memset(sport->rx_dma_buf, 0, size);
140 sport_set_rx_callback(sport, bf5xx_dma_irq, substream); 148 sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
141 sport_config_rx_dma(sport, sport->rx_dma_buf, runtime->periods, 149 sport_config_rx_dma(sport, sport->rx_dma_buf, runtime->periods,
142 runtime->period_size * sizeof(struct ac97_frame)); 150 runtime->period_size * sizeof(struct ac97_frame));
@@ -164,8 +172,12 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
164 pr_debug("%s enter\n", __func__); 172 pr_debug("%s enter\n", __func__);
165 switch (cmd) { 173 switch (cmd) {
166 case SNDRV_PCM_TRIGGER_START: 174 case SNDRV_PCM_TRIGGER_START:
167 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 175 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
176 bf5xx_mmap_copy(substream, runtime->period_size);
177 snd_pcm_period_elapsed(substream);
178 sport->tx_delay_pos = 0;
168 sport_tx_start(sport); 179 sport_tx_start(sport);
180 }
169 else 181 else
170 sport_rx_start(sport); 182 sport_rx_start(sport);
171 break; 183 break;
@@ -198,7 +210,7 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
198 210
199#if defined(CONFIG_SND_MMAP_SUPPORT) 211#if defined(CONFIG_SND_MMAP_SUPPORT)
200 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 212 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
201 curr = sport->tx_pos; 213 curr = sport->tx_delay_pos;
202 else 214 else
203 curr = sport->rx_pos; 215 curr = sport->rx_pos;
204#else 216#else
@@ -237,6 +249,21 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
237 return ret; 249 return ret;
238} 250}
239 251
252static int bf5xx_pcm_close(struct snd_pcm_substream *substream)
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
240#ifdef CONFIG_SND_MMAP_SUPPORT 267#ifdef CONFIG_SND_MMAP_SUPPORT
241static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, 268static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
242 struct vm_area_struct *vma) 269 struct vm_area_struct *vma)
@@ -272,6 +299,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
272 299
273struct snd_pcm_ops bf5xx_pcm_ac97_ops = { 300struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
274 .open = bf5xx_pcm_open, 301 .open = bf5xx_pcm_open,
302 .close = bf5xx_pcm_close,
275 .ioctl = snd_pcm_lib_ioctl, 303 .ioctl = snd_pcm_lib_ioctl,
276 .hw_params = bf5xx_pcm_hw_params, 304 .hw_params = bf5xx_pcm_hw_params,
277 .hw_free = bf5xx_pcm_hw_free, 305 .hw_free = bf5xx_pcm_hw_free,
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index c782e311fd56..5e5aafb6485f 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -129,7 +129,6 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
129 struct ac97_frame *nextwrite; 129 struct ac97_frame *nextwrite;
130 130
131 sport_incfrag(sport, &nextfrag, 1); 131 sport_incfrag(sport, &nextfrag, 1);
132 sport_incfrag(sport, &nextfrag, 1);
133 132
134 nextwrite = (struct ac97_frame *)(sport->tx_buf + \ 133 nextwrite = (struct ac97_frame *)(sport->tx_buf + \
135 nextfrag * sport->tx_fragsize); 134 nextfrag * sport->tx_fragsize);
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
new file mode 100644
index 000000000000..622c9b909532
--- /dev/null
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -0,0 +1,240 @@
1/*
2 * File: sound/soc/blackfin/bf5xx-ad73311.c
3 * Author: Cliff Cai <Cliff.Cai@analog.com>
4 *
5 * Created: Thur Sep 25 2008
6 * Description: Board driver for ad73311 sound chip
7 *
8 * Modified:
9 * Copyright 2008 Analog Devices Inc.
10 *
11 * Bugs: Enter bugs at http://blackfin.uclinux.org/
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see the file COPYING, or write
25 * to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29#include <linux/module.h>
30#include <linux/moduleparam.h>
31#include <linux/device.h>
32#include <linux/delay.h>
33#include <linux/gpio.h>
34
35#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/soc.h>
38#include <sound/soc-dapm.h>
39#include <sound/pcm_params.h>
40
41#include <asm/blackfin.h>
42#include <asm/cacheflush.h>
43#include <asm/irq.h>
44#include <asm/dma.h>
45#include <asm/portmux.h>
46
47#include "../codecs/ad73311.h"
48#include "bf5xx-sport.h"
49#include "bf5xx-i2s-pcm.h"
50#include "bf5xx-i2s.h"
51
52#if CONFIG_SND_BF5XX_SPORT_NUM == 0
53#define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1
54#define bfin_read_SPORT_TCR1 bfin_read_SPORT0_TCR1
55#define bfin_write_SPORT_TCR2 bfin_write_SPORT0_TCR2
56#define bfin_write_SPORT_TX16 bfin_write_SPORT0_TX16
57#define bfin_read_SPORT_STAT bfin_read_SPORT0_STAT
58#else
59#define bfin_write_SPORT_TCR1 bfin_write_SPORT1_TCR1
60#define bfin_read_SPORT_TCR1 bfin_read_SPORT1_TCR1
61#define bfin_write_SPORT_TCR2 bfin_write_SPORT1_TCR2
62#define bfin_write_SPORT_TX16 bfin_write_SPORT1_TX16
63#define bfin_read_SPORT_STAT bfin_read_SPORT1_STAT
64#endif
65
66#define GPIO_SE CONFIG_SND_BFIN_AD73311_SE
67
68static struct snd_soc_machine bf5xx_ad73311;
69
70static int snd_ad73311_startup(void)
71{
72 pr_debug("%s enter\n", __func__);
73
74 /* Pull up SE pin on AD73311L */
75 gpio_set_value(GPIO_SE, 1);
76 return 0;
77}
78
79static int snd_ad73311_configure(void)
80{
81 unsigned short ctrl_regs[6];
82 unsigned short status = 0;
83 int count = 0;
84
85 /* DMCLK = MCLK = 16.384 MHz
86 * SCLK = DMCLK/8 = 2.048 MHz
87 * Sample Rate = DMCLK/2048 = 8 KHz
88 */
89 ctrl_regs[0] = AD_CONTROL | AD_WRITE | CTRL_REG_B | REGB_MCDIV(0) | \
90 REGB_SCDIV(0) | REGB_DIRATE(0);
91 ctrl_regs[1] = AD_CONTROL | AD_WRITE | CTRL_REG_C | REGC_PUDEV | \
92 REGC_PUADC | REGC_PUDAC | REGC_PUREF | REGC_REFUSE ;
93 ctrl_regs[2] = AD_CONTROL | AD_WRITE | CTRL_REG_D | REGD_OGS(2) | \
94 REGD_IGS(2);
95 ctrl_regs[3] = AD_CONTROL | AD_WRITE | CTRL_REG_E | REGE_DA(0x1f);
96 ctrl_regs[4] = AD_CONTROL | AD_WRITE | CTRL_REG_F | REGF_SEEN ;
97 ctrl_regs[5] = AD_CONTROL | AD_WRITE | CTRL_REG_A | REGA_MODE_DATA;
98
99 local_irq_disable();
100 snd_ad73311_startup();
101 udelay(1);
102
103 bfin_write_SPORT_TCR1(TFSR);
104 bfin_write_SPORT_TCR2(0xF);
105 SSYNC();
106
107 /* SPORT Tx Register is a 8 x 16 FIFO, all the data can be put to
108 * FIFO before enable SPORT to transfer the data
109 */
110 for (count = 0; count < 6; count++)
111 bfin_write_SPORT_TX16(ctrl_regs[count]);
112 SSYNC();
113 bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() | TSPEN);
114 SSYNC();
115
116 /* When TUVF is set, the data is already send out */
117 while (!(status & TUVF) && count++ < 10000) {
118 udelay(1);
119 status = bfin_read_SPORT_STAT();
120 SSYNC();
121 }
122 bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() & ~TSPEN);
123 SSYNC();
124 local_irq_enable();
125
126 if (count == 10000) {
127 printk(KERN_ERR "ad73311: failed to configure codec\n");
128 return -1;
129 }
130 return 0;
131}
132
133static int bf5xx_probe(struct platform_device *pdev)
134{
135 int err;
136 if (gpio_request(GPIO_SE, "AD73311_SE")) {
137 printk(KERN_ERR "%s: Failed ro request GPIO_%d\n", __func__, GPIO_SE);
138 return -EBUSY;
139 }
140
141 gpio_direction_output(GPIO_SE, 0);
142
143 err = snd_ad73311_configure();
144 if (err < 0)
145 return -EFAULT;
146
147 return 0;
148}
149
150static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream)
151{
152 struct snd_soc_pcm_runtime *rtd = substream->private_data;
153 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
154
155 pr_debug("%s enter\n", __func__);
156 cpu_dai->private_data = sport_handle;
157 return 0;
158}
159
160static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
161 struct snd_pcm_hw_params *params)
162{
163 struct snd_soc_pcm_runtime *rtd = substream->private_data;
164 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
165 int ret = 0;
166
167 pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
168 params_format(params));
169
170 /* set cpu DAI configuration */
171 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
172 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
173 if (ret < 0)
174 return ret;
175
176 return 0;
177}
178
179
180static struct snd_soc_ops bf5xx_ad73311_ops = {
181 .startup = bf5xx_ad73311_startup,
182 .hw_params = bf5xx_ad73311_hw_params,
183};
184
185static struct snd_soc_dai_link bf5xx_ad73311_dai = {
186 .name = "ad73311",
187 .stream_name = "AD73311",
188 .cpu_dai = &bf5xx_i2s_dai,
189 .codec_dai = &ad73311_dai,
190 .ops = &bf5xx_ad73311_ops,
191};
192
193static struct snd_soc_machine bf5xx_ad73311 = {
194 .name = "bf5xx_ad73311",
195 .probe = bf5xx_probe,
196 .dai_link = &bf5xx_ad73311_dai,
197 .num_links = 1,
198};
199
200static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
201 .machine = &bf5xx_ad73311,
202 .platform = &bf5xx_i2s_soc_platform,
203 .codec_dev = &soc_codec_dev_ad73311,
204};
205
206static struct platform_device *bf52x_ad73311_snd_device;
207
208static int __init bf5xx_ad73311_init(void)
209{
210 int ret;
211
212 pr_debug("%s enter\n", __func__);
213 bf52x_ad73311_snd_device = platform_device_alloc("soc-audio", -1);
214 if (!bf52x_ad73311_snd_device)
215 return -ENOMEM;
216
217 platform_set_drvdata(bf52x_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
218 bf5xx_ad73311_snd_devdata.dev = &bf52x_ad73311_snd_device->dev;
219 ret = platform_device_add(bf52x_ad73311_snd_device);
220
221 if (ret)
222 platform_device_put(bf52x_ad73311_snd_device);
223
224 return ret;
225}
226
227static void __exit bf5xx_ad73311_exit(void)
228{
229 pr_debug("%s enter\n", __func__);
230 platform_device_unregister(bf52x_ad73311_snd_device);
231}
232
233module_init(bf5xx_ad73311_init);
234module_exit(bf5xx_ad73311_exit);
235
236/* Module information */
237MODULE_AUTHOR("Cliff Cai");
238MODULE_DESCRIPTION("ALSA SoC AD73311 Blackfin");
239MODULE_LICENSE("GPL");
240
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 43a4092eeb89..827587f08180 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -70,6 +70,13 @@ static struct sport_param sport_params[2] = {
70 } 70 }
71}; 71};
72 72
73static u16 sport_req[][7] = {
74 { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
75 P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0},
76 { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
77 P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0},
78};
79
73static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, 80static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
74 unsigned int fmt) 81 unsigned int fmt)
75{ 82{
@@ -78,6 +85,14 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
78 /* interface format:support I2S,slave mode */ 85 /* interface format:support I2S,slave mode */
79 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 86 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
80 case SND_SOC_DAIFMT_I2S: 87 case SND_SOC_DAIFMT_I2S:
88 bf5xx_i2s.tcr1 |= TFSR | TCKFE;
89 bf5xx_i2s.rcr1 |= RFSR | RCKFE;
90 bf5xx_i2s.tcr2 |= TSFSE;
91 bf5xx_i2s.rcr2 |= RSFSE;
92 break;
93 case SND_SOC_DAIFMT_DSP_A:
94 bf5xx_i2s.tcr1 |= TFSR;
95 bf5xx_i2s.rcr1 |= RFSR;
81 break; 96 break;
82 case SND_SOC_DAIFMT_LEFT_J: 97 case SND_SOC_DAIFMT_LEFT_J:
83 ret = -EINVAL; 98 ret = -EINVAL;
@@ -127,14 +142,17 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
127 case SNDRV_PCM_FORMAT_S16_LE: 142 case SNDRV_PCM_FORMAT_S16_LE:
128 bf5xx_i2s.tcr2 |= 15; 143 bf5xx_i2s.tcr2 |= 15;
129 bf5xx_i2s.rcr2 |= 15; 144 bf5xx_i2s.rcr2 |= 15;
145 sport_handle->wdsize = 2;
130 break; 146 break;
131 case SNDRV_PCM_FORMAT_S24_LE: 147 case SNDRV_PCM_FORMAT_S24_LE:
132 bf5xx_i2s.tcr2 |= 23; 148 bf5xx_i2s.tcr2 |= 23;
133 bf5xx_i2s.rcr2 |= 23; 149 bf5xx_i2s.rcr2 |= 23;
150 sport_handle->wdsize = 3;
134 break; 151 break;
135 case SNDRV_PCM_FORMAT_S32_LE: 152 case SNDRV_PCM_FORMAT_S32_LE:
136 bf5xx_i2s.tcr2 |= 31; 153 bf5xx_i2s.tcr2 |= 31;
137 bf5xx_i2s.rcr2 |= 31; 154 bf5xx_i2s.rcr2 |= 31;
155 sport_handle->wdsize = 4;
138 break; 156 break;
139 } 157 }
140 158
@@ -145,17 +163,17 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
145 * need to configure both of them at the time when the first 163 * need to configure both of them at the time when the first
146 * stream is opened. 164 * stream is opened.
147 * 165 *
148 * CPU DAI format:I2S, slave mode. 166 * CPU DAI:slave mode.
149 */ 167 */
150 ret = sport_config_rx(sport_handle, RFSR | RCKFE, 168 ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
151 RSFSE|bf5xx_i2s.rcr2, 0, 0); 169 bf5xx_i2s.rcr2, 0, 0);
152 if (ret) { 170 if (ret) {
153 pr_err("SPORT is busy!\n"); 171 pr_err("SPORT is busy!\n");
154 return -EBUSY; 172 return -EBUSY;
155 } 173 }
156 174
157 ret = sport_config_tx(sport_handle, TFSR | TCKFE, 175 ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
158 TSFSE|bf5xx_i2s.tcr2, 0, 0); 176 bf5xx_i2s.tcr2, 0, 0);
159 if (ret) { 177 if (ret) {
160 pr_err("SPORT is busy!\n"); 178 pr_err("SPORT is busy!\n");
161 return -EBUSY; 179 return -EBUSY;
@@ -174,13 +192,6 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream)
174static int bf5xx_i2s_probe(struct platform_device *pdev, 192static int bf5xx_i2s_probe(struct platform_device *pdev,
175 struct snd_soc_dai *dai) 193 struct snd_soc_dai *dai)
176{ 194{
177 u16 sport_req[][7] = {
178 { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
179 P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0},
180 { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
181 P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0},
182 };
183
184 pr_debug("%s enter\n", __func__); 195 pr_debug("%s enter\n", __func__);
185 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { 196 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
186 pr_err("Requesting Peripherals failed\n"); 197 pr_err("Requesting Peripherals failed\n");
@@ -198,6 +209,13 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
198 return 0; 209 return 0;
199} 210}
200 211
212static void bf5xx_i2s_remove(struct platform_device *pdev,
213 struct snd_soc_dai *dai)
214{
215 pr_debug("%s enter\n", __func__);
216 peripheral_free_list(&sport_req[sport_num][0]);
217}
218
201#ifdef CONFIG_PM 219#ifdef CONFIG_PM
202static int bf5xx_i2s_suspend(struct platform_device *dev, 220static int bf5xx_i2s_suspend(struct platform_device *dev,
203 struct snd_soc_dai *dai) 221 struct snd_soc_dai *dai)
@@ -263,15 +281,16 @@ struct snd_soc_dai bf5xx_i2s_dai = {
263 .id = 0, 281 .id = 0,
264 .type = SND_SOC_DAI_I2S, 282 .type = SND_SOC_DAI_I2S,
265 .probe = bf5xx_i2s_probe, 283 .probe = bf5xx_i2s_probe,
284 .remove = bf5xx_i2s_remove,
266 .suspend = bf5xx_i2s_suspend, 285 .suspend = bf5xx_i2s_suspend,
267 .resume = bf5xx_i2s_resume, 286 .resume = bf5xx_i2s_resume,
268 .playback = { 287 .playback = {
269 .channels_min = 2, 288 .channels_min = 1,
270 .channels_max = 2, 289 .channels_max = 2,
271 .rates = BF5XX_I2S_RATES, 290 .rates = BF5XX_I2S_RATES,
272 .formats = BF5XX_I2S_FORMATS,}, 291 .formats = BF5XX_I2S_FORMATS,},
273 .capture = { 292 .capture = {
274 .channels_min = 2, 293 .channels_min = 1,
275 .channels_max = 2, 294 .channels_max = 2,
276 .rates = BF5XX_I2S_RATES, 295 .rates = BF5XX_I2S_RATES,
277 .formats = BF5XX_I2S_FORMATS,}, 296 .formats = BF5XX_I2S_FORMATS,},
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h
index 4c163454bbf8..fcadcc081f7f 100644
--- a/sound/soc/blackfin/bf5xx-sport.h
+++ b/sound/soc/blackfin/bf5xx-sport.h
@@ -123,6 +123,8 @@ struct sport_device {
123 int rx_pos; 123 int rx_pos;
124 unsigned int tx_buffer_size; 124 unsigned int tx_buffer_size;
125 unsigned int rx_buffer_size; 125 unsigned int rx_buffer_size;
126 int tx_delay_pos;
127 int once;
126#endif 128#endif
127 void *private_data; 129 void *private_data;
128}; 130};