xref: /openbmc/linux/sound/ppc/burgundy.c (revision a1e58bbd)
1 /*
2  * PMac Burgundy lowlevel functions
3  *
4  * Copyright (c) by Takashi Iwai <tiwai@suse.de>
5  * code based on dmasound.c.
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 2 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, write to the Free Software
19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
20  */
21 
22 #include <asm/io.h>
23 #include <linux/init.h>
24 #include <linux/slab.h>
25 #include <linux/delay.h>
26 #include <sound/core.h>
27 #include "pmac.h"
28 #include "burgundy.h"
29 
30 
31 /* Waits for busy flag to clear */
32 static inline void
33 snd_pmac_burgundy_busy_wait(struct snd_pmac *chip)
34 {
35 	int timeout = 50;
36 	while ((in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) && timeout--)
37 		udelay(1);
38 	if (! timeout)
39 		printk(KERN_DEBUG "burgundy_busy_wait: timeout\n");
40 }
41 
42 static inline void
43 snd_pmac_burgundy_extend_wait(struct snd_pmac *chip)
44 {
45 	int timeout;
46 	timeout = 50;
47 	while (!(in_le32(&chip->awacs->codec_stat) & MASK_EXTEND) && timeout--)
48 		udelay(1);
49 	if (! timeout)
50 		printk(KERN_DEBUG "burgundy_extend_wait: timeout #1\n");
51 	timeout = 50;
52 	while ((in_le32(&chip->awacs->codec_stat) & MASK_EXTEND) && timeout--)
53 		udelay(1);
54 	if (! timeout)
55 		printk(KERN_DEBUG "burgundy_extend_wait: timeout #2\n");
56 }
57 
58 static void
59 snd_pmac_burgundy_wcw(struct snd_pmac *chip, unsigned addr, unsigned val)
60 {
61 	out_le32(&chip->awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff));
62 	snd_pmac_burgundy_busy_wait(chip);
63 	out_le32(&chip->awacs->codec_ctrl, addr + 0x200d00 +((val>>8) & 0xff));
64 	snd_pmac_burgundy_busy_wait(chip);
65 	out_le32(&chip->awacs->codec_ctrl, addr + 0x200e00 +((val>>16) & 0xff));
66 	snd_pmac_burgundy_busy_wait(chip);
67 	out_le32(&chip->awacs->codec_ctrl, addr + 0x200f00 +((val>>24) & 0xff));
68 	snd_pmac_burgundy_busy_wait(chip);
69 }
70 
71 static unsigned
72 snd_pmac_burgundy_rcw(struct snd_pmac *chip, unsigned addr)
73 {
74 	unsigned val = 0;
75 	unsigned long flags;
76 
77 	spin_lock_irqsave(&chip->reg_lock, flags);
78 
79 	out_le32(&chip->awacs->codec_ctrl, addr + 0x100000);
80 	snd_pmac_burgundy_busy_wait(chip);
81 	snd_pmac_burgundy_extend_wait(chip);
82 	val += (in_le32(&chip->awacs->codec_stat) >> 4) & 0xff;
83 
84 	out_le32(&chip->awacs->codec_ctrl, addr + 0x100100);
85 	snd_pmac_burgundy_busy_wait(chip);
86 	snd_pmac_burgundy_extend_wait(chip);
87 	val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<8;
88 
89 	out_le32(&chip->awacs->codec_ctrl, addr + 0x100200);
90 	snd_pmac_burgundy_busy_wait(chip);
91 	snd_pmac_burgundy_extend_wait(chip);
92 	val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<16;
93 
94 	out_le32(&chip->awacs->codec_ctrl, addr + 0x100300);
95 	snd_pmac_burgundy_busy_wait(chip);
96 	snd_pmac_burgundy_extend_wait(chip);
97 	val += ((in_le32(&chip->awacs->codec_stat)>>4) & 0xff) <<24;
98 
99 	spin_unlock_irqrestore(&chip->reg_lock, flags);
100 
101 	return val;
102 }
103 
104 static void
105 snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr, unsigned int val)
106 {
107 	out_le32(&chip->awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));
108 	snd_pmac_burgundy_busy_wait(chip);
109 }
110 
111 static unsigned
112 snd_pmac_burgundy_rcb(struct snd_pmac *chip, unsigned int addr)
113 {
114 	unsigned val = 0;
115 	unsigned long flags;
116 
117 	spin_lock_irqsave(&chip->reg_lock, flags);
118 
119 	out_le32(&chip->awacs->codec_ctrl, addr + 0x100000);
120 	snd_pmac_burgundy_busy_wait(chip);
121 	snd_pmac_burgundy_extend_wait(chip);
122 	val += (in_le32(&chip->awacs->codec_stat) >> 4) & 0xff;
123 
124 	spin_unlock_irqrestore(&chip->reg_lock, flags);
125 
126 	return val;
127 }
128 
129 /*
130  * Burgundy volume: 0 - 100, stereo
131  */
132 static void
133 snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address,
134 			       long *volume, int shift)
135 {
136 	int hardvolume, lvolume, rvolume;
137 
138 	if (volume[0] < 0 || volume[0] > 100 ||
139 	    volume[1] < 0 || volume[1] > 100)
140 		return; /* -EINVAL */
141 	lvolume = volume[0] ? volume[0] + BURGUNDY_VOLUME_OFFSET : 0;
142 	rvolume = volume[1] ? volume[1] + BURGUNDY_VOLUME_OFFSET : 0;
143 
144 	hardvolume = lvolume + (rvolume << shift);
145 	if (shift == 8)
146 		hardvolume |= hardvolume << 16;
147 
148 	snd_pmac_burgundy_wcw(chip, address, hardvolume);
149 }
150 
151 static void
152 snd_pmac_burgundy_read_volume(struct snd_pmac *chip, unsigned int address,
153 			      long *volume, int shift)
154 {
155 	int wvolume;
156 
157 	wvolume = snd_pmac_burgundy_rcw(chip, address);
158 
159 	volume[0] = wvolume & 0xff;
160 	if (volume[0] >= BURGUNDY_VOLUME_OFFSET)
161 		volume[0] -= BURGUNDY_VOLUME_OFFSET;
162 	else
163 		volume[0] = 0;
164 	volume[1] = (wvolume >> shift) & 0xff;
165 	if (volume[1] >= BURGUNDY_VOLUME_OFFSET)
166 		volume[1] -= BURGUNDY_VOLUME_OFFSET;
167 	else
168 		volume[1] = 0;
169 }
170 
171 
172 /*
173  */
174 
175 #define BASE2ADDR(base)	((base) << 12)
176 #define ADDR2BASE(addr)	((addr) >> 12)
177 
178 static int snd_pmac_burgundy_info_volume(struct snd_kcontrol *kcontrol,
179 					 struct snd_ctl_elem_info *uinfo)
180 {
181 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
182 	uinfo->count = 2;
183 	uinfo->value.integer.min = 0;
184 	uinfo->value.integer.max = 100;
185 	return 0;
186 }
187 
188 static int snd_pmac_burgundy_get_volume(struct snd_kcontrol *kcontrol,
189 					struct snd_ctl_elem_value *ucontrol)
190 {
191 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
192 	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
193 	int shift = (kcontrol->private_value >> 8) & 0xff;
194 	snd_pmac_burgundy_read_volume(chip, addr, ucontrol->value.integer.value,
195 				      shift);
196 	return 0;
197 }
198 
199 static int snd_pmac_burgundy_put_volume(struct snd_kcontrol *kcontrol,
200 					struct snd_ctl_elem_value *ucontrol)
201 {
202 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
203 	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
204 	int shift = (kcontrol->private_value >> 8) & 0xff;
205 	long nvoices[2];
206 
207 	snd_pmac_burgundy_write_volume(chip, addr, ucontrol->value.integer.value,
208 				       shift);
209 	snd_pmac_burgundy_read_volume(chip, addr, nvoices, shift);
210 	return (nvoices[0] != ucontrol->value.integer.value[0] ||
211 		nvoices[1] != ucontrol->value.integer.value[1]);
212 }
213 
214 #define BURGUNDY_VOLUME(xname, xindex, addr, shift) \
215 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
216   .info = snd_pmac_burgundy_info_volume,\
217   .get = snd_pmac_burgundy_get_volume,\
218   .put = snd_pmac_burgundy_put_volume,\
219   .private_value = ((ADDR2BASE(addr) & 0xff) | ((shift) << 8)) }
220 
221 /* lineout/speaker */
222 
223 static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol,
224 					     struct snd_ctl_elem_info *uinfo)
225 {
226 	int stereo = (kcontrol->private_value >> 24) & 1;
227 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
228 	uinfo->count = stereo + 1;
229 	uinfo->value.integer.min = 0;
230 	uinfo->value.integer.max = 1;
231 	return 0;
232 }
233 
234 static int snd_pmac_burgundy_get_switch_out(struct snd_kcontrol *kcontrol,
235 					    struct snd_ctl_elem_value *ucontrol)
236 {
237 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
238 	int lmask = kcontrol->private_value & 0xff;
239 	int rmask = (kcontrol->private_value >> 8) & 0xff;
240 	int stereo = (kcontrol->private_value >> 24) & 1;
241 	int val = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
242 	ucontrol->value.integer.value[0] = (val & lmask) ? 1 : 0;
243 	if (stereo)
244 		ucontrol->value.integer.value[1] = (val & rmask) ? 1 : 0;
245 	return 0;
246 }
247 
248 static int snd_pmac_burgundy_put_switch_out(struct snd_kcontrol *kcontrol,
249 					    struct snd_ctl_elem_value *ucontrol)
250 {
251 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
252 	int lmask = kcontrol->private_value & 0xff;
253 	int rmask = (kcontrol->private_value >> 8) & 0xff;
254 	int stereo = (kcontrol->private_value >> 24) & 1;
255 	int val, oval;
256 	oval = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
257 	val = oval & ~(lmask | rmask);
258 	if (ucontrol->value.integer.value[0])
259 		val |= lmask;
260 	if (stereo && ucontrol->value.integer.value[1])
261 		val |= rmask;
262 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, val);
263 	return val != oval;
264 }
265 
266 #define BURGUNDY_OUTPUT_SWITCH(xname, xindex, lmask, rmask, stereo) \
267 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
268   .info = snd_pmac_burgundy_info_switch_out,\
269   .get = snd_pmac_burgundy_get_switch_out,\
270   .put = snd_pmac_burgundy_put_switch_out,\
271   .private_value = ((lmask) | ((rmask) << 8) | ((stereo) << 24)) }
272 
273 /* line/speaker output volume */
274 static int snd_pmac_burgundy_info_volume_out(struct snd_kcontrol *kcontrol,
275 					     struct snd_ctl_elem_info *uinfo)
276 {
277 	int stereo = (kcontrol->private_value >> 24) & 1;
278 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
279 	uinfo->count = stereo + 1;
280 	uinfo->value.integer.min = 0;
281 	uinfo->value.integer.max = 15;
282 	return 0;
283 }
284 
285 static int snd_pmac_burgundy_get_volume_out(struct snd_kcontrol *kcontrol,
286 					    struct snd_ctl_elem_value *ucontrol)
287 {
288 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
289 	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
290 	int stereo = (kcontrol->private_value >> 24) & 1;
291 	int oval;
292 
293 	oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
294 	ucontrol->value.integer.value[0] = oval & 0xf;
295 	if (stereo)
296 		ucontrol->value.integer.value[1] = (oval >> 4) & 0xf;
297 	return 0;
298 }
299 
300 static int snd_pmac_burgundy_put_volume_out(struct snd_kcontrol *kcontrol,
301 					    struct snd_ctl_elem_value *ucontrol)
302 {
303 	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
304 	unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
305 	int stereo = (kcontrol->private_value >> 24) & 1;
306 	unsigned int oval, val;
307 
308 	oval = ~snd_pmac_burgundy_rcb(chip, addr) & 0xff;
309 	val = ucontrol->value.integer.value[0] & 15;
310 	if (stereo)
311 		val |= (ucontrol->value.integer.value[1] & 15) << 4;
312 	else
313 		val |= val << 4;
314 	val = ~val & 0xff;
315 	snd_pmac_burgundy_wcb(chip, addr, val);
316 	return val != oval;
317 }
318 
319 #define BURGUNDY_OUTPUT_VOLUME(xname, xindex, addr, stereo) \
320 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
321   .info = snd_pmac_burgundy_info_volume_out,\
322   .get = snd_pmac_burgundy_get_volume_out,\
323   .put = snd_pmac_burgundy_put_volume_out,\
324   .private_value = (ADDR2BASE(addr) | ((stereo) << 24)) }
325 
326 static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __initdata = {
327 	BURGUNDY_VOLUME("Master Playback Volume", 0, MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
328 	BURGUNDY_VOLUME("Line Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLLINE, 16),
329 	BURGUNDY_VOLUME("CD Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLCD, 16),
330 	BURGUNDY_VOLUME("Mic Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLMIC, 16),
331 	BURGUNDY_OUTPUT_VOLUME("PC Speaker Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENHP, 0),
332 	/*BURGUNDY_OUTPUT_VOLUME("PCM Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1),*/
333 	BURGUNDY_OUTPUT_VOLUME("Headphone Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1),
334 };
335 static struct snd_kcontrol_new snd_pmac_burgundy_master_sw __initdata =
336 BURGUNDY_OUTPUT_SWITCH("Headphone Playback Switch", 0, BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
337 static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw __initdata =
338 BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0, BURGUNDY_OUTPUT_INTERN, 0, 0);
339 
340 
341 #ifdef PMAC_SUPPORT_AUTOMUTE
342 /*
343  * auto-mute stuffs
344  */
345 static int snd_pmac_burgundy_detect_headphone(struct snd_pmac *chip)
346 {
347 	return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0;
348 }
349 
350 static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_notify)
351 {
352 	if (chip->auto_mute) {
353 		int reg, oreg;
354 		reg = oreg = snd_pmac_burgundy_rcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES);
355 		reg &= ~(BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT | BURGUNDY_OUTPUT_INTERN);
356 		if (snd_pmac_burgundy_detect_headphone(chip))
357 			reg |= BURGUNDY_OUTPUT_LEFT | BURGUNDY_OUTPUT_RIGHT;
358 		else
359 			reg |= BURGUNDY_OUTPUT_INTERN;
360 		if (do_notify && reg == oreg)
361 			return;
362 		snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, reg);
363 		if (do_notify) {
364 			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
365 				       &chip->master_sw_ctl->id);
366 			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
367 				       &chip->speaker_sw_ctl->id);
368 			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
369 				       &chip->hp_detect_ctl->id);
370 		}
371 	}
372 }
373 #endif /* PMAC_SUPPORT_AUTOMUTE */
374 
375 
376 /*
377  * initialize burgundy
378  */
379 int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
380 {
381 	int i, err;
382 
383 	/* Checks to see the chip is alive and kicking */
384 	if ((in_le32(&chip->awacs->codec_ctrl) & MASK_ERRCODE) == 0xf0000) {
385 		printk(KERN_WARNING "pmac burgundy: disabled by MacOS :-(\n");
386 		return 1;
387 	}
388 
389 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_OUTPUTENABLES,
390 			   DEF_BURGUNDY_OUTPUTENABLES);
391 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
392 			   DEF_BURGUNDY_MORE_OUTPUTENABLES);
393 	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_OUTPUTSELECTS,
394 			   DEF_BURGUNDY_OUTPUTSELECTS);
395 
396 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL21,
397 			   DEF_BURGUNDY_INPSEL21);
398 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_INPSEL3,
399 			   DEF_BURGUNDY_INPSEL3);
400 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINCD,
401 			   DEF_BURGUNDY_GAINCD);
402 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINLINE,
403 			   DEF_BURGUNDY_GAINLINE);
404 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINMIC,
405 			   DEF_BURGUNDY_GAINMIC);
406 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_GAINMODEM,
407 			   DEF_BURGUNDY_GAINMODEM);
408 
409 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENSPEAKER,
410 			   DEF_BURGUNDY_ATTENSPEAKER);
411 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENLINEOUT,
412 			   DEF_BURGUNDY_ATTENLINEOUT);
413 	snd_pmac_burgundy_wcb(chip, MASK_ADDR_BURGUNDY_ATTENHP,
414 			   DEF_BURGUNDY_ATTENHP);
415 
416 	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_MASTER_VOLUME,
417 			   DEF_BURGUNDY_MASTER_VOLUME);
418 	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLCD,
419 			   DEF_BURGUNDY_VOLCD);
420 	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLLINE,
421 			   DEF_BURGUNDY_VOLLINE);
422 	snd_pmac_burgundy_wcw(chip, MASK_ADDR_BURGUNDY_VOLMIC,
423 			   DEF_BURGUNDY_VOLMIC);
424 
425 	if (chip->hp_stat_mask == 0)
426 		/* set headphone-jack detection bit */
427 		chip->hp_stat_mask = 0x04;
428 
429 	/*
430 	 * build burgundy mixers
431 	 */
432 	strcpy(chip->card->mixername, "PowerMac Burgundy");
433 
434 	for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) {
435 		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0)
436 			return err;
437 	}
438 	chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_master_sw, chip);
439 	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
440 		return err;
441 	chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_burgundy_speaker_sw, chip);
442 	if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
443 		return err;
444 #ifdef PMAC_SUPPORT_AUTOMUTE
445 	if ((err = snd_pmac_add_automute(chip)) < 0)
446 		return err;
447 
448 	chip->detect_headphone = snd_pmac_burgundy_detect_headphone;
449 	chip->update_automute = snd_pmac_burgundy_update_automute;
450 	snd_pmac_burgundy_update_automute(chip, 0); /* update the status only */
451 #endif
452 
453 	return 0;
454 }
455