tumbler.c 38.6 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
#define IS_G4DA (of_machine_is_compatible("PowerMac3,4"))
51

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
		return -EINVAL;
	}
R
Risto Suominen 已提交
249
	DBG("(I) succeeded to set volume (%u, %u)\n", left_vol, right_vol);
L
Linus Torvalds 已提交
250 251 252 253 254
	return 0;
}


/* output volume */
255 256
static int tumbler_info_master_volume(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
257 258 259 260 261 262 263 264
{
	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;
}

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

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

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

284 285 286 287 288 289 290
	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 已提交
291
	if (change) {
292 293
		mix->master_vol[0] = vol[0];
		mix->master_vol[1] = vol[1];
L
Linus Torvalds 已提交
294 295 296 297 298 299
		tumbler_set_master_volume(mix);
	}
	return change;
}

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

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

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

335
static int tumbler_set_drc(struct pmac_tumbler *mix)
L
Linus Torvalds 已提交
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
{
	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;
	}

355 356
	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC,
					   2, val) < 0) {
357
		snd_printk(KERN_ERR "failed to set DRC\n");
L
Linus Torvalds 已提交
358 359
		return -EINVAL;
	}
R
Risto Suominen 已提交
360
	DBG("(I) succeeded to set DRC (%u, %u)\n", val[0], val[1]);
L
Linus Torvalds 已提交
361 362 363 364 365 366 367 368 369
	return 0;
}

/*
 * TAS3004
 */

#define TAS3004_DRC_MAX		0xef

370
static int snapper_set_drc(struct pmac_tumbler *mix)
L
Linus Torvalds 已提交
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
{
	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;

392 393
	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, TAS_REG_DRC,
					   6, val) < 0) {
394
		snd_printk(KERN_ERR "failed to set DRC\n");
L
Linus Torvalds 已提交
395 396
		return -EINVAL;
	}
R
Risto Suominen 已提交
397
	DBG("(I) succeeded to set DRC (%u, %u)\n", val[0], val[1]);
L
Linus Torvalds 已提交
398 399 400
	return 0;
}

401 402
static int tumbler_info_drc_value(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
403
{
404
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
405 406 407 408 409 410 411 412
	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;
}

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

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

	if (! (mix = chip->mixer_data))
		return -ENODEV;
434 435 436 437 438 439 440 441 442
	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 已提交
443
	if (change) {
444
		mix->drc_range = val;
L
Linus Torvalds 已提交
445 446 447 448 449 450 451 452
		if (chip->model == PMAC_TUMBLER)
			tumbler_set_drc(mix);
		else
			snapper_set_drc(mix);
	}
	return change;
}

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

464 465
static int tumbler_put_drc_switch(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
466
{
467 468
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
L
Linus Torvalds 已提交
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 494 495 496
	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;
};

497 498
static int tumbler_set_mono_volume(struct pmac_tumbler *mix,
				   struct tumbler_mono_vol *info)
L
Linus Torvalds 已提交
499 500 501 502 503 504 505 506 507 508 509 510 511 512
{
	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;
513 514
	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, info->reg,
					   info->bytes, block) < 0) {
515 516
		snd_printk(KERN_ERR "failed to set mono volume %d\n",
			   info->index);
L
Linus Torvalds 已提交
517 518 519 520 521
		return -EINVAL;
	}
	return 0;
}

522 523
static int tumbler_info_mono(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
524 525 526 527 528 529 530 531 532 533
{
	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;
}

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

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

	if (! (mix = chip->mixer_data))
		return -ENODEV;
557 558 559 560
	vol = ucontrol->value.integer.value[0];
	if (vol >= info->max)
		return -EINVAL;
	change = mix->mono_vol[info->index] != vol;
L
Linus Torvalds 已提交
561
	if (change) {
562
		mix->mono_vol[info->index] = vol;
L
Linus Torvalds 已提交
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 631 632 633
		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
 */

634
static int snapper_set_mix_vol1(struct pmac_tumbler *mix, int idx, int ch, int reg)
L
Linus Torvalds 已提交
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
{
	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;
	}
651 652
	if (i2c_smbus_write_i2c_block_data(mix->i2c.client, reg,
					   9, block) < 0) {
653
		snd_printk(KERN_ERR "failed to set mono volume %d\n", reg);
L
Linus Torvalds 已提交
654 655 656 657 658
		return -EINVAL;
	}
	return 0;
}

659
static int snapper_set_mix_vol(struct pmac_tumbler *mix, int idx)
L
Linus Torvalds 已提交
660 661 662 663 664 665 666 667 668
{
	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;
}

669 670
static int snapper_info_mix(struct snd_kcontrol *kcontrol,
			    struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
671 672 673 674 675 676 677 678
{
	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;
}

679 680
static int snapper_get_mix(struct snd_kcontrol *kcontrol,
			   struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
681 682
{
	int idx = (int)kcontrol->private_value;
683 684
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
L
Linus Torvalds 已提交
685 686 687 688 689 690 691
	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;
}

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

	if (! (mix = chip->mixer_data))
		return -ENODEV;
703 704 705 706 707 708 709
	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 已提交
710
	if (change) {
711 712
		mix->mix_vol[idx][0] = vol[0];
		mix->mix_vol[idx][1] = vol[1];
L
Linus Torvalds 已提交
713 714 715 716 717 718 719
		snapper_set_mix_vol(mix, idx);
	}
	return change;
}


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

724
enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP, TUMBLER_MUTE_LINE };
L
Linus Torvalds 已提交
725

726 727
static int tumbler_get_mute_switch(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
728
{
729 730 731
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
	struct pmac_gpio *gp;
L
Linus Torvalds 已提交
732 733
	if (! (mix = chip->mixer_data))
		return -ENODEV;
734 735 736 737 738 739 740 741 742 743 744 745
	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;
746
	ucontrol->value.integer.value[0] = !check_audio_gpio(gp);
L
Linus Torvalds 已提交
747 748 749
	return 0;
}

750 751
static int tumbler_put_mute_switch(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
752
{
753 754 755
	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
	struct pmac_tumbler *mix;
	struct pmac_gpio *gp;
L
Linus Torvalds 已提交
756 757 758 759 760 761 762
	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;
763 764 765 766 767 768 769 770 771 772 773 774
	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;
775
	val = ! check_audio_gpio(gp);
L
Linus Torvalds 已提交
776 777 778 779 780 781 782
	if (val != ucontrol->value.integer.value[0]) {
		write_audio_gpio(gp, ! ucontrol->value.integer.value[0]);
		return 1;
	}
	return 0;
}

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

794 795
static int snapper_info_capture_source(struct snd_kcontrol *kcontrol,
				       struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
796 797 798 799 800 801 802 803 804 805 806 807 808
{
	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;
}

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

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

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

K
Kamalesh Babulal 已提交
826
	change = ucontrol->value.enumerated.item[0] != mix->capture_source;
L
Linus Torvalds 已提交
827
	if (change) {
828
		mix->capture_source = !!ucontrol->value.enumerated.item[0];
L
Linus Torvalds 已提交
829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
		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, \
}


/*
 */
847
static struct snd_kcontrol_new tumbler_mixers[] __devinitdata = {
L
Linus Torvalds 已提交
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
	{ .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
	},
};

871
static struct snd_kcontrol_new snapper_mixers[] __devinitdata = {
L
Linus Torvalds 已提交
872 873 874 875 876 877 878 879 880 881 882 883 884
	{ .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),
885 886
	/* Alternative PCM is assigned to Mic analog loopback on iBook G4 */
	DEFINE_SNAPPER_MIX("Mic Playback Volume", 0, VOL_IDX_PCM2),
L
Linus Torvalds 已提交
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903
	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
	},
};

904
static struct snd_kcontrol_new tumbler_hp_sw __devinitdata = {
L
Linus Torvalds 已提交
905 906 907 908 909 910 911
	.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,
};
912
static struct snd_kcontrol_new tumbler_speaker_sw __devinitdata = {
L
Linus Torvalds 已提交
913
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
914
	.name = "Speaker Playback Switch",
L
Linus Torvalds 已提交
915 916 917 918 919
	.info = snd_pmac_boolean_mono_info,
	.get = tumbler_get_mute_switch,
	.put = tumbler_put_mute_switch,
	.private_value = TUMBLER_MUTE_AMP,
};
920
static struct snd_kcontrol_new tumbler_lineout_sw __devinitdata = {
921 922 923 924 925 926 927
	.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,
};
928
static struct snd_kcontrol_new tumbler_drc_sw __devinitdata = {
L
Linus Torvalds 已提交
929 930 931 932 933 934 935 936 937 938 939 940
	.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
 */
941
static int tumbler_detect_headphone(struct snd_pmac *chip)
L
Linus Torvalds 已提交
942
{
943
	struct pmac_tumbler *mix = chip->mixer_data;
944 945 946 947 948 949 950
	int detect = 0;

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

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

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

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

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

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

	if (!chip)
		return;

	mix = chip->mixer_data;
985 986
	if (snd_BUG_ON(!mix))
		return;
987

988 989 990 991 992 993 994 995 996 997 998 999 1000
	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);
1001
		if (mix->anded_reset)
1002
			msleep(10);
1003
		check_mute(chip, &mix->amp_mute, !IS_G4DA, mix->auto_mute_notify,
1004 1005
			   chip->speaker_sw_ctl);
	} else {
1006
		/* unmute speaker, mute others */
1007 1008 1009
		check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify,
			   chip->speaker_sw_ctl);
		if (mix->anded_reset)
1010
			msleep(10);
1011 1012
		check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify,
			   chip->master_sw_ctl);
1013 1014 1015
		if (mix->line_mute.addr != 0)
			check_mute(chip, &mix->line_mute, 1, mix->auto_mute_notify,
				   chip->lineout_sw_ctl);
1016
	}
1017
	if (mix->auto_mute_notify)
1018 1019
		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
				       &chip->hp_detect_ctl->id);
1020 1021 1022 1023

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

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

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


/* interrupt - headphone plug changed */
1051
static irqreturn_t headphone_intr(int irq, void *devid)
L
Linus Torvalds 已提交
1052
{
1053
	struct snd_pmac *chip = devid;
L
Linus Torvalds 已提交
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
	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)
{
1064
	struct device_node *gpiop;
L
Linus Torvalds 已提交
1065 1066
	struct device_node *np;
  
1067 1068
	gpiop = of_find_node_by_name(NULL, "gpio");
	if (! gpiop)
L
Linus Torvalds 已提交
1069 1070
		return NULL;
  
1071 1072
	for (np = of_get_next_child(gpiop, NULL); np;
			np = of_get_next_child(gpiop, np)) {
1073
		const char *property = of_get_property(np, "audio-gpio", NULL);
L
Linus Torvalds 已提交
1074
		if (property && strcmp(property, name) == 0)
1075
			break;
L
Linus Torvalds 已提交
1076
	}  
1077 1078
	of_node_put(gpiop);
	return np;
L
Linus Torvalds 已提交
1079 1080 1081 1082 1083
}

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

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

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

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

1134 1135
	gp->addr = addr & 0x0000ffff;
	/* Try to find the active state, default to 0 ! */
1136
	base = of_get_property(node, "audio-gpio-active-state", NULL);
1137
	if (base) {
L
Linus Torvalds 已提交
1138
		gp->active_state = *base;
1139 1140 1141
		gp->active_val = (*base) ? 0x5 : 0x4;
		gp->inactive_val = (*base) ? 0x4 : 0x5;
	} else {
1142
		const u32 *prop = NULL;
1143 1144
		gp->active_state = IS_G4DA
				&& !strncmp(device, "keywest-gpio1", 13);
1145 1146 1147 1148 1149 1150 1151
		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)
1152
			prop = of_get_property(node, platform, NULL);
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
		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 已提交
1167

1168 1169 1170
	ret = irq_of_parse_and_map(node, 0);
	of_node_put(node);
	return ret;
L
Linus Torvalds 已提交
1171 1172 1173
}

/* reset audio */
1174
static void tumbler_reset_audio(struct snd_pmac *chip)
L
Linus Torvalds 已提交
1175
{
1176
	struct pmac_tumbler *mix = chip->mixer_data;
L
Linus Torvalds 已提交
1177

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

1192
		write_audio_gpio(&mix->audio_reset, 0);
1193
		msleep(200);
1194
		write_audio_gpio(&mix->audio_reset, 1);
1195
		msleep(100);
1196
		write_audio_gpio(&mix->audio_reset, 0);
1197
		msleep(100);
1198
	}
L
Linus Torvalds 已提交
1199 1200
}

1201
#ifdef CONFIG_PM
1202
/* suspend mixer */
1203
static void tumbler_suspend(struct snd_pmac *chip)
1204
{
1205
	struct pmac_tumbler *mix = chip->mixer_data;
1206 1207 1208

	if (mix->headphone_irq >= 0)
		disable_irq(mix->headphone_irq);
1209 1210
	if (mix->lineout_irq >= 0)
		disable_irq(mix->lineout_irq);
1211 1212
	mix->save_master_switch[0] = mix->master_switch[0];
	mix->save_master_switch[1] = mix->master_switch[1];
1213 1214
	mix->save_master_vol[0] = mix->master_vol[0];
	mix->save_master_vol[1] = mix->master_vol[1];
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
	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 已提交
1232
/* resume mixer */
1233
static void tumbler_resume(struct snd_pmac *chip)
L
Linus Torvalds 已提交
1234
{
1235
	struct pmac_tumbler *mix = chip->mixer_data;
L
Linus Torvalds 已提交
1236

1237 1238 1239
	mix->acs &= ~1;
	mix->master_switch[0] = mix->save_master_switch[0];
	mix->master_switch[1] = mix->save_master_switch[1];
1240 1241
	mix->master_vol[0] = mix->save_master_vol[0];
	mix->master_vol[1] = mix->save_master_vol[1];
L
Linus Torvalds 已提交
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264
	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);
1265 1266 1267
	if (mix->headphone_irq >= 0) {
		unsigned char val;

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

/* initialize tumbler */
1279
static int __devinit tumbler_init(struct snd_pmac *chip)
L
Linus Torvalds 已提交
1280
{
1281
	int irq;
1282
	struct pmac_tumbler *mix = chip->mixer_data;
L
Linus Torvalds 已提交
1283

1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309
	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);
1310
	if (irq <= NO_IRQ)
1311 1312
		irq = tumbler_find_device("headphone-detect",
					  NULL, &mix->hp_detect, 1);
1313
	if (irq <= NO_IRQ)
1314 1315 1316 1317 1318
		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);
1319
 	if (irq <= NO_IRQ)
1320 1321
		irq = tumbler_find_device("line-output-detect",
					  NULL, &mix->line_detect, 1);
1322 1323 1324
	if (IS_G4DA && irq <= NO_IRQ)
		irq = tumbler_find_device("keywest-gpio16",
					  NULL, &mix->line_detect, 1);
1325
	mix->lineout_irq = irq;
L
Linus Torvalds 已提交
1326 1327 1328 1329 1330 1331

	tumbler_reset_audio(chip);
  
	return 0;
}

1332
static void tumbler_cleanup(struct snd_pmac *chip)
L
Linus Torvalds 已提交
1333
{
1334
	struct pmac_tumbler *mix = chip->mixer_data;
L
Linus Torvalds 已提交
1335 1336 1337 1338 1339
	if (! mix)
		return;

	if (mix->headphone_irq >= 0)
		free_irq(mix->headphone_irq, chip);
1340 1341
	if (mix->lineout_irq >= 0)
		free_irq(mix->lineout_irq, chip);
L
Linus Torvalds 已提交
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351
	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 */
1352
int __devinit snd_pmac_tumbler_init(struct snd_pmac *chip)
L
Linus Torvalds 已提交
1353 1354
{
	int i, err;
1355
	struct pmac_tumbler *mix;
1356
	const u32 *paddr;
1357
	struct device_node *tas_node, *np;
L
Linus Torvalds 已提交
1358 1359
	char *chipname;

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

1362
	mix = kzalloc(sizeof(*mix), GFP_KERNEL);
L
Linus Torvalds 已提交
1363 1364 1365 1366 1367 1368
	if (! mix)
		return -ENOMEM;
	mix->headphone_irq = -1;

	chip->mixer_data = mix;
	chip->mixer_free = tumbler_cleanup;
1369 1370 1371 1372 1373
	mix->anded_reset = 0;
	mix->reset_on_sleep = 1;

	for (np = chip->node->child; np; np = np->sibling) {
		if (!strcmp(np->name, "sound")) {
1374
			if (of_get_property(np, "has-anded-reset", NULL))
1375
				mix->anded_reset = 1;
1376
			if (of_get_property(np, "layout-id", NULL))
1377 1378 1379 1380
				mix->reset_on_sleep = 0;
			break;
		}
	}
L
Linus Torvalds 已提交
1381 1382 1383 1384
	if ((err = tumbler_init(chip)) < 0)
		return err;

	/* set up TAS */
1385
	tas_node = of_find_node_by_name(NULL, "deq");
1386
	if (tas_node == NULL)
1387
		tas_node = of_find_node_by_name(NULL, "codec");
L
Linus Torvalds 已提交
1388 1389 1390
	if (tas_node == NULL)
		return -ENODEV;

1391
	paddr = of_get_property(tas_node, "i2c-address", NULL);
1392
	if (paddr == NULL)
1393
		paddr = of_get_property(tas_node, "reg", NULL);
L
Linus Torvalds 已提交
1394 1395 1396 1397
	if (paddr)
		mix->i2c.addr = (*paddr) >> 1;
	else
		mix->i2c.addr = TAS_I2C_ADDR;
1398
	of_node_put(tas_node);
L
Linus Torvalds 已提交
1399

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

L
Linus Torvalds 已提交
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 1430 1431 1432 1433 1434 1435 1436
	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;
1437 1438 1439 1440 1441
	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 已提交
1442 1443 1444 1445
	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;

1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456
	/* 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);

1457
#ifdef CONFIG_PM
1458
	chip->suspend = tumbler_suspend;
L
Linus Torvalds 已提交
1459 1460 1461
	chip->resume = tumbler_resume;
#endif

D
David Howells 已提交
1462 1463
	INIT_WORK(&device_change, device_change_handler);
	device_change_chip = chip;
L
Linus Torvalds 已提交
1464 1465

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

	/* 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 已提交
1492 1493 1494 1495
#endif

	return 0;
}