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