Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *   ALSA driver for ICEnsemble ICE1712 (Envy24)
0004  *
0005  *   Lowlevel functions for Hoontech STDSP24
0006  *
0007  *  Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
0008  */      
0009 
0010 #include <linux/delay.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/init.h>
0013 #include <linux/slab.h>
0014 #include <linux/mutex.h>
0015 
0016 #include <sound/core.h>
0017 
0018 #include "ice1712.h"
0019 #include "hoontech.h"
0020 
0021 /* Hoontech-specific setting */
0022 struct hoontech_spec {
0023     unsigned char boxbits[4];
0024     unsigned int config;
0025     unsigned short boxconfig[4];
0026 };
0027 
0028 static void snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte)
0029 {
0030     byte |= ICE1712_STDSP24_CLOCK_BIT;
0031     udelay(100);
0032     snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
0033     byte &= ~ICE1712_STDSP24_CLOCK_BIT;
0034     udelay(100);
0035     snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
0036     byte |= ICE1712_STDSP24_CLOCK_BIT;
0037     udelay(100);
0038     snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
0039 }
0040 
0041 static void snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate)
0042 {
0043     struct hoontech_spec *spec = ice->spec;
0044     mutex_lock(&ice->gpio_mutex);
0045     ICE1712_STDSP24_0_DAREAR(spec->boxbits, activate);
0046     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
0047     mutex_unlock(&ice->gpio_mutex);
0048 }
0049 
0050 static void snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate)
0051 {
0052     struct hoontech_spec *spec = ice->spec;
0053     mutex_lock(&ice->gpio_mutex);
0054     ICE1712_STDSP24_3_MUTE(spec->boxbits, activate);
0055     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
0056     mutex_unlock(&ice->gpio_mutex);
0057 }
0058 
0059 static void snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate)
0060 {
0061     struct hoontech_spec *spec = ice->spec;
0062     mutex_lock(&ice->gpio_mutex);
0063     ICE1712_STDSP24_3_INSEL(spec->boxbits, activate);
0064     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
0065     mutex_unlock(&ice->gpio_mutex);
0066 }
0067 
0068 static void snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate)
0069 {
0070     struct hoontech_spec *spec = ice->spec;
0071 
0072     mutex_lock(&ice->gpio_mutex);
0073 
0074     /* select box */
0075     ICE1712_STDSP24_0_BOX(spec->boxbits, box);
0076     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
0077 
0078     /* prepare for write */
0079     if (chn == 3)
0080         ICE1712_STDSP24_2_CHN4(spec->boxbits, 0);
0081     ICE1712_STDSP24_2_MIDI1(spec->boxbits, activate);
0082     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
0083     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
0084 
0085     ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
0086     ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
0087     ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
0088     ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
0089     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
0090     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
0091     udelay(100);
0092     if (chn == 3) {
0093         ICE1712_STDSP24_2_CHN4(spec->boxbits, 0);
0094         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
0095     } else {
0096         switch (chn) {
0097         case 0: ICE1712_STDSP24_1_CHN1(spec->boxbits, 0); break;
0098         case 1: ICE1712_STDSP24_1_CHN2(spec->boxbits, 0); break;
0099         case 2: ICE1712_STDSP24_1_CHN3(spec->boxbits, 0); break;
0100         }
0101         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
0102     }
0103     udelay(100);
0104     ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
0105     ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
0106     ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
0107     ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
0108     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
0109     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
0110     udelay(100);
0111 
0112     ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0);
0113     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
0114 
0115     mutex_unlock(&ice->gpio_mutex);
0116 }
0117 
0118 static void snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master)
0119 {
0120     struct hoontech_spec *spec = ice->spec;
0121 
0122     mutex_lock(&ice->gpio_mutex);
0123 
0124     /* select box */
0125     ICE1712_STDSP24_0_BOX(spec->boxbits, box);
0126     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
0127 
0128     ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
0129     ICE1712_STDSP24_2_MIDI1(spec->boxbits, master);
0130     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
0131     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
0132 
0133     udelay(100);
0134     
0135     ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 0);
0136     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
0137     
0138     mdelay(10);
0139     
0140     ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
0141     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
0142 
0143     mutex_unlock(&ice->gpio_mutex);
0144 }
0145 
0146 static void snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate)
0147 {
0148     struct hoontech_spec *spec = ice->spec;
0149     mutex_lock(&ice->gpio_mutex);
0150     ICE1712_STDSP24_3_MIDI2(spec->boxbits, activate);
0151     snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
0152     mutex_unlock(&ice->gpio_mutex);
0153 }
0154 
0155 static int hoontech_init(struct snd_ice1712 *ice, bool staudio)
0156 {
0157     struct hoontech_spec *spec;
0158     int box, chn;
0159 
0160     ice->num_total_dacs = 8;
0161     ice->num_total_adcs = 8;
0162 
0163     spec = kzalloc(sizeof(*spec), GFP_KERNEL);
0164     if (!spec)
0165         return -ENOMEM;
0166     ice->spec = spec;
0167 
0168     ICE1712_STDSP24_SET_ADDR(spec->boxbits, 0);
0169     ICE1712_STDSP24_CLOCK(spec->boxbits, 0, 1);
0170     ICE1712_STDSP24_0_BOX(spec->boxbits, 0);
0171     ICE1712_STDSP24_0_DAREAR(spec->boxbits, 0);
0172 
0173     ICE1712_STDSP24_SET_ADDR(spec->boxbits, 1);
0174     ICE1712_STDSP24_CLOCK(spec->boxbits, 1, 1);
0175     ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
0176     ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
0177     ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
0178     
0179     ICE1712_STDSP24_SET_ADDR(spec->boxbits, 2);
0180     ICE1712_STDSP24_CLOCK(spec->boxbits, 2, 1);
0181     ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
0182     ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
0183     ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0);
0184 
0185     ICE1712_STDSP24_SET_ADDR(spec->boxbits, 3);
0186     ICE1712_STDSP24_CLOCK(spec->boxbits, 3, 1);
0187     ICE1712_STDSP24_3_MIDI2(spec->boxbits, 0);
0188     ICE1712_STDSP24_3_MUTE(spec->boxbits, 1);
0189     ICE1712_STDSP24_3_INSEL(spec->boxbits, 0);
0190 
0191     /* let's go - activate only functions in first box */
0192     if (staudio)
0193         spec->config = ICE1712_STDSP24_MUTE;
0194     else
0195         spec->config = 0;
0196                 /* ICE1712_STDSP24_MUTE |
0197                    ICE1712_STDSP24_INSEL |
0198                    ICE1712_STDSP24_DAREAR; */
0199     /*  These boxconfigs have caused problems in the past.
0200      *  The code is not optimal, but should now enable a working config to
0201      *  be achieved.
0202      *  ** MIDI IN can only be configured on one box **
0203      *  ICE1712_STDSP24_BOX_MIDI1 needs to be set for that box.
0204      *  Tests on a ADAC2000 box suggest the box config flags do not
0205      *  work as would be expected, and the inputs are crossed.
0206      *  Setting ICE1712_STDSP24_BOX_MIDI1 and ICE1712_STDSP24_BOX_MIDI2
0207      *  on the same box connects MIDI-In to both 401 uarts; both outputs
0208      *  are then active on all boxes.
0209      *  The default config here sets up everything on the first box.
0210      *  Alan Horstmann  5.2.2008
0211      */
0212     spec->boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 |
0213                      ICE1712_STDSP24_BOX_CHN2 |
0214                      ICE1712_STDSP24_BOX_CHN3 |
0215                      ICE1712_STDSP24_BOX_CHN4 |
0216                      ICE1712_STDSP24_BOX_MIDI1 |
0217                      ICE1712_STDSP24_BOX_MIDI2;
0218     if (staudio) {
0219         spec->boxconfig[1] =
0220         spec->boxconfig[2] =
0221         spec->boxconfig[3] = spec->boxconfig[0];
0222     } else {
0223         spec->boxconfig[1] =
0224         spec->boxconfig[2] =
0225         spec->boxconfig[3] = 0;
0226     }
0227 
0228     snd_ice1712_stdsp24_darear(ice,
0229         (spec->config & ICE1712_STDSP24_DAREAR) ? 1 : 0);
0230     snd_ice1712_stdsp24_mute(ice,
0231         (spec->config & ICE1712_STDSP24_MUTE) ? 1 : 0);
0232     snd_ice1712_stdsp24_insel(ice,
0233         (spec->config & ICE1712_STDSP24_INSEL) ? 1 : 0);
0234     for (box = 0; box < 4; box++) {
0235         if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2)
0236                         snd_ice1712_stdsp24_midi2(ice, 1);
0237         for (chn = 0; chn < 4; chn++)
0238             snd_ice1712_stdsp24_box_channel(ice, box, chn,
0239                 (spec->boxconfig[box] & (1 << chn)) ? 1 : 0);
0240         if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1)
0241             snd_ice1712_stdsp24_box_midi(ice, box, 1);
0242     }
0243 
0244     return 0;
0245 }
0246 
0247 static int snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
0248 {
0249     return hoontech_init(ice, false);
0250 }
0251 
0252 static int snd_ice1712_staudio_init(struct snd_ice1712 *ice)
0253 {
0254     return hoontech_init(ice, true);
0255 }
0256 
0257 /*
0258  * AK4524 access
0259  */
0260 
0261 /* start callback for STDSP24 with modified hardware */
0262 static void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip)
0263 {
0264     struct snd_ice1712 *ice = ak->private_data[0];
0265     unsigned char tmp;
0266     snd_ice1712_save_gpio_status(ice);
0267     tmp =   ICE1712_STDSP24_SERIAL_DATA |
0268         ICE1712_STDSP24_SERIAL_CLOCK |
0269         ICE1712_STDSP24_AK4524_CS;
0270     snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION,
0271               ice->gpio.direction | tmp);
0272     snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp);
0273 }
0274 
0275 static int snd_ice1712_value_init(struct snd_ice1712 *ice)
0276 {
0277     /* Hoontech STDSP24 with modified hardware */
0278     static const struct snd_akm4xxx akm_stdsp24_mv = {
0279         .num_adcs = 2,
0280         .num_dacs = 2,
0281         .type = SND_AK4524,
0282         .ops = {
0283             .lock = stdsp24_ak4524_lock
0284         }
0285     };
0286 
0287     static const struct snd_ak4xxx_private akm_stdsp24_mv_priv = {
0288         .caddr = 2,
0289         .cif = 1, /* CIF high */
0290         .data_mask = ICE1712_STDSP24_SERIAL_DATA,
0291         .clk_mask = ICE1712_STDSP24_SERIAL_CLOCK,
0292         .cs_mask = ICE1712_STDSP24_AK4524_CS,
0293         .cs_addr = ICE1712_STDSP24_AK4524_CS,
0294         .cs_none = 0,
0295         .add_flags = 0,
0296     };
0297 
0298     int err;
0299     struct snd_akm4xxx *ak;
0300 
0301     /* set the analog DACs */
0302     ice->num_total_dacs = 2;
0303 
0304     /* set the analog ADCs */
0305     ice->num_total_adcs = 2;
0306     
0307     /* analog section */
0308     ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
0309     if (! ak)
0310         return -ENOMEM;
0311     ice->akm_codecs = 1;
0312 
0313     err = snd_ice1712_akm4xxx_init(ak, &akm_stdsp24_mv, &akm_stdsp24_mv_priv, ice);
0314     if (err < 0)
0315         return err;
0316 
0317     /* ak4524 controls */
0318     return snd_ice1712_akm4xxx_build_controls(ice);
0319 }
0320 
0321 static int snd_ice1712_ez8_init(struct snd_ice1712 *ice)
0322 {
0323     ice->gpio.write_mask = ice->eeprom.gpiomask;
0324     ice->gpio.direction = ice->eeprom.gpiodir;
0325     snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ice->eeprom.gpiomask);
0326     snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, ice->eeprom.gpiodir);
0327     snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, ice->eeprom.gpiostate);
0328     return 0;
0329 }
0330 
0331 
0332 /* entry point */
0333 struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] = {
0334     {
0335         .subvendor = ICE1712_SUBDEVICE_STDSP24,
0336         .name = "Hoontech SoundTrack Audio DSP24",
0337         .model = "dsp24",
0338         .chip_init = snd_ice1712_hoontech_init,
0339         .mpu401_1_name = "MIDI-1 Hoontech/STA DSP24",
0340         .mpu401_2_name = "MIDI-2 Hoontech/STA DSP24",
0341     },
0342     {
0343         .subvendor = ICE1712_SUBDEVICE_STDSP24_VALUE,   /* a dummy id */
0344         .name = "Hoontech SoundTrack Audio DSP24 Value",
0345         .model = "dsp24_value",
0346         .chip_init = snd_ice1712_value_init,
0347     },
0348     {
0349         .subvendor = ICE1712_SUBDEVICE_STDSP24_MEDIA7_1,
0350         .name = "Hoontech STA DSP24 Media 7.1",
0351         .model = "dsp24_71",
0352         .chip_init = snd_ice1712_hoontech_init,
0353     },
0354     {
0355         .subvendor = ICE1712_SUBDEVICE_EVENT_EZ8,   /* a dummy id */
0356         .name = "Event Electronics EZ8",
0357         .model = "ez8",
0358         .chip_init = snd_ice1712_ez8_init,
0359     },
0360     {
0361         /* STAudio ADCIII has the same SSID as Hoontech StA DSP24,
0362          * thus identified only via the explicit model option
0363          */
0364         .subvendor = ICE1712_SUBDEVICE_STAUDIO_ADCIII,  /* a dummy id */
0365         .name = "STAudio ADCIII",
0366         .model = "staudio",
0367         .chip_init = snd_ice1712_staudio_init,
0368     },
0369     { } /* terminator */
0370 };