root/sound/pci/ice1712/hoontech.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_ice1712_stdsp24_gpio_write
  2. snd_ice1712_stdsp24_darear
  3. snd_ice1712_stdsp24_mute
  4. snd_ice1712_stdsp24_insel
  5. snd_ice1712_stdsp24_box_channel
  6. snd_ice1712_stdsp24_box_midi
  7. snd_ice1712_stdsp24_midi2
  8. hoontech_init
  9. snd_ice1712_hoontech_init
  10. snd_ice1712_staudio_init
  11. stdsp24_ak4524_lock
  12. snd_ice1712_value_init
  13. snd_ice1712_ez8_init

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

/* [<][>][^][v][top][bottom][index][help] */