pontis.c 22.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
/*
 *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
 *
 *   Lowlevel functions for Pontis MS300
 *
 *	Copyright (c) 2004 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
 *
 */

#include <sound/driver.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/slab.h>
30 31
#include <linux/mutex.h>

L
Linus Torvalds 已提交
32 33
#include <sound/core.h>
#include <sound/info.h>
34
#include <sound/tlv.h>
L
Linus Torvalds 已提交
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 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

#include "ice1712.h"
#include "envy24ht.h"
#include "pontis.h"

/* I2C addresses */
#define WM_DEV		0x34
#define CS_DEV		0x20

/* WM8776 registers */
#define WM_HP_ATTEN_L		0x00	/* headphone left attenuation */
#define WM_HP_ATTEN_R		0x01	/* headphone left attenuation */
#define WM_HP_MASTER		0x02	/* headphone master (both channels), override LLR */
#define WM_DAC_ATTEN_L		0x03	/* digital left attenuation */
#define WM_DAC_ATTEN_R		0x04
#define WM_DAC_MASTER		0x05
#define WM_PHASE_SWAP		0x06	/* DAC phase swap */
#define WM_DAC_CTRL1		0x07
#define WM_DAC_MUTE		0x08
#define WM_DAC_CTRL2		0x09
#define WM_DAC_INT		0x0a
#define WM_ADC_INT		0x0b
#define WM_MASTER_CTRL		0x0c
#define WM_POWERDOWN		0x0d
#define WM_ADC_ATTEN_L		0x0e
#define WM_ADC_ATTEN_R		0x0f
#define WM_ALC_CTRL1		0x10
#define WM_ALC_CTRL2		0x11
#define WM_ALC_CTRL3		0x12
#define WM_NOISE_GATE		0x13
#define WM_LIMITER		0x14
#define WM_ADC_MUX		0x15
#define WM_OUT_MUX		0x16
#define WM_RESET		0x17

/*
 * GPIO
 */
#define PONTIS_CS_CS		(1<<4)	/* CS */
#define PONTIS_CS_CLK		(1<<5)	/* CLK */
#define PONTIS_CS_RDATA		(1<<6)	/* CS8416 -> VT1720 */
#define PONTIS_CS_WDATA		(1<<7)	/* VT1720 -> CS8416 */


/*
 * get the current register value of WM codec
 */
82
static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
L
Linus Torvalds 已提交
83 84 85 86 87 88 89 90 91
{
	reg <<= 1;
	return ((unsigned short)ice->akm[0].images[reg] << 8) |
		ice->akm[0].images[reg + 1];
}

/*
 * set the register value of WM codec and remember it
 */
92
static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
L
Linus Torvalds 已提交
93 94 95 96 97 98
{
	unsigned short cval;
	cval = (reg << 9) | val;
	snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
}

99
static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
L
Linus Torvalds 已提交
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
{
	wm_put_nocache(ice, reg, val);
	reg <<= 1;
	ice->akm[0].images[reg] = val >> 8;
	ice->akm[0].images[reg + 1] = val;
}

/*
 * DAC volume attenuation mixer control (-64dB to 0dB)
 */

#define DAC_0dB	0xff
#define DAC_RES	128
#define DAC_MIN	(DAC_0dB - DAC_RES)

115
static int wm_dac_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
116 117 118 119 120 121 122 123
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 2;
	uinfo->value.integer.min = 0;	/* mute */
	uinfo->value.integer.max = DAC_RES;	/* 0dB, 0.5dB step */
	return 0;
}

124
static int wm_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
125
{
126
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
127 128 129
	unsigned short val;
	int i;

130
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
131 132 133 134 135
	for (i = 0; i < 2; i++) {
		val = wm_get(ice, WM_DAC_ATTEN_L + i) & 0xff;
		val = val > DAC_MIN ? (val - DAC_MIN) : 0;
		ucontrol->value.integer.value[i] = val;
	}
136
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
137 138 139
	return 0;
}

140
static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
141
{
142
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
143 144 145
	unsigned short oval, nval;
	int i, idx, change = 0;

146
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
147 148 149 150 151 152 153 154 155 156 157
	for (i = 0; i < 2; i++) {
		nval = ucontrol->value.integer.value[i];
		nval = (nval ? (nval + DAC_MIN) : 0) & 0xff;
		idx = WM_DAC_ATTEN_L + i;
		oval = wm_get(ice, idx) & 0xff;
		if (oval != nval) {
			wm_put(ice, idx, nval);
			wm_put_nocache(ice, idx, nval | 0x100);
			change = 1;
		}
	}
158
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
159 160 161 162 163 164 165 166 167 168 169
	return change;
}

/*
 * ADC gain mixer control (-64dB to 0dB)
 */

#define ADC_0dB	0xcf
#define ADC_RES	128
#define ADC_MIN	(ADC_0dB - ADC_RES)

170
static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
171 172 173 174 175 176 177 178
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 2;
	uinfo->value.integer.min = 0;	/* mute (-64dB) */
	uinfo->value.integer.max = ADC_RES;	/* 0dB, 0.5dB step */
	return 0;
}

179
static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
180
{
181
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
182 183 184
	unsigned short val;
	int i;

185
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
186 187 188 189 190
	for (i = 0; i < 2; i++) {
		val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff;
		val = val > ADC_MIN ? (val - ADC_MIN) : 0;
		ucontrol->value.integer.value[i] = val;
	}
191
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
192 193 194
	return 0;
}

195
static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
196
{
197
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
198 199 200
	unsigned short ovol, nvol;
	int i, idx, change = 0;

201
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
202 203 204 205 206 207 208 209 210 211
	for (i = 0; i < 2; i++) {
		nvol = ucontrol->value.integer.value[i];
		nvol = nvol ? (nvol + ADC_MIN) : 0;
		idx  = WM_ADC_ATTEN_L + i;
		ovol = wm_get(ice, idx) & 0xff;
		if (ovol != nvol) {
			wm_put(ice, idx, nvol);
			change = 1;
		}
	}
212
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
213 214 215 216 217 218
	return change;
}

/*
 * ADC input mux mixer control
 */
219
static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
220 221 222 223 224 225 226 227
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 1;
	return 0;
}

228
static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
229
{
230
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
231 232
	int bit = kcontrol->private_value;

233
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
234
	ucontrol->value.integer.value[0] = (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0;
235
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
236 237 238
	return 0;
}

239
static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
240
{
241
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
242 243 244 245
	int bit = kcontrol->private_value;
	unsigned short oval, nval;
	int change;

246
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
247 248 249 250 251 252 253 254 255
	nval = oval = wm_get(ice, WM_ADC_MUX);
	if (ucontrol->value.integer.value[0])
		nval |= (1 << bit);
	else
		nval &= ~(1 << bit);
	change = nval != oval;
	if (change) {
		wm_put(ice, WM_ADC_MUX, nval);
	}
256
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
257 258 259 260 261 262
	return 0;
}

/*
 * Analog bypass (In -> Out)
 */
263
static int wm_bypass_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
264 265 266 267 268 269 270 271
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 1;
	return 0;
}

272
static int wm_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
273
{
274
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
275

276
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
277
	ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0;
278
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
279 280 281
	return 0;
}

282
static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
283
{
284
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
285 286 287
	unsigned short val, oval;
	int change = 0;

288
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
289 290 291 292 293 294 295 296 297
	val = oval = wm_get(ice, WM_OUT_MUX);
	if (ucontrol->value.integer.value[0])
		val |= 0x04;
	else
		val &= ~0x04;
	if (val != oval) {
		wm_put(ice, WM_OUT_MUX, val);
		change = 1;
	}
298
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
299 300 301 302 303 304
	return change;
}

/*
 * Left/Right swap
 */
305
static int wm_chswap_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
306 307 308 309 310 311 312 313
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 1;
	return 0;
}

314
static int wm_chswap_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
315
{
316
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
317

318
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
319
	ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90;
320
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
321 322 323
	return 0;
}

324
static int wm_chswap_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
325
{
326
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
327 328 329
	unsigned short val, oval;
	int change = 0;

330
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
331 332 333 334 335 336 337 338 339 340 341
	oval = wm_get(ice, WM_DAC_CTRL1);
	val = oval & 0x0f;
	if (ucontrol->value.integer.value[0])
		val |= 0x60;
	else
		val |= 0x90;
	if (val != oval) {
		wm_put(ice, WM_DAC_CTRL1, val);
		wm_put_nocache(ice, WM_DAC_CTRL1, val);
		change = 1;
	}
342
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
343 344 345 346 347 348
	return change;
}

/*
 * write data in the SPI mode
 */
349
static void set_gpio_bit(struct snd_ice1712 *ice, unsigned int bit, int val)
L
Linus Torvalds 已提交
350 351 352 353 354 355 356 357 358
{
	unsigned int tmp = snd_ice1712_gpio_read(ice);
	if (val)
		tmp |= bit;
	else
		tmp &= ~bit;
	snd_ice1712_gpio_write(ice, tmp);
}

359
static void spi_send_byte(struct snd_ice1712 *ice, unsigned char data)
L
Linus Torvalds 已提交
360 361 362 363 364 365 366 367 368 369 370 371 372
{
	int i;
	for (i = 0; i < 8; i++) {
		set_gpio_bit(ice, PONTIS_CS_CLK, 0);
		udelay(1);
		set_gpio_bit(ice, PONTIS_CS_WDATA, data & 0x80);
		udelay(1);
		set_gpio_bit(ice, PONTIS_CS_CLK, 1);
		udelay(1);
		data <<= 1;
	}
}

373
static unsigned int spi_read_byte(struct snd_ice1712 *ice)
L
Linus Torvalds 已提交
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
{
	int i;
	unsigned int val = 0;

	for (i = 0; i < 8; i++) {
		val <<= 1;
		set_gpio_bit(ice, PONTIS_CS_CLK, 0);
		udelay(1);
		if (snd_ice1712_gpio_read(ice) & PONTIS_CS_RDATA)
			val |= 1;
		udelay(1);
		set_gpio_bit(ice, PONTIS_CS_CLK, 1);
		udelay(1);
	}
	return val;
}


392
static void spi_write(struct snd_ice1712 *ice, unsigned int dev, unsigned int reg, unsigned int data)
L
Linus Torvalds 已提交
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
{
	snd_ice1712_gpio_set_dir(ice, PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK);
	snd_ice1712_gpio_set_mask(ice, ~(PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK));
	set_gpio_bit(ice, PONTIS_CS_CS, 0);
	spi_send_byte(ice, dev & ~1); /* WRITE */
	spi_send_byte(ice, reg); /* MAP */
	spi_send_byte(ice, data); /* DATA */
	/* trigger */
	set_gpio_bit(ice, PONTIS_CS_CS, 1);
	udelay(1);
	/* restore */
	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
}

408
static unsigned int spi_read(struct snd_ice1712 *ice, unsigned int dev, unsigned int reg)
L
Linus Torvalds 已提交
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
{
	unsigned int val;
	snd_ice1712_gpio_set_dir(ice, PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK);
	snd_ice1712_gpio_set_mask(ice, ~(PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK));
	set_gpio_bit(ice, PONTIS_CS_CS, 0);
	spi_send_byte(ice, dev & ~1); /* WRITE */
	spi_send_byte(ice, reg); /* MAP */
	/* trigger */
	set_gpio_bit(ice, PONTIS_CS_CS, 1);
	udelay(1);
	set_gpio_bit(ice, PONTIS_CS_CS, 0);
	spi_send_byte(ice, dev | 1); /* READ */
	val = spi_read_byte(ice);
	/* trigger */
	set_gpio_bit(ice, PONTIS_CS_CS, 1);
	udelay(1);
	/* restore */
	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
	return val;
}


/*
 * SPDIF input source
 */
435
static int cs_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
{
	static char *texts[] = {
		"Coax",		/* RXP0 */
		"Optical",	/* RXP1 */
		"CD",		/* RXP2 */
	};
	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
	uinfo->count = 1;
	uinfo->value.enumerated.items = 3;
	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
	return 0;
}

451
static int cs_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
452
{
453
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
454

455
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
456
	ucontrol->value.enumerated.item[0] = ice->gpio.saved[0];
457
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
458 459 460
	return 0;
}

461
static int cs_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
462
{
463
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
464 465 466
	unsigned char val;
	int change = 0;

467
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
468 469 470 471 472 473
	if (ucontrol->value.enumerated.item[0] != ice->gpio.saved[0]) {
		ice->gpio.saved[0] = ucontrol->value.enumerated.item[0] & 3;
		val = 0x80 | (ice->gpio.saved[0] << 3);
		spi_write(ice, CS_DEV, 0x04, val);
		change = 1;
	}
474
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
475 476 477 478 479 480 481
	return 0;
}


/*
 * GPIO controls
 */
482
static int pontis_gpio_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
L
Linus Torvalds 已提交
483 484 485 486 487 488 489 490
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 1;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 0xffff; /* 16bit */
	return 0;
}

491
static int pontis_gpio_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
492
{
493
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
494
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
495 496
	/* 4-7 reserved */
	ucontrol->value.integer.value[0] = (~ice->gpio.write_mask & 0xffff) | 0x00f0;
497
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
498 499 500
	return 0;
}
	
501
static int pontis_gpio_mask_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
502
{
503
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
504 505
	unsigned int val;
	int changed;
506
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
507 508 509 510
	/* 4-7 reserved */
	val = (~ucontrol->value.integer.value[0] & 0xffff) | 0x00f0;
	changed = val != ice->gpio.write_mask;
	ice->gpio.write_mask = val;
511
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
512 513 514
	return changed;
}

515
static int pontis_gpio_dir_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
516
{
517
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
518
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
519 520
	/* 4-7 reserved */
	ucontrol->value.integer.value[0] = ice->gpio.direction & 0xff0f;
521
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
522 523 524
	return 0;
}
	
525
static int pontis_gpio_dir_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
526
{
527
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
528 529
	unsigned int val;
	int changed;
530
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
531 532 533 534
	/* 4-7 reserved */
	val = ucontrol->value.integer.value[0] & 0xff0f;
	changed = (val != ice->gpio.direction);
	ice->gpio.direction = val;
535
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
536 537 538
	return changed;
}

539
static int pontis_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
540
{
541
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
542
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
543 544 545
	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
	ucontrol->value.integer.value[0] = snd_ice1712_gpio_read(ice) & 0xffff;
546
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
547 548 549
	return 0;
}

550
static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
L
Linus Torvalds 已提交
551
{
552
	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
L
Linus Torvalds 已提交
553 554
	unsigned int val, nval;
	int changed = 0;
555
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
556 557 558 559 560 561 562 563
	snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
	snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
	val = snd_ice1712_gpio_read(ice) & 0xffff;
	nval = ucontrol->value.integer.value[0] & 0xffff;
	if (val != nval) {
		snd_ice1712_gpio_write(ice, nval);
		changed = 1;
	}
564
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
565 566 567
	return changed;
}

568 569
static DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1);

L
Linus Torvalds 已提交
570 571 572 573
/*
 * mixers
 */

574
static struct snd_kcontrol_new pontis_controls[] __devinitdata = {
L
Linus Torvalds 已提交
575 576
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
577 578
		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
L
Linus Torvalds 已提交
579 580 581 582
		.name = "PCM Playback Volume",
		.info = wm_dac_vol_info,
		.get = wm_dac_vol_get,
		.put = wm_dac_vol_put,
583
		.tlv = { .p = db_scale_volume },
L
Linus Torvalds 已提交
584 585 586
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
587 588
		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
L
Linus Torvalds 已提交
589 590 591 592
		.name = "Capture Volume",
		.info = wm_adc_vol_info,
		.get = wm_adc_vol_get,
		.put = wm_adc_vol_put,
593
		.tlv = { .p = db_scale_volume },
L
Linus Torvalds 已提交
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 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "CD Capture Switch",
		.info = wm_adc_mux_info,
		.get = wm_adc_mux_get,
		.put = wm_adc_mux_put,
		.private_value = 0,
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Line Capture Switch",
		.info = wm_adc_mux_info,
		.get = wm_adc_mux_get,
		.put = wm_adc_mux_put,
		.private_value = 1,
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Analog Bypass Switch",
		.info = wm_bypass_info,
		.get = wm_bypass_get,
		.put = wm_bypass_put,
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "Swap Output Channels",
		.info = wm_chswap_info,
		.get = wm_chswap_get,
		.put = wm_chswap_put,
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "IEC958 Input Source",
		.info = cs_source_info,
		.get = cs_source_get,
		.put = cs_source_put,
	},
	/* FIXME: which interface? */
	{
		.iface = SNDRV_CTL_ELEM_IFACE_CARD,
		.name = "GPIO Mask",
		.info = pontis_gpio_mask_info,
		.get = pontis_gpio_mask_get,
		.put = pontis_gpio_mask_put,
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_CARD,
		.name = "GPIO Direction",
		.info = pontis_gpio_mask_info,
		.get = pontis_gpio_dir_get,
		.put = pontis_gpio_dir_put,
	},
	{
		.iface = SNDRV_CTL_ELEM_IFACE_CARD,
		.name = "GPIO Data",
		.info = pontis_gpio_mask_info,
		.get = pontis_gpio_data_get,
		.put = pontis_gpio_data_put,
	},
};


/*
 * WM codec registers
 */
660
static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
L
Linus Torvalds 已提交
661
{
662
	struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
L
Linus Torvalds 已提交
663 664
	char line[64];
	unsigned int reg, val;
665
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
666 667 668 669 670 671
	while (!snd_info_get_line(buffer, line, sizeof(line))) {
		if (sscanf(line, "%x %x", &reg, &val) != 2)
			continue;
		if (reg <= 0x17 && val <= 0xffff)
			wm_put(ice, reg, val);
	}
672
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
673 674
}

675
static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
L
Linus Torvalds 已提交
676
{
677
	struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
L
Linus Torvalds 已提交
678 679
	int reg, val;

680
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
681 682 683 684
	for (reg = 0; reg <= 0x17; reg++) {
		val = wm_get(ice, reg);
		snd_iprintf(buffer, "%02x = %04x\n", reg, val);
	}
685
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
686 687
}

688
static void wm_proc_init(struct snd_ice1712 *ice)
L
Linus Torvalds 已提交
689
{
690
	struct snd_info_entry *entry;
L
Linus Torvalds 已提交
691
	if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) {
692
		snd_info_set_text_ops(entry, ice, wm_proc_regs_read);
L
Linus Torvalds 已提交
693 694 695 696 697
		entry->mode |= S_IWUSR;
		entry->c.text.write = wm_proc_regs_write;
	}
}

698
static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
L
Linus Torvalds 已提交
699
{
700
	struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
L
Linus Torvalds 已提交
701 702
	int reg, val;

703
	mutex_lock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
704 705 706 707 708 709
	for (reg = 0; reg <= 0x26; reg++) {
		val = spi_read(ice, CS_DEV, reg);
		snd_iprintf(buffer, "%02x = %02x\n", reg, val);
	}
	val = spi_read(ice, CS_DEV, 0x7f);
	snd_iprintf(buffer, "%02x = %02x\n", 0x7f, val);
710
	mutex_unlock(&ice->gpio_mutex);
L
Linus Torvalds 已提交
711 712
}

713
static void cs_proc_init(struct snd_ice1712 *ice)
L
Linus Torvalds 已提交
714
{
715
	struct snd_info_entry *entry;
716 717
	if (! snd_card_proc_new(ice->card, "cs_codec", &entry))
		snd_info_set_text_ops(entry, ice, cs_proc_regs_read);
L
Linus Torvalds 已提交
718 719 720
}


721
static int __devinit pontis_add_controls(struct snd_ice1712 *ice)
L
Linus Torvalds 已提交
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
{
	unsigned int i;
	int err;

	for (i = 0; i < ARRAY_SIZE(pontis_controls); i++) {
		err = snd_ctl_add(ice->card, snd_ctl_new1(&pontis_controls[i], ice));
		if (err < 0)
			return err;
	}

	wm_proc_init(ice);
	cs_proc_init(ice);

	return 0;
}


/*
 * initialize the chip
 */
742
static int __devinit pontis_init(struct snd_ice1712 *ice)
L
Linus Torvalds 已提交
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792
{
	static unsigned short wm_inits[] = {
		/* These come first to reduce init pop noise */
		WM_ADC_MUX,	0x00c0,	/* ADC mute */
		WM_DAC_MUTE,	0x0001,	/* DAC softmute */
		WM_DAC_CTRL1,	0x0000,	/* DAC mute */

		WM_POWERDOWN,	0x0008,	/* All power-up except HP */
		WM_RESET,	0x0000,	/* reset */
	};
	static unsigned short wm_inits2[] = {
		WM_MASTER_CTRL,	0x0022,	/* 256fs, slave mode */
		WM_DAC_INT,	0x0022,	/* I2S, normal polarity, 24bit */
		WM_ADC_INT,	0x0022,	/* I2S, normal polarity, 24bit */
		WM_DAC_CTRL1,	0x0090,	/* DAC L/R */
		WM_OUT_MUX,	0x0001,	/* OUT DAC */
		WM_HP_ATTEN_L,	0x0179,	/* HP 0dB */
		WM_HP_ATTEN_R,	0x0179,	/* HP 0dB */
		WM_DAC_ATTEN_L,	0x0000,	/* DAC 0dB */
		WM_DAC_ATTEN_L,	0x0100,	/* DAC 0dB */
		WM_DAC_ATTEN_R,	0x0000,	/* DAC 0dB */
		WM_DAC_ATTEN_R,	0x0100,	/* DAC 0dB */
		// WM_DAC_MASTER,	0x0100,	/* DAC master muted */
		WM_PHASE_SWAP,	0x0000,	/* phase normal */
		WM_DAC_CTRL2,	0x0000,	/* no deemphasis, no ZFLG */
		WM_ADC_ATTEN_L,	0x0000,	/* ADC muted */
		WM_ADC_ATTEN_R,	0x0000,	/* ADC muted */
#if 0
		WM_ALC_CTRL1,	0x007b,	/* */
		WM_ALC_CTRL2,	0x0000,	/* */
		WM_ALC_CTRL3,	0x0000,	/* */
		WM_NOISE_GATE,	0x0000,	/* */
#endif
		WM_DAC_MUTE,	0x0000,	/* DAC unmute */
		WM_ADC_MUX,	0x0003,	/* ADC unmute, both CD/Line On */
	};
	static unsigned char cs_inits[] = {
		0x04,	0x80,	/* RUN, RXP0 */
		0x05,	0x05,	/* slave, 24bit */
		0x01,	0x00,
		0x02,	0x00,
		0x03,	0x00,
	};
	unsigned int i;

	ice->vt1720 = 1;
	ice->num_total_dacs = 2;
	ice->num_total_adcs = 2;

	/* to remeber the register values */
793
	ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
L
Linus Torvalds 已提交
794 795 796 797 798 799 800 801 802 803 804 805
	if (! ice->akm)
		return -ENOMEM;
	ice->akm_codecs = 1;

	/* HACK - use this as the SPDIF source.
	 * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten
	 */
	ice->gpio.saved[0] = 0;

	/* initialize WM8776 codec */
	for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2)
		wm_put(ice, wm_inits[i], wm_inits[i+1]);
806
	schedule_timeout_uninterruptible(1);
L
Linus Torvalds 已提交
807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
	for (i = 0; i < ARRAY_SIZE(wm_inits2); i += 2)
		wm_put(ice, wm_inits2[i], wm_inits2[i+1]);

	/* initialize CS8416 codec */
	/* assert PRST#; MT05 bit 7 */
	outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));
	mdelay(5);
	/* deassert PRST# */
	outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));

	for (i = 0; i < ARRAY_SIZE(cs_inits); i += 2)
		spi_write(ice, CS_DEV, cs_inits[i], cs_inits[i+1]);

	return 0;
}


/*
 * Pontis boards don't provide the EEPROM data at all.
 * hence the driver needs to sets up it properly.
 */

static unsigned char pontis_eeprom[] __devinitdata = {
830 831 832 833 834 835 836 837 838 839 840 841 842
	[ICE_EEP2_SYSCONF]     = 0x08,	/* clock 256, mpu401, spdif-in/ADC, 1DAC */
	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
	[ICE_EEP2_I2S]         = 0xf8,	/* vol, 96k, 24bit, 192k */
	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
	[ICE_EEP2_GPIO_DIR]    = 0x07,
	[ICE_EEP2_GPIO_DIR1]   = 0x00,
	[ICE_EEP2_GPIO_DIR2]   = 0x00,	/* ignored */
	[ICE_EEP2_GPIO_MASK]   = 0x0f,	/* 4-7 reserved for CS8416 */
	[ICE_EEP2_GPIO_MASK1]  = 0xff,
	[ICE_EEP2_GPIO_MASK2]  = 0x00,	/* ignored */
	[ICE_EEP2_GPIO_STATE]  = 0x06,	/* 0-low, 1-high, 2-high */
	[ICE_EEP2_GPIO_STATE1] = 0x00,
	[ICE_EEP2_GPIO_STATE2] = 0x00,	/* ignored */
L
Linus Torvalds 已提交
843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
};

/* entry point */
struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = {
	{
		.subvendor = VT1720_SUBDEVICE_PONTIS_MS300,
		.name = "Pontis MS300",
		.model = "ms300",
		.chip_init = pontis_init,
		.build_controls = pontis_add_controls,
		.eeprom_size = sizeof(pontis_eeprom),
		.eeprom_data = pontis_eeprom,
	},
	{ } /* terminator */
};