Linux Audio

Check our new training course

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