brintos

brintos / linux-shallow public Read only

0
0
Text · 31.3 KiB · 49399a4 Raw
1136 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * PMac AWACS lowlevel functions4 *5 * Copyright (c) by Takashi Iwai <tiwai@suse.de>6 * code based on dmasound.c.7 */8 9 10#include <linux/io.h>11#include <asm/nvram.h>12#include <linux/init.h>13#include <linux/delay.h>14#include <linux/of.h>15#include <linux/slab.h>16#include <sound/core.h>17#include "pmac.h"18 19 20#ifdef CONFIG_ADB_CUDA21#define PMAC_AMP_AVAIL22#endif23 24#ifdef PMAC_AMP_AVAIL25struct awacs_amp {26	unsigned char amp_master;27	unsigned char amp_vol[2][2];28	unsigned char amp_tone[2];29};30 31#define CHECK_CUDA_AMP() (sys_ctrler == SYS_CTRLER_CUDA)32 33#endif /* PMAC_AMP_AVAIL */34 35 36static void snd_pmac_screamer_wait(struct snd_pmac *chip)37{38	long timeout = 2000;39	while (!(in_le32(&chip->awacs->codec_stat) & MASK_VALID)) {40		mdelay(1);41		if (! --timeout) {42			dev_dbg(chip->card->dev, "%s timeout\n", __func__);43			break;44		}45	}46}47 48/*49 * write AWACS register50 */51static void52snd_pmac_awacs_write(struct snd_pmac *chip, int val)53{54	long timeout = 5000000;55 56	if (chip->model == PMAC_SCREAMER)57		snd_pmac_screamer_wait(chip);58	out_le32(&chip->awacs->codec_ctrl, val | (chip->subframe << 22));59	while (in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) {60		if (! --timeout) {61			dev_dbg(chip->card->dev, "%s timeout\n", __func__);62			break;63		}64	}65}66 67static void68snd_pmac_awacs_write_reg(struct snd_pmac *chip, int reg, int val)69{70	snd_pmac_awacs_write(chip, val | (reg << 12));71	chip->awacs_reg[reg] = val;72}73 74static void75snd_pmac_awacs_write_noreg(struct snd_pmac *chip, int reg, int val)76{77	snd_pmac_awacs_write(chip, val | (reg << 12));78}79 80#ifdef CONFIG_PM81/* Recalibrate chip */82static void screamer_recalibrate(struct snd_pmac *chip)83{84	if (chip->model != PMAC_SCREAMER)85		return;86 87	/* Sorry for the horrible delays... I hope to get that improved88	 * by making the whole PM process asynchronous in a future version89	 */90	snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);91	if (chip->manufacturer == 0x1)92		/* delay for broken crystal part */93		msleep(750);94	snd_pmac_awacs_write_noreg(chip, 1,95				   chip->awacs_reg[1] | MASK_RECALIBRATE |96				   MASK_CMUTE | MASK_AMUTE);97	snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);98	snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);99}100 101#else102#define screamer_recalibrate(chip) /* NOP */103#endif104 105 106/*107 * additional callback to set the pcm format108 */109static void snd_pmac_awacs_set_format(struct snd_pmac *chip)110{111	chip->awacs_reg[1] &= ~MASK_SAMPLERATE;112	chip->awacs_reg[1] |= chip->rate_index << 3;113	snd_pmac_awacs_write_reg(chip, 1, chip->awacs_reg[1]);114}115 116 117/*118 * AWACS volume callbacks119 */120/*121 * volumes: 0-15 stereo122 */123static int snd_pmac_awacs_info_volume(struct snd_kcontrol *kcontrol,124				      struct snd_ctl_elem_info *uinfo)125{126	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;127	uinfo->count = 2;128	uinfo->value.integer.min = 0;129	uinfo->value.integer.max = 15;130	return 0;131}132 133static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol,134				     struct snd_ctl_elem_value *ucontrol)135{136	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);137	int reg = kcontrol->private_value & 0xff;138	int lshift = (kcontrol->private_value >> 8) & 0xff;139	int inverted = (kcontrol->private_value >> 16) & 1;140	unsigned long flags;141	int vol[2];142 143	spin_lock_irqsave(&chip->reg_lock, flags);144	vol[0] = (chip->awacs_reg[reg] >> lshift) & 0xf;145	vol[1] = chip->awacs_reg[reg] & 0xf;146	spin_unlock_irqrestore(&chip->reg_lock, flags);147	if (inverted) {148		vol[0] = 0x0f - vol[0];149		vol[1] = 0x0f - vol[1];150	}151	ucontrol->value.integer.value[0] = vol[0];152	ucontrol->value.integer.value[1] = vol[1];153	return 0;154}155 156static int snd_pmac_awacs_put_volume(struct snd_kcontrol *kcontrol,157				     struct snd_ctl_elem_value *ucontrol)158{159	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);160	int reg = kcontrol->private_value & 0xff;161	int lshift = (kcontrol->private_value >> 8) & 0xff;162	int inverted = (kcontrol->private_value >> 16) & 1;163	int val, oldval;164	unsigned long flags;165	unsigned int vol[2];166 167	vol[0] = ucontrol->value.integer.value[0];168	vol[1] = ucontrol->value.integer.value[1];169	if (vol[0] > 0x0f || vol[1] > 0x0f)170		return -EINVAL;171	if (inverted) {172		vol[0] = 0x0f - vol[0];173		vol[1] = 0x0f - vol[1];174	}175	vol[0] &= 0x0f;176	vol[1] &= 0x0f;177	spin_lock_irqsave(&chip->reg_lock, flags);178	oldval = chip->awacs_reg[reg];179	val = oldval & ~(0xf | (0xf << lshift));180	val |= vol[0] << lshift;181	val |= vol[1];182	if (oldval != val)183		snd_pmac_awacs_write_reg(chip, reg, val);184	spin_unlock_irqrestore(&chip->reg_lock, flags);185	return oldval != reg;186}187 188 189#define AWACS_VOLUME(xname, xreg, xshift, xinverted) \190{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \191  .info = snd_pmac_awacs_info_volume, \192  .get = snd_pmac_awacs_get_volume, \193  .put = snd_pmac_awacs_put_volume, \194  .private_value = (xreg) | ((xshift) << 8) | ((xinverted) << 16) }195 196/*197 * mute master/ogain for AWACS: mono198 */199static int snd_pmac_awacs_get_switch(struct snd_kcontrol *kcontrol,200				     struct snd_ctl_elem_value *ucontrol)201{202	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);203	int reg = kcontrol->private_value & 0xff;204	int shift = (kcontrol->private_value >> 8) & 0xff;205	int invert = (kcontrol->private_value >> 16) & 1;206	int val;207	unsigned long flags;208 209	spin_lock_irqsave(&chip->reg_lock, flags);210	val = (chip->awacs_reg[reg] >> shift) & 1;211	spin_unlock_irqrestore(&chip->reg_lock, flags);212	if (invert)213		val = 1 - val;214	ucontrol->value.integer.value[0] = val;215	return 0;216}217 218static int snd_pmac_awacs_put_switch(struct snd_kcontrol *kcontrol,219				     struct snd_ctl_elem_value *ucontrol)220{221	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);222	int reg = kcontrol->private_value & 0xff;223	int shift = (kcontrol->private_value >> 8) & 0xff;224	int invert = (kcontrol->private_value >> 16) & 1;225	int mask = 1 << shift;226	int val, changed;227	unsigned long flags;228 229	spin_lock_irqsave(&chip->reg_lock, flags);230	val = chip->awacs_reg[reg] & ~mask;231	if (ucontrol->value.integer.value[0] != invert)232		val |= mask;233	changed = chip->awacs_reg[reg] != val;234	if (changed)235		snd_pmac_awacs_write_reg(chip, reg, val);236	spin_unlock_irqrestore(&chip->reg_lock, flags);237	return changed;238}239 240#define AWACS_SWITCH(xname, xreg, xshift, xinvert) \241{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \242  .info = snd_pmac_boolean_mono_info, \243  .get = snd_pmac_awacs_get_switch, \244  .put = snd_pmac_awacs_put_switch, \245  .private_value = (xreg) | ((xshift) << 8) | ((xinvert) << 16) }246 247 248#ifdef PMAC_AMP_AVAIL249/*250 * controls for perch/whisper extension cards, e.g. G3 desktop251 *252 * TDA7433 connected via i2c address 0x45 (= 0x8a),253 * accessed through cuda254 */255static void awacs_set_cuda(int reg, int val)256{257	struct adb_request req;258	cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, 0x8a,259			reg, val);260	while (! req.complete)261		cuda_poll();262}263 264/*265 * level = 0 - 14, 7 = 0 dB266 */267static void awacs_amp_set_tone(struct awacs_amp *amp, int bass, int treble)268{269	amp->amp_tone[0] = bass;270	amp->amp_tone[1] = treble;271	if (bass > 7)272		bass = (14 - bass) + 8;273	if (treble > 7)274		treble = (14 - treble) + 8;275	awacs_set_cuda(2, (bass << 4) | treble);276}277 278/*279 * vol = 0 - 31 (attenuation), 32 = mute bit, stereo280 */281static int awacs_amp_set_vol(struct awacs_amp *amp, int index,282			     int lvol, int rvol, int do_check)283{284	if (do_check && amp->amp_vol[index][0] == lvol &&285			amp->amp_vol[index][1] == rvol)286		return 0;287	awacs_set_cuda(3 + index, lvol);288	awacs_set_cuda(5 + index, rvol);289	amp->amp_vol[index][0] = lvol;290	amp->amp_vol[index][1] = rvol;291	return 1;292}293 294/*295 * 0 = -79 dB, 79 = 0 dB, 99 = +20 dB296 */297static void awacs_amp_set_master(struct awacs_amp *amp, int vol)298{299	amp->amp_master = vol;300	if (vol <= 79)301		vol = 32 + (79 - vol);302	else303		vol = 32 - (vol - 79);304	awacs_set_cuda(1, vol);305}306 307static void awacs_amp_free(struct snd_pmac *chip)308{309	struct awacs_amp *amp = chip->mixer_data;310	if (!amp)311		return;312	kfree(amp);313	chip->mixer_data = NULL;314	chip->mixer_free = NULL;315}316 317 318/*319 * mixer controls320 */321static int snd_pmac_awacs_info_volume_amp(struct snd_kcontrol *kcontrol,322					  struct snd_ctl_elem_info *uinfo)323{324	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;325	uinfo->count = 2;326	uinfo->value.integer.min = 0;327	uinfo->value.integer.max = 31;328	return 0;329}330 331static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol,332					 struct snd_ctl_elem_value *ucontrol)333{334	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);335	int index = kcontrol->private_value;336	struct awacs_amp *amp = chip->mixer_data;337 338	ucontrol->value.integer.value[0] = 31 - (amp->amp_vol[index][0] & 31);339	ucontrol->value.integer.value[1] = 31 - (amp->amp_vol[index][1] & 31);340	return 0;341}342 343static int snd_pmac_awacs_put_volume_amp(struct snd_kcontrol *kcontrol,344					 struct snd_ctl_elem_value *ucontrol)345{346	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);347	int index = kcontrol->private_value;348	int vol[2];349	struct awacs_amp *amp = chip->mixer_data;350 351	vol[0] = (31 - (ucontrol->value.integer.value[0] & 31))352		| (amp->amp_vol[index][0] & 32);353	vol[1] = (31 - (ucontrol->value.integer.value[1] & 31))354		| (amp->amp_vol[index][1] & 32);355	return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);356}357 358static int snd_pmac_awacs_get_switch_amp(struct snd_kcontrol *kcontrol,359					 struct snd_ctl_elem_value *ucontrol)360{361	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);362	int index = kcontrol->private_value;363	struct awacs_amp *amp = chip->mixer_data;364 365	ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32)366					? 0 : 1;367	ucontrol->value.integer.value[1] = (amp->amp_vol[index][1] & 32)368					? 0 : 1;369	return 0;370}371 372static int snd_pmac_awacs_put_switch_amp(struct snd_kcontrol *kcontrol,373					 struct snd_ctl_elem_value *ucontrol)374{375	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);376	int index = kcontrol->private_value;377	int vol[2];378	struct awacs_amp *amp = chip->mixer_data;379 380	vol[0] = (ucontrol->value.integer.value[0] ? 0 : 32)381		| (amp->amp_vol[index][0] & 31);382	vol[1] = (ucontrol->value.integer.value[1] ? 0 : 32)383		| (amp->amp_vol[index][1] & 31);384	return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);385}386 387static int snd_pmac_awacs_info_tone_amp(struct snd_kcontrol *kcontrol,388					struct snd_ctl_elem_info *uinfo)389{390	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;391	uinfo->count = 1;392	uinfo->value.integer.min = 0;393	uinfo->value.integer.max = 14;394	return 0;395}396 397static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol,398				       struct snd_ctl_elem_value *ucontrol)399{400	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);401	int index = kcontrol->private_value;402	struct awacs_amp *amp = chip->mixer_data;403 404	ucontrol->value.integer.value[0] = amp->amp_tone[index];405	return 0;406}407 408static int snd_pmac_awacs_put_tone_amp(struct snd_kcontrol *kcontrol,409				       struct snd_ctl_elem_value *ucontrol)410{411	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);412	int index = kcontrol->private_value;413	struct awacs_amp *amp = chip->mixer_data;414	unsigned int val;415 416	val = ucontrol->value.integer.value[0];417	if (val > 14)418		return -EINVAL;419	if (val != amp->amp_tone[index]) {420		amp->amp_tone[index] = val;421		awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);422		return 1;423	}424	return 0;425}426 427static int snd_pmac_awacs_info_master_amp(struct snd_kcontrol *kcontrol,428					  struct snd_ctl_elem_info *uinfo)429{430	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;431	uinfo->count = 1;432	uinfo->value.integer.min = 0;433	uinfo->value.integer.max = 99;434	return 0;435}436 437static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol,438					 struct snd_ctl_elem_value *ucontrol)439{440	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);441	struct awacs_amp *amp = chip->mixer_data;442 443	ucontrol->value.integer.value[0] = amp->amp_master;444	return 0;445}446 447static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol,448					 struct snd_ctl_elem_value *ucontrol)449{450	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);451	struct awacs_amp *amp = chip->mixer_data;452	unsigned int val;453 454	val = ucontrol->value.integer.value[0];455	if (val > 99)456		return -EINVAL;457	if (val != amp->amp_master) {458		amp->amp_master = val;459		awacs_amp_set_master(amp, amp->amp_master);460		return 1;461	}462	return 0;463}464 465#define AMP_CH_SPK	0466#define AMP_CH_HD	1467 468static const struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] = {469	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,470	  .name = "Speaker Playback Volume",471	  .info = snd_pmac_awacs_info_volume_amp,472	  .get = snd_pmac_awacs_get_volume_amp,473	  .put = snd_pmac_awacs_put_volume_amp,474	  .private_value = AMP_CH_SPK,475	},476	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,477	  .name = "Headphone Playback Volume",478	  .info = snd_pmac_awacs_info_volume_amp,479	  .get = snd_pmac_awacs_get_volume_amp,480	  .put = snd_pmac_awacs_put_volume_amp,481	  .private_value = AMP_CH_HD,482	},483	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,484	  .name = "Tone Control - Bass",485	  .info = snd_pmac_awacs_info_tone_amp,486	  .get = snd_pmac_awacs_get_tone_amp,487	  .put = snd_pmac_awacs_put_tone_amp,488	  .private_value = 0,489	},490	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,491	  .name = "Tone Control - Treble",492	  .info = snd_pmac_awacs_info_tone_amp,493	  .get = snd_pmac_awacs_get_tone_amp,494	  .put = snd_pmac_awacs_put_tone_amp,495	  .private_value = 1,496	},497	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,498	  .name = "Amp Master Playback Volume",499	  .info = snd_pmac_awacs_info_master_amp,500	  .get = snd_pmac_awacs_get_master_amp,501	  .put = snd_pmac_awacs_put_master_amp,502	},503};504 505static const struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {506	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,507	.name = "Headphone Playback Switch",508	.info = snd_pmac_boolean_stereo_info,509	.get = snd_pmac_awacs_get_switch_amp,510	.put = snd_pmac_awacs_put_switch_amp,511	.private_value = AMP_CH_HD,512};513 514static const struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = {515	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,516	.name = "Speaker Playback Switch",517	.info = snd_pmac_boolean_stereo_info,518	.get = snd_pmac_awacs_get_switch_amp,519	.put = snd_pmac_awacs_put_switch_amp,520	.private_value = AMP_CH_SPK,521};522 523#endif /* PMAC_AMP_AVAIL */524 525 526/*527 * mic boost for screamer528 */529static int snd_pmac_screamer_mic_boost_info(struct snd_kcontrol *kcontrol,530					    struct snd_ctl_elem_info *uinfo)531{532	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;533	uinfo->count = 1;534	uinfo->value.integer.min = 0;535	uinfo->value.integer.max = 3;536	return 0;537}538 539static int snd_pmac_screamer_mic_boost_get(struct snd_kcontrol *kcontrol,540					   struct snd_ctl_elem_value *ucontrol)541{542	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);543	int val = 0;544	unsigned long flags;545 546	spin_lock_irqsave(&chip->reg_lock, flags);547	if (chip->awacs_reg[6] & MASK_MIC_BOOST)548		val |= 2;549	if (chip->awacs_reg[0] & MASK_GAINLINE)550		val |= 1;551	spin_unlock_irqrestore(&chip->reg_lock, flags);552	ucontrol->value.integer.value[0] = val;553	return 0;554}555 556static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,557					   struct snd_ctl_elem_value *ucontrol)558{559	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);560	int changed = 0;561	int val0, val6;562	unsigned long flags;563 564	spin_lock_irqsave(&chip->reg_lock, flags);565	val0 = chip->awacs_reg[0] & ~MASK_GAINLINE;566	val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST;567	if (ucontrol->value.integer.value[0] & 1)568		val0 |= MASK_GAINLINE;569	if (ucontrol->value.integer.value[0] & 2)570		val6 |= MASK_MIC_BOOST;571	if (val0 != chip->awacs_reg[0]) {572		snd_pmac_awacs_write_reg(chip, 0, val0);573		changed = 1;574	}575	if (val6 != chip->awacs_reg[6]) {576		snd_pmac_awacs_write_reg(chip, 6, val6);577		changed = 1;578	}579	spin_unlock_irqrestore(&chip->reg_lock, flags);580	return changed;581}582 583/*584 * lists of mixer elements585 */586static const struct snd_kcontrol_new snd_pmac_awacs_mixers[] = {587	AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),588	AWACS_VOLUME("Master Capture Volume", 0, 4, 0),589/*	AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */590};591 592static const struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] = {593	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),594	AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),595	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),596	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),597};598 599static const struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] = {600	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),601};602 603static const struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] = {604	AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),605	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),606};607 608static const struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] = {609	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),610	AWACS_VOLUME("Master Playback Volume", 5, 6, 1),611	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),612	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),613};614 615static const struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] = {616	AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),617	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),618	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),619};620 621static const struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] = {622	AWACS_VOLUME("Headphone Playback Volume", 2, 6, 1),623};624 625static const struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] = {626	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),627	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),628};629 630/* FIXME: is this correct order?631 * screamer (powerbook G3 pismo) seems to have different bits...632 */633static const struct snd_kcontrol_new snd_pmac_awacs_mixers2[] = {634	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),635	AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0),636};637 638static const struct snd_kcontrol_new snd_pmac_screamer_mixers2[] = {639	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),640	AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),641};642 643static const struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] = {644	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),645};646 647static const struct snd_kcontrol_new snd_pmac_awacs_master_sw =648AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);649 650static const struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac =651AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);652 653static const struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 =654AWACS_SWITCH("Headphone Playback Switch", 1, SHIFT_HDMUTE, 1);655 656static const struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] = {657	AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),658};659 660static const struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] = {661	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,662	  .name = "Mic Boost Capture Volume",663	  .info = snd_pmac_screamer_mic_boost_info,664	  .get = snd_pmac_screamer_mic_boost_get,665	  .put = snd_pmac_screamer_mic_boost_put,666	},667};668 669static const struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] =670{671	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),672};673 674static const struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] =675{676	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),677	AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),678};679 680static const struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] =681{682	AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),683	AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),684};685 686static const struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] = {687	AWACS_VOLUME("Speaker Playback Volume", 4, 6, 1),688};689 690static const struct snd_kcontrol_new snd_pmac_awacs_speaker_sw =691AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);692 693static const struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 =694AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 1);695 696static const struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 =697AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);698 699 700/*701 * add new mixer elements to the card702 */703static int build_mixers(struct snd_pmac *chip, int nums,704			const struct snd_kcontrol_new *mixers)705{706	int i, err;707 708	for (i = 0; i < nums; i++) {709		err = snd_ctl_add(chip->card, snd_ctl_new1(&mixers[i], chip));710		if (err < 0)711			return err;712	}713	return 0;714}715 716 717/*718 * restore all registers719 */720static void awacs_restore_all_regs(struct snd_pmac *chip)721{722	snd_pmac_awacs_write_noreg(chip, 0, chip->awacs_reg[0]);723	snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);724	snd_pmac_awacs_write_noreg(chip, 2, chip->awacs_reg[2]);725	snd_pmac_awacs_write_noreg(chip, 4, chip->awacs_reg[4]);726	if (chip->model == PMAC_SCREAMER) {727		snd_pmac_awacs_write_noreg(chip, 5, chip->awacs_reg[5]);728		snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);729		snd_pmac_awacs_write_noreg(chip, 7, chip->awacs_reg[7]);730	}731}732 733#ifdef CONFIG_PM734static void snd_pmac_awacs_suspend(struct snd_pmac *chip)735{736	snd_pmac_awacs_write_noreg(chip, 1, (chip->awacs_reg[1]737					     | MASK_AMUTE | MASK_CMUTE));738}739 740static void snd_pmac_awacs_resume(struct snd_pmac *chip)741{742	if (of_machine_is_compatible("PowerBook3,1")743	    || of_machine_is_compatible("PowerBook3,2")) {744		msleep(100);745		snd_pmac_awacs_write_reg(chip, 1,746			chip->awacs_reg[1] & ~MASK_PAROUT);747		msleep(300);748	}749 750	awacs_restore_all_regs(chip);751	if (chip->model == PMAC_SCREAMER) {752		/* reset power bits in reg 6 */753		mdelay(5);754		snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);755	}756	screamer_recalibrate(chip);757#ifdef PMAC_AMP_AVAIL758	if (chip->mixer_data) {759		struct awacs_amp *amp = chip->mixer_data;760		awacs_amp_set_vol(amp, 0,761				  amp->amp_vol[0][0], amp->amp_vol[0][1], 0);762		awacs_amp_set_vol(amp, 1,763				  amp->amp_vol[1][0], amp->amp_vol[1][1], 0);764		awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);765		awacs_amp_set_master(amp, amp->amp_master);766	}767#endif768}769#endif /* CONFIG_PM */770 771#define IS_PM7500 (of_machine_is_compatible("AAPL,7500") \772		|| of_machine_is_compatible("AAPL,8500") \773		|| of_machine_is_compatible("AAPL,9500"))774#define IS_PM5500 (of_machine_is_compatible("AAPL,e411"))775#define IS_BEIGE (of_machine_is_compatible("AAPL,Gossamer"))776#define IS_IMAC1 (of_machine_is_compatible("PowerMac2,1"))777#define IS_IMAC2 (of_machine_is_compatible("PowerMac2,2") \778		|| of_machine_is_compatible("PowerMac4,1"))779#define IS_G4AGP (of_machine_is_compatible("PowerMac3,1"))780#define IS_LOMBARD (of_machine_is_compatible("PowerBook1,1"))781 782static int imac1, imac2;783 784#ifdef PMAC_SUPPORT_AUTOMUTE785/*786 * auto-mute stuffs787 */788static int snd_pmac_awacs_detect_headphone(struct snd_pmac *chip)789{790	return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0;791}792 793#ifdef PMAC_AMP_AVAIL794static int toggle_amp_mute(struct awacs_amp *amp, int index, int mute)795{796	int vol[2];797	vol[0] = amp->amp_vol[index][0] & 31;798	vol[1] = amp->amp_vol[index][1] & 31;799	if (mute) {800		vol[0] |= 32;801		vol[1] |= 32;802	}803	return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);804}805#endif806 807static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)808{809	if (chip->auto_mute) {810#ifdef PMAC_AMP_AVAIL811		if (chip->mixer_data) {812			struct awacs_amp *amp = chip->mixer_data;813			int changed;814			if (snd_pmac_awacs_detect_headphone(chip)) {815				changed = toggle_amp_mute(amp, AMP_CH_HD, 0);816				changed |= toggle_amp_mute(amp, AMP_CH_SPK, 1);817			} else {818				changed = toggle_amp_mute(amp, AMP_CH_HD, 1);819				changed |= toggle_amp_mute(amp, AMP_CH_SPK, 0);820			}821			if (do_notify && ! changed)822				return;823		} else824#endif825		{826			int reg = chip->awacs_reg[1]827				| (MASK_HDMUTE | MASK_SPKMUTE);828			if (imac1) {829				reg &= ~MASK_SPKMUTE;830				reg |= MASK_PAROUT1;831			} else if (imac2) {832				reg &= ~MASK_SPKMUTE;833				reg &= ~MASK_PAROUT1;834			}835			if (snd_pmac_awacs_detect_headphone(chip))836				reg &= ~MASK_HDMUTE;837			else if (imac1)838				reg &= ~MASK_PAROUT1;839			else if (imac2)840				reg |= MASK_PAROUT1;841			else842				reg &= ~MASK_SPKMUTE;843			if (do_notify && reg == chip->awacs_reg[1])844				return;845			snd_pmac_awacs_write_reg(chip, 1, reg);846		}847		if (do_notify) {848			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,849				       &chip->master_sw_ctl->id);850			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,851				       &chip->speaker_sw_ctl->id);852			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,853				       &chip->hp_detect_ctl->id);854		}855	}856}857#endif /* PMAC_SUPPORT_AUTOMUTE */858 859 860/*861 * initialize chip862 */863int864snd_pmac_awacs_init(struct snd_pmac *chip)865{866	int pm7500 = IS_PM7500;867	int pm5500 = IS_PM5500;868	int beige = IS_BEIGE;869	int g4agp = IS_G4AGP;870	int lombard = IS_LOMBARD;871	int imac;872	int err, vol;873	struct snd_kcontrol *vmaster_sw, *vmaster_vol;874	struct snd_kcontrol *master_vol, *speaker_vol;875 876	imac1 = IS_IMAC1;877	imac2 = IS_IMAC2;878	imac = imac1 || imac2;879	/* looks like MASK_GAINLINE triggers something, so we set here880	 * as start-up881	 */882	chip->awacs_reg[0] = MASK_MUX_CD | 0xff | MASK_GAINLINE;883	chip->awacs_reg[1] = MASK_CMUTE | MASK_AMUTE;884	/* FIXME: Only machines with external SRS module need MASK_PAROUT */885	if (chip->has_iic || chip->device_id == 0x5 ||886	    /* chip->_device_id == 0x8 || */887	    chip->device_id == 0xb)888		chip->awacs_reg[1] |= MASK_PAROUT;889	/* get default volume from nvram */890	// vol = (~nvram_read_byte(0x1308) & 7) << 1;891	// vol = ((pmac_xpram_read( 8 ) & 7 ) << 1 );892	vol = 0x0f; /* no, on alsa, muted as default */893	vol = vol + (vol << 6);894	chip->awacs_reg[2] = vol;895	chip->awacs_reg[4] = vol;896	if (chip->model == PMAC_SCREAMER) {897		/* FIXME: screamer has loopthru vol control */898		chip->awacs_reg[5] = vol;899		/* FIXME: maybe should be vol << 3 for PCMCIA speaker */900		chip->awacs_reg[6] = MASK_MIC_BOOST;901		chip->awacs_reg[7] = 0;902	}903 904	awacs_restore_all_regs(chip);905	chip->manufacturer = (in_le32(&chip->awacs->codec_stat) >> 8) & 0xf;906	screamer_recalibrate(chip);907 908	chip->revision = (in_le32(&chip->awacs->codec_stat) >> 12) & 0xf;909#ifdef PMAC_AMP_AVAIL910	if (chip->revision == 3 && chip->has_iic && CHECK_CUDA_AMP()) {911		struct awacs_amp *amp = kzalloc(sizeof(*amp), GFP_KERNEL);912		if (! amp)913			return -ENOMEM;914		chip->mixer_data = amp;915		chip->mixer_free = awacs_amp_free;916		/* mute and zero vol */917		awacs_amp_set_vol(amp, 0, 63, 63, 0);918		awacs_amp_set_vol(amp, 1, 63, 63, 0);919		awacs_amp_set_tone(amp, 7, 7); /* 0 dB */920		awacs_amp_set_master(amp, 79); /* 0 dB */921	}922#endif /* PMAC_AMP_AVAIL */923 924	if (chip->hp_stat_mask == 0) {925		/* set headphone-jack detection bit */926		switch (chip->model) {927		case PMAC_AWACS:928			chip->hp_stat_mask = pm7500 || pm5500 ? MASK_HDPCONN929				: MASK_LOCONN;930			break;931		case PMAC_SCREAMER:932			switch (chip->device_id) {933			case 0x08:934			case 0x0B:935				chip->hp_stat_mask = imac936					? MASK_LOCONN_IMAC |937					MASK_HDPLCONN_IMAC |938					MASK_HDPRCONN_IMAC939					: MASK_HDPCONN;940				break;941			case 0x00:942			case 0x05:943				chip->hp_stat_mask = MASK_LOCONN;944				break;945			default:946				chip->hp_stat_mask = MASK_HDPCONN;947				break;948			}949			break;950		default:951			snd_BUG();952			break;953		}954	}955 956	/*957	 * build mixers958	 */959	strcpy(chip->card->mixername, "PowerMac AWACS");960 961	err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),962				snd_pmac_awacs_mixers);963	if (err < 0)964		return err;965	if (beige || g4agp)966		;967	else if (chip->model == PMAC_SCREAMER || pm5500)968		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),969				   snd_pmac_screamer_mixers2);970	else if (!pm7500)971		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2),972				   snd_pmac_awacs_mixers2);973	if (err < 0)974		return err;975	if (pm5500) {976		err = build_mixers(chip,977				   ARRAY_SIZE(snd_pmac_awacs_mixers2_pmac5500),978				   snd_pmac_awacs_mixers2_pmac5500);979		if (err < 0)980			return err;981	}982	master_vol = NULL;983	if (pm7500)984		err = build_mixers(chip,985				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),986				   snd_pmac_awacs_mixers_pmac7500);987	else if (pm5500)988		err = snd_ctl_add(chip->card,989		    (master_vol = snd_ctl_new1(snd_pmac_awacs_mixers_pmac5500,990						chip)));991	else if (beige)992		err = build_mixers(chip,993				   ARRAY_SIZE(snd_pmac_screamer_mixers_beige),994				   snd_pmac_screamer_mixers_beige);995	else if (imac || lombard) {996		err = snd_ctl_add(chip->card,997		    (master_vol = snd_ctl_new1(snd_pmac_screamer_mixers_lo,998						chip)));999		if (err < 0)1000			return err;1001		err = build_mixers(chip,1002				   ARRAY_SIZE(snd_pmac_screamer_mixers_imac),1003				   snd_pmac_screamer_mixers_imac);1004	} else if (g4agp)1005		err = build_mixers(chip,1006				   ARRAY_SIZE(snd_pmac_screamer_mixers_g4agp),1007				   snd_pmac_screamer_mixers_g4agp);1008	else1009		err = build_mixers(chip,1010				   ARRAY_SIZE(snd_pmac_awacs_mixers_pmac),1011				   snd_pmac_awacs_mixers_pmac);1012	if (err < 0)1013		return err;1014	chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac || g4agp || lombard)1015			? &snd_pmac_awacs_master_sw_imac1016			: pm55001017			? &snd_pmac_awacs_master_sw_pmac55001018			: &snd_pmac_awacs_master_sw, chip);1019	err = snd_ctl_add(chip->card, chip->master_sw_ctl);1020	if (err < 0)1021		return err;1022#ifdef PMAC_AMP_AVAIL1023	if (chip->mixer_data) {1024		/* use amplifier.  the signal is connected from route A1025		 * to the amp.  the amp has its headphone and speaker1026		 * volumes and mute switches, so we use them instead of1027		 * screamer registers.1028		 * in this case, it seems the route C is not used.1029		 */1030		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),1031					snd_pmac_awacs_amp_vol);1032		if (err < 0)1033			return err;1034		/* overwrite */1035		chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_hp_sw,1036							chip);1037		err = snd_ctl_add(chip->card, chip->master_sw_ctl);1038		if (err < 0)1039			return err;1040		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_amp_spk_sw,1041							chip);1042		err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);1043		if (err < 0)1044			return err;1045	} else1046#endif /* PMAC_AMP_AVAIL */1047	{1048		/* route A = headphone, route C = speaker */1049		err = snd_ctl_add(chip->card,1050		    (speaker_vol = snd_ctl_new1(snd_pmac_awacs_speaker_vol,1051						chip)));1052		if (err < 0)1053			return err;1054		chip->speaker_sw_ctl = snd_ctl_new1(imac11055				? &snd_pmac_awacs_speaker_sw_imac11056				: imac21057				? &snd_pmac_awacs_speaker_sw_imac21058				: &snd_pmac_awacs_speaker_sw, chip);1059		err = snd_ctl_add(chip->card, chip->speaker_sw_ctl);1060		if (err < 0)1061			return err;1062	}1063 1064	if (pm5500 || imac || lombard) {1065		vmaster_sw = snd_ctl_make_virtual_master(1066			"Master Playback Switch", (unsigned int *) NULL);1067		err = snd_ctl_add_follower_uncached(vmaster_sw,1068						    chip->master_sw_ctl);1069		if (err < 0)1070			return err;1071		err = snd_ctl_add_follower_uncached(vmaster_sw,1072						    chip->speaker_sw_ctl);1073		if (err < 0)1074			return err;1075		err = snd_ctl_add(chip->card, vmaster_sw);1076		if (err < 0)1077			return err;1078		vmaster_vol = snd_ctl_make_virtual_master(1079			"Master Playback Volume", (unsigned int *) NULL);1080		err = snd_ctl_add_follower(vmaster_vol, master_vol);1081		if (err < 0)1082			return err;1083		err = snd_ctl_add_follower(vmaster_vol, speaker_vol);1084		if (err < 0)1085			return err;1086		err = snd_ctl_add(chip->card, vmaster_vol);1087		if (err < 0)1088			return err;1089	}1090 1091	if (beige || g4agp)1092		err = build_mixers(chip,1093				ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige),1094				snd_pmac_screamer_mic_boost_beige);1095	else if (imac)1096		err = build_mixers(chip,1097				ARRAY_SIZE(snd_pmac_screamer_mic_boost_imac),1098				snd_pmac_screamer_mic_boost_imac);1099	else if (chip->model == PMAC_SCREAMER)1100		err = build_mixers(chip,1101				ARRAY_SIZE(snd_pmac_screamer_mic_boost),1102				snd_pmac_screamer_mic_boost);1103	else if (pm7500)1104		err = build_mixers(chip,1105				ARRAY_SIZE(snd_pmac_awacs_mic_boost_pmac7500),1106				snd_pmac_awacs_mic_boost_pmac7500);1107	else1108		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),1109				snd_pmac_awacs_mic_boost);1110	if (err < 0)1111		return err;1112 1113	/*1114	 * set lowlevel callbacks1115	 */1116	chip->set_format = snd_pmac_awacs_set_format;1117#ifdef CONFIG_PM1118	chip->suspend = snd_pmac_awacs_suspend;1119	chip->resume = snd_pmac_awacs_resume;1120#endif1121#ifdef PMAC_SUPPORT_AUTOMUTE1122	err = snd_pmac_add_automute(chip);1123	if (err < 0)1124		return err;1125	chip->detect_headphone = snd_pmac_awacs_detect_headphone;1126	chip->update_automute = snd_pmac_awacs_update_automute;1127	snd_pmac_awacs_update_automute(chip, 0); /* update the status only */1128#endif1129	if (chip->model == PMAC_SCREAMER) {1130		snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);1131		snd_pmac_awacs_write_noreg(chip, 0, chip->awacs_reg[0]);1132	}1133 1134	return 0;1135}1136