2 Copyright © 2005-2013, Davy Wentzler. All rights reserved.
6 #include <proto/exec.h>
8 #include <proto/expansion.h>
9 #include "DriverData.h"
15 #define snd_akm4xxx_get(ak,chip,reg) (ak)->images[(chip) * 16 + (reg)]
16 #define snd_akm4xxx_set(ak,chip,reg,val) ((ak)->images[(chip) * 16 + (reg)] = (val))
17 #define snd_akm4xxx_get_ipga(ak,chip,reg) (ak)->ipga_gain[chip][(reg)-4]
18 #define snd_akm4xxx_set_ipga(ak,chip,reg,val) ((ak)->ipga_gain[chip][(reg)-4] = (val))
21 void akm4xxx_write(struct CardData
*card
, struct akm_codec
*codec
, int chip
, unsigned char addr
, unsigned char data
)
25 unsigned int addrdata
= 0;
26 unsigned long base
= card
->iobase
;
30 akm4xxx_write_new(card
, codec
, chip
, addr
, data
);
34 //DEBUGPRINTF("AKM: m = %x, %x, data = %x\n", INBYTE(base + 0x1F), INWORD(base + 0x16), data);
35 //DEBUGPRINTF("AKM: %x, %x\n", addr, data);
37 tmp
= GetGPIOData(card
, base
);
39 tmp
|= codec
->addflags
;
47 tmp
&= ~codec
->csmask
; // cs down
48 SetGPIOData(card
, base
, tmp
); // set CS low
54 /* build I2C address + data byte */
55 addrdata
= (codec
->caddr
<< 6) | 0x20 | (addr
& 0x1f); // Chip Address in C1/C0 | r/w bit on (=write) | address & 5 left over bit positions
56 addrdata
= (addrdata
<< 8) | data
;
58 for (idx
= 15; idx
>= 0; idx
--) {
61 tmp
&= ~codec
->clockmask
;
62 SetGPIOData(card
, base
, tmp
);
66 if (addrdata
& (1 << idx
))
67 tmp
|= codec
->datamask
;
69 tmp
&= ~codec
->datamask
;
71 SetGPIOData(card
, base
, tmp
);
75 tmp
|= codec
->clockmask
;
76 SetGPIOData(card
, base
, tmp
);
80 /* assert a cs pulse to trigger */
81 //tmp &= ~codec->clockmask;
85 tmp
&= ~codec
->csmask
;
86 SetGPIOData(card
, base
, tmp
);
91 SetGPIOData(card
, base
, tmp
);
96 // with alsa-like flags
97 void akm4xxx_write_new(struct CardData
*card
, struct akm_codec
*priv
, int chip
, unsigned char addr
, unsigned char data
)
101 unsigned int addrdata
= 0;
102 unsigned long base
= card
->iobase
;
104 //DEBUGPRINTF("AKM: %x, %x\n", addr, data);
106 tmp
= GetGPIOData(card
, base
);
107 tmp
|= priv
->addflags
;
108 tmp
&= ~priv
->totalmask
;
109 if (priv
->csmask
== priv
->csaddr
) {
111 tmp
|= priv
->csmask
; /* start without chip select */
113 tmp
&= ~priv
->csmask
; /* chip select low */
114 SetGPIOData(card
, base
, tmp
);
118 /* doesn't handle cf=1 yet */
119 tmp
&= ~priv
->csmask
;
121 SetGPIOData(card
, base
, tmp
);
126 /* build I2C address + data byte */
127 addrdata
= (priv
->caddr
<< 6) | 0x20 | (addr
& 0x1f); // Chip Address in C1/C0 | r/w bit on (=write) | address & 5 left over bit positions
128 addrdata
= (addrdata
<< 8) | data
;
130 for (idx
= 15; idx
>= 0; idx
--) {
133 tmp
&= ~priv
->clockmask
;
134 SetGPIOData(card
, base
, tmp
);
138 if (addrdata
& (1 << idx
))
139 tmp
|= priv
->datamask
;
141 tmp
&= ~priv
->datamask
;
143 SetGPIOData(card
, base
, tmp
);
147 tmp
|= priv
->clockmask
;
148 SetGPIOData(card
, base
, tmp
);
152 if (priv
->csmask
== priv
->csaddr
)
155 tmp
&= ~priv
->csmask
;
156 SetGPIOData(card
, base
, tmp
);
162 tmp
&= ~priv
->csmask
;
166 SetGPIOData(card
, base
, tmp
);
170 static unsigned char inits_ak4524
[] = {
171 0x00, 0x07, /* 0: all power up */
172 0x01, 0x00, /* 1: ADC/DAC reset */
173 0x02, 0x60, /* 2: 24bit I2S */
174 0x03, 0x19, /* 3: deemphasis off */
175 0x01, 0x03, /* 1: ADC/DAC enable */
176 0x04, 0x00, /* 4: ADC left muted */
177 0x05, 0x00, /* 5: ADC right muted */
178 0x04, 0x80, /* 4: ADC IPGA gain 0dB */
179 0x05, 0x80, /* 5: ADC IPGA gain 0dB */
180 0x06, 0x7E, /* 6: DAC left muted */
181 0x07, 0x7E, /* 7: DAC right muted */
184 static unsigned char inits_ak4528
[] = {
185 0x00, 0x07, /* 0: all power up */
186 0x01, 0x00, /* 1: ADC/DAC reset */
187 0x02, 0x60, /* 2: 24bit I2S */
188 0x03, 0x0d, /* 3: deemphasis off, turn LR highpass filters on */
189 0x01, 0x03, /* 1: ADC/DAC enable */
190 0x04, 0x00, /* 4: ADC left muted */
191 0x05, 0x00, /* 5: ADC right muted */
194 static unsigned char inits_ak4529
[] = {
195 0x09, 0x01, /* 9: ATS=0, RSTN=1 */
196 0x0a, 0x3f, /* A: all power up, no zero/overflow detection */
197 0x00, 0x0c, /* 0: TDM=0, 24bit I2S, SMUTE=0 */
198 0x01, 0x00, /* 1: ACKS=0, ADC, loop off */
199 0x02, 0xff, /* 2: LOUT1 muted */
200 0x03, 0xff, /* 3: ROUT1 muted */
201 0x04, 0xff, /* 4: LOUT2 muted */
202 0x05, 0xff, /* 5: ROUT2 muted */
203 0x06, 0xff, /* 6: LOUT3 muted */
204 0x07, 0xff, /* 7: ROUT3 muted */
205 0x0b, 0xff, /* B: LOUT4 muted */
206 0x0c, 0xff, /* C: ROUT4 muted */
207 0x08, 0x55, /* 8: deemphasis all off */
210 static unsigned char inits_ak4355
[] = {
211 0x01, 0x03, // soft mute, no reset
212 0x03, 0x00, // vol mute
213 0x04, 0x00, // vol mute
214 0x02, 0x01, // power down dacs
216 0x01, 0x02, // soft mute + reset
217 0x01, 0x03, // soft mute, no reset
219 0x00, 0x87, // auto + I2S + no reset
220 0x01, 0x01, // soft mute off
221 0x02, 0x1F, /* double speed + all DAC's power up */
222 0x03, 0x00, /* 3: de-emphasis 44.1 kHz */
224 0x04, 0xFF, /* 4: LOUT1 volume */
225 0x05, 0xFF, /* 5: ROUT1 volume */
226 0x06, 0xFF, /* 6: LOUT2 volume */
227 0x07, 0xFF, /* 7: ROUT2 volume */
228 0x08, 0xFF, /* 8: LOUT3 volume */
229 0x09, 0xFF, /* 9: ROUT3 volume */
230 0x0a, 0x00, /* a: DATT speed=0, ignore DZF */
235 static unsigned char inits_ak4358
[] = {
236 0x01, 0x02, /* 1: reset and soft-mute */
237 0x00, 0x87, /* 0: mode3(i2s), auto-clock detect, disable DZF, sharp roll-off, RSTN#=0 */
239 0x02, 0x4F, /* 2: DA's power up, normal speed, RSTN#=0 */
240 // 0x02, 0x2e, /* quad speed */
241 0x03, 0x01, /* 3: de-emphasis off */
242 0x04, 0xFF, /* 4: LOUT1 volume */
243 0x05, 0xFF, /* 5: ROUT1 volume */
244 0x06, 0xFF, /* 6: LOUT2 volume */
245 0x07, 0xFF, /* 7: ROUT2 volume */
246 0x08, 0xFF, /* 8: LOUT3 volume */
247 0x09, 0xFF, /* 9: ROUT3 volume */
248 0x0b, 0x00, /* b: LOUT4 volume */
249 0x0c, 0x00, /* c: ROUT4 volume */
250 0x0a, 0x00, /* a: DATT speed=0, ignore DZF */
254 static unsigned char inits_ak4381
[] = {
255 0x00, 0x00, // power down
256 0x00, 0x8F, /* 0: mode3(i2s), auto-clock detect, power up */
257 0x01, 0x08, // de-emphases on 44.1 KHz, double speed
258 0x03, 0xFF, /* 3: LATT 0 */
259 0x04, 0xFF, /* 4: RATT 0 */
263 static unsigned char inits_ak5365
[] = {
264 0x00, 0x00, /* power down */
265 0x00, 0x01, /* power up */
266 0x01, 0x01, /* 1 = line in */
269 0x04, 0x80, /* gain 0 dB */
270 0x05, 0x80, /* gain 0 dB */
275 * initialize all the ak4xxx chips
277 void Init_akm4xxx(struct CardData
*card
, struct akm_codec
*codec
)
281 unsigned char *ptr
, reg
, data
, *inits
;
283 switch (codec
->type
) {
285 inits
= inits_ak4524
;
289 inits
= inits_ak4528
;
293 inits
= inits_ak4529
;
297 inits
= inits_ak4355
;
301 inits
= inits_ak4358
;
305 inits
= inits_ak4381
;
310 inits
= inits_ak5365
;
314 inits
= inits_ak4524
;
322 for (chip
= 0; chip
< num_chips
; chip
++) {
324 while (*ptr
!= 0xff) {
327 akm4xxx_write(card
, codec
, 0, reg
, data
);
333 #define AK_GET_CHIP(val) (((val) >> 8) & 0xff)
334 #define AK_GET_ADDR(val) ((val) & 0xff)
335 #define AK_GET_SHIFT(val) (((val) >> 16) & 0x7f)
336 #define AK_GET_INVERT(val) (((val) >> 23) & 1)
337 #define AK_GET_MASK(val) (((val) >> 24) & 0xff)
338 #define AK_COMPOSE(chip,addr,shift,mask) (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24))
339 #define AK_INVERT (1<<23)
343 static int akm4xxx_volume_info(kcontrol_t
*kcontrol
, ctl_elem_info_t
* uinfo
)
345 unsigned int mask
= AK_GET_MASK(kcontrol
->private_value
);
347 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
349 uinfo
->value
.integer
.min
= 0;
350 uinfo
->value
.integer
.max
= mask
;
354 static int akm4xxx_volume_get(kcontrol_t
*kcontrol
, ctl_elem_value_t
*ucontrol
)
356 akm4xxx_t
*ak
= _kcontrol_chip(kcontrol
);
357 int chip
= AK_GET_CHIP(kcontrol
->private_value
);
358 int addr
= AK_GET_ADDR(kcontrol
->private_value
);
359 int invert
= AK_GET_INVERT(kcontrol
->private_value
);
360 unsigned int mask
= AK_GET_MASK(kcontrol
->private_value
);
361 unsigned char val
= akm4xxx_get(ak
, chip
, addr
);
363 ucontrol
->value
.integer
.value
[0] = invert
? mask
- val
: val
;
367 static int akm4xxx_volume_put(kcontrol_t
*kcontrol
, ctl_elem_value_t
*ucontrol
)
369 akm4xxx_t
*ak
= _kcontrol_chip(kcontrol
);
370 int chip
= AK_GET_CHIP(kcontrol
->private_value
);
371 int addr
= AK_GET_ADDR(kcontrol
->private_value
);
372 int invert
= AK_GET_INVERT(kcontrol
->private_value
);
373 unsigned int mask
= AK_GET_MASK(kcontrol
->private_value
);
374 unsigned char nval
= ucontrol
->value
.integer
.value
[0] % (mask
+1);
379 change
= akm4xxx_get(ak
, chip
, addr
) != nval
;
381 akm4xxx_write(ak
, chip
, addr
, nval
);
385 static int akm4xxx_ipga_gain_info(kcontrol_t
*kcontrol
, ctl_elem_info_t
* uinfo
)
387 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
389 uinfo
->value
.integer
.min
= 0;
390 uinfo
->value
.integer
.max
= 36;
394 static int akm4xxx_ipga_gain_get(kcontrol_t
*kcontrol
, ctl_elem_value_t
*ucontrol
)
396 akm4xxx_t
*ak
= _kcontrol_chip(kcontrol
);
397 int chip
= AK_GET_CHIP(kcontrol
->private_value
);
398 int addr
= AK_GET_ADDR(kcontrol
->private_value
);
399 ucontrol
->value
.integer
.value
[0] = akm4xxx_get_ipga(ak
, chip
, addr
) & 0x7f;
403 static int akm4xxx_ipga_gain_put(kcontrol_t
*kcontrol
, ctl_elem_value_t
*ucontrol
)
405 akm4xxx_t
*ak
= _kcontrol_chip(kcontrol
);
406 int chip
= AK_GET_CHIP(kcontrol
->private_value
);
407 int addr
= AK_GET_ADDR(kcontrol
->private_value
);
408 unsigned char nval
= (ucontrol
->value
.integer
.value
[0] % 37) | 0x80;
409 int change
= akm4xxx_get_ipga(ak
, chip
, addr
) != nval
;
411 akm4xxx_write(ak
, chip
, addr
, nval
);
415 static int akm4xxx_deemphasis_info(kcontrol_t
*kcontrol
, ctl_elem_info_t
*uinfo
)
417 static char *texts
[4] = {
418 "44.1kHz", "Off", "48kHz", "32kHz",
420 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
422 uinfo
->value
.enumerated
.items
= 4;
423 if (uinfo
->value
.enumerated
.item
>= 4)
424 uinfo
->value
.enumerated
.item
= 3;
425 strcpy(uinfo
->value
.enumerated
.name
, texts
[uinfo
->value
.enumerated
.item
]);
429 static int akm4xxx_deemphasis_get(kcontrol_t
* kcontrol
, ctl_elem_value_t
*ucontrol
)
431 akm4xxx_t
*ak
= _kcontrol_chip(kcontrol
);
432 int chip
= AK_GET_CHIP(kcontrol
->private_value
);
433 int addr
= AK_GET_ADDR(kcontrol
->private_value
);
434 int shift
= AK_GET_SHIFT(kcontrol
->private_value
);
435 ucontrol
->value
.enumerated
.item
[0] = (akm4xxx_get(ak
, chip
, addr
) >> shift
) & 3;
439 static int akm4xxx_deemphasis_put(kcontrol_t
*kcontrol
, ctl_elem_value_t
*ucontrol
)
441 akm4xxx_t
*ak
= _kcontrol_chip(kcontrol
);
442 int chip
= AK_GET_CHIP(kcontrol
->private_value
);
443 int addr
= AK_GET_ADDR(kcontrol
->private_value
);
444 int shift
= AK_GET_SHIFT(kcontrol
->private_value
);
445 unsigned char nval
= ucontrol
->value
.enumerated
.item
[0] & 3;
448 nval
= (nval
<< shift
) | (akm4xxx_get(ak
, chip
, addr
) & ~(3 << shift
));
449 change
= akm4xxx_get(ak
, chip
, addr
) != nval
;
451 akm4xxx_write(ak
, chip
, addr
, nval
);
456 * build AK4xxx controls
459 int akm4xxx_build_controls(akm4xxx_t
*ak
)
461 unsigned int idx
, num_emphs
;
464 for (idx
= 0; idx
< ak
->num_dacs
; ++idx
) {
466 memset(&ctl
, 0, sizeof(ctl
));
467 strcpy(ctl
.id
.name
, "DAC Volume");
468 ctl
.id
.index
= idx
+ ak
->idx_offset
* 2;
469 ctl
.id
.iface
= SNDRV_CTL_ELEM_IFACE_MIXER
;
471 ctl
.info
= akm4xxx_volume_info
;
472 ctl
.get
= akm4xxx_volume_get
;
473 ctl
.put
= akm4xxx_volume_put
;
476 ctl
.private_value
= AK_COMPOSE(idx
/2, (idx
%2) + 6, 0, 127); /* register 6 & 7 */
479 ctl
.private_value
= AK_COMPOSE(idx
/2, (idx
%2) + 4, 0, 127); /* register 4 & 5 */
482 int val
= idx
< 6 ? idx
+ 2 : (idx
- 6) + 0xb; /* registers 2-7 and b,c */
483 ctl
.private_value
= AK_COMPOSE(0, val
, 0, 255) | AK_INVERT
;
487 ctl
.private_value
= AK_COMPOSE(0, idx
+ 4, 0, 255); /* register 4-9, chip #0 only */
490 ctl
.private_value
= AK_COMPOSE(idx
/2, (idx
%2) + 3, 0, 255); /* register 3 & 4 */
495 ctl
.private_data
= ak
;
496 if ((err
= ctl_add(ak
->card
, ctl_new(&ctl
, SNDRV_CTL_ELEM_ACCESS_READ
|SNDRV_CTL_ELEM_ACCESS_WRITE
))) < 0)
499 for (idx
= 0; idx
< ak
->num_adcs
&& ak
->type
== AK4524
; ++idx
) {
501 memset(&ctl
, 0, sizeof(ctl
));
502 strcpy(ctl
.id
.name
, "ADC Volume");
503 ctl
.id
.index
= idx
+ ak
->idx_offset
* 2;
504 ctl
.id
.iface
= SNDRV_CTL_ELEM_IFACE_MIXER
;
506 ctl
.info
= akm4xxx_volume_info
;
507 ctl
.get
= akm4xxx_volume_get
;
508 ctl
.put
= akm4xxx_volume_put
;
509 ctl
.private_value
= AK_COMPOSE(idx
/2, (idx
%2) + 4, 0, 127); /* register 4 & 5 */
510 ctl
.private_data
= ak
;
511 if ((err
= ctl_add(ak
->card
, ctl_new(&ctl
, SNDRV_CTL_ELEM_ACCESS_READ
|SNDRV_CTL_ELEM_ACCESS_WRITE
))) < 0)
513 memset(&ctl
, 0, sizeof(ctl
));
514 strcpy(ctl
.id
.name
, "IPGA Analog Capture Volume");
515 ctl
.id
.index
= idx
+ ak
->idx_offset
* 2;
516 ctl
.id
.iface
= SNDRV_CTL_ELEM_IFACE_MIXER
;
518 ctl
.info
= akm4xxx_ipga_gain_info
;
519 ctl
.get
= akm4xxx_ipga_gain_get
;
520 ctl
.put
= akm4xxx_ipga_gain_put
;
521 ctl
.private_value
= AK_COMPOSE(idx
/2, (idx
%2) + 4, 0, 0); /* register 4 & 5 */
522 ctl
.private_data
= ak
;
523 if ((err
= ctl_add(ak
->card
, ctl_new(&ctl
, SNDRV_CTL_ELEM_ACCESS_READ
|SNDRV_CTL_ELEM_ACCESS_WRITE
))) < 0)
526 if (ak
->type
== AK4355
)
529 num_emphs
= ak
->num_dacs
/ 2;
530 for (idx
= 0; idx
< num_emphs
; idx
++) {
532 memset(&ctl
, 0, sizeof(ctl
));
533 strcpy(ctl
.id
.name
, "Deemphasis");
534 ctl
.id
.index
= idx
+ ak
->idx_offset
;
535 ctl
.id
.iface
= SNDRV_CTL_ELEM_IFACE_MIXER
;
537 ctl
.info
= akm4xxx_deemphasis_info
;
538 ctl
.get
= akm4xxx_deemphasis_get
;
539 ctl
.put
= akm4xxx_deemphasis_put
;
543 ctl
.private_value
= AK_COMPOSE(idx
, 3, 0, 0); /* register 3 */
546 int shift
= idx
== 3 ? 6 : (2 - idx
) * 2;
547 ctl
.private_value
= AK_COMPOSE(0, 8, shift
, 0); /* register 8 with shift */
551 ctl
.private_value
= AK_COMPOSE(idx
, 3, 0, 0);
554 ctl
.private_value
= AK_COMPOSE(idx
, 1, 1, 0);
557 ctl
.private_data
= ak
;
558 if ((err
= ctl_add(ak
->card
, ctl_new(&ctl
, SNDRV_CTL_ELEM_ACCESS_READ
|SNDRV_CTL_ELEM_ACCESS_WRITE
))) < 0)
564 static int __init
alsa_akm4xxx_module_init(void)
569 static void __exit
alsa_akm4xxx_module_exit(void)
573 module_init(alsa_akm4xxx_module_init
)
574 module_exit(alsa_akm4xxx_module_exit
)
576 EXPORT_SYMBOL(akm4xxx_write
);
577 EXPORT_SYMBOL(akm4xxx_reset
);
578 EXPORT_SYMBOL(akm4xxx_init
);
579 EXPORT_SYMBOL(akm4xxx_build_controls
);