18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *   ALSA driver for ICEnsemble ICE1712 (Envy24)
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *   Lowlevel functions for Hoontech STDSP24
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci *	Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/delay.h>
118c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
128c2ecf20Sopenharmony_ci#include <linux/init.h>
138c2ecf20Sopenharmony_ci#include <linux/slab.h>
148c2ecf20Sopenharmony_ci#include <linux/mutex.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <sound/core.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "ice1712.h"
198c2ecf20Sopenharmony_ci#include "hoontech.h"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci/* Hoontech-specific setting */
228c2ecf20Sopenharmony_cistruct hoontech_spec {
238c2ecf20Sopenharmony_ci	unsigned char boxbits[4];
248c2ecf20Sopenharmony_ci	unsigned int config;
258c2ecf20Sopenharmony_ci	unsigned short boxconfig[4];
268c2ecf20Sopenharmony_ci};
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic void snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte)
298c2ecf20Sopenharmony_ci{
308c2ecf20Sopenharmony_ci	byte |= ICE1712_STDSP24_CLOCK_BIT;
318c2ecf20Sopenharmony_ci	udelay(100);
328c2ecf20Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
338c2ecf20Sopenharmony_ci	byte &= ~ICE1712_STDSP24_CLOCK_BIT;
348c2ecf20Sopenharmony_ci	udelay(100);
358c2ecf20Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
368c2ecf20Sopenharmony_ci	byte |= ICE1712_STDSP24_CLOCK_BIT;
378c2ecf20Sopenharmony_ci	udelay(100);
388c2ecf20Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
398c2ecf20Sopenharmony_ci}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic void snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	struct hoontech_spec *spec = ice->spec;
448c2ecf20Sopenharmony_ci	mutex_lock(&ice->gpio_mutex);
458c2ecf20Sopenharmony_ci	ICE1712_STDSP24_0_DAREAR(spec->boxbits, activate);
468c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
478c2ecf20Sopenharmony_ci	mutex_unlock(&ice->gpio_mutex);
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic void snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	struct hoontech_spec *spec = ice->spec;
538c2ecf20Sopenharmony_ci	mutex_lock(&ice->gpio_mutex);
548c2ecf20Sopenharmony_ci	ICE1712_STDSP24_3_MUTE(spec->boxbits, activate);
558c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
568c2ecf20Sopenharmony_ci	mutex_unlock(&ice->gpio_mutex);
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic void snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	struct hoontech_spec *spec = ice->spec;
628c2ecf20Sopenharmony_ci	mutex_lock(&ice->gpio_mutex);
638c2ecf20Sopenharmony_ci	ICE1712_STDSP24_3_INSEL(spec->boxbits, activate);
648c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
658c2ecf20Sopenharmony_ci	mutex_unlock(&ice->gpio_mutex);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic void snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	struct hoontech_spec *spec = ice->spec;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	mutex_lock(&ice->gpio_mutex);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	/* select box */
758c2ecf20Sopenharmony_ci	ICE1712_STDSP24_0_BOX(spec->boxbits, box);
768c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	/* prepare for write */
798c2ecf20Sopenharmony_ci	if (chn == 3)
808c2ecf20Sopenharmony_ci		ICE1712_STDSP24_2_CHN4(spec->boxbits, 0);
818c2ecf20Sopenharmony_ci	ICE1712_STDSP24_2_MIDI1(spec->boxbits, activate);
828c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
838c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
868c2ecf20Sopenharmony_ci	ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
878c2ecf20Sopenharmony_ci	ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
888c2ecf20Sopenharmony_ci	ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
898c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
908c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
918c2ecf20Sopenharmony_ci	udelay(100);
928c2ecf20Sopenharmony_ci	if (chn == 3) {
938c2ecf20Sopenharmony_ci		ICE1712_STDSP24_2_CHN4(spec->boxbits, 0);
948c2ecf20Sopenharmony_ci		snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
958c2ecf20Sopenharmony_ci	} else {
968c2ecf20Sopenharmony_ci		switch (chn) {
978c2ecf20Sopenharmony_ci		case 0:	ICE1712_STDSP24_1_CHN1(spec->boxbits, 0); break;
988c2ecf20Sopenharmony_ci		case 1:	ICE1712_STDSP24_1_CHN2(spec->boxbits, 0); break;
998c2ecf20Sopenharmony_ci		case 2:	ICE1712_STDSP24_1_CHN3(spec->boxbits, 0); break;
1008c2ecf20Sopenharmony_ci		}
1018c2ecf20Sopenharmony_ci		snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
1028c2ecf20Sopenharmony_ci	}
1038c2ecf20Sopenharmony_ci	udelay(100);
1048c2ecf20Sopenharmony_ci	ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
1058c2ecf20Sopenharmony_ci	ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
1068c2ecf20Sopenharmony_ci	ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
1078c2ecf20Sopenharmony_ci	ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
1088c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
1098c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
1108c2ecf20Sopenharmony_ci	udelay(100);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0);
1138c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	mutex_unlock(&ice->gpio_mutex);
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic void snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master)
1198c2ecf20Sopenharmony_ci{
1208c2ecf20Sopenharmony_ci	struct hoontech_spec *spec = ice->spec;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	mutex_lock(&ice->gpio_mutex);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	/* select box */
1258c2ecf20Sopenharmony_ci	ICE1712_STDSP24_0_BOX(spec->boxbits, box);
1268c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
1298c2ecf20Sopenharmony_ci	ICE1712_STDSP24_2_MIDI1(spec->boxbits, master);
1308c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
1318c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	udelay(100);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 0);
1368c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	mdelay(10);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
1418c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	mutex_unlock(&ice->gpio_mutex);
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic void snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	struct hoontech_spec *spec = ice->spec;
1498c2ecf20Sopenharmony_ci	mutex_lock(&ice->gpio_mutex);
1508c2ecf20Sopenharmony_ci	ICE1712_STDSP24_3_MIDI2(spec->boxbits, activate);
1518c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
1528c2ecf20Sopenharmony_ci	mutex_unlock(&ice->gpio_mutex);
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_cistatic int hoontech_init(struct snd_ice1712 *ice, bool staudio)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	struct hoontech_spec *spec;
1588c2ecf20Sopenharmony_ci	int box, chn;
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	ice->num_total_dacs = 8;
1618c2ecf20Sopenharmony_ci	ice->num_total_adcs = 8;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1648c2ecf20Sopenharmony_ci	if (!spec)
1658c2ecf20Sopenharmony_ci		return -ENOMEM;
1668c2ecf20Sopenharmony_ci	ice->spec = spec;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	ICE1712_STDSP24_SET_ADDR(spec->boxbits, 0);
1698c2ecf20Sopenharmony_ci	ICE1712_STDSP24_CLOCK(spec->boxbits, 0, 1);
1708c2ecf20Sopenharmony_ci	ICE1712_STDSP24_0_BOX(spec->boxbits, 0);
1718c2ecf20Sopenharmony_ci	ICE1712_STDSP24_0_DAREAR(spec->boxbits, 0);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	ICE1712_STDSP24_SET_ADDR(spec->boxbits, 1);
1748c2ecf20Sopenharmony_ci	ICE1712_STDSP24_CLOCK(spec->boxbits, 1, 1);
1758c2ecf20Sopenharmony_ci	ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
1768c2ecf20Sopenharmony_ci	ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
1778c2ecf20Sopenharmony_ci	ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	ICE1712_STDSP24_SET_ADDR(spec->boxbits, 2);
1808c2ecf20Sopenharmony_ci	ICE1712_STDSP24_CLOCK(spec->boxbits, 2, 1);
1818c2ecf20Sopenharmony_ci	ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
1828c2ecf20Sopenharmony_ci	ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
1838c2ecf20Sopenharmony_ci	ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0);
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	ICE1712_STDSP24_SET_ADDR(spec->boxbits, 3);
1868c2ecf20Sopenharmony_ci	ICE1712_STDSP24_CLOCK(spec->boxbits, 3, 1);
1878c2ecf20Sopenharmony_ci	ICE1712_STDSP24_3_MIDI2(spec->boxbits, 0);
1888c2ecf20Sopenharmony_ci	ICE1712_STDSP24_3_MUTE(spec->boxbits, 1);
1898c2ecf20Sopenharmony_ci	ICE1712_STDSP24_3_INSEL(spec->boxbits, 0);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	/* let's go - activate only functions in first box */
1928c2ecf20Sopenharmony_ci	if (staudio)
1938c2ecf20Sopenharmony_ci		spec->config = ICE1712_STDSP24_MUTE;
1948c2ecf20Sopenharmony_ci	else
1958c2ecf20Sopenharmony_ci		spec->config = 0;
1968c2ecf20Sopenharmony_ci			    /* ICE1712_STDSP24_MUTE |
1978c2ecf20Sopenharmony_ci			       ICE1712_STDSP24_INSEL |
1988c2ecf20Sopenharmony_ci			       ICE1712_STDSP24_DAREAR; */
1998c2ecf20Sopenharmony_ci	/*  These boxconfigs have caused problems in the past.
2008c2ecf20Sopenharmony_ci	 *  The code is not optimal, but should now enable a working config to
2018c2ecf20Sopenharmony_ci	 *  be achieved.
2028c2ecf20Sopenharmony_ci	 *  ** MIDI IN can only be configured on one box **
2038c2ecf20Sopenharmony_ci	 *  ICE1712_STDSP24_BOX_MIDI1 needs to be set for that box.
2048c2ecf20Sopenharmony_ci	 *  Tests on a ADAC2000 box suggest the box config flags do not
2058c2ecf20Sopenharmony_ci	 *  work as would be expected, and the inputs are crossed.
2068c2ecf20Sopenharmony_ci	 *  Setting ICE1712_STDSP24_BOX_MIDI1 and ICE1712_STDSP24_BOX_MIDI2
2078c2ecf20Sopenharmony_ci	 *  on the same box connects MIDI-In to both 401 uarts; both outputs
2088c2ecf20Sopenharmony_ci	 *  are then active on all boxes.
2098c2ecf20Sopenharmony_ci	 *  The default config here sets up everything on the first box.
2108c2ecf20Sopenharmony_ci	 *  Alan Horstmann  5.2.2008
2118c2ecf20Sopenharmony_ci	 */
2128c2ecf20Sopenharmony_ci	spec->boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 |
2138c2ecf20Sopenharmony_ci				     ICE1712_STDSP24_BOX_CHN2 |
2148c2ecf20Sopenharmony_ci				     ICE1712_STDSP24_BOX_CHN3 |
2158c2ecf20Sopenharmony_ci				     ICE1712_STDSP24_BOX_CHN4 |
2168c2ecf20Sopenharmony_ci				     ICE1712_STDSP24_BOX_MIDI1 |
2178c2ecf20Sopenharmony_ci				     ICE1712_STDSP24_BOX_MIDI2;
2188c2ecf20Sopenharmony_ci	if (staudio) {
2198c2ecf20Sopenharmony_ci		spec->boxconfig[1] =
2208c2ecf20Sopenharmony_ci		spec->boxconfig[2] =
2218c2ecf20Sopenharmony_ci		spec->boxconfig[3] = spec->boxconfig[0];
2228c2ecf20Sopenharmony_ci	} else {
2238c2ecf20Sopenharmony_ci		spec->boxconfig[1] =
2248c2ecf20Sopenharmony_ci		spec->boxconfig[2] =
2258c2ecf20Sopenharmony_ci		spec->boxconfig[3] = 0;
2268c2ecf20Sopenharmony_ci	}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_darear(ice,
2298c2ecf20Sopenharmony_ci		(spec->config & ICE1712_STDSP24_DAREAR) ? 1 : 0);
2308c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_mute(ice,
2318c2ecf20Sopenharmony_ci		(spec->config & ICE1712_STDSP24_MUTE) ? 1 : 0);
2328c2ecf20Sopenharmony_ci	snd_ice1712_stdsp24_insel(ice,
2338c2ecf20Sopenharmony_ci		(spec->config & ICE1712_STDSP24_INSEL) ? 1 : 0);
2348c2ecf20Sopenharmony_ci	for (box = 0; box < 4; box++) {
2358c2ecf20Sopenharmony_ci		if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2)
2368c2ecf20Sopenharmony_ci                        snd_ice1712_stdsp24_midi2(ice, 1);
2378c2ecf20Sopenharmony_ci		for (chn = 0; chn < 4; chn++)
2388c2ecf20Sopenharmony_ci			snd_ice1712_stdsp24_box_channel(ice, box, chn,
2398c2ecf20Sopenharmony_ci				(spec->boxconfig[box] & (1 << chn)) ? 1 : 0);
2408c2ecf20Sopenharmony_ci		if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1)
2418c2ecf20Sopenharmony_ci			snd_ice1712_stdsp24_box_midi(ice, box, 1);
2428c2ecf20Sopenharmony_ci	}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	return 0;
2458c2ecf20Sopenharmony_ci}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_cistatic int snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
2488c2ecf20Sopenharmony_ci{
2498c2ecf20Sopenharmony_ci	return hoontech_init(ice, false);
2508c2ecf20Sopenharmony_ci}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_cistatic int snd_ice1712_staudio_init(struct snd_ice1712 *ice)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	return hoontech_init(ice, true);
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci/*
2588c2ecf20Sopenharmony_ci * AK4524 access
2598c2ecf20Sopenharmony_ci */
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci/* start callback for STDSP24 with modified hardware */
2628c2ecf20Sopenharmony_cistatic void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci	struct snd_ice1712 *ice = ak->private_data[0];
2658c2ecf20Sopenharmony_ci	unsigned char tmp;
2668c2ecf20Sopenharmony_ci	snd_ice1712_save_gpio_status(ice);
2678c2ecf20Sopenharmony_ci	tmp =	ICE1712_STDSP24_SERIAL_DATA |
2688c2ecf20Sopenharmony_ci		ICE1712_STDSP24_SERIAL_CLOCK |
2698c2ecf20Sopenharmony_ci		ICE1712_STDSP24_AK4524_CS;
2708c2ecf20Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION,
2718c2ecf20Sopenharmony_ci			  ice->gpio.direction | tmp);
2728c2ecf20Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp);
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic int snd_ice1712_value_init(struct snd_ice1712 *ice)
2768c2ecf20Sopenharmony_ci{
2778c2ecf20Sopenharmony_ci	/* Hoontech STDSP24 with modified hardware */
2788c2ecf20Sopenharmony_ci	static const struct snd_akm4xxx akm_stdsp24_mv = {
2798c2ecf20Sopenharmony_ci		.num_adcs = 2,
2808c2ecf20Sopenharmony_ci		.num_dacs = 2,
2818c2ecf20Sopenharmony_ci		.type = SND_AK4524,
2828c2ecf20Sopenharmony_ci		.ops = {
2838c2ecf20Sopenharmony_ci			.lock = stdsp24_ak4524_lock
2848c2ecf20Sopenharmony_ci		}
2858c2ecf20Sopenharmony_ci	};
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	static const struct snd_ak4xxx_private akm_stdsp24_mv_priv = {
2888c2ecf20Sopenharmony_ci		.caddr = 2,
2898c2ecf20Sopenharmony_ci		.cif = 1, /* CIF high */
2908c2ecf20Sopenharmony_ci		.data_mask = ICE1712_STDSP24_SERIAL_DATA,
2918c2ecf20Sopenharmony_ci		.clk_mask = ICE1712_STDSP24_SERIAL_CLOCK,
2928c2ecf20Sopenharmony_ci		.cs_mask = ICE1712_STDSP24_AK4524_CS,
2938c2ecf20Sopenharmony_ci		.cs_addr = ICE1712_STDSP24_AK4524_CS,
2948c2ecf20Sopenharmony_ci		.cs_none = 0,
2958c2ecf20Sopenharmony_ci		.add_flags = 0,
2968c2ecf20Sopenharmony_ci	};
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	int err;
2998c2ecf20Sopenharmony_ci	struct snd_akm4xxx *ak;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	/* set the analog DACs */
3028c2ecf20Sopenharmony_ci	ice->num_total_dacs = 2;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	/* set the analog ADCs */
3058c2ecf20Sopenharmony_ci	ice->num_total_adcs = 2;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	/* analog section */
3088c2ecf20Sopenharmony_ci	ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
3098c2ecf20Sopenharmony_ci	if (! ak)
3108c2ecf20Sopenharmony_ci		return -ENOMEM;
3118c2ecf20Sopenharmony_ci	ice->akm_codecs = 1;
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	err = snd_ice1712_akm4xxx_init(ak, &akm_stdsp24_mv, &akm_stdsp24_mv_priv, ice);
3148c2ecf20Sopenharmony_ci	if (err < 0)
3158c2ecf20Sopenharmony_ci		return err;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	/* ak4524 controls */
3188c2ecf20Sopenharmony_ci	return snd_ice1712_akm4xxx_build_controls(ice);
3198c2ecf20Sopenharmony_ci}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_cistatic int snd_ice1712_ez8_init(struct snd_ice1712 *ice)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	ice->gpio.write_mask = ice->eeprom.gpiomask;
3248c2ecf20Sopenharmony_ci	ice->gpio.direction = ice->eeprom.gpiodir;
3258c2ecf20Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ice->eeprom.gpiomask);
3268c2ecf20Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, ice->eeprom.gpiodir);
3278c2ecf20Sopenharmony_ci	snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, ice->eeprom.gpiostate);
3288c2ecf20Sopenharmony_ci	return 0;
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci/* entry point */
3338c2ecf20Sopenharmony_cistruct snd_ice1712_card_info snd_ice1712_hoontech_cards[] = {
3348c2ecf20Sopenharmony_ci	{
3358c2ecf20Sopenharmony_ci		.subvendor = ICE1712_SUBDEVICE_STDSP24,
3368c2ecf20Sopenharmony_ci		.name = "Hoontech SoundTrack Audio DSP24",
3378c2ecf20Sopenharmony_ci		.model = "dsp24",
3388c2ecf20Sopenharmony_ci		.chip_init = snd_ice1712_hoontech_init,
3398c2ecf20Sopenharmony_ci		.mpu401_1_name = "MIDI-1 Hoontech/STA DSP24",
3408c2ecf20Sopenharmony_ci		.mpu401_2_name = "MIDI-2 Hoontech/STA DSP24",
3418c2ecf20Sopenharmony_ci	},
3428c2ecf20Sopenharmony_ci	{
3438c2ecf20Sopenharmony_ci		.subvendor = ICE1712_SUBDEVICE_STDSP24_VALUE,	/* a dummy id */
3448c2ecf20Sopenharmony_ci		.name = "Hoontech SoundTrack Audio DSP24 Value",
3458c2ecf20Sopenharmony_ci		.model = "dsp24_value",
3468c2ecf20Sopenharmony_ci		.chip_init = snd_ice1712_value_init,
3478c2ecf20Sopenharmony_ci	},
3488c2ecf20Sopenharmony_ci	{
3498c2ecf20Sopenharmony_ci		.subvendor = ICE1712_SUBDEVICE_STDSP24_MEDIA7_1,
3508c2ecf20Sopenharmony_ci		.name = "Hoontech STA DSP24 Media 7.1",
3518c2ecf20Sopenharmony_ci		.model = "dsp24_71",
3528c2ecf20Sopenharmony_ci		.chip_init = snd_ice1712_hoontech_init,
3538c2ecf20Sopenharmony_ci	},
3548c2ecf20Sopenharmony_ci	{
3558c2ecf20Sopenharmony_ci		.subvendor = ICE1712_SUBDEVICE_EVENT_EZ8,	/* a dummy id */
3568c2ecf20Sopenharmony_ci		.name = "Event Electronics EZ8",
3578c2ecf20Sopenharmony_ci		.model = "ez8",
3588c2ecf20Sopenharmony_ci		.chip_init = snd_ice1712_ez8_init,
3598c2ecf20Sopenharmony_ci	},
3608c2ecf20Sopenharmony_ci	{
3618c2ecf20Sopenharmony_ci		/* STAudio ADCIII has the same SSID as Hoontech StA DSP24,
3628c2ecf20Sopenharmony_ci		 * thus identified only via the explicit model option
3638c2ecf20Sopenharmony_ci		 */
3648c2ecf20Sopenharmony_ci		.subvendor = ICE1712_SUBDEVICE_STAUDIO_ADCIII,	/* a dummy id */
3658c2ecf20Sopenharmony_ci		.name = "STAudio ADCIII",
3668c2ecf20Sopenharmony_ci		.model = "staudio",
3678c2ecf20Sopenharmony_ci		.chip_init = snd_ice1712_staudio_init,
3688c2ecf20Sopenharmony_ci	},
3698c2ecf20Sopenharmony_ci	{ } /* terminator */
3708c2ecf20Sopenharmony_ci};
371