Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Driver for Digigram pcxhr compatible soundcards
0004  *
0005  * hwdep device manager
0006  *
0007  * Copyright (c) 2004 by Digigram <alsa@digigram.com>
0008  */
0009 
0010 #include <linux/interrupt.h>
0011 #include <linux/vmalloc.h>
0012 #include <linux/firmware.h>
0013 #include <linux/pci.h>
0014 #include <linux/module.h>
0015 #include <linux/io.h>
0016 #include <sound/core.h>
0017 #include <sound/hwdep.h>
0018 #include "pcxhr.h"
0019 #include "pcxhr_mixer.h"
0020 #include "pcxhr_hwdep.h"
0021 #include "pcxhr_core.h"
0022 #include "pcxhr_mix22.h"
0023 
0024 
0025 static int pcxhr_sub_init(struct pcxhr_mgr *mgr);
0026 /*
0027  * get basic information and init pcxhr card
0028  */
0029 static int pcxhr_init_board(struct pcxhr_mgr *mgr)
0030 {
0031     int err;
0032     struct pcxhr_rmh rmh;
0033     int card_streams;
0034 
0035     /* calc the number of all streams used */
0036     if (mgr->mono_capture)
0037         card_streams = mgr->capture_chips * 2;
0038     else
0039         card_streams = mgr->capture_chips;
0040     card_streams += mgr->playback_chips * PCXHR_PLAYBACK_STREAMS;
0041 
0042     /* enable interrupts */
0043     pcxhr_enable_dsp(mgr);
0044 
0045     pcxhr_init_rmh(&rmh, CMD_SUPPORTED);
0046     err = pcxhr_send_msg(mgr, &rmh);
0047     if (err)
0048         return err;
0049     /* test 4, 8 or 12 phys out */
0050     if ((rmh.stat[0] & MASK_FIRST_FIELD) < mgr->playback_chips * 2)
0051         return -EINVAL;
0052     /* test 4, 8 or 2 phys in */
0053     if (((rmh.stat[0] >> (2 * FIELD_SIZE)) & MASK_FIRST_FIELD) <
0054         mgr->capture_chips * 2)
0055         return -EINVAL;
0056     /* test max nb substream per board */
0057     if ((rmh.stat[1] & 0x5F) < card_streams)
0058         return -EINVAL;
0059     /* test max nb substream per pipe */
0060     if (((rmh.stat[1] >> 7) & 0x5F) < PCXHR_PLAYBACK_STREAMS)
0061         return -EINVAL;
0062     dev_dbg(&mgr->pci->dev,
0063         "supported formats : playback=%x capture=%x\n",
0064             rmh.stat[2], rmh.stat[3]);
0065 
0066     pcxhr_init_rmh(&rmh, CMD_VERSION);
0067     /* firmware num for DSP */
0068     rmh.cmd[0] |= mgr->firmware_num;
0069     /* transfer granularity in samples (should be multiple of 48) */
0070     rmh.cmd[1] = (1<<23) + mgr->granularity;
0071     rmh.cmd_len = 2;
0072     err = pcxhr_send_msg(mgr, &rmh);
0073     if (err)
0074         return err;
0075     dev_dbg(&mgr->pci->dev,
0076         "PCXHR DSP version is %d.%d.%d\n", (rmh.stat[0]>>16)&0xff,
0077             (rmh.stat[0]>>8)&0xff, rmh.stat[0]&0xff);
0078     mgr->dsp_version = rmh.stat[0];
0079 
0080     if (mgr->is_hr_stereo)
0081         err = hr222_sub_init(mgr);
0082     else
0083         err = pcxhr_sub_init(mgr);
0084     return err;
0085 }
0086 
0087 static int pcxhr_sub_init(struct pcxhr_mgr *mgr)
0088 {
0089     int err;
0090     struct pcxhr_rmh rmh;
0091 
0092     /* get options */
0093     pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
0094     rmh.cmd[0] |= IO_NUM_REG_STATUS;
0095     rmh.cmd[1]  = REG_STATUS_OPTIONS;
0096     rmh.cmd_len = 2;
0097     err = pcxhr_send_msg(mgr, &rmh);
0098     if (err)
0099         return err;
0100 
0101     if ((rmh.stat[1] & REG_STATUS_OPT_DAUGHTER_MASK) ==
0102         REG_STATUS_OPT_ANALOG_BOARD)
0103         mgr->board_has_analog = 1;  /* analog addon board found */
0104 
0105     /* unmute inputs */
0106     err = pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS,
0107                       REG_CONT_UNMUTE_INPUTS, NULL);
0108     if (err)
0109         return err;
0110     /* unmute outputs (a write to IO_NUM_REG_MUTE_OUT mutes!) */
0111     pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
0112     rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
0113     if (DSP_EXT_CMD_SET(mgr)) {
0114         rmh.cmd[1]  = 1;    /* unmute digital plugs */
0115         rmh.cmd_len = 2;
0116     }
0117     err = pcxhr_send_msg(mgr, &rmh);
0118     return err;
0119 }
0120 
0121 void pcxhr_reset_board(struct pcxhr_mgr *mgr)
0122 {
0123     struct pcxhr_rmh rmh;
0124 
0125     if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
0126         /* mute outputs */
0127         if (!mgr->is_hr_stereo) {
0128         /* a read to IO_NUM_REG_MUTE_OUT register unmutes! */
0129         pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
0130         rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
0131         pcxhr_send_msg(mgr, &rmh);
0132         /* mute inputs */
0133         pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS,
0134                         0, NULL);
0135         }
0136         /* stereo cards mute with reset of dsp */
0137     }
0138     /* reset pcxhr dsp */
0139     if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_EPRM_INDEX))
0140         pcxhr_reset_dsp(mgr);
0141     /* reset second xilinx */
0142     if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_XLX_COM_INDEX)) {
0143         pcxhr_reset_xilinx_com(mgr);
0144         mgr->dsp_loaded = 1;
0145     }
0146     return;
0147 }
0148 
0149 
0150 /*
0151  *  allocate a playback/capture pipe (pcmp0/pcmc0)
0152  */
0153 static int pcxhr_dsp_allocate_pipe(struct pcxhr_mgr *mgr,
0154                    struct pcxhr_pipe *pipe,
0155                    int is_capture, int pin)
0156 {
0157     int stream_count, audio_count;
0158     int err;
0159     struct pcxhr_rmh rmh;
0160 
0161     if (is_capture) {
0162         stream_count = 1;
0163         if (mgr->mono_capture)
0164             audio_count = 1;
0165         else
0166             audio_count = 2;
0167     } else {
0168         stream_count = PCXHR_PLAYBACK_STREAMS;
0169         audio_count = 2;    /* always stereo */
0170     }
0171     dev_dbg(&mgr->pci->dev, "snd_add_ref_pipe pin(%d) pcm%c0\n",
0172             pin, is_capture ? 'c' : 'p');
0173     pipe->is_capture = is_capture;
0174     pipe->first_audio = pin;
0175     /* define pipe (P_PCM_ONLY_MASK (0x020000) is not necessary) */
0176     pcxhr_init_rmh(&rmh, CMD_RES_PIPE);
0177     pcxhr_set_pipe_cmd_params(&rmh, is_capture, pin,
0178                   audio_count, stream_count);
0179     rmh.cmd[1] |= 0x020000; /* add P_PCM_ONLY_MASK */
0180     if (DSP_EXT_CMD_SET(mgr)) {
0181         /* add channel mask to command */
0182       rmh.cmd[rmh.cmd_len++] = (audio_count == 1) ? 0x01 : 0x03;
0183     }
0184     err = pcxhr_send_msg(mgr, &rmh);
0185     if (err < 0) {
0186         dev_err(&mgr->pci->dev, "error pipe allocation "
0187                "(CMD_RES_PIPE) err=%x!\n", err);
0188         return err;
0189     }
0190     pipe->status = PCXHR_PIPE_DEFINED;
0191 
0192     return 0;
0193 }
0194 
0195 /*
0196  *  free playback/capture pipe (pcmp0/pcmc0)
0197  */
0198 #if 0
0199 static int pcxhr_dsp_free_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe)
0200 {
0201     struct pcxhr_rmh rmh;
0202     int capture_mask = 0;
0203     int playback_mask = 0;
0204     int err = 0;
0205 
0206     if (pipe->is_capture)
0207         capture_mask  = (1 << pipe->first_audio);
0208     else
0209         playback_mask = (1 << pipe->first_audio);
0210 
0211     /* stop one pipe */
0212     err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0);
0213     if (err < 0)
0214         dev_err(&mgr->pci->dev, "error stopping pipe!\n");
0215     /* release the pipe */
0216     pcxhr_init_rmh(&rmh, CMD_FREE_PIPE);
0217     pcxhr_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->first_audio,
0218                   0, 0);
0219     err = pcxhr_send_msg(mgr, &rmh);
0220     if (err < 0)
0221         dev_err(&mgr->pci->dev, "error pipe release "
0222                "(CMD_FREE_PIPE) err(%x)\n", err);
0223     pipe->status = PCXHR_PIPE_UNDEFINED;
0224     return err;
0225 }
0226 #endif
0227 
0228 
0229 static int pcxhr_config_pipes(struct pcxhr_mgr *mgr)
0230 {
0231     int err, i, j;
0232     struct snd_pcxhr *chip;
0233     struct pcxhr_pipe *pipe;
0234 
0235     /* allocate the pipes on the dsp */
0236     for (i = 0; i < mgr->num_cards; i++) {
0237         chip = mgr->chip[i];
0238         if (chip->nb_streams_play) {
0239             pipe = &chip->playback_pipe;
0240             err = pcxhr_dsp_allocate_pipe( mgr, pipe, 0, i*2);
0241             if (err)
0242                 return err;
0243             for(j = 0; j < chip->nb_streams_play; j++)
0244                 chip->playback_stream[j].pipe = pipe;
0245         }
0246         for (j = 0; j < chip->nb_streams_capt; j++) {
0247             pipe = &chip->capture_pipe[j];
0248             err = pcxhr_dsp_allocate_pipe(mgr, pipe, 1, i*2 + j);
0249             if (err)
0250                 return err;
0251             chip->capture_stream[j].pipe = pipe;
0252         }
0253     }
0254     return 0;
0255 }
0256 
0257 static int pcxhr_start_pipes(struct pcxhr_mgr *mgr)
0258 {
0259     int i, j;
0260     struct snd_pcxhr *chip;
0261     int playback_mask = 0;
0262     int capture_mask = 0;
0263 
0264     /* start all the pipes on the dsp */
0265     for (i = 0; i < mgr->num_cards; i++) {
0266         chip = mgr->chip[i];
0267         if (chip->nb_streams_play)
0268             playback_mask |= 1 << chip->playback_pipe.first_audio;
0269         for (j = 0; j < chip->nb_streams_capt; j++)
0270             capture_mask |= 1 << chip->capture_pipe[j].first_audio;
0271     }
0272     return pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
0273 }
0274 
0275 
0276 static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index,
0277               const struct firmware *dsp)
0278 {
0279     int err, card_index;
0280 
0281     dev_dbg(&mgr->pci->dev,
0282         "loading dsp [%d] size = %zd\n", index, dsp->size);
0283 
0284     switch (index) {
0285     case PCXHR_FIRMWARE_XLX_INT_INDEX:
0286         pcxhr_reset_xilinx_com(mgr);
0287         return pcxhr_load_xilinx_binary(mgr, dsp, 0);
0288 
0289     case PCXHR_FIRMWARE_XLX_COM_INDEX:
0290         pcxhr_reset_xilinx_com(mgr);
0291         return pcxhr_load_xilinx_binary(mgr, dsp, 1);
0292 
0293     case PCXHR_FIRMWARE_DSP_EPRM_INDEX:
0294         pcxhr_reset_dsp(mgr);
0295         return pcxhr_load_eeprom_binary(mgr, dsp);
0296 
0297     case PCXHR_FIRMWARE_DSP_BOOT_INDEX:
0298         return pcxhr_load_boot_binary(mgr, dsp);
0299 
0300     case PCXHR_FIRMWARE_DSP_MAIN_INDEX:
0301         err = pcxhr_load_dsp_binary(mgr, dsp);
0302         if (err)
0303             return err;
0304         break;  /* continue with first init */
0305     default:
0306         dev_err(&mgr->pci->dev, "wrong file index\n");
0307         return -EFAULT;
0308     } /* end of switch file index*/
0309 
0310     /* first communication with embedded */
0311     err = pcxhr_init_board(mgr);
0312         if (err < 0) {
0313         dev_err(&mgr->pci->dev, "pcxhr could not be set up\n");
0314         return err;
0315     }
0316     err = pcxhr_config_pipes(mgr);
0317         if (err < 0) {
0318         dev_err(&mgr->pci->dev, "pcxhr pipes could not be set up\n");
0319         return err;
0320     }
0321         /* create devices and mixer in accordance with HW options*/
0322         for (card_index = 0; card_index < mgr->num_cards; card_index++) {
0323         struct snd_pcxhr *chip = mgr->chip[card_index];
0324 
0325         err = pcxhr_create_pcm(chip);
0326         if (err < 0)
0327             return err;
0328 
0329         if (card_index == 0) {
0330             err = pcxhr_create_mixer(chip->mgr);
0331             if (err < 0)
0332                 return err;
0333         }
0334         err = snd_card_register(chip->card);
0335         if (err < 0)
0336             return err;
0337     }
0338     err = pcxhr_start_pipes(mgr);
0339         if (err < 0) {
0340         dev_err(&mgr->pci->dev, "pcxhr pipes could not be started\n");
0341         return err;
0342     }
0343     dev_dbg(&mgr->pci->dev,
0344         "pcxhr firmware downloaded and successfully set up\n");
0345 
0346     return 0;
0347 }
0348 
0349 /*
0350  * fw loader entry
0351  */
0352 int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
0353 {
0354     static const char * const fw_files[][5] = {
0355     [0] = { "xlxint.dat", "xlxc882hr.dat",
0356         "dspe882.e56", "dspb882hr.b56", "dspd882.d56" },
0357     [1] = { "xlxint.dat", "xlxc882e.dat",
0358         "dspe882.e56", "dspb882e.b56", "dspd882.d56" },
0359     [2] = { "xlxint.dat", "xlxc1222hr.dat",
0360         "dspe882.e56", "dspb1222hr.b56", "dspd1222.d56" },
0361     [3] = { "xlxint.dat", "xlxc1222e.dat",
0362         "dspe882.e56", "dspb1222e.b56", "dspd1222.d56" },
0363     [4] = { NULL, "xlxc222.dat",
0364         "dspe924.e56", "dspb924.b56", "dspd222.d56" },
0365     [5] = { NULL, "xlxc924.dat",
0366         "dspe924.e56", "dspb924.b56", "dspd222.d56" },
0367     };
0368     char path[32];
0369 
0370     const struct firmware *fw_entry;
0371     int i, err;
0372     int fw_set = mgr->fw_file_set;
0373 
0374     for (i = 0; i < 5; i++) {
0375         if (!fw_files[fw_set][i])
0376             continue;
0377         sprintf(path, "pcxhr/%s", fw_files[fw_set][i]);
0378         if (request_firmware(&fw_entry, path, &mgr->pci->dev)) {
0379             dev_err(&mgr->pci->dev,
0380                 "pcxhr: can't load firmware %s\n",
0381                    path);
0382             return -ENOENT;
0383         }
0384         /* fake hwdep dsp record */
0385         err = pcxhr_dsp_load(mgr, i, fw_entry);
0386         release_firmware(fw_entry);
0387         if (err < 0)
0388             return err;
0389         mgr->dsp_loaded |= 1 << i;
0390     }
0391     return 0;
0392 }
0393 
0394 MODULE_FIRMWARE("pcxhr/xlxint.dat");
0395 MODULE_FIRMWARE("pcxhr/xlxc882hr.dat");
0396 MODULE_FIRMWARE("pcxhr/xlxc882e.dat");
0397 MODULE_FIRMWARE("pcxhr/dspe882.e56");
0398 MODULE_FIRMWARE("pcxhr/dspb882hr.b56");
0399 MODULE_FIRMWARE("pcxhr/dspb882e.b56");
0400 MODULE_FIRMWARE("pcxhr/dspd882.d56");
0401 
0402 MODULE_FIRMWARE("pcxhr/xlxc1222hr.dat");
0403 MODULE_FIRMWARE("pcxhr/xlxc1222e.dat");
0404 MODULE_FIRMWARE("pcxhr/dspb1222hr.b56");
0405 MODULE_FIRMWARE("pcxhr/dspb1222e.b56");
0406 MODULE_FIRMWARE("pcxhr/dspd1222.d56");
0407 
0408 MODULE_FIRMWARE("pcxhr/xlxc222.dat");
0409 MODULE_FIRMWARE("pcxhr/xlxc924.dat");
0410 MODULE_FIRMWARE("pcxhr/dspe924.e56");
0411 MODULE_FIRMWARE("pcxhr/dspb924.b56");
0412 MODULE_FIRMWARE("pcxhr/dspd222.d56");