633 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ALSA driver for ICEnsemble VT1724 (Envy24HT)4 *5 * Lowlevel functions for Ego Sys Waveterminal 192M6 *7 * Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com>8 * Some functions are taken from the Prodigy192 driver9 * source10 */11 12 13 14#include <linux/delay.h>15#include <linux/interrupt.h>16#include <linux/init.h>17#include <sound/core.h>18#include <sound/tlv.h>19#include <linux/slab.h>20 21#include "ice1712.h"22#include "envy24ht.h"23#include "wtm.h"24#include "stac946x.h"25 26struct wtm_spec {27 /* rate change needs atomic mute/unmute of all dacs*/28 struct mutex mute_mutex;29};30 31 32/*33 * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus34 */35static inline void stac9460_put(struct snd_ice1712 *ice, int reg,36 unsigned char val)37{38 snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);39}40 41static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)42{43 return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);44}45 46/*47 * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus48 */49static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,50 unsigned char val)51{52 snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);53}54 55static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)56{57 return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);58}59 60 61/*62 * DAC mute control63 */64static void stac9460_dac_mute_all(struct snd_ice1712 *ice, unsigned char mute,65 unsigned short int *change_mask)66{67 unsigned char new, old;68 int id, idx, change;69 70 /*stac9460 1*/71 for (id = 0; id < 7; id++) {72 if (*change_mask & (0x01 << id)) {73 if (id == 0)74 idx = STAC946X_MASTER_VOLUME;75 else76 idx = STAC946X_LF_VOLUME - 1 + id;77 old = stac9460_get(ice, idx);78 new = (~mute << 7 & 0x80) | (old & ~0x80);79 change = (new != old);80 if (change) {81 stac9460_put(ice, idx, new);82 *change_mask = *change_mask | (0x01 << id);83 } else {84 *change_mask = *change_mask & ~(0x01 << id);85 }86 }87 }88 89 /*stac9460 2*/90 for (id = 0; id < 3; id++) {91 if (*change_mask & (0x01 << (id + 7))) {92 if (id == 0)93 idx = STAC946X_MASTER_VOLUME;94 else95 idx = STAC946X_LF_VOLUME - 1 + id;96 old = stac9460_2_get(ice, idx);97 new = (~mute << 7 & 0x80) | (old & ~0x80);98 change = (new != old);99 if (change) {100 stac9460_2_put(ice, idx, new);101 *change_mask = *change_mask | (0x01 << id);102 } else {103 *change_mask = *change_mask & ~(0x01 << id);104 }105 }106 }107}108 109 110 111#define stac9460_dac_mute_info snd_ctl_boolean_mono_info112 113static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,114 struct snd_ctl_elem_value *ucontrol)115{116 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);117 struct wtm_spec *spec = ice->spec;118 unsigned char val;119 int idx, id;120 121 mutex_lock(&spec->mute_mutex);122 123 if (kcontrol->private_value) {124 idx = STAC946X_MASTER_VOLUME;125 id = 0;126 } else {127 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);128 idx = id + STAC946X_LF_VOLUME;129 }130 if (id < 6)131 val = stac9460_get(ice, idx);132 else133 val = stac9460_2_get(ice, idx - 6);134 ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;135 136 mutex_unlock(&spec->mute_mutex);137 return 0;138}139 140static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,141 struct snd_ctl_elem_value *ucontrol)142{143 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);144 unsigned char new, old;145 int id, idx;146 int change;147 148 if (kcontrol->private_value) {149 idx = STAC946X_MASTER_VOLUME;150 old = stac9460_get(ice, idx);151 new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |152 (old & ~0x80);153 change = (new != old);154 if (change) {155 stac9460_put(ice, idx, new);156 stac9460_2_put(ice, idx, new);157 }158 } else {159 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);160 idx = id + STAC946X_LF_VOLUME;161 if (id < 6)162 old = stac9460_get(ice, idx);163 else164 old = stac9460_2_get(ice, idx - 6);165 new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |166 (old & ~0x80);167 change = (new != old);168 if (change) {169 if (id < 6)170 stac9460_put(ice, idx, new);171 else172 stac9460_2_put(ice, idx - 6, new);173 }174 }175 return change;176}177 178/*179 * DAC volume attenuation mixer control180 */181static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,182 struct snd_ctl_elem_info *uinfo)183{184 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;185 uinfo->count = 1;186 uinfo->value.integer.min = 0; /* mute */187 uinfo->value.integer.max = 0x7f; /* 0dB */188 return 0;189}190 191static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,192 struct snd_ctl_elem_value *ucontrol)193{194 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);195 int idx, id;196 unsigned char vol;197 198 if (kcontrol->private_value) {199 idx = STAC946X_MASTER_VOLUME;200 id = 0;201 } else {202 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);203 idx = id + STAC946X_LF_VOLUME;204 }205 if (id < 6)206 vol = stac9460_get(ice, idx) & 0x7f;207 else208 vol = stac9460_2_get(ice, idx - 6) & 0x7f;209 ucontrol->value.integer.value[0] = 0x7f - vol;210 return 0;211}212 213static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,214 struct snd_ctl_elem_value *ucontrol)215{216 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);217 int idx, id;218 unsigned char tmp, ovol, nvol;219 int change;220 221 if (kcontrol->private_value) {222 idx = STAC946X_MASTER_VOLUME;223 nvol = ucontrol->value.integer.value[0] & 0x7f;224 tmp = stac9460_get(ice, idx);225 ovol = 0x7f - (tmp & 0x7f);226 change = (ovol != nvol);227 if (change) {228 stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));229 stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));230 }231 } else {232 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);233 idx = id + STAC946X_LF_VOLUME;234 nvol = ucontrol->value.integer.value[0] & 0x7f;235 if (id < 6)236 tmp = stac9460_get(ice, idx);237 else238 tmp = stac9460_2_get(ice, idx - 6);239 ovol = 0x7f - (tmp & 0x7f);240 change = (ovol != nvol);241 if (change) {242 if (id < 6)243 stac9460_put(ice, idx, (0x7f - nvol) |244 (tmp & 0x80));245 else246 stac9460_2_put(ice, idx-6, (0x7f - nvol) |247 (tmp & 0x80));248 }249 }250 return change;251}252 253/*254 * ADC mute control255 */256#define stac9460_adc_mute_info snd_ctl_boolean_stereo_info257 258static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,259 struct snd_ctl_elem_value *ucontrol)260{261 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);262 unsigned char val;263 int i, id;264 265 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);266 if (id == 0) {267 for (i = 0; i < 2; ++i) {268 val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);269 ucontrol->value.integer.value[i] = ~val>>7 & 0x1;270 }271 } else {272 for (i = 0; i < 2; ++i) {273 val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i);274 ucontrol->value.integer.value[i] = ~val>>7 & 0x1;275 }276 }277 return 0;278}279 280static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,281 struct snd_ctl_elem_value *ucontrol)282{283 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);284 unsigned char new, old;285 int i, reg, id;286 int change;287 288 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);289 if (id == 0) {290 for (i = 0; i < 2; ++i) {291 reg = STAC946X_MIC_L_VOLUME + i;292 old = stac9460_get(ice, reg);293 new = (~ucontrol->value.integer.value[i]<<7&0x80) |294 (old&~0x80);295 change = (new != old);296 if (change)297 stac9460_put(ice, reg, new);298 }299 } else {300 for (i = 0; i < 2; ++i) {301 reg = STAC946X_MIC_L_VOLUME + i;302 old = stac9460_2_get(ice, reg);303 new = (~ucontrol->value.integer.value[i]<<7&0x80) |304 (old&~0x80);305 change = (new != old);306 if (change)307 stac9460_2_put(ice, reg, new);308 }309 }310 return change;311}312 313/*314 *ADC gain mixer control315 */316static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,317 struct snd_ctl_elem_info *uinfo)318{319 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;320 uinfo->count = 2;321 uinfo->value.integer.min = 0; /* 0dB */322 uinfo->value.integer.max = 0x0f; /* 22.5dB */323 return 0;324}325 326static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,327 struct snd_ctl_elem_value *ucontrol)328{329 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);330 int i, reg, id;331 unsigned char vol;332 333 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);334 if (id == 0) {335 for (i = 0; i < 2; ++i) {336 reg = STAC946X_MIC_L_VOLUME + i;337 vol = stac9460_get(ice, reg) & 0x0f;338 ucontrol->value.integer.value[i] = 0x0f - vol;339 }340 } else {341 for (i = 0; i < 2; ++i) {342 reg = STAC946X_MIC_L_VOLUME + i;343 vol = stac9460_2_get(ice, reg) & 0x0f;344 ucontrol->value.integer.value[i] = 0x0f - vol;345 }346 }347 return 0;348}349 350static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,351 struct snd_ctl_elem_value *ucontrol)352{353 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);354 int i, reg, id;355 unsigned char ovol, nvol;356 int change;357 358 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);359 if (id == 0) {360 for (i = 0; i < 2; ++i) {361 reg = STAC946X_MIC_L_VOLUME + i;362 nvol = ucontrol->value.integer.value[i] & 0x0f;363 ovol = 0x0f - stac9460_get(ice, reg);364 change = ((ovol & 0x0f) != nvol);365 if (change)366 stac9460_put(ice, reg, (0x0f - nvol) |367 (ovol & ~0x0f));368 }369 } else {370 for (i = 0; i < 2; ++i) {371 reg = STAC946X_MIC_L_VOLUME + i;372 nvol = ucontrol->value.integer.value[i] & 0x0f;373 ovol = 0x0f - stac9460_2_get(ice, reg);374 change = ((ovol & 0x0f) != nvol);375 if (change)376 stac9460_2_put(ice, reg, (0x0f - nvol) |377 (ovol & ~0x0f));378 }379 }380 return change;381}382 383/*384 * MIC / LINE switch fonction385 */386static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,387 struct snd_ctl_elem_info *uinfo)388{389 static const char * const texts[2] = { "Line In", "Mic" };390 391 return snd_ctl_enum_info(uinfo, 1, 2, texts);392}393 394 395static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,396 struct snd_ctl_elem_value *ucontrol)397{398 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);399 unsigned char val;400 int id;401 402 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);403 if (id == 0)404 val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);405 else406 val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);407 ucontrol->value.enumerated.item[0] = (val >> 7) & 0x1;408 return 0;409}410 411static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,412 struct snd_ctl_elem_value *ucontrol)413{414 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);415 unsigned char new, old;416 int change, id;417 418 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);419 if (id == 0)420 old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);421 else422 old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);423 new = (ucontrol->value.enumerated.item[0] << 7 & 0x80) | (old & ~0x80);424 change = (new != old);425 if (change) {426 if (id == 0)427 stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);428 else429 stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);430 }431 return change;432}433 434 435/*436 * Handler for setting correct codec rate - called when rate change is detected437 */438static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate)439{440 unsigned char old, new;441 unsigned short int changed;442 struct wtm_spec *spec = ice->spec;443 444 if (rate == 0) /* no hint - S/PDIF input is master, simply return */445 return;446 else if (rate <= 48000)447 new = 0x08; /* 256x, base rate mode */448 else if (rate <= 96000)449 new = 0x11; /* 256x, mid rate mode */450 else451 new = 0x12; /* 128x, high rate mode */452 453 old = stac9460_get(ice, STAC946X_MASTER_CLOCKING);454 if (old == new)455 return;456 /* change detected, setting master clock, muting first */457 /* due to possible conflicts with mute controls - mutexing */458 mutex_lock(&spec->mute_mutex);459 /* we have to remember current mute status for each DAC */460 changed = 0xFFFF;461 stac9460_dac_mute_all(ice, 0, &changed);462 /*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/463 stac9460_put(ice, STAC946X_MASTER_CLOCKING, new);464 stac9460_2_put(ice, STAC946X_MASTER_CLOCKING, new);465 udelay(10);466 /* unmuting - only originally unmuted dacs -467 * i.e. those changed when muting */468 stac9460_dac_mute_all(ice, 1, &changed);469 mutex_unlock(&spec->mute_mutex);470}471 472 473/*Limits value in dB for fader*/474static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);475static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);476 477/*478 * Control tabs479 */480static const struct snd_kcontrol_new stac9640_controls[] = {481 {482 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,483 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |484 SNDRV_CTL_ELEM_ACCESS_TLV_READ),485 .name = "Master Playback Switch",486 .info = stac9460_dac_mute_info,487 .get = stac9460_dac_mute_get,488 .put = stac9460_dac_mute_put,489 .private_value = 1,490 .tlv = { .p = db_scale_dac }491 },492 {493 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,494 .name = "Master Playback Volume",495 .info = stac9460_dac_vol_info,496 .get = stac9460_dac_vol_get,497 .put = stac9460_dac_vol_put,498 .private_value = 1,499 },500 {501 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,502 .name = "MIC/Line Input Enum",503 .count = 2,504 .info = stac9460_mic_sw_info,505 .get = stac9460_mic_sw_get,506 .put = stac9460_mic_sw_put,507 508 },509 {510 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,511 .name = "DAC Switch",512 .count = 8,513 .info = stac9460_dac_mute_info,514 .get = stac9460_dac_mute_get,515 .put = stac9460_dac_mute_put,516 },517 {518 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,519 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |520 SNDRV_CTL_ELEM_ACCESS_TLV_READ),521 522 .name = "DAC Volume",523 .count = 8,524 .info = stac9460_dac_vol_info,525 .get = stac9460_dac_vol_get,526 .put = stac9460_dac_vol_put,527 .tlv = { .p = db_scale_dac }528 },529 {530 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,531 .name = "ADC Switch",532 .count = 2,533 .info = stac9460_adc_mute_info,534 .get = stac9460_adc_mute_get,535 .put = stac9460_adc_mute_put,536 },537 {538 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,539 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |540 SNDRV_CTL_ELEM_ACCESS_TLV_READ),541 542 .name = "ADC Volume",543 .count = 2,544 .info = stac9460_adc_vol_info,545 .get = stac9460_adc_vol_get,546 .put = stac9460_adc_vol_put,547 .tlv = { .p = db_scale_adc }548 }549};550 551 552 553/*INIT*/554static int wtm_add_controls(struct snd_ice1712 *ice)555{556 unsigned int i;557 int err;558 559 for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) {560 err = snd_ctl_add(ice->card,561 snd_ctl_new1(&stac9640_controls[i], ice));562 if (err < 0)563 return err;564 }565 return 0;566}567 568static int wtm_init(struct snd_ice1712 *ice)569{570 static const unsigned short stac_inits_wtm[] = {571 STAC946X_RESET, 0,572 STAC946X_MASTER_CLOCKING, 0x11,573 (unsigned short)-1574 };575 const unsigned short *p;576 struct wtm_spec *spec;577 578 /*WTM 192M*/579 ice->num_total_dacs = 8;580 ice->num_total_adcs = 4;581 ice->force_rdma1 = 1;582 583 /*init mutex for dac mute conflict*/584 spec = kzalloc(sizeof(*spec), GFP_KERNEL);585 if (!spec)586 return -ENOMEM;587 ice->spec = spec;588 mutex_init(&spec->mute_mutex);589 590 591 /*initialize codec*/592 p = stac_inits_wtm;593 for (; *p != (unsigned short)-1; p += 2) {594 stac9460_put(ice, p[0], p[1]);595 stac9460_2_put(ice, p[0], p[1]);596 }597 ice->gpio.set_pro_rate = stac9460_set_rate_val;598 return 0;599}600 601 602static const unsigned char wtm_eeprom[] = {603 [ICE_EEP2_SYSCONF] = 0x67, /*SYSCONF: clock 192KHz, mpu401,604 4ADC, 8DAC */605 [ICE_EEP2_ACLINK] = 0x80, /* ACLINK : I2S */606 [ICE_EEP2_I2S] = 0xf8, /* I2S: vol; 96k, 24bit, 192k */607 [ICE_EEP2_SPDIF] = 0xc1, /*SPDIF: out-en, spidf ext out*/608 [ICE_EEP2_GPIO_DIR] = 0x9f,609 [ICE_EEP2_GPIO_DIR1] = 0xff,610 [ICE_EEP2_GPIO_DIR2] = 0x7f,611 [ICE_EEP2_GPIO_MASK] = 0x9f,612 [ICE_EEP2_GPIO_MASK1] = 0xff,613 [ICE_EEP2_GPIO_MASK2] = 0x7f,614 [ICE_EEP2_GPIO_STATE] = 0x16,615 [ICE_EEP2_GPIO_STATE1] = 0x80,616 [ICE_EEP2_GPIO_STATE2] = 0x00,617};618 619 620/*entry point*/621struct snd_ice1712_card_info snd_vt1724_wtm_cards[] = {622 {623 .subvendor = VT1724_SUBDEVICE_WTM,624 .name = "ESI Waveterminal 192M",625 .model = "WT192M",626 .chip_init = wtm_init,627 .build_controls = wtm_add_controls,628 .eeprom_size = sizeof(wtm_eeprom),629 .eeprom_data = wtm_eeprom,630 },631 {} /*terminator*/632};633