tumbler.c 38.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * PMac Tumbler/Snapper lowlevel functions
 *
 * Copyright (c) by Takashi Iwai <tiwai@suse.de>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 *   Rene Rebe <rene.rebe@gmx.net>:
 *     * update from shadow registers on wakeup and headphone plug
 *     * automatically toggle DRC on headphone plug
 *	
 */


#include <linux/init.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
33
#include <linux/string.h>
L
Linus Torvalds 已提交
34 35 36
#include <sound/core.h>
#include <asm/io.h>
#include <asm/irq.h>
37
#include <asm/machdep.h>
L
Linus Torvalds 已提交
38 39 40 41
#include <asm/pmac_feature.h>
#include "pmac.h"
#include "tumbler_volume.h"

42 43 44
#undef DEBUG

#ifdef DEBUG
45
#define DBG(fmt...) printk(KERN_DEBUG fmt)
46 47 48 49
#else
#define DBG(fmt...)
#endif

50 51
#define IS_G4DA (machine_is_compatible("PowerMac3,4"))

L
Linus Torvalds 已提交
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
/* i2c address for tumbler */
#define TAS_I2C_ADDR	0x34

/* registers */
#define TAS_REG_MCS	0x01	/* main control */
#define TAS_REG_DRC	0x02
#define TAS_REG_VOL	0x04
#define TAS_REG_TREBLE	0x05
#define TAS_REG_BASS	0x06
#define TAS_REG_INPUT1	0x07
#define TAS_REG_INPUT2	0x08

/* tas3001c */
#define TAS_REG_PCM	TAS_REG_INPUT1
 
/* tas3004 */
#define TAS_REG_LMIX	TAS_REG_INPUT1
#define TAS_REG_RMIX	TAS_REG_INPUT2
#define TAS_REG_MCS2	0x43		/* main control 2 */
#define TAS_REG_ACS	0x40		/* analog control */

/* mono volumes for tas3001c/tas3004 */
enum {
	VOL_IDX_PCM_MONO, /* tas3001c only */
	VOL_IDX_BASS, VOL_IDX_TREBLE,
	VOL_IDX_LAST_MONO
};

/* stereo volumes for tas3004 */
enum {
	VOL_IDX_PCM, VOL_IDX_PCM2, VOL_IDX_ADC,
	VOL_IDX_LAST_MIX
};

86
struct pmac_gpio {
L
Linus Torvalds 已提交
87
	unsigned int addr;
88 89 90
	u8 active_val;
	u8 inactive_val;
	u8 active_state;
91 92 93 94 95 96 97 98 99 100
};

struct pmac_tumbler {
	struct pmac_keywest i2c;
	struct pmac_gpio audio_reset;
	struct pmac_gpio amp_mute;
	struct pmac_gpio line_mute;
	struct pmac_gpio line_detect;
	struct pmac_gpio hp_mute;
	struct pmac_gpio hp_detect;
L
Linus Torvalds 已提交
101
	int headphone_irq;
102
	int lineout_irq;
103
	unsigned int save_master_vol[2];
L
Linus Torvalds 已提交
104
	unsigned int master_vol[2];
105
	unsigned int save_master_switch[2];
L
Linus Torvalds 已提交
106 107 108 109 110 111
	unsigned int master_switch[2];
	unsigned int mono_vol[VOL_IDX_LAST_MONO];
	unsigned int mix_vol[VOL_IDX_LAST_MIX][2]; /* stereo volumes for tas3004 */
	int drc_range;
	int drc_enable;
	int capture_source;
112 113 114 115
	int anded_reset;
	int auto_mute_notify;
	int reset_on_sleep;
	u8  acs;
116
};
L
Linus Torvalds 已提交
117 118 119 120 121


/*
 */

122
static int send_init_client(struct pmac_keywest *i2c, unsigned int *regs)
L
Linus Torvalds 已提交
123 124 125 126 127 128 129 130
{
	while (*regs > 0) {
		int err, count = 10;
		do {
			err = i2c_smbus_write_byte_data(i2c->client,
							regs[0], regs[1]);
			if (err >= 0)
				break;
131
			DBG("(W) i2c error %d\n", err);
L
Linus Torvalds 已提交
132 133 134 135 136 137 138 139 140 141
			mdelay(10);
		} while (count--);
		if (err < 0)
			return -ENXIO;
		regs += 2;
	}
	return 0;
}


142
static int tumbler_init_client(struct pmac_keywest *i2c)
L
Linus Torvalds 已提交
143 144 145 146 147 148
{
	static unsigned int regs[] = {
		/* normal operation, SCLK=64fps, i2s output, i2s input, 16bit width */
		TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0,
		0, /* terminator */
	};
149
	DBG("(I) tumbler init client\n");
L
Linus Torvalds 已提交
150 151 152
	return send_init_client(i2c, regs);
}

153
static int snapper_init_client(struct pmac_keywest *i2c)
L
Linus Torvalds 已提交
154 155 156 157 158 159 160 161 162 163
{
	static unsigned int regs[] = {
		/* normal operation, SCLK=64fps, i2s output, 16bit width */
		TAS_REG_MCS, (1<<6)|(2<<4)|0,
		/* normal operation, all-pass mode */
		TAS_REG_MCS2, (1<<1),
		/* normal output, no deemphasis, A input, power-up, line-in */
		TAS_REG_ACS, 0,
		0, /* terminator */
	};
164
	DBG("(I) snapper init client\n");
L
Linus Torvalds 已提交
165 166 167 168 169 170 171 172 173 174 175 176
	return send_init_client(i2c, regs);
}
	
/*
 * gpio access
 */
#define do_gpio_write(gp, val) \
	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val)
#define do_gpio_read(gp) \
	pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0)
#define tumbler_gpio_free(gp) /* NOP */

177
static void write_audio_gpio(struct pmac_gpio *gp, int active)
L
Linus Torvalds 已提交
178 179 180
{
	if (! gp->addr)
		return;
181 182 183
	active = active ? gp->active_val : gp->inactive_val;
	do_gpio_write(gp, active);
	DBG("(I) gpio %x write %d\n", gp->addr, active);
L
Linus Torvalds 已提交
184 185
}

186
static int check_audio_gpio(struct pmac_gpio *gp)
187 188 189 190 191 192 193 194
{
	int ret;

	if (! gp->addr)
		return 0;

	ret = do_gpio_read(gp);

195
	return (ret & 0x1) == (gp->active_val & 0x1);
196 197
}

198
static int read_audio_gpio(struct pmac_gpio *gp)
L
Linus Torvalds 已提交
199 200 201 202
{
	int ret;
	if (! gp->addr)
		return 0;
203 204
	ret = do_gpio_read(gp);
	ret = (ret & 0x02) !=0;
L
Linus Torvalds 已提交
205 206 207 208 209 210
	return ret == gp->active_state;
}

/*
 * update master volume
 */
211
static int tumbler_set_master_volume(struct pmac_tumbler *mix)
L
Linus Torvalds 已提交
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
{
	unsigned char block[6];
	unsigned int left_vol, right_vol;
  
	if (! mix->i2c.client)
		return -ENODEV;
  
	if (! mix->master_switch[0])
		left_vol = 0;
	else {
		left_vol = mix->master_vol[0];
		if (left_vol >= ARRAY_SIZE(master_volume_table))
			left_vol = ARRAY_SIZE(master_volume_table) - 1;
		left_vol = master_volume_table[left_vol];
	}
	if (! mix->master_switch[1])
		right_vol = 0;
	else {
		right_vol = mix->master_vol[1];
		if (right_vol >= ARRAY_SIZE(master_volume_table))
			right_vol = ARRAY_SIZE(master_volume_table) - 1;
		right_vol = master_volume_table[right_vol];
	}

	block[0] = (left_vol >> 16) & 0xff;
	block[1] = (left_vol >> 8)  & 0xff;
	block[2] = (left_vol >> 0)  & 0xff;

	block[3] = (right_vol >> 16) & 0xff;
	block[4] = (right_vol >> 8)  & 0xff;
	block[5] = (right_vol >> 0)  & 0xff;
  
244 245
	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_VOL, 6,
					   block) < 0) {
246
		snd_printk(KERN_ERR "failed to set volume \n");
L
Linus Torvalds 已提交
247 248 249 250 251 252 253
		return -EINVAL;
	}
	return 0;
}


/* output volume */
254 255
static int tumbler_info_master_volume(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
256 257 258 259 260 261 262 263
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 2;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = ARRAY_SIZE(master_volume_table) - 1;
	return 0;
}

264 265
static int tumbler_get_master_volume(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
266
{
267 268
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix = chip->mixer_data;
269

L
Linus Torvalds 已提交
270 271 272 273 274
	ucontrol->value.integer.value[0] = mix->master_vol[0];
	ucontrol->value.integer.value[1] = mix->master_vol[1];
	return 0;
}

275 276
static int tumbler_put_master_volume(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
277
{
278 279
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix = chip->mixer_data;
280
	unsigned int vol[2];
L
Linus Torvalds 已提交
281 282
	int change;

283 284 285 286 287 288 289
	vol[0] = ucontrol->value.integer.value[0];
	vol[1] = ucontrol->value.integer.value[1];
	if (vol[0] >= ARRAY_SIZE(master_volume_table) ||
	    vol[1] >= ARRAY_SIZE(master_volume_table))
		return -EINVAL;
	change = mix->master_vol[0] != vol[0] ||
		mix->master_vol[1] != vol[1];
L
Linus Torvalds 已提交
290
	if (change) {
291 292
		mix->master_vol[0] = vol[0];
		mix->master_vol[1] = vol[1];
L
Linus Torvalds 已提交
293 294 295 296 297 298
		tumbler_set_master_volume(mix);
	}
	return change;
}

/* output switch */
299 300
static int tumbler_get_master_switch(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
301
{
302 303
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix = chip->mixer_data;
304

L
Linus Torvalds 已提交
305 306 307 308 309
	ucontrol->value.integer.value[0] = mix->master_switch[0];
	ucontrol->value.integer.value[1] = mix->master_switch[1];
	return 0;
}

310 311
static int tumbler_put_master_switch(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
312
{
313 314
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix = chip->mixer_data;
L
Linus Torvalds 已提交
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
	int change;

	change = mix->master_switch[0] != ucontrol->value.integer.value[0] ||
		mix->master_switch[1] != ucontrol->value.integer.value[1];
	if (change) {
		mix->master_switch[0] = !!ucontrol->value.integer.value[0];
		mix->master_switch[1] = !!ucontrol->value.integer.value[1];
		tumbler_set_master_volume(mix);
	}
	return change;
}


/*
 * TAS3001c dynamic range compression
 */

#define TAS3001_DRC_MAX		0x5f

334
static int tumbler_set_drc(struct pmac_tumbler *mix)
L
Linus Torvalds 已提交
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
{
	unsigned char val[2];

	if (! mix->i2c.client)
		return -ENODEV;
  
	if (mix->drc_enable) {
		val[0] = 0xc1; /* enable, 3:1 compression */
		if (mix->drc_range > TAS3001_DRC_MAX)
			val[1] = 0xf0;
		else if (mix->drc_range < 0)
			val[1] = 0x91;
		else
			val[1] = mix->drc_range + 0x91;
	} else {
		val[0] = 0;
		val[1] = 0;
	}

354 355
	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC,
					   2, val) < 0) {
356
		snd_printk(KERN_ERR "failed to set DRC\n");
L
Linus Torvalds 已提交
357 358 359 360 361 362 363 364 365 366 367
		return -EINVAL;
	}
	return 0;
}

/*
 * TAS3004
 */

#define TAS3004_DRC_MAX		0xef

368
static int snapper_set_drc(struct pmac_tumbler *mix)
L
Linus Torvalds 已提交
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
{
	unsigned char val[6];

	if (! mix->i2c.client)
		return -ENODEV;
  
	if (mix->drc_enable)
		val[0] = 0x50; /* 3:1 above threshold */
	else
		val[0] = 0x51; /* disabled */
	val[1] = 0x02; /* 1:1 below threshold */
	if (mix->drc_range > 0xef)
		val[2] = 0xef;
	else if (mix->drc_range < 0)
		val[2] = 0x00;
	else
		val[2] = mix->drc_range;
	val[3] = 0xb0;
	val[4] = 0x60;
	val[5] = 0xa0;

390 391
	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC,
					   6, val) < 0) {
392
		snd_printk(KERN_ERR "failed to set DRC\n");
L
Linus Torvalds 已提交
393 394 395 396 397
		return -EINVAL;
	}
	return 0;
}

398 399
static int tumbler_info_drc_value(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
400
{
401
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
402 403 404 405 406 407 408 409
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max =
		chip->model == PMAC_TUMBLER ? TAS3001_DRC_MAX : TAS3004_DRC_MAX;
	return 0;
}

410 411
static int tumbler_get_drc_value(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
412
{
413 414
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
L
Linus Torvalds 已提交
415 416 417 418 419 420
	if (! (mix = chip->mixer_data))
		return -ENODEV;
	ucontrol->value.integer.value[0] = mix->drc_range;
	return 0;
}

421 422
static int tumbler_put_drc_value(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
423
{
424 425
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
426
	unsigned int val;
L
Linus Torvalds 已提交
427 428 429 430
	int change;

	if (! (mix = chip->mixer_data))
		return -ENODEV;
431 432 433 434 435 436 437 438 439
	val = ucontrol->value.integer.value[0];
	if (chip->model == PMAC_TUMBLER) {
		if (val > TAS3001_DRC_MAX)
			return -EINVAL;
	} else {
		if (val > TAS3004_DRC_MAX)
			return -EINVAL;
	}
	change = mix->drc_range != val;
L
Linus Torvalds 已提交
440
	if (change) {
441
		mix->drc_range = val;
L
Linus Torvalds 已提交
442 443 444 445 446 447 448 449
		if (chip->model == PMAC_TUMBLER)
			tumbler_set_drc(mix);
		else
			snapper_set_drc(mix);
	}
	return change;
}

450 451
static int tumbler_get_drc_switch(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
452
{
453 454
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
L
Linus Torvalds 已提交
455 456 457 458 459 460
	if (! (mix = chip->mixer_data))
		return -ENODEV;
	ucontrol->value.integer.value[0] = mix->drc_enable;
	return 0;
}

461 462
static int tumbler_put_drc_switch(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
463
{
464 465
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
L
Linus Torvalds 已提交
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
	int change;

	if (! (mix = chip->mixer_data))
		return -ENODEV;
	change = mix->drc_enable != ucontrol->value.integer.value[0];
	if (change) {
		mix->drc_enable = !!ucontrol->value.integer.value[0];
		if (chip->model == PMAC_TUMBLER)
			tumbler_set_drc(mix);
		else
			snapper_set_drc(mix);
	}
	return change;
}


/*
 * mono volumes
 */

struct tumbler_mono_vol {
	int index;
	int reg;
	int bytes;
	unsigned int max;
	unsigned int *table;
};

494 495
static int tumbler_set_mono_volume(struct pmac_tumbler *mix,
				   struct tumbler_mono_vol *info)
L
Linus Torvalds 已提交
496 497 498 499 500 501 502 503 504 505 506 507 508 509
{
	unsigned char block[4];
	unsigned int vol;
	int i;
  
	if (! mix->i2c.client)
		return -ENODEV;
  
	vol = mix->mono_vol[info->index];
	if (vol >= info->max)
		vol = info->max - 1;
	vol = info->table[vol];
	for (i = 0; i < info->bytes; i++)
		block[i] = (vol >> ((info->bytes - i - 1) * 8)) & 0xff;
510 511
	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, info->reg,
					   info->bytes, block) < 0) {
512 513
		snd_printk(KERN_ERR "failed to set mono volume %d\n",
			   info->index);
L
Linus Torvalds 已提交
514 515 516 517 518
		return -EINVAL;
	}
	return 0;
}

519 520
static int tumbler_info_mono(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
521 522 523 524 525 526 527 528 529 530
{
	struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;

	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = info->max - 1;
	return 0;
}

531 532
static int tumbler_get_mono(struct snd_kcontrol *kcontrol,
			    struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
533 534
{
	struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
535 536
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
L
Linus Torvalds 已提交
537 538 539 540 541 542
	if (! (mix = chip->mixer_data))
		return -ENODEV;
	ucontrol->value.integer.value[0] = mix->mono_vol[info->index];
	return 0;
}

543 544
static int tumbler_put_mono(struct snd_kcontrol *kcontrol,
			    struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
545 546
{
	struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
547 548
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
549
	unsigned int vol;
L
Linus Torvalds 已提交
550 551 552 553
	int change;

	if (! (mix = chip->mixer_data))
		return -ENODEV;
554 555 556 557
	vol = ucontrol->value.integer.value[0];
	if (vol >= info->max)
		return -EINVAL;
	change = mix->mono_vol[info->index] != vol;
L
Linus Torvalds 已提交
558
	if (change) {
559
		mix->mono_vol[info->index] = vol;
L
Linus Torvalds 已提交
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
		tumbler_set_mono_volume(mix, info);
	}
	return change;
}

/* TAS3001c mono volumes */
static struct tumbler_mono_vol tumbler_pcm_vol_info = {
	.index = VOL_IDX_PCM_MONO,
	.reg = TAS_REG_PCM,
	.bytes = 3,
	.max = ARRAY_SIZE(mixer_volume_table),
	.table = mixer_volume_table,
};

static struct tumbler_mono_vol tumbler_bass_vol_info = {
	.index = VOL_IDX_BASS,
	.reg = TAS_REG_BASS,
	.bytes = 1,
	.max = ARRAY_SIZE(bass_volume_table),
	.table = bass_volume_table,
};

static struct tumbler_mono_vol tumbler_treble_vol_info = {
	.index = VOL_IDX_TREBLE,
	.reg = TAS_REG_TREBLE,
	.bytes = 1,
	.max = ARRAY_SIZE(treble_volume_table),
	.table = treble_volume_table,
};

/* TAS3004 mono volumes */
static struct tumbler_mono_vol snapper_bass_vol_info = {
	.index = VOL_IDX_BASS,
	.reg = TAS_REG_BASS,
	.bytes = 1,
	.max = ARRAY_SIZE(snapper_bass_volume_table),
	.table = snapper_bass_volume_table,
};

static struct tumbler_mono_vol snapper_treble_vol_info = {
	.index = VOL_IDX_TREBLE,
	.reg = TAS_REG_TREBLE,
	.bytes = 1,
	.max = ARRAY_SIZE(snapper_treble_volume_table),
	.table = snapper_treble_volume_table,
};


#define DEFINE_MONO(xname,type) { \
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,\
	.name = xname, \
	.info = tumbler_info_mono, \
	.get = tumbler_get_mono, \
	.put = tumbler_put_mono, \
	.private_value = (unsigned long)(&tumbler_##type##_vol_info), \
}

#define DEFINE_SNAPPER_MONO(xname,type) { \
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,\
	.name = xname, \
	.info = tumbler_info_mono, \
	.get = tumbler_get_mono, \
	.put = tumbler_put_mono, \
	.private_value = (unsigned long)(&snapper_##type##_vol_info), \
}


/*
 * snapper mixer volumes
 */

631
static int snapper_set_mix_vol1(struct pmac_tumbler *mix, int idx, int ch, int reg)
L
Linus Torvalds 已提交
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
{
	int i, j, vol;
	unsigned char block[9];

	vol = mix->mix_vol[idx][ch];
	if (vol >= ARRAY_SIZE(mixer_volume_table)) {
		vol = ARRAY_SIZE(mixer_volume_table) - 1;
		mix->mix_vol[idx][ch] = vol;
	}

	for (i = 0; i < 3; i++) {
		vol = mix->mix_vol[i][ch];
		vol = mixer_volume_table[vol];
		for (j = 0; j < 3; j++)
			block[i * 3 + j] = (vol >> ((2 - j) * 8)) & 0xff;
	}
648 649
	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, reg,
					   9, block) < 0) {
650
		snd_printk(KERN_ERR "failed to set mono volume %d\n", reg);
L
Linus Torvalds 已提交
651 652 653 654 655
		return -EINVAL;
	}
	return 0;
}

656
static int snapper_set_mix_vol(struct pmac_tumbler *mix, int idx)
L
Linus Torvalds 已提交
657 658 659 660 661 662 663 664 665
{
	if (! mix->i2c.client)
		return -ENODEV;
	if (snapper_set_mix_vol1(mix, idx, 0, TAS_REG_LMIX) < 0 ||
	    snapper_set_mix_vol1(mix, idx, 1, TAS_REG_RMIX) < 0)
		return -EINVAL;
	return 0;
}

666 667
static int snapper_info_mix(struct snd_kcontrol *kcontrol,
			    struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
668 669 670 671 672 673 674 675
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 2;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = ARRAY_SIZE(mixer_volume_table) - 1;
	return 0;
}

676 677
static int snapper_get_mix(struct snd_kcontrol *kcontrol,
			   struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
678 679
{
	int idx = (int)kcontrol->private_value;
680 681
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
L
Linus Torvalds 已提交
682 683 684 685 686 687 688
	if (! (mix = chip->mixer_data))
		return -ENODEV;
	ucontrol->value.integer.value[0] = mix->mix_vol[idx][0];
	ucontrol->value.integer.value[1] = mix->mix_vol[idx][1];
	return 0;
}

689 690
static int snapper_put_mix(struct snd_kcontrol *kcontrol,
			   struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
691 692
{
	int idx = (int)kcontrol->private_value;
693 694
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
695
	unsigned int vol[2];
L
Linus Torvalds 已提交
696 697 698 699
	int change;

	if (! (mix = chip->mixer_data))
		return -ENODEV;
700 701 702 703 704 705 706
	vol[0] = ucontrol->value.integer.value[0];
	vol[1] = ucontrol->value.integer.value[1];
	if (vol[0] >= ARRAY_SIZE(mixer_volume_table) ||
	    vol[1] >= ARRAY_SIZE(mixer_volume_table))
		return -EINVAL;
	change = mix->mix_vol[idx][0] != vol[0] ||
		mix->mix_vol[idx][1] != vol[1];
L
Linus Torvalds 已提交
707
	if (change) {
708 709
		mix->mix_vol[idx][0] = vol[0];
		mix->mix_vol[idx][1] = vol[1];
L
Linus Torvalds 已提交
710 711 712 713 714 715 716
		snapper_set_mix_vol(mix, idx);
	}
	return change;
}


/*
717 718
 * mute switches. FIXME: Turn that into software mute when both outputs are muted
 * to avoid codec reset on ibook M7
L
Linus Torvalds 已提交
719 720
 */

721
enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP, TUMBLER_MUTE_LINE };
L
Linus Torvalds 已提交
722

723 724
static int tumbler_get_mute_switch(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
725
{
726 727 728
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
	struct pmac_gpio *gp;
L
Linus Torvalds 已提交
729 730
	if (! (mix = chip->mixer_data))
		return -ENODEV;
731 732 733 734 735 736 737 738 739 740 741 742
	switch(kcontrol->private_value) {
	case TUMBLER_MUTE_HP:
		gp = &mix->hp_mute;	break;
	case TUMBLER_MUTE_AMP:
		gp = &mix->amp_mute;	break;
	case TUMBLER_MUTE_LINE:
		gp = &mix->line_mute;	break;
	default:
		gp = NULL;
	}
	if (gp == NULL)
		return -EINVAL;
743
	ucontrol->value.integer.value[0] = !check_audio_gpio(gp);
L
Linus Torvalds 已提交
744 745 746
	return 0;
}

747 748
static int tumbler_put_mute_switch(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
749
{
750 751 752
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
	struct pmac_gpio *gp;
L
Linus Torvalds 已提交
753 754 755 756 757 758 759
	int val;
#ifdef PMAC_SUPPORT_AUTOMUTE
	if (chip->update_automute && chip->auto_mute)
		return 0; /* don't touch in the auto-mute mode */
#endif	
	if (! (mix = chip->mixer_data))
		return -ENODEV;
760 761 762 763 764 765 766 767 768 769 770 771
	switch(kcontrol->private_value) {
	case TUMBLER_MUTE_HP:
		gp = &mix->hp_mute;	break;
	case TUMBLER_MUTE_AMP:
		gp = &mix->amp_mute;	break;
	case TUMBLER_MUTE_LINE:
		gp = &mix->line_mute;	break;
	default:
		gp = NULL;
	}
	if (gp == NULL)
		return -EINVAL;
772
	val = ! check_audio_gpio(gp);
L
Linus Torvalds 已提交
773 774 775 776 777 778 779
	if (val != ucontrol->value.integer.value[0]) {
		write_audio_gpio(gp, ! ucontrol->value.integer.value[0]);
		return 1;
	}
	return 0;
}

780
static int snapper_set_capture_source(struct pmac_tumbler *mix)
L
Linus Torvalds 已提交
781 782 783
{
	if (! mix->i2c.client)
		return -ENODEV;
784 785 786 787 788
	if (mix->capture_source)
		mix->acs = mix->acs |= 2;
	else
		mix->acs &= ~2;
	return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
L
Linus Torvalds 已提交
789 790
}

791 792
static int snapper_info_capture_source(struct snd_kcontrol *kcontrol,
				       struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
793 794 795 796 797 798 799 800 801 802 803 804 805
{
	static char *texts[2] = {
		"Line", "Mic"
	};
	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
	uinfo->count = 1;
	uinfo->value.enumerated.items = 2;
	if (uinfo->value.enumerated.item > 1)
		uinfo->value.enumerated.item = 1;
	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
	return 0;
}

806 807
static int snapper_get_capture_source(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
808
{
809 810
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix = chip->mixer_data;
L
Linus Torvalds 已提交
811

K
Kamalesh Babulal 已提交
812
	ucontrol->value.enumerated.item[0] = mix->capture_source;
L
Linus Torvalds 已提交
813 814 815
	return 0;
}

816 817
static int snapper_put_capture_source(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
818
{
819 820
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix = chip->mixer_data;
L
Linus Torvalds 已提交
821 822
	int change;

K
Kamalesh Babulal 已提交
823
	change = ucontrol->value.enumerated.item[0] != mix->capture_source;
L
Linus Torvalds 已提交
824
	if (change) {
825
		mix->capture_source = !!ucontrol->value.enumerated.item[0];
L
Linus Torvalds 已提交
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
		snapper_set_capture_source(mix);
	}
	return change;
}

#define DEFINE_SNAPPER_MIX(xname,idx,ofs) { \
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,\
	.name = xname, \
	.info = snapper_info_mix, \
	.get = snapper_get_mix, \
	.put = snapper_put_mix, \
	.index = idx,\
	.private_value = ofs, \
}


/*
 */
844
static struct snd_kcontrol_new tumbler_mixers[] __devinitdata = {
L
Linus Torvalds 已提交
845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	  .name = "Master Playback Volume",
	  .info = tumbler_info_master_volume,
	  .get = tumbler_get_master_volume,
	  .put = tumbler_put_master_volume
	},
	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	  .name = "Master Playback Switch",
	  .info = snd_pmac_boolean_stereo_info,
	  .get = tumbler_get_master_switch,
	  .put = tumbler_put_master_switch
	},
	DEFINE_MONO("Tone Control - Bass", bass),
	DEFINE_MONO("Tone Control - Treble", treble),
	DEFINE_MONO("PCM Playback Volume", pcm),
	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	  .name = "DRC Range",
	  .info = tumbler_info_drc_value,
	  .get = tumbler_get_drc_value,
	  .put = tumbler_put_drc_value
	},
};

868
static struct snd_kcontrol_new snapper_mixers[] __devinitdata = {
L
Linus Torvalds 已提交
869 870 871 872 873 874 875 876 877 878 879 880 881
	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	  .name = "Master Playback Volume",
	  .info = tumbler_info_master_volume,
	  .get = tumbler_get_master_volume,
	  .put = tumbler_put_master_volume
	},
	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	  .name = "Master Playback Switch",
	  .info = snd_pmac_boolean_stereo_info,
	  .get = tumbler_get_master_switch,
	  .put = tumbler_put_master_switch
	},
	DEFINE_SNAPPER_MIX("PCM Playback Volume", 0, VOL_IDX_PCM),
882 883
	/* Alternative PCM is assigned to Mic analog loopback on iBook G4 */
	DEFINE_SNAPPER_MIX("Mic Playback Volume", 0, VOL_IDX_PCM2),
L
Linus Torvalds 已提交
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
	DEFINE_SNAPPER_MIX("Monitor Mix Volume", 0, VOL_IDX_ADC),
	DEFINE_SNAPPER_MONO("Tone Control - Bass", bass),
	DEFINE_SNAPPER_MONO("Tone Control - Treble", treble),
	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	  .name = "DRC Range",
	  .info = tumbler_info_drc_value,
	  .get = tumbler_get_drc_value,
	  .put = tumbler_put_drc_value
	},
	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	  .name = "Input Source", /* FIXME: "Capture Source" doesn't work properly */
	  .info = snapper_info_capture_source,
	  .get = snapper_get_capture_source,
	  .put = snapper_put_capture_source
	},
};

901
static struct snd_kcontrol_new tumbler_hp_sw __devinitdata = {
L
Linus Torvalds 已提交
902 903 904 905 906 907 908
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	.name = "Headphone Playback Switch",
	.info = snd_pmac_boolean_mono_info,
	.get = tumbler_get_mute_switch,
	.put = tumbler_put_mute_switch,
	.private_value = TUMBLER_MUTE_HP,
};
909
static struct snd_kcontrol_new tumbler_speaker_sw __devinitdata = {
L
Linus Torvalds 已提交
910
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
911
	.name = "Speaker Playback Switch",
L
Linus Torvalds 已提交
912 913 914 915 916
	.info = snd_pmac_boolean_mono_info,
	.get = tumbler_get_mute_switch,
	.put = tumbler_put_mute_switch,
	.private_value = TUMBLER_MUTE_AMP,
};
917
static struct snd_kcontrol_new tumbler_lineout_sw __devinitdata = {
918 919 920 921 922 923 924
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	.name = "Line Out Playback Switch",
	.info = snd_pmac_boolean_mono_info,
	.get = tumbler_get_mute_switch,
	.put = tumbler_put_mute_switch,
	.private_value = TUMBLER_MUTE_LINE,
};
925
static struct snd_kcontrol_new tumbler_drc_sw __devinitdata = {
L
Linus Torvalds 已提交
926 927 928 929 930 931 932 933 934 935 936 937
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	.name = "DRC Switch",
	.info = snd_pmac_boolean_mono_info,
	.get = tumbler_get_drc_switch,
	.put = tumbler_put_drc_switch
};


#ifdef PMAC_SUPPORT_AUTOMUTE
/*
 * auto-mute stuffs
 */
938
static int tumbler_detect_headphone(struct snd_pmac *chip)
L
Linus Torvalds 已提交
939
{
940
	struct pmac_tumbler *mix = chip->mixer_data;
941 942 943 944 945 946 947
	int detect = 0;

	if (mix->hp_detect.addr)
		detect |= read_audio_gpio(&mix->hp_detect);
	return detect;
}

948
static int tumbler_detect_lineout(struct snd_pmac *chip)
949
{
950
	struct pmac_tumbler *mix = chip->mixer_data;
951 952 953 954 955
	int detect = 0;

	if (mix->line_detect.addr)
		detect |= read_audio_gpio(&mix->line_detect);
	return detect;
L
Linus Torvalds 已提交
956 957
}

958 959
static void check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val, int do_notify,
		       struct snd_kcontrol *sw)
L
Linus Torvalds 已提交
960
{
961
	if (check_audio_gpio(gp) != val) {
L
Linus Torvalds 已提交
962 963
		write_audio_gpio(gp, val);
		if (do_notify)
964 965
			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
				       &sw->id);
L
Linus Torvalds 已提交
966 967 968 969
	}
}

static struct work_struct device_change;
D
David Howells 已提交
970
static struct snd_pmac *device_change_chip;
L
Linus Torvalds 已提交
971

D
David Howells 已提交
972
static void device_change_handler(struct work_struct *work)
L
Linus Torvalds 已提交
973
{
D
David Howells 已提交
974
	struct snd_pmac *chip = device_change_chip;
975
	struct pmac_tumbler *mix;
976
	int headphone, lineout;
L
Linus Torvalds 已提交
977 978 979 980 981

	if (!chip)
		return;

	mix = chip->mixer_data;
982 983
	if (snd_BUG_ON(!mix))
		return;
984

985 986 987 988 989 990 991 992 993 994 995 996 997
	headphone = tumbler_detect_headphone(chip);
	lineout = tumbler_detect_lineout(chip);

	DBG("headphone: %d, lineout: %d\n", headphone, lineout);

	if (headphone || lineout) {
		/* unmute headphone/lineout & mute speaker */
		if (headphone)
			check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify,
				   chip->master_sw_ctl);
		if (lineout && mix->line_mute.addr != 0)
			check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify,
				   chip->lineout_sw_ctl);
998
		if (mix->anded_reset)
999
			msleep(10);
1000 1001 1002
		check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify,
			   chip->speaker_sw_ctl);
	} else {
1003
		/* unmute speaker, mute others */
1004 1005 1006
		check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify,
			   chip->speaker_sw_ctl);
		if (mix->anded_reset)
1007
			msleep(10);
1008 1009
		check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify,
			   chip->master_sw_ctl);
1010 1011 1012
		if (mix->line_mute.addr != 0)
			check_mute(chip, &mix->line_mute, 1, mix->auto_mute_notify,
				   chip->lineout_sw_ctl);
1013
	}
1014
	if (mix->auto_mute_notify)
1015 1016
		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
				       &chip->hp_detect_ctl->id);
1017 1018 1019 1020

#ifdef CONFIG_SND_POWERMAC_AUTO_DRC
	mix->drc_enable = ! (headphone || lineout);
	if (mix->auto_mute_notify)
1021 1022
		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
			       &chip->drc_sw_ctl->id);
L
Linus Torvalds 已提交
1023 1024 1025 1026
	if (chip->model == PMAC_TUMBLER)
		tumbler_set_drc(mix);
	else
		snapper_set_drc(mix);
1027
#endif
L
Linus Torvalds 已提交
1028 1029 1030 1031 1032

	/* reset the master volume so the correct amplification is applied */
	tumbler_set_master_volume(mix);
}

1033
static void tumbler_update_automute(struct snd_pmac *chip, int do_notify)
L
Linus Torvalds 已提交
1034 1035
{
	if (chip->auto_mute) {
1036
		struct pmac_tumbler *mix;
1037
		mix = chip->mixer_data;
1038 1039
		if (snd_BUG_ON(!mix))
			return;
1040
		mix->auto_mute_notify = do_notify;
L
Linus Torvalds 已提交
1041 1042 1043 1044 1045 1046 1047
		schedule_work(&device_change);
	}
}
#endif /* PMAC_SUPPORT_AUTOMUTE */


/* interrupt - headphone plug changed */
1048
static irqreturn_t headphone_intr(int irq, void *devid)
L
Linus Torvalds 已提交
1049
{
1050
	struct snd_pmac *chip = devid;
L
Linus Torvalds 已提交
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
	if (chip->update_automute && chip->initialized) {
		chip->update_automute(chip, 1);
		return IRQ_HANDLED;
	}
	return IRQ_NONE;
}

/* look for audio-gpio device */
static struct device_node *find_audio_device(const char *name)
{
1061
	struct device_node *gpiop;
L
Linus Torvalds 已提交
1062 1063
	struct device_node *np;
  
1064 1065
	gpiop = of_find_node_by_name(NULL, "gpio");
	if (! gpiop)
L
Linus Torvalds 已提交
1066 1067
		return NULL;
  
1068 1069
	for (np = of_get_next_child(gpiop, NULL); np;
			np = of_get_next_child(gpiop, np)) {
1070
		const char *property = of_get_property(np, "audio-gpio", NULL);
L
Linus Torvalds 已提交
1071
		if (property && strcmp(property, name) == 0)
1072
			break;
L
Linus Torvalds 已提交
1073
	}  
1074 1075
	of_node_put(gpiop);
	return np;
L
Linus Torvalds 已提交
1076 1077 1078 1079 1080
}

/* look for audio-gpio device */
static struct device_node *find_compatible_audio_device(const char *name)
{
1081
	struct device_node *gpiop;
L
Linus Torvalds 已提交
1082 1083
	struct device_node *np;
  
1084 1085
	gpiop = of_find_node_by_name(NULL, "gpio");
	if (!gpiop)
L
Linus Torvalds 已提交
1086 1087
		return NULL;
  
1088 1089
	for (np = of_get_next_child(gpiop, NULL); np;
			np = of_get_next_child(gpiop, np)) {
1090
		if (of_device_is_compatible(np, name))
1091
			break;
L
Linus Torvalds 已提交
1092
	}  
1093 1094
	of_node_put(gpiop);
	return np;
L
Linus Torvalds 已提交
1095 1096 1097
}

/* find an audio device and get its address */
1098 1099
static long tumbler_find_device(const char *device, const char *platform,
				struct pmac_gpio *gp, int is_compatible)
L
Linus Torvalds 已提交
1100 1101
{
	struct device_node *node;
1102 1103
	const u32 *base;
	u32 addr;
1104
	long ret;
L
Linus Torvalds 已提交
1105 1106 1107 1108 1109 1110

	if (is_compatible)
		node = find_compatible_audio_device(device);
	else
		node = find_audio_device(device);
	if (! node) {
1111
		DBG("(W) cannot find audio device %s !\n", device);
L
Linus Torvalds 已提交
1112 1113 1114 1115
		snd_printdd("cannot find device %s\n", device);
		return -ENODEV;
	}

1116
	base = of_get_property(node, "AAPL,address", NULL);
L
Linus Torvalds 已提交
1117
	if (! base) {
1118
		base = of_get_property(node, "reg", NULL);
1119
		if (!base) {
1120
			DBG("(E) cannot find address for device %s !\n", device);
1121
			snd_printd("cannot find address for device %s\n", device);
1122
			of_node_put(node);
1123 1124 1125 1126 1127 1128 1129
			return -ENODEV;
		}
		addr = *base;
		if (addr < 0x50)
			addr += 0x50;
	} else
		addr = *base;
L
Linus Torvalds 已提交
1130

1131 1132
	gp->addr = addr & 0x0000ffff;
	/* Try to find the active state, default to 0 ! */
1133
	base = of_get_property(node, "audio-gpio-active-state", NULL);
1134
	if (base) {
L
Linus Torvalds 已提交
1135
		gp->active_state = *base;
1136 1137 1138
		gp->active_val = (*base) ? 0x5 : 0x4;
		gp->inactive_val = (*base) ? 0x4 : 0x5;
	} else {
1139
		const u32 *prop = NULL;
1140
		gp->active_state = IS_G4DA && !strcmp(device, "keywest-gpio15");
1141 1142 1143 1144 1145 1146 1147
		gp->active_val = 0x4;
		gp->inactive_val = 0x5;
		/* Here are some crude hacks to extract the GPIO polarity and
		 * open collector informations out of the do-platform script
		 * as we don't yet have an interpreter for these things
		 */
		if (platform)
1148
			prop = of_get_property(node, platform, NULL);
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
		if (prop) {
			if (prop[3] == 0x9 && prop[4] == 0x9) {
				gp->active_val = 0xd;
				gp->inactive_val = 0xc;
			}
			if (prop[3] == 0x1 && prop[4] == 0x1) {
				gp->active_val = 0x5;
				gp->inactive_val = 0x4;
			}
		}
	}

	DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n",
	    device, gp->addr, gp->active_state);
L
Linus Torvalds 已提交
1163

1164 1165 1166
	ret = irq_of_parse_and_map(node, 0);
	of_node_put(node);
	return ret;
L
Linus Torvalds 已提交
1167 1168 1169
}

/* reset audio */
1170
static void tumbler_reset_audio(struct snd_pmac *chip)
L
Linus Torvalds 已提交
1171
{
1172
	struct pmac_tumbler *mix = chip->mixer_data;
L
Linus Torvalds 已提交
1173

1174
	if (mix->anded_reset) {
1175
		DBG("(I) codec anded reset !\n");
1176 1177
		write_audio_gpio(&mix->hp_mute, 0);
		write_audio_gpio(&mix->amp_mute, 0);
1178
		msleep(200);
1179 1180
		write_audio_gpio(&mix->hp_mute, 1);
		write_audio_gpio(&mix->amp_mute, 1);
1181
		msleep(100);
1182 1183
		write_audio_gpio(&mix->hp_mute, 0);
		write_audio_gpio(&mix->amp_mute, 0);
1184
		msleep(100);
1185
	} else {
1186 1187
		DBG("(I) codec normal reset !\n");

1188
		write_audio_gpio(&mix->audio_reset, 0);
1189
		msleep(200);
1190
		write_audio_gpio(&mix->audio_reset, 1);
1191
		msleep(100);
1192
		write_audio_gpio(&mix->audio_reset, 0);
1193
		msleep(100);
1194
	}
L
Linus Torvalds 已提交
1195 1196
}

1197
#ifdef CONFIG_PM
1198
/* suspend mixer */
1199
static void tumbler_suspend(struct snd_pmac *chip)
1200
{
1201
	struct pmac_tumbler *mix = chip->mixer_data;
1202 1203 1204

	if (mix->headphone_irq >= 0)
		disable_irq(mix->headphone_irq);
1205 1206
	if (mix->lineout_irq >= 0)
		disable_irq(mix->lineout_irq);
1207 1208
	mix->save_master_switch[0] = mix->master_switch[0];
	mix->save_master_switch[1] = mix->master_switch[1];
1209 1210
	mix->save_master_vol[0] = mix->master_vol[0];
	mix->save_master_vol[1] = mix->master_vol[1];
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
	mix->master_switch[0] = mix->master_switch[1] = 0;
	tumbler_set_master_volume(mix);
	if (!mix->anded_reset) {
		write_audio_gpio(&mix->amp_mute, 1);
		write_audio_gpio(&mix->hp_mute, 1);
	}
	if (chip->model == PMAC_SNAPPER) {
		mix->acs |= 1;
		i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
	}
	if (mix->anded_reset) {
		write_audio_gpio(&mix->amp_mute, 1);
		write_audio_gpio(&mix->hp_mute, 1);
	} else
		write_audio_gpio(&mix->audio_reset, 1);
}

L
Linus Torvalds 已提交
1228
/* resume mixer */
1229
static void tumbler_resume(struct snd_pmac *chip)
L
Linus Torvalds 已提交
1230
{
1231
	struct pmac_tumbler *mix = chip->mixer_data;
L
Linus Torvalds 已提交
1232

1233 1234 1235
	mix->acs &= ~1;
	mix->master_switch[0] = mix->save_master_switch[0];
	mix->master_switch[1] = mix->save_master_switch[1];
1236 1237
	mix->master_vol[0] = mix->save_master_vol[0];
	mix->master_vol[1] = mix->save_master_vol[1];
L
Linus Torvalds 已提交
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
	tumbler_reset_audio(chip);
	if (mix->i2c.client && mix->i2c.init_client) {
		if (mix->i2c.init_client(&mix->i2c) < 0)
			printk(KERN_ERR "tumbler_init_client error\n");
	} else
		printk(KERN_ERR "tumbler: i2c is not initialized\n");
	if (chip->model == PMAC_TUMBLER) {
		tumbler_set_mono_volume(mix, &tumbler_pcm_vol_info);
		tumbler_set_mono_volume(mix, &tumbler_bass_vol_info);
		tumbler_set_mono_volume(mix, &tumbler_treble_vol_info);
		tumbler_set_drc(mix);
	} else {
		snapper_set_mix_vol(mix, VOL_IDX_PCM);
		snapper_set_mix_vol(mix, VOL_IDX_PCM2);
		snapper_set_mix_vol(mix, VOL_IDX_ADC);
		tumbler_set_mono_volume(mix, &snapper_bass_vol_info);
		tumbler_set_mono_volume(mix, &snapper_treble_vol_info);
		snapper_set_drc(mix);
		snapper_set_capture_source(mix);
	}
	tumbler_set_master_volume(mix);
	if (chip->update_automute)
		chip->update_automute(chip, 0);
1261 1262 1263
	if (mix->headphone_irq >= 0) {
		unsigned char val;

1264
		enable_irq(mix->headphone_irq);
1265 1266 1267 1268
		/* activate headphone status interrupts */
		val = do_gpio_read(&mix->hp_detect);
		do_gpio_write(&mix->hp_detect, val | 0x80);
	}
1269 1270
	if (mix->lineout_irq >= 0)
		enable_irq(mix->lineout_irq);
L
Linus Torvalds 已提交
1271 1272 1273 1274
}
#endif

/* initialize tumbler */
1275
static int __devinit tumbler_init(struct snd_pmac *chip)
L
Linus Torvalds 已提交
1276
{
1277
	int irq;
1278
	struct pmac_tumbler *mix = chip->mixer_data;
L
Linus Torvalds 已提交
1279

1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305
	if (tumbler_find_device("audio-hw-reset",
				"platform-do-hw-reset",
				&mix->audio_reset, 0) < 0)
		tumbler_find_device("hw-reset",
				    "platform-do-hw-reset",
				    &mix->audio_reset, 1);
	if (tumbler_find_device("amp-mute",
				"platform-do-amp-mute",
				&mix->amp_mute, 0) < 0)
		tumbler_find_device("amp-mute",
				    "platform-do-amp-mute",
				    &mix->amp_mute, 1);
	if (tumbler_find_device("headphone-mute",
				"platform-do-headphone-mute",
				&mix->hp_mute, 0) < 0)
		tumbler_find_device("headphone-mute",
				    "platform-do-headphone-mute",
				    &mix->hp_mute, 1);
	if (tumbler_find_device("line-output-mute",
				"platform-do-lineout-mute",
				&mix->line_mute, 0) < 0)
		tumbler_find_device("line-output-mute",
				   "platform-do-lineout-mute",
				    &mix->line_mute, 1);
	irq = tumbler_find_device("headphone-detect",
				  NULL, &mix->hp_detect, 0);
1306
	if (irq <= NO_IRQ)
1307 1308
		irq = tumbler_find_device("headphone-detect",
					  NULL, &mix->hp_detect, 1);
1309
	if (irq <= NO_IRQ)
1310 1311 1312 1313 1314
		irq = tumbler_find_device("keywest-gpio15",
					  NULL, &mix->hp_detect, 1);
	mix->headphone_irq = irq;
 	irq = tumbler_find_device("line-output-detect",
				  NULL, &mix->line_detect, 0);
1315
 	if (irq <= NO_IRQ)
1316 1317 1318
		irq = tumbler_find_device("line-output-detect",
					  NULL, &mix->line_detect, 1);
	mix->lineout_irq = irq;
L
Linus Torvalds 已提交
1319 1320 1321 1322 1323 1324

	tumbler_reset_audio(chip);
  
	return 0;
}

1325
static void tumbler_cleanup(struct snd_pmac *chip)
L
Linus Torvalds 已提交
1326
{
1327
	struct pmac_tumbler *mix = chip->mixer_data;
L
Linus Torvalds 已提交
1328 1329 1330 1331 1332
	if (! mix)
		return;

	if (mix->headphone_irq >= 0)
		free_irq(mix->headphone_irq, chip);
1333 1334
	if (mix->lineout_irq >= 0)
		free_irq(mix->lineout_irq, chip);
L
Linus Torvalds 已提交
1335 1336 1337 1338 1339 1340 1341 1342 1343 1344
	tumbler_gpio_free(&mix->audio_reset);
	tumbler_gpio_free(&mix->amp_mute);
	tumbler_gpio_free(&mix->hp_mute);
	tumbler_gpio_free(&mix->hp_detect);
	snd_pmac_keywest_cleanup(&mix->i2c);
	kfree(mix);
	chip->mixer_data = NULL;
}

/* exported */
1345
int __devinit snd_pmac_tumbler_init(struct snd_pmac *chip)
L
Linus Torvalds 已提交
1346 1347
{
	int i, err;
1348
	struct pmac_tumbler *mix;
1349
	const u32 *paddr;
1350
	struct device_node *tas_node, *np;
L
Linus Torvalds 已提交
1351 1352
	char *chipname;

J
Jan Blunck 已提交
1353
	request_module("i2c-powermac");
L
Linus Torvalds 已提交
1354

1355
	mix = kzalloc(sizeof(*mix), GFP_KERNEL);
L
Linus Torvalds 已提交
1356 1357 1358 1359 1360 1361
	if (! mix)
		return -ENOMEM;
	mix->headphone_irq = -1;

	chip->mixer_data = mix;
	chip->mixer_free = tumbler_cleanup;
1362 1363 1364 1365 1366
	mix->anded_reset = 0;
	mix->reset_on_sleep = 1;

	for (np = chip->node->child; np; np = np->sibling) {
		if (!strcmp(np->name, "sound")) {
1367
			if (of_get_property(np, "has-anded-reset", NULL))
1368
				mix->anded_reset = 1;
1369
			if (of_get_property(np, "layout-id", NULL))
1370 1371 1372 1373
				mix->reset_on_sleep = 0;
			break;
		}
	}
L
Linus Torvalds 已提交
1374 1375 1376 1377
	if ((err = tumbler_init(chip)) < 0)
		return err;

	/* set up TAS */
1378
	tas_node = of_find_node_by_name(NULL, "deq");
1379
	if (tas_node == NULL)
1380
		tas_node = of_find_node_by_name(NULL, "codec");
L
Linus Torvalds 已提交
1381 1382 1383
	if (tas_node == NULL)
		return -ENODEV;

1384
	paddr = of_get_property(tas_node, "i2c-address", NULL);
1385
	if (paddr == NULL)
1386
		paddr = of_get_property(tas_node, "reg", NULL);
L
Linus Torvalds 已提交
1387 1388 1389 1390
	if (paddr)
		mix->i2c.addr = (*paddr) >> 1;
	else
		mix->i2c.addr = TAS_I2C_ADDR;
1391
	of_node_put(tas_node);
L
Linus Torvalds 已提交
1392

1393 1394
	DBG("(I) TAS i2c address is: %x\n", mix->i2c.addr);

L
Linus Torvalds 已提交
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429
	if (chip->model == PMAC_TUMBLER) {
		mix->i2c.init_client = tumbler_init_client;
		mix->i2c.name = "TAS3001c";
		chipname = "Tumbler";
	} else {
		mix->i2c.init_client = snapper_init_client;
		mix->i2c.name = "TAS3004";
		chipname = "Snapper";
	}

	if ((err = snd_pmac_keywest_init(&mix->i2c)) < 0)
		return err;

	/*
	 * build mixers
	 */
	sprintf(chip->card->mixername, "PowerMac %s", chipname);

	if (chip->model == PMAC_TUMBLER) {
		for (i = 0; i < ARRAY_SIZE(tumbler_mixers); i++) {
			if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&tumbler_mixers[i], chip))) < 0)
				return err;
		}
	} else {
		for (i = 0; i < ARRAY_SIZE(snapper_mixers); i++) {
			if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snapper_mixers[i], chip))) < 0)
				return err;
		}
	}
	chip->master_sw_ctl = snd_ctl_new1(&tumbler_hp_sw, chip);
	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
		return err;
	chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip);
	if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
		return err;
1430 1431 1432 1433 1434
	if (mix->line_mute.addr != 0) {
		chip->lineout_sw_ctl = snd_ctl_new1(&tumbler_lineout_sw, chip);
		if ((err = snd_ctl_add(chip->card, chip->lineout_sw_ctl)) < 0)
			return err;
	}
L
Linus Torvalds 已提交
1435 1436 1437 1438
	chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip);
	if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0)
		return err;

1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449
	/* set initial DRC range to 60% */
	if (chip->model == PMAC_TUMBLER)
		mix->drc_range = (TAS3001_DRC_MAX * 6) / 10;
	else
		mix->drc_range = (TAS3004_DRC_MAX * 6) / 10;
	mix->drc_enable = 1; /* will be changed later if AUTO_DRC is set */
	if (chip->model == PMAC_TUMBLER)
		tumbler_set_drc(mix);
	else
		snapper_set_drc(mix);

1450
#ifdef CONFIG_PM
1451
	chip->suspend = tumbler_suspend;
L
Linus Torvalds 已提交
1452 1453 1454
	chip->resume = tumbler_resume;
#endif

D
David Howells 已提交
1455 1456
	INIT_WORK(&device_change, device_change_handler);
	device_change_chip = chip;
L
Linus Torvalds 已提交
1457 1458

#ifdef PMAC_SUPPORT_AUTOMUTE
1459 1460
	if ((mix->headphone_irq >=0 || mix->lineout_irq >= 0)
	    && (err = snd_pmac_add_automute(chip)) < 0)
L
Linus Torvalds 已提交
1461 1462 1463 1464
		return err;
	chip->detect_headphone = tumbler_detect_headphone;
	chip->update_automute = tumbler_update_automute;
	tumbler_update_automute(chip, 0); /* update the status only */
1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484

	/* activate headphone status interrupts */
  	if (mix->headphone_irq >= 0) {
		unsigned char val;
		if ((err = request_irq(mix->headphone_irq, headphone_intr, 0,
				       "Sound Headphone Detection", chip)) < 0)
			return 0;
		/* activate headphone status interrupts */
		val = do_gpio_read(&mix->hp_detect);
		do_gpio_write(&mix->hp_detect, val | 0x80);
	}
  	if (mix->lineout_irq >= 0) {
		unsigned char val;
		if ((err = request_irq(mix->lineout_irq, headphone_intr, 0,
				       "Sound Lineout Detection", chip)) < 0)
			return 0;
		/* activate headphone status interrupts */
		val = do_gpio_read(&mix->line_detect);
		do_gpio_write(&mix->line_detect, val | 0x80);
	}
L
Linus Torvalds 已提交
1485 1486 1487 1488
#endif

	return 0;
}