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 */ 504