aboutsummaryrefslogtreecommitdiffstats
path: root/sound/aoa/soundbus/i2sbus
diff options
context:
space:
mode:
Diffstat (limited to 'sound/aoa/soundbus/i2sbus')
-rw-r--r--sound/aoa/soundbus/i2sbus/Makefile2
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-control.c192
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-control.h37
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-core.c387
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-interface.h187
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-pcm.c1021
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus.h112
7 files changed, 1938 insertions, 0 deletions
diff --git a/sound/aoa/soundbus/i2sbus/Makefile b/sound/aoa/soundbus/i2sbus/Makefile
new file mode 100644
index 00000000000..e57a5cf6565
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/Makefile
@@ -0,0 +1,2 @@
1obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += snd-aoa-i2sbus.o
2snd-aoa-i2sbus-objs := i2sbus-core.o i2sbus-pcm.o i2sbus-control.o
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.c b/sound/aoa/soundbus/i2sbus/i2sbus-control.c
new file mode 100644
index 00000000000..f50407952d3
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.c
@@ -0,0 +1,192 @@
1/*
2 * i2sbus driver -- bus control 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#include <asm/prom.h>
12#include <asm/macio.h>
13#include <asm/pmac_feature.h>
14#include <asm/pmac_pfunc.h>
15#include "i2sbus.h"
16
17int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c)
18{
19 *c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL);
20 if (!*c)
21 return -ENOMEM;
22
23 INIT_LIST_HEAD(&(*c)->list);
24
25 if (of_address_to_resource(dev->ofdev.node, 0, &(*c)->rsrc))
26 goto err;
27 /* we really should be using feature calls instead of mapping
28 * these registers. It's safe for now since no one else is
29 * touching them... */
30 (*c)->controlregs = ioremap((*c)->rsrc.start,
31 sizeof(struct i2s_control_regs));
32 if (!(*c)->controlregs)
33 goto err;
34
35 return 0;
36 err:
37 kfree(*c);
38 *c = NULL;
39 return -ENODEV;
40}
41
42void i2sbus_control_destroy(struct i2sbus_control *c)
43{
44 iounmap(c->controlregs);
45 kfree(c);
46}
47
48/* this is serialised externally */
49int i2sbus_control_add_dev(struct i2sbus_control *c,
50 struct i2sbus_dev *i2sdev)
51{
52 struct device_node *np;
53
54 np = i2sdev->sound.ofdev.node;
55 i2sdev->enable = pmf_find_function(np, "enable");
56 i2sdev->cell_enable = pmf_find_function(np, "cell-enable");
57 i2sdev->clock_enable = pmf_find_function(np, "clock-enable");
58 i2sdev->cell_disable = pmf_find_function(np, "cell-disable");
59 i2sdev->clock_disable = pmf_find_function(np, "clock-disable");
60
61 /* if the bus number is not 0 or 1 we absolutely need to use
62 * the platform functions -- there's nothing in Darwin that
63 * would allow seeing a system behind what the FCRs are then,
64 * and I don't want to go parsing a bunch of platform functions
65 * by hand to try finding a system... */
66 if (i2sdev->bus_number != 0 && i2sdev->bus_number != 1 &&
67 (!i2sdev->enable ||
68 !i2sdev->cell_enable || !i2sdev->clock_enable ||
69 !i2sdev->cell_disable || !i2sdev->clock_disable)) {
70 pmf_put_function(i2sdev->enable);
71 pmf_put_function(i2sdev->cell_enable);
72 pmf_put_function(i2sdev->clock_enable);
73 pmf_put_function(i2sdev->cell_disable);
74 pmf_put_function(i2sdev->clock_disable);
75 return -ENODEV;
76 }
77
78 list_add(&i2sdev->item, &c->list);
79
80 return 0;
81}
82
83void i2sbus_control_remove_dev(struct i2sbus_control *c,
84 struct i2sbus_dev *i2sdev)
85{
86 /* this is serialised externally */
87 list_del(&i2sdev->item);
88 if (list_empty(&c->list))
89 i2sbus_control_destroy(c);
90}
91
92int i2sbus_control_enable(struct i2sbus_control *c,
93 struct i2sbus_dev *i2sdev)
94{
95 struct pmf_args args = { .count = 0 };
96 int cc;
97
98 if (i2sdev->enable)
99 return pmf_call_one(i2sdev->enable, &args);
100
101 switch (i2sdev->bus_number) {
102 case 0:
103 cc = in_le32(&c->controlregs->cell_control);
104 out_le32(&c->controlregs->cell_control, cc | CTRL_CLOCK_INTF_0_ENABLE);
105 break;
106 case 1:
107 cc = in_le32(&c->controlregs->cell_control);
108 out_le32(&c->controlregs->cell_control, cc | CTRL_CLOCK_INTF_1_ENABLE);
109 break;
110 default:
111 return -ENODEV;
112 }
113 return 0;
114}
115
116int i2sbus_control_cell(struct i2sbus_control *c,
117 struct i2sbus_dev *i2sdev,
118 int enable)
119{
120 struct pmf_args args = { .count = 0 };
121 int cc;
122
123 switch (enable) {
124 case 0:
125 if (i2sdev->cell_disable)
126 return pmf_call_one(i2sdev->cell_disable, &args);
127 break;
128 case 1:
129 if (i2sdev->cell_enable)
130 return pmf_call_one(i2sdev->cell_enable, &args);
131 break;
132 default:
133 printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n");
134 return -ENODEV;
135 }
136 switch (i2sdev->bus_number) {
137 case 0:
138 cc = in_le32(&c->controlregs->cell_control);
139 cc &= ~CTRL_CLOCK_CELL_0_ENABLE;
140 cc |= enable * CTRL_CLOCK_CELL_0_ENABLE;
141 out_le32(&c->controlregs->cell_control, cc);
142 break;
143 case 1:
144 cc = in_le32(&c->controlregs->cell_control);
145 cc &= ~CTRL_CLOCK_CELL_1_ENABLE;
146 cc |= enable * CTRL_CLOCK_CELL_1_ENABLE;
147 out_le32(&c->controlregs->cell_control, cc);
148 break;
149 default:
150 return -ENODEV;
151 }
152 return 0;
153}
154
155int i2sbus_control_clock(struct i2sbus_control *c,
156 struct i2sbus_dev *i2sdev,
157 int enable)
158{
159 struct pmf_args args = { .count = 0 };
160 int cc;
161
162 switch (enable) {
163 case 0:
164 if (i2sdev->clock_disable)
165 return pmf_call_one(i2sdev->clock_disable, &args);
166 break;
167 case 1:
168 if (i2sdev->clock_enable)
169 return pmf_call_one(i2sdev->clock_enable, &args);
170 break;
171 default:
172 printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n");
173 return -ENODEV;
174 }
175 switch (i2sdev->bus_number) {
176 case 0:
177 cc = in_le32(&c->controlregs->cell_control);
178 cc &= ~CTRL_CLOCK_CLOCK_0_ENABLE;
179 cc |= enable * CTRL_CLOCK_CLOCK_0_ENABLE;
180 out_le32(&c->controlregs->cell_control, cc);
181 break;
182 case 1:
183 cc = in_le32(&c->controlregs->cell_control);
184 cc &= ~CTRL_CLOCK_CLOCK_1_ENABLE;
185 cc |= enable * CTRL_CLOCK_CLOCK_1_ENABLE;
186 out_le32(&c->controlregs->cell_control, cc);
187 break;
188 default:
189 return -ENODEV;
190 }
191 return 0;
192}
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.h b/sound/aoa/soundbus/i2sbus/i2sbus-control.h
new file mode 100644
index 00000000000..bb05550f730
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.h
@@ -0,0 +1,37 @@
1/*
2 * i2sbus driver -- bus register definitions
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8#ifndef __I2SBUS_CONTROLREGS_H
9#define __I2SBUS_CONTROLREGS_H
10
11/* i2s control registers, at least what we know about them */
12
13#define __PAD(m,n) u8 __pad##m[n]
14#define _PAD(line, n) __PAD(line, n)
15#define PAD(n) _PAD(__LINE__, (n))
16struct i2s_control_regs {
17 PAD(0x38);
18 __le32 fcr0; /* 0x38 (unknown) */
19 __le32 cell_control; /* 0x3c (fcr1) */
20 __le32 fcr2; /* 0x40 (unknown) */
21 __le32 fcr3; /* 0x44 (fcr3) */
22 __le32 clock_control; /* 0x48 (unknown) */
23 PAD(4);
24 /* total size: 0x50 bytes */
25} __attribute__((__packed__));
26
27#define CTRL_CLOCK_CELL_0_ENABLE (1<<10)
28#define CTRL_CLOCK_CLOCK_0_ENABLE (1<<12)
29#define CTRL_CLOCK_SWRESET_0 (1<<11)
30#define CTRL_CLOCK_INTF_0_ENABLE (1<<13)
31
32#define CTRL_CLOCK_CELL_1_ENABLE (1<<17)
33#define CTRL_CLOCK_CLOCK_1_ENABLE (1<<18)
34#define CTRL_CLOCK_SWRESET_1 (1<<19)
35#define CTRL_CLOCK_INTF_1_ENABLE (1<<20)
36
37#endif /* __I2SBUS_CONTROLREGS_H */
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
new file mode 100644
index 00000000000..f268dacdaa0
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
@@ -0,0 +1,387 @@
1/*
2 * i2sbus driver
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8
9#include <linux/module.h>
10#include <asm/macio.h>
11#include <asm/dbdma.h>
12#include <linux/pci.h>
13#include <linux/interrupt.h>
14#include <sound/driver.h>
15#include <sound/core.h>
16#include <linux/dma-mapping.h>
17#include "../soundbus.h"
18#include "i2sbus.h"
19
20MODULE_LICENSE("GPL");
21MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
22MODULE_DESCRIPTION("Apple Soundbus: I2S support");
23/* for auto-loading, declare that we handle this weird
24 * string that macio puts into the relevant device */
25MODULE_ALIAS("of:Ni2sTi2sC");
26
27static struct of_device_id i2sbus_match[] = {
28 { .name = "i2s" },
29 { }
30};
31
32static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
33 struct dbdma_command_mem *r,
34 int numcmds)
35{
36 /* one more for rounding */
37 r->size = (numcmds+1) * sizeof(struct dbdma_cmd);
38 /* We use the PCI APIs for now until the generic one gets fixed
39 * enough or until we get some macio-specific versions
40 */
41 r->space = dma_alloc_coherent(
42 &macio_get_pci_dev(i2sdev->macio)->dev,
43 r->size,
44 &r->bus_addr,
45 GFP_KERNEL);
46
47 if (!r->space) return -ENOMEM;
48
49 memset(r->space, 0, r->size);
50 r->cmds = (void*)DBDMA_ALIGN(r->space);
51 r->bus_cmd_start = r->bus_addr +
52 (dma_addr_t)((char*)r->cmds - (char*)r->space);
53
54 return 0;
55}
56
57static void free_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
58 struct dbdma_command_mem *r)
59{
60 if (!r->space) return;
61
62 dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
63 r->size, r->space, r->bus_addr);
64}
65
66static void i2sbus_release_dev(struct device *dev)
67{
68 struct i2sbus_dev *i2sdev;
69 int i;
70
71 i2sdev = container_of(dev, struct i2sbus_dev, sound.ofdev.dev);
72
73 if (i2sdev->intfregs) iounmap(i2sdev->intfregs);
74 if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma);
75 if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma);
76 for (i=0;i<3;i++)
77 if (i2sdev->allocated_resource[i])
78 release_and_free_resource(i2sdev->allocated_resource[i]);
79 free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring);
80 free_dbdma_descriptor_ring(i2sdev, &i2sdev->in.dbdma_ring);
81 for (i=0;i<3;i++)
82 free_irq(i2sdev->interrupts[i], i2sdev);
83 i2sbus_control_remove_dev(i2sdev->control, i2sdev);
84 mutex_destroy(&i2sdev->lock);
85 kfree(i2sdev);
86}
87
88static irqreturn_t i2sbus_bus_intr(int irq, void *devid, struct pt_regs *regs)
89{
90 struct i2sbus_dev *dev = devid;
91 u32 intreg;
92
93 spin_lock(&dev->low_lock);
94 intreg = in_le32(&dev->intfregs->intr_ctl);
95
96 /* acknowledge interrupt reasons */
97 out_le32(&dev->intfregs->intr_ctl, intreg);
98
99 spin_unlock(&dev->low_lock);
100
101 return IRQ_HANDLED;
102}
103
104static int force;
105module_param(force, int, 0444);
106MODULE_PARM_DESC(force, "Force loading i2sbus even when"
107 " no layout-id property is present");
108
109/* FIXME: look at device node refcounting */
110static int i2sbus_add_dev(struct macio_dev *macio,
111 struct i2sbus_control *control,
112 struct device_node *np)
113{
114 struct i2sbus_dev *dev;
115 struct device_node *child = NULL, *sound = NULL;
116 int i;
117 static const char *rnames[] = { "i2sbus: %s (control)",
118 "i2sbus: %s (tx)",
119 "i2sbus: %s (rx)" };
120 static irqreturn_t (*ints[])(int irq, void *devid,
121 struct pt_regs *regs) = {
122 i2sbus_bus_intr,
123 i2sbus_tx_intr,
124 i2sbus_rx_intr
125 };
126
127 if (strlen(np->name) != 5)
128 return 0;
129 if (strncmp(np->name, "i2s-", 4))
130 return 0;
131
132 if (np->n_intrs != 3)
133 return 0;
134
135 dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL);
136 if (!dev)
137 return 0;
138
139 i = 0;
140 while ((child = of_get_next_child(np, child))) {
141 if (strcmp(child->name, "sound") == 0) {
142 i++;
143 sound = child;
144 }
145 }
146 if (i == 1) {
147 u32 *layout_id;
148 layout_id = (u32*) get_property(sound, "layout-id", NULL);
149 if (layout_id) {
150 snprintf(dev->sound.modalias, 32,
151 "sound-layout-%d", *layout_id);
152 force = 1;
153 }
154 }
155 /* for the time being, until we can handle non-layout-id
156 * things in some fabric, refuse to attach if there is no
157 * layout-id property or we haven't been forced to attach.
158 * When there are two i2s busses and only one has a layout-id,
159 * then this depends on the order, but that isn't important
160 * either as the second one in that case is just a modem. */
161 if (!force) {
162 kfree(dev);
163 return -ENODEV;
164 }
165
166 mutex_init(&dev->lock);
167 spin_lock_init(&dev->low_lock);
168 dev->sound.ofdev.node = np;
169 dev->sound.ofdev.dma_mask = macio->ofdev.dma_mask;
170 dev->sound.ofdev.dev.dma_mask = &dev->sound.ofdev.dma_mask;
171 dev->sound.ofdev.dev.parent = &macio->ofdev.dev;
172 dev->sound.ofdev.dev.release = i2sbus_release_dev;
173 dev->sound.attach_codec = i2sbus_attach_codec;
174 dev->sound.detach_codec = i2sbus_detach_codec;
175 dev->sound.pcmid = -1;
176 dev->macio = macio;
177 dev->control = control;
178 dev->bus_number = np->name[4] - 'a';
179 INIT_LIST_HEAD(&dev->sound.codec_list);
180
181 for (i=0;i<3;i++) {
182 dev->interrupts[i] = -1;
183 snprintf(dev->rnames[i], sizeof(dev->rnames[i]), rnames[i], np->name);
184 }
185 for (i=0;i<3;i++) {
186 if (request_irq(np->intrs[i].line, ints[i], 0, dev->rnames[i], dev))
187 goto err;
188 dev->interrupts[i] = np->intrs[i].line;
189 }
190
191 for (i=0;i<3;i++) {
192 if (of_address_to_resource(np, i, &dev->resources[i]))
193 goto err;
194 /* if only we could use our resource dev->resources[i]...
195 * but request_resource doesn't know about parents and
196 * contained resources... */
197 dev->allocated_resource[i] =
198 request_mem_region(dev->resources[i].start,
199 dev->resources[i].end -
200 dev->resources[i].start + 1,
201 dev->rnames[i]);
202 if (!dev->allocated_resource[i]) {
203 printk(KERN_ERR "i2sbus: failed to claim resource %d!\n", i);
204 goto err;
205 }
206 }
207 /* should do sanity checking here about length of them */
208 dev->intfregs = ioremap(dev->resources[0].start,
209 dev->resources[0].end-dev->resources[0].start+1);
210 dev->out.dbdma = ioremap(dev->resources[1].start,
211 dev->resources[1].end-dev->resources[1].start+1);
212 dev->in.dbdma = ioremap(dev->resources[2].start,
213 dev->resources[2].end-dev->resources[2].start+1);
214 if (!dev->intfregs || !dev->out.dbdma || !dev->in.dbdma)
215 goto err;
216
217 if (alloc_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring,
218 MAX_DBDMA_COMMANDS))
219 goto err;
220 if (alloc_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring,
221 MAX_DBDMA_COMMANDS))
222 goto err;
223
224 if (i2sbus_control_add_dev(dev->control, dev)) {
225 printk(KERN_ERR "i2sbus: control layer didn't like bus\n");
226 goto err;
227 }
228
229 if (soundbus_add_one(&dev->sound)) {
230 printk(KERN_DEBUG "i2sbus: device registration error!\n");
231 goto err;
232 }
233
234 /* enable this cell */
235 i2sbus_control_cell(dev->control, dev, 1);
236 i2sbus_control_enable(dev->control, dev);
237 i2sbus_control_clock(dev->control, dev, 1);
238
239 return 1;
240 err:
241 for (i=0;i<3;i++)
242 if (dev->interrupts[i] != -1)
243 free_irq(dev->interrupts[i], dev);
244 free_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring);
245 free_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring);
246 if (dev->intfregs) iounmap(dev->intfregs);
247 if (dev->out.dbdma) iounmap(dev->out.dbdma);
248 if (dev->in.dbdma) iounmap(dev->in.dbdma);
249 for (i=0;i<3;i++)
250 if (dev->allocated_resource[i])
251 release_and_free_resource(dev->allocated_resource[i]);
252 mutex_destroy(&dev->lock);
253 kfree(dev);
254 return 0;
255}
256
257static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match)
258{
259 struct device_node *np = NULL;
260 int got = 0, err;
261 struct i2sbus_control *control = NULL;
262
263 err = i2sbus_control_init(dev, &control);
264 if (err)
265 return err;
266 if (!control) {
267 printk(KERN_ERR "i2sbus_control_init API breakage\n");
268 return -ENODEV;
269 }
270
271 while ((np = of_get_next_child(dev->ofdev.node, np))) {
272 if (device_is_compatible(np, "i2sbus") ||
273 device_is_compatible(np, "i2s-modem")) {
274 got += i2sbus_add_dev(dev, control, np);
275 }
276 }
277
278 if (!got) {
279 /* found none, clean up */
280 i2sbus_control_destroy(control);
281 return -ENODEV;
282 }
283
284 dev->ofdev.dev.driver_data = control;
285
286 return 0;
287}
288
289static int i2sbus_remove(struct macio_dev* dev)
290{
291 struct i2sbus_control *control = dev->ofdev.dev.driver_data;
292 struct i2sbus_dev *i2sdev, *tmp;
293
294 list_for_each_entry_safe(i2sdev, tmp, &control->list, item)
295 soundbus_remove_one(&i2sdev->sound);
296
297 return 0;
298}
299
300#ifdef CONFIG_PM
301static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state)
302{
303 struct i2sbus_control *control = dev->ofdev.dev.driver_data;
304 struct codec_info_item *cii;
305 struct i2sbus_dev* i2sdev;
306 int err, ret = 0;
307
308 list_for_each_entry(i2sdev, &control->list, item) {
309 /* Notify Alsa */
310 if (i2sdev->sound.pcm) {
311 /* Suspend PCM streams */
312 snd_pcm_suspend_all(i2sdev->sound.pcm);
313 /* Probably useless as we handle
314 * power transitions ourselves */
315 snd_power_change_state(i2sdev->sound.pcm->card,
316 SNDRV_CTL_POWER_D3hot);
317 }
318 /* Notify codecs */
319 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
320 err = 0;
321 if (cii->codec->suspend)
322 err = cii->codec->suspend(cii, state);
323 if (err)
324 ret = err;
325 }
326 }
327 return ret;
328}
329
330static int i2sbus_resume(struct macio_dev* dev)
331{
332 struct i2sbus_control *control = dev->ofdev.dev.driver_data;
333 struct codec_info_item *cii;
334 struct i2sbus_dev* i2sdev;
335 int err, ret = 0;
336
337 list_for_each_entry(i2sdev, &control->list, item) {
338 /* Notify codecs so they can re-initialize */
339 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
340 err = 0;
341 if (cii->codec->resume)
342 err = cii->codec->resume(cii);
343 if (err)
344 ret = err;
345 }
346 /* Notify Alsa */
347 if (i2sdev->sound.pcm) {
348 /* Same comment as above, probably useless */
349 snd_power_change_state(i2sdev->sound.pcm->card,
350 SNDRV_CTL_POWER_D0);
351 }
352 }
353
354 return ret;
355}
356#endif /* CONFIG_PM */
357
358static int i2sbus_shutdown(struct macio_dev* dev)
359{
360 return 0;
361}
362
363static struct macio_driver i2sbus_drv = {
364 .name = "soundbus-i2s",
365 .owner = THIS_MODULE,
366 .match_table = i2sbus_match,
367 .probe = i2sbus_probe,
368 .remove = i2sbus_remove,
369#ifdef CONFIG_PM
370 .suspend = i2sbus_suspend,
371 .resume = i2sbus_resume,
372#endif
373 .shutdown = i2sbus_shutdown,
374};
375
376static int __init soundbus_i2sbus_init(void)
377{
378 return macio_register_driver(&i2sbus_drv);
379}
380
381static void __exit soundbus_i2sbus_exit(void)
382{
383 macio_unregister_driver(&i2sbus_drv);
384}
385
386module_init(soundbus_i2sbus_init);
387module_exit(soundbus_i2sbus_exit);
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-interface.h b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h
new file mode 100644
index 00000000000..c6b5f5452d2
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h
@@ -0,0 +1,187 @@
1/*
2 * i2sbus driver -- interface register definitions
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8#ifndef __I2SBUS_INTERFACE_H
9#define __I2SBUS_INTERFACE_H
10
11/* i2s bus control registers, at least what we know about them */
12
13#define __PAD(m,n) u8 __pad##m[n]
14#define _PAD(line, n) __PAD(line, n)
15#define PAD(n) _PAD(__LINE__, (n))
16struct i2s_interface_regs {
17 __le32 intr_ctl; /* 0x00 */
18 PAD(12);
19 __le32 serial_format; /* 0x10 */
20 PAD(12);
21 __le32 codec_msg_out; /* 0x20 */
22 PAD(12);
23 __le32 codec_msg_in; /* 0x30 */
24 PAD(12);
25 __le32 frame_count; /* 0x40 */
26 PAD(12);
27 __le32 frame_match; /* 0x50 */
28 PAD(12);
29 __le32 data_word_sizes; /* 0x60 */
30 PAD(12);
31 __le32 peak_level_sel; /* 0x70 */
32 PAD(12);
33 __le32 peak_level_in0; /* 0x80 */
34 PAD(12);
35 __le32 peak_level_in1; /* 0x90 */
36 PAD(12);
37 /* total size: 0x100 bytes */
38} __attribute__((__packed__));
39
40/* interrupt register is just a bitfield with
41 * interrupt enable and pending bits */
42#define I2S_REG_INTR_CTL 0x00
43# define I2S_INT_FRAME_COUNT (1<<31)
44# define I2S_PENDING_FRAME_COUNT (1<<30)
45# define I2S_INT_MESSAGE_FLAG (1<<29)
46# define I2S_PENDING_MESSAGE_FLAG (1<<28)
47# define I2S_INT_NEW_PEAK (1<<27)
48# define I2S_PENDING_NEW_PEAK (1<<26)
49# define I2S_INT_CLOCKS_STOPPED (1<<25)
50# define I2S_PENDING_CLOCKS_STOPPED (1<<24)
51# define I2S_INT_EXTERNAL_SYNC_ERROR (1<<23)
52# define I2S_PENDING_EXTERNAL_SYNC_ERROR (1<<22)
53# define I2S_INT_EXTERNAL_SYNC_OK (1<<21)
54# define I2S_PENDING_EXTERNAL_SYNC_OK (1<<20)
55# define I2S_INT_NEW_SAMPLE_RATE (1<<19)
56# define I2S_PENDING_NEW_SAMPLE_RATE (1<<18)
57# define I2S_INT_STATUS_FLAG (1<<17)
58# define I2S_PENDING_STATUS_FLAG (1<<16)
59
60/* serial format register is more interesting :)
61 * It contains:
62 * - clock source
63 * - MClk divisor
64 * - SClk divisor
65 * - SClk master flag
66 * - serial format (sony, i2s 64x, i2s 32x, dav, silabs)
67 * - external sample frequency interrupt (don't understand)
68 * - external sample frequency
69 */
70#define I2S_REG_SERIAL_FORMAT 0x10
71/* clock source. You get either 18.432, 45.1584 or 49.1520 MHz */
72# define I2S_SF_CLOCK_SOURCE_SHIFT 30
73# define I2S_SF_CLOCK_SOURCE_MASK (3<<I2S_SF_CLOCK_SOURCE_SHIFT)
74# define I2S_SF_CLOCK_SOURCE_18MHz (0<<I2S_SF_CLOCK_SOURCE_SHIFT)
75# define I2S_SF_CLOCK_SOURCE_45MHz (1<<I2S_SF_CLOCK_SOURCE_SHIFT)
76# define I2S_SF_CLOCK_SOURCE_49MHz (2<<I2S_SF_CLOCK_SOURCE_SHIFT)
77/* also, let's define the exact clock speeds here, in Hz */
78#define I2S_CLOCK_SPEED_18MHz 18432000
79#define I2S_CLOCK_SPEED_45MHz 45158400
80#define I2S_CLOCK_SPEED_49MHz 49152000
81/* MClk is the clock that drives the codec, usually called its 'system clock'.
82 * It is derived by taking only every 'divisor' tick of the clock.
83 */
84# define I2S_SF_MCLKDIV_SHIFT 24
85# define I2S_SF_MCLKDIV_MASK (0x1F<<I2S_SF_MCLKDIV_SHIFT)
86# define I2S_SF_MCLKDIV_1 (0x14<<I2S_SF_MCLKDIV_SHIFT)
87# define I2S_SF_MCLKDIV_3 (0x13<<I2S_SF_MCLKDIV_SHIFT)
88# define I2S_SF_MCLKDIV_5 (0x12<<I2S_SF_MCLKDIV_SHIFT)
89# define I2S_SF_MCLKDIV_14 (0x0E<<I2S_SF_MCLKDIV_SHIFT)
90# define I2S_SF_MCLKDIV_OTHER(div) (((div/2-1)<<I2S_SF_MCLKDIV_SHIFT)&I2S_SF_MCLKDIV_MASK)
91static inline int i2s_sf_mclkdiv(int div, int *out)
92{
93 int d;
94
95 switch(div) {
96 case 1: *out |= I2S_SF_MCLKDIV_1; return 0;
97 case 3: *out |= I2S_SF_MCLKDIV_3; return 0;
98 case 5: *out |= I2S_SF_MCLKDIV_5; return 0;
99 case 14: *out |= I2S_SF_MCLKDIV_14; return 0;
100 default:
101 if (div%2) return -1;
102 d = div/2-1;
103 if (d == 0x14 || d == 0x13 || d == 0x12 || d == 0x0E)
104 return -1;
105 *out |= I2S_SF_MCLKDIV_OTHER(div);
106 return 0;
107 }
108}
109/* SClk is the clock that drives the i2s wire bus. Note that it is
110 * derived from the MClk above by taking only every 'divisor' tick
111 * of MClk.
112 */
113# define I2S_SF_SCLKDIV_SHIFT 20
114# define I2S_SF_SCLKDIV_MASK (0xF<<I2S_SF_SCLKDIV_SHIFT)
115# define I2S_SF_SCLKDIV_1 (8<<I2S_SF_SCLKDIV_SHIFT)
116# define I2S_SF_SCLKDIV_3 (9<<I2S_SF_SCLKDIV_SHIFT)
117# define I2S_SF_SCLKDIV_OTHER(div) (((div/2-1)<<I2S_SF_SCLKDIV_SHIFT)&I2S_SF_SCLKDIV_MASK)
118static inline int i2s_sf_sclkdiv(int div, int *out)
119{
120 int d;
121
122 switch(div) {
123 case 1: *out |= I2S_SF_SCLKDIV_1; return 0;
124 case 3: *out |= I2S_SF_SCLKDIV_3; return 0;
125 default:
126 if (div%2) return -1;
127 d = div/2-1;
128 if (d == 8 || d == 9) return -1;
129 *out |= I2S_SF_SCLKDIV_OTHER(div);
130 return 0;
131 }
132}
133# define I2S_SF_SCLK_MASTER (1<<19)
134/* serial format is the way the data is put to the i2s wire bus */
135# define I2S_SF_SERIAL_FORMAT_SHIFT 16
136# define I2S_SF_SERIAL_FORMAT_MASK (7<<I2S_SF_SERIAL_FORMAT_SHIFT)
137# define I2S_SF_SERIAL_FORMAT_SONY (0<<I2S_SF_SERIAL_FORMAT_SHIFT)
138# define I2S_SF_SERIAL_FORMAT_I2S_64X (1<<I2S_SF_SERIAL_FORMAT_SHIFT)
139# define I2S_SF_SERIAL_FORMAT_I2S_32X (2<<I2S_SF_SERIAL_FORMAT_SHIFT)
140# define I2S_SF_SERIAL_FORMAT_I2S_DAV (4<<I2S_SF_SERIAL_FORMAT_SHIFT)
141# define I2S_SF_SERIAL_FORMAT_I2S_SILABS (5<<I2S_SF_SERIAL_FORMAT_SHIFT)
142/* unknown */
143# define I2S_SF_EXT_SAMPLE_FREQ_INT_SHIFT 12
144# define I2S_SF_EXT_SAMPLE_FREQ_INT_MASK (0xF<<I2S_SF_SAMPLE_FREQ_INT_SHIFT)
145/* probably gives external frequency? */
146# define I2S_SF_EXT_SAMPLE_FREQ_MASK 0xFFF
147
148/* used to send codec messages, but how isn't clear */
149#define I2S_REG_CODEC_MSG_OUT 0x20
150
151/* used to receive codec messages, but how isn't clear */
152#define I2S_REG_CODEC_MSG_IN 0x30
153
154/* frame count reg isn't clear to me yet, but probably useful */
155#define I2S_REG_FRAME_COUNT 0x40
156
157/* program to some value, and get interrupt if frame count reaches it */
158#define I2S_REG_FRAME_MATCH 0x50
159
160/* this register describes how the bus transfers data */
161#define I2S_REG_DATA_WORD_SIZES 0x60
162/* number of interleaved input channels */
163# define I2S_DWS_NUM_CHANNELS_IN_SHIFT 24
164# define I2S_DWS_NUM_CHANNELS_IN_MASK (0x1F<<I2S_DWS_NUM_CHANNELS_IN_SHIFT)
165/* word size of input data */
166# define I2S_DWS_DATA_IN_SIZE_SHIFT 16
167# define I2S_DWS_DATA_IN_16BIT (0<<I2S_DWS_DATA_IN_SIZE_SHIFT)
168# define I2S_DWS_DATA_IN_24BIT (3<<I2S_DWS_DATA_IN_SIZE_SHIFT)
169/* number of interleaved output channels */
170# define I2S_DWS_NUM_CHANNELS_OUT_SHIFT 8
171# define I2S_DWS_NUM_CHANNELS_OUT_MASK (0x1F<<I2S_DWS_NUM_CHANNELS_OUT_SHIFT)
172/* word size of output data */
173# define I2S_DWS_DATA_OUT_SIZE_SHIFT 0
174# define I2S_DWS_DATA_OUT_16BIT (0<<I2S_DWS_DATA_OUT_SIZE_SHIFT)
175# define I2S_DWS_DATA_OUT_24BIT (3<<I2S_DWS_DATA_OUT_SIZE_SHIFT)
176
177
178/* unknown */
179#define I2S_REG_PEAK_LEVEL_SEL 0x70
180
181/* unknown */
182#define I2S_REG_PEAK_LEVEL_IN0 0x80
183
184/* unknown */
185#define I2S_REG_PEAK_LEVEL_IN1 0x90
186
187#endif /* __I2SBUS_INTERFACE_H */
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
new file mode 100644
index 00000000000..3049015a04f
--- /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
20static 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
36static 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
74static 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
224static 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
248static 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
254static int i2sbus_hw_free(struct snd_pcm_substream *substream)
255{
256 snd_pcm_lib_free_pages(substream);
257 return 0;
258}
259
260static 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
438static struct dbdma_cmd STOP_CMD = {
439 .command = __constant_cpu_to_le16(DBDMA_STOP),
440};
441
442static 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
567static 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
583static 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
645irqreturn_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
651irqreturn_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
657static 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
667static 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
682static 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
693static 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
704static 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
716static 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
727static 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
737static 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
752static 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
763static 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
774static 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
786static 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
797static 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 */
816int
817i2sbus_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
1001void 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}
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h
new file mode 100644
index 00000000000..cfa5162e3b0
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus.h
@@ -0,0 +1,112 @@
1/*
2 * i2sbus driver -- private definitions
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPL v2, can be found in COPYING.
7 */
8#ifndef __I2SBUS_H
9#define __I2SBUS_H
10#include <asm/dbdma.h>
11#include <linux/interrupt.h>
12#include <sound/pcm.h>
13#include <linux/spinlock.h>
14#include <linux/mutex.h>
15#include <asm/prom.h>
16#include "i2sbus-interface.h"
17#include "i2sbus-control.h"
18#include "../soundbus.h"
19
20struct i2sbus_control {
21 volatile struct i2s_control_regs __iomem *controlregs;
22 struct resource rsrc;
23 struct list_head list;
24};
25
26#define MAX_DBDMA_COMMANDS 32
27
28struct dbdma_command_mem {
29 dma_addr_t bus_addr;
30 dma_addr_t bus_cmd_start;
31 struct dbdma_cmd *cmds;
32 void *space;
33 int size;
34 u32 running:1;
35};
36
37struct pcm_info {
38 u32 created:1, /* has this direction been created with alsa? */
39 active:1; /* is this stream active? */
40 /* runtime information */
41 struct snd_pcm_substream *substream;
42 int current_period;
43 u32 frame_count;
44 struct dbdma_command_mem dbdma_ring;
45 volatile struct dbdma_regs __iomem *dbdma;
46};
47
48struct i2sbus_dev {
49 struct soundbus_dev sound;
50 struct macio_dev *macio;
51 struct i2sbus_control *control;
52 volatile struct i2s_interface_regs __iomem *intfregs;
53
54 struct resource resources[3];
55 struct resource *allocated_resource[3];
56 int interrupts[3];
57 char rnames[3][32];
58
59 /* info about currently active substreams */
60 struct pcm_info out, in;
61 snd_pcm_format_t format;
62 unsigned int rate;
63
64 /* list for a single controller */
65 struct list_head item;
66 /* number of bus on controller */
67 int bus_number;
68 /* for use by control layer */
69 struct pmf_function *enable,
70 *cell_enable,
71 *cell_disable,
72 *clock_enable,
73 *clock_disable;
74
75 /* locks */
76 /* spinlock for low-level interrupt locking */
77 spinlock_t low_lock;
78 /* mutex for high-level consistency */
79 struct mutex lock;
80};
81
82#define soundbus_dev_to_i2sbus_dev(sdev) \
83 container_of(sdev, struct i2sbus_dev, sound)
84
85/* pcm specific functions */
86extern int
87i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
88 struct codec_info *ci, void *data);
89extern void
90i2sbus_detach_codec(struct soundbus_dev *dev, void *data);
91extern irqreturn_t
92i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs);
93extern irqreturn_t
94i2sbus_rx_intr(int irq, void *devid, struct pt_regs *regs);
95
96/* control specific functions */
97extern int i2sbus_control_init(struct macio_dev* dev,
98 struct i2sbus_control **c);
99extern void i2sbus_control_destroy(struct i2sbus_control *c);
100extern int i2sbus_control_add_dev(struct i2sbus_control *c,
101 struct i2sbus_dev *i2sdev);
102extern void i2sbus_control_remove_dev(struct i2sbus_control *c,
103 struct i2sbus_dev *i2sdev);
104extern int i2sbus_control_enable(struct i2sbus_control *c,
105 struct i2sbus_dev *i2sdev);
106extern int i2sbus_control_cell(struct i2sbus_control *c,
107 struct i2sbus_dev *i2sdev,
108 int enable);
109extern int i2sbus_control_clock(struct i2sbus_control *c,
110 struct i2sbus_dev *i2sdev,
111 int enable);
112#endif /* __I2SBUS_H */