aboutsummaryrefslogtreecommitdiffstats
path: root/sound/aoa
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-07-31 20:37:25 -0400
committerPaul Mackerras <paulus@samba.org>2006-07-31 20:37:25 -0400
commit57cad8084e0837e0f2c97da789ec9b3f36809be9 (patch)
treee9c790afb4286f78cb08d9664f58baa7e876fe55 /sound/aoa
parentcb18bd40030c879cd93fef02fd579f74dbab473d (diff)
parent49b1e3ea19b1c95c2f012b8331ffb3b169e4c042 (diff)
Merge branch 'merge'
Diffstat (limited to 'sound/aoa')
-rw-r--r--sound/aoa/Makefile4
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h134
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas.c331
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas.h8
-rw-r--r--sound/aoa/core/snd-aoa-gpio-pmf.c14
-rw-r--r--sound/aoa/fabrics/snd-aoa-fabric-layout.c26
-rw-r--r--sound/aoa/soundbus/core.c22
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-control.c79
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-control.h37
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-core.c129
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus.h18
11 files changed, 645 insertions, 157 deletions
diff --git a/sound/aoa/Makefile b/sound/aoa/Makefile
index d8de3e7df48d..a8c037f908f8 100644
--- a/sound/aoa/Makefile
+++ b/sound/aoa/Makefile
@@ -1,4 +1,4 @@
1obj-$(CONFIG_SND_AOA) += core/ 1obj-$(CONFIG_SND_AOA) += core/
2obj-$(CONFIG_SND_AOA) += codecs/
3obj-$(CONFIG_SND_AOA) += fabrics/
4obj-$(CONFIG_SND_AOA_SOUNDBUS) += soundbus/ 2obj-$(CONFIG_SND_AOA_SOUNDBUS) += soundbus/
3obj-$(CONFIG_SND_AOA) += fabrics/
4obj-$(CONFIG_SND_AOA) += codecs/
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h b/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h
new file mode 100644
index 000000000000..69b61136fd54
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h
@@ -0,0 +1,134 @@
1/*
2 * This file is only included exactly once!
3 *
4 * The tables here are derived from the tas3004 datasheet,
5 * modulo typo corrections and some smoothing...
6 */
7
8#define TAS3004_TREBLE_MIN 0
9#define TAS3004_TREBLE_MAX 72
10#define TAS3004_BASS_MIN 0
11#define TAS3004_BASS_MAX 72
12#define TAS3004_TREBLE_ZERO 36
13#define TAS3004_BASS_ZERO 36
14
15static u8 tas3004_treble_table[] = {
16 150, /* -18 dB */
17 149,
18 148,
19 147,
20 146,
21 145,
22 144,
23 143,
24 142,
25 141,
26 140,
27 139,
28 138,
29 137,
30 136,
31 135,
32 134,
33 133,
34 132,
35 131,
36 130,
37 129,
38 128,
39 127,
40 126,
41 125,
42 124,
43 123,
44 122,
45 121,
46 120,
47 119,
48 118,
49 117,
50 116,
51 115,
52 114, /* 0 dB */
53 113,
54 112,
55 111,
56 109,
57 108,
58 107,
59 105,
60 104,
61 103,
62 101,
63 99,
64 98,
65 96,
66 93,
67 91,
68 89,
69 86,
70 83,
71 81,
72 77,
73 74,
74 71,
75 67,
76 63,
77 59,
78 54,
79 49,
80 44,
81 38,
82 32,
83 26,
84 19,
85 10,
86 4,
87 2,
88 1, /* +18 dB */
89};
90
91static inline u8 tas3004_treble(int idx)
92{
93 return tas3004_treble_table[idx];
94}
95
96/* I only save the difference here to the treble table
97 * so that the binary is smaller...
98 * I have also ignored completely differences of
99 * +/- 1
100 */
101static s8 tas3004_bass_diff_to_treble[] = {
102 2, /* 7 dB, offset 50 */
103 2,
104 2,
105 2,
106 2,
107 1,
108 2,
109 2,
110 2,
111 3,
112 4,
113 4,
114 5,
115 6,
116 7,
117 8,
118 9,
119 10,
120 11,
121 14,
122 13,
123 8,
124 1, /* 18 dB */
125};
126
127static inline u8 tas3004_bass(int idx)
128{
129 u8 result = tas3004_treble_table[idx];
130
131 if (idx >= 50)
132 result += tas3004_bass_diff_to_treble[idx-50];
133 return result;
134}
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c
index 2e39ff6ee349..16c0b6b0a805 100644
--- a/sound/aoa/codecs/snd-aoa-codec-tas.c
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.c
@@ -72,22 +72,29 @@ MODULE_DESCRIPTION("tas codec driver for snd-aoa");
72 72
73#include "snd-aoa-codec-tas.h" 73#include "snd-aoa-codec-tas.h"
74#include "snd-aoa-codec-tas-gain-table.h" 74#include "snd-aoa-codec-tas-gain-table.h"
75#include "snd-aoa-codec-tas-basstreble.h"
75#include "../aoa.h" 76#include "../aoa.h"
76#include "../soundbus/soundbus.h" 77#include "../soundbus/soundbus.h"
77 78
78
79#define PFX "snd-aoa-codec-tas: " 79#define PFX "snd-aoa-codec-tas: "
80 80
81
81struct tas { 82struct tas {
82 struct aoa_codec codec; 83 struct aoa_codec codec;
83 struct i2c_client i2c; 84 struct i2c_client i2c;
84 u32 muted_l:1, muted_r:1, 85 u32 mute_l:1, mute_r:1 ,
85 controls_created:1; 86 controls_created:1 ,
87 drc_enabled:1,
88 hw_enabled:1;
86 u8 cached_volume_l, cached_volume_r; 89 u8 cached_volume_l, cached_volume_r;
87 u8 mixer_l[3], mixer_r[3]; 90 u8 mixer_l[3], mixer_r[3];
91 u8 bass, treble;
88 u8 acr; 92 u8 acr;
93 int drc_range;
89}; 94};
90 95
96static int tas_reset_init(struct tas *tas);
97
91static struct tas *codec_to_tas(struct aoa_codec *codec) 98static struct tas *codec_to_tas(struct aoa_codec *codec)
92{ 99{
93 return container_of(codec, struct tas, codec); 100 return container_of(codec, struct tas, codec);
@@ -101,6 +108,44 @@ static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data)
101 return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data); 108 return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data);
102} 109}
103 110
111static void tas3004_set_drc(struct tas *tas)
112{
113 unsigned char val[6];
114
115 if (tas->drc_enabled)
116 val[0] = 0x50; /* 3:1 above threshold */
117 else
118 val[0] = 0x51; /* disabled */
119 val[1] = 0x02; /* 1:1 below threshold */
120 if (tas->drc_range > 0xef)
121 val[2] = 0xef;
122 else if (tas->drc_range < 0)
123 val[2] = 0x00;
124 else
125 val[2] = tas->drc_range;
126 val[3] = 0xb0;
127 val[4] = 0x60;
128 val[5] = 0xa0;
129
130 tas_write_reg(tas, TAS_REG_DRC, 6, val);
131}
132
133static void tas_set_treble(struct tas *tas)
134{
135 u8 tmp;
136
137 tmp = tas3004_treble(tas->treble);
138 tas_write_reg(tas, TAS_REG_TREBLE, 1, &tmp);
139}
140
141static void tas_set_bass(struct tas *tas)
142{
143 u8 tmp;
144
145 tmp = tas3004_bass(tas->bass);
146 tas_write_reg(tas, TAS_REG_BASS, 1, &tmp);
147}
148
104static void tas_set_volume(struct tas *tas) 149static void tas_set_volume(struct tas *tas)
105{ 150{
106 u8 block[6]; 151 u8 block[6];
@@ -113,8 +158,8 @@ static void tas_set_volume(struct tas *tas)
113 if (left > 177) left = 177; 158 if (left > 177) left = 177;
114 if (right > 177) right = 177; 159 if (right > 177) right = 177;
115 160
116 if (tas->muted_l) left = 0; 161 if (tas->mute_l) left = 0;
117 if (tas->muted_r) right = 0; 162 if (tas->mute_r) right = 0;
118 163
119 /* analysing the volume and mixer tables shows 164 /* analysing the volume and mixer tables shows
120 * that they are similar enough when we shift 165 * that they are similar enough when we shift
@@ -202,7 +247,8 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol,
202 247
203 tas->cached_volume_l = ucontrol->value.integer.value[0]; 248 tas->cached_volume_l = ucontrol->value.integer.value[0];
204 tas->cached_volume_r = ucontrol->value.integer.value[1]; 249 tas->cached_volume_r = ucontrol->value.integer.value[1];
205 tas_set_volume(tas); 250 if (tas->hw_enabled)
251 tas_set_volume(tas);
206 return 1; 252 return 1;
207} 253}
208 254
@@ -230,8 +276,8 @@ static int tas_snd_mute_get(struct snd_kcontrol *kcontrol,
230{ 276{
231 struct tas *tas = snd_kcontrol_chip(kcontrol); 277 struct tas *tas = snd_kcontrol_chip(kcontrol);
232 278
233 ucontrol->value.integer.value[0] = !tas->muted_l; 279 ucontrol->value.integer.value[0] = !tas->mute_l;
234 ucontrol->value.integer.value[1] = !tas->muted_r; 280 ucontrol->value.integer.value[1] = !tas->mute_r;
235 return 0; 281 return 0;
236} 282}
237 283
@@ -240,13 +286,14 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol,
240{ 286{
241 struct tas *tas = snd_kcontrol_chip(kcontrol); 287 struct tas *tas = snd_kcontrol_chip(kcontrol);
242 288
243 if (tas->muted_l == !ucontrol->value.integer.value[0] 289 if (tas->mute_l == !ucontrol->value.integer.value[0]
244 && tas->muted_r == !ucontrol->value.integer.value[1]) 290 && tas->mute_r == !ucontrol->value.integer.value[1])
245 return 0; 291 return 0;
246 292
247 tas->muted_l = !ucontrol->value.integer.value[0]; 293 tas->mute_l = !ucontrol->value.integer.value[0];
248 tas->muted_r = !ucontrol->value.integer.value[1]; 294 tas->mute_r = !ucontrol->value.integer.value[1];
249 tas_set_volume(tas); 295 if (tas->hw_enabled)
296 tas_set_volume(tas);
250 return 1; 297 return 1;
251} 298}
252 299
@@ -294,7 +341,8 @@ static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol,
294 tas->mixer_l[idx] = ucontrol->value.integer.value[0]; 341 tas->mixer_l[idx] = ucontrol->value.integer.value[0];
295 tas->mixer_r[idx] = ucontrol->value.integer.value[1]; 342 tas->mixer_r[idx] = ucontrol->value.integer.value[1];
296 343
297 tas_set_mixer(tas); 344 if (tas->hw_enabled)
345 tas_set_mixer(tas);
298 return 1; 346 return 1;
299} 347}
300 348
@@ -309,9 +357,93 @@ static struct snd_kcontrol_new n##_control = { \
309 .private_value = idx, \ 357 .private_value = idx, \
310} 358}
311 359
312MIXER_CONTROL(pcm1, "PCM1", 0); 360MIXER_CONTROL(pcm1, "PCM", 0);
313MIXER_CONTROL(monitor, "Monitor", 2); 361MIXER_CONTROL(monitor, "Monitor", 2);
314 362
363static int tas_snd_drc_range_info(struct snd_kcontrol *kcontrol,
364 struct snd_ctl_elem_info *uinfo)
365{
366 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
367 uinfo->count = 1;
368 uinfo->value.integer.min = 0;
369 uinfo->value.integer.max = TAS3004_DRC_MAX;
370 return 0;
371}
372
373static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol,
374 struct snd_ctl_elem_value *ucontrol)
375{
376 struct tas *tas = snd_kcontrol_chip(kcontrol);
377
378 ucontrol->value.integer.value[0] = tas->drc_range;
379 return 0;
380}
381
382static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol,
383 struct snd_ctl_elem_value *ucontrol)
384{
385 struct tas *tas = snd_kcontrol_chip(kcontrol);
386
387 if (tas->drc_range == ucontrol->value.integer.value[0])
388 return 0;
389
390 tas->drc_range = ucontrol->value.integer.value[0];
391 if (tas->hw_enabled)
392 tas3004_set_drc(tas);
393 return 1;
394}
395
396static struct snd_kcontrol_new drc_range_control = {
397 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
398 .name = "DRC Range",
399 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
400 .info = tas_snd_drc_range_info,
401 .get = tas_snd_drc_range_get,
402 .put = tas_snd_drc_range_put,
403};
404
405static int tas_snd_drc_switch_info(struct snd_kcontrol *kcontrol,
406 struct snd_ctl_elem_info *uinfo)
407{
408 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
409 uinfo->count = 1;
410 uinfo->value.integer.min = 0;
411 uinfo->value.integer.max = 1;
412 return 0;
413}
414
415static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol,
416 struct snd_ctl_elem_value *ucontrol)
417{
418 struct tas *tas = snd_kcontrol_chip(kcontrol);
419
420 ucontrol->value.integer.value[0] = tas->drc_enabled;
421 return 0;
422}
423
424static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol,
425 struct snd_ctl_elem_value *ucontrol)
426{
427 struct tas *tas = snd_kcontrol_chip(kcontrol);
428
429 if (tas->drc_enabled == ucontrol->value.integer.value[0])
430 return 0;
431
432 tas->drc_enabled = ucontrol->value.integer.value[0];
433 if (tas->hw_enabled)
434 tas3004_set_drc(tas);
435 return 1;
436}
437
438static struct snd_kcontrol_new drc_switch_control = {
439 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
440 .name = "DRC Range Switch",
441 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
442 .info = tas_snd_drc_switch_info,
443 .get = tas_snd_drc_switch_get,
444 .put = tas_snd_drc_switch_put,
445};
446
315static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol, 447static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol,
316 struct snd_ctl_elem_info *uinfo) 448 struct snd_ctl_elem_info *uinfo)
317{ 449{
@@ -346,7 +478,8 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
346 tas->acr |= TAS_ACR_INPUT_B; 478 tas->acr |= TAS_ACR_INPUT_B;
347 if (oldacr == tas->acr) 479 if (oldacr == tas->acr)
348 return 0; 480 return 0;
349 tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); 481 if (tas->hw_enabled)
482 tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
350 return 1; 483 return 1;
351} 484}
352 485
@@ -370,6 +503,89 @@ static struct snd_kcontrol_new capture_source_control = {
370 .put = tas_snd_capture_source_put, 503 .put = tas_snd_capture_source_put,
371}; 504};
372 505
506static int tas_snd_treble_info(struct snd_kcontrol *kcontrol,
507 struct snd_ctl_elem_info *uinfo)
508{
509 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
510 uinfo->count = 1;
511 uinfo->value.integer.min = TAS3004_TREBLE_MIN;
512 uinfo->value.integer.max = TAS3004_TREBLE_MAX;
513 return 0;
514}
515
516static int tas_snd_treble_get(struct snd_kcontrol *kcontrol,
517 struct snd_ctl_elem_value *ucontrol)
518{
519 struct tas *tas = snd_kcontrol_chip(kcontrol);
520
521 ucontrol->value.integer.value[0] = tas->treble;
522 return 0;
523}
524
525static int tas_snd_treble_put(struct snd_kcontrol *kcontrol,
526 struct snd_ctl_elem_value *ucontrol)
527{
528 struct tas *tas = snd_kcontrol_chip(kcontrol);
529
530 if (tas->treble == ucontrol->value.integer.value[0])
531 return 0;
532
533 tas->treble = ucontrol->value.integer.value[0];
534 if (tas->hw_enabled)
535 tas_set_treble(tas);
536 return 1;
537}
538
539static struct snd_kcontrol_new treble_control = {
540 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
541 .name = "Treble",
542 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
543 .info = tas_snd_treble_info,
544 .get = tas_snd_treble_get,
545 .put = tas_snd_treble_put,
546};
547
548static int tas_snd_bass_info(struct snd_kcontrol *kcontrol,
549 struct snd_ctl_elem_info *uinfo)
550{
551 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
552 uinfo->count = 1;
553 uinfo->value.integer.min = TAS3004_BASS_MIN;
554 uinfo->value.integer.max = TAS3004_BASS_MAX;
555 return 0;
556}
557
558static int tas_snd_bass_get(struct snd_kcontrol *kcontrol,
559 struct snd_ctl_elem_value *ucontrol)
560{
561 struct tas *tas = snd_kcontrol_chip(kcontrol);
562
563 ucontrol->value.integer.value[0] = tas->bass;
564 return 0;
565}
566
567static int tas_snd_bass_put(struct snd_kcontrol *kcontrol,
568 struct snd_ctl_elem_value *ucontrol)
569{
570 struct tas *tas = snd_kcontrol_chip(kcontrol);
571
572 if (tas->bass == ucontrol->value.integer.value[0])
573 return 0;
574
575 tas->bass = ucontrol->value.integer.value[0];
576 if (tas->hw_enabled)
577 tas_set_bass(tas);
578 return 1;
579}
580
581static struct snd_kcontrol_new bass_control = {
582 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
583 .name = "Bass",
584 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
585 .info = tas_snd_bass_info,
586 .get = tas_snd_bass_get,
587 .put = tas_snd_bass_put,
588};
373 589
374static struct transfer_info tas_transfers[] = { 590static struct transfer_info tas_transfers[] = {
375 { 591 {
@@ -399,26 +615,67 @@ static int tas_usable(struct codec_info_item *cii,
399static int tas_reset_init(struct tas *tas) 615static int tas_reset_init(struct tas *tas)
400{ 616{
401 u8 tmp; 617 u8 tmp;
618
619 tas->codec.gpio->methods->all_amps_off(tas->codec.gpio);
620 msleep(5);
402 tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); 621 tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0);
403 msleep(1); 622 msleep(5);
404 tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1); 623 tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1);
405 msleep(1); 624 msleep(20);
406 tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); 625 tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0);
407 msleep(1); 626 msleep(10);
408 627 tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio);
409 tas->acr &= ~TAS_ACR_ANALOG_PDOWN;
410 tas->acr |= TAS_ACR_B_MONAUREAL | TAS_ACR_B_MON_SEL_RIGHT;
411 if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
412 return -ENODEV;
413 628
414 tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT; 629 tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT;
415 if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp)) 630 if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp))
416 return -ENODEV; 631 return -ENODEV;
417 632
633 tas->acr |= TAS_ACR_ANALOG_PDOWN | TAS_ACR_B_MONAUREAL |
634 TAS_ACR_B_MON_SEL_RIGHT;
635 if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
636 return -ENODEV;
637
418 tmp = 0; 638 tmp = 0;
419 if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp)) 639 if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp))
420 return -ENODEV; 640 return -ENODEV;
421 641
642 tas3004_set_drc(tas);
643
644 /* Set treble & bass to 0dB */
645 tas->treble = TAS3004_TREBLE_ZERO;
646 tas->bass = TAS3004_BASS_ZERO;
647 tas_set_treble(tas);
648 tas_set_bass(tas);
649
650 tas->acr &= ~TAS_ACR_ANALOG_PDOWN;
651 if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
652 return -ENODEV;
653
654 return 0;
655}
656
657static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock)
658{
659 struct tas *tas = cii->codec_data;
660
661 switch(clock) {
662 case CLOCK_SWITCH_PREPARE_SLAVE:
663 /* Clocks are going away, mute mute mute */
664 tas->codec.gpio->methods->all_amps_off(tas->codec.gpio);
665 tas->hw_enabled = 0;
666 break;
667 case CLOCK_SWITCH_SLAVE:
668 /* Clocks are back, re-init the codec */
669 tas_reset_init(tas);
670 tas_set_volume(tas);
671 tas_set_mixer(tas);
672 tas->hw_enabled = 1;
673 tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio);
674 break;
675 default:
676 /* doesn't happen as of now */
677 return -EINVAL;
678 }
422 return 0; 679 return 0;
423} 680}
424 681
@@ -427,6 +684,7 @@ static int tas_reset_init(struct tas *tas)
427 * our i2c device is suspended, and then take note of that! */ 684 * our i2c device is suspended, and then take note of that! */
428static int tas_suspend(struct tas *tas) 685static int tas_suspend(struct tas *tas)
429{ 686{
687 tas->hw_enabled = 0;
430 tas->acr |= TAS_ACR_ANALOG_PDOWN; 688 tas->acr |= TAS_ACR_ANALOG_PDOWN;
431 tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); 689 tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
432 return 0; 690 return 0;
@@ -438,6 +696,7 @@ static int tas_resume(struct tas *tas)
438 tas_reset_init(tas); 696 tas_reset_init(tas);
439 tas_set_volume(tas); 697 tas_set_volume(tas);
440 tas_set_mixer(tas); 698 tas_set_mixer(tas);
699 tas->hw_enabled = 1;
441 return 0; 700 return 0;
442} 701}
443 702
@@ -463,6 +722,7 @@ static struct codec_info tas_codec_info = {
463 .bus_factor = 64, 722 .bus_factor = 64,
464 .owner = THIS_MODULE, 723 .owner = THIS_MODULE,
465 .usable = tas_usable, 724 .usable = tas_usable,
725 .switch_clock = tas_switch_clock,
466#ifdef CONFIG_PM 726#ifdef CONFIG_PM
467 .suspend = _tas_suspend, 727 .suspend = _tas_suspend,
468 .resume = _tas_resume, 728 .resume = _tas_resume,
@@ -483,6 +743,7 @@ static int tas_init_codec(struct aoa_codec *codec)
483 printk(KERN_ERR PFX "tas failed to initialise\n"); 743 printk(KERN_ERR PFX "tas failed to initialise\n");
484 return -ENXIO; 744 return -ENXIO;
485 } 745 }
746 tas->hw_enabled = 1;
486 747
487 if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, 748 if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev,
488 aoa_get_card(), 749 aoa_get_card(),
@@ -515,6 +776,22 @@ static int tas_init_codec(struct aoa_codec *codec)
515 if (err) 776 if (err)
516 goto error; 777 goto error;
517 778
779 err = aoa_snd_ctl_add(snd_ctl_new1(&drc_range_control, tas));
780 if (err)
781 goto error;
782
783 err = aoa_snd_ctl_add(snd_ctl_new1(&drc_switch_control, tas));
784 if (err)
785 goto error;
786
787 err = aoa_snd_ctl_add(snd_ctl_new1(&treble_control, tas));
788 if (err)
789 goto error;
790
791 err = aoa_snd_ctl_add(snd_ctl_new1(&bass_control, tas));
792 if (err)
793 goto error;
794
518 return 0; 795 return 0;
519 error: 796 error:
520 tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); 797 tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
@@ -548,6 +825,8 @@ static int tas_create(struct i2c_adapter *adapter,
548 tas->i2c.driver = &tas_driver; 825 tas->i2c.driver = &tas_driver;
549 tas->i2c.adapter = adapter; 826 tas->i2c.adapter = adapter;
550 tas->i2c.addr = addr; 827 tas->i2c.addr = addr;
828 /* seems that half is a saner default */
829 tas->drc_range = TAS3004_DRC_MAX / 2;
551 strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1); 830 strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1);
552 831
553 if (i2c_attach_client(&tas->i2c)) { 832 if (i2c_attach_client(&tas->i2c)) {
@@ -564,7 +843,9 @@ static int tas_create(struct i2c_adapter *adapter,
564 if (aoa_codec_register(&tas->codec)) { 843 if (aoa_codec_register(&tas->codec)) {
565 goto detach; 844 goto detach;
566 } 845 }
567 printk(KERN_DEBUG "snd-aoa-codec-tas: created and attached tas instance\n"); 846 printk(KERN_DEBUG
847 "snd-aoa-codec-tas: tas found, addr 0x%02x on %s\n",
848 addr, node->full_name);
568 return 0; 849 return 0;
569 detach: 850 detach:
570 i2c_detach_client(&tas->i2c); 851 i2c_detach_client(&tas->i2c);
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.h b/sound/aoa/codecs/snd-aoa-codec-tas.h
index daf81f45d83a..ae177e3466e6 100644
--- a/sound/aoa/codecs/snd-aoa-codec-tas.h
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.h
@@ -44,4 +44,12 @@
44#define TAS_REG_LEFT_BIQUAD6 0x10 44#define TAS_REG_LEFT_BIQUAD6 0x10
45#define TAS_REG_RIGHT_BIQUAD6 0x19 45#define TAS_REG_RIGHT_BIQUAD6 0x19
46 46
47#define TAS_REG_LEFT_LOUDNESS 0x21
48#define TAS_REG_RIGHT_LOUDNESS 0x22
49#define TAS_REG_LEFT_LOUDNESS_GAIN 0x23
50#define TAS_REG_RIGHT_LOUDNESS_GAIN 0x24
51
52#define TAS3001_DRC_MAX 0x5f
53#define TAS3004_DRC_MAX 0xef
54
47#endif /* __SND_AOA_CODECTASH */ 55#endif /* __SND_AOA_CODECTASH */
diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c
index 0e9b9bb2a6de..3d57fd1aec4b 100644
--- a/sound/aoa/core/snd-aoa-gpio-pmf.c
+++ b/sound/aoa/core/snd-aoa-gpio-pmf.c
@@ -14,9 +14,13 @@
14static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\ 14static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\
15{ \ 15{ \
16 struct pmf_args args = { .count = 1, .u[0].v = !on }; \ 16 struct pmf_args args = { .count = 1, .u[0].v = !on }; \
17 \ 17 int rc; \
18 \
18 if (unlikely(!rt)) return; \ 19 if (unlikely(!rt)) return; \
19 pmf_call_function(rt->node, #name "-mute", &args); \ 20 rc = pmf_call_function(rt->node, #name "-mute", &args); \
21 if (rc) \
22 printk(KERN_WARNING "pmf_gpio_set_" #name \
23 " failed, rc: %d\n", rc); \
20 rt->implementation_private &= ~(1<<bit); \ 24 rt->implementation_private &= ~(1<<bit); \
21 rt->implementation_private |= (!!on << bit); \ 25 rt->implementation_private |= (!!on << bit); \
22} \ 26} \
@@ -33,9 +37,13 @@ PMF_GPIO(lineout, 2);
33static void pmf_gpio_set_hw_reset(struct gpio_runtime *rt, int on) 37static void pmf_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
34{ 38{
35 struct pmf_args args = { .count = 1, .u[0].v = !!on }; 39 struct pmf_args args = { .count = 1, .u[0].v = !!on };
40 int rc;
36 41
37 if (unlikely(!rt)) return; 42 if (unlikely(!rt)) return;
38 pmf_call_function(rt->node, "hw-reset", &args); 43 rc = pmf_call_function(rt->node, "hw-reset", &args);
44 if (rc)
45 printk(KERN_WARNING "pmf_gpio_set_hw_reset"
46 " failed, rc: %d\n", rc);
39} 47}
40 48
41static void pmf_gpio_all_amps_off(struct gpio_runtime *rt) 49static void pmf_gpio_all_amps_off(struct gpio_runtime *rt)
diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
index cbc8a3b5cea4..172eb95476c0 100644
--- a/sound/aoa/fabrics/snd-aoa-fabric-layout.c
+++ b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
@@ -77,24 +77,39 @@ struct layout {
77 int pcmid; 77 int pcmid;
78}; 78};
79 79
80MODULE_ALIAS("sound-layout-36");
80MODULE_ALIAS("sound-layout-41"); 81MODULE_ALIAS("sound-layout-41");
81MODULE_ALIAS("sound-layout-45"); 82MODULE_ALIAS("sound-layout-45");
83MODULE_ALIAS("sound-layout-47");
84MODULE_ALIAS("sound-layout-48");
85MODULE_ALIAS("sound-layout-49");
86MODULE_ALIAS("sound-layout-50");
82MODULE_ALIAS("sound-layout-51"); 87MODULE_ALIAS("sound-layout-51");
88MODULE_ALIAS("sound-layout-56");
89MODULE_ALIAS("sound-layout-57");
83MODULE_ALIAS("sound-layout-58"); 90MODULE_ALIAS("sound-layout-58");
84MODULE_ALIAS("sound-layout-60"); 91MODULE_ALIAS("sound-layout-60");
85MODULE_ALIAS("sound-layout-61"); 92MODULE_ALIAS("sound-layout-61");
93MODULE_ALIAS("sound-layout-62");
86MODULE_ALIAS("sound-layout-64"); 94MODULE_ALIAS("sound-layout-64");
87MODULE_ALIAS("sound-layout-65"); 95MODULE_ALIAS("sound-layout-65");
96MODULE_ALIAS("sound-layout-66");
97MODULE_ALIAS("sound-layout-67");
88MODULE_ALIAS("sound-layout-68"); 98MODULE_ALIAS("sound-layout-68");
89MODULE_ALIAS("sound-layout-69"); 99MODULE_ALIAS("sound-layout-69");
90MODULE_ALIAS("sound-layout-70"); 100MODULE_ALIAS("sound-layout-70");
91MODULE_ALIAS("sound-layout-72"); 101MODULE_ALIAS("sound-layout-72");
102MODULE_ALIAS("sound-layout-76");
92MODULE_ALIAS("sound-layout-80"); 103MODULE_ALIAS("sound-layout-80");
93MODULE_ALIAS("sound-layout-82"); 104MODULE_ALIAS("sound-layout-82");
94MODULE_ALIAS("sound-layout-84"); 105MODULE_ALIAS("sound-layout-84");
95MODULE_ALIAS("sound-layout-86"); 106MODULE_ALIAS("sound-layout-86");
107MODULE_ALIAS("sound-layout-90");
96MODULE_ALIAS("sound-layout-92"); 108MODULE_ALIAS("sound-layout-92");
109MODULE_ALIAS("sound-layout-94");
97MODULE_ALIAS("sound-layout-96"); 110MODULE_ALIAS("sound-layout-96");
111MODULE_ALIAS("sound-layout-98");
112MODULE_ALIAS("sound-layout-100");
98 113
99/* onyx with all but microphone connected */ 114/* onyx with all but microphone connected */
100static struct codec_connection onyx_connections_nomic[] = { 115static struct codec_connection onyx_connections_nomic[] = {
@@ -950,11 +965,12 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
950 layout_id = (unsigned int *) get_property(sound, "layout-id", NULL); 965 layout_id = (unsigned int *) get_property(sound, "layout-id", NULL);
951 if (!layout_id) 966 if (!layout_id)
952 goto outnodev; 967 goto outnodev;
953 printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d ", *layout_id); 968 printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d\n",
969 *layout_id);
954 970
955 layout = find_layout_by_id(*layout_id); 971 layout = find_layout_by_id(*layout_id);
956 if (!layout) { 972 if (!layout) {
957 printk("(no idea how to handle)\n"); 973 printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n");
958 goto outnodev; 974 goto outnodev;
959 } 975 }
960 976
@@ -972,15 +988,17 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
972 case 51: /* PowerBook5,4 */ 988 case 51: /* PowerBook5,4 */
973 case 58: /* Mac Mini */ 989 case 58: /* Mac Mini */
974 ldev->gpio.methods = ftr_gpio_methods; 990 ldev->gpio.methods = ftr_gpio_methods;
991 printk(KERN_DEBUG
992 "snd-aoa-fabric-layout: Using direct GPIOs\n");
975 break; 993 break;
976 default: 994 default:
977 ldev->gpio.methods = pmf_gpio_methods; 995 ldev->gpio.methods = pmf_gpio_methods;
996 printk(KERN_DEBUG
997 "snd-aoa-fabric-layout: Using PMF GPIOs\n");
978 } 998 }
979 ldev->selfptr_headphone.ptr = ldev; 999 ldev->selfptr_headphone.ptr = ldev;
980 ldev->selfptr_lineout.ptr = ldev; 1000 ldev->selfptr_lineout.ptr = ldev;
981 sdev->ofdev.dev.driver_data = ldev; 1001 sdev->ofdev.dev.driver_data = ldev;
982
983 printk("(using)\n");
984 list_add(&ldev->list, &layouts_list); 1002 list_add(&ldev->list, &layouts_list);
985 layouts_list_items++; 1003 layouts_list_items++;
986 1004
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c
index abe84a76c835..47b3e3768df0 100644
--- a/sound/aoa/soundbus/core.c
+++ b/sound/aoa/soundbus/core.c
@@ -194,16 +194,6 @@ static struct bus_type soundbus_bus_type = {
194 .dev_attrs = soundbus_dev_attrs, 194 .dev_attrs = soundbus_dev_attrs,
195}; 195};
196 196
197static int __init soundbus_init(void)
198{
199 return bus_register(&soundbus_bus_type);
200}
201
202static void __exit soundbus_exit(void)
203{
204 bus_unregister(&soundbus_bus_type);
205}
206
207int soundbus_add_one(struct soundbus_dev *dev) 197int soundbus_add_one(struct soundbus_dev *dev)
208{ 198{
209 static int devcount; 199 static int devcount;
@@ -246,5 +236,15 @@ void soundbus_unregister_driver(struct soundbus_driver *drv)
246} 236}
247EXPORT_SYMBOL_GPL(soundbus_unregister_driver); 237EXPORT_SYMBOL_GPL(soundbus_unregister_driver);
248 238
249module_init(soundbus_init); 239static int __init soundbus_init(void)
240{
241 return bus_register(&soundbus_bus_type);
242}
243
244static void __exit soundbus_exit(void)
245{
246 bus_unregister(&soundbus_bus_type);
247}
248
249subsys_initcall(soundbus_init);
250module_exit(soundbus_exit); 250module_exit(soundbus_exit);
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.c b/sound/aoa/soundbus/i2sbus/i2sbus-control.c
index f50407952d3c..87beb4ad4d63 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-control.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.c
@@ -6,12 +6,16 @@
6 * GPL v2, can be found in COPYING. 6 * GPL v2, can be found in COPYING.
7 */ 7 */
8 8
9#include <asm/io.h> 9#include <linux/kernel.h>
10#include <linux/delay.h> 10#include <linux/delay.h>
11
12#include <asm/io.h>
11#include <asm/prom.h> 13#include <asm/prom.h>
12#include <asm/macio.h> 14#include <asm/macio.h>
13#include <asm/pmac_feature.h> 15#include <asm/pmac_feature.h>
14#include <asm/pmac_pfunc.h> 16#include <asm/pmac_pfunc.h>
17#include <asm/keylargo.h>
18
15#include "i2sbus.h" 19#include "i2sbus.h"
16 20
17int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c) 21int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c)
@@ -22,26 +26,12 @@ int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c)
22 26
23 INIT_LIST_HEAD(&(*c)->list); 27 INIT_LIST_HEAD(&(*c)->list);
24 28
25 if (of_address_to_resource(dev->ofdev.node, 0, &(*c)->rsrc)) 29 (*c)->macio = dev->bus->chip;
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; 30 return 0;
36 err:
37 kfree(*c);
38 *c = NULL;
39 return -ENODEV;
40} 31}
41 32
42void i2sbus_control_destroy(struct i2sbus_control *c) 33void i2sbus_control_destroy(struct i2sbus_control *c)
43{ 34{
44 iounmap(c->controlregs);
45 kfree(c); 35 kfree(c);
46} 36}
47 37
@@ -93,19 +83,22 @@ int i2sbus_control_enable(struct i2sbus_control *c,
93 struct i2sbus_dev *i2sdev) 83 struct i2sbus_dev *i2sdev)
94{ 84{
95 struct pmf_args args = { .count = 0 }; 85 struct pmf_args args = { .count = 0 };
96 int cc; 86 struct macio_chip *macio = c->macio;
97 87
98 if (i2sdev->enable) 88 if (i2sdev->enable)
99 return pmf_call_one(i2sdev->enable, &args); 89 return pmf_call_one(i2sdev->enable, &args);
100 90
91 if (macio == NULL || macio->base == NULL)
92 return -ENODEV;
93
101 switch (i2sdev->bus_number) { 94 switch (i2sdev->bus_number) {
102 case 0: 95 case 0:
103 cc = in_le32(&c->controlregs->cell_control); 96 /* these need to be locked or done through
104 out_le32(&c->controlregs->cell_control, cc | CTRL_CLOCK_INTF_0_ENABLE); 97 * newly created feature calls! */
98 MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE);
105 break; 99 break;
106 case 1: 100 case 1:
107 cc = in_le32(&c->controlregs->cell_control); 101 MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_ENABLE);
108 out_le32(&c->controlregs->cell_control, cc | CTRL_CLOCK_INTF_1_ENABLE);
109 break; 102 break;
110 default: 103 default:
111 return -ENODEV; 104 return -ENODEV;
@@ -118,7 +111,7 @@ int i2sbus_control_cell(struct i2sbus_control *c,
118 int enable) 111 int enable)
119{ 112{
120 struct pmf_args args = { .count = 0 }; 113 struct pmf_args args = { .count = 0 };
121 int cc; 114 struct macio_chip *macio = c->macio;
122 115
123 switch (enable) { 116 switch (enable) {
124 case 0: 117 case 0:
@@ -133,18 +126,22 @@ int i2sbus_control_cell(struct i2sbus_control *c,
133 printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n"); 126 printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n");
134 return -ENODEV; 127 return -ENODEV;
135 } 128 }
129
130 if (macio == NULL || macio->base == NULL)
131 return -ENODEV;
132
136 switch (i2sdev->bus_number) { 133 switch (i2sdev->bus_number) {
137 case 0: 134 case 0:
138 cc = in_le32(&c->controlregs->cell_control); 135 if (enable)
139 cc &= ~CTRL_CLOCK_CELL_0_ENABLE; 136 MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);
140 cc |= enable * CTRL_CLOCK_CELL_0_ENABLE; 137 else
141 out_le32(&c->controlregs->cell_control, cc); 138 MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE);
142 break; 139 break;
143 case 1: 140 case 1:
144 cc = in_le32(&c->controlregs->cell_control); 141 if (enable)
145 cc &= ~CTRL_CLOCK_CELL_1_ENABLE; 142 MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);
146 cc |= enable * CTRL_CLOCK_CELL_1_ENABLE; 143 else
147 out_le32(&c->controlregs->cell_control, cc); 144 MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE);
148 break; 145 break;
149 default: 146 default:
150 return -ENODEV; 147 return -ENODEV;
@@ -157,7 +154,7 @@ int i2sbus_control_clock(struct i2sbus_control *c,
157 int enable) 154 int enable)
158{ 155{
159 struct pmf_args args = { .count = 0 }; 156 struct pmf_args args = { .count = 0 };
160 int cc; 157 struct macio_chip *macio = c->macio;
161 158
162 switch (enable) { 159 switch (enable) {
163 case 0: 160 case 0:
@@ -172,18 +169,22 @@ int i2sbus_control_clock(struct i2sbus_control *c,
172 printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n"); 169 printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n");
173 return -ENODEV; 170 return -ENODEV;
174 } 171 }
172
173 if (macio == NULL || macio->base == NULL)
174 return -ENODEV;
175
175 switch (i2sdev->bus_number) { 176 switch (i2sdev->bus_number) {
176 case 0: 177 case 0:
177 cc = in_le32(&c->controlregs->cell_control); 178 if (enable)
178 cc &= ~CTRL_CLOCK_CLOCK_0_ENABLE; 179 MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
179 cc |= enable * CTRL_CLOCK_CLOCK_0_ENABLE; 180 else
180 out_le32(&c->controlregs->cell_control, cc); 181 MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
181 break; 182 break;
182 case 1: 183 case 1:
183 cc = in_le32(&c->controlregs->cell_control); 184 if (enable)
184 cc &= ~CTRL_CLOCK_CLOCK_1_ENABLE; 185 MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);
185 cc |= enable * CTRL_CLOCK_CLOCK_1_ENABLE; 186 else
186 out_le32(&c->controlregs->cell_control, cc); 187 MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT);
187 break; 188 break;
188 default: 189 default:
189 return -ENODEV; 190 return -ENODEV;
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.h b/sound/aoa/soundbus/i2sbus/i2sbus-control.h
deleted file mode 100644
index bb05550f730b..000000000000
--- a/sound/aoa/soundbus/i2sbus/i2sbus-control.h
+++ /dev/null
@@ -1,37 +0,0 @@
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
index 01c0724335a3..23190aa6bc7b 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-core.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
@@ -7,13 +7,16 @@
7 */ 7 */
8 8
9#include <linux/module.h> 9#include <linux/module.h>
10#include <asm/macio.h>
11#include <asm/dbdma.h>
12#include <linux/pci.h> 10#include <linux/pci.h>
13#include <linux/interrupt.h> 11#include <linux/interrupt.h>
12#include <linux/dma-mapping.h>
13
14#include <sound/driver.h> 14#include <sound/driver.h>
15#include <sound/core.h> 15#include <sound/core.h>
16#include <linux/dma-mapping.h> 16
17#include <asm/macio.h>
18#include <asm/dbdma.h>
19
17#include "../soundbus.h" 20#include "../soundbus.h"
18#include "i2sbus.h" 21#include "i2sbus.h"
19 22
@@ -24,6 +27,11 @@ MODULE_DESCRIPTION("Apple Soundbus: I2S support");
24 * string that macio puts into the relevant device */ 27 * string that macio puts into the relevant device */
25MODULE_ALIAS("of:Ni2sTi2sC"); 28MODULE_ALIAS("of:Ni2sTi2sC");
26 29
30static int force;
31module_param(force, int, 0444);
32MODULE_PARM_DESC(force, "Force loading i2sbus even when"
33 " no layout-id property is present");
34
27static struct of_device_id i2sbus_match[] = { 35static struct of_device_id i2sbus_match[] = {
28 { .name = "i2s" }, 36 { .name = "i2s" },
29 { } 37 { }
@@ -73,12 +81,12 @@ static void i2sbus_release_dev(struct device *dev)
73 if (i2sdev->intfregs) iounmap(i2sdev->intfregs); 81 if (i2sdev->intfregs) iounmap(i2sdev->intfregs);
74 if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma); 82 if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma);
75 if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma); 83 if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma);
76 for (i=0;i<3;i++) 84 for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++)
77 if (i2sdev->allocated_resource[i]) 85 if (i2sdev->allocated_resource[i])
78 release_and_free_resource(i2sdev->allocated_resource[i]); 86 release_and_free_resource(i2sdev->allocated_resource[i]);
79 free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring); 87 free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring);
80 free_dbdma_descriptor_ring(i2sdev, &i2sdev->in.dbdma_ring); 88 free_dbdma_descriptor_ring(i2sdev, &i2sdev->in.dbdma_ring);
81 for (i=0;i<3;i++) 89 for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++)
82 free_irq(i2sdev->interrupts[i], i2sdev); 90 free_irq(i2sdev->interrupts[i], i2sdev);
83 i2sbus_control_remove_dev(i2sdev->control, i2sdev); 91 i2sbus_control_remove_dev(i2sdev->control, i2sdev);
84 mutex_destroy(&i2sdev->lock); 92 mutex_destroy(&i2sdev->lock);
@@ -101,10 +109,49 @@ static irqreturn_t i2sbus_bus_intr(int irq, void *devid, struct pt_regs *regs)
101 return IRQ_HANDLED; 109 return IRQ_HANDLED;
102} 110}
103 111
104static int force; 112
105module_param(force, int, 0444); 113/*
106MODULE_PARM_DESC(force, "Force loading i2sbus even when" 114 * XXX FIXME: We test the layout_id's here to get the proper way of
107 " no layout-id property is present"); 115 * mapping in various registers, thanks to bugs in Apple device-trees.
116 * We could instead key off the machine model and the name of the i2s
117 * node (i2s-a). This we'll do when we move it all to macio_asic.c
118 * and have that export items for each sub-node too.
119 */
120static int i2sbus_get_and_fixup_rsrc(struct device_node *np, int index,
121 int layout, struct resource *res)
122{
123 struct device_node *parent;
124 int pindex, rc = -ENXIO;
125 u32 *reg;
126
127 /* Machines with layout 76 and 36 (K2 based) have a weird device
128 * tree what we need to special case.
129 * Normal machines just fetch the resource from the i2s-X node.
130 * Darwin further divides normal machines into old and new layouts
131 * with a subtely different code path but that doesn't seem necessary
132 * in practice, they just bloated it. In addition, even on our K2
133 * case the i2s-modem node, if we ever want to handle it, uses the
134 * normal layout
135 */
136 if (layout != 76 && layout != 36)
137 return of_address_to_resource(np, index, res);
138
139 parent = of_get_parent(np);
140 pindex = (index == aoa_resource_i2smmio) ? 0 : 1;
141 rc = of_address_to_resource(parent, pindex, res);
142 if (rc)
143 goto bail;
144 reg = (u32 *)get_property(np, "reg", NULL);
145 if (reg == NULL) {
146 rc = -ENXIO;
147 goto bail;
148 }
149 res->start += reg[index * 2];
150 res->end = res->start + reg[index * 2 + 1] - 1;
151 bail:
152 of_node_put(parent);
153 return rc;
154}
108 155
109/* FIXME: look at device node refcounting */ 156/* FIXME: look at device node refcounting */
110static int i2sbus_add_dev(struct macio_dev *macio, 157static int i2sbus_add_dev(struct macio_dev *macio,
@@ -113,7 +160,8 @@ static int i2sbus_add_dev(struct macio_dev *macio,
113{ 160{
114 struct i2sbus_dev *dev; 161 struct i2sbus_dev *dev;
115 struct device_node *child = NULL, *sound = NULL; 162 struct device_node *child = NULL, *sound = NULL;
116 int i; 163 struct resource *r;
164 int i, layout = 0, rlen;
117 static const char *rnames[] = { "i2sbus: %s (control)", 165 static const char *rnames[] = { "i2sbus: %s (control)",
118 "i2sbus: %s (tx)", 166 "i2sbus: %s (tx)",
119 "i2sbus: %s (rx)" }; 167 "i2sbus: %s (rx)" };
@@ -129,9 +177,6 @@ static int i2sbus_add_dev(struct macio_dev *macio,
129 if (strncmp(np->name, "i2s-", 4)) 177 if (strncmp(np->name, "i2s-", 4))
130 return 0; 178 return 0;
131 179
132 if (macio_irq_count(macio) != 3)
133 return 0;
134
135 dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL); 180 dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL);
136 if (!dev) 181 if (!dev)
137 return 0; 182 return 0;
@@ -147,8 +192,9 @@ static int i2sbus_add_dev(struct macio_dev *macio,
147 u32 *layout_id; 192 u32 *layout_id;
148 layout_id = (u32*) get_property(sound, "layout-id", NULL); 193 layout_id = (u32*) get_property(sound, "layout-id", NULL);
149 if (layout_id) { 194 if (layout_id) {
195 layout = *layout_id;
150 snprintf(dev->sound.modalias, 32, 196 snprintf(dev->sound.modalias, 32,
151 "sound-layout-%d", *layout_id); 197 "sound-layout-%d", layout);
152 force = 1; 198 force = 1;
153 } 199 }
154 } 200 }
@@ -178,23 +224,32 @@ static int i2sbus_add_dev(struct macio_dev *macio,
178 dev->bus_number = np->name[4] - 'a'; 224 dev->bus_number = np->name[4] - 'a';
179 INIT_LIST_HEAD(&dev->sound.codec_list); 225 INIT_LIST_HEAD(&dev->sound.codec_list);
180 226
181 for (i=0;i<3;i++) { 227 for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) {
182 dev->interrupts[i] = -1; 228 dev->interrupts[i] = -1;
183 snprintf(dev->rnames[i], sizeof(dev->rnames[i]), rnames[i], np->name); 229 snprintf(dev->rnames[i], sizeof(dev->rnames[i]),
230 rnames[i], np->name);
184 } 231 }
185 for (i=0;i<3;i++) { 232 for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) {
186 if (request_irq(macio_irq(macio, i), ints[i], 0, 233 int irq = irq_of_parse_and_map(np, i);
187 dev->rnames[i], dev)) 234 if (request_irq(irq, ints[i], 0, dev->rnames[i], dev))
188 goto err; 235 goto err;
189 dev->interrupts[i] = macio_irq(macio, i); 236 dev->interrupts[i] = irq;
190 } 237 }
191 238
192 for (i=0;i<3;i++) { 239
193 if (of_address_to_resource(np, i, &dev->resources[i])) 240 /* Resource handling is problematic as some device-trees contain
241 * useless crap (ugh ugh ugh). We work around that here by calling
242 * specific functions for calculating the appropriate resources.
243 *
244 * This will all be moved to macio_asic.c at one point
245 */
246 for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) {
247 if (i2sbus_get_and_fixup_rsrc(np,i,layout,&dev->resources[i]))
194 goto err; 248 goto err;
195 /* if only we could use our resource dev->resources[i]... 249 /* If only we could use our resource dev->resources[i]...
196 * but request_resource doesn't know about parents and 250 * but request_resource doesn't know about parents and
197 * contained resources... */ 251 * contained resources...
252 */
198 dev->allocated_resource[i] = 253 dev->allocated_resource[i] =
199 request_mem_region(dev->resources[i].start, 254 request_mem_region(dev->resources[i].start,
200 dev->resources[i].end - 255 dev->resources[i].end -
@@ -205,13 +260,25 @@ static int i2sbus_add_dev(struct macio_dev *macio,
205 goto err; 260 goto err;
206 } 261 }
207 } 262 }
208 /* should do sanity checking here about length of them */ 263
209 dev->intfregs = ioremap(dev->resources[0].start, 264 r = &dev->resources[aoa_resource_i2smmio];
210 dev->resources[0].end-dev->resources[0].start+1); 265 rlen = r->end - r->start + 1;
211 dev->out.dbdma = ioremap(dev->resources[1].start, 266 if (rlen < sizeof(struct i2s_interface_regs))
212 dev->resources[1].end-dev->resources[1].start+1); 267 goto err;
213 dev->in.dbdma = ioremap(dev->resources[2].start, 268 dev->intfregs = ioremap(r->start, rlen);
214 dev->resources[2].end-dev->resources[2].start+1); 269
270 r = &dev->resources[aoa_resource_txdbdma];
271 rlen = r->end - r->start + 1;
272 if (rlen < sizeof(struct dbdma_regs))
273 goto err;
274 dev->out.dbdma = ioremap(r->start, rlen);
275
276 r = &dev->resources[aoa_resource_rxdbdma];
277 rlen = r->end - r->start + 1;
278 if (rlen < sizeof(struct dbdma_regs))
279 goto err;
280 dev->in.dbdma = ioremap(r->start, rlen);
281
215 if (!dev->intfregs || !dev->out.dbdma || !dev->in.dbdma) 282 if (!dev->intfregs || !dev->out.dbdma || !dev->in.dbdma)
216 goto err; 283 goto err;
217 284
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h
index cfa5162e3b0f..0c69d209be50 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus.h
+++ b/sound/aoa/soundbus/i2sbus/i2sbus.h
@@ -7,20 +7,22 @@
7 */ 7 */
8#ifndef __I2SBUS_H 8#ifndef __I2SBUS_H
9#define __I2SBUS_H 9#define __I2SBUS_H
10#include <asm/dbdma.h>
11#include <linux/interrupt.h> 10#include <linux/interrupt.h>
12#include <sound/pcm.h>
13#include <linux/spinlock.h> 11#include <linux/spinlock.h>
14#include <linux/mutex.h> 12#include <linux/mutex.h>
13
14#include <sound/pcm.h>
15
15#include <asm/prom.h> 16#include <asm/prom.h>
17#include <asm/pmac_feature.h>
18#include <asm/dbdma.h>
19
16#include "i2sbus-interface.h" 20#include "i2sbus-interface.h"
17#include "i2sbus-control.h"
18#include "../soundbus.h" 21#include "../soundbus.h"
19 22
20struct i2sbus_control { 23struct i2sbus_control {
21 volatile struct i2s_control_regs __iomem *controlregs;
22 struct resource rsrc;
23 struct list_head list; 24 struct list_head list;
25 struct macio_chip *macio;
24}; 26};
25 27
26#define MAX_DBDMA_COMMANDS 32 28#define MAX_DBDMA_COMMANDS 32
@@ -45,6 +47,12 @@ struct pcm_info {
45 volatile struct dbdma_regs __iomem *dbdma; 47 volatile struct dbdma_regs __iomem *dbdma;
46}; 48};
47 49
50enum {
51 aoa_resource_i2smmio = 0,
52 aoa_resource_txdbdma,
53 aoa_resource_rxdbdma,
54};
55
48struct i2sbus_dev { 56struct i2sbus_dev {
49 struct soundbus_dev sound; 57 struct soundbus_dev sound;
50 struct macio_dev *macio; 58 struct macio_dev *macio;