diff options
Diffstat (limited to 'sound/aoa/soundbus/i2sbus/i2sbus-pcm.c')
-rw-r--r-- | sound/aoa/soundbus/i2sbus/i2sbus-pcm.c | 1021 |
1 files changed, 1021 insertions, 0 deletions
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c new file mode 100644 index 000000000000..3049015a04f1 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c | |||
@@ -0,0 +1,1021 @@ | |||
1 | /* | ||
2 | * i2sbus driver -- pcm routines | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | |||
9 | #include <asm/io.h> | ||
10 | #include <linux/delay.h> | ||
11 | /* So apparently there's a reason for requiring driver.h | ||
12 | * to be included first, even if I don't know it... */ | ||
13 | #include <sound/driver.h> | ||
14 | #include <sound/core.h> | ||
15 | #include <asm/macio.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include "../soundbus.h" | ||
18 | #include "i2sbus.h" | ||
19 | |||
20 | static inline void get_pcm_info(struct i2sbus_dev *i2sdev, int in, | ||
21 | struct pcm_info **pi, struct pcm_info **other) | ||
22 | { | ||
23 | if (in) { | ||
24 | if (pi) | ||
25 | *pi = &i2sdev->in; | ||
26 | if (other) | ||
27 | *other = &i2sdev->out; | ||
28 | } else { | ||
29 | if (pi) | ||
30 | *pi = &i2sdev->out; | ||
31 | if (other) | ||
32 | *other = &i2sdev->in; | ||
33 | } | ||
34 | } | ||
35 | |||
36 | static int clock_and_divisors(int mclk, int sclk, int rate, int *out) | ||
37 | { | ||
38 | /* sclk must be derived from mclk! */ | ||
39 | if (mclk % sclk) | ||
40 | return -1; | ||
41 | /* derive sclk register value */ | ||
42 | if (i2s_sf_sclkdiv(mclk / sclk, out)) | ||
43 | return -1; | ||
44 | |||
45 | if (I2S_CLOCK_SPEED_18MHz % (rate * mclk) == 0) { | ||
46 | if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_18MHz / (rate * mclk), out)) { | ||
47 | *out |= I2S_SF_CLOCK_SOURCE_18MHz; | ||
48 | return 0; | ||
49 | } | ||
50 | } | ||
51 | if (I2S_CLOCK_SPEED_45MHz % (rate * mclk) == 0) { | ||
52 | if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_45MHz / (rate * mclk), out)) { | ||
53 | *out |= I2S_SF_CLOCK_SOURCE_45MHz; | ||
54 | return 0; | ||
55 | } | ||
56 | } | ||
57 | if (I2S_CLOCK_SPEED_49MHz % (rate * mclk) == 0) { | ||
58 | if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_49MHz / (rate * mclk), out)) { | ||
59 | *out |= I2S_SF_CLOCK_SOURCE_49MHz; | ||
60 | return 0; | ||
61 | } | ||
62 | } | ||
63 | return -1; | ||
64 | } | ||
65 | |||
66 | #define CHECK_RATE(rate) \ | ||
67 | do { if (rates & SNDRV_PCM_RATE_ ##rate) { \ | ||
68 | int dummy; \ | ||
69 | if (clock_and_divisors(sysclock_factor, \ | ||
70 | bus_factor, rate, &dummy)) \ | ||
71 | rates &= ~SNDRV_PCM_RATE_ ##rate; \ | ||
72 | } } while (0) | ||
73 | |||
74 | static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) | ||
75 | { | ||
76 | struct pcm_info *pi, *other; | ||
77 | struct soundbus_dev *sdev; | ||
78 | int masks_inited = 0, err; | ||
79 | struct codec_info_item *cii, *rev; | ||
80 | struct snd_pcm_hardware *hw; | ||
81 | u64 formats = 0; | ||
82 | unsigned int rates = 0; | ||
83 | struct transfer_info v; | ||
84 | int result = 0; | ||
85 | int bus_factor = 0, sysclock_factor = 0; | ||
86 | int found_this; | ||
87 | |||
88 | mutex_lock(&i2sdev->lock); | ||
89 | |||
90 | get_pcm_info(i2sdev, in, &pi, &other); | ||
91 | |||
92 | hw = &pi->substream->runtime->hw; | ||
93 | sdev = &i2sdev->sound; | ||
94 | |||
95 | if (pi->active) { | ||
96 | /* alsa messed up */ | ||
97 | result = -EBUSY; | ||
98 | goto out_unlock; | ||
99 | } | ||
100 | |||
101 | /* we now need to assign the hw */ | ||
102 | list_for_each_entry(cii, &sdev->codec_list, list) { | ||
103 | struct transfer_info *ti = cii->codec->transfers; | ||
104 | bus_factor = cii->codec->bus_factor; | ||
105 | sysclock_factor = cii->codec->sysclock_factor; | ||
106 | while (ti->formats && ti->rates) { | ||
107 | v = *ti; | ||
108 | if (ti->transfer_in == in | ||
109 | && cii->codec->usable(cii, ti, &v)) { | ||
110 | if (masks_inited) { | ||
111 | formats &= v.formats; | ||
112 | rates &= v.rates; | ||
113 | } else { | ||
114 | formats = v.formats; | ||
115 | rates = v.rates; | ||
116 | masks_inited = 1; | ||
117 | } | ||
118 | } | ||
119 | ti++; | ||
120 | } | ||
121 | } | ||
122 | if (!masks_inited || !bus_factor || !sysclock_factor) { | ||
123 | result = -ENODEV; | ||
124 | goto out_unlock; | ||
125 | } | ||
126 | /* bus dependent stuff */ | ||
127 | hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | ||
128 | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME; | ||
129 | |||
130 | CHECK_RATE(5512); | ||
131 | CHECK_RATE(8000); | ||
132 | CHECK_RATE(11025); | ||
133 | CHECK_RATE(16000); | ||
134 | CHECK_RATE(22050); | ||
135 | CHECK_RATE(32000); | ||
136 | CHECK_RATE(44100); | ||
137 | CHECK_RATE(48000); | ||
138 | CHECK_RATE(64000); | ||
139 | CHECK_RATE(88200); | ||
140 | CHECK_RATE(96000); | ||
141 | CHECK_RATE(176400); | ||
142 | CHECK_RATE(192000); | ||
143 | hw->rates = rates; | ||
144 | |||
145 | /* well. the codec might want 24 bits only, and we'll | ||
146 | * ever only transfer 24 bits, but they are top-aligned! | ||
147 | * So for alsa, we claim that we're doing full 32 bit | ||
148 | * while in reality we'll ignore the lower 8 bits of | ||
149 | * that when doing playback (they're transferred as 0 | ||
150 | * as far as I know, no codecs we have are 32-bit capable | ||
151 | * so I can't really test) and when doing recording we'll | ||
152 | * always have those lower 8 bits recorded as 0 */ | ||
153 | if (formats & SNDRV_PCM_FMTBIT_S24_BE) | ||
154 | formats |= SNDRV_PCM_FMTBIT_S32_BE; | ||
155 | if (formats & SNDRV_PCM_FMTBIT_U24_BE) | ||
156 | formats |= SNDRV_PCM_FMTBIT_U32_BE; | ||
157 | /* now mask off what we can support. I suppose we could | ||
158 | * also support S24_3LE and some similar formats, but I | ||
159 | * doubt there's a codec that would be able to use that, | ||
160 | * so we don't support it here. */ | ||
161 | hw->formats = formats & (SNDRV_PCM_FMTBIT_S16_BE | | ||
162 | SNDRV_PCM_FMTBIT_U16_BE | | ||
163 | SNDRV_PCM_FMTBIT_S32_BE | | ||
164 | SNDRV_PCM_FMTBIT_U32_BE); | ||
165 | |||
166 | /* we need to set the highest and lowest rate possible. | ||
167 | * These are the highest and lowest rates alsa can | ||
168 | * support properly in its bitfield. | ||
169 | * Below, we'll use that to restrict to the rate | ||
170 | * currently in use (if any). */ | ||
171 | hw->rate_min = 5512; | ||
172 | hw->rate_max = 192000; | ||
173 | /* if the other stream is active, then we can only | ||
174 | * support what it is currently using. | ||
175 | * FIXME: I lied. This comment is wrong. We can support | ||
176 | * anything that works with the same serial format, ie. | ||
177 | * when recording 24 bit sound we can well play 16 bit | ||
178 | * sound at the same time iff using the same transfer mode. | ||
179 | */ | ||
180 | if (other->active) { | ||
181 | /* FIXME: is this guaranteed by the alsa api? */ | ||
182 | hw->formats &= (1ULL << i2sdev->format); | ||
183 | /* see above, restrict rates to the one we already have */ | ||
184 | hw->rate_min = i2sdev->rate; | ||
185 | hw->rate_max = i2sdev->rate; | ||
186 | } | ||
187 | |||
188 | hw->channels_min = 2; | ||
189 | hw->channels_max = 2; | ||
190 | /* these are somewhat arbitrary */ | ||
191 | hw->buffer_bytes_max = 131072; | ||
192 | hw->period_bytes_min = 256; | ||
193 | hw->period_bytes_max = 16384; | ||
194 | hw->periods_min = 3; | ||
195 | hw->periods_max = MAX_DBDMA_COMMANDS; | ||
196 | list_for_each_entry(cii, &sdev->codec_list, list) { | ||
197 | if (cii->codec->open) { | ||
198 | err = cii->codec->open(cii, pi->substream); | ||
199 | if (err) { | ||
200 | result = err; | ||
201 | /* unwind */ | ||
202 | found_this = 0; | ||
203 | list_for_each_entry_reverse(rev, | ||
204 | &sdev->codec_list, list) { | ||
205 | if (found_this && rev->codec->close) { | ||
206 | rev->codec->close(rev, | ||
207 | pi->substream); | ||
208 | } | ||
209 | if (rev == cii) | ||
210 | found_this = 1; | ||
211 | } | ||
212 | goto out_unlock; | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | |||
217 | out_unlock: | ||
218 | mutex_unlock(&i2sdev->lock); | ||
219 | return result; | ||
220 | } | ||
221 | |||
222 | #undef CHECK_RATE | ||
223 | |||
224 | static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in) | ||
225 | { | ||
226 | struct codec_info_item *cii; | ||
227 | struct pcm_info *pi; | ||
228 | int err = 0, tmp; | ||
229 | |||
230 | mutex_lock(&i2sdev->lock); | ||
231 | |||
232 | get_pcm_info(i2sdev, in, &pi, NULL); | ||
233 | |||
234 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { | ||
235 | if (cii->codec->close) { | ||
236 | tmp = cii->codec->close(cii, pi->substream); | ||
237 | if (tmp) | ||
238 | err = tmp; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | pi->substream = NULL; | ||
243 | pi->active = 0; | ||
244 | mutex_unlock(&i2sdev->lock); | ||
245 | return err; | ||
246 | } | ||
247 | |||
248 | static int i2sbus_hw_params(struct snd_pcm_substream *substream, | ||
249 | struct snd_pcm_hw_params *params) | ||
250 | { | ||
251 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
252 | } | ||
253 | |||
254 | static int i2sbus_hw_free(struct snd_pcm_substream *substream) | ||
255 | { | ||
256 | snd_pcm_lib_free_pages(substream); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) | ||
261 | { | ||
262 | /* whee. Hard work now. The user has selected a bitrate | ||
263 | * and bit format, so now we have to program our | ||
264 | * I2S controller appropriately. */ | ||
265 | struct snd_pcm_runtime *runtime; | ||
266 | struct dbdma_cmd *command; | ||
267 | int i, periodsize; | ||
268 | dma_addr_t offset; | ||
269 | struct bus_info bi; | ||
270 | struct codec_info_item *cii; | ||
271 | int sfr = 0; /* serial format register */ | ||
272 | int dws = 0; /* data word sizes reg */ | ||
273 | int input_16bit; | ||
274 | struct pcm_info *pi, *other; | ||
275 | int cnt; | ||
276 | int result = 0; | ||
277 | |||
278 | mutex_lock(&i2sdev->lock); | ||
279 | |||
280 | get_pcm_info(i2sdev, in, &pi, &other); | ||
281 | |||
282 | if (pi->dbdma_ring.running) { | ||
283 | result = -EBUSY; | ||
284 | goto out_unlock; | ||
285 | } | ||
286 | |||
287 | runtime = pi->substream->runtime; | ||
288 | pi->active = 1; | ||
289 | if (other->active && | ||
290 | ((i2sdev->format != runtime->format) | ||
291 | || (i2sdev->rate != runtime->rate))) { | ||
292 | result = -EINVAL; | ||
293 | goto out_unlock; | ||
294 | } | ||
295 | |||
296 | i2sdev->format = runtime->format; | ||
297 | i2sdev->rate = runtime->rate; | ||
298 | |||
299 | periodsize = snd_pcm_lib_period_bytes(pi->substream); | ||
300 | pi->current_period = 0; | ||
301 | |||
302 | /* generate dbdma command ring first */ | ||
303 | command = pi->dbdma_ring.cmds; | ||
304 | offset = runtime->dma_addr; | ||
305 | for (i = 0; i < pi->substream->runtime->periods; | ||
306 | i++, command++, offset += periodsize) { | ||
307 | memset(command, 0, sizeof(struct dbdma_cmd)); | ||
308 | command->command = | ||
309 | cpu_to_le16((in ? INPUT_MORE : OUTPUT_MORE) | INTR_ALWAYS); | ||
310 | command->phy_addr = cpu_to_le32(offset); | ||
311 | command->req_count = cpu_to_le16(periodsize); | ||
312 | command->xfer_status = cpu_to_le16(0); | ||
313 | } | ||
314 | /* last one branches back to first */ | ||
315 | command--; | ||
316 | command->command |= cpu_to_le16(BR_ALWAYS); | ||
317 | command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start); | ||
318 | |||
319 | /* ok, let's set the serial format and stuff */ | ||
320 | switch (runtime->format) { | ||
321 | /* 16 bit formats */ | ||
322 | case SNDRV_PCM_FORMAT_S16_BE: | ||
323 | case SNDRV_PCM_FORMAT_U16_BE: | ||
324 | /* FIXME: if we add different bus factors we need to | ||
325 | * do more here!! */ | ||
326 | bi.bus_factor = 0; | ||
327 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { | ||
328 | bi.bus_factor = cii->codec->bus_factor; | ||
329 | break; | ||
330 | } | ||
331 | if (!bi.bus_factor) { | ||
332 | result = -ENODEV; | ||
333 | goto out_unlock; | ||
334 | } | ||
335 | input_16bit = 1; | ||
336 | break; | ||
337 | case SNDRV_PCM_FORMAT_S32_BE: | ||
338 | case SNDRV_PCM_FORMAT_U32_BE: | ||
339 | /* force 64x bus speed, otherwise the data cannot be | ||
340 | * transferred quickly enough! */ | ||
341 | bi.bus_factor = 64; | ||
342 | input_16bit = 0; | ||
343 | break; | ||
344 | default: | ||
345 | result = -EINVAL; | ||
346 | goto out_unlock; | ||
347 | } | ||
348 | /* we assume all sysclocks are the same! */ | ||
349 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { | ||
350 | bi.sysclock_factor = cii->codec->sysclock_factor; | ||
351 | break; | ||
352 | } | ||
353 | |||
354 | if (clock_and_divisors(bi.sysclock_factor, | ||
355 | bi.bus_factor, | ||
356 | runtime->rate, | ||
357 | &sfr) < 0) { | ||
358 | result = -EINVAL; | ||
359 | goto out_unlock; | ||
360 | } | ||
361 | switch (bi.bus_factor) { | ||
362 | case 32: | ||
363 | sfr |= I2S_SF_SERIAL_FORMAT_I2S_32X; | ||
364 | break; | ||
365 | case 64: | ||
366 | sfr |= I2S_SF_SERIAL_FORMAT_I2S_64X; | ||
367 | break; | ||
368 | } | ||
369 | /* FIXME: THIS ASSUMES MASTER ALL THE TIME */ | ||
370 | sfr |= I2S_SF_SCLK_MASTER; | ||
371 | |||
372 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { | ||
373 | int err = 0; | ||
374 | if (cii->codec->prepare) | ||
375 | err = cii->codec->prepare(cii, &bi, pi->substream); | ||
376 | if (err) { | ||
377 | result = err; | ||
378 | goto out_unlock; | ||
379 | } | ||
380 | } | ||
381 | /* codecs are fine with it, so set our clocks */ | ||
382 | if (input_16bit) | ||
383 | dws = (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) | | ||
384 | (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) | | ||
385 | I2S_DWS_DATA_IN_16BIT | I2S_DWS_DATA_OUT_16BIT; | ||
386 | else | ||
387 | dws = (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) | | ||
388 | (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) | | ||
389 | I2S_DWS_DATA_IN_24BIT | I2S_DWS_DATA_OUT_24BIT; | ||
390 | |||
391 | /* early exit if already programmed correctly */ | ||
392 | /* not locking these is fine since we touch them only in this function */ | ||
393 | if (in_le32(&i2sdev->intfregs->serial_format) == sfr | ||
394 | && in_le32(&i2sdev->intfregs->data_word_sizes) == dws) | ||
395 | goto out_unlock; | ||
396 | |||
397 | /* let's notify the codecs about clocks going away. | ||
398 | * For now we only do mastering on the i2s cell... */ | ||
399 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) | ||
400 | if (cii->codec->switch_clock) | ||
401 | cii->codec->switch_clock(cii, CLOCK_SWITCH_PREPARE_SLAVE); | ||
402 | |||
403 | i2sbus_control_enable(i2sdev->control, i2sdev); | ||
404 | i2sbus_control_cell(i2sdev->control, i2sdev, 1); | ||
405 | |||
406 | out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED); | ||
407 | |||
408 | i2sbus_control_clock(i2sdev->control, i2sdev, 0); | ||
409 | |||
410 | msleep(1); | ||
411 | |||
412 | /* wait for clock stopped. This can apparently take a while... */ | ||
413 | cnt = 100; | ||
414 | while (cnt-- && | ||
415 | !(in_le32(&i2sdev->intfregs->intr_ctl) & I2S_PENDING_CLOCKS_STOPPED)) { | ||
416 | msleep(5); | ||
417 | } | ||
418 | out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED); | ||
419 | |||
420 | /* not locking these is fine since we touch them only in this function */ | ||
421 | out_le32(&i2sdev->intfregs->serial_format, sfr); | ||
422 | out_le32(&i2sdev->intfregs->data_word_sizes, dws); | ||
423 | |||
424 | i2sbus_control_enable(i2sdev->control, i2sdev); | ||
425 | i2sbus_control_cell(i2sdev->control, i2sdev, 1); | ||
426 | i2sbus_control_clock(i2sdev->control, i2sdev, 1); | ||
427 | msleep(1); | ||
428 | |||
429 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) | ||
430 | if (cii->codec->switch_clock) | ||
431 | cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE); | ||
432 | |||
433 | out_unlock: | ||
434 | mutex_unlock(&i2sdev->lock); | ||
435 | return result; | ||
436 | } | ||
437 | |||
438 | static struct dbdma_cmd STOP_CMD = { | ||
439 | .command = __constant_cpu_to_le16(DBDMA_STOP), | ||
440 | }; | ||
441 | |||
442 | static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd) | ||
443 | { | ||
444 | struct codec_info_item *cii; | ||
445 | struct pcm_info *pi; | ||
446 | int timeout; | ||
447 | struct dbdma_cmd tmp; | ||
448 | int result = 0; | ||
449 | unsigned long flags; | ||
450 | |||
451 | spin_lock_irqsave(&i2sdev->low_lock, flags); | ||
452 | |||
453 | get_pcm_info(i2sdev, in, &pi, NULL); | ||
454 | |||
455 | switch (cmd) { | ||
456 | case SNDRV_PCM_TRIGGER_START: | ||
457 | case SNDRV_PCM_TRIGGER_RESUME: | ||
458 | if (pi->dbdma_ring.running) { | ||
459 | result = -EALREADY; | ||
460 | goto out_unlock; | ||
461 | } | ||
462 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) | ||
463 | if (cii->codec->start) | ||
464 | cii->codec->start(cii, pi->substream); | ||
465 | pi->dbdma_ring.running = 1; | ||
466 | |||
467 | /* reset dma engine */ | ||
468 | out_le32(&pi->dbdma->control, | ||
469 | 0 | (RUN | PAUSE | FLUSH | WAKE) << 16); | ||
470 | timeout = 100; | ||
471 | while (in_le32(&pi->dbdma->status) & RUN && timeout--) | ||
472 | udelay(1); | ||
473 | if (timeout <= 0) { | ||
474 | printk(KERN_ERR | ||
475 | "i2sbus: error waiting for dma reset\n"); | ||
476 | result = -ENXIO; | ||
477 | goto out_unlock; | ||
478 | } | ||
479 | |||
480 | /* write dma command buffer address to the dbdma chip */ | ||
481 | out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start); | ||
482 | /* post PCI write */ | ||
483 | mb(); | ||
484 | (void)in_le32(&pi->dbdma->status); | ||
485 | |||
486 | /* change first command to STOP */ | ||
487 | tmp = *pi->dbdma_ring.cmds; | ||
488 | *pi->dbdma_ring.cmds = STOP_CMD; | ||
489 | |||
490 | /* set running state, remember that the first command is STOP */ | ||
491 | out_le32(&pi->dbdma->control, RUN | (RUN << 16)); | ||
492 | timeout = 100; | ||
493 | /* wait for STOP to be executed */ | ||
494 | while (in_le32(&pi->dbdma->status) & ACTIVE && timeout--) | ||
495 | udelay(1); | ||
496 | if (timeout <= 0) { | ||
497 | printk(KERN_ERR "i2sbus: error waiting for dma stop\n"); | ||
498 | result = -ENXIO; | ||
499 | goto out_unlock; | ||
500 | } | ||
501 | /* again, write dma command buffer address to the dbdma chip, | ||
502 | * this time of the first real command */ | ||
503 | *pi->dbdma_ring.cmds = tmp; | ||
504 | out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start); | ||
505 | /* post write */ | ||
506 | mb(); | ||
507 | (void)in_le32(&pi->dbdma->status); | ||
508 | |||
509 | /* reset dma engine again */ | ||
510 | out_le32(&pi->dbdma->control, | ||
511 | 0 | (RUN | PAUSE | FLUSH | WAKE) << 16); | ||
512 | timeout = 100; | ||
513 | while (in_le32(&pi->dbdma->status) & RUN && timeout--) | ||
514 | udelay(1); | ||
515 | if (timeout <= 0) { | ||
516 | printk(KERN_ERR | ||
517 | "i2sbus: error waiting for dma reset\n"); | ||
518 | result = -ENXIO; | ||
519 | goto out_unlock; | ||
520 | } | ||
521 | |||
522 | /* wake up the chip with the next descriptor */ | ||
523 | out_le32(&pi->dbdma->control, | ||
524 | (RUN | WAKE) | ((RUN | WAKE) << 16)); | ||
525 | /* get the frame count */ | ||
526 | pi->frame_count = in_le32(&i2sdev->intfregs->frame_count); | ||
527 | |||
528 | /* off you go! */ | ||
529 | break; | ||
530 | case SNDRV_PCM_TRIGGER_STOP: | ||
531 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
532 | if (!pi->dbdma_ring.running) { | ||
533 | result = -EALREADY; | ||
534 | goto out_unlock; | ||
535 | } | ||
536 | |||
537 | /* turn off all relevant bits */ | ||
538 | out_le32(&pi->dbdma->control, | ||
539 | (RUN | WAKE | FLUSH | PAUSE) << 16); | ||
540 | { | ||
541 | /* FIXME: move to own function */ | ||
542 | int timeout = 5000; | ||
543 | while ((in_le32(&pi->dbdma->status) & RUN) | ||
544 | && --timeout > 0) | ||
545 | udelay(1); | ||
546 | if (!timeout) | ||
547 | printk(KERN_ERR | ||
548 | "i2sbus: timed out turning " | ||
549 | "off dbdma engine!\n"); | ||
550 | } | ||
551 | |||
552 | pi->dbdma_ring.running = 0; | ||
553 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) | ||
554 | if (cii->codec->stop) | ||
555 | cii->codec->stop(cii, pi->substream); | ||
556 | break; | ||
557 | default: | ||
558 | result = -EINVAL; | ||
559 | goto out_unlock; | ||
560 | } | ||
561 | |||
562 | out_unlock: | ||
563 | spin_unlock_irqrestore(&i2sdev->low_lock, flags); | ||
564 | return result; | ||
565 | } | ||
566 | |||
567 | static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in) | ||
568 | { | ||
569 | struct pcm_info *pi; | ||
570 | u32 fc; | ||
571 | |||
572 | get_pcm_info(i2sdev, in, &pi, NULL); | ||
573 | |||
574 | fc = in_le32(&i2sdev->intfregs->frame_count); | ||
575 | fc = fc - pi->frame_count; | ||
576 | |||
577 | return (bytes_to_frames(pi->substream->runtime, | ||
578 | pi->current_period * | ||
579 | snd_pcm_lib_period_bytes(pi->substream)) | ||
580 | + fc) % pi->substream->runtime->buffer_size; | ||
581 | } | ||
582 | |||
583 | static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in) | ||
584 | { | ||
585 | struct pcm_info *pi; | ||
586 | u32 fc; | ||
587 | u32 delta; | ||
588 | |||
589 | spin_lock(&i2sdev->low_lock); | ||
590 | get_pcm_info(i2sdev, in, &pi, NULL); | ||
591 | |||
592 | if (!pi->dbdma_ring.running) { | ||
593 | /* there was still an interrupt pending | ||
594 | * while we stopped. or maybe another | ||
595 | * processor (not the one that was stopping | ||
596 | * the DMA engine) was spinning above | ||
597 | * waiting for the lock. */ | ||
598 | goto out_unlock; | ||
599 | } | ||
600 | |||
601 | fc = in_le32(&i2sdev->intfregs->frame_count); | ||
602 | /* a counter overflow does not change the calculation. */ | ||
603 | delta = fc - pi->frame_count; | ||
604 | |||
605 | /* update current_period */ | ||
606 | while (delta >= pi->substream->runtime->period_size) { | ||
607 | pi->current_period++; | ||
608 | delta = delta - pi->substream->runtime->period_size; | ||
609 | } | ||
610 | |||
611 | if (unlikely(delta)) { | ||
612 | /* Some interrupt came late, so check the dbdma. | ||
613 | * This special case exists to syncronize the frame_count with | ||
614 | * the dbdma transfer, but is hit every once in a while. */ | ||
615 | int period; | ||
616 | |||
617 | period = (in_le32(&pi->dbdma->cmdptr) | ||
618 | - pi->dbdma_ring.bus_cmd_start) | ||
619 | / sizeof(struct dbdma_cmd); | ||
620 | pi->current_period = pi->current_period | ||
621 | % pi->substream->runtime->periods; | ||
622 | |||
623 | while (pi->current_period != period) { | ||
624 | pi->current_period++; | ||
625 | pi->current_period %= pi->substream->runtime->periods; | ||
626 | /* Set delta to zero, as the frame_count value is too | ||
627 | * high (otherwise the code path will not be executed). | ||
628 | * This corrects the fact that the frame_count is too | ||
629 | * low at the beginning due to buffering. */ | ||
630 | delta = 0; | ||
631 | } | ||
632 | } | ||
633 | |||
634 | pi->frame_count = fc - delta; | ||
635 | pi->current_period %= pi->substream->runtime->periods; | ||
636 | |||
637 | spin_unlock(&i2sdev->low_lock); | ||
638 | /* may call _trigger again, hence needs to be unlocked */ | ||
639 | snd_pcm_period_elapsed(pi->substream); | ||
640 | return; | ||
641 | out_unlock: | ||
642 | spin_unlock(&i2sdev->low_lock); | ||
643 | } | ||
644 | |||
645 | irqreturn_t i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs) | ||
646 | { | ||
647 | handle_interrupt((struct i2sbus_dev *)devid, 0); | ||
648 | return IRQ_HANDLED; | ||
649 | } | ||
650 | |||
651 | irqreturn_t i2sbus_rx_intr(int irq, void *devid, struct pt_regs * regs) | ||
652 | { | ||
653 | handle_interrupt((struct i2sbus_dev *)devid, 1); | ||
654 | return IRQ_HANDLED; | ||
655 | } | ||
656 | |||
657 | static int i2sbus_playback_open(struct snd_pcm_substream *substream) | ||
658 | { | ||
659 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
660 | |||
661 | if (!i2sdev) | ||
662 | return -EINVAL; | ||
663 | i2sdev->out.substream = substream; | ||
664 | return i2sbus_pcm_open(i2sdev, 0); | ||
665 | } | ||
666 | |||
667 | static int i2sbus_playback_close(struct snd_pcm_substream *substream) | ||
668 | { | ||
669 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
670 | int err; | ||
671 | |||
672 | if (!i2sdev) | ||
673 | return -EINVAL; | ||
674 | if (i2sdev->out.substream != substream) | ||
675 | return -EINVAL; | ||
676 | err = i2sbus_pcm_close(i2sdev, 0); | ||
677 | if (!err) | ||
678 | i2sdev->out.substream = NULL; | ||
679 | return err; | ||
680 | } | ||
681 | |||
682 | static int i2sbus_playback_prepare(struct snd_pcm_substream *substream) | ||
683 | { | ||
684 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
685 | |||
686 | if (!i2sdev) | ||
687 | return -EINVAL; | ||
688 | if (i2sdev->out.substream != substream) | ||
689 | return -EINVAL; | ||
690 | return i2sbus_pcm_prepare(i2sdev, 0); | ||
691 | } | ||
692 | |||
693 | static int i2sbus_playback_trigger(struct snd_pcm_substream *substream, int cmd) | ||
694 | { | ||
695 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
696 | |||
697 | if (!i2sdev) | ||
698 | return -EINVAL; | ||
699 | if (i2sdev->out.substream != substream) | ||
700 | return -EINVAL; | ||
701 | return i2sbus_pcm_trigger(i2sdev, 0, cmd); | ||
702 | } | ||
703 | |||
704 | static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream | ||
705 | *substream) | ||
706 | { | ||
707 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
708 | |||
709 | if (!i2sdev) | ||
710 | return -EINVAL; | ||
711 | if (i2sdev->out.substream != substream) | ||
712 | return 0; | ||
713 | return i2sbus_pcm_pointer(i2sdev, 0); | ||
714 | } | ||
715 | |||
716 | static struct snd_pcm_ops i2sbus_playback_ops = { | ||
717 | .open = i2sbus_playback_open, | ||
718 | .close = i2sbus_playback_close, | ||
719 | .ioctl = snd_pcm_lib_ioctl, | ||
720 | .hw_params = i2sbus_hw_params, | ||
721 | .hw_free = i2sbus_hw_free, | ||
722 | .prepare = i2sbus_playback_prepare, | ||
723 | .trigger = i2sbus_playback_trigger, | ||
724 | .pointer = i2sbus_playback_pointer, | ||
725 | }; | ||
726 | |||
727 | static int i2sbus_record_open(struct snd_pcm_substream *substream) | ||
728 | { | ||
729 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
730 | |||
731 | if (!i2sdev) | ||
732 | return -EINVAL; | ||
733 | i2sdev->in.substream = substream; | ||
734 | return i2sbus_pcm_open(i2sdev, 1); | ||
735 | } | ||
736 | |||
737 | static int i2sbus_record_close(struct snd_pcm_substream *substream) | ||
738 | { | ||
739 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
740 | int err; | ||
741 | |||
742 | if (!i2sdev) | ||
743 | return -EINVAL; | ||
744 | if (i2sdev->in.substream != substream) | ||
745 | return -EINVAL; | ||
746 | err = i2sbus_pcm_close(i2sdev, 1); | ||
747 | if (!err) | ||
748 | i2sdev->in.substream = NULL; | ||
749 | return err; | ||
750 | } | ||
751 | |||
752 | static int i2sbus_record_prepare(struct snd_pcm_substream *substream) | ||
753 | { | ||
754 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
755 | |||
756 | if (!i2sdev) | ||
757 | return -EINVAL; | ||
758 | if (i2sdev->in.substream != substream) | ||
759 | return -EINVAL; | ||
760 | return i2sbus_pcm_prepare(i2sdev, 1); | ||
761 | } | ||
762 | |||
763 | static int i2sbus_record_trigger(struct snd_pcm_substream *substream, int cmd) | ||
764 | { | ||
765 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
766 | |||
767 | if (!i2sdev) | ||
768 | return -EINVAL; | ||
769 | if (i2sdev->in.substream != substream) | ||
770 | return -EINVAL; | ||
771 | return i2sbus_pcm_trigger(i2sdev, 1, cmd); | ||
772 | } | ||
773 | |||
774 | static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream | ||
775 | *substream) | ||
776 | { | ||
777 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
778 | |||
779 | if (!i2sdev) | ||
780 | return -EINVAL; | ||
781 | if (i2sdev->in.substream != substream) | ||
782 | return 0; | ||
783 | return i2sbus_pcm_pointer(i2sdev, 1); | ||
784 | } | ||
785 | |||
786 | static struct snd_pcm_ops i2sbus_record_ops = { | ||
787 | .open = i2sbus_record_open, | ||
788 | .close = i2sbus_record_close, | ||
789 | .ioctl = snd_pcm_lib_ioctl, | ||
790 | .hw_params = i2sbus_hw_params, | ||
791 | .hw_free = i2sbus_hw_free, | ||
792 | .prepare = i2sbus_record_prepare, | ||
793 | .trigger = i2sbus_record_trigger, | ||
794 | .pointer = i2sbus_record_pointer, | ||
795 | }; | ||
796 | |||
797 | static void i2sbus_private_free(struct snd_pcm *pcm) | ||
798 | { | ||
799 | struct i2sbus_dev *i2sdev = snd_pcm_chip(pcm); | ||
800 | struct codec_info_item *p, *tmp; | ||
801 | |||
802 | i2sdev->sound.pcm = NULL; | ||
803 | i2sdev->out.created = 0; | ||
804 | i2sdev->in.created = 0; | ||
805 | list_for_each_entry_safe(p, tmp, &i2sdev->sound.codec_list, list) { | ||
806 | printk(KERN_ERR "i2sbus: a codec didn't unregister!\n"); | ||
807 | list_del(&p->list); | ||
808 | module_put(p->codec->owner); | ||
809 | kfree(p); | ||
810 | } | ||
811 | soundbus_dev_put(&i2sdev->sound); | ||
812 | module_put(THIS_MODULE); | ||
813 | } | ||
814 | |||
815 | /* FIXME: this function needs an error handling strategy with labels */ | ||
816 | int | ||
817 | i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, | ||
818 | struct codec_info *ci, void *data) | ||
819 | { | ||
820 | int err, in = 0, out = 0; | ||
821 | struct transfer_info *tmp; | ||
822 | struct i2sbus_dev *i2sdev = soundbus_dev_to_i2sbus_dev(dev); | ||
823 | struct codec_info_item *cii; | ||
824 | |||
825 | if (!dev->pcmname || dev->pcmid == -1) { | ||
826 | printk(KERN_ERR "i2sbus: pcm name and id must be set!\n"); | ||
827 | return -EINVAL; | ||
828 | } | ||
829 | |||
830 | list_for_each_entry(cii, &dev->codec_list, list) { | ||
831 | if (cii->codec_data == data) | ||
832 | return -EALREADY; | ||
833 | } | ||
834 | |||
835 | if (!ci->transfers || !ci->transfers->formats | ||
836 | || !ci->transfers->rates || !ci->usable) | ||
837 | return -EINVAL; | ||
838 | |||
839 | /* we currently code the i2s transfer on the clock, and support only | ||
840 | * 32 and 64 */ | ||
841 | if (ci->bus_factor != 32 && ci->bus_factor != 64) | ||
842 | return -EINVAL; | ||
843 | |||
844 | /* If you want to fix this, you need to keep track of what transport infos | ||
845 | * are to be used, which codecs they belong to, and then fix all the | ||
846 | * sysclock/busclock stuff above to depend on which is usable */ | ||
847 | list_for_each_entry(cii, &dev->codec_list, list) { | ||
848 | if (cii->codec->sysclock_factor != ci->sysclock_factor) { | ||
849 | printk(KERN_DEBUG | ||
850 | "cannot yet handle multiple different sysclocks!\n"); | ||
851 | return -EINVAL; | ||
852 | } | ||
853 | if (cii->codec->bus_factor != ci->bus_factor) { | ||
854 | printk(KERN_DEBUG | ||
855 | "cannot yet handle multiple different bus clocks!\n"); | ||
856 | return -EINVAL; | ||
857 | } | ||
858 | } | ||
859 | |||
860 | tmp = ci->transfers; | ||
861 | while (tmp->formats && tmp->rates) { | ||
862 | if (tmp->transfer_in) | ||
863 | in = 1; | ||
864 | else | ||
865 | out = 1; | ||
866 | tmp++; | ||
867 | } | ||
868 | |||
869 | cii = kzalloc(sizeof(struct codec_info_item), GFP_KERNEL); | ||
870 | if (!cii) { | ||
871 | printk(KERN_DEBUG "i2sbus: failed to allocate cii\n"); | ||
872 | return -ENOMEM; | ||
873 | } | ||
874 | |||
875 | /* use the private data to point to the codec info */ | ||
876 | cii->sdev = soundbus_dev_get(dev); | ||
877 | cii->codec = ci; | ||
878 | cii->codec_data = data; | ||
879 | |||
880 | if (!cii->sdev) { | ||
881 | printk(KERN_DEBUG | ||
882 | "i2sbus: failed to get soundbus dev reference\n"); | ||
883 | kfree(cii); | ||
884 | return -ENODEV; | ||
885 | } | ||
886 | |||
887 | if (!try_module_get(THIS_MODULE)) { | ||
888 | printk(KERN_DEBUG "i2sbus: failed to get module reference!\n"); | ||
889 | soundbus_dev_put(dev); | ||
890 | kfree(cii); | ||
891 | return -EBUSY; | ||
892 | } | ||
893 | |||
894 | if (!try_module_get(ci->owner)) { | ||
895 | printk(KERN_DEBUG | ||
896 | "i2sbus: failed to get module reference to codec owner!\n"); | ||
897 | module_put(THIS_MODULE); | ||
898 | soundbus_dev_put(dev); | ||
899 | kfree(cii); | ||
900 | return -EBUSY; | ||
901 | } | ||
902 | |||
903 | if (!dev->pcm) { | ||
904 | err = snd_pcm_new(card, | ||
905 | dev->pcmname, | ||
906 | dev->pcmid, | ||
907 | 0, | ||
908 | 0, | ||
909 | &dev->pcm); | ||
910 | if (err) { | ||
911 | printk(KERN_DEBUG "i2sbus: failed to create pcm\n"); | ||
912 | kfree(cii); | ||
913 | module_put(ci->owner); | ||
914 | soundbus_dev_put(dev); | ||
915 | module_put(THIS_MODULE); | ||
916 | return err; | ||
917 | } | ||
918 | } | ||
919 | |||
920 | /* ALSA yet again sucks. | ||
921 | * If it is ever fixed, remove this line. See below. */ | ||
922 | out = in = 1; | ||
923 | |||
924 | if (!i2sdev->out.created && out) { | ||
925 | if (dev->pcm->card != card) { | ||
926 | /* eh? */ | ||
927 | printk(KERN_ERR | ||
928 | "Can't attach same bus to different cards!\n"); | ||
929 | module_put(ci->owner); | ||
930 | kfree(cii); | ||
931 | soundbus_dev_put(dev); | ||
932 | module_put(THIS_MODULE); | ||
933 | return -EINVAL; | ||
934 | } | ||
935 | if ((err = | ||
936 | snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 1))) { | ||
937 | module_put(ci->owner); | ||
938 | kfree(cii); | ||
939 | soundbus_dev_put(dev); | ||
940 | module_put(THIS_MODULE); | ||
941 | return err; | ||
942 | } | ||
943 | snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
944 | &i2sbus_playback_ops); | ||
945 | i2sdev->out.created = 1; | ||
946 | } | ||
947 | |||
948 | if (!i2sdev->in.created && in) { | ||
949 | if (dev->pcm->card != card) { | ||
950 | printk(KERN_ERR | ||
951 | "Can't attach same bus to different cards!\n"); | ||
952 | module_put(ci->owner); | ||
953 | kfree(cii); | ||
954 | soundbus_dev_put(dev); | ||
955 | module_put(THIS_MODULE); | ||
956 | return -EINVAL; | ||
957 | } | ||
958 | if ((err = | ||
959 | snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1))) { | ||
960 | module_put(ci->owner); | ||
961 | kfree(cii); | ||
962 | soundbus_dev_put(dev); | ||
963 | module_put(THIS_MODULE); | ||
964 | return err; | ||
965 | } | ||
966 | snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, | ||
967 | &i2sbus_record_ops); | ||
968 | i2sdev->in.created = 1; | ||
969 | } | ||
970 | |||
971 | /* so we have to register the pcm after adding any substream | ||
972 | * to it because alsa doesn't create the devices for the | ||
973 | * substreams when we add them later. | ||
974 | * Therefore, force in and out on both busses (above) and | ||
975 | * register the pcm now instead of just after creating it. | ||
976 | */ | ||
977 | err = snd_device_register(card, dev->pcm); | ||
978 | if (err) { | ||
979 | printk(KERN_ERR "i2sbus: error registering new pcm\n"); | ||
980 | module_put(ci->owner); | ||
981 | kfree(cii); | ||
982 | soundbus_dev_put(dev); | ||
983 | module_put(THIS_MODULE); | ||
984 | return err; | ||
985 | } | ||
986 | /* no errors any more, so let's add this to our list */ | ||
987 | list_add(&cii->list, &dev->codec_list); | ||
988 | |||
989 | dev->pcm->private_data = i2sdev; | ||
990 | dev->pcm->private_free = i2sbus_private_free; | ||
991 | |||
992 | /* well, we really should support scatter/gather DMA */ | ||
993 | snd_pcm_lib_preallocate_pages_for_all( | ||
994 | dev->pcm, SNDRV_DMA_TYPE_DEV, | ||
995 | snd_dma_pci_data(macio_get_pci_dev(i2sdev->macio)), | ||
996 | 64 * 1024, 64 * 1024); | ||
997 | |||
998 | return 0; | ||
999 | } | ||
1000 | |||
1001 | void i2sbus_detach_codec(struct soundbus_dev *dev, void *data) | ||
1002 | { | ||
1003 | struct codec_info_item *cii = NULL, *i; | ||
1004 | |||
1005 | list_for_each_entry(i, &dev->codec_list, list) { | ||
1006 | if (i->codec_data == data) { | ||
1007 | cii = i; | ||
1008 | break; | ||
1009 | } | ||
1010 | } | ||
1011 | if (cii) { | ||
1012 | list_del(&cii->list); | ||
1013 | module_put(cii->codec->owner); | ||
1014 | kfree(cii); | ||
1015 | } | ||
1016 | /* no more codecs, but still a pcm? */ | ||
1017 | if (list_empty(&dev->codec_list) && dev->pcm) { | ||
1018 | /* the actual cleanup is done by the callback above! */ | ||
1019 | snd_device_free(dev->pcm->card, dev->pcm); | ||
1020 | } | ||
1021 | } | ||