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 <asm/io.h> 28 #include <sound/core.h> 29 #include <sound/hwdep.h> 30 #include "pcxhr.h" 31 #include "pcxhr_mixer.h" 32 #include "pcxhr_hwdep.h" 33 #include "pcxhr_core.h" 34 35 36 #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) 37 #if !defined(CONFIG_USE_PCXHRLOADER) && !defined(CONFIG_SND_PCXHR) /* built-in kernel */ 38 #define SND_PCXHR_FW_LOADER /* use the standard firmware loader */ 39 #endif 40 #endif 41 42 43 /* 44 * get basic information and init pcxhr card 45 */ 46 47 static int pcxhr_init_board(struct pcxhr_mgr *mgr) 48 { 49 int err; 50 struct pcxhr_rmh rmh; 51 int card_streams; 52 53 /* calc the number of all streams used */ 54 if (mgr->mono_capture) 55 card_streams = mgr->capture_chips * 2; 56 else 57 card_streams = mgr->capture_chips; 58 card_streams += mgr->playback_chips * PCXHR_PLAYBACK_STREAMS; 59 60 /* enable interrupts */ 61 pcxhr_enable_dsp(mgr); 62 63 pcxhr_init_rmh(&rmh, CMD_SUPPORTED); 64 err = pcxhr_send_msg(mgr, &rmh); 65 if (err) 66 return err; 67 /* test 8 or 12 phys out */ 68 if ((rmh.stat[0] & MASK_FIRST_FIELD) != mgr->playback_chips * 2) 69 return -EINVAL; 70 /* test 8 or 2 phys in */ 71 if (((rmh.stat[0] >> (2 * FIELD_SIZE)) & MASK_FIRST_FIELD) != 72 mgr->capture_chips * 2) 73 return -EINVAL; 74 /* test max nb substream per board */ 75 if ((rmh.stat[1] & 0x5F) < card_streams) 76 return -EINVAL; 77 /* test max nb substream per pipe */ 78 if (((rmh.stat[1] >> 7) & 0x5F) < PCXHR_PLAYBACK_STREAMS) 79 return -EINVAL; 80 81 pcxhr_init_rmh(&rmh, CMD_VERSION); 82 /* firmware num for DSP */ 83 rmh.cmd[0] |= mgr->firmware_num; 84 /* transfer granularity in samples (should be multiple of 48) */ 85 rmh.cmd[1] = (1<<23) + PCXHR_GRANULARITY; 86 rmh.cmd_len = 2; 87 err = pcxhr_send_msg(mgr, &rmh); 88 if (err) 89 return err; 90 snd_printdd("PCXHR DSP version is %d.%d.%d\n", 91 (rmh.stat[0]>>16)&0xff, (rmh.stat[0]>>8)&0xff, rmh.stat[0]&0xff); 92 mgr->dsp_version = rmh.stat[0]; 93 94 /* get options */ 95 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); 96 rmh.cmd[0] |= IO_NUM_REG_STATUS; 97 rmh.cmd[1] = REG_STATUS_OPTIONS; 98 rmh.cmd_len = 2; 99 err = pcxhr_send_msg(mgr, &rmh); 100 if (err) 101 return err; 102 103 if ((rmh.stat[1] & REG_STATUS_OPT_DAUGHTER_MASK) == REG_STATUS_OPT_ANALOG_BOARD) 104 mgr->board_has_analog = 1; /* analog addon board available */ 105 else 106 /* analog addon board not available -> no support for instance */ 107 return -EINVAL; 108 109 /* unmute inputs */ 110 err = pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS, 111 REG_CONT_UNMUTE_INPUTS, NULL); 112 if (err) 113 return err; 114 /* unmute outputs */ 115 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); /* a write to IO_NUM_REG_MUTE_OUT mutes! */ 116 rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT; 117 err = pcxhr_send_msg(mgr, &rmh); 118 return err; 119 } 120 121 void pcxhr_reset_board(struct pcxhr_mgr *mgr) 122 { 123 struct pcxhr_rmh rmh; 124 125 if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) { 126 /* mute outputs */ 127 /* a read to IO_NUM_REG_MUTE_OUT register unmutes! */ 128 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); 129 rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT; 130 pcxhr_send_msg(mgr, &rmh); 131 /* mute inputs */ 132 pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS, 0, NULL); 133 } 134 /* reset pcxhr dsp */ 135 if (mgr->dsp_loaded & ( 1 << PCXHR_FIRMWARE_DSP_EPRM_INDEX)) 136 pcxhr_reset_dsp(mgr); 137 /* reset second xilinx */ 138 if (mgr->dsp_loaded & ( 1 << PCXHR_FIRMWARE_XLX_COM_INDEX)) 139 pcxhr_reset_xilinx_com(mgr); 140 return; 141 } 142 143 144 /* 145 * allocate a playback/capture pipe (pcmp0/pcmc0) 146 */ 147 static int pcxhr_dsp_allocate_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe, 148 int is_capture, int pin) 149 { 150 int stream_count, audio_count; 151 int err; 152 struct pcxhr_rmh rmh; 153 154 if (is_capture) { 155 stream_count = 1; 156 if (mgr->mono_capture) 157 audio_count = 1; 158 else 159 audio_count = 2; 160 } else { 161 stream_count = PCXHR_PLAYBACK_STREAMS; 162 audio_count = 2; /* always stereo */ 163 } 164 snd_printdd("snd_add_ref_pipe pin(%d) pcm%c0\n", pin, is_capture ? 'c' : 'p'); 165 pipe->is_capture = is_capture; 166 pipe->first_audio = pin; 167 /* define pipe (P_PCM_ONLY_MASK (0x020000) is not necessary) */ 168 pcxhr_init_rmh(&rmh, CMD_RES_PIPE); 169 pcxhr_set_pipe_cmd_params(&rmh, is_capture, pin, audio_count, stream_count); 170 err = pcxhr_send_msg(mgr, &rmh); 171 if (err < 0) { 172 snd_printk(KERN_ERR "error pipe allocation (CMD_RES_PIPE) err=%x!\n", err ); 173 return err; 174 } 175 pipe->status = PCXHR_PIPE_DEFINED; 176 177 return 0; 178 } 179 180 /* 181 * free playback/capture pipe (pcmp0/pcmc0) 182 */ 183 #if 0 184 static int pcxhr_dsp_free_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe) 185 { 186 struct pcxhr_rmh rmh; 187 int capture_mask = 0; 188 int playback_mask = 0; 189 int err = 0; 190 191 if (pipe->is_capture) 192 capture_mask = (1 << pipe->first_audio); 193 else 194 playback_mask = (1 << pipe->first_audio); 195 196 /* stop one pipe */ 197 err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0); 198 if (err < 0) 199 snd_printk(KERN_ERR "error stopping pipe!\n"); 200 /* release the pipe */ 201 pcxhr_init_rmh(&rmh, CMD_FREE_PIPE); 202 pcxhr_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->first_audio, 0, 0); 203 err = pcxhr_send_msg(mgr, &rmh); 204 if (err < 0) 205 snd_printk(KERN_ERR "error pipe release (CMD_FREE_PIPE) err(%x)\n", err); 206 pipe->status = PCXHR_PIPE_UNDEFINED; 207 return err; 208 } 209 #endif 210 211 212 static int pcxhr_config_pipes(struct pcxhr_mgr *mgr) 213 { 214 int err, i, j; 215 struct snd_pcxhr *chip; 216 struct pcxhr_pipe *pipe; 217 218 /* allocate the pipes on the dsp */ 219 for (i = 0; i < mgr->num_cards; i++) { 220 chip = mgr->chip[i]; 221 if (chip->nb_streams_play) { 222 pipe = &chip->playback_pipe; 223 err = pcxhr_dsp_allocate_pipe( mgr, pipe, 0, i*2); 224 if (err) 225 return err; 226 for(j = 0; j < chip->nb_streams_play; j++) 227 chip->playback_stream[j].pipe = pipe; 228 } 229 for (j = 0; j < chip->nb_streams_capt; j++) { 230 pipe = &chip->capture_pipe[j]; 231 err = pcxhr_dsp_allocate_pipe(mgr, pipe, 1, i*2 + j); 232 if (err) 233 return err; 234 chip->capture_stream[j].pipe = pipe; 235 } 236 } 237 return 0; 238 } 239 240 static int pcxhr_start_pipes(struct pcxhr_mgr *mgr) 241 { 242 int i, j; 243 struct snd_pcxhr *chip; 244 int playback_mask = 0; 245 int capture_mask = 0; 246 247 /* start all the pipes on the dsp */ 248 for (i = 0; i < mgr->num_cards; i++) { 249 chip = mgr->chip[i]; 250 if (chip->nb_streams_play) 251 playback_mask |= (1 << chip->playback_pipe.first_audio); 252 for (j = 0; j < chip->nb_streams_capt; j++) 253 capture_mask |= (1 << chip->capture_pipe[j].first_audio); 254 } 255 return pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1); 256 } 257 258 259 static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index, const struct firmware *dsp) 260 { 261 int err, card_index; 262 263 snd_printdd("loading dsp [%d] size = %Zd\n", index, dsp->size); 264 265 switch (index) { 266 case PCXHR_FIRMWARE_XLX_INT_INDEX: 267 pcxhr_reset_xilinx_com(mgr); 268 return pcxhr_load_xilinx_binary(mgr, dsp, 0); 269 270 case PCXHR_FIRMWARE_XLX_COM_INDEX: 271 pcxhr_reset_xilinx_com(mgr); 272 return pcxhr_load_xilinx_binary(mgr, dsp, 1); 273 274 case PCXHR_FIRMWARE_DSP_EPRM_INDEX: 275 pcxhr_reset_dsp(mgr); 276 return pcxhr_load_eeprom_binary(mgr, dsp); 277 278 case PCXHR_FIRMWARE_DSP_BOOT_INDEX: 279 return pcxhr_load_boot_binary(mgr, dsp); 280 281 case PCXHR_FIRMWARE_DSP_MAIN_INDEX: 282 err = pcxhr_load_dsp_binary(mgr, dsp); 283 if (err) 284 return err; 285 break; /* continue with first init */ 286 default: 287 snd_printk(KERN_ERR "wrong file index\n"); 288 return -EFAULT; 289 } /* end of switch file index*/ 290 291 /* first communication with embedded */ 292 err = pcxhr_init_board(mgr); 293 if (err < 0) { 294 snd_printk(KERN_ERR "pcxhr could not be set up\n"); 295 return err; 296 } 297 err = pcxhr_config_pipes(mgr); 298 if (err < 0) { 299 snd_printk(KERN_ERR "pcxhr pipes could not be set up\n"); 300 return err; 301 } 302 /* create devices and mixer in accordance with HW options*/ 303 for (card_index = 0; card_index < mgr->num_cards; card_index++) { 304 struct snd_pcxhr *chip = mgr->chip[card_index]; 305 306 if ((err = pcxhr_create_pcm(chip)) < 0) 307 return err; 308 309 if (card_index == 0) { 310 if ((err = pcxhr_create_mixer(chip->mgr)) < 0) 311 return err; 312 } 313 if ((err = snd_card_register(chip->card)) < 0) 314 return err; 315 } 316 err = pcxhr_start_pipes(mgr); 317 if (err < 0) { 318 snd_printk(KERN_ERR "pcxhr pipes could not be started\n"); 319 return err; 320 } 321 snd_printdd("pcxhr firmware downloaded and successfully set up\n"); 322 323 return 0; 324 } 325 326 /* 327 * fw loader entry 328 */ 329 #ifdef SND_PCXHR_FW_LOADER 330 331 int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) 332 { 333 static char *fw_files[5] = { 334 "xi_1_882.dat", 335 "xc_1_882.dat", 336 "e321_512.e56", 337 "b321_512.b56", 338 "d321_512.d56" 339 }; 340 char path[32]; 341 342 const struct firmware *fw_entry; 343 int i, err; 344 345 for (i = 0; i < ARRAY_SIZE(fw_files); i++) { 346 sprintf(path, "pcxhr/%s", fw_files[i]); 347 if (request_firmware(&fw_entry, path, &mgr->pci->dev)) { 348 snd_printk(KERN_ERR "pcxhr: can't load firmware %s\n", path); 349 return -ENOENT; 350 } 351 /* fake hwdep dsp record */ 352 err = pcxhr_dsp_load(mgr, i, fw_entry); 353 release_firmware(fw_entry); 354 if (err < 0) 355 return err; 356 mgr->dsp_loaded |= 1 << i; 357 } 358 return 0; 359 } 360 361 MODULE_FIRMWARE("pcxhr/xi_1_882.dat"); 362 MODULE_FIRMWARE("pcxhr/xc_1_882.dat"); 363 MODULE_FIRMWARE("pcxhr/e321_512.e56"); 364 MODULE_FIRMWARE("pcxhr/b321_512.b56"); 365 MODULE_FIRMWARE("pcxhr/d321_512.d56"); 366 367 #else /* old style firmware loading */ 368 369 /* pcxhr hwdep interface id string */ 370 #define PCXHR_HWDEP_ID "pcxhr loader" 371 372 373 static int pcxhr_hwdep_dsp_status(struct snd_hwdep *hw, 374 struct snd_hwdep_dsp_status *info) 375 { 376 strcpy(info->id, "pcxhr"); 377 info->num_dsps = PCXHR_FIRMWARE_FILES_MAX_INDEX; 378 379 if (hw->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) 380 info->chip_ready = 1; 381 382 info->version = PCXHR_DRIVER_VERSION; 383 return 0; 384 } 385 386 static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw, 387 struct snd_hwdep_dsp_image *dsp) 388 { 389 struct pcxhr_mgr *mgr = hw->private_data; 390 int err; 391 struct firmware fw; 392 393 fw.size = dsp->length; 394 fw.data = vmalloc(fw.size); 395 if (! fw.data) { 396 snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image (%lu bytes)\n", 397 (unsigned long)fw.size); 398 return -ENOMEM; 399 } 400 if (copy_from_user((void *)fw.data, dsp->image, dsp->length)) { 401 vfree(fw.data); 402 return -EFAULT; 403 } 404 err = pcxhr_dsp_load(mgr, dsp->index, &fw); 405 vfree(fw.data); 406 if (err < 0) 407 return err; 408 mgr->dsp_loaded |= 1 << dsp->index; 409 return 0; 410 } 411 412 static int pcxhr_hwdep_open(struct snd_hwdep *hw, struct file *file) 413 { 414 return 0; 415 } 416 417 static int pcxhr_hwdep_release(struct snd_hwdep *hw, struct file *file) 418 { 419 return 0; 420 } 421 422 int pcxhr_setup_firmware(struct pcxhr_mgr *mgr) 423 { 424 int err; 425 struct snd_hwdep *hw; 426 427 /* only create hwdep interface for first cardX (see "index" module parameter)*/ 428 if ((err = snd_hwdep_new(mgr->chip[0]->card, PCXHR_HWDEP_ID, 0, &hw)) < 0) 429 return err; 430 431 hw->iface = SNDRV_HWDEP_IFACE_PCXHR; 432 hw->private_data = mgr; 433 hw->ops.open = pcxhr_hwdep_open; 434 hw->ops.release = pcxhr_hwdep_release; 435 hw->ops.dsp_status = pcxhr_hwdep_dsp_status; 436 hw->ops.dsp_load = pcxhr_hwdep_dsp_load; 437 hw->exclusive = 1; 438 mgr->dsp_loaded = 0; 439 sprintf(hw->name, PCXHR_HWDEP_ID); 440 441 if ((err = snd_card_register(mgr->chip[0]->card)) < 0) 442 return err; 443 return 0; 444 } 445 446 #endif /* SND_PCXHR_FW_LOADER */ 447