linux/sound/pci/ice1712/hoontech.c
<<
>>
Prefs
   1/*
   2 *   ALSA driver for ICEnsemble ICE1712 (Envy24)
   3 *
   4 *   Lowlevel functions for Hoontech STDSP24
   5 *
   6 *      Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
   7 *
   8 *   This program is free software; you can redistribute it and/or modify
   9 *   it under the terms of the GNU General Public License as published by
  10 *   the Free Software Foundation; either version 2 of the License, or
  11 *   (at your option) any later version.
  12 *
  13 *   This program is distributed in the hope that it will be useful,
  14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 *   GNU General Public License for more details.
  17 *
  18 *   You should have received a copy of the GNU General Public License
  19 *   along with this program; if not, write to the Free Software
  20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  21 *
  22 */      
  23
  24#include <asm/io.h>
  25#include <linux/delay.h>
  26#include <linux/interrupt.h>
  27#include <linux/init.h>
  28#include <linux/slab.h>
  29#include <linux/mutex.h>
  30
  31#include <sound/core.h>
  32
  33#include "ice1712.h"
  34#include "hoontech.h"
  35
  36/* Hoontech-specific setting */
  37struct hoontech_spec {
  38        unsigned char boxbits[4];
  39        unsigned int config;
  40        unsigned short boxconfig[4];
  41};
  42
  43static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte)
  44{
  45        byte |= ICE1712_STDSP24_CLOCK_BIT;
  46        udelay(100);
  47        snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
  48        byte &= ~ICE1712_STDSP24_CLOCK_BIT;
  49        udelay(100);
  50        snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
  51        byte |= ICE1712_STDSP24_CLOCK_BIT;
  52        udelay(100);
  53        snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
  54}
  55
  56static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate)
  57{
  58        struct hoontech_spec *spec = ice->spec;
  59        mutex_lock(&ice->gpio_mutex);
  60        ICE1712_STDSP24_0_DAREAR(spec->boxbits, activate);
  61        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
  62        mutex_unlock(&ice->gpio_mutex);
  63}
  64
  65static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate)
  66{
  67        struct hoontech_spec *spec = ice->spec;
  68        mutex_lock(&ice->gpio_mutex);
  69        ICE1712_STDSP24_3_MUTE(spec->boxbits, activate);
  70        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
  71        mutex_unlock(&ice->gpio_mutex);
  72}
  73
  74static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate)
  75{
  76        struct hoontech_spec *spec = ice->spec;
  77        mutex_lock(&ice->gpio_mutex);
  78        ICE1712_STDSP24_3_INSEL(spec->boxbits, activate);
  79        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
  80        mutex_unlock(&ice->gpio_mutex);
  81}
  82
  83static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate)
  84{
  85        struct hoontech_spec *spec = ice->spec;
  86
  87        mutex_lock(&ice->gpio_mutex);
  88
  89        /* select box */
  90        ICE1712_STDSP24_0_BOX(spec->boxbits, box);
  91        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
  92
  93        /* prepare for write */
  94        if (chn == 3)
  95                ICE1712_STDSP24_2_CHN4(spec->boxbits, 0);
  96        ICE1712_STDSP24_2_MIDI1(spec->boxbits, activate);
  97        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
  98        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
  99
 100        ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
 101        ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
 102        ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
 103        ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
 104        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
 105        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
 106        udelay(100);
 107        if (chn == 3) {
 108                ICE1712_STDSP24_2_CHN4(spec->boxbits, 0);
 109                snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
 110        } else {
 111                switch (chn) {
 112                case 0: ICE1712_STDSP24_1_CHN1(spec->boxbits, 0); break;
 113                case 1: ICE1712_STDSP24_1_CHN2(spec->boxbits, 0); break;
 114                case 2: ICE1712_STDSP24_1_CHN3(spec->boxbits, 0); break;
 115                }
 116                snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
 117        }
 118        udelay(100);
 119        ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
 120        ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
 121        ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
 122        ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
 123        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
 124        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
 125        udelay(100);
 126
 127        ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0);
 128        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
 129
 130        mutex_unlock(&ice->gpio_mutex);
 131}
 132
 133static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master)
 134{
 135        struct hoontech_spec *spec = ice->spec;
 136
 137        mutex_lock(&ice->gpio_mutex);
 138
 139        /* select box */
 140        ICE1712_STDSP24_0_BOX(spec->boxbits, box);
 141        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
 142
 143        ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
 144        ICE1712_STDSP24_2_MIDI1(spec->boxbits, master);
 145        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
 146        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
 147
 148        udelay(100);
 149        
 150        ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 0);
 151        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
 152        
 153        mdelay(10);
 154        
 155        ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
 156        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
 157
 158        mutex_unlock(&ice->gpio_mutex);
 159}
 160
 161static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate)
 162{
 163        struct hoontech_spec *spec = ice->spec;
 164        mutex_lock(&ice->gpio_mutex);
 165        ICE1712_STDSP24_3_MIDI2(spec->boxbits, activate);
 166        snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
 167        mutex_unlock(&ice->gpio_mutex);
 168}
 169
 170static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
 171{
 172        struct hoontech_spec *spec;
 173        int box, chn;
 174
 175        ice->num_total_dacs = 8;
 176        ice->num_total_adcs = 8;
 177
 178        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 179        if (!spec)
 180                return -ENOMEM;
 181        ice->spec = spec;
 182
 183        ICE1712_STDSP24_SET_ADDR(spec->boxbits, 0);
 184        ICE1712_STDSP24_CLOCK(spec->boxbits, 0, 1);
 185        ICE1712_STDSP24_0_BOX(spec->boxbits, 0);
 186        ICE1712_STDSP24_0_DAREAR(spec->boxbits, 0);
 187
 188        ICE1712_STDSP24_SET_ADDR(spec->boxbits, 1);
 189        ICE1712_STDSP24_CLOCK(spec->boxbits, 1, 1);
 190        ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
 191        ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
 192        ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
 193        
 194        ICE1712_STDSP24_SET_ADDR(spec->boxbits, 2);
 195        ICE1712_STDSP24_CLOCK(spec->boxbits, 2, 1);
 196        ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
 197        ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
 198        ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0);
 199
 200        ICE1712_STDSP24_SET_ADDR(spec->boxbits, 3);
 201        ICE1712_STDSP24_CLOCK(spec->boxbits, 3, 1);
 202        ICE1712_STDSP24_3_MIDI2(spec->boxbits, 0);
 203        ICE1712_STDSP24_3_MUTE(spec->boxbits, 1);
 204        ICE1712_STDSP24_3_INSEL(spec->boxbits, 0);
 205
 206        /* let's go - activate only functions in first box */
 207        spec->config = 0;
 208                            /* ICE1712_STDSP24_MUTE |
 209                               ICE1712_STDSP24_INSEL |
 210                               ICE1712_STDSP24_DAREAR; */
 211        /*  These boxconfigs have caused problems in the past.
 212         *  The code is not optimal, but should now enable a working config to
 213         *  be achieved.
 214         *  ** MIDI IN can only be configured on one box **
 215         *  ICE1712_STDSP24_BOX_MIDI1 needs to be set for that box.
 216         *  Tests on a ADAC2000 box suggest the box config flags do not
 217         *  work as would be expected, and the inputs are crossed.
 218         *  Setting ICE1712_STDSP24_BOX_MIDI1 and ICE1712_STDSP24_BOX_MIDI2
 219         *  on the same box connects MIDI-In to both 401 uarts; both outputs
 220         *  are then active on all boxes.
 221         *  The default config here sets up everything on the first box.
 222         *  Alan Horstmann  5.2.2008
 223         */
 224        spec->boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 |
 225                                     ICE1712_STDSP24_BOX_CHN2 |
 226                                     ICE1712_STDSP24_BOX_CHN3 |
 227                                     ICE1712_STDSP24_BOX_CHN4 |
 228                                     ICE1712_STDSP24_BOX_MIDI1 |
 229                                     ICE1712_STDSP24_BOX_MIDI2;
 230        spec->boxconfig[1] = 
 231        spec->boxconfig[2] = 
 232        spec->boxconfig[3] = 0;
 233        snd_ice1712_stdsp24_darear(ice,
 234                (spec->config & ICE1712_STDSP24_DAREAR) ? 1 : 0);
 235        snd_ice1712_stdsp24_mute(ice,
 236                (spec->config & ICE1712_STDSP24_MUTE) ? 1 : 0);
 237        snd_ice1712_stdsp24_insel(ice,
 238                (spec->config & ICE1712_STDSP24_INSEL) ? 1 : 0);
 239        for (box = 0; box < 4; box++) {
 240                if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2)
 241                        snd_ice1712_stdsp24_midi2(ice, 1);
 242                for (chn = 0; chn < 4; chn++)
 243                        snd_ice1712_stdsp24_box_channel(ice, box, chn,
 244                                (spec->boxconfig[box] & (1 << chn)) ? 1 : 0);
 245                if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1)
 246                        snd_ice1712_stdsp24_box_midi(ice, box, 1);
 247        }
 248
 249        return 0;
 250}
 251
 252/*
 253 * AK4524 access
 254 */
 255
 256/* start callback for STDSP24 with modified hardware */
 257static void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip)
 258{
 259        struct snd_ice1712 *ice = ak->private_data[0];
 260        unsigned char tmp;
 261        snd_ice1712_save_gpio_status(ice);
 262        tmp =   ICE1712_STDSP24_SERIAL_DATA |
 263                ICE1712_STDSP24_SERIAL_CLOCK |
 264                ICE1712_STDSP24_AK4524_CS;
 265        snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION,
 266                          ice->gpio.direction | tmp);
 267        snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp);
 268}
 269
 270static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
 271{
 272        /* Hoontech STDSP24 with modified hardware */
 273        static struct snd_akm4xxx akm_stdsp24_mv __devinitdata = {
 274                .num_adcs = 2,
 275                .num_dacs = 2,
 276                .type = SND_AK4524,
 277                .ops = {
 278                        .lock = stdsp24_ak4524_lock
 279                }
 280        };
 281
 282        static struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = {
 283                .caddr = 2,
 284                .cif = 1, /* CIF high */
 285                .data_mask = ICE1712_STDSP24_SERIAL_DATA,
 286                .clk_mask = ICE1712_STDSP24_SERIAL_CLOCK,
 287                .cs_mask = ICE1712_STDSP24_AK4524_CS,
 288                .cs_addr = ICE1712_STDSP24_AK4524_CS,
 289                .cs_none = 0,
 290                .add_flags = 0,
 291        };
 292
 293        int err;
 294        struct snd_akm4xxx *ak;
 295
 296        /* set the analog DACs */
 297        ice->num_total_dacs = 2;
 298
 299        /* set the analog ADCs */
 300        ice->num_total_adcs = 2;
 301        
 302        /* analog section */
 303        ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
 304        if (! ak)
 305                return -ENOMEM;
 306        ice->akm_codecs = 1;
 307
 308        err = snd_ice1712_akm4xxx_init(ak, &akm_stdsp24_mv, &akm_stdsp24_mv_priv, ice);
 309        if (err < 0)
 310                return err;
 311
 312        /* ak4524 controls */
 313        err = snd_ice1712_akm4xxx_build_controls(ice);
 314        if (err < 0)
 315                return err;
 316
 317        return 0;
 318}
 319
 320static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice)
 321{
 322        ice->gpio.write_mask = ice->eeprom.gpiomask;
 323        ice->gpio.direction = ice->eeprom.gpiodir;
 324        snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ice->eeprom.gpiomask);
 325        snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, ice->eeprom.gpiodir);
 326        snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, ice->eeprom.gpiostate);
 327        return 0;
 328}
 329
 330
 331/* entry point */
 332struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
 333        {
 334                .subvendor = ICE1712_SUBDEVICE_STDSP24,
 335                .name = "Hoontech SoundTrack Audio DSP24",
 336                .model = "dsp24",
 337                .chip_init = snd_ice1712_hoontech_init,
 338                .mpu401_1_name = "MIDI-1 Hoontech/STA DSP24",
 339                .mpu401_2_name = "MIDI-2 Hoontech/STA DSP24",
 340        },
 341        {
 342                .subvendor = ICE1712_SUBDEVICE_STDSP24_VALUE,   /* a dummy id */
 343                .name = "Hoontech SoundTrack Audio DSP24 Value",
 344                .model = "dsp24_value",
 345                .chip_init = snd_ice1712_value_init,
 346        },
 347        {
 348                .subvendor = ICE1712_SUBDEVICE_STDSP24_MEDIA7_1,
 349                .name = "Hoontech STA DSP24 Media 7.1",
 350                .model = "dsp24_71",
 351                .chip_init = snd_ice1712_hoontech_init,
 352        },
 353        {
 354                .subvendor = ICE1712_SUBDEVICE_EVENT_EZ8,       /* a dummy id */
 355                .name = "Event Electronics EZ8",
 356                .model = "ez8",
 357                .chip_init = snd_ice1712_ez8_init,
 358        },
 359        { } /* terminator */
 360};
 361