162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *   ALSA driver for ICEnsemble ICE1712 (Envy24)
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *   Lowlevel functions for Hoontech STDSP24
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *	Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/delay.h>
1162306a36Sopenharmony_ci#include <linux/interrupt.h>
1262306a36Sopenharmony_ci#include <linux/init.h>
1362306a36Sopenharmony_ci#include <linux/slab.h>
1462306a36Sopenharmony_ci#include <linux/mutex.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <sound/core.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include "ice1712.h"
1962306a36Sopenharmony_ci#include "hoontech.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/* Hoontech-specific setting */
2262306a36Sopenharmony_cistruct hoontech_spec {
2362306a36Sopenharmony_ci	unsigned char boxbits[4];
2462306a36Sopenharmony_ci	unsigned int config;
2562306a36Sopenharmony_ci	unsigned short boxconfig[4];
2662306a36Sopenharmony_ci};
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic void snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	byte |= ICE1712_STDSP24_CLOCK_BIT;
3162306a36Sopenharmony_ci	udelay(100);
3262306a36Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
3362306a36Sopenharmony_ci	byte &= ~ICE1712_STDSP24_CLOCK_BIT;
3462306a36Sopenharmony_ci	udelay(100);
3562306a36Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
3662306a36Sopenharmony_ci	byte |= ICE1712_STDSP24_CLOCK_BIT;
3762306a36Sopenharmony_ci	udelay(100);
3862306a36Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic void snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	struct hoontech_spec *spec = ice->spec;
4462306a36Sopenharmony_ci	mutex_lock(&ice->gpio_mutex);
4562306a36Sopenharmony_ci	ICE1712_STDSP24_0_DAREAR(spec->boxbits, activate);
4662306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
4762306a36Sopenharmony_ci	mutex_unlock(&ice->gpio_mutex);
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic void snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	struct hoontech_spec *spec = ice->spec;
5362306a36Sopenharmony_ci	mutex_lock(&ice->gpio_mutex);
5462306a36Sopenharmony_ci	ICE1712_STDSP24_3_MUTE(spec->boxbits, activate);
5562306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
5662306a36Sopenharmony_ci	mutex_unlock(&ice->gpio_mutex);
5762306a36Sopenharmony_ci}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistatic void snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	struct hoontech_spec *spec = ice->spec;
6262306a36Sopenharmony_ci	mutex_lock(&ice->gpio_mutex);
6362306a36Sopenharmony_ci	ICE1712_STDSP24_3_INSEL(spec->boxbits, activate);
6462306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
6562306a36Sopenharmony_ci	mutex_unlock(&ice->gpio_mutex);
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic void snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate)
6962306a36Sopenharmony_ci{
7062306a36Sopenharmony_ci	struct hoontech_spec *spec = ice->spec;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	mutex_lock(&ice->gpio_mutex);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	/* select box */
7562306a36Sopenharmony_ci	ICE1712_STDSP24_0_BOX(spec->boxbits, box);
7662306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	/* prepare for write */
7962306a36Sopenharmony_ci	if (chn == 3)
8062306a36Sopenharmony_ci		ICE1712_STDSP24_2_CHN4(spec->boxbits, 0);
8162306a36Sopenharmony_ci	ICE1712_STDSP24_2_MIDI1(spec->boxbits, activate);
8262306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
8362306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
8662306a36Sopenharmony_ci	ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
8762306a36Sopenharmony_ci	ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
8862306a36Sopenharmony_ci	ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
8962306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
9062306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
9162306a36Sopenharmony_ci	udelay(100);
9262306a36Sopenharmony_ci	if (chn == 3) {
9362306a36Sopenharmony_ci		ICE1712_STDSP24_2_CHN4(spec->boxbits, 0);
9462306a36Sopenharmony_ci		snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
9562306a36Sopenharmony_ci	} else {
9662306a36Sopenharmony_ci		switch (chn) {
9762306a36Sopenharmony_ci		case 0:	ICE1712_STDSP24_1_CHN1(spec->boxbits, 0); break;
9862306a36Sopenharmony_ci		case 1:	ICE1712_STDSP24_1_CHN2(spec->boxbits, 0); break;
9962306a36Sopenharmony_ci		case 2:	ICE1712_STDSP24_1_CHN3(spec->boxbits, 0); break;
10062306a36Sopenharmony_ci		}
10162306a36Sopenharmony_ci		snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
10262306a36Sopenharmony_ci	}
10362306a36Sopenharmony_ci	udelay(100);
10462306a36Sopenharmony_ci	ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
10562306a36Sopenharmony_ci	ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
10662306a36Sopenharmony_ci	ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
10762306a36Sopenharmony_ci	ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
10862306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
10962306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
11062306a36Sopenharmony_ci	udelay(100);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0);
11362306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	mutex_unlock(&ice->gpio_mutex);
11662306a36Sopenharmony_ci}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_cistatic void snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	struct hoontech_spec *spec = ice->spec;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	mutex_lock(&ice->gpio_mutex);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	/* select box */
12562306a36Sopenharmony_ci	ICE1712_STDSP24_0_BOX(spec->boxbits, box);
12662306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
12962306a36Sopenharmony_ci	ICE1712_STDSP24_2_MIDI1(spec->boxbits, master);
13062306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
13162306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	udelay(100);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 0);
13662306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	mdelay(10);
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
14162306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	mutex_unlock(&ice->gpio_mutex);
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic void snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	struct hoontech_spec *spec = ice->spec;
14962306a36Sopenharmony_ci	mutex_lock(&ice->gpio_mutex);
15062306a36Sopenharmony_ci	ICE1712_STDSP24_3_MIDI2(spec->boxbits, activate);
15162306a36Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
15262306a36Sopenharmony_ci	mutex_unlock(&ice->gpio_mutex);
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic int hoontech_init(struct snd_ice1712 *ice, bool staudio)
15662306a36Sopenharmony_ci{
15762306a36Sopenharmony_ci	struct hoontech_spec *spec;
15862306a36Sopenharmony_ci	int box, chn;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	ice->num_total_dacs = 8;
16162306a36Sopenharmony_ci	ice->num_total_adcs = 8;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
16462306a36Sopenharmony_ci	if (!spec)
16562306a36Sopenharmony_ci		return -ENOMEM;
16662306a36Sopenharmony_ci	ice->spec = spec;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	ICE1712_STDSP24_SET_ADDR(spec->boxbits, 0);
16962306a36Sopenharmony_ci	ICE1712_STDSP24_CLOCK(spec->boxbits, 0, 1);
17062306a36Sopenharmony_ci	ICE1712_STDSP24_0_BOX(spec->boxbits, 0);
17162306a36Sopenharmony_ci	ICE1712_STDSP24_0_DAREAR(spec->boxbits, 0);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	ICE1712_STDSP24_SET_ADDR(spec->boxbits, 1);
17462306a36Sopenharmony_ci	ICE1712_STDSP24_CLOCK(spec->boxbits, 1, 1);
17562306a36Sopenharmony_ci	ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
17662306a36Sopenharmony_ci	ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
17762306a36Sopenharmony_ci	ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	ICE1712_STDSP24_SET_ADDR(spec->boxbits, 2);
18062306a36Sopenharmony_ci	ICE1712_STDSP24_CLOCK(spec->boxbits, 2, 1);
18162306a36Sopenharmony_ci	ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
18262306a36Sopenharmony_ci	ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
18362306a36Sopenharmony_ci	ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	ICE1712_STDSP24_SET_ADDR(spec->boxbits, 3);
18662306a36Sopenharmony_ci	ICE1712_STDSP24_CLOCK(spec->boxbits, 3, 1);
18762306a36Sopenharmony_ci	ICE1712_STDSP24_3_MIDI2(spec->boxbits, 0);
18862306a36Sopenharmony_ci	ICE1712_STDSP24_3_MUTE(spec->boxbits, 1);
18962306a36Sopenharmony_ci	ICE1712_STDSP24_3_INSEL(spec->boxbits, 0);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	/* let's go - activate only functions in first box */
19262306a36Sopenharmony_ci	if (staudio)
19362306a36Sopenharmony_ci		spec->config = ICE1712_STDSP24_MUTE;
19462306a36Sopenharmony_ci	else
19562306a36Sopenharmony_ci		spec->config = 0;
19662306a36Sopenharmony_ci			    /* ICE1712_STDSP24_MUTE |
19762306a36Sopenharmony_ci			       ICE1712_STDSP24_INSEL |
19862306a36Sopenharmony_ci			       ICE1712_STDSP24_DAREAR; */
19962306a36Sopenharmony_ci	/*  These boxconfigs have caused problems in the past.
20062306a36Sopenharmony_ci	 *  The code is not optimal, but should now enable a working config to
20162306a36Sopenharmony_ci	 *  be achieved.
20262306a36Sopenharmony_ci	 *  ** MIDI IN can only be configured on one box **
20362306a36Sopenharmony_ci	 *  ICE1712_STDSP24_BOX_MIDI1 needs to be set for that box.
20462306a36Sopenharmony_ci	 *  Tests on a ADAC2000 box suggest the box config flags do not
20562306a36Sopenharmony_ci	 *  work as would be expected, and the inputs are crossed.
20662306a36Sopenharmony_ci	 *  Setting ICE1712_STDSP24_BOX_MIDI1 and ICE1712_STDSP24_BOX_MIDI2
20762306a36Sopenharmony_ci	 *  on the same box connects MIDI-In to both 401 uarts; both outputs
20862306a36Sopenharmony_ci	 *  are then active on all boxes.
20962306a36Sopenharmony_ci	 *  The default config here sets up everything on the first box.
21062306a36Sopenharmony_ci	 *  Alan Horstmann  5.2.2008
21162306a36Sopenharmony_ci	 */
21262306a36Sopenharmony_ci	spec->boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 |
21362306a36Sopenharmony_ci				     ICE1712_STDSP24_BOX_CHN2 |
21462306a36Sopenharmony_ci				     ICE1712_STDSP24_BOX_CHN3 |
21562306a36Sopenharmony_ci				     ICE1712_STDSP24_BOX_CHN4 |
21662306a36Sopenharmony_ci				     ICE1712_STDSP24_BOX_MIDI1 |
21762306a36Sopenharmony_ci				     ICE1712_STDSP24_BOX_MIDI2;
21862306a36Sopenharmony_ci	if (staudio) {
21962306a36Sopenharmony_ci		spec->boxconfig[1] =
22062306a36Sopenharmony_ci		spec->boxconfig[2] =
22162306a36Sopenharmony_ci		spec->boxconfig[3] = spec->boxconfig[0];
22262306a36Sopenharmony_ci	} else {
22362306a36Sopenharmony_ci		spec->boxconfig[1] =
22462306a36Sopenharmony_ci		spec->boxconfig[2] =
22562306a36Sopenharmony_ci		spec->boxconfig[3] = 0;
22662306a36Sopenharmony_ci	}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	snd_ice1712_stdsp24_darear(ice,
22962306a36Sopenharmony_ci		(spec->config & ICE1712_STDSP24_DAREAR) ? 1 : 0);
23062306a36Sopenharmony_ci	snd_ice1712_stdsp24_mute(ice,
23162306a36Sopenharmony_ci		(spec->config & ICE1712_STDSP24_MUTE) ? 1 : 0);
23262306a36Sopenharmony_ci	snd_ice1712_stdsp24_insel(ice,
23362306a36Sopenharmony_ci		(spec->config & ICE1712_STDSP24_INSEL) ? 1 : 0);
23462306a36Sopenharmony_ci	for (box = 0; box < 4; box++) {
23562306a36Sopenharmony_ci		if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2)
23662306a36Sopenharmony_ci                        snd_ice1712_stdsp24_midi2(ice, 1);
23762306a36Sopenharmony_ci		for (chn = 0; chn < 4; chn++)
23862306a36Sopenharmony_ci			snd_ice1712_stdsp24_box_channel(ice, box, chn,
23962306a36Sopenharmony_ci				(spec->boxconfig[box] & (1 << chn)) ? 1 : 0);
24062306a36Sopenharmony_ci		if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1)
24162306a36Sopenharmony_ci			snd_ice1712_stdsp24_box_midi(ice, box, 1);
24262306a36Sopenharmony_ci	}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	return 0;
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_cistatic int snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	return hoontech_init(ice, false);
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_cistatic int snd_ice1712_staudio_init(struct snd_ice1712 *ice)
25362306a36Sopenharmony_ci{
25462306a36Sopenharmony_ci	return hoontech_init(ice, true);
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci/*
25862306a36Sopenharmony_ci * AK4524 access
25962306a36Sopenharmony_ci */
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci/* start callback for STDSP24 with modified hardware */
26262306a36Sopenharmony_cistatic void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	struct snd_ice1712 *ice = ak->private_data[0];
26562306a36Sopenharmony_ci	unsigned char tmp;
26662306a36Sopenharmony_ci	snd_ice1712_save_gpio_status(ice);
26762306a36Sopenharmony_ci	tmp =	ICE1712_STDSP24_SERIAL_DATA |
26862306a36Sopenharmony_ci		ICE1712_STDSP24_SERIAL_CLOCK |
26962306a36Sopenharmony_ci		ICE1712_STDSP24_AK4524_CS;
27062306a36Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION,
27162306a36Sopenharmony_ci			  ice->gpio.direction | tmp);
27262306a36Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp);
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistatic int snd_ice1712_value_init(struct snd_ice1712 *ice)
27662306a36Sopenharmony_ci{
27762306a36Sopenharmony_ci	/* Hoontech STDSP24 with modified hardware */
27862306a36Sopenharmony_ci	static const struct snd_akm4xxx akm_stdsp24_mv = {
27962306a36Sopenharmony_ci		.num_adcs = 2,
28062306a36Sopenharmony_ci		.num_dacs = 2,
28162306a36Sopenharmony_ci		.type = SND_AK4524,
28262306a36Sopenharmony_ci		.ops = {
28362306a36Sopenharmony_ci			.lock = stdsp24_ak4524_lock
28462306a36Sopenharmony_ci		}
28562306a36Sopenharmony_ci	};
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	static const struct snd_ak4xxx_private akm_stdsp24_mv_priv = {
28862306a36Sopenharmony_ci		.caddr = 2,
28962306a36Sopenharmony_ci		.cif = 1, /* CIF high */
29062306a36Sopenharmony_ci		.data_mask = ICE1712_STDSP24_SERIAL_DATA,
29162306a36Sopenharmony_ci		.clk_mask = ICE1712_STDSP24_SERIAL_CLOCK,
29262306a36Sopenharmony_ci		.cs_mask = ICE1712_STDSP24_AK4524_CS,
29362306a36Sopenharmony_ci		.cs_addr = ICE1712_STDSP24_AK4524_CS,
29462306a36Sopenharmony_ci		.cs_none = 0,
29562306a36Sopenharmony_ci		.add_flags = 0,
29662306a36Sopenharmony_ci	};
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	int err;
29962306a36Sopenharmony_ci	struct snd_akm4xxx *ak;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	/* set the analog DACs */
30262306a36Sopenharmony_ci	ice->num_total_dacs = 2;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	/* set the analog ADCs */
30562306a36Sopenharmony_ci	ice->num_total_adcs = 2;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	/* analog section */
30862306a36Sopenharmony_ci	ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
30962306a36Sopenharmony_ci	if (! ak)
31062306a36Sopenharmony_ci		return -ENOMEM;
31162306a36Sopenharmony_ci	ice->akm_codecs = 1;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	err = snd_ice1712_akm4xxx_init(ak, &akm_stdsp24_mv, &akm_stdsp24_mv_priv, ice);
31462306a36Sopenharmony_ci	if (err < 0)
31562306a36Sopenharmony_ci		return err;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	/* ak4524 controls */
31862306a36Sopenharmony_ci	return snd_ice1712_akm4xxx_build_controls(ice);
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic int snd_ice1712_ez8_init(struct snd_ice1712 *ice)
32262306a36Sopenharmony_ci{
32362306a36Sopenharmony_ci	ice->gpio.write_mask = ice->eeprom.gpiomask;
32462306a36Sopenharmony_ci	ice->gpio.direction = ice->eeprom.gpiodir;
32562306a36Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ice->eeprom.gpiomask);
32662306a36Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, ice->eeprom.gpiodir);
32762306a36Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, ice->eeprom.gpiostate);
32862306a36Sopenharmony_ci	return 0;
32962306a36Sopenharmony_ci}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci/* entry point */
33362306a36Sopenharmony_cistruct snd_ice1712_card_info snd_ice1712_hoontech_cards[] = {
33462306a36Sopenharmony_ci	{
33562306a36Sopenharmony_ci		.subvendor = ICE1712_SUBDEVICE_STDSP24,
33662306a36Sopenharmony_ci		.name = "Hoontech SoundTrack Audio DSP24",
33762306a36Sopenharmony_ci		.model = "dsp24",
33862306a36Sopenharmony_ci		.chip_init = snd_ice1712_hoontech_init,
33962306a36Sopenharmony_ci		.mpu401_1_name = "MIDI-1 Hoontech/STA DSP24",
34062306a36Sopenharmony_ci		.mpu401_2_name = "MIDI-2 Hoontech/STA DSP24",
34162306a36Sopenharmony_ci	},
34262306a36Sopenharmony_ci	{
34362306a36Sopenharmony_ci		.subvendor = ICE1712_SUBDEVICE_STDSP24_VALUE,	/* a dummy id */
34462306a36Sopenharmony_ci		.name = "Hoontech SoundTrack Audio DSP24 Value",
34562306a36Sopenharmony_ci		.model = "dsp24_value",
34662306a36Sopenharmony_ci		.chip_init = snd_ice1712_value_init,
34762306a36Sopenharmony_ci	},
34862306a36Sopenharmony_ci	{
34962306a36Sopenharmony_ci		.subvendor = ICE1712_SUBDEVICE_STDSP24_MEDIA7_1,
35062306a36Sopenharmony_ci		.name = "Hoontech STA DSP24 Media 7.1",
35162306a36Sopenharmony_ci		.model = "dsp24_71",
35262306a36Sopenharmony_ci		.chip_init = snd_ice1712_hoontech_init,
35362306a36Sopenharmony_ci	},
35462306a36Sopenharmony_ci	{
35562306a36Sopenharmony_ci		.subvendor = ICE1712_SUBDEVICE_EVENT_EZ8,	/* a dummy id */
35662306a36Sopenharmony_ci		.name = "Event Electronics EZ8",
35762306a36Sopenharmony_ci		.model = "ez8",
35862306a36Sopenharmony_ci		.chip_init = snd_ice1712_ez8_init,
35962306a36Sopenharmony_ci	},
36062306a36Sopenharmony_ci	{
36162306a36Sopenharmony_ci		/* STAudio ADCIII has the same SSID as Hoontech StA DSP24,
36262306a36Sopenharmony_ci		 * thus identified only via the explicit model option
36362306a36Sopenharmony_ci		 */
36462306a36Sopenharmony_ci		.subvendor = ICE1712_SUBDEVICE_STAUDIO_ADCIII,	/* a dummy id */
36562306a36Sopenharmony_ci		.name = "STAudio ADCIII",
36662306a36Sopenharmony_ci		.model = "staudio",
36762306a36Sopenharmony_ci		.chip_init = snd_ice1712_staudio_init,
36862306a36Sopenharmony_ci	},
36962306a36Sopenharmony_ci	{ } /* terminator */
37062306a36Sopenharmony_ci};
371