aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/omap/omap-mcbsp.c47
-rw-r--r--sound/soc/omap/omap-pcm.c7
-rw-r--r--sound/soc/omap/omap-pcm.h2
3 files changed, 49 insertions, 7 deletions
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 6e855080e6ea..580de5a8dba6 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -139,28 +139,59 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {
139static const unsigned long omap34xx_mcbsp_port[][2] = {}; 139static const unsigned long omap34xx_mcbsp_port[][2] = {};
140#endif 140#endif
141 141
142static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
143{
144 struct snd_soc_pcm_runtime *rtd = substream->private_data;
145 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
146 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
147 int samples = snd_pcm_lib_period_bytes(substream) >> 1;
148
149 /* Configure McBSP internal buffer usage */
150 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
151 omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, samples - 1);
152 else
153 omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, samples - 1);
154}
155
142static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, 156static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
143 struct snd_soc_dai *dai) 157 struct snd_soc_dai *dai)
144{ 158{
145 struct snd_soc_pcm_runtime *rtd = substream->private_data; 159 struct snd_soc_pcm_runtime *rtd = substream->private_data;
146 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 160 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
147 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 161 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
162 int bus_id = mcbsp_data->bus_id;
148 int err = 0; 163 int err = 0;
149 164
150 if (cpu_is_omap343x() && mcbsp_data->bus_id == 1) { 165 if (!cpu_dai->active)
166 err = omap_mcbsp_request(bus_id);
167
168 if (cpu_is_omap343x()) {
169 int max_period;
170
151 /* 171 /*
152 * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer. 172 * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer.
153 * Set constraint for minimum buffer size to the same than FIFO 173 * Set constraint for minimum buffer size to the same than FIFO
154 * size in order to avoid underruns in playback startup because 174 * size in order to avoid underruns in playback startup because
155 * HW is keeping the DMA request active until FIFO is filled. 175 * HW is keeping the DMA request active until FIFO is filled.
156 */ 176 */
177 if (bus_id == 1)
178 snd_pcm_hw_constraint_minmax(substream->runtime,
179 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
180 4096, UINT_MAX);
181
182 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
183 max_period = omap_mcbsp_get_max_tx_threshold(bus_id);
184 else
185 max_period = omap_mcbsp_get_max_rx_threshold(bus_id);
186
187 max_period++;
188 max_period <<= 1;
189
157 snd_pcm_hw_constraint_minmax(substream->runtime, 190 snd_pcm_hw_constraint_minmax(substream->runtime,
158 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4096, UINT_MAX); 191 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
192 32, max_period);
159 } 193 }
160 194
161 if (!cpu_dai->active)
162 err = omap_mcbsp_request(mcbsp_data->bus_id);
163
164 return err; 195 return err;
165} 196}
166 197
@@ -220,7 +251,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
220 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 251 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
221 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 252 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
222 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; 253 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
223 int wlen, channels, wpf; 254 int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
224 unsigned long port; 255 unsigned long port;
225 unsigned int format; 256 unsigned int format;
226 257
@@ -236,6 +267,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
236 } else if (cpu_is_omap343x()) { 267 } else if (cpu_is_omap343x()) {
237 dma = omap24xx_dma_reqs[bus_id][substream->stream]; 268 dma = omap24xx_dma_reqs[bus_id][substream->stream];
238 port = omap34xx_mcbsp_port[bus_id][substream->stream]; 269 port = omap34xx_mcbsp_port[bus_id][substream->stream];
270 omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold =
271 omap_mcbsp_set_threshold;
272 sync_mode = OMAP_DMA_SYNC_FRAME;
239 } else { 273 } else {
240 return -ENODEV; 274 return -ENODEV;
241 } 275 }
@@ -243,6 +277,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
243 substream->stream ? "Audio Capture" : "Audio Playback"; 277 substream->stream ? "Audio Capture" : "Audio Playback";
244 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; 278 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
245 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; 279 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
280 omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
246 cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; 281 cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
247 282
248 if (mcbsp_data->configured) { 283 if (mcbsp_data->configured) {
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index b9633d5a9557..5735945788bf 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -162,7 +162,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
162 */ 162 */
163 dma_params.data_type = OMAP_DMA_DATA_TYPE_S16; 163 dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
164 dma_params.trigger = dma_data->dma_req; 164 dma_params.trigger = dma_data->dma_req;
165 dma_params.sync_mode = OMAP_DMA_SYNC_ELEMENT; 165 dma_params.sync_mode = dma_data->sync_mode;
166 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 166 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
167 dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; 167 dma_params.src_amode = OMAP_DMA_AMODE_POST_INC;
168 dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT; 168 dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT;
@@ -205,6 +205,7 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
205{ 205{
206 struct snd_pcm_runtime *runtime = substream->runtime; 206 struct snd_pcm_runtime *runtime = substream->runtime;
207 struct omap_runtime_data *prtd = runtime->private_data; 207 struct omap_runtime_data *prtd = runtime->private_data;
208 struct omap_pcm_dma_data *dma_data = prtd->dma_data;
208 unsigned long flags; 209 unsigned long flags;
209 int ret = 0; 210 int ret = 0;
210 211
@@ -214,6 +215,10 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
214 case SNDRV_PCM_TRIGGER_RESUME: 215 case SNDRV_PCM_TRIGGER_RESUME:
215 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 216 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
216 prtd->period_index = 0; 217 prtd->period_index = 0;
218 /* Configure McBSP internal buffer usage */
219 if (dma_data->set_threshold)
220 dma_data->set_threshold(substream);
221
217 omap_start_dma(prtd->dma_ch); 222 omap_start_dma(prtd->dma_ch);
218 break; 223 break;
219 224
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
index 8d9d26916b05..38a821dd4118 100644
--- a/sound/soc/omap/omap-pcm.h
+++ b/sound/soc/omap/omap-pcm.h
@@ -29,6 +29,8 @@ struct omap_pcm_dma_data {
29 char *name; /* stream identifier */ 29 char *name; /* stream identifier */
30 int dma_req; /* DMA request line */ 30 int dma_req; /* DMA request line */
31 unsigned long port_addr; /* transmit/receive register */ 31 unsigned long port_addr; /* transmit/receive register */
32 int sync_mode; /* DMA sync mode */
33 void (*set_threshold)(struct snd_pcm_substream *substream);
32}; 34};
33 35
34extern struct snd_soc_platform omap_soc_platform; 36extern struct snd_soc_platform omap_soc_platform;