1266 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ALSA driver for ICEnsemble VT1724 (Envy24HT)4 *5 * Lowlevel functions for Audiotrak Prodigy 7.1 Hifi6 * based on pontis.c7 *8 * Copyright (c) 2007 Julian Scheel <julian@jusst.de>9 * Copyright (c) 2007 allank10 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>11 */12 13 14#include <linux/delay.h>15#include <linux/interrupt.h>16#include <linux/init.h>17#include <linux/slab.h>18#include <linux/mutex.h>19 20#include <sound/core.h>21#include <sound/info.h>22#include <sound/tlv.h>23 24#include "ice1712.h"25#include "envy24ht.h"26#include "prodigy_hifi.h"27 28struct prodigy_hifi_spec {29 unsigned short master[2];30 unsigned short vol[8];31};32 33/* I2C addresses */34#define WM_DEV 0x3435 36/* WM8776 registers */37#define WM_HP_ATTEN_L 0x00 /* headphone left attenuation */38#define WM_HP_ATTEN_R 0x01 /* headphone left attenuation */39#define WM_HP_MASTER 0x02 /* headphone master (both channels),40 override LLR */41#define WM_DAC_ATTEN_L 0x03 /* digital left attenuation */42#define WM_DAC_ATTEN_R 0x0443#define WM_DAC_MASTER 0x0544#define WM_PHASE_SWAP 0x06 /* DAC phase swap */45#define WM_DAC_CTRL1 0x0746#define WM_DAC_MUTE 0x0847#define WM_DAC_CTRL2 0x0948#define WM_DAC_INT 0x0a49#define WM_ADC_INT 0x0b50#define WM_MASTER_CTRL 0x0c51#define WM_POWERDOWN 0x0d52#define WM_ADC_ATTEN_L 0x0e53#define WM_ADC_ATTEN_R 0x0f54#define WM_ALC_CTRL1 0x1055#define WM_ALC_CTRL2 0x1156#define WM_ALC_CTRL3 0x1257#define WM_NOISE_GATE 0x1358#define WM_LIMITER 0x1459#define WM_ADC_MUX 0x1560#define WM_OUT_MUX 0x1661#define WM_RESET 0x1762 63/* Analog Recording Source :- Mic, LineIn, CD/Video, */64 65/* implement capture source select control for WM8776 */66 67#define WM_AIN1 "AIN1"68#define WM_AIN2 "AIN2"69#define WM_AIN3 "AIN3"70#define WM_AIN4 "AIN4"71#define WM_AIN5 "AIN5"72 73/* GPIO pins of envy24ht connected to wm8766 */74#define WM8766_SPI_CLK (1<<17) /* CLK, Pin97 on ICE1724 */75#define WM8766_SPI_MD (1<<16) /* DATA VT1724 -> WM8766, Pin96 */76#define WM8766_SPI_ML (1<<18) /* Latch, Pin98 */77 78/* WM8766 registers */79#define WM8766_DAC_CTRL 0x02 /* DAC Control */80#define WM8766_INT_CTRL 0x03 /* Interface Control */81#define WM8766_DAC_CTRL2 0x0982#define WM8766_DAC_CTRL3 0x0a83#define WM8766_RESET 0x1f84#define WM8766_LDA1 0x0085#define WM8766_LDA2 0x0486#define WM8766_LDA3 0x0687#define WM8766_RDA1 0x0188#define WM8766_RDA2 0x0589#define WM8766_RDA3 0x0790#define WM8766_MUTE1 0x0C91#define WM8766_MUTE2 0x0F92 93 94/*95 * Prodigy HD296 */97#define AK4396_ADDR 0x0098#define AK4396_CSN (1 << 8) /* CSN->GPIO8, pin 75 */99#define AK4396_CCLK (1 << 9) /* CCLK->GPIO9, pin 76 */100#define AK4396_CDTI (1 << 10) /* CDTI->GPIO10, pin 77 */101 102/* ak4396 registers */103#define AK4396_CTRL1 0x00104#define AK4396_CTRL2 0x01105#define AK4396_CTRL3 0x02106#define AK4396_LCH_ATT 0x03107#define AK4396_RCH_ATT 0x04108 109 110/*111 * get the current register value of WM codec112 */113static unsigned short wm_get(struct snd_ice1712 *ice, int reg)114{115 reg <<= 1;116 return ((unsigned short)ice->akm[0].images[reg] << 8) |117 ice->akm[0].images[reg + 1];118}119 120/*121 * set the register value of WM codec and remember it122 */123static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)124{125 unsigned short cval;126 cval = (reg << 9) | val;127 snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);128}129 130static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)131{132 wm_put_nocache(ice, reg, val);133 reg <<= 1;134 ice->akm[0].images[reg] = val >> 8;135 ice->akm[0].images[reg + 1] = val;136}137 138/*139 * write data in the SPI mode140 */141 142static void set_gpio_bit(struct snd_ice1712 *ice, unsigned int bit, int val)143{144 unsigned int tmp = snd_ice1712_gpio_read(ice);145 if (val)146 tmp |= bit;147 else148 tmp &= ~bit;149 snd_ice1712_gpio_write(ice, tmp);150}151 152/*153 * SPI implementation for WM8766 codec - only writing supported, no readback154 */155 156static void wm8766_spi_send_word(struct snd_ice1712 *ice, unsigned int data)157{158 int i;159 for (i = 0; i < 16; i++) {160 set_gpio_bit(ice, WM8766_SPI_CLK, 0);161 udelay(1);162 set_gpio_bit(ice, WM8766_SPI_MD, data & 0x8000);163 udelay(1);164 set_gpio_bit(ice, WM8766_SPI_CLK, 1);165 udelay(1);166 data <<= 1;167 }168}169 170static void wm8766_spi_write(struct snd_ice1712 *ice, unsigned int reg,171 unsigned int data)172{173 unsigned int block;174 175 snd_ice1712_gpio_set_dir(ice, WM8766_SPI_MD|176 WM8766_SPI_CLK|WM8766_SPI_ML);177 snd_ice1712_gpio_set_mask(ice, ~(WM8766_SPI_MD|178 WM8766_SPI_CLK|WM8766_SPI_ML));179 /* latch must be low when writing */180 set_gpio_bit(ice, WM8766_SPI_ML, 0);181 block = (reg << 9) | (data & 0x1ff);182 wm8766_spi_send_word(ice, block); /* REGISTER ADDRESS */183 /* release latch */184 set_gpio_bit(ice, WM8766_SPI_ML, 1);185 udelay(1);186 /* restore */187 snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);188 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);189}190 191 192/*193 * serial interface for ak4396 - only writing supported, no readback194 */195 196static void ak4396_send_word(struct snd_ice1712 *ice, unsigned int data)197{198 int i;199 for (i = 0; i < 16; i++) {200 set_gpio_bit(ice, AK4396_CCLK, 0);201 udelay(1);202 set_gpio_bit(ice, AK4396_CDTI, data & 0x8000);203 udelay(1);204 set_gpio_bit(ice, AK4396_CCLK, 1);205 udelay(1);206 data <<= 1;207 }208}209 210static void ak4396_write(struct snd_ice1712 *ice, unsigned int reg,211 unsigned int data)212{213 unsigned int block;214 215 snd_ice1712_gpio_set_dir(ice, AK4396_CSN|AK4396_CCLK|AK4396_CDTI);216 snd_ice1712_gpio_set_mask(ice, ~(AK4396_CSN|AK4396_CCLK|AK4396_CDTI));217 /* latch must be low when writing */218 set_gpio_bit(ice, AK4396_CSN, 0); 219 block = ((AK4396_ADDR & 0x03) << 14) | (1 << 13) |220 ((reg & 0x1f) << 8) | (data & 0xff);221 ak4396_send_word(ice, block); /* REGISTER ADDRESS */222 /* release latch */223 set_gpio_bit(ice, AK4396_CSN, 1);224 udelay(1);225 /* restore */226 snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);227 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);228}229 230 231/*232 * ak4396 mixers233 */234 235 236 237/*238 * DAC volume attenuation mixer control (-64dB to 0dB)239 */240 241static int ak4396_dac_vol_info(struct snd_kcontrol *kcontrol,242 struct snd_ctl_elem_info *uinfo)243{244 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;245 uinfo->count = 2;246 uinfo->value.integer.min = 0; /* mute */247 uinfo->value.integer.max = 0xFF; /* linear */248 return 0;249}250 251static int ak4396_dac_vol_get(struct snd_kcontrol *kcontrol,252 struct snd_ctl_elem_value *ucontrol)253{254 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);255 struct prodigy_hifi_spec *spec = ice->spec;256 int i;257 258 for (i = 0; i < 2; i++)259 ucontrol->value.integer.value[i] = spec->vol[i];260 261 return 0;262}263 264static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)265{266 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);267 struct prodigy_hifi_spec *spec = ice->spec;268 int i;269 int change = 0;270 271 mutex_lock(&ice->gpio_mutex);272 for (i = 0; i < 2; i++) {273 if (ucontrol->value.integer.value[i] != spec->vol[i]) {274 spec->vol[i] = ucontrol->value.integer.value[i];275 ak4396_write(ice, AK4396_LCH_ATT + i,276 spec->vol[i] & 0xff);277 change = 1;278 }279 }280 mutex_unlock(&ice->gpio_mutex);281 return change;282}283 284static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);285static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);286 287static const struct snd_kcontrol_new prodigy_hd2_controls[] = {288 {289 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,290 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |291 SNDRV_CTL_ELEM_ACCESS_TLV_READ),292 .name = "Front Playback Volume",293 .info = ak4396_dac_vol_info,294 .get = ak4396_dac_vol_get,295 .put = ak4396_dac_vol_put,296 .tlv = { .p = ak4396_db_scale },297 },298};299 300 301/* --------------- */302 303#define WM_VOL_MAX 255304#define WM_VOL_MUTE 0x8000305 306 307#define DAC_0dB 0xff308#define DAC_RES 128309#define DAC_MIN (DAC_0dB - DAC_RES)310 311 312static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index,313 unsigned short vol, unsigned short master)314{315 unsigned char nvol;316 317 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))318 nvol = 0;319 else {320 nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128)321 & WM_VOL_MAX;322 nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff;323 }324 325 wm_put(ice, index, nvol);326 wm_put_nocache(ice, index, 0x100 | nvol);327}328 329static void wm8766_set_vol(struct snd_ice1712 *ice, unsigned int index,330 unsigned short vol, unsigned short master)331{332 unsigned char nvol;333 334 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))335 nvol = 0;336 else {337 nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128)338 & WM_VOL_MAX;339 nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff;340 }341 342 wm8766_spi_write(ice, index, (0x0100 | nvol));343}344 345 346/*347 * DAC volume attenuation mixer control (-64dB to 0dB)348 */349 350static int wm_dac_vol_info(struct snd_kcontrol *kcontrol,351 struct snd_ctl_elem_info *uinfo)352{353 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;354 uinfo->count = 2;355 uinfo->value.integer.min = 0; /* mute */356 uinfo->value.integer.max = DAC_RES; /* 0dB, 0.5dB step */357 return 0;358}359 360static int wm_dac_vol_get(struct snd_kcontrol *kcontrol,361 struct snd_ctl_elem_value *ucontrol)362{363 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);364 struct prodigy_hifi_spec *spec = ice->spec;365 int i;366 367 for (i = 0; i < 2; i++)368 ucontrol->value.integer.value[i] =369 spec->vol[2 + i] & ~WM_VOL_MUTE;370 return 0;371}372 373static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)374{375 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);376 struct prodigy_hifi_spec *spec = ice->spec;377 int i, idx, change = 0;378 379 mutex_lock(&ice->gpio_mutex);380 for (i = 0; i < 2; i++) {381 if (ucontrol->value.integer.value[i] != spec->vol[2 + i]) {382 idx = WM_DAC_ATTEN_L + i;383 spec->vol[2 + i] &= WM_VOL_MUTE;384 spec->vol[2 + i] |= ucontrol->value.integer.value[i];385 wm_set_vol(ice, idx, spec->vol[2 + i], spec->master[i]);386 change = 1;387 }388 }389 mutex_unlock(&ice->gpio_mutex);390 return change;391}392 393 394/*395 * WM8766 DAC volume attenuation mixer control396 */397static int wm8766_vol_info(struct snd_kcontrol *kcontrol,398 struct snd_ctl_elem_info *uinfo)399{400 int voices = kcontrol->private_value >> 8;401 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;402 uinfo->count = voices;403 uinfo->value.integer.min = 0; /* mute */404 uinfo->value.integer.max = DAC_RES; /* 0dB */405 return 0;406}407 408static int wm8766_vol_get(struct snd_kcontrol *kcontrol,409 struct snd_ctl_elem_value *ucontrol)410{411 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);412 struct prodigy_hifi_spec *spec = ice->spec;413 int i, ofs, voices;414 415 voices = kcontrol->private_value >> 8;416 ofs = kcontrol->private_value & 0xff;417 for (i = 0; i < voices; i++)418 ucontrol->value.integer.value[i] = spec->vol[ofs + i];419 return 0;420}421 422static int wm8766_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)423{424 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);425 struct prodigy_hifi_spec *spec = ice->spec;426 int i, idx, ofs, voices;427 int change = 0;428 429 voices = kcontrol->private_value >> 8;430 ofs = kcontrol->private_value & 0xff;431 mutex_lock(&ice->gpio_mutex);432 for (i = 0; i < voices; i++) {433 if (ucontrol->value.integer.value[i] != spec->vol[ofs + i]) {434 idx = WM8766_LDA1 + ofs + i;435 spec->vol[ofs + i] &= WM_VOL_MUTE;436 spec->vol[ofs + i] |= ucontrol->value.integer.value[i];437 wm8766_set_vol(ice, idx,438 spec->vol[ofs + i], spec->master[i]);439 change = 1;440 }441 }442 mutex_unlock(&ice->gpio_mutex);443 return change;444}445 446/*447 * Master volume attenuation mixer control / applied to WM8776+WM8766448 */449static int wm_master_vol_info(struct snd_kcontrol *kcontrol,450 struct snd_ctl_elem_info *uinfo)451{452 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;453 uinfo->count = 2;454 uinfo->value.integer.min = 0;455 uinfo->value.integer.max = DAC_RES;456 return 0;457}458 459static int wm_master_vol_get(struct snd_kcontrol *kcontrol,460 struct snd_ctl_elem_value *ucontrol)461{462 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);463 struct prodigy_hifi_spec *spec = ice->spec;464 int i;465 for (i = 0; i < 2; i++)466 ucontrol->value.integer.value[i] = spec->master[i];467 return 0;468}469 470static int wm_master_vol_put(struct snd_kcontrol *kcontrol,471 struct snd_ctl_elem_value *ucontrol)472{473 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);474 struct prodigy_hifi_spec *spec = ice->spec;475 int ch, change = 0;476 477 mutex_lock(&ice->gpio_mutex);478 for (ch = 0; ch < 2; ch++) {479 if (ucontrol->value.integer.value[ch] != spec->master[ch]) {480 spec->master[ch] = ucontrol->value.integer.value[ch];481 482 /* Apply to front DAC */483 wm_set_vol(ice, WM_DAC_ATTEN_L + ch,484 spec->vol[2 + ch], spec->master[ch]);485 486 wm8766_set_vol(ice, WM8766_LDA1 + ch,487 spec->vol[0 + ch], spec->master[ch]);488 489 wm8766_set_vol(ice, WM8766_LDA2 + ch,490 spec->vol[4 + ch], spec->master[ch]);491 492 wm8766_set_vol(ice, WM8766_LDA3 + ch,493 spec->vol[6 + ch], spec->master[ch]);494 change = 1;495 }496 }497 mutex_unlock(&ice->gpio_mutex); 498 return change;499}500 501 502/* KONSTI */503 504static int wm_adc_mux_enum_info(struct snd_kcontrol *kcontrol,505 struct snd_ctl_elem_info *uinfo)506{507 static const char * const texts[32] = {508 "NULL", WM_AIN1, WM_AIN2, WM_AIN1 "+" WM_AIN2,509 WM_AIN3, WM_AIN1 "+" WM_AIN3, WM_AIN2 "+" WM_AIN3,510 WM_AIN1 "+" WM_AIN2 "+" WM_AIN3,511 WM_AIN4, WM_AIN1 "+" WM_AIN4, WM_AIN2 "+" WM_AIN4,512 WM_AIN1 "+" WM_AIN2 "+" WM_AIN4,513 WM_AIN3 "+" WM_AIN4, WM_AIN1 "+" WM_AIN3 "+" WM_AIN4,514 WM_AIN2 "+" WM_AIN3 "+" WM_AIN4,515 WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4,516 WM_AIN5, WM_AIN1 "+" WM_AIN5, WM_AIN2 "+" WM_AIN5,517 WM_AIN1 "+" WM_AIN2 "+" WM_AIN5,518 WM_AIN3 "+" WM_AIN5, WM_AIN1 "+" WM_AIN3 "+" WM_AIN5,519 WM_AIN2 "+" WM_AIN3 "+" WM_AIN5,520 WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN5,521 WM_AIN4 "+" WM_AIN5, WM_AIN1 "+" WM_AIN4 "+" WM_AIN5,522 WM_AIN2 "+" WM_AIN4 "+" WM_AIN5,523 WM_AIN1 "+" WM_AIN2 "+" WM_AIN4 "+" WM_AIN5,524 WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,525 WM_AIN1 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,526 WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,527 WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5528 };529 530 return snd_ctl_enum_info(uinfo, 1, 32, texts);531}532 533static int wm_adc_mux_enum_get(struct snd_kcontrol *kcontrol,534 struct snd_ctl_elem_value *ucontrol)535{536 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);537 538 mutex_lock(&ice->gpio_mutex);539 ucontrol->value.enumerated.item[0] = wm_get(ice, WM_ADC_MUX) & 0x1f;540 mutex_unlock(&ice->gpio_mutex);541 return 0;542}543 544static int wm_adc_mux_enum_put(struct snd_kcontrol *kcontrol,545 struct snd_ctl_elem_value *ucontrol)546{547 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);548 unsigned short oval, nval;549 int change = 0;550 551 mutex_lock(&ice->gpio_mutex);552 oval = wm_get(ice, WM_ADC_MUX);553 nval = (oval & 0xe0) | ucontrol->value.enumerated.item[0];554 if (nval != oval) {555 wm_put(ice, WM_ADC_MUX, nval);556 change = 1;557 }558 mutex_unlock(&ice->gpio_mutex);559 return change;560}561 562/* KONSTI */563 564/*565 * ADC gain mixer control (-64dB to 0dB)566 */567 568#define ADC_0dB 0xcf569#define ADC_RES 128570#define ADC_MIN (ADC_0dB - ADC_RES)571 572static int wm_adc_vol_info(struct snd_kcontrol *kcontrol,573 struct snd_ctl_elem_info *uinfo)574{575 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;576 uinfo->count = 2;577 uinfo->value.integer.min = 0; /* mute (-64dB) */578 uinfo->value.integer.max = ADC_RES; /* 0dB, 0.5dB step */579 return 0;580}581 582static int wm_adc_vol_get(struct snd_kcontrol *kcontrol,583 struct snd_ctl_elem_value *ucontrol)584{585 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);586 unsigned short val;587 int i;588 589 mutex_lock(&ice->gpio_mutex);590 for (i = 0; i < 2; i++) {591 val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff;592 val = val > ADC_MIN ? (val - ADC_MIN) : 0;593 ucontrol->value.integer.value[i] = val;594 }595 mutex_unlock(&ice->gpio_mutex);596 return 0;597}598 599static int wm_adc_vol_put(struct snd_kcontrol *kcontrol,600 struct snd_ctl_elem_value *ucontrol)601{602 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);603 unsigned short ovol, nvol;604 int i, idx, change = 0;605 606 mutex_lock(&ice->gpio_mutex);607 for (i = 0; i < 2; i++) {608 nvol = ucontrol->value.integer.value[i];609 nvol = nvol ? (nvol + ADC_MIN) : 0;610 idx = WM_ADC_ATTEN_L + i;611 ovol = wm_get(ice, idx) & 0xff;612 if (ovol != nvol) {613 wm_put(ice, idx, nvol);614 change = 1;615 }616 }617 mutex_unlock(&ice->gpio_mutex);618 return change;619}620 621/*622 * ADC input mux mixer control623 */624#define wm_adc_mux_info snd_ctl_boolean_mono_info625 626static int wm_adc_mux_get(struct snd_kcontrol *kcontrol,627 struct snd_ctl_elem_value *ucontrol)628{629 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);630 int bit = kcontrol->private_value;631 632 mutex_lock(&ice->gpio_mutex);633 ucontrol->value.integer.value[0] =634 (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0;635 mutex_unlock(&ice->gpio_mutex);636 return 0;637}638 639static int wm_adc_mux_put(struct snd_kcontrol *kcontrol,640 struct snd_ctl_elem_value *ucontrol)641{642 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);643 int bit = kcontrol->private_value;644 unsigned short oval, nval;645 int change;646 647 mutex_lock(&ice->gpio_mutex);648 nval = oval = wm_get(ice, WM_ADC_MUX);649 if (ucontrol->value.integer.value[0])650 nval |= (1 << bit);651 else652 nval &= ~(1 << bit);653 change = nval != oval;654 if (change) {655 wm_put(ice, WM_ADC_MUX, nval);656 }657 mutex_unlock(&ice->gpio_mutex);658 return 0;659}660 661/*662 * Analog bypass (In -> Out)663 */664#define wm_bypass_info snd_ctl_boolean_mono_info665 666static int wm_bypass_get(struct snd_kcontrol *kcontrol,667 struct snd_ctl_elem_value *ucontrol)668{669 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);670 671 mutex_lock(&ice->gpio_mutex);672 ucontrol->value.integer.value[0] =673 (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0;674 mutex_unlock(&ice->gpio_mutex);675 return 0;676}677 678static int wm_bypass_put(struct snd_kcontrol *kcontrol,679 struct snd_ctl_elem_value *ucontrol)680{681 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);682 unsigned short val, oval;683 int change = 0;684 685 mutex_lock(&ice->gpio_mutex);686 val = oval = wm_get(ice, WM_OUT_MUX);687 if (ucontrol->value.integer.value[0])688 val |= 0x04;689 else690 val &= ~0x04;691 if (val != oval) {692 wm_put(ice, WM_OUT_MUX, val);693 change = 1;694 }695 mutex_unlock(&ice->gpio_mutex);696 return change;697}698 699/*700 * Left/Right swap701 */702#define wm_chswap_info snd_ctl_boolean_mono_info703 704static int wm_chswap_get(struct snd_kcontrol *kcontrol,705 struct snd_ctl_elem_value *ucontrol)706{707 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);708 709 mutex_lock(&ice->gpio_mutex);710 ucontrol->value.integer.value[0] =711 (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90;712 mutex_unlock(&ice->gpio_mutex);713 return 0;714}715 716static int wm_chswap_put(struct snd_kcontrol *kcontrol,717 struct snd_ctl_elem_value *ucontrol)718{719 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);720 unsigned short val, oval;721 int change = 0;722 723 mutex_lock(&ice->gpio_mutex);724 oval = wm_get(ice, WM_DAC_CTRL1);725 val = oval & 0x0f;726 if (ucontrol->value.integer.value[0])727 val |= 0x60;728 else729 val |= 0x90;730 if (val != oval) {731 wm_put(ice, WM_DAC_CTRL1, val);732 wm_put_nocache(ice, WM_DAC_CTRL1, val);733 change = 1;734 }735 mutex_unlock(&ice->gpio_mutex);736 return change;737}738 739 740/*741 * mixers742 */743 744static const struct snd_kcontrol_new prodigy_hifi_controls[] = {745 {746 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,747 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |748 SNDRV_CTL_ELEM_ACCESS_TLV_READ),749 .name = "Master Playback Volume",750 .info = wm_master_vol_info,751 .get = wm_master_vol_get,752 .put = wm_master_vol_put,753 .tlv = { .p = db_scale_wm_dac }754 },755 {756 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,757 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |758 SNDRV_CTL_ELEM_ACCESS_TLV_READ),759 .name = "Front Playback Volume",760 .info = wm_dac_vol_info,761 .get = wm_dac_vol_get,762 .put = wm_dac_vol_put,763 .tlv = { .p = db_scale_wm_dac },764 },765 {766 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,767 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |768 SNDRV_CTL_ELEM_ACCESS_TLV_READ),769 .name = "Rear Playback Volume",770 .info = wm8766_vol_info,771 .get = wm8766_vol_get,772 .put = wm8766_vol_put,773 .private_value = (2 << 8) | 0,774 .tlv = { .p = db_scale_wm_dac },775 },776 {777 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,778 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |779 SNDRV_CTL_ELEM_ACCESS_TLV_READ),780 .name = "Center Playback Volume",781 .info = wm8766_vol_info,782 .get = wm8766_vol_get,783 .put = wm8766_vol_put,784 .private_value = (1 << 8) | 4,785 .tlv = { .p = db_scale_wm_dac }786 },787 {788 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,789 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |790 SNDRV_CTL_ELEM_ACCESS_TLV_READ),791 .name = "LFE Playback Volume",792 .info = wm8766_vol_info,793 .get = wm8766_vol_get,794 .put = wm8766_vol_put,795 .private_value = (1 << 8) | 5,796 .tlv = { .p = db_scale_wm_dac }797 },798 {799 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,800 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |801 SNDRV_CTL_ELEM_ACCESS_TLV_READ),802 .name = "Side Playback Volume",803 .info = wm8766_vol_info,804 .get = wm8766_vol_get,805 .put = wm8766_vol_put,806 .private_value = (2 << 8) | 6,807 .tlv = { .p = db_scale_wm_dac },808 },809 {810 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,811 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |812 SNDRV_CTL_ELEM_ACCESS_TLV_READ),813 .name = "Capture Volume",814 .info = wm_adc_vol_info,815 .get = wm_adc_vol_get,816 .put = wm_adc_vol_put,817 .tlv = { .p = db_scale_wm_dac },818 },819 {820 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,821 .name = "CD Capture Switch",822 .info = wm_adc_mux_info,823 .get = wm_adc_mux_get,824 .put = wm_adc_mux_put,825 .private_value = 0,826 },827 {828 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,829 .name = "Line Capture Switch",830 .info = wm_adc_mux_info,831 .get = wm_adc_mux_get,832 .put = wm_adc_mux_put,833 .private_value = 1,834 },835 {836 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,837 .name = "Analog Bypass Switch",838 .info = wm_bypass_info,839 .get = wm_bypass_get,840 .put = wm_bypass_put,841 },842 {843 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,844 .name = "Swap Output Channels",845 .info = wm_chswap_info,846 .get = wm_chswap_get,847 .put = wm_chswap_put,848 },849 {850 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,851 .name = "Analog Capture Source",852 .info = wm_adc_mux_enum_info,853 .get = wm_adc_mux_enum_get,854 .put = wm_adc_mux_enum_put,855 },856};857 858/*859 * WM codec registers860 */861static void wm_proc_regs_write(struct snd_info_entry *entry,862 struct snd_info_buffer *buffer)863{864 struct snd_ice1712 *ice = entry->private_data;865 char line[64];866 unsigned int reg, val;867 mutex_lock(&ice->gpio_mutex);868 while (!snd_info_get_line(buffer, line, sizeof(line))) {869 if (sscanf(line, "%x %x", ®, &val) != 2)870 continue;871 if (reg <= 0x17 && val <= 0xffff)872 wm_put(ice, reg, val);873 }874 mutex_unlock(&ice->gpio_mutex);875}876 877static void wm_proc_regs_read(struct snd_info_entry *entry,878 struct snd_info_buffer *buffer)879{880 struct snd_ice1712 *ice = entry->private_data;881 int reg, val;882 883 mutex_lock(&ice->gpio_mutex);884 for (reg = 0; reg <= 0x17; reg++) {885 val = wm_get(ice, reg);886 snd_iprintf(buffer, "%02x = %04x\n", reg, val);887 }888 mutex_unlock(&ice->gpio_mutex);889}890 891static void wm_proc_init(struct snd_ice1712 *ice)892{893 snd_card_rw_proc_new(ice->card, "wm_codec", ice, wm_proc_regs_read,894 wm_proc_regs_write);895}896 897static int prodigy_hifi_add_controls(struct snd_ice1712 *ice)898{899 unsigned int i;900 int err;901 902 for (i = 0; i < ARRAY_SIZE(prodigy_hifi_controls); i++) {903 err = snd_ctl_add(ice->card,904 snd_ctl_new1(&prodigy_hifi_controls[i], ice));905 if (err < 0)906 return err;907 }908 909 wm_proc_init(ice);910 911 return 0;912}913 914static int prodigy_hd2_add_controls(struct snd_ice1712 *ice)915{916 unsigned int i;917 int err;918 919 for (i = 0; i < ARRAY_SIZE(prodigy_hd2_controls); i++) {920 err = snd_ctl_add(ice->card,921 snd_ctl_new1(&prodigy_hd2_controls[i], ice));922 if (err < 0)923 return err;924 }925 926 wm_proc_init(ice);927 928 return 0;929}930 931static void wm8766_init(struct snd_ice1712 *ice)932{933 static const unsigned short wm8766_inits[] = {934 WM8766_RESET, 0x0000,935 WM8766_DAC_CTRL, 0x0120,936 WM8766_INT_CTRL, 0x0022, /* I2S Normal Mode, 24 bit */937 WM8766_DAC_CTRL2, 0x0001,938 WM8766_DAC_CTRL3, 0x0080,939 WM8766_LDA1, 0x0100,940 WM8766_LDA2, 0x0100,941 WM8766_LDA3, 0x0100,942 WM8766_RDA1, 0x0100,943 WM8766_RDA2, 0x0100,944 WM8766_RDA3, 0x0100,945 WM8766_MUTE1, 0x0000,946 WM8766_MUTE2, 0x0000,947 };948 unsigned int i;949 950 for (i = 0; i < ARRAY_SIZE(wm8766_inits); i += 2)951 wm8766_spi_write(ice, wm8766_inits[i], wm8766_inits[i + 1]);952}953 954static void wm8776_init(struct snd_ice1712 *ice)955{956 static const unsigned short wm8776_inits[] = {957 /* These come first to reduce init pop noise */958 WM_ADC_MUX, 0x0003, /* ADC mute */959 /* 0x00c0 replaced by 0x0003 */960 961 WM_DAC_MUTE, 0x0001, /* DAC softmute */962 WM_DAC_CTRL1, 0x0000, /* DAC mute */963 964 WM_POWERDOWN, 0x0008, /* All power-up except HP */965 WM_RESET, 0x0000, /* reset */966 };967 unsigned int i;968 969 for (i = 0; i < ARRAY_SIZE(wm8776_inits); i += 2)970 wm_put(ice, wm8776_inits[i], wm8776_inits[i + 1]);971}972 973#ifdef CONFIG_PM_SLEEP974static int prodigy_hifi_resume(struct snd_ice1712 *ice)975{976 static const unsigned short wm8776_reinit_registers[] = {977 WM_MASTER_CTRL,978 WM_DAC_INT,979 WM_ADC_INT,980 WM_OUT_MUX,981 WM_HP_ATTEN_L,982 WM_HP_ATTEN_R,983 WM_PHASE_SWAP,984 WM_DAC_CTRL2,985 WM_ADC_ATTEN_L,986 WM_ADC_ATTEN_R,987 WM_ALC_CTRL1,988 WM_ALC_CTRL2,989 WM_ALC_CTRL3,990 WM_NOISE_GATE,991 WM_ADC_MUX,992 /* no DAC attenuation here */993 };994 struct prodigy_hifi_spec *spec = ice->spec;995 int i, ch;996 997 mutex_lock(&ice->gpio_mutex);998 999 /* reinitialize WM8776 and re-apply old register values */1000 wm8776_init(ice);1001 schedule_timeout_uninterruptible(1);1002 for (i = 0; i < ARRAY_SIZE(wm8776_reinit_registers); i++)1003 wm_put(ice, wm8776_reinit_registers[i],1004 wm_get(ice, wm8776_reinit_registers[i]));1005 1006 /* reinitialize WM8766 and re-apply volumes for all DACs */1007 wm8766_init(ice);1008 for (ch = 0; ch < 2; ch++) {1009 wm_set_vol(ice, WM_DAC_ATTEN_L + ch,1010 spec->vol[2 + ch], spec->master[ch]);1011 1012 wm8766_set_vol(ice, WM8766_LDA1 + ch,1013 spec->vol[0 + ch], spec->master[ch]);1014 1015 wm8766_set_vol(ice, WM8766_LDA2 + ch,1016 spec->vol[4 + ch], spec->master[ch]);1017 1018 wm8766_set_vol(ice, WM8766_LDA3 + ch,1019 spec->vol[6 + ch], spec->master[ch]);1020 }1021 1022 /* unmute WM8776 DAC */1023 wm_put(ice, WM_DAC_MUTE, 0x00);1024 wm_put(ice, WM_DAC_CTRL1, 0x90);1025 1026 mutex_unlock(&ice->gpio_mutex);1027 return 0;1028}1029#endif1030 1031/*1032 * initialize the chip1033 */1034static int prodigy_hifi_init(struct snd_ice1712 *ice)1035{1036 static const unsigned short wm8776_defaults[] = {1037 WM_MASTER_CTRL, 0x0022, /* 256fs, slave mode */1038 WM_DAC_INT, 0x0022, /* I2S, normal polarity, 24bit */1039 WM_ADC_INT, 0x0022, /* I2S, normal polarity, 24bit */1040 WM_DAC_CTRL1, 0x0090, /* DAC L/R */1041 WM_OUT_MUX, 0x0001, /* OUT DAC */1042 WM_HP_ATTEN_L, 0x0179, /* HP 0dB */1043 WM_HP_ATTEN_R, 0x0179, /* HP 0dB */1044 WM_DAC_ATTEN_L, 0x0000, /* DAC 0dB */1045 WM_DAC_ATTEN_L, 0x0100, /* DAC 0dB */1046 WM_DAC_ATTEN_R, 0x0000, /* DAC 0dB */1047 WM_DAC_ATTEN_R, 0x0100, /* DAC 0dB */1048 WM_PHASE_SWAP, 0x0000, /* phase normal */1049#if 01050 WM_DAC_MASTER, 0x0100, /* DAC master muted */1051#endif1052 WM_DAC_CTRL2, 0x0000, /* no deemphasis, no ZFLG */1053 WM_ADC_ATTEN_L, 0x0000, /* ADC muted */1054 WM_ADC_ATTEN_R, 0x0000, /* ADC muted */1055#if 11056 WM_ALC_CTRL1, 0x007b, /* */1057 WM_ALC_CTRL2, 0x0000, /* */1058 WM_ALC_CTRL3, 0x0000, /* */1059 WM_NOISE_GATE, 0x0000, /* */1060#endif1061 WM_DAC_MUTE, 0x0000, /* DAC unmute */1062 WM_ADC_MUX, 0x0003, /* ADC unmute, both CD/Line On */1063 };1064 struct prodigy_hifi_spec *spec;1065 unsigned int i;1066 1067 ice->vt1720 = 0;1068 ice->vt1724 = 1;1069 1070 ice->num_total_dacs = 8;1071 ice->num_total_adcs = 1;1072 1073 /* HACK - use this as the SPDIF source.1074 * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten1075 */1076 ice->gpio.saved[0] = 0;1077 /* to remember the register values */1078 1079 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);1080 if (! ice->akm)1081 return -ENOMEM;1082 ice->akm_codecs = 1;1083 1084 spec = kzalloc(sizeof(*spec), GFP_KERNEL);1085 if (!spec)1086 return -ENOMEM;1087 ice->spec = spec;1088 1089 /* initialize WM8776 codec */1090 wm8776_init(ice);1091 schedule_timeout_uninterruptible(1);1092 for (i = 0; i < ARRAY_SIZE(wm8776_defaults); i += 2)1093 wm_put(ice, wm8776_defaults[i], wm8776_defaults[i + 1]);1094 1095 wm8766_init(ice);1096 1097#ifdef CONFIG_PM_SLEEP1098 ice->pm_resume = &prodigy_hifi_resume;1099 ice->pm_suspend_enabled = 1;1100#endif1101 1102 return 0;1103}1104 1105 1106/*1107 * initialize the chip1108 */1109static void ak4396_init(struct snd_ice1712 *ice)1110{1111 static const unsigned short ak4396_inits[] = {1112 AK4396_CTRL1, 0x87, /* I2S Normal Mode, 24 bit */1113 AK4396_CTRL2, 0x02,1114 AK4396_CTRL3, 0x00, 1115 AK4396_LCH_ATT, 0x00,1116 AK4396_RCH_ATT, 0x00,1117 };1118 1119 unsigned int i;1120 1121 /* initialize ak4396 codec */1122 /* reset codec */1123 ak4396_write(ice, AK4396_CTRL1, 0x86);1124 msleep(100);1125 ak4396_write(ice, AK4396_CTRL1, 0x87);1126 1127 for (i = 0; i < ARRAY_SIZE(ak4396_inits); i += 2)1128 ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]);1129}1130 1131#ifdef CONFIG_PM_SLEEP1132static int prodigy_hd2_resume(struct snd_ice1712 *ice)1133{1134 /* initialize ak4396 codec and restore previous mixer volumes */1135 struct prodigy_hifi_spec *spec = ice->spec;1136 int i;1137 mutex_lock(&ice->gpio_mutex);1138 ak4396_init(ice);1139 for (i = 0; i < 2; i++)1140 ak4396_write(ice, AK4396_LCH_ATT + i, spec->vol[i] & 0xff);1141 mutex_unlock(&ice->gpio_mutex);1142 return 0;1143}1144#endif1145 1146static int prodigy_hd2_init(struct snd_ice1712 *ice)1147{1148 struct prodigy_hifi_spec *spec;1149 1150 ice->vt1720 = 0;1151 ice->vt1724 = 1;1152 1153 ice->num_total_dacs = 1;1154 ice->num_total_adcs = 1;1155 1156 /* HACK - use this as the SPDIF source.1157 * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten1158 */1159 ice->gpio.saved[0] = 0;1160 /* to remember the register values */1161 1162 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);1163 if (! ice->akm)1164 return -ENOMEM;1165 ice->akm_codecs = 1;1166 1167 spec = kzalloc(sizeof(*spec), GFP_KERNEL);1168 if (!spec)1169 return -ENOMEM;1170 ice->spec = spec;1171 1172#ifdef CONFIG_PM_SLEEP1173 ice->pm_resume = &prodigy_hd2_resume;1174 ice->pm_suspend_enabled = 1;1175#endif1176 1177 ak4396_init(ice);1178 1179 return 0;1180}1181 1182 1183static const unsigned char prodigy71hifi_eeprom[] = {1184 0x4b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */1185 0x80, /* ACLINK: I2S */1186 0xfc, /* I2S: vol, 96k, 24bit, 192k */1187 0xc3, /* SPDIF: out-en, out-int, spdif-in */1188 0xff, /* GPIO_DIR */1189 0xff, /* GPIO_DIR1 */1190 0x5f, /* GPIO_DIR2 */1191 0x00, /* GPIO_MASK */1192 0x00, /* GPIO_MASK1 */1193 0x00, /* GPIO_MASK2 */1194 0x00, /* GPIO_STATE */1195 0x00, /* GPIO_STATE1 */1196 0x00, /* GPIO_STATE2 */1197};1198 1199static const unsigned char prodigyhd2_eeprom[] = {1200 0x4b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */1201 0x80, /* ACLINK: I2S */1202 0xfc, /* I2S: vol, 96k, 24bit, 192k */1203 0xc3, /* SPDIF: out-en, out-int, spdif-in */1204 0xff, /* GPIO_DIR */1205 0xff, /* GPIO_DIR1 */1206 0x5f, /* GPIO_DIR2 */1207 0x00, /* GPIO_MASK */1208 0x00, /* GPIO_MASK1 */1209 0x00, /* GPIO_MASK2 */1210 0x00, /* GPIO_STATE */1211 0x00, /* GPIO_STATE1 */1212 0x00, /* GPIO_STATE2 */1213};1214 1215static const unsigned char fortissimo4_eeprom[] = {1216 0x43, /* SYSCONF: clock 512, ADC, 4DACs */ 1217 0x80, /* ACLINK: I2S */1218 0xfc, /* I2S: vol, 96k, 24bit, 192k */1219 0xc1, /* SPDIF: out-en, out-int */1220 0xff, /* GPIO_DIR */1221 0xff, /* GPIO_DIR1 */1222 0x5f, /* GPIO_DIR2 */1223 0x00, /* GPIO_MASK */1224 0x00, /* GPIO_MASK1 */1225 0x00, /* GPIO_MASK2 */1226 0x00, /* GPIO_STATE */1227 0x00, /* GPIO_STATE1 */1228 0x00, /* GPIO_STATE2 */1229};1230 1231/* entry point */1232struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] = {1233 {1234 .subvendor = VT1724_SUBDEVICE_PRODIGY_HIFI,1235 .name = "Audiotrak Prodigy 7.1 HiFi",1236 .model = "prodigy71hifi",1237 .chip_init = prodigy_hifi_init,1238 .build_controls = prodigy_hifi_add_controls,1239 .eeprom_size = sizeof(prodigy71hifi_eeprom),1240 .eeprom_data = prodigy71hifi_eeprom,1241 .driver = "Prodigy71HIFI",1242 },1243 {1244 .subvendor = VT1724_SUBDEVICE_PRODIGY_HD2,1245 .name = "Audiotrak Prodigy HD2",1246 .model = "prodigyhd2",1247 .chip_init = prodigy_hd2_init,1248 .build_controls = prodigy_hd2_add_controls,1249 .eeprom_size = sizeof(prodigyhd2_eeprom),1250 .eeprom_data = prodigyhd2_eeprom,1251 .driver = "Prodigy71HD2",1252 },1253 {1254 .subvendor = VT1724_SUBDEVICE_FORTISSIMO4,1255 .name = "Hercules Fortissimo IV",1256 .model = "fortissimo4",1257 .chip_init = prodigy_hifi_init,1258 .build_controls = prodigy_hifi_add_controls,1259 .eeprom_size = sizeof(fortissimo4_eeprom),1260 .eeprom_data = fortissimo4_eeprom,1261 .driver = "Fortissimo4",1262 },1263 { } /* terminator */1264};1265 1266