File Index
Files and directories
Sign in
FILE

awacs.c

File preview with syntax highlighting.

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