Commit b706cbf8 authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA update

   - CS4231 - added sparc support to merge sparc/cs4231.c code
   - ICE1712
     - added support for AK4529
     - added support for Midiman M-Audio Delta410
   - USB driver
     - fixed against newer USB API but allow compilation under 2.4
parent a1a1c402
......@@ -26,9 +26,24 @@
#include "pcm.h"
#include "timer.h"
#ifdef CONFIG_SBUS
#define SBUS_SUPPORT
#include <asm/sbus.h>
#endif
#if defined(CONFIG_PCI) && defined(CONFIG_SPARC64)
#define EBUS_SUPPORT
#include <linux/pci.h>
#include <asm/ebus.h>
#endif
#if !defined(SBUS_SUPPORT) && !defined(EBUS_SUPPORT)
#define LEGACY_SUPPORT
#endif
/* IO ports */
#define CS4231P(chip, x) ((chip)->port + c_d_c_CS4231##x)
#define CS4231P(x) (c_d_c_CS4231##x)
#define c_d_c_CS4231REGSEL 0
#define c_d_c_CS4231REG 1
......@@ -221,17 +236,38 @@ typedef struct _snd_cs4231 cs4231_t;
struct _snd_cs4231 {
unsigned long port; /* base i/o port */
#ifdef LEGACY_SUPPORT
struct resource *res_port;
unsigned long cport; /* control base i/o port (CS4236) */
struct resource *res_cport;
int irq; /* IRQ line */
int dma1; /* playback DMA */
int dma2; /* record DMA */
#endif
unsigned short version; /* version of CODEC chip */
unsigned short mode; /* see to CS4231_MODE_XXXX */
unsigned short hardware; /* see to CS4231_HW_XXXX */
unsigned short hwshare; /* shared resources */
unsigned short single_dma:1; /* forced single DMA mode (GUS 16-bit daughter board) or dma1 == dma2 */
unsigned short single_dma:1, /* forced single DMA mode (GUS 16-bit daughter board) or dma1 == dma2 */
ebus_flag:1; /* SPARC: EBUS present */
#ifdef EBUS_SUPPORT
struct ebus_dma_info eb2c;
struct ebus_dma_info eb2p;
#endif
#if defined(SBUS_SUPPORT) || defined(EBUS_SUPPORT)
union {
#ifdef SBUS_SUPPORT
struct sbus_dev *sdev;
#endif
#ifdef EBUS_SUPPORT
struct pci_dev *pdev;
#endif
} dev_u;
unsigned int p_periods_sent;
unsigned int c_periods_sent;
#endif
snd_card_t *card;
snd_pcm_t *pcm;
......@@ -245,8 +281,10 @@ struct _snd_cs4231 {
int mce_bit;
int calibrate_mute;
int sw_3d_bit;
#ifdef LEGACY_SUPPORT
unsigned int p_dma_size;
unsigned int c_dma_size;
#endif
spinlock_t reg_lock;
struct semaphore mce_mutex;
......@@ -255,14 +293,17 @@ struct _snd_cs4231 {
int (*rate_constraint) (snd_pcm_runtime_t *runtime);
void (*set_playback_format) (cs4231_t *chip, snd_pcm_hw_params_t *hw_params, unsigned char pdfr);
void (*set_capture_format) (cs4231_t *chip, snd_pcm_hw_params_t *hw_params, unsigned char cdfr);
void (*trigger) (cs4231_t *chip, unsigned int what, int start);
#ifdef CONFIG_PM
struct pm_dev *pm_dev;
void (*suspend) (cs4231_t *chip);
void (*resume) (cs4231_t *chip);
#endif
void *dma_private_data;
#ifdef LEGACY_SUPPORT
int (*claim_dma) (cs4231_t *chip, void *dma_private_data, int dma);
int (*release_dma) (cs4231_t *chip, void *dma_private_data, int dma);
#endif
};
/* exported functions */
......
/* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc5"
#define CONFIG_SND_DATE " (Tue Oct 29 09:19:27 2002 UTC)"
#define CONFIG_SND_DATE " (Sun Nov 10 19:48:18 2002 UTC)"
......@@ -124,6 +124,48 @@ static unsigned char snd_cs4231_original_image[32] =
* Basic I/O functions
*/
#if !defined(EBUS_SUPPORT) && !defined(SBUS_SUPPORT)
#define __CS4231_INLINE__ inline
#else
#define __CS4231_INLINE__ /* nothing */
#endif
static __CS4231_INLINE__ void cs4231_outb(cs4231_t *chip, u8 offset, u8 val)
{
#ifdef EBUS_SUPPORT
if (chip->ebus->flag) {
writeb(val, chip->port + (offset << 2));
} else {
#endif
#ifdef SBUS_SUPPORT
sbus_writeb(val, chip->port + (offset << 2));
#endif
#ifdef EBUS_SUPPORT
}
#endif
#ifdef LEGACY_SUPPORT
outb(val, chip->port + offset);
#endif
}
static __CS4231_INLINE__ u8 cs4231_inb(cs4231_t *chip, u8 offset)
{
#ifdef EBUS_SUPPORT
if (chip->ebus_flag) {
return readb(chip->port + (offset << 2));
} else {
#endif
#ifdef SBUS_SUPPORT
return sbus_writeb(chip->port + (offset << 2));
#endif
#ifdef EBUS_SUPPORT
}
#endif
#ifdef LEGACY_SUPPORT
return inb(chip->port + offset);
#endif
}
void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
unsigned char mask, unsigned char value)
{
......@@ -131,21 +173,21 @@ void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
unsigned char tmp;
for (timeout = 250;
timeout > 0 && (inb(CS4231P(chip, REGSEL)) & CS4231_INIT);
timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
timeout--)
udelay(100);
#ifdef CONFIG_SND_DEBUG
if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)
if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
#endif
if (chip->calibrate_mute) {
chip->image[reg] &= mask;
chip->image[reg] |= value;
} else {
outb(chip->mce_bit | reg, CS4231P(chip, REGSEL));
cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
mb();
tmp = (chip->image[reg] & mask) | value;
outb(tmp, CS4231P(chip, REG));
cs4231_outb(chip, CS4231P(REG), tmp);
chip->image[reg] = tmp;
mb();
}
......@@ -156,11 +198,11 @@ static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char val
int timeout;
for (timeout = 250;
timeout > 0 && (inb(CS4231P(chip, REGSEL)) & CS4231_INIT);
timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
timeout--)
udelay(10);
outb(chip->mce_bit | reg, CS4231P(chip, REGSEL));
outb(value, CS4231P(chip, REG));
cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
cs4231_outb(chip, CS4231P(REG), value);
mb();
}
......@@ -169,15 +211,15 @@ void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char value)
int timeout;
for (timeout = 250;
timeout > 0 && (inb(CS4231P(chip, REGSEL)) & CS4231_INIT);
timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
timeout--)
udelay(100);
#ifdef CONFIG_SND_DEBUG
if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)
if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
#endif
outb(chip->mce_bit | reg, CS4231P(chip, REGSEL));
outb(value, CS4231P(chip, REG));
cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
cs4231_outb(chip, CS4231P(REG), value);
chip->image[reg] = value;
mb();
#if 0
......@@ -190,23 +232,23 @@ unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
int timeout;
for (timeout = 250;
timeout > 0 && (inb(CS4231P(chip, REGSEL)) & CS4231_INIT);
timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
timeout--)
udelay(100);
#ifdef CONFIG_SND_DEBUG
if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)
if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
#endif
outb(chip->mce_bit | reg, CS4231P(chip, REGSEL));
cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
mb();
return inb(CS4231P(chip, REG));
return cs4231_inb(chip, CS4231P(REG));
}
void snd_cs4236_ext_out(cs4231_t *chip, unsigned char reg, unsigned char val)
{
outb(chip->mce_bit | 0x17, CS4231P(chip, REGSEL));
outb(reg | (chip->image[CS4236_EXT_REG] & 0x01), CS4231P(chip, REG));
outb(val, CS4231P(chip, REG));
cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01));
cs4231_outb(chip, CS4231P(REG), val);
chip->eimage[CS4236_REG(reg)] = val;
#if 0
printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val);
......@@ -215,14 +257,14 @@ void snd_cs4236_ext_out(cs4231_t *chip, unsigned char reg, unsigned char val)
unsigned char snd_cs4236_ext_in(cs4231_t *chip, unsigned char reg)
{
outb(chip->mce_bit | 0x17, CS4231P(chip, REGSEL));
outb(reg | (chip->image[CS4236_EXT_REG] & 0x01), CS4231P(chip, REG));
cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01));
#if 1
return inb(CS4231P(chip, REG));
return cs4231_inb(chip, CS4231P(REG));
#else
{
unsigned char res;
res = inb(CS4231P(chip, REG));
res = cs4231_inb(chip, CS4231P(REG));
printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res);
return res;
}
......@@ -233,8 +275,8 @@ unsigned char snd_cs4236_ext_in(cs4231_t *chip, unsigned char reg)
void snd_cs4231_debug(cs4231_t *chip)
{
printk("CS4231 REGS: INDEX = 0x%02x ", inb(CS4231P(chip, REGSEL)));
printk(" STATUS = 0x%02x\n", inb(CS4231P(chip, STATUS)));
printk("CS4231 REGS: INDEX = 0x%02x ", cs4231_inb(chip, CS4231P(REGSEL)));
printk(" STATUS = 0x%02x\n", cs4231_inb(chip, CS4231P(STATUS)));
printk(" 0x00: left input = 0x%02x ", snd_cs4231_in(chip, 0x00));
printk(" 0x10: alt 1 (CFIG 2) = 0x%02x\n", snd_cs4231_in(chip, 0x10));
printk(" 0x01: right input = 0x%02x ", snd_cs4231_in(chip, 0x01));
......@@ -281,10 +323,10 @@ static void snd_cs4231_busy_wait(cs4231_t *chip)
/* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
for (timeout = 5; timeout > 0; timeout--)
inb(CS4231P(chip, REGSEL));
cs4231_inb(chip, CS4231P(REGSEL));
/* end of cleanup sequence */
for (timeout = 250;
timeout > 0 && (inb(CS4231P(chip, REGSEL)) & CS4231_INIT);
timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
timeout--)
udelay(10);
}
......@@ -295,18 +337,18 @@ void snd_cs4231_mce_up(cs4231_t *chip)
int timeout;
spin_lock_irqsave(&chip->reg_lock, flags);
for (timeout = 250; timeout > 0 && (inb(CS4231P(chip, REGSEL)) & CS4231_INIT); timeout--)
for (timeout = 250; timeout > 0 && (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); timeout--)
udelay(100);
#ifdef CONFIG_SND_DEBUG
if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)
if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("mce_up - auto calibration time out (0)\n");
#endif
chip->mce_bit |= CS4231_MCE;
timeout = inb(CS4231P(chip, REGSEL));
timeout = cs4231_inb(chip, CS4231P(REGSEL));
if (timeout == 0x80)
snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
if (!(timeout & CS4231_MCE))
outb(chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
......@@ -322,12 +364,12 @@ void snd_cs4231_mce_down(cs4231_t *chip)
printk("(1) timeout = %i\n", timeout);
#endif
#ifdef CONFIG_SND_DEBUG
if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)
snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", CS4231P(chip, REGSEL));
if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL));
#endif
chip->mce_bit &= ~CS4231_MCE;
timeout = inb(CS4231P(chip, REGSEL));
outb(chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
timeout = cs4231_inb(chip, CS4231P(REGSEL));
cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
if (timeout == 0x80)
snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
if ((timeout & CS4231_MCE) == 0 ||
......@@ -364,7 +406,7 @@ void snd_cs4231_mce_down(cs4231_t *chip)
printk("(3) jiffies = %li\n", jiffies);
#endif
time = HZ / 10;
while (inb(CS4231P(chip, REGSEL)) & CS4231_INIT) {
while (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
spin_unlock_irqrestore(&chip->reg_lock, flags);
if (time <= 0) {
snd_printk("mce_down - auto calibration time out (3)\n");
......@@ -377,7 +419,7 @@ void snd_cs4231_mce_down(cs4231_t *chip)
spin_unlock_irqrestore(&chip->reg_lock, flags);
#if 0
printk("(4) jiffies = %li\n", jiffies);
snd_printk("mce_down - exit = 0x%x\n", inb(CS4231P(chip, REGSEL)));
snd_printk("mce_down - exit = 0x%x\n", cs4231_inb(chip, CS4231P(REGSEL)));
#endif
}
......@@ -403,7 +445,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream,
int result = 0;
#if 0
printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, inb(CS4231P(card, STATUS)));
printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, cs4231_inb(chip, CS4231P(STATUS)));
#endif
switch (cmd) {
......@@ -423,10 +465,15 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream,
s = s->link_next;
} while (s != substream);
spin_lock(&chip->reg_lock);
if (cmd == SNDRV_PCM_TRIGGER_START)
if (cmd == SNDRV_PCM_TRIGGER_START) {
chip->image[CS4231_IFACE_CTRL] |= what;
else
if (chip->trigger)
chip->trigger(chip, what, 1);
} else {
chip->image[CS4231_IFACE_CTRL] &= ~what;
if (chip->trigger)
chip->trigger(chip, what, 0);
}
snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
spin_unlock(&chip->reg_lock);
break;
......@@ -640,7 +687,7 @@ static void snd_cs4231_init(cs4231_t *chip)
snd_cs4231_mce_down(chip);
#ifdef SNDRV_DEBUG_MCE
#ifdef SNDRV_DEBUGq_MCE
snd_printk("init: (1)\n");
#endif
snd_cs4231_mce_up(chip);
......@@ -713,8 +760,8 @@ static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
CS4231_RECORD_IRQ |
CS4231_TIMER_IRQ);
snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
outb(0, CS4231P(chip, STATUS)); /* clear IRQ */
outb(0, CS4231P(chip, STATUS)); /* clear IRQ */
cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
snd_cs4231_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |
......@@ -743,8 +790,8 @@ static void snd_cs4231_close(cs4231_t *chip, unsigned int mode)
/* disable IRQ */
spin_lock_irqsave(&chip->reg_lock, flags);
snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
outb(0, CS4231P(chip, STATUS)); /* clear IRQ */
outb(0, CS4231P(chip, STATUS)); /* clear IRQ */
cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
snd_cs4231_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
......@@ -765,8 +812,8 @@ static void snd_cs4231_close(cs4231_t *chip, unsigned int mode)
/* clear IRQ again */
snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
outb(0, CS4231P(chip, STATUS)); /* clear IRQ */
outb(0, CS4231P(chip, STATUS)); /* clear IRQ */
cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
cs4231_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
spin_unlock_irqrestore(&chip->reg_lock, flags);
snd_cs4231_calibrate_mute(chip, 0);
......@@ -829,6 +876,7 @@ static int snd_cs4231_playback_hw_free(snd_pcm_substream_t * substream)
return snd_pcm_lib_free_pages(substream);
}
#ifdef LEGACY_SUPPORT
static int snd_cs4231_playback_prepare(snd_pcm_substream_t * substream)
{
cs4231_t *chip = snd_pcm_substream_chip(substream);
......@@ -850,6 +898,7 @@ static int snd_cs4231_playback_prepare(snd_pcm_substream_t * substream)
#endif
return 0;
}
#endif /* LEGACY_SUPPORT */
static int snd_cs4231_capture_hw_params(snd_pcm_substream_t * substream,
snd_pcm_hw_params_t * hw_params)
......@@ -871,6 +920,7 @@ static int snd_cs4231_capture_hw_free(snd_pcm_substream_t * substream)
return snd_pcm_lib_free_pages(substream);
}
#ifdef LEGACY_SUPPORT
static int snd_cs4231_capture_prepare(snd_pcm_substream_t * substream)
{
cs4231_t *chip = snd_pcm_substream_chip(substream);
......@@ -894,6 +944,7 @@ static int snd_cs4231_capture_prepare(snd_pcm_substream_t * substream)
spin_unlock_irqrestore(&chip->reg_lock, flags);
return 0;
}
#endif
static void snd_cs4231_overrange(cs4231_t *chip)
{
......@@ -940,6 +991,7 @@ void snd_cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock(&chip->reg_lock);
}
#ifdef LEGACY_SUPPORT
static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t * substream)
{
cs4231_t *chip = snd_pcm_substream_chip(substream);
......@@ -961,12 +1013,13 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substr
ptr = chip->c_dma_size - snd_dma_residue(chip->dma2);
return bytes_to_frames(substream->runtime, ptr);
}
#endif /* LEGACY_SUPPORT */
/*
*/
static int snd_cs4231_probe(cs4231_t *chip)
int snd_cs4231_probe(cs4231_t *chip)
{
unsigned long flags;
int i, id, rev;
......@@ -979,7 +1032,7 @@ static int snd_cs4231_probe(cs4231_t *chip)
id = 0;
for (i = 0; i < 50; i++) {
mb();
if (inb(CS4231P(chip, REGSEL)) & CS4231_INIT)
if (cs4231_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
udelay(2000);
else {
spin_lock_irqsave(&chip->reg_lock, flags);
......@@ -1020,8 +1073,8 @@ static int snd_cs4231_probe(cs4231_t *chip)
}
}
spin_lock_irqsave(&chip->reg_lock, flags);
inb(CS4231P(chip, STATUS)); /* clear any pendings IRQ */
outb(0, CS4231P(chip, STATUS));
cs4231_inb(chip, CS4231P(STATUS)); /* clear any pendings IRQ */
cs4231_outb(chip, CS4231P(STATUS), 0);
mb();
spin_unlock_irqrestore(&chip->reg_lock, flags);
......@@ -1189,6 +1242,7 @@ static int snd_cs4231_playback_open(snd_pcm_substream_t * substream)
chip->hardware == CS4231_HW_CS4239)
runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
#ifdef LEGACY_SUPPORT
snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
......@@ -1196,14 +1250,20 @@ static int snd_cs4231_playback_open(snd_pcm_substream_t * substream)
if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)
return err;
}
#endif
if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) {
#ifdef LEGACY_SUPPORT
if (chip->release_dma)
chip->release_dma(chip, chip->dma_private_data, chip->dma1);
#endif
snd_free_pages(runtime->dma_area, runtime->dma_bytes);
return err;
}
chip->playback_substream = substream;
#if defined(SBUS_SUPPORT) || defined(EBUS_SUPPORT)
chip->p_periods_sent = 0;
#endif
snd_pcm_set_sync(substream);
chip->rate_constraint(runtime);
return 0;
......@@ -1222,21 +1282,28 @@ static int snd_cs4231_capture_open(snd_pcm_substream_t * substream)
chip->hardware == CS4231_HW_CS4239)
runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
#ifdef LEGACY_SUPPORT
snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
if (chip->claim_dma) {
if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)
return err;
}
snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
#endif
if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) {
#ifdef LEGACY_SUPPORT
if (chip->release_dma)
chip->release_dma(chip, chip->dma_private_data, chip->dma2);
#endif
snd_free_pages(runtime->dma_area, runtime->dma_bytes);
return err;
}
chip->capture_substream = substream;
#if defined(SBUS_SUPPORT) || defined(EBUS_SUPPORT)
chip->c_periods_sent = 0;
#endif
snd_pcm_set_sync(substream);
chip->rate_constraint(runtime);
return 0;
......@@ -1301,8 +1368,8 @@ static void snd_cs4231_resume(cs4231_t *chip)
spin_lock_irqsave(&chip->reg_lock, flags);
snd_cs4231_busy_wait(chip);
chip->mce_bit &= ~CS4231_MCE;
timeout = inb(CS4231P(chip, REGSEL));
outb(chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
timeout = cs4231_inb(chip, CS4231P(REGSEL));
cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
if (timeout == 0x80)
snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port);
if ((timeout & CS4231_MCE) == 0 ||
......@@ -1334,6 +1401,8 @@ static int snd_cs4231_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *d
#endif /* CONFIG_PM */
#ifdef LEGACY_SUPPORT
static int snd_cs4231_free(cs4231_t *chip)
{
if (chip->res_port) {
......@@ -1373,6 +1442,8 @@ static int snd_cs4231_dev_free(snd_device_t *device)
return snd_cs4231_free(chip);
}
#endif /* LEGACY_SUPPORT */
const char *snd_cs4231_chip_id(cs4231_t *chip)
{
switch (chip->hardware) {
......@@ -1392,6 +1463,35 @@ const char *snd_cs4231_chip_id(cs4231_t *chip)
}
}
static int snd_cs4231_new(snd_card_t * card,
unsigned short hardware,
unsigned short hwshare,
cs4231_t ** rchip)
{
cs4231_t *chip;
*rchip = NULL;
chip = snd_magic_kcalloc(cs4231_t, 0, GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->hardware = hardware;
chip->hwshare = hwshare;
spin_lock_init(&chip->reg_lock);
init_MUTEX(&chip->mce_mutex);
init_MUTEX(&chip->open_mutex);
chip->card = card;
chip->rate_constraint = snd_cs4231_xrate;
chip->set_playback_format = snd_cs4231_playback_format;
chip->set_capture_format = snd_cs4231_capture_format;
memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image));
*rchip = chip;
return 0;
}
#ifdef LEGACY_SUPPORT
int snd_cs4231_create(snd_card_t * card,
unsigned long port,
unsigned long cport,
......@@ -1406,15 +1506,13 @@ int snd_cs4231_create(snd_card_t * card,
cs4231_t *chip;
int err;
*rchip = NULL;
chip = snd_magic_kcalloc(cs4231_t, 0, GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
err = snd_cs4231_new(card, hardware, hwshare, &chip);
if (err < 0)
return err;
chip->irq = -1;
chip->dma1 = -1;
chip->dma2 = -1;
chip->hardware = hardware;
chip->hwshare = hwshare;
if ((chip->res_port = request_region(port, 4, "CS4231")) == NULL) {
snd_cs4231_free(chip);
......@@ -1446,15 +1544,6 @@ int snd_cs4231_create(snd_card_t * card,
} else
chip->dma2 = dma2;
spin_lock_init(&chip->reg_lock);
init_MUTEX(&chip->mce_mutex);
init_MUTEX(&chip->open_mutex);
chip->card = card;
chip->rate_constraint = snd_cs4231_xrate;
chip->set_playback_format = snd_cs4231_playback_format;
chip->set_capture_format = snd_cs4231_capture_format;
memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image));
/* global setup */
if (snd_cs4231_probe(chip) < 0) {
snd_cs4231_free(chip);
......@@ -1486,6 +1575,8 @@ int snd_cs4231_create(snd_card_t * card,
return 0;
}
#endif /* LEGACY_SUPPORT */
static snd_pcm_ops_t snd_cs4231_playback_ops = {
.open = snd_cs4231_playback_open,
.close = snd_cs4231_playback_close,
......@@ -1540,7 +1631,23 @@ int snd_cs4231_pcm(cs4231_t *chip, int device, snd_pcm_t **rpcm)
pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
strcpy(pcm->name, snd_cs4231_chip_id(chip));
#ifdef LEGACY_SUPPORT
snd_pcm_lib_preallocate_isa_pages_for_all(pcm, 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
#else
# ifdef EBUS_SUPPORT
if (chip->ebus_flag) {
snd_pcm_lib_preallocate_pci_pages_for_all(chip->dev_u.pdev, pcm,
64*1024, 128*1024);
} else {
# endif
# ifdef SBUS_SUPPORT
snd_pcm_lib_preallocate_sbus_pages_for_all(chip->dev_u.sdev, pcm,
64*1024, 128*1024);
# endif
# ifdef EBUS_SUPPORT
}
# endif
#endif
chip->pcm = pcm;
if (rpcm)
......
/*
* ALSA driver for ICEnsemble ICE1712 (Envy24)
*
* AK4524 / AK4528 interface
* AK4524 / AK4528 / AK4529 interface
*
* Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
*
......@@ -67,6 +67,7 @@ void snd_ice1712_ak4524_write(ice1712_t *ice, int chip,
addr &= 0x07;
/* build I2C address + data byte */
/* assume C1=1, C0=0 */
addrdata = 0xa000 | (addr << 8) | data;
for (idx = 15; idx >= 0; idx--) {
tmp &= ~(ak->data_mask | ak->clk_mask);
......@@ -80,10 +81,12 @@ void snd_ice1712_ak4524_write(ice1712_t *ice, int chip,
udelay(1);
}
if (ak->type == SND_AK4524) {
if ((addr != 0x04 && addr != 0x05) || (data & 0x80) == 0)
ak->images[chip][addr] = data;
else
ak->ipga_gain[chip][addr-4] = data;
}
if (ak->cs_mask == ak->cs_addr) {
if (ak->cif) {
......@@ -112,17 +115,27 @@ void snd_ice1712_ak4524_reset(ice1712_t *ice, int state)
unsigned char reg;
ak4524_t *ak = &ice->ak4524;
switch (ak->type) {
case SND_AK4524:
case SND_AK4528:
for (chip = 0; chip < ak->num_dacs/2; chip++) {
snd_ice1712_ak4524_write(ice, chip, 0x01, state ? 0x00 : 0x03);
if (state)
continue;
for (reg = 0x04; reg < (ak->is_ak4528 ? 0x06 : 0x08); reg++)
/* DAC volumes */
for (reg = 0x04; reg < (ak->type == SND_AK4528 ? 0x06 : 0x08); reg++)
snd_ice1712_ak4524_write(ice, chip, reg, ak->images[chip][reg]);
if (ak->is_ak4528)
if (ak->type == SND_AK4528)
continue;
/* IPGA */
for (reg = 0x04; reg < 0x06; reg++)
snd_ice1712_ak4524_write(ice, chip, reg, ak->ipga_gain[chip][reg-4]);
}
break;
case SND_AK4529:
/* FIXME: needed for ak4529? */
break;
}
}
/*
......@@ -130,7 +143,7 @@ void snd_ice1712_ak4524_reset(ice1712_t *ice, int state)
*/
void __devinit snd_ice1712_ak4524_init(ice1712_t *ice)
{
static unsigned char inits[] = {
static unsigned char inits_ak4524[] = {
0x00, 0x07, /* 0: all power up */
0x01, 0x00, /* 1: ADC/DAC reset */
0x02, 0x60, /* 2: 24bit I2S */
......@@ -144,28 +157,68 @@ void __devinit snd_ice1712_ak4524_init(ice1712_t *ice)
0x07, 0x00, /* 7: DAC right muted */
0xff, 0xff
};
int chip, idx;
unsigned char *ptr, reg, data;
static unsigned char inits_ak4528[] = {
0x00, 0x07, /* 0: all power up */
0x01, 0x00, /* 1: ADC/DAC reset */
0x02, 0x60, /* 2: 24bit I2S */
0x03, 0x0d, /* 3: deemphasis off, turn LR highpass filters on */
0x01, 0x03, /* 1: ADC/DAC enable */
0x04, 0x00, /* 4: ADC left muted */
0x05, 0x00, /* 5: ADC right muted */
0xff, 0xff
};
static unsigned char inits_ak4529[] = {
0x09, 0x01, /* 9: ATS=0, RSTN=1 */
0x0a, 0x3f, /* A: all power up, no zero/overflow detection */
0x00, 0x08, /* 0: TDM=0, 24bit I2S, SMUTE=0 */
0x01, 0x00, /* 1: ACKS=0, ADC, loop off */
0x02, 0xff, /* 2: LOUT1 muted */
0x03, 0xff, /* 3: ROUT1 muted */
0x04, 0xff, /* 4: LOUT2 muted */
0x05, 0xff, /* 5: ROUT2 muted */
0x06, 0xff, /* 6: LOUT3 muted */
0x07, 0xff, /* 7: ROUT3 muted */
0x0b, 0xff, /* B: LOUT4 muted */
0x0c, 0xff, /* C: ROUT4 muted */
0x08, 0x55, /* 8: deemphasis all off */
0xff, 0xff
};
int chip, num_chips;
unsigned char *ptr, reg, data, *inits;
ak4524_t *ak = &ice->ak4524;
for (chip = idx = 0; chip < ak->num_dacs/2; chip++) {
switch (ak->type) {
case SND_AK4524:
inits = inits_ak4524;
num_chips = ak->num_dacs / 2;
break;
case SND_AK4528:
inits = inits_ak4528;
num_chips = ak->num_dacs / 2;
break;
case SND_AK4529:
default:
inits = inits_ak4529;
num_chips = 1;
break;
}
for (chip = 0; chip < num_chips; chip++) {
ptr = inits;
while (*ptr != 0xff) {
reg = *ptr++;
data = *ptr++;
if (ak->is_ak4528) {
if (reg > 5)
continue;
if (reg >= 4 && (data & 0x80))
continue;
}
if (reg == 0x03 && ak->is_ak4528)
data = 0x0d; /* deemphasis off, turn LR highpass filters on */
snd_ice1712_ak4524_write(ice, chip, reg, data);
}
}
}
#define AK_GET_CHIP(val) (((val) >> 8) & 0xff)
#define AK_GET_ADDR(val) ((val) & 0xff)
#define AK_GET_SHIFT(val) (((val) >> 16) & 0xff)
#define AK_COMPOSE(chip,addr,shift) (((chip) << 8) | (addr) | ((shift) << 16))
static int snd_ice1712_ak4524_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
......@@ -178,8 +231,8 @@ static int snd_ice1712_ak4524_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem
static int snd_ice1712_ak4524_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
int chip = kcontrol->private_value / 8;
int addr = kcontrol->private_value % 8;
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
ucontrol->value.integer.value[0] = ice->ak4524.images[chip][addr];
return 0;
}
......@@ -187,8 +240,8 @@ static int snd_ice1712_ak4524_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_
static int snd_ice1712_ak4524_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
int chip = kcontrol->private_value / 8;
int addr = kcontrol->private_value % 8;
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
unsigned char nval = ucontrol->value.integer.value[0];
int change = ice->ak4524.images[chip][addr] != nval;
if (change)
......@@ -208,8 +261,8 @@ static int snd_ice1712_ak4524_ipga_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_e
static int snd_ice1712_ak4524_ipga_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
int chip = kcontrol->private_value / 8;
int addr = kcontrol->private_value % 8;
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
ucontrol->value.integer.value[0] = ice->ak4524.ipga_gain[chip][addr-4] & 0x7f;
return 0;
}
......@@ -217,8 +270,8 @@ static int snd_ice1712_ak4524_ipga_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_el
static int snd_ice1712_ak4524_ipga_gain_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
int chip = kcontrol->private_value / 8;
int addr = kcontrol->private_value % 8;
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
unsigned char nval = (ucontrol->value.integer.value[0] % 37) | 0x80;
int change = ice->ak4524.ipga_gain[chip][addr] != nval;
if (change)
......@@ -243,21 +296,26 @@ static int snd_ice1712_ak4524_deemphasis_info(snd_kcontrol_t *kcontrol, snd_ctl_
static int snd_ice1712_ak4524_deemphasis_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
int chip = kcontrol->id.index;
ucontrol->value.enumerated.item[0] = ice->ak4524.images[chip][3] & 3;
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
int shift = AK_GET_SHIFT(kcontrol->private_value);
ucontrol->value.enumerated.item[0] = (ice->ak4524.images[chip][addr] >> shift) & 3;
return 0;
}
static int snd_ice1712_ak4524_deemphasis_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ice1712_t *ice = snd_kcontrol_chip(kcontrol);
int chip = kcontrol->id.index;
unsigned char nval = ucontrol->value.enumerated.item[0];
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
int shift = AK_GET_SHIFT(kcontrol->private_value);
unsigned char nval = ucontrol->value.enumerated.item[0] & 3;
int change;
nval |= (nval & 3) | (ice->ak4524.images[chip][3] & ~3);
change = ice->ak4524.images[chip][3] != nval;
nval = (nval << shift) | (ice->ak4524.images[chip][addr] & ~(3 << shift));
change = ice->ak4524.images[chip][addr] != nval;
if (change)
snd_ice1712_ak4524_write(ice, chip, 3, nval);
snd_ice1712_ak4524_write(ice, chip, addr, nval);
return change;
}
......@@ -280,15 +338,24 @@ int __devinit snd_ice1712_ak4524_build_controls(ice1712_t *ice)
ctl.access = SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE;
ctl.get = snd_ice1712_ak4524_volume_get;
ctl.put = snd_ice1712_ak4524_volume_put;
if (ak->is_ak4528)
ctl.private_value = (idx / 2) * 8 + (idx % 2) + 4; /* register 4 & 5 */
else
ctl.private_value = (idx / 2) * 8 + (idx % 2) + 6; /* register 6 & 7 */
switch (ak->type) {
case SND_AK4524:
ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0); /* register 6 & 7 */
break;
case SND_AK4528:
ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0); /* register 4 & 5 */
break;
case SND_AK4529: {
int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; /* registers 2-7 and b,c */
ctl.private_value = AK_COMPOSE(0, val, 0);
break;
}
}
ctl.private_data = ice;
if ((err = snd_ctl_add(ice->card, snd_ctl_new(&ctl))) < 0)
return err;
}
for (idx = 0; idx < ak->num_adcs && !ak->is_ak4528; ++idx) {
for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) {
snd_kcontrol_t ctl;
memset(&ctl, 0, sizeof(ctl));
strcpy(ctl.id.name, "ADC Volume");
......@@ -298,7 +365,7 @@ int __devinit snd_ice1712_ak4524_build_controls(ice1712_t *ice)
ctl.access = SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE;
ctl.get = snd_ice1712_ak4524_volume_get;
ctl.put = snd_ice1712_ak4524_volume_put;
ctl.private_value = (idx / 2) * 8 + (idx % 2) + 4; /* register 4 & 5 */
ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0); /* register 4 & 5 */
ctl.private_data = ice;
if ((err = snd_ctl_add(ice->card, snd_ctl_new(&ctl))) < 0)
return err;
......@@ -310,7 +377,7 @@ int __devinit snd_ice1712_ak4524_build_controls(ice1712_t *ice)
ctl.access = SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE;
ctl.get = snd_ice1712_ak4524_ipga_gain_get;
ctl.put = snd_ice1712_ak4524_ipga_gain_put;
ctl.private_value = (idx / 2) * 8 + (idx % 2) + 4; /* register 4 & 5 */
ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0); /* register 4 & 5 */
ctl.private_data = ice;
if ((err = snd_ctl_add(ice->card, snd_ctl_new(&ctl))) < 0)
return err;
......@@ -325,6 +392,17 @@ int __devinit snd_ice1712_ak4524_build_controls(ice1712_t *ice)
ctl.access = SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE;
ctl.get = snd_ice1712_ak4524_deemphasis_get;
ctl.put = snd_ice1712_ak4524_deemphasis_put;
switch (ak->type) {
case SND_AK4524:
case SND_AK4528:
ctl.private_value = AK_COMPOSE(idx, 3, 0); /* register 3 */
break;
case SND_AK4529: {
int shift = idx == 3 ? 6 : (2 - idx) * 2;
ctl.private_value = AK_COMPOSE(0, 8, shift); /* register 8 with shift */
break;
}
}
ctl.private_data = ice;
if ((err = snd_ctl_add(ice->card, snd_ctl_new(&ctl))) < 0)
return err;
......
......@@ -337,6 +337,9 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
case ICE1712_SUBDEVICE_AUDIOPHILE:
ice->num_total_dacs = 2;
break;
case ICE1712_SUBDEVICE_DELTA410:
ice->num_total_dacs = 8;
break;
case ICE1712_SUBDEVICE_DELTA44:
case ICE1712_SUBDEVICE_DELTA66:
ice->num_total_dacs = ice->omni ? 8 : 4;
......@@ -350,6 +353,7 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
/* initialize spdif */
switch (ice->eeprom.subvendor) {
case ICE1712_SUBDEVICE_AUDIOPHILE:
case ICE1712_SUBDEVICE_DELTA410:
case ICE1712_SUBDEVICE_DELTA1010LT:
if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) {
snd_printk("unable to create I2C bus\n");
......@@ -378,12 +382,17 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
ak = &ice->ak4524;
switch (ice->eeprom.subvendor) {
case ICE1712_SUBDEVICE_AUDIOPHILE:
case ICE1712_SUBDEVICE_DELTA410:
ak->num_adcs = ak->num_dacs = 2;
ak->is_ak4528 = 1;
ak->cif = 0; /* the default level of the CIF pin from AK4524 */
ak->type = SND_AK4528;
if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA410) {
ak->num_dacs = 8;
ak->type = SND_AK4529;
}
ak->cif = 0; /* the default level of the CIF pin from AK4528/4529 */
ak->data_mask = ICE1712_DELTA_AP_DOUT;
ak->clk_mask = ICE1712_DELTA_AP_CCLK;
ak->cs_mask = ak->cs_addr = ICE1712_DELTA_AP_CS_CODEC; /* select AK4528 codec */
ak->cs_mask = ak->cs_addr = ICE1712_DELTA_AP_CS_CODEC; /* select AK4528/4529 codec */
ak->cs_none = 0;
ak->add_flags = ICE1712_DELTA_AP_CS_DIGITAL; /* assert digital high */
ak->mask_flags = 0;
......@@ -392,6 +401,7 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
break;
case ICE1712_SUBDEVICE_DELTA1010LT:
ak->num_adcs = ak->num_dacs = 8;
ak->type = SND_AK4524;
ak->cif = 0; /* the default level of the CIF pin from AK4524 */
ak->data_mask = ICE1712_DELTA_1010LT_DOUT;
ak->clk_mask = ICE1712_DELTA_1010LT_CCLK;
......@@ -406,6 +416,7 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
case ICE1712_SUBDEVICE_DELTA66:
case ICE1712_SUBDEVICE_DELTA44:
ak->num_adcs = ak->num_dacs = 4;
ak->type = SND_AK4524;
ak->cif = 0; /* the default level of the CIF pin from AK4524 */
ak->data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA;
ak->clk_mask = ICE1712_DELTA_CODEC_SERIAL_CLOCK;
......@@ -471,6 +482,8 @@ static int __devinit snd_ice1712_delta_add_controls(ice1712_t *ice)
case ICE1712_SUBDEVICE_DELTADIO2496:
case ICE1712_SUBDEVICE_DELTA66:
case ICE1712_SUBDEVICE_AUDIOPHILE:
case ICE1712_SUBDEVICE_DELTA410:
case ICE1712_SUBDEVICE_DELTA1010LT:
err = snd_ice1712_spdif_build_controls(ice);
if (err < 0)
return err;
......@@ -492,6 +505,7 @@ static int __devinit snd_ice1712_delta_add_controls(ice1712_t *ice)
switch (ice->eeprom.subvendor) {
case ICE1712_SUBDEVICE_DELTA1010LT:
case ICE1712_SUBDEVICE_AUDIOPHILE:
case ICE1712_SUBDEVICE_DELTA410:
case ICE1712_SUBDEVICE_DELTA44:
case ICE1712_SUBDEVICE_DELTA66:
err = snd_ice1712_ak4524_build_controls(ice);
......@@ -538,6 +552,12 @@ struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
snd_ice1712_delta_init,
snd_ice1712_delta_add_controls,
},
{
ICE1712_SUBDEVICE_DELTA410,
"M Audio Delta 410",
snd_ice1712_delta_init,
snd_ice1712_delta_add_controls,
},
{
ICE1712_SUBDEVICE_DELTA1010LT,
"M Audio Delta 1010LT",
......
......@@ -37,6 +37,7 @@
#define ICE1712_SUBDEVICE_DELTA66 0x121432d6
#define ICE1712_SUBDEVICE_DELTA44 0x121433d6
#define ICE1712_SUBDEVICE_AUDIOPHILE 0x121434d6
#define ICE1712_SUBDEVICE_DELTA410 0x121438d6
#define ICE1712_SUBDEVICE_DELTA1010LT 0x12143bd6
/* entry point */
......@@ -106,7 +107,8 @@ extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
/* 0x40 = CODEC_CHIP_A */
/* 0x80 = CODEC_CHIP_B */
/* MidiMan M-Audio Audiophile definitions */
/* MidiMan M-Audio Audiophile/Delta410 definitions */
/* thanks to Kristof Pelckmans <Kristof.Pelckmans@antwerpen.be> for Delta410 info */
/* 0x01 = DFS */
#define ICE1712_DELTA_AP_CCLK 0x02 /* SPI clock */
/* (clocking on rising edge - 0->1) */
......@@ -114,7 +116,7 @@ extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
#define ICE1712_DELTA_AP_DOUT 0x08 /* data output */
#define ICE1712_DELTA_AP_CS_DIGITAL 0x10 /* CS8427 chip select */
/* low signal = select */
#define ICE1712_DELTA_AP_CS_CODEC 0x20 /* AK4528 chip select */
#define ICE1712_DELTA_AP_CS_CODEC 0x20 /* AK4528 (audiophile), AK4529 (Delta410) chip select */
/* low signal = select */
/* MidiMan M-Audio Delta1010LT definitions */
......
......@@ -406,6 +406,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
switch (ice->eeprom.subvendor) {
case ICE1712_SUBDEVICE_EWS88MT:
ak->num_adcs = ak->num_dacs = 8;
ak->type = SND_AK4524;
ak->cif = 1; /* CIF high */
ak->data_mask = ICE1712_EWS88_SERIAL_DATA;
ak->clk_mask = ICE1712_EWS88_SERIAL_CLOCK;
......@@ -418,6 +419,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
break;
case ICE1712_SUBDEVICE_EWX2496:
ak->num_adcs = ak->num_dacs = 2;
ak->type = SND_AK4524;
ak->cif = 1; /* CIF high */
ak->data_mask = ICE1712_EWS88_SERIAL_DATA;
ak->clk_mask = ICE1712_EWS88_SERIAL_CLOCK;
......@@ -430,6 +432,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
break;
case ICE1712_SUBDEVICE_DMX6FIRE:
ak->num_adcs = ak->num_dacs = 6;
ak->type = SND_AK4524;
ak->cif = 1; /* CIF high */
ak->data_mask = ICE1712_6FIRE_SERIAL_DATA;
ak->clk_mask = ICE1712_6FIRE_SERIAL_CLOCK;
......
......@@ -1532,7 +1532,7 @@ static snd_kcontrol_new_t snd_ice1712_eeprom __devinitdata = {
/*
*/
static int snd_ice1712_spdif_default_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
static int snd_ice1712_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
......@@ -1561,18 +1561,11 @@ static snd_kcontrol_new_t snd_ice1712_spdif_default __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
.info = snd_ice1712_spdif_default_info,
.info = snd_ice1712_spdif_info,
.get = snd_ice1712_spdif_default_get,
.put = snd_ice1712_spdif_default_put
};
static int snd_ice1712_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
static int snd_ice1712_spdif_maskc_get(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
{
......@@ -1620,7 +1613,7 @@ static snd_kcontrol_new_t snd_ice1712_spdif_maskc __devinitdata =
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
.info = snd_ice1712_spdif_mask_info,
.info = snd_ice1712_spdif_info,
.get = snd_ice1712_spdif_maskc_get,
};
......@@ -1629,17 +1622,10 @@ static snd_kcontrol_new_t snd_ice1712_spdif_maskp __devinitdata =
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
.info = snd_ice1712_spdif_mask_info,
.info = snd_ice1712_spdif_info,
.get = snd_ice1712_spdif_maskp_get,
};
static int snd_ice1712_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
static int snd_ice1712_spdif_stream_get(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
{
......@@ -1663,7 +1649,7 @@ static snd_kcontrol_new_t snd_ice1712_spdif_stream __devinitdata =
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
.info = snd_ice1712_spdif_stream_info,
.info = snd_ice1712_spdif_info,
.get = snd_ice1712_spdif_stream_get,
.put = snd_ice1712_spdif_stream_put
};
......
......@@ -239,10 +239,12 @@ typedef struct {
struct snd_ak4524 {
int num_adcs; /* AK4524 or AK4528 ADCs */
int num_dacs; /* AK4524 or AK4528 DACs */
unsigned char images[4][8];
unsigned char images[4][16];
unsigned char ipga_gain[4][2];
/* */
unsigned int is_ak4528: 1; /* AK4524 or AK4528 */
enum {
SND_AK4524, SND_AK4528, SND_AK4529
} type;
unsigned int cif: 1;
unsigned char data_mask;
unsigned char clk_mask;
......
......@@ -935,6 +935,7 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
struct usb_device *dev = subs->dev;
struct usb_host_config *config = dev->actconfig;
struct usb_host_interface *alts;
struct usb_interface_descriptor *altsd;
struct usb_interface *iface;
struct audioformat *fmt;
unsigned int ep, attr;
......@@ -951,7 +952,8 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
iface = &config->interface[fmt->iface];
alts = &iface->altsetting[fmt->altset_idx];
snd_assert(alts->desc.bAlternateSetting == fmt->altsetting, return -EINVAL);
altsd = get_iface_desc(alts);
snd_assert(altsd->bAlternateSetting == fmt->altsetting, return -EINVAL);
/* close the old interface */
if (subs->interface >= 0 && subs->interface != fmt->iface) {
......@@ -973,31 +975,31 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
}
/* create a data pipe */
ep = alts->endpoint[0].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep = get_endpoint(alts, 0)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
if (is_playback)
subs->datapipe = usb_sndisocpipe(dev, ep);
else
subs->datapipe = usb_rcvisocpipe(dev, ep);
subs->syncpipe = subs->syncinterval = 0;
subs->maxpacksize = alts->endpoint[0].desc.wMaxPacketSize;
subs->maxpacksize = get_endpoint(alts, 0)->wMaxPacketSize;
subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize);
subs->fill_max = 0;
/* we need a sync pipe in async OUT or adaptive IN mode */
attr = alts->endpoint[0].desc.bmAttributes & EP_ATTR_MASK;
attr = get_endpoint(alts, 0)->bmAttributes & EP_ATTR_MASK;
if ((is_playback && attr == EP_ATTR_ASYNC) ||
(! is_playback && attr == EP_ATTR_ADAPTIVE)) {
/* check endpoint */
if (alts->desc.bNumEndpoints < 2 ||
alts->endpoint[1].desc.bmAttributes != 0x01 ||
alts->endpoint[1].desc.bSynchAddress != 0) {
if (altsd->bNumEndpoints < 2 ||
get_endpoint(alts, 1)->bmAttributes != 0x01 ||
get_endpoint(alts, 1)->bSynchAddress != 0) {
snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n",
dev->devnum, fmt->iface, fmt->altsetting);
return -EINVAL;
}
ep = alts->endpoint[1].desc.bEndpointAddress;
if ((is_playback && ep != (alts->endpoint[0].desc.bSynchAddress | USB_DIR_IN)) ||
(! is_playback && ep != (alts->endpoint[0].desc.bSynchAddress & ~USB_DIR_IN))) {
ep = get_endpoint(alts, 1)->bEndpointAddress;
if ((is_playback && ep != (get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) ||
(! is_playback && ep != (get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN))) {
snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n",
dev->devnum, fmt->iface, fmt->altsetting);
return -EINVAL;
......@@ -1007,10 +1009,10 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
subs->syncpipe = usb_rcvisocpipe(dev, ep);
else
subs->syncpipe = usb_sndisocpipe(dev, ep);
subs->syncinterval = alts->endpoint[1].desc.bRefresh;
subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
}
ep = alts->endpoint[0].desc.bEndpointAddress;
ep = get_endpoint(alts, 0)->bEndpointAddress;
/* if endpoint has pitch control, enable it */
if (fmt->attributes & EP_CS_ATTR_PITCH_CONTROL) {
data[0] = 1;
......@@ -1676,6 +1678,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, unsigned char *buffer, i
struct usb_host_config *config;
struct usb_interface *iface;
struct usb_host_interface *alts;
struct usb_interface_descriptor *altsd;
int i, altno, err, stream;
int channels, nr_rates, pcm_format, format;
struct audioformat *fp;
......@@ -1688,19 +1691,20 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, unsigned char *buffer, i
iface = &config->interface[iface_no];
for (i = 0; i < iface->num_altsetting; i++) {
alts = &iface->altsetting[i];
altsd = get_iface_desc(alts);
/* skip invalid one */
if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO ||
alts->desc.bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING ||
alts->desc.bNumEndpoints < 1)
if (altsd->bInterfaceClass != USB_CLASS_AUDIO ||
altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING ||
altsd->bNumEndpoints < 1)
continue;
/* must be isochronous */
if ((alts->endpoint[0].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
USB_ENDPOINT_XFER_ISOC)
continue;
/* check direction */
stream = (alts->endpoint[0].desc.bEndpointAddress & USB_DIR_IN) ?
stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
altno = alts->desc.bAlternateSetting;
altno = altsd->bAlternateSetting;
/* get audio formats */
fmt = snd_usb_find_csint_desc(buffer, buflen, NULL, AS_GENERAL, iface_no, altno);
......@@ -1767,8 +1771,8 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, unsigned char *buffer, i
fp->altsetting = altno;
fp->altset_idx = i;
fp->format = pcm_format;
fp->endpoint = alts->endpoint[0].desc.bEndpointAddress;
fp->ep_attr = alts->endpoint[0].desc.bmAttributes;
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
fp->channels = channels;
fp->attributes = csep[3];
......@@ -1857,8 +1861,10 @@ static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif,
*/
config = dev->actconfig;
for (i = 0; i < p1[7]; i++) {
struct usb_host_interface *alts;
struct usb_interface_descriptor *altsd;
j = p1[8 + i];
if (j >= config->desc.bNumInterfaces) {
if (j >= get_cfg_desc(config)->bNumInterfaces) {
snd_printk(KERN_ERR "%d:%u:%d : does not exist\n",
dev->devnum, ctrlif, j);
continue;
......@@ -1868,8 +1874,10 @@ static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif,
snd_printdd(KERN_INFO "%d:%d:%d: skipping, already claimed\n", dev->devnum, ctrlif, j);
continue;
}
if (iface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO &&
iface->altsetting[0].desc.bInterfaceSubClass == USB_SUBCLASS_MIDI_STREAMING) {
alts = &iface->altsetting[0];
altsd = get_iface_desc(alts);
if (altsd->bInterfaceClass == USB_CLASS_AUDIO &&
altsd->bInterfaceSubClass == USB_SUBCLASS_MIDI_STREAMING) {
if (snd_usb_create_midi_interface(chip, iface, NULL) < 0) {
snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n", dev->devnum, ctrlif, j);
continue;
......@@ -1877,9 +1885,9 @@ static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif,
usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1);
continue;
}
if (iface->altsetting[0].desc.bInterfaceClass != USB_CLASS_AUDIO ||
iface->altsetting[0].desc.bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING) {
snd_printdd(KERN_ERR "%d:%u:%d: skipping non-supported interface %d\n", dev->devnum, ctrlif, j, iface->altsetting[0].desc.bInterfaceClass);
if (altsd->bInterfaceClass != USB_CLASS_AUDIO ||
altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING) {
snd_printdd(KERN_ERR "%d:%u:%d: skipping non-supported interface %d\n", dev->devnum, ctrlif, j, altsd->bInterfaceClass);
/* skip non-supported classes */
continue;
}
......@@ -1941,7 +1949,7 @@ static int snd_usb_roland_ua100_hack(snd_usb_audio_t *chip)
struct usb_interface *iface;
int err;
if (cfg->desc.bNumInterfaces != 3) {
if (get_cfg_desc(cfg)->bNumInterfaces != 3) {
snd_printdd(KERN_ERR "invalid UA-100 descriptor\n");
return -ENXIO;
}
......@@ -2139,13 +2147,17 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
int i;
snd_card_t *card;
snd_usb_audio_t *chip;
int ifnum = intf->altsetting->desc.bInterfaceNumber;
struct usb_host_interface *alts;
int ifnum;
alts = &intf->altsetting[0];
ifnum = get_iface_desc(alts)->bInterfaceNumber;
if (quirk && quirk->ifnum != QUIRK_ANY_INTERFACE && ifnum != quirk->ifnum)
goto __err_val;
if (usb_set_configuration(dev, config->desc.bConfigurationValue) < 0) {
snd_printk(KERN_ERR "cannot set configuration (value 0x%x)\n", config->desc.bConfigurationValue);
if (usb_set_configuration(dev, get_cfg_desc(config)->bConfigurationValue) < 0) {
snd_printk(KERN_ERR "cannot set configuration (value 0x%x)\n", get_cfg_desc(config)->bConfigurationValue);
goto __err_val;
}
......
......@@ -191,4 +191,15 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif, unsigned char *buffe
int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk);
/*
* retrieve usb_interface descriptor from the host interface
* (conditional for compatibility with the older API)
*/
#ifndef get_iface_desc
#define get_iface_desc(iface) (&iface->desc)
#define get_endpoint(alt,ep) (&(alt)->endpoint[ep].desc)
#define get_ep_desc(ep) (&(ep)->desc)
#define get_cfg_desc(cfg) (&(cfg)->desc)
#endif
#endif /* __USBAUDIO_H */
......@@ -515,7 +515,8 @@ static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
static struct usb_endpoint_descriptor* snd_usbmidi_get_int_epd(snd_usb_midi_t* umidi)
{
struct usb_interface* intf;
struct usb_host_interface* intfd;
struct usb_host_interface *hostif;
struct usb_interface_descriptor* intfd;
if (umidi->chip->dev->descriptor.idVendor != 0x0582)
return NULL;
......@@ -523,29 +524,37 @@ static struct usb_endpoint_descriptor* snd_usbmidi_get_int_epd(snd_usb_midi_t* u
if (!intf || intf->num_altsetting != 2)
return NULL;
intfd = &intf->altsetting[0];
if (intfd->desc.bNumEndpoints != 2 ||
(intfd->endpoint[0].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
(intfd->endpoint[1].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
hostif = &intf->altsetting[0];
intfd = get_iface_desc(hostif);
if (intfd->bNumEndpoints != 2 ||
(get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
(get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
return NULL;
intfd = &intf->altsetting[1];
if (intfd->desc.bNumEndpoints != 2 ||
(intfd->endpoint[0].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
(intfd->endpoint[1].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
hostif = &intf->altsetting[1];
intfd = get_iface_desc(hostif);
if (intfd->bNumEndpoints != 2 ||
(get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
(get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
return NULL;
usb_set_interface(umidi->chip->dev, intfd->desc.bInterfaceNumber,
intfd->desc.bAlternateSetting);
return &intfd->endpoint[1].desc;
usb_set_interface(umidi->chip->dev, intfd->bInterfaceNumber,
intfd->bAlternateSetting);
return get_endpoint(hostif, 1);
}
static struct usb_endpoint_descriptor* snd_usbmidi_get_midiman_int_epd(snd_usb_midi_t* umidi)
{
struct usb_interface* intf = umidi->iface;
if (!intf || intf->altsetting[0].desc.bNumEndpoints < 1)
struct usb_host_interface *hostif;
struct usb_interface_descriptor *intfd;
if (!intf)
return NULL;
hostif = &intf->altsetting[0];
intfd = get_iface_desc(hostif);
if (intfd->bNumEndpoints < 1)
return NULL;
return &intf->altsetting[0].endpoint[0].desc;
return get_endpoint(hostif, 0);
}
/*
......@@ -772,18 +781,21 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_info_t* endpoints)
{
struct usb_interface* intf;
struct usb_host_interface* intfd;
struct usb_host_interface *hostif;
struct usb_interface_descriptor* intfd;
struct usb_ms_header_descriptor* ms_header;
struct usb_host_endpoint* ep;
struct usb_host_endpoint *hostep;
struct usb_endpoint_descriptor* ep;
struct usb_ms_endpoint_descriptor* ms_ep;
int i, epidx;
intf = umidi->iface;
if (!intf)
return -ENXIO;
intfd = &intf->altsetting[0];
ms_header = (struct usb_ms_header_descriptor*)intfd->extra;
if (intfd->extralen >= 7 &&
hostif = &intf->altsetting[0];
intfd = get_iface_desc(hostif);
ms_header = (struct usb_ms_header_descriptor*)hostif->extra;
if (hostif->extralen >= 7 &&
ms_header->bLength >= 7 &&
ms_header->bDescriptorType == USB_DT_CS_INTERFACE &&
ms_header->bDescriptorSubtype == HEADER)
......@@ -793,33 +805,34 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
printk(KERN_WARNING "snd-usb-midi: MIDIStreaming interface descriptor not found\n");
epidx = 0;
for (i = 0; i < intfd->desc.bNumEndpoints; ++i) {
ep = &intfd->endpoint[i];
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
for (i = 0; i < intfd->bNumEndpoints; ++i) {
hostep = &hostif->endpoint[i];
ep = get_ep_desc(hostep);
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
continue;
ms_ep = (struct usb_ms_endpoint_descriptor*)ep->extra;
if (ep->extralen < 4 ||
ms_ep = (struct usb_ms_endpoint_descriptor*)hostep->extra;
if (hostep->extralen < 4 ||
ms_ep->bLength < 4 ||
ms_ep->bDescriptorType != USB_DT_CS_ENDPOINT ||
ms_ep->bDescriptorSubtype != MS_GENERAL)
continue;
if (endpoints[epidx].epnum != 0 &&
endpoints[epidx].epnum != (ep->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)) {
endpoints[epidx].epnum != (ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)) {
++epidx;
if (epidx >= MIDI_MAX_ENDPOINTS) {
printk(KERN_WARNING "snd-usb-midi: too many endpoints\n");
break;
}
}
endpoints[epidx].epnum = ep->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
if (ep->desc.bEndpointAddress & USB_DIR_IN) {
endpoints[epidx].epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
if (ep->bEndpointAddress & USB_DIR_IN) {
endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
} else {
endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
}
printk(KERN_INFO "snd-usb-midi: detected %d %s jack(s) on endpoint %d\n",
ms_ep->bNumEmbMIDIJack,
ep->desc.bEndpointAddress & USB_DIR_IN ? "input" : "output",
ep->bEndpointAddress & USB_DIR_IN ? "input" : "output",
endpoints[epidx].epnum);
}
return 0;
......@@ -833,17 +846,19 @@ static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_info_t* endpoint)
{
struct usb_interface* intf;
struct usb_host_interface* intfd;
struct usb_host_interface *hostif;
struct usb_interface_descriptor* intfd;
struct usb_endpoint_descriptor* epd;
if (endpoint->epnum == -1) {
intf = umidi->iface;
if (!intf || intf->num_altsetting < 1)
return -ENOENT;
intfd = intf->altsetting;
if (intfd->desc.bNumEndpoints < 1)
hostif = intf->altsetting;
intfd = get_iface_desc(hostif);
if (intfd->bNumEndpoints < 1)
return -ENOENT;
epd = &intfd->endpoint [0].desc;
epd = get_endpoint(hostif, 0);
endpoint->epnum = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
}
return 0;
......@@ -856,18 +871,20 @@ static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_info_t* endpoint)
{
struct usb_interface* intf;
struct usb_host_interface* intfd;
struct usb_host_interface *hostif;
struct usb_interface_descriptor* intfd;
uint8_t* cs_desc;
intf = umidi->iface;
if (!intf)
return -ENOENT;
intfd = intf->altsetting;
if (intfd->desc.bNumEndpoints < 1)
hostif = intf->altsetting;
intfd = get_iface_desc(hostif);
if (intfd->bNumEndpoints < 1)
return -ENOENT;
for (cs_desc = intfd->extra;
cs_desc < intfd->extra + intfd->extralen && cs_desc[0] >= 2;
for (cs_desc = hostif->extra;
cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2;
cs_desc += cs_desc[0]) {
if (cs_desc[1] == CS_AUDIO_INTERFACE) {
if (cs_desc[2] == MIDI_IN_JACK)
......@@ -890,33 +907,35 @@ static int snd_usbmidi_create_endpoints_midiman(snd_usb_midi_t* umidi, int ports
{
snd_usb_midi_endpoint_info_t ep_info;
struct usb_interface* intf;
struct usb_host_interface* intfd;
struct usb_host_interface *hostif;
struct usb_interface_descriptor* intfd;
struct usb_endpoint_descriptor* epd;
int cable, err;
intf = umidi->iface;
if (!intf)
return -ENOENT;
intfd = intf->altsetting;
if (intfd->desc.bNumEndpoints < (ports > 1 ? 5 : 3)) {
hostif = intf->altsetting;
intfd = get_iface_desc(hostif);
if (intfd->bNumEndpoints < (ports > 1 ? 5 : 3)) {
snd_printdd(KERN_ERR "not enough endpoints\n");
return -ENOENT;
}
epd = &intfd->endpoint[0].desc;
epd = get_endpoint(hostif, 0);
if ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN ||
(epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) {
snd_printdd(KERN_ERR "endpoint[0] isn't interrupt\n");
return -ENXIO;
}
epd = &intfd->endpoint[2].desc;
epd = get_endpoint(hostif, 2);
if ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_OUT ||
(epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) {
snd_printdd(KERN_ERR "endpoint[2] isn't bulk output\n");
return -ENXIO;
}
if (ports > 1) {
epd = &intfd->endpoint[4].desc;
epd = get_endpoint(hostif, 4);
if ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_OUT ||
(epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) {
snd_printdd(KERN_ERR "endpoint[4] isn't bulk output\n");
......@@ -924,13 +943,13 @@ static int snd_usbmidi_create_endpoints_midiman(snd_usb_midi_t* umidi, int ports
}
}
ep_info.epnum = intfd->endpoint[2].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep_info.epnum = get_endpoint(hostif, 2)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep_info.out_cables = 0x5555 & ((1 << ports) - 1);
err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]);
if (err < 0)
return err;
ep_info.epnum = intfd->endpoint[0].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep_info.epnum = get_endpoint(hostif, 0)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep_info.in_cables = (1 << ports) - 1;
err = snd_usbmidi_in_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]);
if (err < 0)
......@@ -938,7 +957,7 @@ static int snd_usbmidi_create_endpoints_midiman(snd_usb_midi_t* umidi, int ports
umidi->endpoints[0].in->urb->complete = snd_usbmidi_in_midiman_complete;
if (ports > 1) {
ep_info.epnum = intfd->endpoint[4].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep_info.epnum = get_endpoint(hostif, 4)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
ep_info.out_cables = 0xaaaa & ((1 << ports) - 1);
err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[1]);
if (err < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment