/* * snd_vx_inb - read a byte from the register * @offset: register offset
*/ staticunsignedchar vxp_inb(struct vx_core *chip, int offset)
{ return inb(vxp_reg_addr(chip, offset));
}
/* * snd_vx_outb - write a byte on the register * @offset: the register offset * @val: the value to write
*/ staticvoid vxp_outb(struct vx_core *chip, int offset, unsignedchar val)
{
outb(val, vxp_reg_addr(chip, offset));
}
/* * vx_check_magic - check the magic word on xilinx * * returns zero if a magic word is detected, or a negative error code.
*/ staticint vx_check_magic(struct vx_core *chip)
{ unsignedlong end_time = jiffies + HZ / 5; int c; do {
c = vx_inb(chip, CDSP); if (c == CDSP_MAGIC) return 0;
msleep(10);
} while (time_after_eq(end_time, jiffies));
dev_err(chip->card->dev, "cannot find xilinx magic word (%x)\n", c); return -EIO;
}
/* Set the reset CODEC bit to 1. */
vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_CODEC_RESET_MASK);
vx_inb(chip, CDSP);
msleep(10); /* Set the reset CODEC bit to 0. */
chip->regCDSP &= ~VXP_CDSP_CODEC_RESET_MASK;
vx_outb(chip, CDSP, chip->regCDSP);
vx_inb(chip, CDSP);
msleep(1);
}
/* * vx_load_xilinx_binary - load the xilinx binary image * the binary image is the binary array converted from the bitstream file.
*/ staticint vxp_load_xilinx_binary(struct vx_core *_chip, conststruct firmware *fw)
{ struct snd_vxpocket *chip = to_vxpocket(_chip); unsignedint i; int c; int regCSUER, regRUER; constunsignedchar *image; unsignedchar data;
/* * vx_test_and_ack - test and acknowledge interrupt * * called from irq hander, too * * spinlock held!
*/ staticint vxp_test_and_ack(struct vx_core *_chip)
{ struct snd_vxpocket *chip = to_vxpocket(_chip);
/* not booted yet? */ if (! (_chip->chip_status & VX_STAT_XILINX_LOADED)) return -ENXIO;
if (! (vx_inb(chip, DIALOG) & VXP_DLG_MEMIRQ_MASK)) return -EIO;
/* ok, interrupts generated, now ack it */ /* set ACQUIT bit up and down */
vx_outb(chip, DIALOG, chip->regDIALOG | VXP_DLG_ACK_MEMIRQ_MASK); /* useless read just to spend some time and maintain * the ACQUIT signal up for a while ( a bus cycle )
*/
vx_inb(chip, DIALOG);
vx_outb(chip, DIALOG, chip->regDIALOG & ~VXP_DLG_ACK_MEMIRQ_MASK);
/* Set the interrupt enable bit to 1 in CDSP register */ if (enable)
chip->regCDSP |= VXP_CDSP_VALID_IRQ_MASK; else
chip->regCDSP &= ~VXP_CDSP_VALID_IRQ_MASK;
vx_outb(chip, CDSP, chip->regCDSP);
}
/* * vx_setup_pseudo_dma - set up the pseudo dma read/write mode. * @do_write: 0 = read, 1 = set up for DMA write
*/ staticvoid vx_setup_pseudo_dma(struct vx_core *_chip, int do_write)
{ struct snd_vxpocket *chip = to_vxpocket(_chip);
/* Interrupt mode and HREQ pin enabled for host transmit / receive data transfers */
vx_outb(chip, ICR, do_write ? ICR_TREQ : ICR_RREQ); /* Reset the pseudo-dma register */
vx_inb(chip, ISR);
vx_outb(chip, ISR, 0);
/* Select DMA in read/write transfer mode and in 16-bit accesses */
chip->regDIALOG |= VXP_DLG_DMA16_SEL_MASK;
chip->regDIALOG |= do_write ? VXP_DLG_DMAWRITE_SEL_MASK : VXP_DLG_DMAREAD_SEL_MASK;
vx_outb(chip, DIALOG, chip->regDIALOG);
/* * vx_pseudo_dma_write - write bulk data on pseudo-DMA mode * @count: data length to transfer in bytes * * data size must be aligned to 6 bytes to ensure the 24bit alignment on DSP. * NB: call with a certain lock!
*/ staticvoid vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, struct vx_pipe *pipe, int count)
{ long port = vxp_reg_addr(chip, VX_DMA); int offset = pipe->hw_ptr; unsignedshort *addr = (unsignedshort *)(runtime->dma_area + offset);
vx_setup_pseudo_dma(chip, 1); if (offset + count >= pipe->buffer_bytes) { int length = pipe->buffer_bytes - offset;
count -= length;
length >>= 1; /* in 16bit words */ /* Transfer using pseudo-dma. */ for (; length > 0; length--) {
outw(*addr, port);
addr++;
}
addr = (unsignedshort *)runtime->dma_area;
pipe->hw_ptr = 0;
}
pipe->hw_ptr += count;
count >>= 1; /* in 16bit words */ /* Transfer using pseudo-dma. */ for (; count > 0; count--) {
outw(*addr, port);
addr++;
}
vx_release_pseudo_dma(chip);
}
/* * vx_pseudo_dma_read - read bulk data on pseudo DMA mode * @offset: buffer offset in bytes * @count: data length to transfer in bytes * * the read length must be aligned to 6 bytes, as well as write. * NB: call with a certain lock!
*/ staticvoid vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, struct vx_pipe *pipe, int count)
{ struct snd_vxpocket *pchip = to_vxpocket(chip); long port = vxp_reg_addr(chip, VX_DMA); int offset = pipe->hw_ptr; unsignedshort *addr = (unsignedshort *)(runtime->dma_area + offset);
if (snd_BUG_ON(count % 2)) return;
vx_setup_pseudo_dma(chip, 0); if (offset + count >= pipe->buffer_bytes) { int length = pipe->buffer_bytes - offset;
count -= length;
length >>= 1; /* in 16bit words */ /* Transfer using pseudo-dma. */ for (; length > 0; length--)
*addr++ = inw(port);
addr = (unsignedshort *)runtime->dma_area;
pipe->hw_ptr = 0;
}
pipe->hw_ptr += count;
count >>= 1; /* in 16bit words */ /* Transfer using pseudo-dma. */ for (; count > 1; count--)
*addr++ = inw(port); /* Disable DMA */
pchip->regDIALOG &= ~VXP_DLG_DMAREAD_SEL_MASK;
vx_outb(chip, DIALOG, pchip->regDIALOG); /* Read the last word (16 bits) */
*addr = inw(port); /* Disable 16-bit accesses */
pchip->regDIALOG &= ~VXP_DLG_DMA16_SEL_MASK;
vx_outb(chip, DIALOG, pchip->regDIALOG); /* HREQ pin disabled. */
vx_outb(chip, ICR, 0);
}
/* * write a codec data (24bit)
*/ staticvoid vxp_write_codec_reg(struct vx_core *chip, int codec, unsignedint data)
{ int i;
/* Activate access to the corresponding codec register */ if (! codec)
vx_inb(chip, LOFREQ); else
vx_inb(chip, CODEC2);
/* We have to send 24 bits (3 x 8 bits). Start with most signif. Bit */ for (i = 0; i < 24; i++, data <<= 1)
vx_outb(chip, DATA, ((data & 0x800000) ? VX_DATA_CODEC_MASK : 0));
/* Terminate access to codec registers */
vx_inb(chip, HIFREQ);
}
/* * vx_set_mic_boost - set mic boost level (on vxp440 only) * @boost: 0 = 20dB, 1 = +38dB
*/ void vx_set_mic_boost(struct vx_core *chip, int boost)
{ struct snd_vxpocket *pchip = to_vxpocket(chip);
/* * remap the linear value (0-8) to the actual value (0-15)
*/ staticint vx_compute_mic_level(int level)
{ switch (level) { case 5: level = 6 ; break; case 6: level = 8 ; break; case 7: level = 11; break; case 8: level = 15; break; default: break ;
} return level;
}
/* * vx_set_mic_level - set mic level (on vxpocket only) * @level: the mic level = 0 - 8 (max)
*/ void vx_set_mic_level(struct vx_core *chip, int level)
{ struct snd_vxpocket *pchip = to_vxpocket(chip);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.