xref: /openbmc/linux/sound/pci/pcxhr/pcxhr_hwdep.c (revision 4327ad25)
11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2e12229b4SMarkus Bollinger /*
3e12229b4SMarkus Bollinger  * Driver for Digigram pcxhr compatible soundcards
4e12229b4SMarkus Bollinger  *
5e12229b4SMarkus Bollinger  * hwdep device manager
6e12229b4SMarkus Bollinger  *
7e12229b4SMarkus Bollinger  * Copyright (c) 2004 by Digigram <alsa@digigram.com>
8e12229b4SMarkus Bollinger  */
9e12229b4SMarkus Bollinger 
10e12229b4SMarkus Bollinger #include <linux/interrupt.h>
11e12229b4SMarkus Bollinger #include <linux/vmalloc.h>
12e12229b4SMarkus Bollinger #include <linux/firmware.h>
13e12229b4SMarkus Bollinger #include <linux/pci.h>
14da155d5bSPaul Gortmaker #include <linux/module.h>
156cbbfe1cSTakashi Iwai #include <linux/io.h>
16e12229b4SMarkus Bollinger #include <sound/core.h>
17e12229b4SMarkus Bollinger #include <sound/hwdep.h>
18e12229b4SMarkus Bollinger #include "pcxhr.h"
19e12229b4SMarkus Bollinger #include "pcxhr_mixer.h"
20e12229b4SMarkus Bollinger #include "pcxhr_hwdep.h"
21e12229b4SMarkus Bollinger #include "pcxhr_core.h"
227628700eSMarkus Bollinger #include "pcxhr_mix22.h"
23e12229b4SMarkus Bollinger 
24e12229b4SMarkus Bollinger 
257628700eSMarkus Bollinger static int pcxhr_sub_init(struct pcxhr_mgr *mgr);
26e12229b4SMarkus Bollinger /*
27e12229b4SMarkus Bollinger  * get basic information and init pcxhr card
28e12229b4SMarkus Bollinger  */
pcxhr_init_board(struct pcxhr_mgr * mgr)29e12229b4SMarkus Bollinger static int pcxhr_init_board(struct pcxhr_mgr *mgr)
30e12229b4SMarkus Bollinger {
31e12229b4SMarkus Bollinger 	int err;
32e12229b4SMarkus Bollinger 	struct pcxhr_rmh rmh;
33e12229b4SMarkus Bollinger 	int card_streams;
34e12229b4SMarkus Bollinger 
35e12229b4SMarkus Bollinger 	/* calc the number of all streams used */
36e12229b4SMarkus Bollinger 	if (mgr->mono_capture)
37e12229b4SMarkus Bollinger 		card_streams = mgr->capture_chips * 2;
38e12229b4SMarkus Bollinger 	else
39e12229b4SMarkus Bollinger 		card_streams = mgr->capture_chips;
40e12229b4SMarkus Bollinger 	card_streams += mgr->playback_chips * PCXHR_PLAYBACK_STREAMS;
41e12229b4SMarkus Bollinger 
42e12229b4SMarkus Bollinger 	/* enable interrupts */
43e12229b4SMarkus Bollinger 	pcxhr_enable_dsp(mgr);
44e12229b4SMarkus Bollinger 
45e12229b4SMarkus Bollinger 	pcxhr_init_rmh(&rmh, CMD_SUPPORTED);
46e12229b4SMarkus Bollinger 	err = pcxhr_send_msg(mgr, &rmh);
47e12229b4SMarkus Bollinger 	if (err)
48e12229b4SMarkus Bollinger 		return err;
498c3f1b1cSMarkus Bollinger 	/* test 4, 8 or 12 phys out */
508c3f1b1cSMarkus Bollinger 	if ((rmh.stat[0] & MASK_FIRST_FIELD) < mgr->playback_chips * 2)
51da3cec35STakashi Iwai 		return -EINVAL;
528c3f1b1cSMarkus Bollinger 	/* test 4, 8 or 2 phys in */
537628700eSMarkus Bollinger 	if (((rmh.stat[0] >> (2 * FIELD_SIZE)) & MASK_FIRST_FIELD) <
54da3cec35STakashi Iwai 	    mgr->capture_chips * 2)
55da3cec35STakashi Iwai 		return -EINVAL;
56e12229b4SMarkus Bollinger 	/* test max nb substream per board */
57da3cec35STakashi Iwai 	if ((rmh.stat[1] & 0x5F) < card_streams)
58da3cec35STakashi Iwai 		return -EINVAL;
59e12229b4SMarkus Bollinger 	/* test max nb substream per pipe */
60da3cec35STakashi Iwai 	if (((rmh.stat[1] >> 7) & 0x5F) < PCXHR_PLAYBACK_STREAMS)
61da3cec35STakashi Iwai 		return -EINVAL;
62b59bb8efSTakashi Iwai 	dev_dbg(&mgr->pci->dev,
63b59bb8efSTakashi Iwai 		"supported formats : playback=%x capture=%x\n",
647628700eSMarkus Bollinger 		    rmh.stat[2], rmh.stat[3]);
65e12229b4SMarkus Bollinger 
66e12229b4SMarkus Bollinger 	pcxhr_init_rmh(&rmh, CMD_VERSION);
67e12229b4SMarkus Bollinger 	/* firmware num for DSP */
68e12229b4SMarkus Bollinger 	rmh.cmd[0] |= mgr->firmware_num;
69e12229b4SMarkus Bollinger 	/* transfer granularity in samples (should be multiple of 48) */
707628700eSMarkus Bollinger 	rmh.cmd[1] = (1<<23) + mgr->granularity;
71e12229b4SMarkus Bollinger 	rmh.cmd_len = 2;
72e12229b4SMarkus Bollinger 	err = pcxhr_send_msg(mgr, &rmh);
73e12229b4SMarkus Bollinger 	if (err)
74e12229b4SMarkus Bollinger 		return err;
75b59bb8efSTakashi Iwai 	dev_dbg(&mgr->pci->dev,
76b59bb8efSTakashi Iwai 		"PCXHR DSP version is %d.%d.%d\n", (rmh.stat[0]>>16)&0xff,
777628700eSMarkus Bollinger 		    (rmh.stat[0]>>8)&0xff, rmh.stat[0]&0xff);
78e12229b4SMarkus Bollinger 	mgr->dsp_version = rmh.stat[0];
79e12229b4SMarkus Bollinger 
807628700eSMarkus Bollinger 	if (mgr->is_hr_stereo)
817628700eSMarkus Bollinger 		err = hr222_sub_init(mgr);
827628700eSMarkus Bollinger 	else
837628700eSMarkus Bollinger 		err = pcxhr_sub_init(mgr);
847628700eSMarkus Bollinger 	return err;
857628700eSMarkus Bollinger }
867628700eSMarkus Bollinger 
pcxhr_sub_init(struct pcxhr_mgr * mgr)877628700eSMarkus Bollinger static int pcxhr_sub_init(struct pcxhr_mgr *mgr)
887628700eSMarkus Bollinger {
897628700eSMarkus Bollinger 	int err;
907628700eSMarkus Bollinger 	struct pcxhr_rmh rmh;
917628700eSMarkus Bollinger 
92e12229b4SMarkus Bollinger 	/* get options */
93e12229b4SMarkus Bollinger 	pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
94e12229b4SMarkus Bollinger 	rmh.cmd[0] |= IO_NUM_REG_STATUS;
95e12229b4SMarkus Bollinger 	rmh.cmd[1]  = REG_STATUS_OPTIONS;
96e12229b4SMarkus Bollinger 	rmh.cmd_len = 2;
97e12229b4SMarkus Bollinger 	err = pcxhr_send_msg(mgr, &rmh);
98e12229b4SMarkus Bollinger 	if (err)
99e12229b4SMarkus Bollinger 		return err;
100e12229b4SMarkus Bollinger 
1017628700eSMarkus Bollinger 	if ((rmh.stat[1] & REG_STATUS_OPT_DAUGHTER_MASK) ==
1027628700eSMarkus Bollinger 	    REG_STATUS_OPT_ANALOG_BOARD)
1037628700eSMarkus Bollinger 		mgr->board_has_analog = 1;	/* analog addon board found */
104e12229b4SMarkus Bollinger 
105e12229b4SMarkus Bollinger 	/* unmute inputs */
106e12229b4SMarkus Bollinger 	err = pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS,
107e12229b4SMarkus Bollinger 					  REG_CONT_UNMUTE_INPUTS, NULL);
108e12229b4SMarkus Bollinger 	if (err)
109e12229b4SMarkus Bollinger 		return err;
1107628700eSMarkus Bollinger 	/* unmute outputs (a write to IO_NUM_REG_MUTE_OUT mutes!) */
1117628700eSMarkus Bollinger 	pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
112e12229b4SMarkus Bollinger 	rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
1137628700eSMarkus Bollinger 	if (DSP_EXT_CMD_SET(mgr)) {
1147628700eSMarkus Bollinger 		rmh.cmd[1]  = 1;	/* unmute digital plugs */
1157628700eSMarkus Bollinger 		rmh.cmd_len = 2;
1167628700eSMarkus Bollinger 	}
117e12229b4SMarkus Bollinger 	err = pcxhr_send_msg(mgr, &rmh);
118e12229b4SMarkus Bollinger 	return err;
119e12229b4SMarkus Bollinger }
120e12229b4SMarkus Bollinger 
pcxhr_reset_board(struct pcxhr_mgr * mgr)121e12229b4SMarkus Bollinger void pcxhr_reset_board(struct pcxhr_mgr *mgr)
122e12229b4SMarkus Bollinger {
123e12229b4SMarkus Bollinger 	struct pcxhr_rmh rmh;
124e12229b4SMarkus Bollinger 
125e12229b4SMarkus Bollinger 	if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
126e12229b4SMarkus Bollinger 		/* mute outputs */
1277628700eSMarkus Bollinger 	    if (!mgr->is_hr_stereo) {
128e12229b4SMarkus Bollinger 		/* a read to IO_NUM_REG_MUTE_OUT register unmutes! */
129e12229b4SMarkus Bollinger 		pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
130e12229b4SMarkus Bollinger 		rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
131e12229b4SMarkus Bollinger 		pcxhr_send_msg(mgr, &rmh);
132e12229b4SMarkus Bollinger 		/* mute inputs */
1337628700eSMarkus Bollinger 		pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS,
1347628700eSMarkus Bollinger 					    0, NULL);
1357628700eSMarkus Bollinger 	    }
1367628700eSMarkus Bollinger 		/* stereo cards mute with reset of dsp */
137e12229b4SMarkus Bollinger 	}
138e12229b4SMarkus Bollinger 	/* reset pcxhr dsp */
139e12229b4SMarkus Bollinger 	if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_EPRM_INDEX))
140e12229b4SMarkus Bollinger 		pcxhr_reset_dsp(mgr);
141e12229b4SMarkus Bollinger 	/* reset second xilinx */
1427628700eSMarkus Bollinger 	if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_XLX_COM_INDEX)) {
143e12229b4SMarkus Bollinger 		pcxhr_reset_xilinx_com(mgr);
1447628700eSMarkus Bollinger 		mgr->dsp_loaded = 1;
1457628700eSMarkus Bollinger 	}
146e12229b4SMarkus Bollinger 	return;
147e12229b4SMarkus Bollinger }
148e12229b4SMarkus Bollinger 
149e12229b4SMarkus Bollinger 
150e12229b4SMarkus Bollinger /*
151e12229b4SMarkus Bollinger  *  allocate a playback/capture pipe (pcmp0/pcmc0)
152e12229b4SMarkus Bollinger  */
pcxhr_dsp_allocate_pipe(struct pcxhr_mgr * mgr,struct pcxhr_pipe * pipe,int is_capture,int pin)1537628700eSMarkus Bollinger static int pcxhr_dsp_allocate_pipe(struct pcxhr_mgr *mgr,
1547628700eSMarkus Bollinger 				   struct pcxhr_pipe *pipe,
155e12229b4SMarkus Bollinger 				   int is_capture, int pin)
156e12229b4SMarkus Bollinger {
157e12229b4SMarkus Bollinger 	int stream_count, audio_count;
158e12229b4SMarkus Bollinger 	int err;
159e12229b4SMarkus Bollinger 	struct pcxhr_rmh rmh;
160e12229b4SMarkus Bollinger 
161e12229b4SMarkus Bollinger 	if (is_capture) {
162e12229b4SMarkus Bollinger 		stream_count = 1;
163e12229b4SMarkus Bollinger 		if (mgr->mono_capture)
164e12229b4SMarkus Bollinger 			audio_count = 1;
165e12229b4SMarkus Bollinger 		else
166e12229b4SMarkus Bollinger 			audio_count = 2;
167e12229b4SMarkus Bollinger 	} else {
168e12229b4SMarkus Bollinger 		stream_count = PCXHR_PLAYBACK_STREAMS;
169e12229b4SMarkus Bollinger 		audio_count = 2;	/* always stereo */
170e12229b4SMarkus Bollinger 	}
171b59bb8efSTakashi Iwai 	dev_dbg(&mgr->pci->dev, "snd_add_ref_pipe pin(%d) pcm%c0\n",
1727628700eSMarkus Bollinger 		    pin, is_capture ? 'c' : 'p');
173e12229b4SMarkus Bollinger 	pipe->is_capture = is_capture;
174e12229b4SMarkus Bollinger 	pipe->first_audio = pin;
175e12229b4SMarkus Bollinger 	/* define pipe (P_PCM_ONLY_MASK (0x020000) is not necessary) */
176e12229b4SMarkus Bollinger 	pcxhr_init_rmh(&rmh, CMD_RES_PIPE);
1777628700eSMarkus Bollinger 	pcxhr_set_pipe_cmd_params(&rmh, is_capture, pin,
1787628700eSMarkus Bollinger 				  audio_count, stream_count);
1797628700eSMarkus Bollinger 	rmh.cmd[1] |= 0x020000; /* add P_PCM_ONLY_MASK */
1807628700eSMarkus Bollinger 	if (DSP_EXT_CMD_SET(mgr)) {
1817628700eSMarkus Bollinger 		/* add channel mask to command */
1827628700eSMarkus Bollinger 	  rmh.cmd[rmh.cmd_len++] = (audio_count == 1) ? 0x01 : 0x03;
1837628700eSMarkus Bollinger 	}
184e12229b4SMarkus Bollinger 	err = pcxhr_send_msg(mgr, &rmh);
185e12229b4SMarkus Bollinger 	if (err < 0) {
186b59bb8efSTakashi Iwai 		dev_err(&mgr->pci->dev, "error pipe allocation "
1877628700eSMarkus Bollinger 			   "(CMD_RES_PIPE) err=%x!\n", err);
188e12229b4SMarkus Bollinger 		return err;
189e12229b4SMarkus Bollinger 	}
190e12229b4SMarkus Bollinger 	pipe->status = PCXHR_PIPE_DEFINED;
191e12229b4SMarkus Bollinger 
192e12229b4SMarkus Bollinger 	return 0;
193e12229b4SMarkus Bollinger }
194e12229b4SMarkus Bollinger 
195e12229b4SMarkus Bollinger /*
196e12229b4SMarkus Bollinger  *  free playback/capture pipe (pcmp0/pcmc0)
197e12229b4SMarkus Bollinger  */
198e12229b4SMarkus Bollinger #if 0
199e12229b4SMarkus Bollinger static int pcxhr_dsp_free_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe)
200e12229b4SMarkus Bollinger {
201e12229b4SMarkus Bollinger 	struct pcxhr_rmh rmh;
202e12229b4SMarkus Bollinger 	int capture_mask = 0;
203e12229b4SMarkus Bollinger 	int playback_mask = 0;
204e12229b4SMarkus Bollinger 	int err = 0;
205e12229b4SMarkus Bollinger 
206e12229b4SMarkus Bollinger 	if (pipe->is_capture)
207e12229b4SMarkus Bollinger 		capture_mask  = (1 << pipe->first_audio);
208e12229b4SMarkus Bollinger 	else
209e12229b4SMarkus Bollinger 		playback_mask = (1 << pipe->first_audio);
210e12229b4SMarkus Bollinger 
211e12229b4SMarkus Bollinger 	/* stop one pipe */
212e12229b4SMarkus Bollinger 	err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0);
213e12229b4SMarkus Bollinger 	if (err < 0)
214b59bb8efSTakashi Iwai 		dev_err(&mgr->pci->dev, "error stopping pipe!\n");
215e12229b4SMarkus Bollinger 	/* release the pipe */
216e12229b4SMarkus Bollinger 	pcxhr_init_rmh(&rmh, CMD_FREE_PIPE);
2177628700eSMarkus Bollinger 	pcxhr_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->first_audio,
2187628700eSMarkus Bollinger 				  0, 0);
219e12229b4SMarkus Bollinger 	err = pcxhr_send_msg(mgr, &rmh);
220e12229b4SMarkus Bollinger 	if (err < 0)
221b59bb8efSTakashi Iwai 		dev_err(&mgr->pci->dev, "error pipe release "
2227628700eSMarkus Bollinger 			   "(CMD_FREE_PIPE) err(%x)\n", err);
223e12229b4SMarkus Bollinger 	pipe->status = PCXHR_PIPE_UNDEFINED;
224e12229b4SMarkus Bollinger 	return err;
225e12229b4SMarkus Bollinger }
226e12229b4SMarkus Bollinger #endif
227e12229b4SMarkus Bollinger 
228e12229b4SMarkus Bollinger 
pcxhr_config_pipes(struct pcxhr_mgr * mgr)229e12229b4SMarkus Bollinger static int pcxhr_config_pipes(struct pcxhr_mgr *mgr)
230e12229b4SMarkus Bollinger {
231e12229b4SMarkus Bollinger 	int err, i, j;
232e12229b4SMarkus Bollinger 	struct snd_pcxhr *chip;
233e12229b4SMarkus Bollinger 	struct pcxhr_pipe *pipe;
234e12229b4SMarkus Bollinger 
235e12229b4SMarkus Bollinger 	/* allocate the pipes on the dsp */
236e12229b4SMarkus Bollinger 	for (i = 0; i < mgr->num_cards; i++) {
237e12229b4SMarkus Bollinger 		chip = mgr->chip[i];
238e12229b4SMarkus Bollinger 		if (chip->nb_streams_play) {
239e12229b4SMarkus Bollinger 			pipe = &chip->playback_pipe;
240e12229b4SMarkus Bollinger 			err = pcxhr_dsp_allocate_pipe( mgr, pipe, 0, i*2);
241e12229b4SMarkus Bollinger 			if (err)
242e12229b4SMarkus Bollinger 				return err;
243e12229b4SMarkus Bollinger 			for(j = 0; j < chip->nb_streams_play; j++)
244e12229b4SMarkus Bollinger 				chip->playback_stream[j].pipe = pipe;
245e12229b4SMarkus Bollinger 		}
246e12229b4SMarkus Bollinger 		for (j = 0; j < chip->nb_streams_capt; j++) {
247e12229b4SMarkus Bollinger 			pipe = &chip->capture_pipe[j];
248e12229b4SMarkus Bollinger 			err = pcxhr_dsp_allocate_pipe(mgr, pipe, 1, i*2 + j);
249e12229b4SMarkus Bollinger 			if (err)
250e12229b4SMarkus Bollinger 				return err;
251e12229b4SMarkus Bollinger 			chip->capture_stream[j].pipe = pipe;
252e12229b4SMarkus Bollinger 		}
253e12229b4SMarkus Bollinger 	}
254e12229b4SMarkus Bollinger 	return 0;
255e12229b4SMarkus Bollinger }
256e12229b4SMarkus Bollinger 
pcxhr_start_pipes(struct pcxhr_mgr * mgr)257e12229b4SMarkus Bollinger static int pcxhr_start_pipes(struct pcxhr_mgr *mgr)
258e12229b4SMarkus Bollinger {
259e12229b4SMarkus Bollinger 	int i, j;
260e12229b4SMarkus Bollinger 	struct snd_pcxhr *chip;
261e12229b4SMarkus Bollinger 	int playback_mask = 0;
262e12229b4SMarkus Bollinger 	int capture_mask = 0;
263e12229b4SMarkus Bollinger 
264e12229b4SMarkus Bollinger 	/* start all the pipes on the dsp */
265e12229b4SMarkus Bollinger 	for (i = 0; i < mgr->num_cards; i++) {
266e12229b4SMarkus Bollinger 		chip = mgr->chip[i];
267e12229b4SMarkus Bollinger 		if (chip->nb_streams_play)
2687628700eSMarkus Bollinger 			playback_mask |= 1 << chip->playback_pipe.first_audio;
269e12229b4SMarkus Bollinger 		for (j = 0; j < chip->nb_streams_capt; j++)
2707628700eSMarkus Bollinger 			capture_mask |= 1 << chip->capture_pipe[j].first_audio;
271e12229b4SMarkus Bollinger 	}
272e12229b4SMarkus Bollinger 	return pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
273e12229b4SMarkus Bollinger }
274e12229b4SMarkus Bollinger 
275e12229b4SMarkus Bollinger 
pcxhr_dsp_load(struct pcxhr_mgr * mgr,int index,const struct firmware * dsp)2767628700eSMarkus Bollinger static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index,
2777628700eSMarkus Bollinger 			  const struct firmware *dsp)
278e12229b4SMarkus Bollinger {
279e12229b4SMarkus Bollinger 	int err, card_index;
280e12229b4SMarkus Bollinger 
281b59bb8efSTakashi Iwai 	dev_dbg(&mgr->pci->dev,
2825b5e0928SAlexey Dobriyan 		"loading dsp [%d] size = %zd\n", index, dsp->size);
283e12229b4SMarkus Bollinger 
284e12229b4SMarkus Bollinger 	switch (index) {
285e12229b4SMarkus Bollinger 	case PCXHR_FIRMWARE_XLX_INT_INDEX:
286e12229b4SMarkus Bollinger 		pcxhr_reset_xilinx_com(mgr);
287e12229b4SMarkus Bollinger 		return pcxhr_load_xilinx_binary(mgr, dsp, 0);
288e12229b4SMarkus Bollinger 
289e12229b4SMarkus Bollinger 	case PCXHR_FIRMWARE_XLX_COM_INDEX:
290e12229b4SMarkus Bollinger 		pcxhr_reset_xilinx_com(mgr);
291e12229b4SMarkus Bollinger 		return pcxhr_load_xilinx_binary(mgr, dsp, 1);
292e12229b4SMarkus Bollinger 
293e12229b4SMarkus Bollinger 	case PCXHR_FIRMWARE_DSP_EPRM_INDEX:
294e12229b4SMarkus Bollinger 		pcxhr_reset_dsp(mgr);
295e12229b4SMarkus Bollinger 		return pcxhr_load_eeprom_binary(mgr, dsp);
296e12229b4SMarkus Bollinger 
297e12229b4SMarkus Bollinger 	case PCXHR_FIRMWARE_DSP_BOOT_INDEX:
298e12229b4SMarkus Bollinger 		return pcxhr_load_boot_binary(mgr, dsp);
299e12229b4SMarkus Bollinger 
300e12229b4SMarkus Bollinger 	case PCXHR_FIRMWARE_DSP_MAIN_INDEX:
301e12229b4SMarkus Bollinger 		err = pcxhr_load_dsp_binary(mgr, dsp);
302e12229b4SMarkus Bollinger 		if (err)
303e12229b4SMarkus Bollinger 			return err;
304e12229b4SMarkus Bollinger 		break;	/* continue with first init */
305e12229b4SMarkus Bollinger 	default:
306b59bb8efSTakashi Iwai 		dev_err(&mgr->pci->dev, "wrong file index\n");
307e12229b4SMarkus Bollinger 		return -EFAULT;
308e12229b4SMarkus Bollinger 	} /* end of switch file index*/
309e12229b4SMarkus Bollinger 
310e12229b4SMarkus Bollinger 	/* first communication with embedded */
311e12229b4SMarkus Bollinger 	err = pcxhr_init_board(mgr);
312e12229b4SMarkus Bollinger         if (err < 0) {
313b59bb8efSTakashi Iwai 		dev_err(&mgr->pci->dev, "pcxhr could not be set up\n");
314e12229b4SMarkus Bollinger 		return err;
315e12229b4SMarkus Bollinger 	}
316e12229b4SMarkus Bollinger 	err = pcxhr_config_pipes(mgr);
317e12229b4SMarkus Bollinger         if (err < 0) {
318b59bb8efSTakashi Iwai 		dev_err(&mgr->pci->dev, "pcxhr pipes could not be set up\n");
319e12229b4SMarkus Bollinger 		return err;
320e12229b4SMarkus Bollinger 	}
321e12229b4SMarkus Bollinger        	/* create devices and mixer in accordance with HW options*/
322e12229b4SMarkus Bollinger         for (card_index = 0; card_index < mgr->num_cards; card_index++) {
323e12229b4SMarkus Bollinger 		struct snd_pcxhr *chip = mgr->chip[card_index];
324e12229b4SMarkus Bollinger 
325*4327ad25STakashi Iwai 		err = pcxhr_create_pcm(chip);
326*4327ad25STakashi Iwai 		if (err < 0)
327e12229b4SMarkus Bollinger 			return err;
328e12229b4SMarkus Bollinger 
329e12229b4SMarkus Bollinger 		if (card_index == 0) {
330*4327ad25STakashi Iwai 			err = pcxhr_create_mixer(chip->mgr);
331*4327ad25STakashi Iwai 			if (err < 0)
332e12229b4SMarkus Bollinger 				return err;
333e12229b4SMarkus Bollinger 		}
334*4327ad25STakashi Iwai 		err = snd_card_register(chip->card);
335*4327ad25STakashi Iwai 		if (err < 0)
336e12229b4SMarkus Bollinger 			return err;
337e12229b4SMarkus Bollinger 	}
338e12229b4SMarkus Bollinger 	err = pcxhr_start_pipes(mgr);
339e12229b4SMarkus Bollinger         if (err < 0) {
340b59bb8efSTakashi Iwai 		dev_err(&mgr->pci->dev, "pcxhr pipes could not be started\n");
341e12229b4SMarkus Bollinger 		return err;
342e12229b4SMarkus Bollinger 	}
343b59bb8efSTakashi Iwai 	dev_dbg(&mgr->pci->dev,
344b59bb8efSTakashi Iwai 		"pcxhr firmware downloaded and successfully set up\n");
345e12229b4SMarkus Bollinger 
346e12229b4SMarkus Bollinger 	return 0;
347e12229b4SMarkus Bollinger }
348e12229b4SMarkus Bollinger 
349e12229b4SMarkus Bollinger /*
350e12229b4SMarkus Bollinger  * fw loader entry
351e12229b4SMarkus Bollinger  */
pcxhr_setup_firmware(struct pcxhr_mgr * mgr)352e12229b4SMarkus Bollinger int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
353e12229b4SMarkus Bollinger {
35498fd5398STakashi Iwai 	static const char * const fw_files[][5] = {
355ade9b2fbSMarkus Bollinger 	[0] = { "xlxint.dat", "xlxc882hr.dat",
356ade9b2fbSMarkus Bollinger 		"dspe882.e56", "dspb882hr.b56", "dspd882.d56" },
357ade9b2fbSMarkus Bollinger 	[1] = { "xlxint.dat", "xlxc882e.dat",
358ade9b2fbSMarkus Bollinger 		"dspe882.e56", "dspb882e.b56", "dspd882.d56" },
359ade9b2fbSMarkus Bollinger 	[2] = { "xlxint.dat", "xlxc1222hr.dat",
360ade9b2fbSMarkus Bollinger 		"dspe882.e56", "dspb1222hr.b56", "dspd1222.d56" },
361ade9b2fbSMarkus Bollinger 	[3] = { "xlxint.dat", "xlxc1222e.dat",
362ade9b2fbSMarkus Bollinger 		"dspe882.e56", "dspb1222e.b56", "dspd1222.d56" },
363ade9b2fbSMarkus Bollinger 	[4] = { NULL, "xlxc222.dat",
364ade9b2fbSMarkus Bollinger 		"dspe924.e56", "dspb924.b56", "dspd222.d56" },
365ade9b2fbSMarkus Bollinger 	[5] = { NULL, "xlxc924.dat",
366ade9b2fbSMarkus Bollinger 		"dspe924.e56", "dspb924.b56", "dspd222.d56" },
367e12229b4SMarkus Bollinger 	};
368e12229b4SMarkus Bollinger 	char path[32];
369e12229b4SMarkus Bollinger 
370e12229b4SMarkus Bollinger 	const struct firmware *fw_entry;
371e12229b4SMarkus Bollinger 	int i, err;
3727628700eSMarkus Bollinger 	int fw_set = mgr->fw_file_set;
373e12229b4SMarkus Bollinger 
3747628700eSMarkus Bollinger 	for (i = 0; i < 5; i++) {
3757628700eSMarkus Bollinger 		if (!fw_files[fw_set][i])
3767628700eSMarkus Bollinger 			continue;
3777628700eSMarkus Bollinger 		sprintf(path, "pcxhr/%s", fw_files[fw_set][i]);
378e12229b4SMarkus Bollinger 		if (request_firmware(&fw_entry, path, &mgr->pci->dev)) {
379b59bb8efSTakashi Iwai 			dev_err(&mgr->pci->dev,
380b59bb8efSTakashi Iwai 				"pcxhr: can't load firmware %s\n",
3817628700eSMarkus Bollinger 				   path);
382e12229b4SMarkus Bollinger 			return -ENOENT;
383e12229b4SMarkus Bollinger 		}
384e12229b4SMarkus Bollinger 		/* fake hwdep dsp record */
385e12229b4SMarkus Bollinger 		err = pcxhr_dsp_load(mgr, i, fw_entry);
386e12229b4SMarkus Bollinger 		release_firmware(fw_entry);
387e12229b4SMarkus Bollinger 		if (err < 0)
388e12229b4SMarkus Bollinger 			return err;
389e12229b4SMarkus Bollinger 		mgr->dsp_loaded |= 1 << i;
390e12229b4SMarkus Bollinger 	}
391e12229b4SMarkus Bollinger 	return 0;
392e12229b4SMarkus Bollinger }
393e12229b4SMarkus Bollinger 
394ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/xlxint.dat");
395ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/xlxc882hr.dat");
396ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/xlxc882e.dat");
397ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/dspe882.e56");
398ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/dspb882hr.b56");
399ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/dspb882e.b56");
400ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/dspd882.d56");
4017e0af29dSClemens Ladisch 
402ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/xlxc1222hr.dat");
403ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/xlxc1222e.dat");
404ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/dspb1222hr.b56");
405ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/dspb1222e.b56");
406ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/dspd1222.d56");
4077628700eSMarkus Bollinger 
408ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/xlxc222.dat");
409ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/xlxc924.dat");
410ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/dspe924.e56");
411ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/dspb924.b56");
412ade9b2fbSMarkus Bollinger MODULE_FIRMWARE("pcxhr/dspd222.d56");
413