xref: /openbmc/linux/sound/pci/echoaudio/gina24_dsp.c (revision 762f99f4f3cb41a775b5157dd761217beba65873)
1dd7b254dSGiuliano Pochini /****************************************************************************
2dd7b254dSGiuliano Pochini 
3dd7b254dSGiuliano Pochini    Copyright Echo Digital Audio Corporation (c) 1998 - 2004
4dd7b254dSGiuliano Pochini    All rights reserved
5dd7b254dSGiuliano Pochini    www.echoaudio.com
6dd7b254dSGiuliano Pochini 
7dd7b254dSGiuliano Pochini    This file is part of Echo Digital Audio's generic driver library.
8dd7b254dSGiuliano Pochini 
9dd7b254dSGiuliano Pochini    Echo Digital Audio's generic driver library is free software;
10dd7b254dSGiuliano Pochini    you can redistribute it and/or modify it under the terms of
11dd7b254dSGiuliano Pochini    the GNU General Public License as published by the Free Software
12dd7b254dSGiuliano Pochini    Foundation.
13dd7b254dSGiuliano Pochini 
14dd7b254dSGiuliano Pochini    This program is distributed in the hope that it will be useful,
15dd7b254dSGiuliano Pochini    but WITHOUT ANY WARRANTY; without even the implied warranty of
16dd7b254dSGiuliano Pochini    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17dd7b254dSGiuliano Pochini    GNU General Public License for more details.
18dd7b254dSGiuliano Pochini 
19dd7b254dSGiuliano Pochini    You should have received a copy of the GNU General Public License
20dd7b254dSGiuliano Pochini    along with this program; if not, write to the Free Software
21dd7b254dSGiuliano Pochini    Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22dd7b254dSGiuliano Pochini    MA  02111-1307, USA.
23dd7b254dSGiuliano Pochini 
24dd7b254dSGiuliano Pochini    *************************************************************************
25dd7b254dSGiuliano Pochini 
26dd7b254dSGiuliano Pochini  Translation from C++ and adaptation for use in ALSA-Driver
27dd7b254dSGiuliano Pochini  were made by Giuliano Pochini <pochini@shiny.it>
28dd7b254dSGiuliano Pochini 
29dd7b254dSGiuliano Pochini ****************************************************************************/
30dd7b254dSGiuliano Pochini 
31dd7b254dSGiuliano Pochini 
32dd7b254dSGiuliano Pochini static int write_control_reg(struct echoaudio *chip, u32 value, char force);
33dd7b254dSGiuliano Pochini static int set_input_clock(struct echoaudio *chip, u16 clock);
34dd7b254dSGiuliano Pochini static int set_professional_spdif(struct echoaudio *chip, char prof);
35dd7b254dSGiuliano Pochini static int set_digital_mode(struct echoaudio *chip, u8 mode);
3619b50063SGiuliano Pochini static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic);
37dd7b254dSGiuliano Pochini static int check_asic_status(struct echoaudio *chip);
38dd7b254dSGiuliano Pochini 
39dd7b254dSGiuliano Pochini 
init_hw(struct echoaudio * chip,u16 device_id,u16 subdevice_id)40dd7b254dSGiuliano Pochini static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
41dd7b254dSGiuliano Pochini {
42dd7b254dSGiuliano Pochini 	int err;
43dd7b254dSGiuliano Pochini 
44da3cec35STakashi Iwai 	if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA24))
45da3cec35STakashi Iwai 		return -ENODEV;
46dd7b254dSGiuliano Pochini 
47*549717fcSTakashi Iwai 	err = init_dsp_comm_page(chip);
48*549717fcSTakashi Iwai 	if (err) {
49b5b4a41bSSudip Mukherjee 		dev_err(chip->card->dev,
50b5b4a41bSSudip Mukherjee 			"init_hw - could not initialize DSP comm page\n");
51dd7b254dSGiuliano Pochini 		return err;
52dd7b254dSGiuliano Pochini 	}
53dd7b254dSGiuliano Pochini 
54dd7b254dSGiuliano Pochini 	chip->device_id = device_id;
55dd7b254dSGiuliano Pochini 	chip->subdevice_id = subdevice_id;
563f6175ecSMark Brown 	chip->bad_board = true;
57dd7b254dSGiuliano Pochini 	chip->input_clock_types =
58dd7b254dSGiuliano Pochini 		ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF |
59dd7b254dSGiuliano Pochini 		ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96 |
60dd7b254dSGiuliano Pochini 		ECHO_CLOCK_BIT_ADAT;
61dd7b254dSGiuliano Pochini 
62dd7b254dSGiuliano Pochini 	/* Gina24 comes in both '301 and '361 flavors */
63dd7b254dSGiuliano Pochini 	if (chip->device_id == DEVICE_ID_56361) {
6419b50063SGiuliano Pochini 		chip->dsp_code_to_load = FW_GINA24_361_DSP;
65dd7b254dSGiuliano Pochini 		chip->digital_modes =
66dd7b254dSGiuliano Pochini 			ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
67dd7b254dSGiuliano Pochini 			ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
68dd7b254dSGiuliano Pochini 			ECHOCAPS_HAS_DIGITAL_MODE_ADAT;
69dd7b254dSGiuliano Pochini 	} else {
7019b50063SGiuliano Pochini 		chip->dsp_code_to_load = FW_GINA24_301_DSP;
71dd7b254dSGiuliano Pochini 		chip->digital_modes =
72dd7b254dSGiuliano Pochini 			ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA |
73dd7b254dSGiuliano Pochini 			ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL |
74dd7b254dSGiuliano Pochini 			ECHOCAPS_HAS_DIGITAL_MODE_ADAT |
75dd7b254dSGiuliano Pochini 			ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_CDROM;
76dd7b254dSGiuliano Pochini 	}
77dd7b254dSGiuliano Pochini 
78*549717fcSTakashi Iwai 	err = load_firmware(chip);
79*549717fcSTakashi Iwai 	if (err < 0)
80dd7b254dSGiuliano Pochini 		return err;
813f6175ecSMark Brown 	chip->bad_board = false;
82dd7b254dSGiuliano Pochini 
83dd7b254dSGiuliano Pochini 	return err;
84dd7b254dSGiuliano Pochini }
85dd7b254dSGiuliano Pochini 
86dd7b254dSGiuliano Pochini 
87dd7b254dSGiuliano Pochini 
set_mixer_defaults(struct echoaudio * chip)88ad3499f4SGiuliano Pochini static int set_mixer_defaults(struct echoaudio *chip)
89ad3499f4SGiuliano Pochini {
90ad3499f4SGiuliano Pochini 	chip->digital_mode = DIGITAL_MODE_SPDIF_RCA;
913f6175ecSMark Brown 	chip->professional_spdif = false;
923f6175ecSMark Brown 	chip->digital_in_automute = true;
93ad3499f4SGiuliano Pochini 	return init_line_levels(chip);
94ad3499f4SGiuliano Pochini }
95ad3499f4SGiuliano Pochini 
96ad3499f4SGiuliano Pochini 
97ad3499f4SGiuliano Pochini 
detect_input_clocks(const struct echoaudio * chip)98dd7b254dSGiuliano Pochini static u32 detect_input_clocks(const struct echoaudio *chip)
99dd7b254dSGiuliano Pochini {
100dd7b254dSGiuliano Pochini 	u32 clocks_from_dsp, clock_bits;
101dd7b254dSGiuliano Pochini 
102dd7b254dSGiuliano Pochini 	/* Map the DSP clock detect bits to the generic driver clock
103dd7b254dSGiuliano Pochini 	   detect bits */
104dd7b254dSGiuliano Pochini 	clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
105dd7b254dSGiuliano Pochini 
106dd7b254dSGiuliano Pochini 	clock_bits = ECHO_CLOCK_BIT_INTERNAL;
107dd7b254dSGiuliano Pochini 
108dd7b254dSGiuliano Pochini 	if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF)
109dd7b254dSGiuliano Pochini 		clock_bits |= ECHO_CLOCK_BIT_SPDIF;
110dd7b254dSGiuliano Pochini 
111dd7b254dSGiuliano Pochini 	if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT)
112dd7b254dSGiuliano Pochini 		clock_bits |= ECHO_CLOCK_BIT_ADAT;
113dd7b254dSGiuliano Pochini 
114dd7b254dSGiuliano Pochini 	if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ESYNC)
115dd7b254dSGiuliano Pochini 		clock_bits |= ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96;
116dd7b254dSGiuliano Pochini 
117dd7b254dSGiuliano Pochini 	return clock_bits;
118dd7b254dSGiuliano Pochini }
119dd7b254dSGiuliano Pochini 
120dd7b254dSGiuliano Pochini 
121dd7b254dSGiuliano Pochini 
122dd7b254dSGiuliano Pochini /* Gina24 has an ASIC on the PCI card which must be loaded for anything
123dd7b254dSGiuliano Pochini interesting to happen. */
load_asic(struct echoaudio * chip)124dd7b254dSGiuliano Pochini static int load_asic(struct echoaudio *chip)
125dd7b254dSGiuliano Pochini {
126dd7b254dSGiuliano Pochini 	u32 control_reg;
127dd7b254dSGiuliano Pochini 	int err;
12819b50063SGiuliano Pochini 	short asic;
129dd7b254dSGiuliano Pochini 
130dd7b254dSGiuliano Pochini 	if (chip->asic_loaded)
131dd7b254dSGiuliano Pochini 		return 1;
132dd7b254dSGiuliano Pochini 
133dd7b254dSGiuliano Pochini 	/* Give the DSP a few milliseconds to settle down */
134dd7b254dSGiuliano Pochini 	mdelay(10);
135dd7b254dSGiuliano Pochini 
136dd7b254dSGiuliano Pochini 	/* Pick the correct ASIC for '301 or '361 Gina24 */
137dd7b254dSGiuliano Pochini 	if (chip->device_id == DEVICE_ID_56361)
13819b50063SGiuliano Pochini 		asic = FW_GINA24_361_ASIC;
139dd7b254dSGiuliano Pochini 	else
14019b50063SGiuliano Pochini 		asic = FW_GINA24_301_ASIC;
141dd7b254dSGiuliano Pochini 
14219b50063SGiuliano Pochini 	err = load_asic_generic(chip, DSP_FNC_LOAD_GINA24_ASIC, asic);
14319b50063SGiuliano Pochini 	if (err < 0)
144dd7b254dSGiuliano Pochini 		return err;
145dd7b254dSGiuliano Pochini 
14619b50063SGiuliano Pochini 	chip->asic_code = asic;
147dd7b254dSGiuliano Pochini 
148dd7b254dSGiuliano Pochini 	/* Now give the new ASIC a little time to set up */
149dd7b254dSGiuliano Pochini 	mdelay(10);
150dd7b254dSGiuliano Pochini 	/* See if it worked */
151dd7b254dSGiuliano Pochini 	err = check_asic_status(chip);
152dd7b254dSGiuliano Pochini 
153dd7b254dSGiuliano Pochini 	/* Set up the control register if the load succeeded -
154dd7b254dSGiuliano Pochini 	   48 kHz, internal clock, S/PDIF RCA mode */
155dd7b254dSGiuliano Pochini 	if (!err) {
156dd7b254dSGiuliano Pochini 		control_reg = GML_CONVERTER_ENABLE | GML_48KHZ;
1573f6175ecSMark Brown 		err = write_control_reg(chip, control_reg, true);
158dd7b254dSGiuliano Pochini 	}
159dd7b254dSGiuliano Pochini 	return err;
160dd7b254dSGiuliano Pochini }
161dd7b254dSGiuliano Pochini 
162dd7b254dSGiuliano Pochini 
163dd7b254dSGiuliano Pochini 
set_sample_rate(struct echoaudio * chip,u32 rate)164dd7b254dSGiuliano Pochini static int set_sample_rate(struct echoaudio *chip, u32 rate)
165dd7b254dSGiuliano Pochini {
166dd7b254dSGiuliano Pochini 	u32 control_reg, clock;
167dd7b254dSGiuliano Pochini 
168da3cec35STakashi Iwai 	if (snd_BUG_ON(rate >= 50000 &&
169da3cec35STakashi Iwai 		       chip->digital_mode == DIGITAL_MODE_ADAT))
170da3cec35STakashi Iwai 		return -EINVAL;
171dd7b254dSGiuliano Pochini 
172dd7b254dSGiuliano Pochini 	/* Only set the clock for internal mode. */
173dd7b254dSGiuliano Pochini 	if (chip->input_clock != ECHO_CLOCK_INTERNAL) {
174b5b4a41bSSudip Mukherjee 		dev_warn(chip->card->dev,
175b5b4a41bSSudip Mukherjee 			 "Cannot set sample rate - clock not set to CLK_CLOCKININTERNAL\n");
176dd7b254dSGiuliano Pochini 		/* Save the rate anyhow */
177dd7b254dSGiuliano Pochini 		chip->comm_page->sample_rate = cpu_to_le32(rate);
178dd7b254dSGiuliano Pochini 		chip->sample_rate = rate;
179dd7b254dSGiuliano Pochini 		return 0;
180dd7b254dSGiuliano Pochini 	}
181dd7b254dSGiuliano Pochini 
182dd7b254dSGiuliano Pochini 	clock = 0;
183dd7b254dSGiuliano Pochini 
184dd7b254dSGiuliano Pochini 	control_reg = le32_to_cpu(chip->comm_page->control_register);
185dd7b254dSGiuliano Pochini 	control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK;
186dd7b254dSGiuliano Pochini 
187dd7b254dSGiuliano Pochini 	switch (rate) {
188dd7b254dSGiuliano Pochini 	case 96000:
189dd7b254dSGiuliano Pochini 		clock = GML_96KHZ;
190dd7b254dSGiuliano Pochini 		break;
191dd7b254dSGiuliano Pochini 	case 88200:
192dd7b254dSGiuliano Pochini 		clock = GML_88KHZ;
193dd7b254dSGiuliano Pochini 		break;
194dd7b254dSGiuliano Pochini 	case 48000:
195dd7b254dSGiuliano Pochini 		clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1;
196dd7b254dSGiuliano Pochini 		break;
197dd7b254dSGiuliano Pochini 	case 44100:
198dd7b254dSGiuliano Pochini 		clock = GML_44KHZ;
199dd7b254dSGiuliano Pochini 		/* Professional mode ? */
200dd7b254dSGiuliano Pochini 		if (control_reg & GML_SPDIF_PRO_MODE)
201dd7b254dSGiuliano Pochini 			clock |= GML_SPDIF_SAMPLE_RATE0;
202dd7b254dSGiuliano Pochini 		break;
203dd7b254dSGiuliano Pochini 	case 32000:
204dd7b254dSGiuliano Pochini 		clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 |
205dd7b254dSGiuliano Pochini 			GML_SPDIF_SAMPLE_RATE1;
206dd7b254dSGiuliano Pochini 		break;
207dd7b254dSGiuliano Pochini 	case 22050:
208dd7b254dSGiuliano Pochini 		clock = GML_22KHZ;
209dd7b254dSGiuliano Pochini 		break;
210dd7b254dSGiuliano Pochini 	case 16000:
211dd7b254dSGiuliano Pochini 		clock = GML_16KHZ;
212dd7b254dSGiuliano Pochini 		break;
213dd7b254dSGiuliano Pochini 	case 11025:
214dd7b254dSGiuliano Pochini 		clock = GML_11KHZ;
215dd7b254dSGiuliano Pochini 		break;
216dd7b254dSGiuliano Pochini 	case 8000:
217dd7b254dSGiuliano Pochini 		clock = GML_8KHZ;
218dd7b254dSGiuliano Pochini 		break;
219dd7b254dSGiuliano Pochini 	default:
220b5b4a41bSSudip Mukherjee 		dev_err(chip->card->dev,
221b5b4a41bSSudip Mukherjee 			"set_sample_rate: %d invalid!\n", rate);
222dd7b254dSGiuliano Pochini 		return -EINVAL;
223dd7b254dSGiuliano Pochini 	}
224dd7b254dSGiuliano Pochini 
225dd7b254dSGiuliano Pochini 	control_reg |= clock;
226dd7b254dSGiuliano Pochini 
227dd7b254dSGiuliano Pochini 	chip->comm_page->sample_rate = cpu_to_le32(rate);	/* ignored by the DSP */
228dd7b254dSGiuliano Pochini 	chip->sample_rate = rate;
229b5b4a41bSSudip Mukherjee 	dev_dbg(chip->card->dev, "set_sample_rate: %d clock %d\n", rate, clock);
230dd7b254dSGiuliano Pochini 
2313f6175ecSMark Brown 	return write_control_reg(chip, control_reg, false);
232dd7b254dSGiuliano Pochini }
233dd7b254dSGiuliano Pochini 
234dd7b254dSGiuliano Pochini 
235dd7b254dSGiuliano Pochini 
set_input_clock(struct echoaudio * chip,u16 clock)236dd7b254dSGiuliano Pochini static int set_input_clock(struct echoaudio *chip, u16 clock)
237dd7b254dSGiuliano Pochini {
238dd7b254dSGiuliano Pochini 	u32 control_reg, clocks_from_dsp;
239dd7b254dSGiuliano Pochini 
240dd7b254dSGiuliano Pochini 
241dd7b254dSGiuliano Pochini 	/* Mask off the clock select bits */
242dd7b254dSGiuliano Pochini 	control_reg = le32_to_cpu(chip->comm_page->control_register) &
243dd7b254dSGiuliano Pochini 		GML_CLOCK_CLEAR_MASK;
244dd7b254dSGiuliano Pochini 	clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks);
245dd7b254dSGiuliano Pochini 
246dd7b254dSGiuliano Pochini 	switch (clock) {
247dd7b254dSGiuliano Pochini 	case ECHO_CLOCK_INTERNAL:
248dd7b254dSGiuliano Pochini 		chip->input_clock = ECHO_CLOCK_INTERNAL;
249dd7b254dSGiuliano Pochini 		return set_sample_rate(chip, chip->sample_rate);
250dd7b254dSGiuliano Pochini 	case ECHO_CLOCK_SPDIF:
251dd7b254dSGiuliano Pochini 		if (chip->digital_mode == DIGITAL_MODE_ADAT)
252dd7b254dSGiuliano Pochini 			return -EAGAIN;
253dd7b254dSGiuliano Pochini 		control_reg |= GML_SPDIF_CLOCK;
254dd7b254dSGiuliano Pochini 		if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF96)
255dd7b254dSGiuliano Pochini 			control_reg |= GML_DOUBLE_SPEED_MODE;
256dd7b254dSGiuliano Pochini 		else
257dd7b254dSGiuliano Pochini 			control_reg &= ~GML_DOUBLE_SPEED_MODE;
258dd7b254dSGiuliano Pochini 		break;
259dd7b254dSGiuliano Pochini 	case ECHO_CLOCK_ADAT:
260dd7b254dSGiuliano Pochini 		if (chip->digital_mode != DIGITAL_MODE_ADAT)
261dd7b254dSGiuliano Pochini 			return -EAGAIN;
262dd7b254dSGiuliano Pochini 		control_reg |= GML_ADAT_CLOCK;
263dd7b254dSGiuliano Pochini 		control_reg &= ~GML_DOUBLE_SPEED_MODE;
264dd7b254dSGiuliano Pochini 		break;
265dd7b254dSGiuliano Pochini 	case ECHO_CLOCK_ESYNC:
266dd7b254dSGiuliano Pochini 		control_reg |= GML_ESYNC_CLOCK;
267dd7b254dSGiuliano Pochini 		control_reg &= ~GML_DOUBLE_SPEED_MODE;
268dd7b254dSGiuliano Pochini 		break;
269dd7b254dSGiuliano Pochini 	case ECHO_CLOCK_ESYNC96:
270dd7b254dSGiuliano Pochini 		control_reg |= GML_ESYNC_CLOCK | GML_DOUBLE_SPEED_MODE;
271dd7b254dSGiuliano Pochini 		break;
272dd7b254dSGiuliano Pochini 	default:
273b5b4a41bSSudip Mukherjee 		dev_err(chip->card->dev,
274b5b4a41bSSudip Mukherjee 			"Input clock 0x%x not supported for Gina24\n", clock);
275dd7b254dSGiuliano Pochini 		return -EINVAL;
276dd7b254dSGiuliano Pochini 	}
277dd7b254dSGiuliano Pochini 
278dd7b254dSGiuliano Pochini 	chip->input_clock = clock;
2793f6175ecSMark Brown 	return write_control_reg(chip, control_reg, true);
280dd7b254dSGiuliano Pochini }
281dd7b254dSGiuliano Pochini 
282dd7b254dSGiuliano Pochini 
283dd7b254dSGiuliano Pochini 
dsp_set_digital_mode(struct echoaudio * chip,u8 mode)284dd7b254dSGiuliano Pochini static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode)
285dd7b254dSGiuliano Pochini {
286dd7b254dSGiuliano Pochini 	u32 control_reg;
287dd7b254dSGiuliano Pochini 	int err, incompatible_clock;
288dd7b254dSGiuliano Pochini 
289dd7b254dSGiuliano Pochini 	/* Set clock to "internal" if it's not compatible with the new mode */
2903f6175ecSMark Brown 	incompatible_clock = false;
291dd7b254dSGiuliano Pochini 	switch (mode) {
292dd7b254dSGiuliano Pochini 	case DIGITAL_MODE_SPDIF_OPTICAL:
293dd7b254dSGiuliano Pochini 	case DIGITAL_MODE_SPDIF_CDROM:
294dd7b254dSGiuliano Pochini 	case DIGITAL_MODE_SPDIF_RCA:
295dd7b254dSGiuliano Pochini 		if (chip->input_clock == ECHO_CLOCK_ADAT)
2963f6175ecSMark Brown 			incompatible_clock = true;
297dd7b254dSGiuliano Pochini 		break;
298dd7b254dSGiuliano Pochini 	case DIGITAL_MODE_ADAT:
299dd7b254dSGiuliano Pochini 		if (chip->input_clock == ECHO_CLOCK_SPDIF)
3003f6175ecSMark Brown 			incompatible_clock = true;
301dd7b254dSGiuliano Pochini 		break;
302dd7b254dSGiuliano Pochini 	default:
303b5b4a41bSSudip Mukherjee 		dev_err(chip->card->dev,
304b5b4a41bSSudip Mukherjee 			"Digital mode not supported: %d\n", mode);
305dd7b254dSGiuliano Pochini 		return -EINVAL;
306dd7b254dSGiuliano Pochini 	}
307dd7b254dSGiuliano Pochini 
308dd7b254dSGiuliano Pochini 	spin_lock_irq(&chip->lock);
309dd7b254dSGiuliano Pochini 
310dd7b254dSGiuliano Pochini 	if (incompatible_clock) {	/* Switch to 48KHz, internal */
311dd7b254dSGiuliano Pochini 		chip->sample_rate = 48000;
312dd7b254dSGiuliano Pochini 		set_input_clock(chip, ECHO_CLOCK_INTERNAL);
313dd7b254dSGiuliano Pochini 	}
314dd7b254dSGiuliano Pochini 
315dd7b254dSGiuliano Pochini 	/* Clear the current digital mode */
316dd7b254dSGiuliano Pochini 	control_reg = le32_to_cpu(chip->comm_page->control_register);
317dd7b254dSGiuliano Pochini 	control_reg &= GML_DIGITAL_MODE_CLEAR_MASK;
318dd7b254dSGiuliano Pochini 
319dd7b254dSGiuliano Pochini 	/* Tweak the control reg */
320dd7b254dSGiuliano Pochini 	switch (mode) {
321dd7b254dSGiuliano Pochini 	case DIGITAL_MODE_SPDIF_OPTICAL:
322dd7b254dSGiuliano Pochini 		control_reg |= GML_SPDIF_OPTICAL_MODE;
323dd7b254dSGiuliano Pochini 		break;
324dd7b254dSGiuliano Pochini 	case DIGITAL_MODE_SPDIF_CDROM:
325dd7b254dSGiuliano Pochini 		/* '361 Gina24 cards do not have the S/PDIF CD-ROM mode */
326dd7b254dSGiuliano Pochini 		if (chip->device_id == DEVICE_ID_56301)
327dd7b254dSGiuliano Pochini 			control_reg |= GML_SPDIF_CDROM_MODE;
328dd7b254dSGiuliano Pochini 		break;
329dd7b254dSGiuliano Pochini 	case DIGITAL_MODE_SPDIF_RCA:
330dd7b254dSGiuliano Pochini 		/* GML_SPDIF_OPTICAL_MODE bit cleared */
331dd7b254dSGiuliano Pochini 		break;
332dd7b254dSGiuliano Pochini 	case DIGITAL_MODE_ADAT:
333dd7b254dSGiuliano Pochini 		control_reg |= GML_ADAT_MODE;
334dd7b254dSGiuliano Pochini 		control_reg &= ~GML_DOUBLE_SPEED_MODE;
335dd7b254dSGiuliano Pochini 		break;
336dd7b254dSGiuliano Pochini 	}
337dd7b254dSGiuliano Pochini 
3383f6175ecSMark Brown 	err = write_control_reg(chip, control_reg, true);
339dd7b254dSGiuliano Pochini 	spin_unlock_irq(&chip->lock);
340dd7b254dSGiuliano Pochini 	if (err < 0)
341dd7b254dSGiuliano Pochini 		return err;
342dd7b254dSGiuliano Pochini 	chip->digital_mode = mode;
343dd7b254dSGiuliano Pochini 
344b5b4a41bSSudip Mukherjee 	dev_dbg(chip->card->dev,
345b5b4a41bSSudip Mukherjee 		"set_digital_mode to %d\n", chip->digital_mode);
346dd7b254dSGiuliano Pochini 	return incompatible_clock;
347dd7b254dSGiuliano Pochini }
348