xref: /minix/minix/drivers/audio/es1370/ak4531.c (revision 83133719)
1 /* best viewed with tabsize 4 */
2 
3 
4 #include "ak4531.h"
5 #include "pci_helper.h"
6 
7 
8 #define MASTER_VOLUME_LCH				0x00
9 #define MASTER_VOLUME_RCH				0x01
10 #define FM_VOLUME_LCH					0x04
11 #define FM_VOLUME_RCH					0x05
12 #define CD_AUDIO_VOLUME_LCH				0x06
13 #define CD_AUDIO_VOLUME_RCH				0x07
14 #define LINE_VOLUME_LCH					0x08
15 #define LINE_VOLUME_RCH					0x09
16 #define MIC_VOLUME						0x0e
17 #define MONO_OUT_VOLUME					0x0f
18 
19 #define RESET_AND_POWER_DOWN			0x16
20 #define PD								0x02
21 #define RST								0x01
22 
23 #define AD_INPUT_SELECT					0x18
24 #define MIC_AMP_GAIN					0x19
25 
26 #define MUTE							0x80
27 
28 
29 static int ak4531_write(u8_t address, u8_t data);
30 static int ak4531_finished(void);
31 static int set_volume(struct volume_level *level, int cmd_left, int
32 	cmd_right, int max_level);
33 
34 static u16_t base_address;
35 static u16_t status_register;
36 static u16_t status_bit;
37 static u16_t poll_address;
38 
39 u8_t mixer_values[0x20] = {
40 	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 0x00 - 0x07 */
41 	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, /* 0x08 - 0x0f */
42 	0x7e, 0x3d, 0x01, 0x01, 0x00, 0x00, 0x03, 0x00, /* 0x10 - 0x17 */
43 	0x00, 0x01										/* 0x18 - 0x19 */
44 };
45 #if 0
46 u8_t mixer_values[0x20] = {
47 	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 0x00 - 0x07 */
48 	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 0x08 - 0x0f */
49 	0x7f, 0x3d, 0x55, 0x26, 0xf7, 0xef, 0x03, 0x00, /* 0x10 - 0x17 */
50 	0x00, 0x01										/* 0x18 - 0x19 */
51 };
52 #endif
53 
54 
55 
56 static int ak4531_finished(void) {
57 	int i;
58 	u16_t cstat;
59 	for (i = 0; i < 0x40000; i++) {
60 		cstat = pci_inw(status_register);
61 		if (!(cstat & status_bit)) {
62 			return 1;
63 		}
64 	}
65 	return 0;
66 }
67 
68 
69 static int ak4531_write (u8_t address, u8_t data) {
70 	u16_t to_be_written;
71 
72 
73 	if (address > MIC_AMP_GAIN) return -1;
74 
75 	to_be_written = (u16_t)((address << 8) | data);
76 
77 	if (!ak4531_finished()) return -1;
78 	pci_outw(base_address, to_be_written);
79 	return 0;
80 }
81 
82 
83 int ak4531_init(u16_t base, u16_t status_reg, u16_t bit,
84 		u16_t poll) {
85 	int i;
86 
87 	base_address = base;
88 	status_register = status_reg;
89 	status_bit = bit;
90 	poll_address = poll;
91 
92 	for (i=0; i<100; i++) {
93 		pci_inb(poll_address);
94 	}
95 	if(ak4531_write(RESET_AND_POWER_DOWN, PD|RST) < 0) return -1;
96 
97 	for (i=0; i<100; i++) {
98 		pci_inb(poll_address);
99 	}
100 
101 	ak4531_write(AD_INPUT_SELECT, 0x00);
102 
103 	for (i = MASTER_VOLUME_LCH ; i <= MIC_AMP_GAIN; i++) {
104 		if (ak4531_write(i, mixer_values[i]) < 0) return -1;
105 	}
106 	return 0;
107 }
108 
109 
110 int ak4531_get_set_volume(struct volume_level *level, int flag) {
111 	int cmd_left, cmd_right, max_level;
112 
113 	max_level = 0x1f;
114 
115 	switch(level->device) {
116 		case Master:
117 			cmd_left = MASTER_VOLUME_LCH;
118 			cmd_right = MASTER_VOLUME_RCH;
119 			break;
120 		case Dac:
121 			return EINVAL;
122 			break;
123 		case Fm:
124 			cmd_left = FM_VOLUME_LCH;
125 			cmd_right = FM_VOLUME_RCH;
126 			break;
127 		case Cd:
128 			cmd_left = CD_AUDIO_VOLUME_LCH;
129 			cmd_right = CD_AUDIO_VOLUME_RCH;
130 			break;
131 		case Line:
132 			cmd_left = LINE_VOLUME_LCH;
133 			cmd_right = LINE_VOLUME_RCH;
134 			break;
135 		case Mic:
136 			cmd_left = cmd_right = MIC_VOLUME;
137 			break;
138 		case Speaker:
139 			cmd_left = cmd_right = MONO_OUT_VOLUME;
140 			max_level = 0x03;
141 			break;
142 		case Treble:
143 			return EINVAL;
144 			break;
145 		case Bass:
146 			return EINVAL;
147 			break;
148 		default:
149 			return EINVAL;
150 	}
151 
152 	if (flag) { /* set volume */
153 		return set_volume(level, cmd_left, cmd_right, max_level);
154 	}
155 	else { /* get volume */
156 		level->left = - ((int) (mixer_values[cmd_left] & ~MUTE)) + 0x1f;
157 		level->right = - ((int) (mixer_values[cmd_right] & ~MUTE)) + 0x1f;
158 		return OK;
159 	}
160 }
161 
162 
163 static int set_volume(struct volume_level *level, int cmd_left, int cmd_right,
164 		int max_level) {
165 
166 	if(level->right < 0) level->right = 0;
167 	else if(level->right > max_level) level->right = max_level;
168 	if(level->left < 0) level->left = 0;
169 	else if(level->left > max_level) level->left = max_level;
170 
171 	mixer_values[cmd_left] = (-level->left)+0x1f;
172 	ak4531_write(cmd_left, mixer_values[cmd_left]);
173 	mixer_values[cmd_right] = (-level->right)+0x1f;
174 	ak4531_write(cmd_right, mixer_values[cmd_right]);
175 
176 	return OK;
177 }
178