Fixed warnings in AHI code (Part 2).
[AROS.git] / workbench / devs / AHI / Drivers / Envy24HT / ak_codec.c
blobf0d09187c7a888650bf9badc3b07831df4672456
1 /*
2 Copyright © 2005-2013, Davy Wentzler. All rights reserved.
3 $Id$
4 */
6 #include <proto/exec.h>
7 #include <proto/dos.h>
8 #include <proto/expansion.h>
9 #include "DriverData.h"
10 #include "ak_codec.h"
11 #include "regs.h"
12 #include "misc.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)
23 unsigned int tmp;
24 int idx;
25 unsigned int addrdata = 0;
26 unsigned long base = card->iobase;
28 if (codec->newflag)
30 akm4xxx_write_new(card, codec, chip, addr, data);
31 return;
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;
41 if (codec->cif)
43 tmp |= codec->csmask;
45 else
47 tmp &= ~codec->csmask; // cs down
48 SetGPIOData(card, base, tmp); // set CS low
51 MicroDelay(1);
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--) {
60 /* drop clock */
61 tmp &= ~codec->clockmask;
62 SetGPIOData(card, base, tmp);
63 MicroDelay(1);
65 /* set data */
66 if (addrdata & (1 << idx))
67 tmp |= codec->datamask;
68 else
69 tmp &= ~codec->datamask;
71 SetGPIOData(card, base, tmp);
72 MicroDelay(1);
74 /* raise clock */
75 tmp |= codec->clockmask;
76 SetGPIOData(card, base, tmp);
77 MicroDelay(1);
80 /* assert a cs pulse to trigger */
81 //tmp &= ~codec->clockmask;
83 if (codec->cif)
85 tmp &= ~codec->csmask;
86 SetGPIOData(card, base, tmp);
87 MicroDelay(1);
90 tmp |= codec->csmask;
91 SetGPIOData(card, base, tmp);
92 MicroDelay(1);
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)
99 unsigned int tmp;
100 int idx;
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) {
110 if (priv->cif) {
111 tmp |= priv->csmask; /* start without chip select */
112 } else {
113 tmp &= ~priv->csmask; /* chip select low */
114 SetGPIOData(card, base, tmp);
115 MicroDelay(1);
117 } else {
118 /* doesn't handle cf=1 yet */
119 tmp &= ~priv->csmask;
120 tmp |= priv->csaddr;
121 SetGPIOData(card, base, tmp);
122 MicroDelay(1);
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--) {
132 /* drop clock */
133 tmp &= ~priv->clockmask;
134 SetGPIOData(card, base, tmp);
135 MicroDelay(1);
137 /* set data */
138 if (addrdata & (1 << idx))
139 tmp |= priv->datamask;
140 else
141 tmp &= ~priv->datamask;
143 SetGPIOData(card, base, tmp);
144 MicroDelay(1);
146 /* raise clock */
147 tmp |= priv->clockmask;
148 SetGPIOData(card, base, tmp);
149 MicroDelay(1);
152 if (priv->csmask == priv->csaddr)
154 if (priv->cif) {
155 tmp &= ~priv->csmask;
156 SetGPIOData(card, base, tmp);
157 MicroDelay(1);
159 tmp |= priv->csmask;
161 else {
162 tmp &= ~priv->csmask;
163 tmp |= priv->csnone;
166 SetGPIOData(card, base, tmp);
167 MicroDelay(1);
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 */
182 0xff, 0xff
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 */
192 0xff, 0xff
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 */
208 0xff, 0xff
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 */
231 0xff, 0xff
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 */
238 0x01, 0x01,
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 */
251 0x0d, 0xFF,
252 0xff, 0xff
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 */
260 0xff, 0xff
263 static unsigned char inits_ak5365[] = {
264 0x00, 0x00, /* power down */
265 0x00, 0x01, /* power up */
266 0x01, 0x01, /* 1 = line in */
267 0x02, 0x08,
268 0x03, 0x00, /* */
269 0x04, 0x80, /* gain 0 dB */
270 0x05, 0x80, /* gain 0 dB */
271 0xff, 0xff
275 * initialize all the ak4xxx chips
277 void Init_akm4xxx(struct CardData *card, struct akm_codec *codec)
280 int chip, num_chips;
281 unsigned char *ptr, reg, data, *inits;
283 switch (codec->type) {
284 case AKM4524:
285 inits = inits_ak4524;
286 num_chips = 1;
287 break;
288 case AKM4528:
289 inits = inits_ak4528;
290 num_chips = 8 / 2;
291 break;
292 case AKM4529:
293 inits = inits_ak4529;
294 num_chips = 1;
295 break;
296 case AKM4355:
297 inits = inits_ak4355;
298 num_chips = 1;
299 break;
300 case AKM4358:
301 inits = inits_ak4358;
302 num_chips = 1;
303 break;
304 case AKM4381:
305 inits = inits_ak4381;
306 num_chips = 8 / 2;
307 break;
309 case AKM5365:
310 inits = inits_ak5365;
311 num_chips = 1;
312 break;
313 default:
314 inits = inits_ak4524;
315 num_chips = 8 / 2;
316 return;
319 #if 1
320 num_chips = 1;
321 #endif
322 for (chip = 0; chip < num_chips; chip++) {
323 ptr = inits;
324 while (*ptr != 0xff) {
325 reg = *ptr++;
326 data = *ptr++;
327 akm4xxx_write(card, codec, 0, reg, data);
328 MicroDelay(5);
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)
342 #if 0
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;
348 uinfo->count = 1;
349 uinfo->value.integer.min = 0;
350 uinfo->value.integer.max = mask;
351 return 0;
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;
364 return 0;
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);
375 int change;
377 if (invert)
378 nval = mask - nval;
379 change = akm4xxx_get(ak, chip, addr) != nval;
380 if (change)
381 akm4xxx_write(ak, chip, addr, nval);
382 return change;
385 static int akm4xxx_ipga_gain_info(kcontrol_t *kcontrol, ctl_elem_info_t * uinfo)
387 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
388 uinfo->count = 1;
389 uinfo->value.integer.min = 0;
390 uinfo->value.integer.max = 36;
391 return 0;
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;
400 return 0;
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;
410 if (change)
411 akm4xxx_write(ak, chip, addr, nval);
412 return change;
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;
421 uinfo->count = 1;
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]);
426 return 0;
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;
436 return 0;
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;
446 int change;
448 nval = (nval << shift) | (akm4xxx_get(ak, chip, addr) & ~(3 << shift));
449 change = akm4xxx_get(ak, chip, addr) != nval;
450 if (change)
451 akm4xxx_write(ak, chip, addr, nval);
452 return change;
456 * build AK4xxx controls
459 int akm4xxx_build_controls(akm4xxx_t *ak)
461 unsigned int idx, num_emphs;
462 int err;
464 for (idx = 0; idx < ak->num_dacs; ++idx) {
465 kcontrol_t ctl;
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;
470 ctl.count = 1;
471 ctl.info = akm4xxx_volume_info;
472 ctl.get = akm4xxx_volume_get;
473 ctl.put = akm4xxx_volume_put;
474 switch (ak->type) {
475 case AK4524:
476 ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); /* register 6 & 7 */
477 break;
478 case AK4528:
479 ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */
480 break;
481 case AK4529: {
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;
484 break;
486 case AK4355:
487 ctl.private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */
488 break;
489 case AK4381:
490 ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); /* register 3 & 4 */
491 break;
492 default:
493 return -EINVAL;
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)
497 return err;
499 for (idx = 0; idx < ak->num_adcs && ak->type == AK4524; ++idx) {
500 kcontrol_t ctl;
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;
505 ctl.count = 1;
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)
512 return err;
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;
517 ctl.count = 1;
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)
524 return err;
526 if (ak->type == AK4355)
527 num_emphs = 1;
528 else
529 num_emphs = ak->num_dacs / 2;
530 for (idx = 0; idx < num_emphs; idx++) {
531 kcontrol_t ctl;
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;
536 ctl.count = 1;
537 ctl.info = akm4xxx_deemphasis_info;
538 ctl.get = akm4xxx_deemphasis_get;
539 ctl.put = akm4xxx_deemphasis_put;
540 switch (ak->type) {
541 case AK4524:
542 case AK4528:
543 ctl.private_value = AK_COMPOSE(idx, 3, 0, 0); /* register 3 */
544 break;
545 case AK4529: {
546 int shift = idx == 3 ? 6 : (2 - idx) * 2;
547 ctl.private_value = AK_COMPOSE(0, 8, shift, 0); /* register 8 with shift */
548 break;
550 case AK4355:
551 ctl.private_value = AK_COMPOSE(idx, 3, 0, 0);
552 break;
553 case AK4381:
554 ctl.private_value = AK_COMPOSE(idx, 1, 1, 0);
555 break;
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)
559 return err;
561 return 0;
564 static int __init alsa_akm4xxx_module_init(void)
566 return 0;
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);
580 #endif