diff options
-rw-r--r-- | sound/soc/omap/omap-mcbsp.c | 47 | ||||
-rw-r--r-- | sound/soc/omap/omap-pcm.c | 7 | ||||
-rw-r--r-- | sound/soc/omap/omap-pcm.h | 2 |
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] = { | |||
139 | static const unsigned long omap34xx_mcbsp_port[][2] = {}; | 139 | static const unsigned long omap34xx_mcbsp_port[][2] = {}; |
140 | #endif | 140 | #endif |
141 | 141 | ||
142 | static 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 | |||
142 | static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, | 156 | static 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 | ||
34 | extern struct snd_soc_platform omap_soc_platform; | 36 | extern struct snd_soc_platform omap_soc_platform; |