cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vx_core.c (20150B)


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