818 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for Digigram VX soundcards4 *5 * Hardware core part6 *7 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>8 */9 10#include <linux/delay.h>11#include <linux/slab.h>12#include <linux/interrupt.h>13#include <linux/init.h>14#include <linux/device.h>15#include <linux/firmware.h>16#include <linux/module.h>17#include <linux/io.h>18#include <sound/core.h>19#include <sound/pcm.h>20#include <sound/asoundef.h>21#include <sound/info.h>22#include <sound/vx_core.h>23#include "vx_cmd.h"24 25MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");26MODULE_DESCRIPTION("Common routines for Digigram VX drivers");27MODULE_LICENSE("GPL");28 29 30/*31 * vx_check_reg_bit - wait for the specified bit is set/reset on a register32 * @reg: register to check33 * @mask: bit mask34 * @bit: resultant bit to be checked35 * @time: time-out of loop in msec36 *37 * returns zero if a bit matches, or a negative error code.38 */39int snd_vx_check_reg_bit(struct vx_core *chip, int reg, int mask, int bit, int time)40{41 unsigned long end_time = jiffies + (time * HZ + 999) / 1000;42 static const char * const reg_names[VX_REG_MAX] = {43 "ICR", "CVR", "ISR", "IVR", "RXH", "RXM", "RXL",44 "DMA", "CDSP", "RFREQ", "RUER/V2", "DATA", "MEMIRQ",45 "ACQ", "BIT0", "BIT1", "MIC0", "MIC1", "MIC2",46 "MIC3", "INTCSR", "CNTRL", "GPIOC",47 "LOFREQ", "HIFREQ", "CSUER", "RUER"48 };49 50 do {51 if ((snd_vx_inb(chip, reg) & mask) == bit)52 return 0;53 //msleep(10);54 } while (time_after_eq(end_time, jiffies));55 dev_dbg(chip->card->dev,56 "vx_check_reg_bit: timeout, reg=%s, mask=0x%x, val=0x%x\n",57 reg_names[reg], mask, snd_vx_inb(chip, reg));58 return -EIO;59}60 61EXPORT_SYMBOL(snd_vx_check_reg_bit);62 63/*64 * vx_send_irq_dsp - set command irq bit65 * @num: the requested IRQ type, IRQ_XXX66 *67 * this triggers the specified IRQ request68 * returns 0 if successful, or a negative error code.69 * 70 */71static int vx_send_irq_dsp(struct vx_core *chip, int num)72{73 int nirq;74 75 /* wait for Hc = 0 */76 if (snd_vx_check_reg_bit(chip, VX_CVR, CVR_HC, 0, 200) < 0)77 return -EIO;78 79 nirq = num;80 if (vx_has_new_dsp(chip))81 nirq += VXP_IRQ_OFFSET;82 vx_outb(chip, CVR, (nirq >> 1) | CVR_HC);83 return 0;84}85 86 87/*88 * vx_reset_chk - reset CHK bit on ISR89 *90 * returns 0 if successful, or a negative error code.91 */92static int vx_reset_chk(struct vx_core *chip)93{94 /* Reset irq CHK */95 if (vx_send_irq_dsp(chip, IRQ_RESET_CHK) < 0)96 return -EIO;97 /* Wait until CHK = 0 */98 if (vx_check_isr(chip, ISR_CHK, 0, 200) < 0)99 return -EIO;100 return 0;101}102 103/*104 * vx_transfer_end - terminate message transfer105 * @cmd: IRQ message to send (IRQ_MESS_XXX_END)106 *107 * returns 0 if successful, or a negative error code.108 * the error code can be VX-specific, retrieved via vx_get_error().109 * NB: call with mutex held!110 */111static int vx_transfer_end(struct vx_core *chip, int cmd)112{113 int err;114 115 err = vx_reset_chk(chip);116 if (err < 0)117 return err;118 119 /* irq MESS_READ/WRITE_END */120 err = vx_send_irq_dsp(chip, cmd);121 if (err < 0)122 return err;123 124 /* Wait CHK = 1 */125 err = vx_wait_isr_bit(chip, ISR_CHK);126 if (err < 0)127 return err;128 129 /* If error, Read RX */130 err = vx_inb(chip, ISR);131 if (err & ISR_ERR) {132 err = vx_wait_for_rx_full(chip);133 if (err < 0) {134 dev_dbg(chip->card->dev,135 "transfer_end: error in rx_full\n");136 return err;137 }138 err = vx_inb(chip, RXH) << 16;139 err |= vx_inb(chip, RXM) << 8;140 err |= vx_inb(chip, RXL);141 dev_dbg(chip->card->dev, "transfer_end: error = 0x%x\n", err);142 return -(VX_ERR_MASK | err);143 }144 return 0;145}146 147/*148 * vx_read_status - return the status rmh149 * @rmh: rmh record to store the status150 *151 * returns 0 if successful, or a negative error code.152 * the error code can be VX-specific, retrieved via vx_get_error().153 * NB: call with mutex held!154 */155static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh)156{157 int i, err, val, size;158 159 /* no read necessary? */160 if (rmh->DspStat == RMH_SSIZE_FIXED && rmh->LgStat == 0)161 return 0;162 163 /* Wait for RX full (with timeout protection)164 * The first word of status is in RX165 */166 err = vx_wait_for_rx_full(chip);167 if (err < 0)168 return err;169 170 /* Read RX */171 val = vx_inb(chip, RXH) << 16;172 val |= vx_inb(chip, RXM) << 8;173 val |= vx_inb(chip, RXL);174 175 /* If status given by DSP, let's decode its size */176 switch (rmh->DspStat) {177 case RMH_SSIZE_ARG:178 size = val & 0xff;179 rmh->Stat[0] = val & 0xffff00;180 rmh->LgStat = size + 1;181 break;182 case RMH_SSIZE_MASK:183 /* Let's count the arg numbers from a mask */184 rmh->Stat[0] = val;185 size = 0;186 while (val) {187 if (val & 0x01)188 size++;189 val >>= 1;190 }191 rmh->LgStat = size + 1;192 break;193 default:194 /* else retrieve the status length given by the driver */195 size = rmh->LgStat;196 rmh->Stat[0] = val; /* Val is the status 1st word */197 size--; /* hence adjust remaining length */198 break;199 }200 201 if (size < 1)202 return 0;203 if (snd_BUG_ON(size >= SIZE_MAX_STATUS))204 return -EINVAL;205 206 for (i = 1; i <= size; i++) {207 /* trigger an irq MESS_WRITE_NEXT */208 err = vx_send_irq_dsp(chip, IRQ_MESS_WRITE_NEXT);209 if (err < 0)210 return err;211 /* Wait for RX full (with timeout protection) */212 err = vx_wait_for_rx_full(chip);213 if (err < 0)214 return err;215 rmh->Stat[i] = vx_inb(chip, RXH) << 16;216 rmh->Stat[i] |= vx_inb(chip, RXM) << 8;217 rmh->Stat[i] |= vx_inb(chip, RXL);218 }219 220 return vx_transfer_end(chip, IRQ_MESS_WRITE_END);221}222 223 224#define MASK_MORE_THAN_1_WORD_COMMAND 0x00008000225#define MASK_1_WORD_COMMAND 0x00ff7fff226 227/*228 * vx_send_msg_nolock - send a DSP message and read back the status229 * @rmh: the rmh record to send and receive230 *231 * returns 0 if successful, or a negative error code.232 * the error code can be VX-specific, retrieved via vx_get_error().233 * 234 * this function doesn't call mutex lock at all.235 */236int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)237{238 int i, err;239 240 if (chip->chip_status & VX_STAT_IS_STALE)241 return -EBUSY;242 243 err = vx_reset_chk(chip);244 if (err < 0) {245 dev_dbg(chip->card->dev, "vx_send_msg: vx_reset_chk error\n");246 return err;247 }248 249 /* Check bit M is set according to length of the command */250 if (rmh->LgCmd > 1)251 rmh->Cmd[0] |= MASK_MORE_THAN_1_WORD_COMMAND;252 else253 rmh->Cmd[0] &= MASK_1_WORD_COMMAND;254 255 /* Wait for TX empty */256 err = vx_wait_isr_bit(chip, ISR_TX_EMPTY);257 if (err < 0) {258 dev_dbg(chip->card->dev, "vx_send_msg: wait tx empty error\n");259 return err;260 }261 262 /* Write Cmd[0] */263 vx_outb(chip, TXH, (rmh->Cmd[0] >> 16) & 0xff);264 vx_outb(chip, TXM, (rmh->Cmd[0] >> 8) & 0xff);265 vx_outb(chip, TXL, rmh->Cmd[0] & 0xff);266 267 /* Trigger irq MESSAGE */268 err = vx_send_irq_dsp(chip, IRQ_MESSAGE);269 if (err < 0) {270 dev_dbg(chip->card->dev,271 "vx_send_msg: send IRQ_MESSAGE error\n");272 return err;273 }274 275 /* Wait for CHK = 1 */276 err = vx_wait_isr_bit(chip, ISR_CHK);277 if (err < 0)278 return err;279 280 /* If error, get error value from RX */281 if (vx_inb(chip, ISR) & ISR_ERR) {282 err = vx_wait_for_rx_full(chip);283 if (err < 0) {284 dev_dbg(chip->card->dev,285 "vx_send_msg: rx_full read error\n");286 return err;287 }288 err = vx_inb(chip, RXH) << 16;289 err |= vx_inb(chip, RXM) << 8;290 err |= vx_inb(chip, RXL);291 dev_dbg(chip->card->dev,292 "msg got error = 0x%x at cmd[0]\n", err);293 err = -(VX_ERR_MASK | err);294 return err;295 }296 297 /* Send the other words */298 if (rmh->LgCmd > 1) {299 for (i = 1; i < rmh->LgCmd; i++) {300 /* Wait for TX ready */301 err = vx_wait_isr_bit(chip, ISR_TX_READY);302 if (err < 0) {303 dev_dbg(chip->card->dev,304 "vx_send_msg: tx_ready error\n");305 return err;306 }307 308 /* Write Cmd[i] */309 vx_outb(chip, TXH, (rmh->Cmd[i] >> 16) & 0xff);310 vx_outb(chip, TXM, (rmh->Cmd[i] >> 8) & 0xff);311 vx_outb(chip, TXL, rmh->Cmd[i] & 0xff);312 313 /* Trigger irq MESS_READ_NEXT */314 err = vx_send_irq_dsp(chip, IRQ_MESS_READ_NEXT);315 if (err < 0) {316 dev_dbg(chip->card->dev,317 "vx_send_msg: IRQ_READ_NEXT error\n");318 return err;319 }320 }321 /* Wait for TX empty */322 err = vx_wait_isr_bit(chip, ISR_TX_READY);323 if (err < 0) {324 dev_dbg(chip->card->dev,325 "vx_send_msg: TX_READY error\n");326 return err;327 }328 /* End of transfer */329 err = vx_transfer_end(chip, IRQ_MESS_READ_END);330 if (err < 0)331 return err;332 }333 334 return vx_read_status(chip, rmh);335}336 337 338/*339 * vx_send_msg - send a DSP message with mutex340 * @rmh: the rmh record to send and receive341 *342 * returns 0 if successful, or a negative error code.343 * see vx_send_msg_nolock().344 */345int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh)346{347 int err;348 349 mutex_lock(&chip->lock);350 err = vx_send_msg_nolock(chip, rmh);351 mutex_unlock(&chip->lock);352 return err;353}354 355 356/*357 * vx_send_rih_nolock - send an RIH to xilinx358 * @cmd: the command to send359 *360 * returns 0 if successful, or a negative error code.361 * the error code can be VX-specific, retrieved via vx_get_error().362 *363 * this function doesn't call mutex at all.364 *365 * unlike RMH, no command is sent to DSP.366 */367int vx_send_rih_nolock(struct vx_core *chip, int cmd)368{369 int err;370 371 if (chip->chip_status & VX_STAT_IS_STALE)372 return -EBUSY;373 374 err = vx_reset_chk(chip);375 if (err < 0)376 return err;377 /* send the IRQ */378 err = vx_send_irq_dsp(chip, cmd);379 if (err < 0)380 return err;381 /* Wait CHK = 1 */382 err = vx_wait_isr_bit(chip, ISR_CHK);383 if (err < 0)384 return err;385 /* If error, read RX */386 if (vx_inb(chip, ISR) & ISR_ERR) {387 err = vx_wait_for_rx_full(chip);388 if (err < 0)389 return err;390 err = vx_inb(chip, RXH) << 16;391 err |= vx_inb(chip, RXM) << 8;392 err |= vx_inb(chip, RXL);393 return -(VX_ERR_MASK | err);394 }395 return 0;396}397 398 399/*400 * vx_send_rih - send an RIH with mutex401 * @cmd: the command to send402 *403 * see vx_send_rih_nolock().404 */405int vx_send_rih(struct vx_core *chip, int cmd)406{407 int err;408 409 mutex_lock(&chip->lock);410 err = vx_send_rih_nolock(chip, cmd);411 mutex_unlock(&chip->lock);412 return err;413}414 415#define END_OF_RESET_WAIT_TIME 500 /* us */416 417/**418 * snd_vx_load_boot_image - boot up the xilinx interface419 * @chip: VX core instance420 * @boot: the boot record to load421 */422int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *boot)423{424 unsigned int i;425 int no_fillup = vx_has_new_dsp(chip);426 427 /* check the length of boot image */428 if (boot->size <= 0)429 return -EINVAL;430 if (boot->size % 3)431 return -EINVAL;432#if 0433 {434 /* more strict check */435 unsigned int c = ((u32)boot->data[0] << 16) | ((u32)boot->data[1] << 8) | boot->data[2];436 if (boot->size != (c + 2) * 3)437 return -EINVAL;438 }439#endif440 441 /* reset dsp */442 vx_reset_dsp(chip);443 444 udelay(END_OF_RESET_WAIT_TIME); /* another wait? */445 446 /* download boot strap */447 for (i = 0; i < 0x600; i += 3) {448 if (i >= boot->size) {449 if (no_fillup)450 break;451 if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) {452 dev_err(chip->card->dev, "dsp boot failed at %d\n", i);453 return -EIO;454 }455 vx_outb(chip, TXH, 0);456 vx_outb(chip, TXM, 0);457 vx_outb(chip, TXL, 0);458 } else {459 const unsigned char *image = boot->data + i;460 if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) {461 dev_err(chip->card->dev, "dsp boot failed at %d\n", i);462 return -EIO;463 }464 vx_outb(chip, TXH, image[0]);465 vx_outb(chip, TXM, image[1]);466 vx_outb(chip, TXL, image[2]);467 }468 }469 return 0;470}471 472EXPORT_SYMBOL(snd_vx_load_boot_image);473 474/*475 * vx_test_irq_src - query the source of interrupts476 *477 * called from irq handler only478 */479static int vx_test_irq_src(struct vx_core *chip, unsigned int *ret)480{481 int err;482 483 vx_init_rmh(&chip->irq_rmh, CMD_TEST_IT);484 mutex_lock(&chip->lock);485 err = vx_send_msg_nolock(chip, &chip->irq_rmh);486 if (err < 0)487 *ret = 0;488 else489 *ret = chip->irq_rmh.Stat[0];490 mutex_unlock(&chip->lock);491 return err;492}493 494 495/*496 * snd_vx_threaded_irq_handler - threaded irq handler497 */498irqreturn_t snd_vx_threaded_irq_handler(int irq, void *dev)499{500 struct vx_core *chip = dev;501 unsigned int events;502 503 if (chip->chip_status & VX_STAT_IS_STALE)504 return IRQ_HANDLED;505 506 if (vx_test_irq_src(chip, &events) < 0)507 return IRQ_HANDLED;508 509 /* We must prevent any application using this DSP510 * and block any further request until the application511 * either unregisters or reloads the DSP512 */513 if (events & FATAL_DSP_ERROR) {514 dev_err(chip->card->dev, "vx_core: fatal DSP error!!\n");515 return IRQ_HANDLED;516 }517 518 /* The start on time code conditions are filled (ie the time code519 * received by the board is equal to one of those given to it).520 */521 if (events & TIME_CODE_EVENT_PENDING) {522 ; /* so far, nothing to do yet */523 }524 525 /* The frequency has changed on the board (UER mode). */526 if (events & FREQUENCY_CHANGE_EVENT_PENDING)527 vx_change_frequency(chip);528 529 /* update the pcm streams */530 vx_pcm_update_intr(chip, events);531 return IRQ_HANDLED;532}533EXPORT_SYMBOL(snd_vx_threaded_irq_handler);534 535/**536 * snd_vx_irq_handler - interrupt handler537 * @irq: irq number538 * @dev: VX core instance539 */540irqreturn_t snd_vx_irq_handler(int irq, void *dev)541{542 struct vx_core *chip = dev;543 544 if (! (chip->chip_status & VX_STAT_CHIP_INIT) ||545 (chip->chip_status & VX_STAT_IS_STALE))546 return IRQ_NONE;547 if (! vx_test_and_ack(chip))548 return IRQ_WAKE_THREAD;549 return IRQ_NONE;550}551 552EXPORT_SYMBOL(snd_vx_irq_handler);553 554/*555 */556static void vx_reset_board(struct vx_core *chip, int cold_reset)557{558 if (snd_BUG_ON(!chip->ops->reset_board))559 return;560 561 /* current source, later sync'ed with target */562 chip->audio_source = VX_AUDIO_SRC_LINE;563 if (cold_reset) {564 chip->audio_source_target = chip->audio_source;565 chip->clock_source = INTERNAL_QUARTZ;566 chip->clock_mode = VX_CLOCK_MODE_AUTO;567 chip->freq = 48000;568 chip->uer_detected = VX_UER_MODE_NOT_PRESENT;569 chip->uer_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;570 }571 572 chip->ops->reset_board(chip, cold_reset);573 574 vx_reset_codec(chip, cold_reset);575 576 vx_set_internal_clock(chip, chip->freq);577 578 /* Reset the DSP */579 vx_reset_dsp(chip);580 581 if (vx_is_pcmcia(chip)) {582 /* Acknowledge any pending IRQ and reset the MEMIRQ flag. */583 vx_test_and_ack(chip);584 vx_validate_irq(chip, 1);585 }586 587 /* init CBits */588 vx_set_iec958_status(chip, chip->uer_bits);589}590 591 592/*593 * proc interface594 */595 596static void vx_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)597{598 struct vx_core *chip = entry->private_data;599 static const char * const audio_src_vxp[] = { "Line", "Mic", "Digital" };600 static const char * const audio_src_vx2[] = { "Analog", "Analog", "Digital" };601 static const char * const clock_mode[] = { "Auto", "Internal", "External" };602 static const char * const clock_src[] = { "Internal", "External" };603 static const char * const uer_type[] = { "Consumer", "Professional", "Not Present" };604 605 snd_iprintf(buffer, "%s\n", chip->card->longname);606 snd_iprintf(buffer, "Xilinx Firmware: %s\n",607 (chip->chip_status & VX_STAT_XILINX_LOADED) ? "Loaded" : "No");608 snd_iprintf(buffer, "Device Initialized: %s\n",609 (chip->chip_status & VX_STAT_DEVICE_INIT) ? "Yes" : "No");610 snd_iprintf(buffer, "DSP audio info:");611 if (chip->audio_info & VX_AUDIO_INFO_REAL_TIME)612 snd_iprintf(buffer, " realtime");613 if (chip->audio_info & VX_AUDIO_INFO_OFFLINE)614 snd_iprintf(buffer, " offline");615 if (chip->audio_info & VX_AUDIO_INFO_MPEG1)616 snd_iprintf(buffer, " mpeg1");617 if (chip->audio_info & VX_AUDIO_INFO_MPEG2)618 snd_iprintf(buffer, " mpeg2");619 if (chip->audio_info & VX_AUDIO_INFO_LINEAR_8)620 snd_iprintf(buffer, " linear8");621 if (chip->audio_info & VX_AUDIO_INFO_LINEAR_16)622 snd_iprintf(buffer, " linear16");623 if (chip->audio_info & VX_AUDIO_INFO_LINEAR_24)624 snd_iprintf(buffer, " linear24");625 snd_iprintf(buffer, "\n");626 snd_iprintf(buffer, "Input Source: %s\n", vx_is_pcmcia(chip) ?627 audio_src_vxp[chip->audio_source] :628 audio_src_vx2[chip->audio_source]);629 snd_iprintf(buffer, "Clock Mode: %s\n", clock_mode[chip->clock_mode]);630 snd_iprintf(buffer, "Clock Source: %s\n", clock_src[chip->clock_source]);631 snd_iprintf(buffer, "Frequency: %d\n", chip->freq);632 snd_iprintf(buffer, "Detected Frequency: %d\n", chip->freq_detected);633 snd_iprintf(buffer, "Detected UER type: %s\n", uer_type[chip->uer_detected]);634 snd_iprintf(buffer, "Min/Max/Cur IBL: %d/%d/%d (granularity=%d)\n",635 chip->ibl.min_size, chip->ibl.max_size, chip->ibl.size,636 chip->ibl.granularity);637}638 639static void vx_proc_init(struct vx_core *chip)640{641 snd_card_ro_proc_new(chip->card, "vx-status", chip, vx_proc_read);642}643 644 645/**646 * snd_vx_dsp_boot - load the DSP boot647 * @chip: VX core instance648 * @boot: firmware data649 */650int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *boot)651{652 int err;653 int cold_reset = !(chip->chip_status & VX_STAT_DEVICE_INIT);654 655 vx_reset_board(chip, cold_reset);656 vx_validate_irq(chip, 0);657 658 err = snd_vx_load_boot_image(chip, boot);659 if (err < 0)660 return err;661 msleep(10);662 663 return 0;664}665 666EXPORT_SYMBOL(snd_vx_dsp_boot);667 668/**669 * snd_vx_dsp_load - load the DSP image670 * @chip: VX core instance671 * @dsp: firmware data672 */673int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp)674{675 unsigned int i;676 int err;677 unsigned int csum = 0;678 const unsigned char *image, *cptr;679 680 if (dsp->size % 3)681 return -EINVAL;682 683 vx_toggle_dac_mute(chip, 1);684 685 /* Transfert data buffer from PC to DSP */686 for (i = 0; i < dsp->size; i += 3) {687 image = dsp->data + i;688 /* Wait DSP ready for a new read */689 err = vx_wait_isr_bit(chip, ISR_TX_EMPTY);690 if (err < 0) {691 dev_err(chip->card->dev,692 "dsp loading error at position %d\n", i);693 return err;694 }695 cptr = image;696 csum ^= *cptr;697 csum = (csum >> 24) | (csum << 8);698 vx_outb(chip, TXH, *cptr++);699 csum ^= *cptr;700 csum = (csum >> 24) | (csum << 8);701 vx_outb(chip, TXM, *cptr++);702 csum ^= *cptr;703 csum = (csum >> 24) | (csum << 8);704 vx_outb(chip, TXL, *cptr++);705 }706 707 msleep(200);708 709 err = vx_wait_isr_bit(chip, ISR_CHK);710 if (err < 0)711 return err;712 713 vx_toggle_dac_mute(chip, 0);714 715 vx_test_and_ack(chip);716 vx_validate_irq(chip, 1);717 718 return 0;719}720 721EXPORT_SYMBOL(snd_vx_dsp_load);722 723#ifdef CONFIG_PM724/*725 * suspend726 */727int snd_vx_suspend(struct vx_core *chip)728{729 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);730 chip->chip_status |= VX_STAT_IN_SUSPEND;731 732 return 0;733}734 735EXPORT_SYMBOL(snd_vx_suspend);736 737/*738 * resume739 */740int snd_vx_resume(struct vx_core *chip)741{742 int i, err;743 744 chip->chip_status &= ~VX_STAT_CHIP_INIT;745 746 for (i = 0; i < 4; i++) {747 if (! chip->firmware[i])748 continue;749 err = chip->ops->load_dsp(chip, i, chip->firmware[i]);750 if (err < 0) {751 dev_err(chip->card->dev,752 "vx: firmware resume error at DSP %d\n", i);753 return -EIO;754 }755 }756 757 chip->chip_status |= VX_STAT_CHIP_INIT;758 chip->chip_status &= ~VX_STAT_IN_SUSPEND;759 760 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);761 return 0;762}763 764EXPORT_SYMBOL(snd_vx_resume);765#endif766 767static void snd_vx_release(struct device *dev, void *data)768{769 snd_vx_free_firmware(data);770}771 772/**773 * snd_vx_create - constructor for struct vx_core774 * @card: card instance775 * @hw: hardware specific record776 * @ops: VX ops pointer777 * @extra_size: extra byte size to allocate appending to chip778 *779 * this function allocates the instance and prepare for the hardware780 * initialization.781 *782 * The object is managed via devres, and will be automatically released.783 *784 * return the instance pointer if successful, NULL in error.785 */786struct vx_core *snd_vx_create(struct snd_card *card,787 const struct snd_vx_hardware *hw,788 const struct snd_vx_ops *ops,789 int extra_size)790{791 struct vx_core *chip;792 793 if (snd_BUG_ON(!card || !hw || !ops))794 return NULL;795 796 chip = devres_alloc(snd_vx_release, sizeof(*chip) + extra_size,797 GFP_KERNEL);798 if (!chip)799 return NULL;800 mutex_init(&chip->lock);801 chip->irq = -1;802 chip->hw = hw;803 chip->type = hw->type;804 chip->ops = ops;805 mutex_init(&chip->mixer_mutex);806 807 chip->card = card;808 card->private_data = chip;809 strcpy(card->driver, hw->name);810 sprintf(card->shortname, "Digigram %s", hw->name);811 812 vx_proc_init(chip);813 814 return chip;815}816 817EXPORT_SYMBOL(snd_vx_create);818