xref: /minix3/minix/drivers/audio/cmi8738/mixer.c (revision 37e23b1cc7a8bf4f9734839628f9e4ce93b7b5d8)
1*37e23b1cSJia-Ju Bai #include "mixer.h"
2*37e23b1cSJia-Ju Bai 
3*37e23b1cSJia-Ju Bai #ifdef MIXER_AK4531
4*37e23b1cSJia-Ju Bai u8_t mixer_value[] = {
5*37e23b1cSJia-Ju Bai 	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
6*37e23b1cSJia-Ju Bai 	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08,
7*37e23b1cSJia-Ju Bai 	0x7e, 0x3d, 0x01, 0x01, 0x00, 0x00, 0x03, 0x00,
8*37e23b1cSJia-Ju Bai 	0x00, 0x01
9*37e23b1cSJia-Ju Bai };
get_set_volume(u32_t * base,struct volume_level * level,int flag)10*37e23b1cSJia-Ju Bai int get_set_volume(u32_t *base, struct volume_level *level, int flag) {
11*37e23b1cSJia-Ju Bai 	int max_level, cmd_left, cmd_right;
12*37e23b1cSJia-Ju Bai 
13*37e23b1cSJia-Ju Bai 	max_level = 0x1f;
14*37e23b1cSJia-Ju Bai 	/* Check device */
15*37e23b1cSJia-Ju Bai 	switch (level->device) {
16*37e23b1cSJia-Ju Bai 		case Master:
17*37e23b1cSJia-Ju Bai 			cmd_left = MASTER_VOLUME_LCH;
18*37e23b1cSJia-Ju Bai 			cmd_right = MASTER_VOLUME_RCH;
19*37e23b1cSJia-Ju Bai 			break;
20*37e23b1cSJia-Ju Bai 		case Dac:
21*37e23b1cSJia-Ju Bai 			return EINVAL;
22*37e23b1cSJia-Ju Bai 		case Fm:
23*37e23b1cSJia-Ju Bai 			cmd_left = FM_VOLUME_LCH;
24*37e23b1cSJia-Ju Bai 			cmd_right = FM_VOLUME_RCH;
25*37e23b1cSJia-Ju Bai 			break;
26*37e23b1cSJia-Ju Bai 		case Cd:
27*37e23b1cSJia-Ju Bai 			cmd_left = CD_AUDIO_VOLUME_LCH;
28*37e23b1cSJia-Ju Bai 			cmd_right = CD_AUDIO_VOLUME_RCH;
29*37e23b1cSJia-Ju Bai 			break;
30*37e23b1cSJia-Ju Bai 		case Line:
31*37e23b1cSJia-Ju Bai 			cmd_left = LINE_VOLUME_LCH;
32*37e23b1cSJia-Ju Bai 			cmd_right = LINE_VOLUME_RCH;
33*37e23b1cSJia-Ju Bai 			break;
34*37e23b1cSJia-Ju Bai 		case Mic:
35*37e23b1cSJia-Ju Bai 			cmd_left = cmd_right = MIC_VOLUME;
36*37e23b1cSJia-Ju Bai 			break;
37*37e23b1cSJia-Ju Bai 		case Speaker:
38*37e23b1cSJia-Ju Bai 			cmd_left = cmd_right = MONO_OUT_VOLUME;
39*37e23b1cSJia-Ju Bai 			max_level = 0x03;
40*37e23b1cSJia-Ju Bai 			break;
41*37e23b1cSJia-Ju Bai 		case Treble:
42*37e23b1cSJia-Ju Bai 			return EINVAL;
43*37e23b1cSJia-Ju Bai 		case Bass:
44*37e23b1cSJia-Ju Bai 			return EINVAL;
45*37e23b1cSJia-Ju Bai 		default:
46*37e23b1cSJia-Ju Bai 			return EINVAL;
47*37e23b1cSJia-Ju Bai 	}
48*37e23b1cSJia-Ju Bai 	/* Set volume */
49*37e23b1cSJia-Ju Bai 	if (flag) {
50*37e23b1cSJia-Ju Bai 		if (level->right < 0)
51*37e23b1cSJia-Ju Bai 			level->right = 0;
52*37e23b1cSJia-Ju Bai 		else if (level->right > max_level)
53*37e23b1cSJia-Ju Bai 			level->right = max_level;
54*37e23b1cSJia-Ju Bai 		if (level->left < 0)
55*37e23b1cSJia-Ju Bai 			level->left = 0;
56*37e23b1cSJia-Ju Bai 		else if (level->left > max_level)
57*37e23b1cSJia-Ju Bai 			level->left = max_level;
58*37e23b1cSJia-Ju Bai 		/* ### WRITE_MIXER_REG ### */
59*37e23b1cSJia-Ju Bai 		dev_mixer_write(base, cmd_left, 0x1f - level->left);
60*37e23b1cSJia-Ju Bai 		/* ### WRITE_MIXER_REG ### */
61*37e23b1cSJia-Ju Bai 		dev_mixer_write(base, cmd_right, 0x1f - level->right);
62*37e23b1cSJia-Ju Bai 		mixer_value[cmd_left] = 0x1f - level->left;
63*37e23b1cSJia-Ju Bai 		mixer_value[cmd_right] = 0x1f - level->right;
64*37e23b1cSJia-Ju Bai 	}
65*37e23b1cSJia-Ju Bai 	/* Get volume (mixer register can not be read in ak4531 codec) */
66*37e23b1cSJia-Ju Bai 	else {
67*37e23b1cSJia-Ju Bai 		/* ### READ_MIXER_REG ### */
68*37e23b1cSJia-Ju Bai 		dev_mixer_read(base, cmd_left);
69*37e23b1cSJia-Ju Bai 		/* ### READ_MIXER_REG ### */
70*37e23b1cSJia-Ju Bai 		dev_mixer_read(base, cmd_right);
71*37e23b1cSJia-Ju Bai 		level->left = 0x1f - mixer_value[cmd_left];
72*37e23b1cSJia-Ju Bai 		level->right = 0x1f - mixer_value[cmd_right];
73*37e23b1cSJia-Ju Bai 	}
74*37e23b1cSJia-Ju Bai 	return OK;
75*37e23b1cSJia-Ju Bai }
76*37e23b1cSJia-Ju Bai #endif
77*37e23b1cSJia-Ju Bai 
78*37e23b1cSJia-Ju Bai #ifdef MIXER_SB16
get_set_volume(u32_t * base,struct volume_level * level,int flag)79*37e23b1cSJia-Ju Bai int get_set_volume(u32_t *base, struct volume_level *level, int flag) {
80*37e23b1cSJia-Ju Bai 	int max_level, shift, cmd_left, cmd_right;
81*37e23b1cSJia-Ju Bai 
82*37e23b1cSJia-Ju Bai 	max_level = 0x0f;
83*37e23b1cSJia-Ju Bai 	shift = 4;
84*37e23b1cSJia-Ju Bai 	/* Check device */
85*37e23b1cSJia-Ju Bai 	switch (level->device) {
86*37e23b1cSJia-Ju Bai 		case Master:
87*37e23b1cSJia-Ju Bai 			cmd_left = SB16_MASTER_LEFT;
88*37e23b1cSJia-Ju Bai 			cmd_right = SB16_MASTER_RIGHT;
89*37e23b1cSJia-Ju Bai 			break;
90*37e23b1cSJia-Ju Bai 		case Dac:
91*37e23b1cSJia-Ju Bai 			cmd_left = SB16_DAC_LEFT;
92*37e23b1cSJia-Ju Bai 			cmd_right = SB16_DAC_RIGHT;
93*37e23b1cSJia-Ju Bai 			break;
94*37e23b1cSJia-Ju Bai 		case Fm:
95*37e23b1cSJia-Ju Bai 			cmd_left = SB16_FM_LEFT;
96*37e23b1cSJia-Ju Bai 			cmd_right = SB16_FM_RIGHT;
97*37e23b1cSJia-Ju Bai 			break;
98*37e23b1cSJia-Ju Bai 		case Cd:
99*37e23b1cSJia-Ju Bai 			cmd_left = SB16_CD_LEFT;
100*37e23b1cSJia-Ju Bai 			cmd_right = SB16_CD_RIGHT;
101*37e23b1cSJia-Ju Bai 			break;
102*37e23b1cSJia-Ju Bai 		case Line:
103*37e23b1cSJia-Ju Bai 			cmd_left = SB16_LINE_LEFT;
104*37e23b1cSJia-Ju Bai 			cmd_left = SB16_LINE_RIGHT;
105*37e23b1cSJia-Ju Bai 			break;
106*37e23b1cSJia-Ju Bai 		case Mic:
107*37e23b1cSJia-Ju Bai 			cmd_left = cmd_right = SB16_MIC_LEVEL;
108*37e23b1cSJia-Ju Bai 			break;
109*37e23b1cSJia-Ju Bai 		case Speaker:
110*37e23b1cSJia-Ju Bai 			cmd_left = cmd_right = SB16_PC_LEVEL;
111*37e23b1cSJia-Ju Bai 			shift = 6;
112*37e23b1cSJia-Ju Bai 			max_level = 0x03;
113*37e23b1cSJia-Ju Bai 			break;
114*37e23b1cSJia-Ju Bai 		case Treble:
115*37e23b1cSJia-Ju Bai 			cmd_left = SB16_TREBLE_LEFT;
116*37e23b1cSJia-Ju Bai 			cmd_right = SB16_TREBLE_RIGHT;
117*37e23b1cSJia-Ju Bai 			shift = 4;
118*37e23b1cSJia-Ju Bai 			max_level = 0x0f;
119*37e23b1cSJia-Ju Bai 			break;
120*37e23b1cSJia-Ju Bai 		case Bass:
121*37e23b1cSJia-Ju Bai 			cmd_left = SB16_BASS_LEFT;
122*37e23b1cSJia-Ju Bai 			cmd_right = SB16_BASS_RIGHT;
123*37e23b1cSJia-Ju Bai 			shift = 4;
124*37e23b1cSJia-Ju Bai 			max_level = 0x0f;
125*37e23b1cSJia-Ju Bai 			break;
126*37e23b1cSJia-Ju Bai 		default:
127*37e23b1cSJia-Ju Bai 			return EINVAL;
128*37e23b1cSJia-Ju Bai 	}
129*37e23b1cSJia-Ju Bai 	/* Set volume */
130*37e23b1cSJia-Ju Bai 	if (flag) {
131*37e23b1cSJia-Ju Bai 		if (level->right < 0)
132*37e23b1cSJia-Ju Bai 			level->right = 0;
133*37e23b1cSJia-Ju Bai 		else if (level->right > max_level)
134*37e23b1cSJia-Ju Bai 			level->right = max_level;
135*37e23b1cSJia-Ju Bai 		if (level->left < 0)
136*37e23b1cSJia-Ju Bai 			level->left = 0;
137*37e23b1cSJia-Ju Bai 		else if (level->left > max_level)
138*37e23b1cSJia-Ju Bai 			level->left = max_level;
139*37e23b1cSJia-Ju Bai 		/* ### WRITE_MIXER_REG ### */
140*37e23b1cSJia-Ju Bai 		dev_mixer_write(base, cmd_left, level->left << shift);
141*37e23b1cSJia-Ju Bai 		/* ### WRITE_MIXER_REG ### */
142*37e23b1cSJia-Ju Bai 		dev_mixer_write(base, cmd_right, level->right << shift);
143*37e23b1cSJia-Ju Bai 	}
144*37e23b1cSJia-Ju Bai 	/* Get volume */
145*37e23b1cSJia-Ju Bai 	else {
146*37e23b1cSJia-Ju Bai 		/* ### READ_MIXER_REG ### */
147*37e23b1cSJia-Ju Bai 		level->left = dev_mixer_read(base, cmd_left);
148*37e23b1cSJia-Ju Bai 		/* ### READ_MIXER_REG ### */
149*37e23b1cSJia-Ju Bai 		level->right = dev_mixer_read(base, cmd_right);
150*37e23b1cSJia-Ju Bai 		level->left >>= shift;
151*37e23b1cSJia-Ju Bai 		level->right >>= shift;
152*37e23b1cSJia-Ju Bai 	}
153*37e23b1cSJia-Ju Bai 	return OK;
154*37e23b1cSJia-Ju Bai }
155*37e23b1cSJia-Ju Bai #endif
156*37e23b1cSJia-Ju Bai 
157*37e23b1cSJia-Ju Bai #ifdef MIXER_AC97
get_set_volume(u32_t * base,struct volume_level * level,int flag)158*37e23b1cSJia-Ju Bai int get_set_volume(u32_t *base, struct volume_level *level, int flag) {
159*37e23b1cSJia-Ju Bai 	int max_level, cmd, data;
160*37e23b1cSJia-Ju Bai 
161*37e23b1cSJia-Ju Bai 	max_level = 0x1f;
162*37e23b1cSJia-Ju Bai 	/* Check device */
163*37e23b1cSJia-Ju Bai 	switch (level->device) {
164*37e23b1cSJia-Ju Bai 		case Master:
165*37e23b1cSJia-Ju Bai 			cmd = AC97_MASTER_VOLUME;
166*37e23b1cSJia-Ju Bai 			break;
167*37e23b1cSJia-Ju Bai 		case Dac:
168*37e23b1cSJia-Ju Bai 			return EINVAL;
169*37e23b1cSJia-Ju Bai 		case Fm:
170*37e23b1cSJia-Ju Bai 			cmd = AC97_PCM_OUT_VOLUME;
171*37e23b1cSJia-Ju Bai 			break;
172*37e23b1cSJia-Ju Bai 		case Cd:
173*37e23b1cSJia-Ju Bai 			cmd = AC97_CD_VOLUME;
174*37e23b1cSJia-Ju Bai 			break;
175*37e23b1cSJia-Ju Bai 		case Line:
176*37e23b1cSJia-Ju Bai 			cmd = AC97_LINE_IN_VOLUME;
177*37e23b1cSJia-Ju Bai 			break;
178*37e23b1cSJia-Ju Bai 		case Mic:
179*37e23b1cSJia-Ju Bai 			cmd = AC97_MIC_VOLUME;
180*37e23b1cSJia-Ju Bai 			break;
181*37e23b1cSJia-Ju Bai 		case Speaker:
182*37e23b1cSJia-Ju Bai 			return EINVAL;
183*37e23b1cSJia-Ju Bai 		case Treble:
184*37e23b1cSJia-Ju Bai 			return EINVAL;
185*37e23b1cSJia-Ju Bai 		case Bass:
186*37e23b1cSJia-Ju Bai 			return EINVAL;
187*37e23b1cSJia-Ju Bai 		default:
188*37e23b1cSJia-Ju Bai 			return EINVAL;
189*37e23b1cSJia-Ju Bai 	}
190*37e23b1cSJia-Ju Bai 	/* Set volume */
191*37e23b1cSJia-Ju Bai 	if (flag) {
192*37e23b1cSJia-Ju Bai 		if (level->right < 0)
193*37e23b1cSJia-Ju Bai 			level->right = 0;
194*37e23b1cSJia-Ju Bai 		else if (level->right > max_level)
195*37e23b1cSJia-Ju Bai 			level->right = max_level;
196*37e23b1cSJia-Ju Bai 		if (level->left < 0)
197*37e23b1cSJia-Ju Bai 			level->left = 0;
198*37e23b1cSJia-Ju Bai 		else if (level->left > max_level)
199*37e23b1cSJia-Ju Bai 			level->left = max_level;
200*37e23b1cSJia-Ju Bai 		data = (max_level - level->left) << 8 | (max_level - level->right);
201*37e23b1cSJia-Ju Bai 		/* ### WRITE_MIXER_REG ### */
202*37e23b1cSJia-Ju Bai 		dev_mixer_write(base, cmd, data);
203*37e23b1cSJia-Ju Bai 	}
204*37e23b1cSJia-Ju Bai 	/* Get volume */
205*37e23b1cSJia-Ju Bai 	else {
206*37e23b1cSJia-Ju Bai 		/* ### READ_MIXER_REG ### */
207*37e23b1cSJia-Ju Bai 		data = dev_mixer_read(base, cmd);
208*37e23b1cSJia-Ju Bai 		level->left = (u16_t)(data >> 8);
209*37e23b1cSJia-Ju Bai 		level->right = (u16_t)(data & 0xff);
210*37e23b1cSJia-Ju Bai 		if (level->right < 0)
211*37e23b1cSJia-Ju Bai 			level->right = 0;
212*37e23b1cSJia-Ju Bai 		else if (level->right > max_level)
213*37e23b1cSJia-Ju Bai 			level->right = max_level;
214*37e23b1cSJia-Ju Bai 		if (level->left < 0)
215*37e23b1cSJia-Ju Bai 			level->left = 0;
216*37e23b1cSJia-Ju Bai 		else if (level->left > max_level)
217*37e23b1cSJia-Ju Bai 			level->left = max_level;
218*37e23b1cSJia-Ju Bai 		level->left = max_level - level->left;
219*37e23b1cSJia-Ju Bai 		level->right = max_level - level->right;
220*37e23b1cSJia-Ju Bai 	}
221*37e23b1cSJia-Ju Bai 	return OK;
222*37e23b1cSJia-Ju Bai }
223*37e23b1cSJia-Ju Bai #endif
224*37e23b1cSJia-Ju Bai 
225*37e23b1cSJia-Ju Bai /* Set default mixer volume */
dev_set_default_volume(u32_t * base)226*37e23b1cSJia-Ju Bai void dev_set_default_volume(u32_t *base) {
227*37e23b1cSJia-Ju Bai 	int i;
228*37e23b1cSJia-Ju Bai #ifdef MIXER_AK4531
229*37e23b1cSJia-Ju Bai 	for (i = 0; i <= 0x19; i++)
230*37e23b1cSJia-Ju Bai 		dev_mixer_write(base, i, mixer_value[i]);
231*37e23b1cSJia-Ju Bai #endif
232*37e23b1cSJia-Ju Bai #ifdef MIXER_SB16
233*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_MASTER_LEFT, 0x18 << 3);
234*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_MASTER_RIGHT, 0x18 << 3);
235*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_DAC_LEFT, 0x0f << 4);
236*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_DAC_RIGHT, 0x0f << 4);
237*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_FM_LEFT, 0x08 << 4);
238*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_FM_RIGHT, 0x08 << 4);
239*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_CD_LEFT, 0x08 << 4);
240*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_CD_RIGHT, 0x08 << 4);
241*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_LINE_LEFT, 0x08 << 4);
242*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_LINE_RIGHT, 0x08 << 4);
243*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_MIC_LEVEL, 0x0f << 4);
244*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_PC_LEVEL, 0x02 << 6);
245*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_TREBLE_LEFT, 0x08 << 4);
246*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_TREBLE_RIGHT, 0x08 << 4);
247*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_BASS_LEFT, 0x08 << 4);
248*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, SB16_BASS_RIGHT, 0x08 << 4);
249*37e23b1cSJia-Ju Bai #endif
250*37e23b1cSJia-Ju Bai 
251*37e23b1cSJia-Ju Bai #ifdef MIXER_AC97
252*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, AC97_POWERDOWN, 0x0000);
253*37e23b1cSJia-Ju Bai 	for (i = 0; i < 50000; i++) {
254*37e23b1cSJia-Ju Bai 		if (dev_mixer_read(base, AC97_POWERDOWN) & 0x03)
255*37e23b1cSJia-Ju Bai 			break;
256*37e23b1cSJia-Ju Bai 		micro_delay(100);
257*37e23b1cSJia-Ju Bai 	}
258*37e23b1cSJia-Ju Bai 	if (i == 50000)
259*37e23b1cSJia-Ju Bai 		printf("SDR: AC97 is not ready\n");
260*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, AC97_MASTER_VOLUME, 0x0000);
261*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, AC97_MONO_VOLUME, 0x8000);
262*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, AC97_PHONE_VOLUME, 0x8008);
263*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, AC97_MIC_VOLUME, 0x0000);
264*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, AC97_LINE_IN_VOLUME, 0x0303);
265*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, AC97_CD_VOLUME, 0x0808);
266*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, AC97_AUX_IN_VOLUME, 0x0808);
267*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, AC97_PCM_OUT_VOLUME, 0x0808);
268*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, AC97_RECORD_GAIN_VOLUME, 0x0000);
269*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, AC97_RECORD_SELECT, 0x0000);
270*37e23b1cSJia-Ju Bai 	dev_mixer_write(base, AC97_GENERAL_PURPOSE, 0x0000);
271*37e23b1cSJia-Ju Bai #endif
272*37e23b1cSJia-Ju Bai }
273