Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / sound / pci / pcxhr / pcxhr_hwdep.c
1 /*
2  * Driver for Digigram pcxhr compatible soundcards
3  *
4  * hwdep device manager
5  *
6  * Copyright (c) 2004 by Digigram <alsa@digigram.com>
7  *
8  *   This program is free software; you can redistribute it and/or modify
9  *   it under the terms of the GNU General Public License as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22
23 #include <linux/interrupt.h>
24 #include <linux/vmalloc.h>
25 #include <linux/firmware.h>
26 #include <linux/pci.h>
27 #include <linux/module.h>
28 #include <asm/io.h>
29 #include <sound/core.h>
30 #include <sound/hwdep.h>
31 #include "pcxhr.h"
32 #include "pcxhr_mixer.h"
33 #include "pcxhr_hwdep.h"
34 #include "pcxhr_core.h"
35 #include "pcxhr_mix22.h"
36
37
38 #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
39 #if !defined(CONFIG_USE_PCXHRLOADER) && !defined(CONFIG_SND_PCXHR) /* built-in kernel */
40 #define SND_PCXHR_FW_LOADER     /* use the standard firmware loader */
41 #endif
42 #endif
43
44
45 static int pcxhr_sub_init(struct pcxhr_mgr *mgr);
46 /*
47  * get basic information and init pcxhr card
48  */
49 static int pcxhr_init_board(struct pcxhr_mgr *mgr)
50 {
51         int err;
52         struct pcxhr_rmh rmh;
53         int card_streams;
54
55         /* calc the number of all streams used */
56         if (mgr->mono_capture)
57                 card_streams = mgr->capture_chips * 2;
58         else
59                 card_streams = mgr->capture_chips;
60         card_streams += mgr->playback_chips * PCXHR_PLAYBACK_STREAMS;
61
62         /* enable interrupts */
63         pcxhr_enable_dsp(mgr);
64
65         pcxhr_init_rmh(&rmh, CMD_SUPPORTED);
66         err = pcxhr_send_msg(mgr, &rmh);
67         if (err)
68                 return err;
69         /* test 8 or 12 phys out */
70         if ((rmh.stat[0] & MASK_FIRST_FIELD) != mgr->playback_chips * 2)
71                 return -EINVAL;
72         /* test 8 or 2 phys in */
73         if (((rmh.stat[0] >> (2 * FIELD_SIZE)) & MASK_FIRST_FIELD) <
74             mgr->capture_chips * 2)
75                 return -EINVAL;
76         /* test max nb substream per board */
77         if ((rmh.stat[1] & 0x5F) < card_streams)
78                 return -EINVAL;
79         /* test max nb substream per pipe */
80         if (((rmh.stat[1] >> 7) & 0x5F) < PCXHR_PLAYBACK_STREAMS)
81                 return -EINVAL;
82         snd_printdd("supported formats : playback=%x capture=%x\n",
83                     rmh.stat[2], rmh.stat[3]);
84
85         pcxhr_init_rmh(&rmh, CMD_VERSION);
86         /* firmware num for DSP */
87         rmh.cmd[0] |= mgr->firmware_num;
88         /* transfer granularity in samples (should be multiple of 48) */
89         rmh.cmd[1] = (1<<23) + mgr->granularity;
90         rmh.cmd_len = 2;
91         err = pcxhr_send_msg(mgr, &rmh);
92         if (err)
93                 return err;
94         snd_printdd("PCXHR DSP version is %d.%d.%d\n", (rmh.stat[0]>>16)&0xff,
95                     (rmh.stat[0]>>8)&0xff, rmh.stat[0]&0xff);
96         mgr->dsp_version = rmh.stat[0];
97
98         if (mgr->is_hr_stereo)
99                 err = hr222_sub_init(mgr);
100         else
101                 err = pcxhr_sub_init(mgr);
102         return err;
103 }
104
105 static int pcxhr_sub_init(struct pcxhr_mgr *mgr)
106 {
107         int err;
108         struct pcxhr_rmh rmh;
109
110         /* get options */
111         pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
112         rmh.cmd[0] |= IO_NUM_REG_STATUS;
113         rmh.cmd[1]  = REG_STATUS_OPTIONS;
114         rmh.cmd_len = 2;
115         err = pcxhr_send_msg(mgr, &rmh);
116         if (err)
117                 return err;
118
119         if ((rmh.stat[1] & REG_STATUS_OPT_DAUGHTER_MASK) ==
120             REG_STATUS_OPT_ANALOG_BOARD)
121                 mgr->board_has_analog = 1;      /* analog addon board found */
122
123         /* unmute inputs */
124         err = pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS,
125                                           REG_CONT_UNMUTE_INPUTS, NULL);
126         if (err)
127                 return err;
128         /* unmute outputs (a write to IO_NUM_REG_MUTE_OUT mutes!) */
129         pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
130         rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
131         if (DSP_EXT_CMD_SET(mgr)) {
132                 rmh.cmd[1]  = 1;        /* unmute digital plugs */
133                 rmh.cmd_len = 2;
134         }
135         err = pcxhr_send_msg(mgr, &rmh);
136         return err;
137 }
138
139 void pcxhr_reset_board(struct pcxhr_mgr *mgr)
140 {
141         struct pcxhr_rmh rmh;
142
143         if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
144                 /* mute outputs */
145             if (!mgr->is_hr_stereo) {
146                 /* a read to IO_NUM_REG_MUTE_OUT register unmutes! */
147                 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
148                 rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
149                 pcxhr_send_msg(mgr, &rmh);
150                 /* mute inputs */
151                 pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS,
152                                             0, NULL);
153             }
154                 /* stereo cards mute with reset of dsp */
155         }
156         /* reset pcxhr dsp */
157         if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_EPRM_INDEX))
158                 pcxhr_reset_dsp(mgr);
159         /* reset second xilinx */
160         if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_XLX_COM_INDEX)) {
161                 pcxhr_reset_xilinx_com(mgr);
162                 mgr->dsp_loaded = 1;
163         }
164         return;
165 }
166
167
168 /*
169  *  allocate a playback/capture pipe (pcmp0/pcmc0)
170  */
171 static int pcxhr_dsp_allocate_pipe(struct pcxhr_mgr *mgr,
172                                    struct pcxhr_pipe *pipe,
173                                    int is_capture, int pin)
174 {
175         int stream_count, audio_count;
176         int err;
177         struct pcxhr_rmh rmh;
178
179         if (is_capture) {
180                 stream_count = 1;
181                 if (mgr->mono_capture)
182                         audio_count = 1;
183                 else
184                         audio_count = 2;
185         } else {
186                 stream_count = PCXHR_PLAYBACK_STREAMS;
187                 audio_count = 2;        /* always stereo */
188         }
189         snd_printdd("snd_add_ref_pipe pin(%d) pcm%c0\n",
190                     pin, is_capture ? 'c' : 'p');
191         pipe->is_capture = is_capture;
192         pipe->first_audio = pin;
193         /* define pipe (P_PCM_ONLY_MASK (0x020000) is not necessary) */
194         pcxhr_init_rmh(&rmh, CMD_RES_PIPE);
195         pcxhr_set_pipe_cmd_params(&rmh, is_capture, pin,
196                                   audio_count, stream_count);
197         rmh.cmd[1] |= 0x020000; /* add P_PCM_ONLY_MASK */
198         if (DSP_EXT_CMD_SET(mgr)) {
199                 /* add channel mask to command */
200           rmh.cmd[rmh.cmd_len++] = (audio_count == 1) ? 0x01 : 0x03;
201         }
202         err = pcxhr_send_msg(mgr, &rmh);
203         if (err < 0) {
204                 snd_printk(KERN_ERR "error pipe allocation "
205                            "(CMD_RES_PIPE) err=%x!\n", err);
206                 return err;
207         }
208         pipe->status = PCXHR_PIPE_DEFINED;
209
210         return 0;
211 }
212
213 /*
214  *  free playback/capture pipe (pcmp0/pcmc0)
215  */
216 #if 0
217 static int pcxhr_dsp_free_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe)
218 {
219         struct pcxhr_rmh rmh;
220         int capture_mask = 0;
221         int playback_mask = 0;
222         int err = 0;
223
224         if (pipe->is_capture)
225                 capture_mask  = (1 << pipe->first_audio);
226         else
227                 playback_mask = (1 << pipe->first_audio);
228
229         /* stop one pipe */
230         err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0);
231         if (err < 0)
232                 snd_printk(KERN_ERR "error stopping pipe!\n");
233         /* release the pipe */
234         pcxhr_init_rmh(&rmh, CMD_FREE_PIPE);
235         pcxhr_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->first_audio,
236                                   0, 0);
237         err = pcxhr_send_msg(mgr, &rmh);
238         if (err < 0)
239                 snd_printk(KERN_ERR "error pipe release "
240                            "(CMD_FREE_PIPE) err(%x)\n", err);
241         pipe->status = PCXHR_PIPE_UNDEFINED;
242         return err;
243 }
244 #endif
245
246
247 static int pcxhr_config_pipes(struct pcxhr_mgr *mgr)
248 {
249         int err, i, j;
250         struct snd_pcxhr *chip;
251         struct pcxhr_pipe *pipe;
252
253         /* allocate the pipes on the dsp */
254         for (i = 0; i < mgr->num_cards; i++) {
255                 chip = mgr->chip[i];
256                 if (chip->nb_streams_play) {
257                         pipe = &chip->playback_pipe;
258                         err = pcxhr_dsp_allocate_pipe( mgr, pipe, 0, i*2);
259                         if (err)
260                                 return err;
261                         for(j = 0; j < chip->nb_streams_play; j++)
262                                 chip->playback_stream[j].pipe = pipe;
263                 }
264                 for (j = 0; j < chip->nb_streams_capt; j++) {
265                         pipe = &chip->capture_pipe[j];
266                         err = pcxhr_dsp_allocate_pipe(mgr, pipe, 1, i*2 + j);
267                         if (err)
268                                 return err;
269                         chip->capture_stream[j].pipe = pipe;
270                 }
271         }
272         return 0;
273 }
274
275 static int pcxhr_start_pipes(struct pcxhr_mgr *mgr)
276 {
277         int i, j;
278         struct snd_pcxhr *chip;
279         int playback_mask = 0;
280         int capture_mask = 0;
281
282         /* start all the pipes on the dsp */
283         for (i = 0; i < mgr->num_cards; i++) {
284                 chip = mgr->chip[i];
285                 if (chip->nb_streams_play)
286                         playback_mask |= 1 << chip->playback_pipe.first_audio;
287                 for (j = 0; j < chip->nb_streams_capt; j++)
288                         capture_mask |= 1 << chip->capture_pipe[j].first_audio;
289         }
290         return pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
291 }
292
293
294 static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index,
295                           const struct firmware *dsp)
296 {
297         int err, card_index;
298
299         snd_printdd("loading dsp [%d] size = %Zd\n", index, dsp->size);
300
301         switch (index) {
302         case PCXHR_FIRMWARE_XLX_INT_INDEX:
303                 pcxhr_reset_xilinx_com(mgr);
304                 return pcxhr_load_xilinx_binary(mgr, dsp, 0);
305
306         case PCXHR_FIRMWARE_XLX_COM_INDEX:
307                 pcxhr_reset_xilinx_com(mgr);
308                 return pcxhr_load_xilinx_binary(mgr, dsp, 1);
309
310         case PCXHR_FIRMWARE_DSP_EPRM_INDEX:
311                 pcxhr_reset_dsp(mgr);
312                 return pcxhr_load_eeprom_binary(mgr, dsp);
313
314         case PCXHR_FIRMWARE_DSP_BOOT_INDEX:
315                 return pcxhr_load_boot_binary(mgr, dsp);
316
317         case PCXHR_FIRMWARE_DSP_MAIN_INDEX:
318                 err = pcxhr_load_dsp_binary(mgr, dsp);
319                 if (err)
320                         return err;
321                 break;  /* continue with first init */
322         default:
323                 snd_printk(KERN_ERR "wrong file index\n");
324                 return -EFAULT;
325         } /* end of switch file index*/
326
327         /* first communication with embedded */
328         err = pcxhr_init_board(mgr);
329         if (err < 0) {
330                 snd_printk(KERN_ERR "pcxhr could not be set up\n");
331                 return err;
332         }
333         err = pcxhr_config_pipes(mgr);
334         if (err < 0) {
335                 snd_printk(KERN_ERR "pcxhr pipes could not be set up\n");
336                 return err;
337         }
338         /* create devices and mixer in accordance with HW options*/
339         for (card_index = 0; card_index < mgr->num_cards; card_index++) {
340                 struct snd_pcxhr *chip = mgr->chip[card_index];
341
342                 if ((err = pcxhr_create_pcm(chip)) < 0)
343                         return err;
344
345                 if (card_index == 0) {
346                         if ((err = pcxhr_create_mixer(chip->mgr)) < 0)
347                                 return err;
348                 }
349                 if ((err = snd_card_register(chip->card)) < 0)
350                         return err;
351         }
352         err = pcxhr_start_pipes(mgr);
353         if (err < 0) {
354                 snd_printk(KERN_ERR "pcxhr pipes could not be started\n");
355                 return err;
356         }
357         snd_printdd("pcxhr firmware downloaded and successfully set up\n");
358
359         return 0;
360 }
361
362 /*
363  * fw loader entry
364  */
365 #ifdef SND_PCXHR_FW_LOADER
366
367 int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
368 {
369         static char *fw_files[][5] = {
370         [0] = { "xlxint.dat", "xlxc882hr.dat",
371                 "dspe882.e56", "dspb882hr.b56", "dspd882.d56" },
372         [1] = { "xlxint.dat", "xlxc882e.dat",
373                 "dspe882.e56", "dspb882e.b56", "dspd882.d56" },
374         [2] = { "xlxint.dat", "xlxc1222hr.dat",
375                 "dspe882.e56", "dspb1222hr.b56", "dspd1222.d56" },
376         [3] = { "xlxint.dat", "xlxc1222e.dat",
377                 "dspe882.e56", "dspb1222e.b56", "dspd1222.d56" },
378         [4] = { NULL, "xlxc222.dat",
379                 "dspe924.e56", "dspb924.b56", "dspd222.d56" },
380         [5] = { NULL, "xlxc924.dat",
381                 "dspe924.e56", "dspb924.b56", "dspd222.d56" },
382         };
383         char path[32];
384
385         const struct firmware *fw_entry;
386         int i, err;
387         int fw_set = mgr->fw_file_set;
388
389         for (i = 0; i < 5; i++) {
390                 if (!fw_files[fw_set][i])
391                         continue;
392                 sprintf(path, "pcxhr/%s", fw_files[fw_set][i]);
393                 if (request_firmware(&fw_entry, path, &mgr->pci->dev)) {
394                         snd_printk(KERN_ERR "pcxhr: can't load firmware %s\n",
395                                    path);
396                         return -ENOENT;
397                 }
398                 /* fake hwdep dsp record */
399                 err = pcxhr_dsp_load(mgr, i, fw_entry);
400                 release_firmware(fw_entry);
401                 if (err < 0)
402                         return err;
403                 mgr->dsp_loaded |= 1 << i;
404         }
405         return 0;
406 }
407
408 MODULE_FIRMWARE("pcxhr/xlxint.dat");
409 MODULE_FIRMWARE("pcxhr/xlxc882hr.dat");
410 MODULE_FIRMWARE("pcxhr/xlxc882e.dat");
411 MODULE_FIRMWARE("pcxhr/dspe882.e56");
412 MODULE_FIRMWARE("pcxhr/dspb882hr.b56");
413 MODULE_FIRMWARE("pcxhr/dspb882e.b56");
414 MODULE_FIRMWARE("pcxhr/dspd882.d56");
415
416 MODULE_FIRMWARE("pcxhr/xlxc1222hr.dat");
417 MODULE_FIRMWARE("pcxhr/xlxc1222e.dat");
418 MODULE_FIRMWARE("pcxhr/dspb1222hr.b56");
419 MODULE_FIRMWARE("pcxhr/dspb1222e.b56");
420 MODULE_FIRMWARE("pcxhr/dspd1222.d56");
421
422 MODULE_FIRMWARE("pcxhr/xlxc222.dat");
423 MODULE_FIRMWARE("pcxhr/xlxc924.dat");
424 MODULE_FIRMWARE("pcxhr/dspe924.e56");
425 MODULE_FIRMWARE("pcxhr/dspb924.b56");
426 MODULE_FIRMWARE("pcxhr/dspd222.d56");
427
428
429 #else /* old style firmware loading */
430
431 /* pcxhr hwdep interface id string */
432 #define PCXHR_HWDEP_ID       "pcxhr loader"
433
434
435 static int pcxhr_hwdep_dsp_status(struct snd_hwdep *hw,
436                                   struct snd_hwdep_dsp_status *info)
437 {
438         struct pcxhr_mgr *mgr = hw->private_data;
439         sprintf(info->id, "pcxhr%d", mgr->fw_file_set);
440         info->num_dsps = PCXHR_FIRMWARE_FILES_MAX_INDEX;
441
442         if (hw->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))
443                 info->chip_ready = 1;
444
445         info->version = PCXHR_DRIVER_VERSION;
446         return 0;
447 }
448
449 static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw,
450                                 struct snd_hwdep_dsp_image *dsp)
451 {
452         struct pcxhr_mgr *mgr = hw->private_data;
453         int err;
454         struct firmware fw;
455
456         fw.size = dsp->length;
457         fw.data = vmalloc(fw.size);
458         if (! fw.data) {
459                 snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image "
460                            "(%lu bytes)\n", (unsigned long)fw.size);
461                 return -ENOMEM;
462         }
463         if (copy_from_user((void *)fw.data, dsp->image, dsp->length)) {
464                 vfree(fw.data);
465                 return -EFAULT;
466         }
467         err = pcxhr_dsp_load(mgr, dsp->index, &fw);
468         vfree(fw.data);
469         if (err < 0)
470                 return err;
471         mgr->dsp_loaded |= 1 << dsp->index;
472         return 0;
473 }
474
475 int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
476 {
477         int err;
478         struct snd_hwdep *hw;
479
480         /* only create hwdep interface for first cardX
481          * (see "index" module parameter)
482          */
483         err = snd_hwdep_new(mgr->chip[0]->card, PCXHR_HWDEP_ID, 0, &hw);
484         if (err < 0)
485                 return err;
486
487         hw->iface = SNDRV_HWDEP_IFACE_PCXHR;
488         hw->private_data = mgr;
489         hw->ops.dsp_status = pcxhr_hwdep_dsp_status;
490         hw->ops.dsp_load = pcxhr_hwdep_dsp_load;
491         hw->exclusive = 1;
492         /* stereo cards don't need fw_file_0 -> dsp_loaded = 1 */
493         hw->dsp_loaded = mgr->is_hr_stereo ? 1 : 0;
494         mgr->dsp_loaded = 0;
495         sprintf(hw->name, PCXHR_HWDEP_ID);
496
497         err = snd_card_register(mgr->chip[0]->card);
498         if (err < 0)
499                 return err;
500         return 0;
501 }
502
503 #endif /* SND_PCXHR_FW_LOADER */