linux/sound/pci/ice1712/wtm.c
<<
>>
Prefs
   1/*
   2 *      ALSA driver for ICEnsemble VT1724 (Envy24HT)
   3 *
   4 *      Lowlevel functions for Ego Sys Waveterminal 192M
   5 *
   6 *              Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com>
   7 *              Some functions are taken from the Prodigy192 driver
   8 *              source
   9 *
  10 *      This program is free software; you can redistribute it and/or modify
  11 *      it under the terms of the GNU General Public License as published by
  12 *      the Free Software Foundation; either version 2 of the License, or
  13 *      (at your option) any later version.
  14 *
  15 *      This program is distributed in the hope that it will be useful,
  16 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18 *      GNU General Public License for more details.
  19 *
  20 *      You should have received a copy of the GNU General Public License
  21 *      along with this program; if not, write to the Free Software
  22 *      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23 *
  24 */
  25
  26
  27
  28#include <linux/io.h>
  29#include <linux/delay.h>
  30#include <linux/interrupt.h>
  31#include <linux/init.h>
  32#include <sound/core.h>
  33
  34#include "ice1712.h"
  35#include "envy24ht.h"
  36#include "wtm.h"
  37#include "stac946x.h"
  38
  39
  40/*
  41 *      2*ADC 6*DAC no1 ringbuffer r/w on i2c bus
  42 */
  43static inline void stac9460_put(struct snd_ice1712 *ice, int reg,
  44                                                unsigned char val)
  45{
  46        snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);
  47}
  48
  49static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
  50{
  51        return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);
  52}
  53
  54/*
  55 *      2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
  56 */
  57static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,
  58                                                unsigned char val)
  59{
  60        snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);
  61}
  62
  63static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
  64{
  65        return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);
  66}
  67
  68
  69/*
  70 *      DAC mute control
  71 */
  72#define stac9460_dac_mute_info          snd_ctl_boolean_mono_info
  73
  74static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
  75                                struct snd_ctl_elem_value *ucontrol)
  76{
  77        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
  78        unsigned char val;
  79        int idx, id;
  80
  81        if (kcontrol->private_value) {
  82                idx = STAC946X_MASTER_VOLUME;
  83                id = 0;
  84        } else {
  85                id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  86                idx = id + STAC946X_LF_VOLUME;
  87        }
  88        if (id < 6)
  89                val = stac9460_get(ice, idx);
  90        else
  91                val = stac9460_2_get(ice, idx - 6);
  92        ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
  93        return 0;
  94}
  95
  96static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,
  97                                struct snd_ctl_elem_value *ucontrol)
  98{
  99        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 100        unsigned char new, old;
 101        int id, idx;
 102        int change;
 103
 104        if (kcontrol->private_value) {
 105                idx = STAC946X_MASTER_VOLUME;
 106                old = stac9460_get(ice, idx);
 107                new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |
 108                                                        (old & ~0x80);
 109                change = (new != old);
 110                if (change) {
 111                        stac9460_put(ice, idx, new);
 112                        stac9460_2_put(ice, idx, new);
 113                }
 114        } else {
 115                id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 116                idx = id + STAC946X_LF_VOLUME;
 117                if (id < 6)
 118                        old = stac9460_get(ice, idx);
 119                else
 120                        old = stac9460_2_get(ice, idx - 6);
 121                new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |
 122                                                        (old & ~0x80);
 123                change = (new != old);
 124                if (change) {
 125                        if (id < 6)
 126                                stac9460_put(ice, idx, new);
 127                        else
 128                                stac9460_2_put(ice, idx - 6, new);
 129                }
 130        }
 131        return change;
 132}
 133
 134/*
 135 *      DAC volume attenuation mixer control
 136 */
 137static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,
 138                                struct snd_ctl_elem_info *uinfo)
 139{
 140        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 141        uinfo->count = 1;
 142        uinfo->value.integer.min = 0;                   /* mute */
 143        uinfo->value.integer.max = 0x7f;                /* 0dB */
 144        return 0;
 145}
 146
 147static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,
 148                                struct snd_ctl_elem_value *ucontrol)
 149{
 150        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 151        int idx, id;
 152        unsigned char vol;
 153
 154        if (kcontrol->private_value) {
 155                idx = STAC946X_MASTER_VOLUME;
 156                id = 0;
 157        } else {
 158                id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 159                idx = id + STAC946X_LF_VOLUME;
 160        }
 161        if (id < 6)
 162                vol = stac9460_get(ice, idx) & 0x7f;
 163        else
 164                vol = stac9460_2_get(ice, idx - 6) & 0x7f;
 165        ucontrol->value.integer.value[0] = 0x7f - vol;
 166        return 0;
 167}
 168
 169static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
 170                                struct snd_ctl_elem_value *ucontrol)
 171{
 172        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 173        int idx, id;
 174        unsigned char tmp, ovol, nvol;
 175        int change;
 176
 177        if (kcontrol->private_value) {
 178                idx = STAC946X_MASTER_VOLUME;
 179                nvol = ucontrol->value.integer.value[0] & 0x7f;
 180                tmp = stac9460_get(ice, idx);
 181                ovol = 0x7f - (tmp & 0x7f);
 182                change = (ovol != nvol);
 183                if (change) {
 184                        stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
 185                        stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
 186                }
 187        } else {
 188                id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 189                idx = id + STAC946X_LF_VOLUME;
 190                nvol = ucontrol->value.integer.value[0] & 0x7f;
 191                if (id < 6)
 192                        tmp = stac9460_get(ice, idx);
 193                else
 194                        tmp = stac9460_2_get(ice, idx - 6);
 195                ovol = 0x7f - (tmp & 0x7f);
 196                change = (ovol != nvol);
 197                if (change) {
 198                        if (id < 6)
 199                                stac9460_put(ice, idx, (0x7f - nvol) |
 200                                                        (tmp & 0x80));
 201                        else
 202                                stac9460_2_put(ice, idx-6, (0x7f - nvol) |
 203                                                        (tmp & 0x80));
 204                }
 205        }
 206        return change;
 207}
 208
 209/*
 210 * ADC mute control
 211 */
 212#define stac9460_adc_mute_info          snd_ctl_boolean_stereo_info
 213
 214static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
 215                                struct snd_ctl_elem_value *ucontrol)
 216{
 217        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 218        unsigned char val;
 219        int i, id;
 220
 221        id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 222        if (id == 0) {
 223                for (i = 0; i < 2; ++i) {
 224                        val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
 225                        ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
 226                }
 227        } else {
 228                for (i = 0; i < 2; ++i) {
 229                        val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i);
 230                        ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
 231                }
 232        }
 233        return 0;
 234}
 235
 236static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,
 237                                struct snd_ctl_elem_value *ucontrol)
 238{
 239        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 240        unsigned char new, old;
 241        int i, reg, id;
 242        int change;
 243
 244        id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 245        if (id == 0) {
 246                for (i = 0; i < 2; ++i) {
 247                        reg = STAC946X_MIC_L_VOLUME + i;
 248                        old = stac9460_get(ice, reg);
 249                        new = (~ucontrol->value.integer.value[i]<<7&0x80) |
 250                                                                (old&~0x80);
 251                        change = (new != old);
 252                        if (change)
 253                                stac9460_put(ice, reg, new);
 254                }
 255        } else {
 256                for (i = 0; i < 2; ++i) {
 257                        reg = STAC946X_MIC_L_VOLUME + i;
 258                        old = stac9460_2_get(ice, reg);
 259                        new = (~ucontrol->value.integer.value[i]<<7&0x80) |
 260                                                                (old&~0x80);
 261                        change = (new != old);
 262                        if (change)
 263                                stac9460_2_put(ice, reg, new);
 264                }
 265        }
 266        return change;
 267}
 268
 269/*
 270 *ADC gain mixer control
 271 */
 272static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,
 273                                struct snd_ctl_elem_info *uinfo)
 274{
 275        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 276        uinfo->count = 2;
 277        uinfo->value.integer.min = 0;           /* 0dB */
 278        uinfo->value.integer.max = 0x0f;        /* 22.5dB */
 279        return 0;
 280}
 281
 282static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,
 283                                struct snd_ctl_elem_value *ucontrol)
 284{
 285        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 286        int i, reg, id;
 287        unsigned char vol;
 288
 289        id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 290        if (id == 0) {
 291                for (i = 0; i < 2; ++i) {
 292                        reg = STAC946X_MIC_L_VOLUME + i;
 293                        vol = stac9460_get(ice, reg) & 0x0f;
 294                        ucontrol->value.integer.value[i] = 0x0f - vol;
 295                }
 296        } else {
 297                for (i = 0; i < 2; ++i) {
 298                        reg = STAC946X_MIC_L_VOLUME + i;
 299                        vol = stac9460_2_get(ice, reg) & 0x0f;
 300                        ucontrol->value.integer.value[i] = 0x0f - vol;
 301                }
 302        }
 303        return 0;
 304}
 305
 306static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
 307                                struct snd_ctl_elem_value *ucontrol)
 308{
 309        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 310        int i, reg, id;
 311        unsigned char ovol, nvol;
 312        int change;
 313
 314        id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 315        if (id == 0) {
 316                for (i = 0; i < 2; ++i) {
 317                        reg = STAC946X_MIC_L_VOLUME + i;
 318                        nvol = ucontrol->value.integer.value[i] & 0x0f;
 319                        ovol = 0x0f - stac9460_get(ice, reg);
 320                        change = ((ovol & 0x0f) != nvol);
 321                        if (change)
 322                                stac9460_put(ice, reg, (0x0f - nvol) |
 323                                                        (ovol & ~0x0f));
 324                }
 325        } else {
 326                for (i = 0; i < 2; ++i) {
 327                        reg = STAC946X_MIC_L_VOLUME + i;
 328                        nvol = ucontrol->value.integer.value[i] & 0x0f;
 329                        ovol = 0x0f - stac9460_2_get(ice, reg);
 330                        change = ((ovol & 0x0f) != nvol);
 331                        if (change)
 332                                stac9460_2_put(ice, reg, (0x0f - nvol) |
 333                                                        (ovol & ~0x0f));
 334                }
 335        }
 336        return change;
 337}
 338
 339/*
 340 * MIC / LINE switch fonction
 341 */
 342
 343#define stac9460_mic_sw_info            snd_ctl_boolean_mono_info
 344
 345static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
 346                                struct snd_ctl_elem_value *ucontrol)
 347{
 348        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 349        unsigned char val;
 350        int id;
 351
 352        id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 353        if (id == 0)
 354                val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
 355        else
 356                val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
 357        ucontrol->value.integer.value[0] = ~val>>7 & 0x1;
 358        return 0;
 359}
 360
 361static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
 362                                struct snd_ctl_elem_value *ucontrol)
 363{
 364        struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
 365        unsigned char new, old;
 366        int change, id;
 367
 368        id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 369        if (id == 0)
 370                old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
 371        else
 372                old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
 373        new = (~ucontrol->value.integer.value[0] << 7 & 0x80) | (old & ~0x80);
 374        change = (new != old);
 375        if (change) {
 376                if (id == 0)
 377                        stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
 378                else
 379                        stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);
 380        }
 381        return change;
 382}
 383
 384/*
 385 * Control tabs
 386 */
 387static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
 388        {
 389                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 390                .name = "Master Playback Switch",
 391                .info = stac9460_dac_mute_info,
 392                .get = stac9460_dac_mute_get,
 393                .put = stac9460_dac_mute_put,
 394                .private_value = 1
 395        },
 396        {
 397                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 398                .name = "Master Playback Volume",
 399                .info = stac9460_dac_vol_info,
 400                .get = stac9460_dac_vol_get,
 401                .put = stac9460_dac_vol_put,
 402                .private_value = 1,
 403        },
 404        {
 405                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 406                .name = "MIC/Line switch",
 407                .count = 2,
 408                .info = stac9460_mic_sw_info,
 409                .get = stac9460_mic_sw_get,
 410                .put = stac9460_mic_sw_put,
 411
 412        },
 413        {
 414                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 415                .name = "DAC Switch",
 416                .count = 8,
 417                .info = stac9460_dac_mute_info,
 418                .get = stac9460_dac_mute_get,
 419                .put = stac9460_dac_mute_put,
 420        },
 421        {
 422                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 423                .name = "DAC Volume",
 424                .count = 8,
 425                .info = stac9460_dac_vol_info,
 426                .get = stac9460_dac_vol_get,
 427                .put = stac9460_dac_vol_put,
 428        },
 429        {
 430                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 431                .name = "ADC Switch",
 432                .count = 2,
 433                .info = stac9460_adc_mute_info,
 434                .get = stac9460_adc_mute_get,
 435                .put = stac9460_adc_mute_put,
 436        },
 437        {
 438                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 439                .name = "ADC Volume",
 440                .count = 2,
 441                .info = stac9460_adc_vol_info,
 442                .get = stac9460_adc_vol_get,
 443                .put = stac9460_adc_vol_put,
 444
 445        }
 446};
 447
 448
 449
 450/*INIT*/
 451static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
 452{
 453        unsigned int i;
 454        int err;
 455
 456        for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) {
 457                err = snd_ctl_add(ice->card,
 458                                snd_ctl_new1(&stac9640_controls[i], ice));
 459                if (err < 0)
 460                        return err;
 461        }
 462        return 0;
 463}
 464
 465static int __devinit wtm_init(struct snd_ice1712 *ice)
 466{
 467        static unsigned short stac_inits_prodigy[] = {
 468                STAC946X_RESET, 0,
 469                (unsigned short)-1
 470        };
 471        unsigned short *p;
 472
 473        /*WTM 192M*/
 474        ice->num_total_dacs = 8;
 475        ice->num_total_adcs = 4;
 476        ice->force_rdma1 = 1;
 477
 478        /*initialize codec*/
 479        p = stac_inits_prodigy;
 480        for (; *p != (unsigned short)-1; p += 2) {
 481                stac9460_put(ice, p[0], p[1]);
 482                stac9460_2_put(ice, p[0], p[1]);
 483        }
 484        return 0;
 485}
 486
 487
 488static unsigned char wtm_eeprom[] __devinitdata = {
 489        0x47,   /*SYSCONF: clock 192KHz, 4ADC, 8DAC */
 490        0x80,   /* ACLINK : I2S */
 491        0xf8,   /* I2S: vol; 96k, 24bit, 192k */
 492        0xc1    /*SPDIF: out-en, spidf ext out*/,
 493        0x9f,   /* GPIO_DIR */
 494        0xff,   /* GPIO_DIR1 */
 495        0x7f,   /* GPIO_DIR2 */
 496        0x9f,   /* GPIO_MASK */
 497        0xff,   /* GPIO_MASK1 */
 498        0x7f,   /* GPIO_MASK2 */
 499        0x16,   /* GPIO_STATE */
 500        0x80,   /* GPIO_STATE1 */
 501        0x00,   /* GPIO_STATE2 */
 502};
 503
 504
 505/*entry point*/
 506struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = {
 507        {
 508                .subvendor = VT1724_SUBDEVICE_WTM,
 509                .name = "ESI Waveterminal 192M",
 510                .model = "WT192M",
 511                .chip_init = wtm_init,
 512                .build_controls = wtm_add_controls,
 513                .eeprom_size = sizeof(wtm_eeprom),
 514                .eeprom_data = wtm_eeprom,
 515        },
 516        {} /*terminator*/
 517};
 518