1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * ALSA driver for ICEnsemble ICE1712 (Envy24)
5 * Lowlevel functions for Hoontech STDSP24
7 * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
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>
16 #include <sound/core.h>
21 /* Hoontech-specific setting */
22 struct hoontech_spec
{
23 unsigned char boxbits
[4];
25 unsigned short boxconfig
[4];
28 static void snd_ice1712_stdsp24_gpio_write(struct snd_ice1712
*ice
, unsigned char byte
)
30 byte
|= ICE1712_STDSP24_CLOCK_BIT
;
32 snd_ice1712_write(ice
, ICE1712_IREG_GPIO_DATA
, byte
);
33 byte
&= ~ICE1712_STDSP24_CLOCK_BIT
;
35 snd_ice1712_write(ice
, ICE1712_IREG_GPIO_DATA
, byte
);
36 byte
|= ICE1712_STDSP24_CLOCK_BIT
;
38 snd_ice1712_write(ice
, ICE1712_IREG_GPIO_DATA
, byte
);
41 static void snd_ice1712_stdsp24_darear(struct snd_ice1712
*ice
, int activate
)
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
);
50 static void snd_ice1712_stdsp24_mute(struct snd_ice1712
*ice
, int activate
)
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
);
59 static void snd_ice1712_stdsp24_insel(struct snd_ice1712
*ice
, int activate
)
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
);
68 static void snd_ice1712_stdsp24_box_channel(struct snd_ice1712
*ice
, int box
, int chn
, int activate
)
70 struct hoontech_spec
*spec
= ice
->spec
;
72 mutex_lock(&ice
->gpio_mutex
);
75 ICE1712_STDSP24_0_BOX(spec
->boxbits
, box
);
76 snd_ice1712_stdsp24_gpio_write(ice
, spec
->boxbits
[0]);
78 /* prepare for write */
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]);
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]);
93 ICE1712_STDSP24_2_CHN4(spec
->boxbits
, 0);
94 snd_ice1712_stdsp24_gpio_write(ice
, spec
->boxbits
[2]);
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;
101 snd_ice1712_stdsp24_gpio_write(ice
, spec
->boxbits
[1]);
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]);
112 ICE1712_STDSP24_2_MIDI1(spec
->boxbits
, 0);
113 snd_ice1712_stdsp24_gpio_write(ice
, spec
->boxbits
[2]);
115 mutex_unlock(&ice
->gpio_mutex
);
118 static void snd_ice1712_stdsp24_box_midi(struct snd_ice1712
*ice
, int box
, int master
)
120 struct hoontech_spec
*spec
= ice
->spec
;
122 mutex_lock(&ice
->gpio_mutex
);
125 ICE1712_STDSP24_0_BOX(spec
->boxbits
, box
);
126 snd_ice1712_stdsp24_gpio_write(ice
, spec
->boxbits
[0]);
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]);
135 ICE1712_STDSP24_2_MIDIIN(spec
->boxbits
, 0);
136 snd_ice1712_stdsp24_gpio_write(ice
, spec
->boxbits
[2]);
140 ICE1712_STDSP24_2_MIDIIN(spec
->boxbits
, 1);
141 snd_ice1712_stdsp24_gpio_write(ice
, spec
->boxbits
[2]);
143 mutex_unlock(&ice
->gpio_mutex
);
146 static void snd_ice1712_stdsp24_midi2(struct snd_ice1712
*ice
, int activate
)
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
);
155 static int hoontech_init(struct snd_ice1712
*ice
, bool staudio
)
157 struct hoontech_spec
*spec
;
160 ice
->num_total_dacs
= 8;
161 ice
->num_total_adcs
= 8;
163 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
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);
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);
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);
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);
191 /* let's go - activate only functions in first box */
193 spec
->config
= ICE1712_STDSP24_MUTE
;
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
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
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
;
221 spec
->boxconfig
[3] = spec
->boxconfig
[0];
225 spec
->boxconfig
[3] = 0;
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);
247 static int snd_ice1712_hoontech_init(struct snd_ice1712
*ice
)
249 return hoontech_init(ice
, false);
252 static int snd_ice1712_staudio_init(struct snd_ice1712
*ice
)
254 return hoontech_init(ice
, true);
261 /* start callback for STDSP24 with modified hardware */
262 static void stdsp24_ak4524_lock(struct snd_akm4xxx
*ak
, int chip
)
264 struct snd_ice1712
*ice
= ak
->private_data
[0];
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
);
275 static int snd_ice1712_value_init(struct snd_ice1712
*ice
)
277 /* Hoontech STDSP24 with modified hardware */
278 static const struct snd_akm4xxx akm_stdsp24_mv
= {
283 .lock
= stdsp24_ak4524_lock
287 static const struct snd_ak4xxx_private akm_stdsp24_mv_priv
= {
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
,
299 struct snd_akm4xxx
*ak
;
301 /* set the analog DACs */
302 ice
->num_total_dacs
= 2;
304 /* set the analog ADCs */
305 ice
->num_total_adcs
= 2;
308 ak
= ice
->akm
= kmalloc(sizeof(struct snd_akm4xxx
), GFP_KERNEL
);
313 err
= snd_ice1712_akm4xxx_init(ak
, &akm_stdsp24_mv
, &akm_stdsp24_mv_priv
, ice
);
317 /* ak4524 controls */
318 return snd_ice1712_akm4xxx_build_controls(ice
);
321 static int snd_ice1712_ez8_init(struct snd_ice1712
*ice
)
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
);
333 struct snd_ice1712_card_info snd_ice1712_hoontech_cards
[] = {
335 .subvendor
= ICE1712_SUBDEVICE_STDSP24
,
336 .name
= "Hoontech SoundTrack Audio 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",
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
,
349 .subvendor
= ICE1712_SUBDEVICE_STDSP24_MEDIA7_1
,
350 .name
= "Hoontech STA DSP24 Media 7.1",
352 .chip_init
= snd_ice1712_hoontech_init
,
355 .subvendor
= ICE1712_SUBDEVICE_EVENT_EZ8
, /* a dummy id */
356 .name
= "Event Electronics EZ8",
358 .chip_init
= snd_ice1712_ez8_init
,
361 /* STAudio ADCIII has the same SSID as Hoontech StA DSP24,
362 * thus identified only via the explicit model option
364 .subvendor
= ICE1712_SUBDEVICE_STAUDIO_ADCIII
, /* a dummy id */
365 .name
= "STAudio ADCIII",
367 .chip_init
= snd_ice1712_staudio_init
,