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