Jia-Ju Bai 37e23b1cc7 Add the driver for CMI8738 sound card
Change-Id: I5a53e3b8652a014e105ca7c77c42a730f6824307
2017-01-08 18:59:39 +01:00

273 lines
6.8 KiB
C

#include "mixer.h"
#ifdef MIXER_AK4531
u8_t mixer_value[] = {
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08,
0x7e, 0x3d, 0x01, 0x01, 0x00, 0x00, 0x03, 0x00,
0x00, 0x01
};
int get_set_volume(u32_t *base, struct volume_level *level, int flag) {
int max_level, cmd_left, cmd_right;
max_level = 0x1f;
/* Check device */
switch (level->device) {
case Master:
cmd_left = MASTER_VOLUME_LCH;
cmd_right = MASTER_VOLUME_RCH;
break;
case Dac:
return EINVAL;
case Fm:
cmd_left = FM_VOLUME_LCH;
cmd_right = FM_VOLUME_RCH;
break;
case Cd:
cmd_left = CD_AUDIO_VOLUME_LCH;
cmd_right = CD_AUDIO_VOLUME_RCH;
break;
case Line:
cmd_left = LINE_VOLUME_LCH;
cmd_right = LINE_VOLUME_RCH;
break;
case Mic:
cmd_left = cmd_right = MIC_VOLUME;
break;
case Speaker:
cmd_left = cmd_right = MONO_OUT_VOLUME;
max_level = 0x03;
break;
case Treble:
return EINVAL;
case Bass:
return EINVAL;
default:
return EINVAL;
}
/* Set volume */
if (flag) {
if (level->right < 0)
level->right = 0;
else if (level->right > max_level)
level->right = max_level;
if (level->left < 0)
level->left = 0;
else if (level->left > max_level)
level->left = max_level;
/* ### WRITE_MIXER_REG ### */
dev_mixer_write(base, cmd_left, 0x1f - level->left);
/* ### WRITE_MIXER_REG ### */
dev_mixer_write(base, cmd_right, 0x1f - level->right);
mixer_value[cmd_left] = 0x1f - level->left;
mixer_value[cmd_right] = 0x1f - level->right;
}
/* Get volume (mixer register can not be read in ak4531 codec) */
else {
/* ### READ_MIXER_REG ### */
dev_mixer_read(base, cmd_left);
/* ### READ_MIXER_REG ### */
dev_mixer_read(base, cmd_right);
level->left = 0x1f - mixer_value[cmd_left];
level->right = 0x1f - mixer_value[cmd_right];
}
return OK;
}
#endif
#ifdef MIXER_SB16
int get_set_volume(u32_t *base, struct volume_level *level, int flag) {
int max_level, shift, cmd_left, cmd_right;
max_level = 0x0f;
shift = 4;
/* Check device */
switch (level->device) {
case Master:
cmd_left = SB16_MASTER_LEFT;
cmd_right = SB16_MASTER_RIGHT;
break;
case Dac:
cmd_left = SB16_DAC_LEFT;
cmd_right = SB16_DAC_RIGHT;
break;
case Fm:
cmd_left = SB16_FM_LEFT;
cmd_right = SB16_FM_RIGHT;
break;
case Cd:
cmd_left = SB16_CD_LEFT;
cmd_right = SB16_CD_RIGHT;
break;
case Line:
cmd_left = SB16_LINE_LEFT;
cmd_left = SB16_LINE_RIGHT;
break;
case Mic:
cmd_left = cmd_right = SB16_MIC_LEVEL;
break;
case Speaker:
cmd_left = cmd_right = SB16_PC_LEVEL;
shift = 6;
max_level = 0x03;
break;
case Treble:
cmd_left = SB16_TREBLE_LEFT;
cmd_right = SB16_TREBLE_RIGHT;
shift = 4;
max_level = 0x0f;
break;
case Bass:
cmd_left = SB16_BASS_LEFT;
cmd_right = SB16_BASS_RIGHT;
shift = 4;
max_level = 0x0f;
break;
default:
return EINVAL;
}
/* Set volume */
if (flag) {
if (level->right < 0)
level->right = 0;
else if (level->right > max_level)
level->right = max_level;
if (level->left < 0)
level->left = 0;
else if (level->left > max_level)
level->left = max_level;
/* ### WRITE_MIXER_REG ### */
dev_mixer_write(base, cmd_left, level->left << shift);
/* ### WRITE_MIXER_REG ### */
dev_mixer_write(base, cmd_right, level->right << shift);
}
/* Get volume */
else {
/* ### READ_MIXER_REG ### */
level->left = dev_mixer_read(base, cmd_left);
/* ### READ_MIXER_REG ### */
level->right = dev_mixer_read(base, cmd_right);
level->left >>= shift;
level->right >>= shift;
}
return OK;
}
#endif
#ifdef MIXER_AC97
int get_set_volume(u32_t *base, struct volume_level *level, int flag) {
int max_level, cmd, data;
max_level = 0x1f;
/* Check device */
switch (level->device) {
case Master:
cmd = AC97_MASTER_VOLUME;
break;
case Dac:
return EINVAL;
case Fm:
cmd = AC97_PCM_OUT_VOLUME;
break;
case Cd:
cmd = AC97_CD_VOLUME;
break;
case Line:
cmd = AC97_LINE_IN_VOLUME;
break;
case Mic:
cmd = AC97_MIC_VOLUME;
break;
case Speaker:
return EINVAL;
case Treble:
return EINVAL;
case Bass:
return EINVAL;
default:
return EINVAL;
}
/* Set volume */
if (flag) {
if (level->right < 0)
level->right = 0;
else if (level->right > max_level)
level->right = max_level;
if (level->left < 0)
level->left = 0;
else if (level->left > max_level)
level->left = max_level;
data = (max_level - level->left) << 8 | (max_level - level->right);
/* ### WRITE_MIXER_REG ### */
dev_mixer_write(base, cmd, data);
}
/* Get volume */
else {
/* ### READ_MIXER_REG ### */
data = dev_mixer_read(base, cmd);
level->left = (u16_t)(data >> 8);
level->right = (u16_t)(data & 0xff);
if (level->right < 0)
level->right = 0;
else if (level->right > max_level)
level->right = max_level;
if (level->left < 0)
level->left = 0;
else if (level->left > max_level)
level->left = max_level;
level->left = max_level - level->left;
level->right = max_level - level->right;
}
return OK;
}
#endif
/* Set default mixer volume */
void dev_set_default_volume(u32_t *base) {
int i;
#ifdef MIXER_AK4531
for (i = 0; i <= 0x19; i++)
dev_mixer_write(base, i, mixer_value[i]);
#endif
#ifdef MIXER_SB16
dev_mixer_write(base, SB16_MASTER_LEFT, 0x18 << 3);
dev_mixer_write(base, SB16_MASTER_RIGHT, 0x18 << 3);
dev_mixer_write(base, SB16_DAC_LEFT, 0x0f << 4);
dev_mixer_write(base, SB16_DAC_RIGHT, 0x0f << 4);
dev_mixer_write(base, SB16_FM_LEFT, 0x08 << 4);
dev_mixer_write(base, SB16_FM_RIGHT, 0x08 << 4);
dev_mixer_write(base, SB16_CD_LEFT, 0x08 << 4);
dev_mixer_write(base, SB16_CD_RIGHT, 0x08 << 4);
dev_mixer_write(base, SB16_LINE_LEFT, 0x08 << 4);
dev_mixer_write(base, SB16_LINE_RIGHT, 0x08 << 4);
dev_mixer_write(base, SB16_MIC_LEVEL, 0x0f << 4);
dev_mixer_write(base, SB16_PC_LEVEL, 0x02 << 6);
dev_mixer_write(base, SB16_TREBLE_LEFT, 0x08 << 4);
dev_mixer_write(base, SB16_TREBLE_RIGHT, 0x08 << 4);
dev_mixer_write(base, SB16_BASS_LEFT, 0x08 << 4);
dev_mixer_write(base, SB16_BASS_RIGHT, 0x08 << 4);
#endif
#ifdef MIXER_AC97
dev_mixer_write(base, AC97_POWERDOWN, 0x0000);
for (i = 0; i < 50000; i++) {
if (dev_mixer_read(base, AC97_POWERDOWN) & 0x03)
break;
micro_delay(100);
}
if (i == 50000)
printf("SDR: AC97 is not ready\n");
dev_mixer_write(base, AC97_MASTER_VOLUME, 0x0000);
dev_mixer_write(base, AC97_MONO_VOLUME, 0x8000);
dev_mixer_write(base, AC97_PHONE_VOLUME, 0x8008);
dev_mixer_write(base, AC97_MIC_VOLUME, 0x0000);
dev_mixer_write(base, AC97_LINE_IN_VOLUME, 0x0303);
dev_mixer_write(base, AC97_CD_VOLUME, 0x0808);
dev_mixer_write(base, AC97_AUX_IN_VOLUME, 0x0808);
dev_mixer_write(base, AC97_PCM_OUT_VOLUME, 0x0808);
dev_mixer_write(base, AC97_RECORD_GAIN_VOLUME, 0x0000);
dev_mixer_write(base, AC97_RECORD_SELECT, 0x0000);
dev_mixer_write(base, AC97_GENERAL_PURPOSE, 0x0000);
#endif
}