810 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ALSA driver for ICEnsemble VT1724 (Envy24HT)4 *5 * Lowlevel functions for Pontis MS3006 *7 * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>8 */9 10#include <linux/delay.h>11#include <linux/interrupt.h>12#include <linux/init.h>13#include <linux/slab.h>14#include <linux/mutex.h>15 16#include <sound/core.h>17#include <sound/info.h>18#include <sound/tlv.h>19 20#include "ice1712.h"21#include "envy24ht.h"22#include "pontis.h"23 24/* I2C addresses */25#define WM_DEV 0x3426#define CS_DEV 0x2027 28/* WM8776 registers */29#define WM_HP_ATTEN_L 0x00 /* headphone left attenuation */30#define WM_HP_ATTEN_R 0x01 /* headphone left attenuation */31#define WM_HP_MASTER 0x02 /* headphone master (both channels) */32 /* override LLR */33#define WM_DAC_ATTEN_L 0x03 /* digital left attenuation */34#define WM_DAC_ATTEN_R 0x0435#define WM_DAC_MASTER 0x0536#define WM_PHASE_SWAP 0x06 /* DAC phase swap */37#define WM_DAC_CTRL1 0x0738#define WM_DAC_MUTE 0x0839#define WM_DAC_CTRL2 0x0940#define WM_DAC_INT 0x0a41#define WM_ADC_INT 0x0b42#define WM_MASTER_CTRL 0x0c43#define WM_POWERDOWN 0x0d44#define WM_ADC_ATTEN_L 0x0e45#define WM_ADC_ATTEN_R 0x0f46#define WM_ALC_CTRL1 0x1047#define WM_ALC_CTRL2 0x1148#define WM_ALC_CTRL3 0x1249#define WM_NOISE_GATE 0x1350#define WM_LIMITER 0x1451#define WM_ADC_MUX 0x1552#define WM_OUT_MUX 0x1653#define WM_RESET 0x1754 55/*56 * GPIO57 */58#define PONTIS_CS_CS (1<<4) /* CS */59#define PONTIS_CS_CLK (1<<5) /* CLK */60#define PONTIS_CS_RDATA (1<<6) /* CS8416 -> VT1720 */61#define PONTIS_CS_WDATA (1<<7) /* VT1720 -> CS8416 */62 63 64/*65 * get the current register value of WM codec66 */67static unsigned short wm_get(struct snd_ice1712 *ice, int reg)68{69 reg <<= 1;70 return ((unsigned short)ice->akm[0].images[reg] << 8) |71 ice->akm[0].images[reg + 1];72}73 74/*75 * set the register value of WM codec and remember it76 */77static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)78{79 unsigned short cval;80 cval = (reg << 9) | val;81 snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);82}83 84static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)85{86 wm_put_nocache(ice, reg, val);87 reg <<= 1;88 ice->akm[0].images[reg] = val >> 8;89 ice->akm[0].images[reg + 1] = val;90}91 92/*93 * DAC volume attenuation mixer control (-64dB to 0dB)94 */95 96#define DAC_0dB 0xff97#define DAC_RES 12898#define DAC_MIN (DAC_0dB - DAC_RES)99 100static int wm_dac_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)101{102 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;103 uinfo->count = 2;104 uinfo->value.integer.min = 0; /* mute */105 uinfo->value.integer.max = DAC_RES; /* 0dB, 0.5dB step */106 return 0;107}108 109static int wm_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)110{111 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);112 unsigned short val;113 int i;114 115 mutex_lock(&ice->gpio_mutex);116 for (i = 0; i < 2; i++) {117 val = wm_get(ice, WM_DAC_ATTEN_L + i) & 0xff;118 val = val > DAC_MIN ? (val - DAC_MIN) : 0;119 ucontrol->value.integer.value[i] = val;120 }121 mutex_unlock(&ice->gpio_mutex);122 return 0;123}124 125static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)126{127 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);128 unsigned short oval, nval;129 int i, idx, change = 0;130 131 mutex_lock(&ice->gpio_mutex);132 for (i = 0; i < 2; i++) {133 nval = ucontrol->value.integer.value[i];134 nval = (nval ? (nval + DAC_MIN) : 0) & 0xff;135 idx = WM_DAC_ATTEN_L + i;136 oval = wm_get(ice, idx) & 0xff;137 if (oval != nval) {138 wm_put(ice, idx, nval);139 wm_put_nocache(ice, idx, nval | 0x100);140 change = 1;141 }142 }143 mutex_unlock(&ice->gpio_mutex);144 return change;145}146 147/*148 * ADC gain mixer control (-64dB to 0dB)149 */150 151#define ADC_0dB 0xcf152#define ADC_RES 128153#define ADC_MIN (ADC_0dB - ADC_RES)154 155static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)156{157 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;158 uinfo->count = 2;159 uinfo->value.integer.min = 0; /* mute (-64dB) */160 uinfo->value.integer.max = ADC_RES; /* 0dB, 0.5dB step */161 return 0;162}163 164static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)165{166 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);167 unsigned short val;168 int i;169 170 mutex_lock(&ice->gpio_mutex);171 for (i = 0; i < 2; i++) {172 val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff;173 val = val > ADC_MIN ? (val - ADC_MIN) : 0;174 ucontrol->value.integer.value[i] = val;175 }176 mutex_unlock(&ice->gpio_mutex);177 return 0;178}179 180static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)181{182 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);183 unsigned short ovol, nvol;184 int i, idx, change = 0;185 186 mutex_lock(&ice->gpio_mutex);187 for (i = 0; i < 2; i++) {188 nvol = ucontrol->value.integer.value[i];189 nvol = nvol ? (nvol + ADC_MIN) : 0;190 idx = WM_ADC_ATTEN_L + i;191 ovol = wm_get(ice, idx) & 0xff;192 if (ovol != nvol) {193 wm_put(ice, idx, nvol);194 change = 1;195 }196 }197 mutex_unlock(&ice->gpio_mutex);198 return change;199}200 201/*202 * ADC input mux mixer control203 */204#define wm_adc_mux_info snd_ctl_boolean_mono_info205 206static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)207{208 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);209 int bit = kcontrol->private_value;210 211 mutex_lock(&ice->gpio_mutex);212 ucontrol->value.integer.value[0] = (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0;213 mutex_unlock(&ice->gpio_mutex);214 return 0;215}216 217static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)218{219 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);220 int bit = kcontrol->private_value;221 unsigned short oval, nval;222 int change;223 224 mutex_lock(&ice->gpio_mutex);225 nval = oval = wm_get(ice, WM_ADC_MUX);226 if (ucontrol->value.integer.value[0])227 nval |= (1 << bit);228 else229 nval &= ~(1 << bit);230 change = nval != oval;231 if (change) {232 wm_put(ice, WM_ADC_MUX, nval);233 }234 mutex_unlock(&ice->gpio_mutex);235 return change;236}237 238/*239 * Analog bypass (In -> Out)240 */241#define wm_bypass_info snd_ctl_boolean_mono_info242 243static int wm_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)244{245 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);246 247 mutex_lock(&ice->gpio_mutex);248 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0;249 mutex_unlock(&ice->gpio_mutex);250 return 0;251}252 253static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)254{255 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);256 unsigned short val, oval;257 int change = 0;258 259 mutex_lock(&ice->gpio_mutex);260 val = oval = wm_get(ice, WM_OUT_MUX);261 if (ucontrol->value.integer.value[0])262 val |= 0x04;263 else264 val &= ~0x04;265 if (val != oval) {266 wm_put(ice, WM_OUT_MUX, val);267 change = 1;268 }269 mutex_unlock(&ice->gpio_mutex);270 return change;271}272 273/*274 * Left/Right swap275 */276#define wm_chswap_info snd_ctl_boolean_mono_info277 278static int wm_chswap_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)279{280 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);281 282 mutex_lock(&ice->gpio_mutex);283 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90;284 mutex_unlock(&ice->gpio_mutex);285 return 0;286}287 288static int wm_chswap_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)289{290 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);291 unsigned short val, oval;292 int change = 0;293 294 mutex_lock(&ice->gpio_mutex);295 oval = wm_get(ice, WM_DAC_CTRL1);296 val = oval & 0x0f;297 if (ucontrol->value.integer.value[0])298 val |= 0x60;299 else300 val |= 0x90;301 if (val != oval) {302 wm_put(ice, WM_DAC_CTRL1, val);303 wm_put_nocache(ice, WM_DAC_CTRL1, val);304 change = 1;305 }306 mutex_unlock(&ice->gpio_mutex);307 return change;308}309 310/*311 * write data in the SPI mode312 */313static void set_gpio_bit(struct snd_ice1712 *ice, unsigned int bit, int val)314{315 unsigned int tmp = snd_ice1712_gpio_read(ice);316 if (val)317 tmp |= bit;318 else319 tmp &= ~bit;320 snd_ice1712_gpio_write(ice, tmp);321}322 323static void spi_send_byte(struct snd_ice1712 *ice, unsigned char data)324{325 int i;326 for (i = 0; i < 8; i++) {327 set_gpio_bit(ice, PONTIS_CS_CLK, 0);328 udelay(1);329 set_gpio_bit(ice, PONTIS_CS_WDATA, data & 0x80);330 udelay(1);331 set_gpio_bit(ice, PONTIS_CS_CLK, 1);332 udelay(1);333 data <<= 1;334 }335}336 337static unsigned int spi_read_byte(struct snd_ice1712 *ice)338{339 int i;340 unsigned int val = 0;341 342 for (i = 0; i < 8; i++) {343 val <<= 1;344 set_gpio_bit(ice, PONTIS_CS_CLK, 0);345 udelay(1);346 if (snd_ice1712_gpio_read(ice) & PONTIS_CS_RDATA)347 val |= 1;348 udelay(1);349 set_gpio_bit(ice, PONTIS_CS_CLK, 1);350 udelay(1);351 }352 return val;353}354 355 356static void spi_write(struct snd_ice1712 *ice, unsigned int dev, unsigned int reg, unsigned int data)357{358 snd_ice1712_gpio_set_dir(ice, PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK);359 snd_ice1712_gpio_set_mask(ice, ~(PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK));360 set_gpio_bit(ice, PONTIS_CS_CS, 0);361 spi_send_byte(ice, dev & ~1); /* WRITE */362 spi_send_byte(ice, reg); /* MAP */363 spi_send_byte(ice, data); /* DATA */364 /* trigger */365 set_gpio_bit(ice, PONTIS_CS_CS, 1);366 udelay(1);367 /* restore */368 snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);369 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);370}371 372static unsigned int spi_read(struct snd_ice1712 *ice, unsigned int dev, unsigned int reg)373{374 unsigned int val;375 snd_ice1712_gpio_set_dir(ice, PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK);376 snd_ice1712_gpio_set_mask(ice, ~(PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK));377 set_gpio_bit(ice, PONTIS_CS_CS, 0);378 spi_send_byte(ice, dev & ~1); /* WRITE */379 spi_send_byte(ice, reg); /* MAP */380 /* trigger */381 set_gpio_bit(ice, PONTIS_CS_CS, 1);382 udelay(1);383 set_gpio_bit(ice, PONTIS_CS_CS, 0);384 spi_send_byte(ice, dev | 1); /* READ */385 val = spi_read_byte(ice);386 /* trigger */387 set_gpio_bit(ice, PONTIS_CS_CS, 1);388 udelay(1);389 /* restore */390 snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);391 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);392 return val;393}394 395 396/*397 * SPDIF input source398 */399static int cs_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)400{401 static const char * const texts[] = {402 "Coax", /* RXP0 */403 "Optical", /* RXP1 */404 "CD", /* RXP2 */405 };406 return snd_ctl_enum_info(uinfo, 1, 3, texts);407}408 409static int cs_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)410{411 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);412 413 mutex_lock(&ice->gpio_mutex);414 ucontrol->value.enumerated.item[0] = ice->gpio.saved[0];415 mutex_unlock(&ice->gpio_mutex);416 return 0;417}418 419static int cs_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)420{421 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);422 unsigned char val;423 int change = 0;424 425 mutex_lock(&ice->gpio_mutex);426 if (ucontrol->value.enumerated.item[0] != ice->gpio.saved[0]) {427 ice->gpio.saved[0] = ucontrol->value.enumerated.item[0] & 3;428 val = 0x80 | (ice->gpio.saved[0] << 3);429 spi_write(ice, CS_DEV, 0x04, val);430 change = 1;431 }432 mutex_unlock(&ice->gpio_mutex);433 return change;434}435 436 437/*438 * GPIO controls439 */440static int pontis_gpio_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)441{442 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;443 uinfo->count = 1;444 uinfo->value.integer.min = 0;445 uinfo->value.integer.max = 0xffff; /* 16bit */446 return 0;447}448 449static int pontis_gpio_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)450{451 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);452 mutex_lock(&ice->gpio_mutex);453 /* 4-7 reserved */454 ucontrol->value.integer.value[0] = (~ice->gpio.write_mask & 0xffff) | 0x00f0;455 mutex_unlock(&ice->gpio_mutex);456 return 0;457}458 459static int pontis_gpio_mask_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)460{461 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);462 unsigned int val;463 int changed;464 mutex_lock(&ice->gpio_mutex);465 /* 4-7 reserved */466 val = (~ucontrol->value.integer.value[0] & 0xffff) | 0x00f0;467 changed = val != ice->gpio.write_mask;468 ice->gpio.write_mask = val;469 mutex_unlock(&ice->gpio_mutex);470 return changed;471}472 473static int pontis_gpio_dir_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)474{475 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);476 mutex_lock(&ice->gpio_mutex);477 /* 4-7 reserved */478 ucontrol->value.integer.value[0] = ice->gpio.direction & 0xff0f;479 mutex_unlock(&ice->gpio_mutex);480 return 0;481}482 483static int pontis_gpio_dir_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)484{485 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);486 unsigned int val;487 int changed;488 mutex_lock(&ice->gpio_mutex);489 /* 4-7 reserved */490 val = ucontrol->value.integer.value[0] & 0xff0f;491 changed = (val != ice->gpio.direction);492 ice->gpio.direction = val;493 mutex_unlock(&ice->gpio_mutex);494 return changed;495}496 497static int pontis_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)498{499 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);500 mutex_lock(&ice->gpio_mutex);501 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);502 snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);503 ucontrol->value.integer.value[0] = snd_ice1712_gpio_read(ice) & 0xffff;504 mutex_unlock(&ice->gpio_mutex);505 return 0;506}507 508static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)509{510 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);511 unsigned int val, nval;512 int changed = 0;513 mutex_lock(&ice->gpio_mutex);514 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);515 snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);516 val = snd_ice1712_gpio_read(ice) & 0xffff;517 nval = ucontrol->value.integer.value[0] & 0xffff;518 if (val != nval) {519 snd_ice1712_gpio_write(ice, nval);520 changed = 1;521 }522 mutex_unlock(&ice->gpio_mutex);523 return changed;524}525 526static const DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1);527 528/*529 * mixers530 */531 532static const struct snd_kcontrol_new pontis_controls[] = {533 {534 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,535 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |536 SNDRV_CTL_ELEM_ACCESS_TLV_READ),537 .name = "PCM Playback Volume",538 .info = wm_dac_vol_info,539 .get = wm_dac_vol_get,540 .put = wm_dac_vol_put,541 .tlv = { .p = db_scale_volume },542 },543 {544 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,545 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |546 SNDRV_CTL_ELEM_ACCESS_TLV_READ),547 .name = "Capture Volume",548 .info = wm_adc_vol_info,549 .get = wm_adc_vol_get,550 .put = wm_adc_vol_put,551 .tlv = { .p = db_scale_volume },552 },553 {554 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,555 .name = "CD Capture Switch",556 .info = wm_adc_mux_info,557 .get = wm_adc_mux_get,558 .put = wm_adc_mux_put,559 .private_value = 0,560 },561 {562 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,563 .name = "Line Capture Switch",564 .info = wm_adc_mux_info,565 .get = wm_adc_mux_get,566 .put = wm_adc_mux_put,567 .private_value = 1,568 },569 {570 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,571 .name = "Analog Bypass Switch",572 .info = wm_bypass_info,573 .get = wm_bypass_get,574 .put = wm_bypass_put,575 },576 {577 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,578 .name = "Swap Output Channels",579 .info = wm_chswap_info,580 .get = wm_chswap_get,581 .put = wm_chswap_put,582 },583 {584 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,585 .name = "IEC958 Input Source",586 .info = cs_source_info,587 .get = cs_source_get,588 .put = cs_source_put,589 },590 /* FIXME: which interface? */591 {592 .iface = SNDRV_CTL_ELEM_IFACE_CARD,593 .name = "GPIO Mask",594 .info = pontis_gpio_mask_info,595 .get = pontis_gpio_mask_get,596 .put = pontis_gpio_mask_put,597 },598 {599 .iface = SNDRV_CTL_ELEM_IFACE_CARD,600 .name = "GPIO Direction",601 .info = pontis_gpio_mask_info,602 .get = pontis_gpio_dir_get,603 .put = pontis_gpio_dir_put,604 },605 {606 .iface = SNDRV_CTL_ELEM_IFACE_CARD,607 .name = "GPIO Data",608 .info = pontis_gpio_mask_info,609 .get = pontis_gpio_data_get,610 .put = pontis_gpio_data_put,611 },612};613 614 615/*616 * WM codec registers617 */618static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer)619{620 struct snd_ice1712 *ice = entry->private_data;621 char line[64];622 unsigned int reg, val;623 mutex_lock(&ice->gpio_mutex);624 while (!snd_info_get_line(buffer, line, sizeof(line))) {625 if (sscanf(line, "%x %x", ®, &val) != 2)626 continue;627 if (reg <= 0x17 && val <= 0xffff)628 wm_put(ice, reg, val);629 }630 mutex_unlock(&ice->gpio_mutex);631}632 633static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)634{635 struct snd_ice1712 *ice = entry->private_data;636 int reg, val;637 638 mutex_lock(&ice->gpio_mutex);639 for (reg = 0; reg <= 0x17; reg++) {640 val = wm_get(ice, reg);641 snd_iprintf(buffer, "%02x = %04x\n", reg, val);642 }643 mutex_unlock(&ice->gpio_mutex);644}645 646static void wm_proc_init(struct snd_ice1712 *ice)647{648 snd_card_rw_proc_new(ice->card, "wm_codec", ice, wm_proc_regs_read,649 wm_proc_regs_write);650}651 652static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)653{654 struct snd_ice1712 *ice = entry->private_data;655 int reg, val;656 657 mutex_lock(&ice->gpio_mutex);658 for (reg = 0; reg <= 0x26; reg++) {659 val = spi_read(ice, CS_DEV, reg);660 snd_iprintf(buffer, "%02x = %02x\n", reg, val);661 }662 val = spi_read(ice, CS_DEV, 0x7f);663 snd_iprintf(buffer, "%02x = %02x\n", 0x7f, val);664 mutex_unlock(&ice->gpio_mutex);665}666 667static void cs_proc_init(struct snd_ice1712 *ice)668{669 snd_card_ro_proc_new(ice->card, "cs_codec", ice, cs_proc_regs_read);670}671 672 673static int pontis_add_controls(struct snd_ice1712 *ice)674{675 unsigned int i;676 int err;677 678 for (i = 0; i < ARRAY_SIZE(pontis_controls); i++) {679 err = snd_ctl_add(ice->card, snd_ctl_new1(&pontis_controls[i], ice));680 if (err < 0)681 return err;682 }683 684 wm_proc_init(ice);685 cs_proc_init(ice);686 687 return 0;688}689 690 691/*692 * initialize the chip693 */694static int pontis_init(struct snd_ice1712 *ice)695{696 static const unsigned short wm_inits[] = {697 /* These come first to reduce init pop noise */698 WM_ADC_MUX, 0x00c0, /* ADC mute */699 WM_DAC_MUTE, 0x0001, /* DAC softmute */700 WM_DAC_CTRL1, 0x0000, /* DAC mute */701 702 WM_POWERDOWN, 0x0008, /* All power-up except HP */703 WM_RESET, 0x0000, /* reset */704 };705 static const unsigned short wm_inits2[] = {706 WM_MASTER_CTRL, 0x0022, /* 256fs, slave mode */707 WM_DAC_INT, 0x0022, /* I2S, normal polarity, 24bit */708 WM_ADC_INT, 0x0022, /* I2S, normal polarity, 24bit */709 WM_DAC_CTRL1, 0x0090, /* DAC L/R */710 WM_OUT_MUX, 0x0001, /* OUT DAC */711 WM_HP_ATTEN_L, 0x0179, /* HP 0dB */712 WM_HP_ATTEN_R, 0x0179, /* HP 0dB */713 WM_DAC_ATTEN_L, 0x0000, /* DAC 0dB */714 WM_DAC_ATTEN_L, 0x0100, /* DAC 0dB */715 WM_DAC_ATTEN_R, 0x0000, /* DAC 0dB */716 WM_DAC_ATTEN_R, 0x0100, /* DAC 0dB */717 /* WM_DAC_MASTER, 0x0100, */ /* DAC master muted */718 WM_PHASE_SWAP, 0x0000, /* phase normal */719 WM_DAC_CTRL2, 0x0000, /* no deemphasis, no ZFLG */720 WM_ADC_ATTEN_L, 0x0000, /* ADC muted */721 WM_ADC_ATTEN_R, 0x0000, /* ADC muted */722#if 0723 WM_ALC_CTRL1, 0x007b, /* */724 WM_ALC_CTRL2, 0x0000, /* */725 WM_ALC_CTRL3, 0x0000, /* */726 WM_NOISE_GATE, 0x0000, /* */727#endif728 WM_DAC_MUTE, 0x0000, /* DAC unmute */729 WM_ADC_MUX, 0x0003, /* ADC unmute, both CD/Line On */730 };731 static const unsigned char cs_inits[] = {732 0x04, 0x80, /* RUN, RXP0 */733 0x05, 0x05, /* slave, 24bit */734 0x01, 0x00,735 0x02, 0x00,736 0x03, 0x00,737 };738 unsigned int i;739 740 ice->vt1720 = 1;741 ice->num_total_dacs = 2;742 ice->num_total_adcs = 2;743 744 /* to remember the register values */745 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);746 if (! ice->akm)747 return -ENOMEM;748 ice->akm_codecs = 1;749 750 /* HACK - use this as the SPDIF source.751 * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten752 */753 ice->gpio.saved[0] = 0;754 755 /* initialize WM8776 codec */756 for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2)757 wm_put(ice, wm_inits[i], wm_inits[i+1]);758 schedule_timeout_uninterruptible(1);759 for (i = 0; i < ARRAY_SIZE(wm_inits2); i += 2)760 wm_put(ice, wm_inits2[i], wm_inits2[i+1]);761 762 /* initialize CS8416 codec */763 /* assert PRST#; MT05 bit 7 */764 outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));765 mdelay(5);766 /* deassert PRST# */767 outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));768 769 for (i = 0; i < ARRAY_SIZE(cs_inits); i += 2)770 spi_write(ice, CS_DEV, cs_inits[i], cs_inits[i+1]);771 772 return 0;773}774 775 776/*777 * Pontis boards don't provide the EEPROM data at all.778 * hence the driver needs to sets up it properly.779 */780 781static const unsigned char pontis_eeprom[] = {782 [ICE_EEP2_SYSCONF] = 0x08, /* clock 256, mpu401, spdif-in/ADC, 1DAC */783 [ICE_EEP2_ACLINK] = 0x80, /* I2S */784 [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */785 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */786 [ICE_EEP2_GPIO_DIR] = 0x07,787 [ICE_EEP2_GPIO_DIR1] = 0x00,788 [ICE_EEP2_GPIO_DIR2] = 0x00, /* ignored */789 [ICE_EEP2_GPIO_MASK] = 0x0f, /* 4-7 reserved for CS8416 */790 [ICE_EEP2_GPIO_MASK1] = 0xff,791 [ICE_EEP2_GPIO_MASK2] = 0x00, /* ignored */792 [ICE_EEP2_GPIO_STATE] = 0x06, /* 0-low, 1-high, 2-high */793 [ICE_EEP2_GPIO_STATE1] = 0x00,794 [ICE_EEP2_GPIO_STATE2] = 0x00, /* ignored */795};796 797/* entry point */798struct snd_ice1712_card_info snd_vt1720_pontis_cards[] = {799 {800 .subvendor = VT1720_SUBDEVICE_PONTIS_MS300,801 .name = "Pontis MS300",802 .model = "ms300",803 .chip_init = pontis_init,804 .build_controls = pontis_add_controls,805 .eeprom_size = sizeof(pontis_eeprom),806 .eeprom_data = pontis_eeprom,807 },808 { } /* terminator */809};810