]>
Commit | Line | Data |
---|---|---|
f3d9478b JB |
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 | } |