Merge master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa

This commit is contained in:
Linus Torvalds 2005-07-28 08:41:58 -07:00
commit 7b70888a19
65 changed files with 5110 additions and 1173 deletions

View File

@ -636,11 +636,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
3stack-digout 3-jack in back, a HP out and a SPDIF out
5stack 5-jack in back, 2-jack in front
5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
6stack 6-jack in back, 2-jack in front
6stack-digout 6-jack with a SPDIF out
w810 3-jack
z71v 3-jack (HP shared SPDIF)
asus 3-jack
uniwill 3-jack
F1734 2-jack
test for testing/debugging purpose, almost all controls can be
adjusted. Appearing only when compiled with
$CONFIG_SND_DEBUG=y
CMI9880
minimal 3-jack in back
@ -1054,6 +1059,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
The power-management is supported.
Module snd-pxa2xx-ac97 (on arm only)
------------------------------------
Module for AC97 driver for the Intel PXA2xx chip
For ARM architecture only.
Module snd-rme32
----------------
@ -1173,6 +1185,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module supports up to 8 cards.
Module snd-sun-dbri (on sparc only)
-----------------------------------
Module for DBRI sound chips found on Sparcs.
Module supports up to 8 cards.
Module snd-wavefront
--------------------
@ -1371,7 +1390,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module snd-vxpocket
-------------------
Module for Digigram VX-Pocket VX2 PCMCIA card.
Module for Digigram VX-Pocket VX2 and 440 PCMCIA cards.
ibl - Capture IBL size. (default = 0, minimum size)
@ -1391,29 +1410,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Note: the driver is build only when CONFIG_ISA is set.
Module snd-vxp440
-----------------
Module for Digigram VX-Pocket 440 PCMCIA card.
ibl - Capture IBL size. (default = 0, minimum size)
Module supports up to 8 cards. The module is compiled only when
PCMCIA is supported on kernel.
To activate the driver via the card manager, you'll need to set
up /etc/pcmcia/vxp440.conf. See the sound/pcmcia/vx/vxp440.c.
When the driver is compiled as a module and the hotplug firmware
is supported, the firmware data is loaded via hotplug automatically.
Install the necessary firmware files in alsa-firmware package.
When no hotplug fw loader is available, you need to load the
firmware via vxloader utility in alsa-tools package.
About capture IBL, see the description of snd-vx222 module.
Note: the driver is build only when CONFIG_ISA is set.
Module snd-ymfpci
-----------------

View File

@ -126,25 +126,26 @@ struct snd_monitor_file {
struct snd_monitor_file *next;
};
struct snd_shutdown_f_ops; /* define it later */
struct snd_shutdown_f_ops; /* define it later in init.c */
/* main structure for soundcard */
struct _snd_card {
int number; /* number of soundcard (index to snd_cards) */
int number; /* number of soundcard (index to
snd_cards) */
char id[16]; /* id string of this card */
char driver[16]; /* driver name */
char shortname[32]; /* short name of this soundcard */
char longname[80]; /* name of this soundcard */
char mixername[80]; /* mixer name */
char components[80]; /* card components delimited with space */
char components[80]; /* card components delimited with
space */
struct module *module; /* top-level module */
void *private_data; /* private data for soundcard */
void (*private_free) (snd_card_t *card); /* callback for freeing of private data */
void (*private_free) (snd_card_t *card); /* callback for freeing of
private data */
struct list_head devices; /* devices */
unsigned int last_numid; /* last used numeric ID */
@ -160,7 +161,8 @@ struct _snd_card {
struct proc_dir_entry *proc_root_link; /* number link to real id */
struct snd_monitor_file *files; /* all files associated to this card */
struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown state */
struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown
state */
spinlock_t files_lock; /* lock the files for this card */
int shutdown; /* this card is going down */
wait_queue_head_t shutdown_sleep;
@ -196,8 +198,6 @@ static inline void snd_power_unlock(snd_card_t *card)
up(&card->power_lock);
}
int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file);
static inline unsigned int snd_power_get_state(snd_card_t *card)
{
return card->power_state;
@ -208,6 +208,10 @@ static inline void snd_power_change_state(snd_card_t *card, unsigned int state)
card->power_state = state;
wake_up(&card->power_sleep);
}
/* init.c */
int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file);
int snd_card_set_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *),
@ -238,15 +242,14 @@ static inline int snd_power_wait(snd_card_t *card, unsigned int state, struct fi
#endif /* CONFIG_PM */
/* device.c */
struct _snd_minor {
struct list_head list; /* list of all minors per card */
int number; /* minor number */
int device; /* device number */
const char *comment; /* for /proc/asound/devices */
struct file_operations *f_ops; /* file operations */
char name[0]; /* device name (keep at the end of structure) */
char name[0]; /* device name (keep at the end of
structure) */
};
typedef struct _snd_minor snd_minor_t;
@ -287,12 +290,12 @@ void snd_memory_init(void);
void snd_memory_done(void);
int snd_memory_info_init(void);
int snd_memory_info_done(void);
void *snd_hidden_kmalloc(size_t size, int flags);
void *snd_hidden_kcalloc(size_t n, size_t size, int flags);
void *snd_hidden_kmalloc(size_t size, unsigned int __nocast flags);
void *snd_hidden_kcalloc(size_t n, size_t size, unsigned int __nocast flags);
void snd_hidden_kfree(const void *obj);
void *snd_hidden_vmalloc(unsigned long size);
void snd_hidden_vfree(void *obj);
char *snd_hidden_kstrdup(const char *s, int flags);
char *snd_hidden_kstrdup(const char *s, unsigned int __nocast flags);
#define kmalloc(size, flags) snd_hidden_kmalloc(size, flags)
#define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags)
#define kfree(obj) snd_hidden_kfree(obj)
@ -411,7 +414,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
printk(fmt ,##args)
#endif
/**
* snd_assert - run-time assersion macro
* snd_assert - run-time assertion macro
* @expr: expression
* @args...: the action
*
@ -427,7 +430,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
}\
} while (0)
/**
* snd_runtime_check - run-time assersion macro
* snd_runtime_check - run-time assertion macro
* @expr: expression
* @args...: the action
*

View File

@ -51,7 +51,7 @@
#ifdef CONFIG_SND_DEBUG_MEMORY
#include <linux/slab.h>
#include <linux/vmalloc.h>
void *snd_wrapper_kmalloc(size_t, int);
void *snd_wrapper_kmalloc(size_t, unsigned int __nocast);
#undef kmalloc
void snd_wrapper_kfree(const void *);
#undef kfree

View File

@ -1167,6 +1167,7 @@ int snd_emu10k1_create(snd_card_t * card,
unsigned short extout_mask,
long max_cache_bytes,
int enable_ir,
uint subsystem,
emu10k1_t ** remu);
int snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);

View File

@ -1,3 +1,3 @@
/* include/version.h. Generated by configure. */
#define CONFIG_SND_VERSION "1.0.9"
#define CONFIG_SND_DATE " (Sun May 29 07:31:02 2005 UTC)"
#define CONFIG_SND_VERSION "1.0.9b"
#define CONFIG_SND_DATE " (Thu Jul 28 12:20:13 2005 UTC)"

View File

@ -20,5 +20,17 @@ config SND_ARMAACI
select SND_PCM
select SND_AC97_CODEC
endmenu
config SND_PXA2XX_PCM
tristate
select SND_PCM
config SND_PXA2XX_AC97
tristate "AC97 driver for the Intel PXA2xx chip"
depends on ARCH_PXA && SND
select SND_PXA2XX_PCM
select SND_AC97_CODEC
help
Say Y or M if you want to support any AC97 codec attached to
the PXA2xx AC97 interface.
endmenu

View File

@ -3,9 +3,11 @@
#
snd-sa11xx-uda1341-objs := sa11xx-uda1341.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o
obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o
snd-aaci-objs := aaci.o devdma.o
snd-pxa2xx-pcm-objs := pxa2xx-pcm.o
snd-pxa2xx-ac97-objs := pxa2xx-ac97.o
obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o
obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o
obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o
obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o

410
sound/arm/pxa2xx-ac97.c Normal file
View File

@ -0,0 +1,410 @@
/*
* linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip.
*
* Author: Nicolas Pitre
* Created: Dec 02, 2004
* Copyright: MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
#include <sound/initval.h>
#include <asm/irq.h>
#include <asm/semaphore.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/audio.h>
#include "pxa2xx-pcm.h"
static DECLARE_MUTEX(car_mutex);
static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
static volatile long gsr_bits;
static unsigned short pxa2xx_ac97_read(ac97_t *ac97, unsigned short reg)
{
unsigned short val = -1;
volatile u32 *reg_addr;
down(&car_mutex);
if (CAR & CAR_CAIP) {
printk(KERN_CRIT"%s: CAR_CAIP already set\n", __FUNCTION__);
goto out;
}
/* set up primary or secondary codec space */
reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE;
reg_addr += (reg >> 1);
/* start read access across the ac97 link */
gsr_bits = 0;
val = *reg_addr;
if (reg == AC97_GPIO_STATUS)
goto out;
wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1);
if (!gsr_bits & GSR_SDONE) {
printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
__FUNCTION__, reg, gsr_bits);
val = -1;
goto out;
}
/* valid data now */
gsr_bits = 0;
val = *reg_addr;
/* but we've just started another cycle... */
wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1);
out: up(&car_mutex);
return val;
}
static void pxa2xx_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
{
volatile u32 *reg_addr;
down(&car_mutex);
if (CAR & CAR_CAIP) {
printk(KERN_CRIT "%s: CAR_CAIP already set\n", __FUNCTION__);
goto out;
}
/* set up primary or secondary codec space */
reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE;
reg_addr += (reg >> 1);
gsr_bits = 0;
*reg_addr = val;
wait_event_timeout(gsr_wq, gsr_bits & GSR_CDONE, 1);
if (!gsr_bits & GSR_SDONE)
printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
__FUNCTION__, reg, gsr_bits);
out: up(&car_mutex);
}
static void pxa2xx_ac97_reset(ac97_t *ac97)
{
/* First, try cold reset */
GCR &= GCR_COLD_RST; /* clear everything but nCRST */
GCR &= ~GCR_COLD_RST; /* then assert nCRST */
gsr_bits = 0;
#ifdef CONFIG_PXA27x
/* PXA27x Developers Manual section 13.5.2.2.1 */
pxa_set_cken(1 << 31, 1);
udelay(5);
pxa_set_cken(1 << 31, 0);
GCR = GCR_COLD_RST;
udelay(50);
#else
GCR = GCR_COLD_RST;
GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
#endif
if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) {
printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
__FUNCTION__, gsr_bits);
/* let's try warm reset */
gsr_bits = 0;
#ifdef CONFIG_PXA27x
/* warm reset broken on Bulverde,
so manually keep AC97 reset high */
pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
udelay(10);
GCR |= GCR_WARM_RST;
pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
udelay(50);
#else
GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN;;
wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
#endif
if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
__FUNCTION__, gsr_bits);
}
GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
}
static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id, struct pt_regs *regs)
{
long status;
status = GSR;
if (status) {
GSR = status;
gsr_bits |= status;
wake_up(&gsr_wq);
#ifdef CONFIG_PXA27x
/* Although we don't use those we still need to clear them
since they tend to spuriously trigger when MMC is used
(hardware bug? go figure)... */
MISR = MISR_EOC;
PISR = PISR_EOC;
MCSR = MCSR_EOC;
#endif
return IRQ_HANDLED;
}
return IRQ_NONE;
}
static ac97_bus_ops_t pxa2xx_ac97_ops = {
.read = pxa2xx_ac97_read,
.write = pxa2xx_ac97_write,
.reset = pxa2xx_ac97_reset,
};
static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_out = {
.name = "AC97 PCM out",
.dev_addr = __PREG(PCDR),
.drcmr = &DRCMRTXPCDR,
.dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
DCMD_BURST32 | DCMD_WIDTH4,
};
static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_in = {
.name = "AC97 PCM in",
.dev_addr = __PREG(PCDR),
.drcmr = &DRCMRRXPCDR,
.dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
DCMD_BURST32 | DCMD_WIDTH4,
};
static snd_pcm_t *pxa2xx_ac97_pcm;
static ac97_t *pxa2xx_ac97_ac97;
static int pxa2xx_ac97_pcm_startup(snd_pcm_substream_t *substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
pxa2xx_audio_ops_t *platform_ops;
int r;
runtime->hw.channels_min = 2;
runtime->hw.channels_max = 2;
r = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
AC97_RATES_FRONT_DAC : AC97_RATES_ADC;
runtime->hw.rates = pxa2xx_ac97_ac97->rates[r];
snd_pcm_limit_hw_rates(runtime);
platform_ops = substream->pcm->card->dev->platform_data;
if (platform_ops && platform_ops->startup)
return platform_ops->startup(substream, platform_ops->priv);
else
return 0;
}
static void pxa2xx_ac97_pcm_shutdown(snd_pcm_substream_t *substream)
{
pxa2xx_audio_ops_t *platform_ops;
platform_ops = substream->pcm->card->dev->platform_data;
if (platform_ops && platform_ops->shutdown)
platform_ops->shutdown(substream, platform_ops->priv);
}
static int pxa2xx_ac97_pcm_prepare(snd_pcm_substream_t *substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
return snd_ac97_set_rate(pxa2xx_ac97_ac97, reg, runtime->rate);
}
static pxa2xx_pcm_client_t pxa2xx_ac97_pcm_client = {
.playback_params = &pxa2xx_ac97_pcm_out,
.capture_params = &pxa2xx_ac97_pcm_in,
.startup = pxa2xx_ac97_pcm_startup,
.shutdown = pxa2xx_ac97_pcm_shutdown,
.prepare = pxa2xx_ac97_pcm_prepare,
};
#ifdef CONFIG_PM
static int pxa2xx_ac97_do_suspend(snd_card_t *card, unsigned int state)
{
if (card->power_state != SNDRV_CTL_POWER_D3cold) {
pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
snd_pcm_suspend_all(pxa2xx_ac97_pcm);
snd_ac97_suspend(pxa2xx_ac97_ac97);
snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
if (platform_ops && platform_ops->suspend)
platform_ops->suspend(platform_ops->priv);
GCR |= GCR_ACLINK_OFF;
pxa_set_cken(CKEN2_AC97, 0);
}
return 0;
}
static int pxa2xx_ac97_do_resume(snd_card_t *card, unsigned int state)
{
if (card->power_state != SNDRV_CTL_POWER_D0) {
pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
pxa_set_cken(CKEN2_AC97, 1);
if (platform_ops && platform_ops->resume)
platform_ops->resume(platform_ops->priv);
snd_ac97_resume(pxa2xx_ac97_ac97);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
}
return 0;
}
static int pxa2xx_ac97_suspend(struct device *_dev, u32 state, u32 level)
{
snd_card_t *card = dev_get_drvdata(_dev);
int ret = 0;
if (card && level == SUSPEND_DISABLE)
ret = pxa2xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold);
return ret;
}
static int pxa2xx_ac97_resume(struct device *_dev, u32 level)
{
snd_card_t *card = dev_get_drvdata(_dev);
int ret = 0;
if (card && level == RESUME_ENABLE)
ret = pxa2xx_ac97_do_resume(card, SNDRV_CTL_POWER_D0);
return ret;
}
#else
#define pxa2xx_ac97_suspend NULL
#define pxa2xx_ac97_resume NULL
#endif
static int pxa2xx_ac97_probe(struct device *dev)
{
snd_card_t *card;
ac97_bus_t *ac97_bus;
ac97_template_t ac97_template;
int ret;
ret = -ENOMEM;
card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
THIS_MODULE, 0);
if (!card)
goto err;
card->dev = dev;
strncpy(card->driver, dev->driver->name, sizeof(card->driver));
ret = pxa2xx_pcm_new(card, &pxa2xx_ac97_pcm_client, &pxa2xx_ac97_pcm);
if (ret)
goto err;
ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
if (ret < 0)
goto err;
pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
#ifdef CONFIG_PXA27x
/* Use GPIO 113 as AC97 Reset on Bulverde */
pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
#endif
pxa_set_cken(CKEN2_AC97, 1);
ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus);
if (ret)
goto err;
memset(&ac97_template, 0, sizeof(ac97_template));
ret = snd_ac97_mixer(ac97_bus, &ac97_template, &pxa2xx_ac97_ac97);
if (ret)
goto err;
snprintf(card->shortname, sizeof(card->shortname),
"%s", snd_ac97_get_short_name(pxa2xx_ac97_ac97));
snprintf(card->longname, sizeof(card->longname),
"%s (%s)", dev->driver->name, card->mixername);
snd_card_set_pm_callback(card, pxa2xx_ac97_do_suspend,
pxa2xx_ac97_do_resume, NULL);
ret = snd_card_register(card);
if (ret == 0) {
dev_set_drvdata(dev, card);
return 0;
}
err:
if (card)
snd_card_free(card);
if (CKEN & CKEN2_AC97) {
GCR |= GCR_ACLINK_OFF;
free_irq(IRQ_AC97, NULL);
pxa_set_cken(CKEN2_AC97, 0);
}
return ret;
}
static int pxa2xx_ac97_remove(struct device *dev)
{
snd_card_t *card = dev_get_drvdata(dev);
if (card) {
snd_card_free(card);
dev_set_drvdata(dev, NULL);
GCR |= GCR_ACLINK_OFF;
free_irq(IRQ_AC97, NULL);
pxa_set_cken(CKEN2_AC97, 0);
}
return 0;
}
static struct device_driver pxa2xx_ac97_driver = {
.name = "pxa2xx-ac97",
.bus = &platform_bus_type,
.probe = pxa2xx_ac97_probe,
.remove = pxa2xx_ac97_remove,
.suspend = pxa2xx_ac97_suspend,
.resume = pxa2xx_ac97_resume,
};
static int __init pxa2xx_ac97_init(void)
{
return driver_register(&pxa2xx_ac97_driver);
}
static void __exit pxa2xx_ac97_exit(void)
{
driver_unregister(&pxa2xx_ac97_driver);
}
module_init(pxa2xx_ac97_init);
module_exit(pxa2xx_ac97_exit);
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
MODULE_LICENSE("GPL");

367
sound/arm/pxa2xx-pcm.c Normal file
View File

@ -0,0 +1,367 @@
/*
* linux/sound/arm/pxa2xx-pcm.c -- ALSA PCM interface for the Intel PXA2xx chip
*
* Author: Nicolas Pitre
* Created: Nov 30, 2004
* Copyright: (C) 2004 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <asm/dma.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
#include "pxa2xx-pcm.h"
static const snd_pcm_hardware_t pxa2xx_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.period_bytes_min = 32,
.period_bytes_max = 8192 - 32,
.periods_min = 1,
.periods_max = PAGE_SIZE/sizeof(pxa_dma_desc),
.buffer_bytes_max = 128 * 1024,
.fifo_size = 32,
};
struct pxa2xx_runtime_data {
int dma_ch;
pxa2xx_pcm_dma_params_t *params;
pxa_dma_desc *dma_desc_array;
dma_addr_t dma_desc_array_phys;
};
static int pxa2xx_pcm_hw_params(snd_pcm_substream_t *substream,
snd_pcm_hw_params_t *params)
{
snd_pcm_runtime_t *runtime = substream->runtime;
struct pxa2xx_runtime_data *rtd = runtime->private_data;
size_t totsize = params_buffer_bytes(params);
size_t period = params_period_bytes(params);
pxa_dma_desc *dma_desc;
dma_addr_t dma_buff_phys, next_desc_phys;
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
runtime->dma_bytes = totsize;
dma_desc = rtd->dma_desc_array;
next_desc_phys = rtd->dma_desc_array_phys;
dma_buff_phys = runtime->dma_addr;
do {
next_desc_phys += sizeof(pxa_dma_desc);
dma_desc->ddadr = next_desc_phys;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
dma_desc->dsadr = dma_buff_phys;
dma_desc->dtadr = rtd->params->dev_addr;
} else {
dma_desc->dsadr = rtd->params->dev_addr;
dma_desc->dtadr = dma_buff_phys;
}
if (period > totsize)
period = totsize;
dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN;
dma_desc++;
dma_buff_phys += period;
} while (totsize -= period);
dma_desc[-1].ddadr = rtd->dma_desc_array_phys;
return 0;
}
static int pxa2xx_pcm_hw_free(snd_pcm_substream_t *substream)
{
struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
*rtd->params->drcmr = 0;
snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
}
static int pxa2xx_pcm_prepare(snd_pcm_substream_t *substream)
{
pxa2xx_pcm_client_t *client = substream->private_data;
snd_pcm_runtime_t *runtime = substream->runtime;
struct pxa2xx_runtime_data *rtd = runtime->private_data;
DCSR(rtd->dma_ch) &= ~DCSR_RUN;
DCSR(rtd->dma_ch) = 0;
DCMD(rtd->dma_ch) = 0;
*rtd->params->drcmr = rtd->dma_ch | DRCMR_MAPVLD;
return client->prepare(substream);
}
static int pxa2xx_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
{
struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
DDADR(rtd->dma_ch) = rtd->dma_desc_array_phys;
DCSR(rtd->dma_ch) = DCSR_RUN;
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
DCSR(rtd->dma_ch) &= ~DCSR_RUN;
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
DCSR(rtd->dma_ch) |= DCSR_RUN;
break;
default:
ret = -EINVAL;
}
return ret;
}
static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id, struct pt_regs *regs)
{
snd_pcm_substream_t *substream = dev_id;
struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
int dcsr;
dcsr = DCSR(dma_ch);
DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;
if (dcsr & DCSR_ENDINTR) {
snd_pcm_period_elapsed(substream);
} else {
printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
rtd->params->name, dma_ch, dcsr );
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
}
}
static snd_pcm_uframes_t pxa2xx_pcm_pointer(snd_pcm_substream_t *substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
struct pxa2xx_runtime_data *rtd = runtime->private_data;
dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
DSADR(rtd->dma_ch) : DTADR(rtd->dma_ch);
snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
if (x == runtime->buffer_size)
x = 0;
return x;
}
static int
pxa2xx_pcm_hw_rule_mult32(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule)
{
snd_interval_t *i = hw_param_interval(params, rule->var);
int changed = 0;
if (i->min & 31) {
i->min = (i->min & ~31) + 32;
i->openmin = 0;
changed = 1;
}
if (i->max & 31) {
i->max &= ~31;
i->openmax = 0;
changed = 1;
}
return changed;
}
static int pxa2xx_pcm_open(snd_pcm_substream_t *substream)
{
pxa2xx_pcm_client_t *client = substream->private_data;
snd_pcm_runtime_t *runtime = substream->runtime;
struct pxa2xx_runtime_data *rtd;
int ret;
runtime->hw = pxa2xx_pcm_hardware;
/*
* For mysterious reasons (and despite what the manual says)
* playback samples are lost if the DMA count is not a multiple
* of the DMA burst size. Let's add a rule to enforce that.
*/
ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
pxa2xx_pcm_hw_rule_mult32, NULL,
SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -1);
if (ret)
goto out;
ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
pxa2xx_pcm_hw_rule_mult32, NULL,
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1);
if (ret)
goto out;
ret = -ENOMEM;
rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
if (!rtd)
goto out;
rtd->dma_desc_array =
dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE,
&rtd->dma_desc_array_phys, GFP_KERNEL);
if (!rtd->dma_desc_array)
goto err1;
rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
client->playback_params : client->capture_params;
ret = pxa_request_dma(rtd->params->name, DMA_PRIO_LOW,
pxa2xx_pcm_dma_irq, substream);
if (ret < 0)
goto err2;
rtd->dma_ch = ret;
runtime->private_data = rtd;
ret = client->startup(substream);
if (!ret)
goto out;
pxa_free_dma(rtd->dma_ch);
err2:
dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
rtd->dma_desc_array, rtd->dma_desc_array_phys);
err1:
kfree(rtd);
out:
return ret;
}
static int pxa2xx_pcm_close(snd_pcm_substream_t *substream)
{
pxa2xx_pcm_client_t *client = substream->private_data;
struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
pxa_free_dma(rtd->dma_ch);
client->shutdown(substream);
dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
rtd->dma_desc_array, rtd->dma_desc_array_phys);
kfree(rtd);
return 0;
}
static int
pxa2xx_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma)
{
snd_pcm_runtime_t *runtime = substream->runtime;
return dma_mmap_writecombine(substream->pcm->card->dev, vma,
runtime->dma_area,
runtime->dma_addr,
runtime->dma_bytes);
}
static snd_pcm_ops_t pxa2xx_pcm_ops = {
.open = pxa2xx_pcm_open,
.close = pxa2xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pxa2xx_pcm_hw_params,
.hw_free = pxa2xx_pcm_hw_free,
.prepare = pxa2xx_pcm_prepare,
.trigger = pxa2xx_pcm_trigger,
.pointer = pxa2xx_pcm_pointer,
.mmap = pxa2xx_pcm_mmap,
};
static int pxa2xx_pcm_preallocate_dma_buffer(snd_pcm_t *pcm, int stream)
{
snd_pcm_substream_t *substream = pcm->streams[stream].substream;
struct snd_dma_buffer *buf = &substream->dma_buffer;
size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
buf->dev.type = SNDRV_DMA_TYPE_DEV;
buf->dev.dev = pcm->card->dev;
buf->private_data = NULL;
buf->area = dma_alloc_writecombine(pcm->card->dev, size,
&buf->addr, GFP_KERNEL);
if (!buf->area)
return -ENOMEM;
buf->bytes = size;
return 0;
}
static void pxa2xx_pcm_free_dma_buffers(snd_pcm_t *pcm)
{
snd_pcm_substream_t *substream;
struct snd_dma_buffer *buf;
int stream;
for (stream = 0; stream < 2; stream++) {
substream = pcm->streams[stream].substream;
if (!substream)
continue;
buf = &substream->dma_buffer;
if (!buf->area)
continue;
dma_free_writecombine(pcm->card->dev, buf->bytes,
buf->area, buf->addr);
buf->area = NULL;
}
}
static u64 pxa2xx_pcm_dmamask = 0xffffffff;
int pxa2xx_pcm_new(snd_card_t *card, pxa2xx_pcm_client_t *client, snd_pcm_t **rpcm)
{
snd_pcm_t *pcm;
int play = client->playback_params ? 1 : 0;
int capt = client->capture_params ? 1 : 0;
int ret;
ret = snd_pcm_new(card, "PXA2xx-PCM", 0, play, capt, &pcm);
if (ret)
goto out;
pcm->private_data = client;
pcm->private_free = pxa2xx_pcm_free_dma_buffers;
if (!card->dev->dma_mask)
card->dev->dma_mask = &pxa2xx_pcm_dmamask;
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = 0xffffffff;
if (play) {
int stream = SNDRV_PCM_STREAM_PLAYBACK;
snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops);
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
if (ret)
goto out;
}
if (capt) {
int stream = SNDRV_PCM_STREAM_CAPTURE;
snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops);
ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
if (ret)
goto out;
}
if (rpcm)
*rpcm = pcm;
ret = 0;
out:
return ret;
}
EXPORT_SYMBOL(pxa2xx_pcm_new);
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
MODULE_LICENSE("GPL");

29
sound/arm/pxa2xx-pcm.h Normal file
View File

@ -0,0 +1,29 @@
/*
* linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip
*
* Author: Nicolas Pitre
* Created: Nov 30, 2004
* Copyright: MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
typedef struct {
char *name; /* stream identifier */
u32 dcmd; /* DMA descriptor dcmd field */
volatile u32 *drcmr; /* the DMA request channel to use */
u32 dev_addr; /* device physical address for DMA */
} pxa2xx_pcm_dma_params_t;
typedef struct {
pxa2xx_pcm_dma_params_t *playback_params;
pxa2xx_pcm_dma_params_t *capture_params;
int (*startup)(snd_pcm_substream_t *);
void (*shutdown)(snd_pcm_substream_t *);
int (*prepare)(snd_pcm_substream_t *);
} pxa2xx_pcm_client_t;
extern int pxa2xx_pcm_new(snd_card_t *, pxa2xx_pcm_client_t *, snd_pcm_t **);

View File

@ -28,7 +28,7 @@
/**
* snd_device_new - create an ALSA device component
* @card: the card instance
* @type: the device type, SNDRV_DEV_TYPE_XXX
* @type: the device type, SNDRV_DEV_XXX
* @device_data: the data pointer of this device
* @ops: the operator table
*
@ -46,7 +46,9 @@ int snd_device_new(snd_card_t *card, snd_device_type_t type,
{
snd_device_t *dev;
snd_assert(card != NULL && device_data != NULL && ops != NULL, return -ENXIO);
snd_assert(card != NULL, return -ENXIO);
snd_assert(device_data != NULL, return -ENXIO);
snd_assert(ops != NULL, return -ENXIO);
dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
if (dev == NULL)
return -ENOMEM;
@ -102,7 +104,7 @@ int snd_device_free(snd_card_t *card, void *device_data)
}
/**
* snd_device_free - disconnect the device
* snd_device_disconnect - disconnect the device
* @card: the card instance
* @device_data: the data pointer to disconnect
*
@ -118,7 +120,7 @@ int snd_device_disconnect(snd_card_t *card, void *device_data)
{
struct list_head *list;
snd_device_t *dev;
snd_assert(card != NULL, return -ENXIO);
snd_assert(device_data != NULL, return -ENXIO);
list_for_each(list, &card->devices) {
@ -154,8 +156,9 @@ int snd_device_register(snd_card_t *card, void *device_data)
struct list_head *list;
snd_device_t *dev;
int err;
snd_assert(card != NULL && device_data != NULL, return -ENXIO);
snd_assert(card != NULL, return -ENXIO);
snd_assert(device_data != NULL, return -ENXIO);
list_for_each(list, &card->devices) {
dev = snd_device(list);
if (dev->device_data != device_data)

View File

@ -702,7 +702,7 @@ int snd_info_get_line(snd_info_buffer_t * buffer, char *line, int len)
}
/**
* snd_info_get_line - parse a string token
* snd_info_get_str - parse a string token
* @dest: the buffer to store the string token
* @src: the original string
* @len: the max. length of token - 1
@ -939,7 +939,8 @@ int snd_info_unregister(snd_info_entry_t * entry)
{
struct proc_dir_entry *root;
snd_assert(entry != NULL && entry->p != NULL, return -ENXIO);
snd_assert(entry != NULL, return -ENXIO);
snd_assert(entry->p != NULL, return -ENXIO);
root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
snd_assert(root, return -ENXIO);
down(&info_mutex);

View File

@ -105,7 +105,8 @@ struct snd_mem_list {
*/
static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, int flags)
dma_addr_t *dma_handle,
unsigned int __nocast flags)
{
void *ret;
u64 dma_mask, coherent_dma_mask;

View File

@ -89,7 +89,7 @@ void snd_memory_done(void)
}
}
static void *__snd_kmalloc(size_t size, int flags, void *caller)
static void *__snd_kmalloc(size_t size, unsigned int __nocast flags, void *caller)
{
unsigned long cpu_flags;
struct snd_alloc_track *t;
@ -111,12 +111,12 @@ static void *__snd_kmalloc(size_t size, int flags, void *caller)
}
#define _snd_kmalloc(size, flags) __snd_kmalloc((size), (flags), __builtin_return_address(0));
void *snd_hidden_kmalloc(size_t size, int flags)
void *snd_hidden_kmalloc(size_t size, unsigned int __nocast flags)
{
return _snd_kmalloc(size, flags);
}
void *snd_hidden_kcalloc(size_t n, size_t size, int flags)
void *snd_hidden_kcalloc(size_t n, size_t size, unsigned int __nocast flags)
{
void *ret = NULL;
if (n != 0 && size > INT_MAX / n)
@ -184,7 +184,7 @@ void snd_hidden_vfree(void *obj)
snd_wrapper_vfree(obj);
}
char *snd_hidden_kstrdup(const char *s, int flags)
char *snd_hidden_kstrdup(const char *s, unsigned int __nocast flags)
{
int len;
char *buf;

View File

@ -38,7 +38,7 @@ obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o
obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o
obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-seq-instr.o
obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-seq-midi-emul.o snd-seq-instr.o
obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o
obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o
obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-seq-midi-emul.o snd-seq-instr.o

View File

@ -50,7 +50,8 @@ static int snd_seq_gf1_copy_wave_from_stream(snd_gf1_ops_t *ops,
{
gf1_wave_t *wp, *prev;
gf1_xwave_t xp;
int err, gfp_mask;
int err;
unsigned int gfp_mask;
unsigned int real_size;
gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;

View File

@ -58,7 +58,7 @@ static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype,
iwffff_xenv_t *ex,
char __user **data,
long *len,
int gfp_mask)
unsigned int __nocast gfp_mask)
{
__u32 stype;
iwffff_env_record_t *rp, *rp_last;
@ -128,7 +128,8 @@ static int snd_seq_iwffff_copy_wave_from_stream(snd_iwffff_ops_t *ops,
{
iwffff_wave_t *wp, *prev;
iwffff_xwave_t xp;
int err, gfp_mask;
int err;
unsigned int gfp_mask;
unsigned int real_size;
gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL;
@ -234,7 +235,8 @@ static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr,
iwffff_xinstrument_t ix;
iwffff_layer_t *lp, *prev_lp;
iwffff_xlayer_t lx;
int err, gfp_mask;
int err;
unsigned int gfp_mask;
if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
return -EINVAL;

View File

@ -134,7 +134,7 @@ static int event_process_midi(snd_seq_event_t * ev, int direct,
seq_midisynth_t *msynth = (seq_midisynth_t *) private_data;
unsigned char msg[10]; /* buffer for constructing midi messages */
snd_rawmidi_substream_t *substream;
int res;
int len;
snd_assert(msynth != NULL, return -EINVAL);
substream = msynth->output_rfile.output;
@ -146,20 +146,16 @@ static int event_process_midi(snd_seq_event_t * ev, int direct,
snd_printd("seq_midi: invalid sysex event flags = 0x%x\n", ev->flags);
return 0;
}
res = snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream);
snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream);
snd_midi_event_reset_decode(msynth->parser);
if (res < 0)
return res;
} else {
if (msynth->parser == NULL)
return -EIO;
res = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev);
if (res < 0)
return res;
if ((res = dump_midi(substream, msg, res)) < 0) {
len = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev);
if (len < 0)
return 0;
if (dump_midi(substream, msg, len) < 0)
snd_midi_event_reset_decode(msynth->parser);
return res;
}
}
return 0;
}

View File

@ -27,7 +27,7 @@
#include <linux/fs.h>
#ifdef CONFIG_SND_DEBUG_MEMORY
void *snd_wrapper_kmalloc(size_t size, int flags)
void *snd_wrapper_kmalloc(size_t size, unsigned int __nocast flags)
{
return kmalloc(size, flags);
}

View File

@ -162,34 +162,24 @@ static int vx_read_uer_status(vx_core_t *chip, int *mode)
static int vx_calc_clock_from_freq(vx_core_t *chip, int freq)
{
#define XX_FECH48000 0x0000004B
#define XX_FECH32000 0x00000171
#define XX_FECH24000 0x0000024B
#define XX_FECH16000 0x00000371
#define XX_FECH12000 0x0000044B
#define XX_FECH8000 0x00000571
#define XX_FECH44100 0x0000007F
#define XX_FECH29400 0x0000016F
#define XX_FECH22050 0x0000027F
#define XX_FECH14000 0x000003EF
#define XX_FECH11025 0x0000047F
#define XX_FECH7350 0x000005BF
int hexfreq;
switch (freq) {
case 48000: return XX_FECH48000;
case 44100: return XX_FECH44100;
case 32000: return XX_FECH32000;
case 29400: return XX_FECH29400;
case 24000: return XX_FECH24000;
case 22050: return XX_FECH22050;
case 16000: return XX_FECH16000;
case 14000: return XX_FECH14000;
case 12000: return XX_FECH12000;
case 11025: return XX_FECH11025;
case 8000: return XX_FECH8000;
case 7350: return XX_FECH7350;
default: return freq; /* The value is already correct */
}
snd_assert(freq > 0, return 0);
hexfreq = (28224000 * 10) / freq;
hexfreq = (hexfreq + 5) / 10;
/* max freq = 55125 Hz */
snd_assert(hexfreq > 0x00000200, return 0);
if (hexfreq <= 0x03ff)
return hexfreq - 0x00000201;
if (hexfreq <= 0x07ff)
return (hexfreq / 2) - 1;
if (hexfreq <= 0x0fff)
return (hexfreq / 4) + 0x000001ff;
return 0x5fe; /* min freq = 6893 Hz */
}

View File

@ -554,7 +554,6 @@ int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags)
if (snd_pcm_running(ak4114->capture_substream)) {
// printk("rate changed (%i <- %i)\n", runtime->rate, res);
snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING);
wake_up(&runtime->sleep);
res = 1;
}
snd_pcm_stream_unlock_irqrestore(ak4114->capture_substream, _flags);

View File

@ -417,11 +417,13 @@ static int snd_gus_check_version(snd_gus_card_t * gus)
return 0;
}
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
static void snd_gus_seq_dev_free(snd_seq_device_t *seq_dev)
{
snd_gus_card_t *gus = seq_dev->private_data;
gus->seq_dev = NULL;
}
#endif
int snd_gus_initialize(snd_gus_card_t *gus)
{

View File

@ -34,7 +34,7 @@
/* weird stuff, derived from port I/O tracing with dosemu */
unsigned char page_zero[] __initdata = {
static unsigned char page_zero[] __initdata = {
0x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00,
0x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00,
0x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00,
@ -61,7 +61,7 @@ unsigned char page_zero[] __initdata = {
0x1d, 0x02, 0xdf
};
unsigned char page_one[] __initdata = {
static unsigned char page_one[] __initdata = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00,
0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00,
0x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01,
@ -88,7 +88,7 @@ unsigned char page_one[] __initdata = {
0x60, 0x00, 0x1b
};
unsigned char page_two[] __initdata = {
static unsigned char page_two[] __initdata = {
0xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4,
0x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -103,7 +103,7 @@ unsigned char page_two[] __initdata = {
0x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44
};
unsigned char page_three[] __initdata = {
static unsigned char page_three[] __initdata = {
0x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -118,7 +118,7 @@ unsigned char page_three[] __initdata = {
0x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40
};
unsigned char page_four[] __initdata = {
static unsigned char page_four[] __initdata = {
0x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -133,7 +133,7 @@ unsigned char page_four[] __initdata = {
0x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01
};
unsigned char page_six[] __initdata = {
static unsigned char page_six[] __initdata = {
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00,
0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e,
0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00,
@ -154,7 +154,7 @@ unsigned char page_six[] __initdata = {
0x80, 0x00, 0x7e, 0x80, 0x80
};
unsigned char page_seven[] __initdata = {
static unsigned char page_seven[] __initdata = {
0x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f,
@ -181,7 +181,7 @@ unsigned char page_seven[] __initdata = {
0x00, 0x02, 0x00
};
unsigned char page_zero_v2[] __initdata = {
static unsigned char page_zero_v2[] __initdata = {
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -193,7 +193,7 @@ unsigned char page_zero_v2[] __initdata = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
unsigned char page_one_v2[] __initdata = {
static unsigned char page_one_v2[] __initdata = {
0x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -205,21 +205,21 @@ unsigned char page_one_v2[] __initdata = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
unsigned char page_two_v2[] __initdata = {
static unsigned char page_two_v2[] __initdata = {
0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned char page_three_v2[] __initdata = {
static unsigned char page_three_v2[] __initdata = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned char page_four_v2[] __initdata = {
static unsigned char page_four_v2[] __initdata = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -227,7 +227,7 @@ unsigned char page_four_v2[] __initdata = {
0x00, 0x00, 0x00, 0x00
};
unsigned char page_seven_v2[] __initdata = {
static unsigned char page_seven_v2[] __initdata = {
0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -239,7 +239,7 @@ unsigned char page_seven_v2[] __initdata = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
unsigned char mod_v2[] __initdata = {
static unsigned char mod_v2[] __initdata = {
0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02,
0x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05,
0x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0,
@ -269,7 +269,7 @@ unsigned char mod_v2[] __initdata = {
0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01,
0x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01
};
unsigned char coefficients[] __initdata = {
static unsigned char coefficients[] __initdata = {
0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03,
0x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49,
0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01,
@ -305,14 +305,14 @@ unsigned char coefficients[] __initdata = {
0x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02,
0xba
};
unsigned char coefficients2[] __initdata = {
static unsigned char coefficients2[] __initdata = {
0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f,
0xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d,
0x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07,
0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00,
0x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00
};
unsigned char coefficients3[] __initdata = {
static unsigned char coefficients3[] __initdata = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00,
0x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc,
0x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01,

View File

@ -367,6 +367,7 @@ int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value)
ac97->regs[reg] = value;
ac97->bus->ops->write(ac97, reg, value);
}
set_bit(reg, ac97->reg_accessed);
up(&ac97->reg_mutex);
return change;
}
@ -410,6 +411,7 @@ int snd_ac97_update_bits_nolock(ac97_t *ac97, unsigned short reg,
ac97->regs[reg] = new;
ac97->bus->ops->write(ac97, reg, new);
}
set_bit(reg, ac97->reg_accessed);
return change;
}
@ -1076,6 +1078,11 @@ static void check_volume_resolution(ac97_t *ac97, int reg, unsigned char *lo_max
for (i = 0 ; i < ARRAY_SIZE(cbit); i++) {
unsigned short val;
snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8));
/* Do the read twice due to buffers on some ac97 codecs.
* e.g. The STAC9704 returns exactly what you wrote the the register
* if you read it immediately. This causes the detect routine to fail.
*/
val = snd_ac97_read(ac97, reg);
val = snd_ac97_read(ac97, reg);
if (! *lo_max && (val & 0x7f) == cbit[i])
*lo_max = max[i];
@ -2224,7 +2231,7 @@ void snd_ac97_restore_iec958(ac97_t *ac97)
*/
void snd_ac97_resume(ac97_t *ac97)
{
int i;
unsigned long end_time;
if (ac97->bus->ops->reset) {
ac97->bus->ops->reset(ac97);
@ -2242,26 +2249,26 @@ void snd_ac97_resume(ac97_t *ac97)
snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]);
if (ac97_is_audio(ac97)) {
ac97->bus->ops->write(ac97, AC97_MASTER, 0x8101);
for (i = HZ/10; i >= 0; i--) {
end_time = jiffies + msecs_to_jiffies(100);
do {
if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101)
break;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
} while (time_after_eq(end_time, jiffies));
/* FIXME: extra delay */
ac97->bus->ops->write(ac97, AC97_MASTER, 0x8000);
if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/4);
}
if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000)
msleep(250);
} else {
for (i = HZ/10; i >= 0; i--) {
end_time = jiffies + msecs_to_jiffies(100);
do {
unsigned short val = snd_ac97_read(ac97, AC97_EXTENDED_MID);
if (val != 0xffff && (val & 1) != 0)
break;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
} while (time_after_eq(end_time, jiffies));
}
__reset_ready:

View File

@ -1528,6 +1528,9 @@ static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
},
AC97_SURROUND_JACK_MODE_CTL,
AC97_CHANNEL_MODE_CTL,
AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
};
static int patch_ad1888_specific(ac97_t *ac97)

View File

@ -399,7 +399,7 @@ static int snd_ali_codec_ready( ali_t *codec,
unsigned long end_time;
unsigned int res;
end_time = jiffies + 10 * (HZ >> 2);
end_time = jiffies + 10 * msecs_to_jiffies(250);
do {
res = snd_ali_5451_peek(codec,port);
if (! (res & 0x8000))
@ -422,7 +422,7 @@ static int snd_ali_stimer_ready(ali_t *codec, int sched)
dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER);
dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER);
end_time = jiffies + 10 * (HZ >> 2);
end_time = jiffies + 10 * msecs_to_jiffies(250);
do {
dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER);
if (dwChk2 != dwChk1)

View File

@ -265,6 +265,7 @@ struct snd_atiixp {
*/
static struct pci_device_id snd_atiixp_ids[] = {
{ 0x1002, 0x434d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */
{ 0x1002, 0x4378, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */
{ 0, }
};

View File

@ -306,7 +306,7 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_REG_FM_PCI 0x50
/*
* for CMI-8338 .. this is not valid for CMI-8738.
* access from SB-mixer port
*/
#define CM_REG_EXTENT_IND 0xf0
#define CM_VPHONE_MASK 0xe0 /* Phone volume control (0-3) << 5 */
@ -315,6 +315,7 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_VSPKM 0x08 /* Speaker mute control, default high */
#define CM_RLOOPREN 0x04 /* Rec. R-channel enable */
#define CM_RLOOPLEN 0x02 /* Rec. L-channel enable */
#define CM_VADMIC3 0x01 /* Mic record boost */
/*
* CMI-8338 spec ver 0.5 (this is not valid for CMI-8738):
@ -2135,8 +2136,12 @@ static snd_kcontrol_new_t snd_cmipci_mixers[] __devinitdata = {
CMIPCI_MIXER_VOL_STEREO("Aux Playback Volume", CM_REG_AUX_VOL, 4, 0, 15),
CMIPCI_MIXER_SW_STEREO("Aux Playback Switch", CM_REG_MIXER2, CM_VAUXLM_SHIFT, CM_VAUXRM_SHIFT, 0),
CMIPCI_MIXER_SW_STEREO("Aux Capture Switch", CM_REG_MIXER2, CM_RAUXLEN_SHIFT, CM_RAUXREN_SHIFT, 0),
CMIPCI_MIXER_SW_MONO("Mic Boost", CM_REG_MIXER2, CM_MICGAINZ_SHIFT, 1),
CMIPCI_MIXER_SW_MONO("Mic Boost Playback Switch", CM_REG_MIXER2, CM_MICGAINZ_SHIFT, 1),
CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7),
CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7),
CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0),
CMIPCI_DOUBLE("PC Speaker Playnack Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0),
CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0),
};
/*

View File

@ -2400,8 +2400,7 @@ static void snd_cs46xx_codec_reset (ac97_t * ac97)
if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05)
return;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/100);
msleep(10);
} while (time_after_eq(end_time, jiffies));
snd_printk("CS46xx secondary codec dont respond!\n");
@ -2435,8 +2434,7 @@ static int __devinit cs46xx_detect_codec(cs46xx_t *chip, int codec)
err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]);
return err;
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ/100);
msleep(10);
}
snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec);
return -ENXIO;
@ -3018,8 +3016,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip)
/*
* Wait until the PLL has stabilized.
*/
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/10); /* 100ms */
msleep(100);
/*
* Turn on clocking of the core so that we can setup the serial ports.
@ -3072,8 +3069,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip)
*/
if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY)
goto ok1;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((HZ+99)/100);
msleep(10);
}
@ -3122,8 +3118,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip)
*/
if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
goto ok2;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((HZ+99)/100);
msleep(10);
}
#ifndef CONFIG_SND_CS46XX_NEW_DSP

View File

@ -52,6 +52,7 @@ static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4};
static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64};
static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128};
static int enable_ir[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
static uint subsystem[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* Force card subsystem model */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard.");
@ -71,7 +72,8 @@ module_param_array(max_buffer_size, int, NULL, 0444);
MODULE_PARM_DESC(max_buffer_size, "Maximum sample buffer size in MB.");
module_param_array(enable_ir, bool, NULL, 0444);
MODULE_PARM_DESC(enable_ir, "Enable IR.");
module_param_array(subsystem, uint, NULL, 0444);
MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
/*
* Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400
*/
@ -122,7 +124,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
max_buffer_size[dev] = 1024;
if ((err = snd_emu10k1_create(card, pci, extin[dev], extout[dev],
(long)max_buffer_size[dev] * 1024 * 1024,
enable_ir[dev],
enable_ir[dev], subsystem[dev],
&emu)) < 0) {
snd_card_free(card);
return err;
@ -140,7 +142,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
return err;
}
/* This stores the periods table. */
if (emu->audigy && emu->revision == 4) { /* P16V */
if (emu->card_capabilities->ca0151_chip) { /* P16V */
if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &emu->p16v_buffer) < 0) {
snd_p16v_free(emu);
return -ENOMEM;
@ -161,7 +163,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
if (emu->audigy && emu->revision == 4) { /* P16V */
if (emu->card_capabilities->ca0151_chip) { /* P16V */
if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0) {
snd_card_free(card);
return err;

View File

@ -191,7 +191,7 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
/* Set playback routing. */
snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4);
}
if (emu->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */
if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */
/* Hacks for Alice3 to work independent of haP16V driver */
u32 tmp;
@ -253,6 +253,8 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);
else
outl(HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);
/* FIXME: Remove all these emu->model and replace it with a card recognition parameter,
* e.g. card_capabilities->joystick */
} else if (emu->model == 0x20 ||
emu->model == 0xc400 ||
(emu->model == 0x21 && emu->revision < 6))
@ -299,12 +301,12 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
if (emu->audigy) {
outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
if (emu->revision == 4) { /* audigy2 */
if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
/* Unmute Analog now. Set GPO6 to 1 for Apollo.
* This has to be done after init ALice3 I2SOut beyond 48KHz.
* So, sequence is important. */
outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG);
} else if (emu->serial == 0x10011102) { /* audigy2 value */
} else if (emu->card_capabilities->ca0108_chip) { /* audigy2 value */
/* Unmute Analog now. */
outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG);
} else {
@ -614,6 +616,7 @@ static int snd_emu10k1_dev_free(snd_device_t *device)
static emu_chip_details_t emu_chip_details[] = {
/* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
/* Tested by James@superbug.co.uk 3rd July 2005 */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
.driver = "Audigy2", .name = "Audigy 2 Value [SB0400]",
.id = "Audigy2",
@ -627,6 +630,14 @@ static emu_chip_details_t emu_chip_details[] = {
.emu10k2_chip = 1,
.ca0108_chip = 1,
.ac97_chip = 1} ,
/* Tested by James@superbug.co.uk 8th July 2005. No sound available yet. */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102,
.driver = "Audigy2", .name = "E-mu 1212m [4001]",
.id = "EMU1212m",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ecard = 1} ,
/* Tested by James@superbug.co.uk 3rd July 2005 */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
.driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]",
.id = "Audigy2",
@ -687,19 +698,19 @@ static emu_chip_details_t emu_chip_details[] = {
.ca0151_chip = 1,
.spdif_bug = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10020052,
.driver = "Audigy", .name = "Audigy 1 ES [SB0160]",
.id = "Audigy",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.spdif_bug = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102,
.driver = "Audigy", .name = "Audigy 1 [SB0090]",
.id = "Audigy",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00521102,
.driver = "Audigy", .name = "Audigy 1 ES [SB0160]",
.id = "Audigy",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.spdif_bug = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102,
.driver = "Audigy", .name = "Audigy 1 [SB0090]",
.id = "Audigy",
@ -712,96 +723,8 @@ static emu_chip_details_t emu_chip_details[] = {
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102,
.driver = "EMU10K1", .name = "E-mu APS [4001]",
.id = "APS",
.emu10k1_chip = 1,
.ecard = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
.driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102,
.driver = "EMU10K1", .name = "SB Live 5.1",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102,
.driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102,
.driver = "EMU10K1", .name = "SBLive! [CT4620]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4670]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4780]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102,
.driver = "EMU10K1", .name = "SB PCI512 [CT4790]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4830]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4831]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4832]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4850]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4870]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4871]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
.driver = "EMU10K1", .name = "SBLive! Value [SB0060]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102,
.driver = "EMU10K1", .name = "SBLive! Value [SB0101]",
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102,
.driver = "EMU10K1", .name = "SBLive! [SB0105]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
@ -812,8 +735,91 @@ static emu_chip_details_t emu_chip_details[] = {
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102,
.driver = "EMU10K1", .name = "SBLive! [SB0105]",
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102,
.driver = "EMU10K1", .name = "SBLive! Value [SB0101]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102,
.driver = "EMU10K1", .name = "SB Live 5.1",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
.driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4850]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102,
.driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4871]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4831]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4870]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
/* Tested by James@superbug.co.uk 3rd July 2005 */
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4832]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4830]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102,
.driver = "EMU10K1", .name = "SB PCI512 [CT4790]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4780]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102,
.driver = "EMU10K1", .name = "E-mu APS [4001]",
.id = "APS",
.emu10k1_chip = 1,
.ecard = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102,
.driver = "EMU10K1", .name = "SBLive! [CT4620]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102,
.driver = "EMU10K1", .name = "SBLive! Value [CT4670]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
@ -833,6 +839,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
unsigned short extout_mask,
long max_cache_bytes,
int enable_ir,
uint subsystem,
emu10k1_t ** remu)
{
emu10k1_t *emu;
@ -878,10 +885,16 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
for (c = emu_chip_details; c->vendor; c++) {
if (c->vendor == pci->vendor && c->device == pci->device) {
if (c->subsystem && c->subsystem != emu->serial)
continue;
if (c->revision && c->revision != emu->revision)
continue;
if (subsystem) {
if (c->subsystem && (c->subsystem == subsystem) ) {
break;
} else continue;
} else {
if (c->subsystem && (c->subsystem != emu->serial) )
continue;
if (c->revision && c->revision != emu->revision)
continue;
}
break;
}
}
@ -892,10 +905,14 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
return -ENOENT;
}
emu->card_capabilities = c;
if (c->subsystem != 0)
if (c->subsystem && !subsystem)
snd_printdd("Sound card name=%s\n", c->name);
else
snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x\n", c->name, pci->vendor, pci->device, emu->serial);
else if (subsystem)
snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x. Forced to subsytem=0x%x\n",
c->name, pci->vendor, pci->device, emu->serial, c->subsystem);
else
snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x.\n",
c->name, pci->vendor, pci->device, emu->serial);
if (!*card->id && c->id) {
int i, n = 0;

View File

@ -822,7 +822,7 @@ static int snd_p16v_volume_put_analog_unknown(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_p16v_volume_control_analog_front =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "HD Analog Front Volume",
.name = "HD Analog Front Playback Volume",
.info = snd_p16v_volume_info,
.get = snd_p16v_volume_get_analog_front,
.put = snd_p16v_volume_put_analog_front
@ -831,7 +831,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_analog_front =
static snd_kcontrol_new_t snd_p16v_volume_control_analog_center_lfe =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "HD Analog Center/LFE Volume",
.name = "HD Analog Center/LFE Playback Volume",
.info = snd_p16v_volume_info,
.get = snd_p16v_volume_get_analog_center_lfe,
.put = snd_p16v_volume_put_analog_center_lfe
@ -840,7 +840,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_analog_center_lfe =
static snd_kcontrol_new_t snd_p16v_volume_control_analog_unknown =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "HD Analog Unknown Volume",
.name = "HD Analog Unknown Playback Volume",
.info = snd_p16v_volume_info,
.get = snd_p16v_volume_get_analog_unknown,
.put = snd_p16v_volume_put_analog_unknown
@ -849,7 +849,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_analog_unknown =
static snd_kcontrol_new_t snd_p16v_volume_control_analog_rear =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "HD Analog Rear Volume",
.name = "HD Analog Rear Playback Volume",
.info = snd_p16v_volume_info,
.get = snd_p16v_volume_get_analog_rear,
.put = snd_p16v_volume_put_analog_rear
@ -858,7 +858,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_analog_rear =
static snd_kcontrol_new_t snd_p16v_volume_control_spdif_front =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "HD SPDIF Front Volume",
.name = "HD SPDIF Front Playback Volume",
.info = snd_p16v_volume_info,
.get = snd_p16v_volume_get_spdif_front,
.put = snd_p16v_volume_put_spdif_front
@ -867,7 +867,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_front =
static snd_kcontrol_new_t snd_p16v_volume_control_spdif_center_lfe =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "HD SPDIF Center/LFE Volume",
.name = "HD SPDIF Center/LFE Playback Volume",
.info = snd_p16v_volume_info,
.get = snd_p16v_volume_get_spdif_center_lfe,
.put = snd_p16v_volume_put_spdif_center_lfe
@ -876,7 +876,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_center_lfe =
static snd_kcontrol_new_t snd_p16v_volume_control_spdif_unknown =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "HD SPDIF Unknown Volume",
.name = "HD SPDIF Unknown Playback Volume",
.info = snd_p16v_volume_info,
.get = snd_p16v_volume_get_spdif_unknown,
.put = snd_p16v_volume_put_spdif_unknown
@ -885,7 +885,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_unknown =
static snd_kcontrol_new_t snd_p16v_volume_control_spdif_rear =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "HD SPDIF Rear Volume",
.name = "HD SPDIF Rear Playback Volume",
.info = snd_p16v_volume_info,
.get = snd_p16v_volume_get_spdif_rear,
.put = snd_p16v_volume_put_spdif_rear
@ -936,7 +936,7 @@ static int snd_p16v_capture_source_put(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_p16v_capture_source __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "HD Capture source",
.name = "HD source Capture",
.info = snd_p16v_capture_source_info,
.get = snd_p16v_capture_source_get,
.put = snd_p16v_capture_source_put
@ -985,7 +985,7 @@ static int snd_p16v_capture_channel_put(snd_kcontrol_t * kcontrol,
static snd_kcontrol_new_t snd_p16v_capture_channel __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "HD Capture channel",
.name = "HD channel Capture",
.info = snd_p16v_capture_channel_info,
.get = snd_p16v_capture_channel_get,
.put = snd_p16v_capture_channel_put

View File

@ -685,6 +685,15 @@ static unsigned short snd_es1371_codec_read(ac97_t *ac97,
return 0;
}
static void snd_es1371_codec_wait(ac97_t *ac97)
{
msleep(750);
snd_es1371_codec_read(ac97, AC97_RESET);
snd_es1371_codec_read(ac97, AC97_VENDOR_ID1);
snd_es1371_codec_read(ac97, AC97_VENDOR_ID2);
msleep(50);
}
static void snd_es1371_adc_rate(ensoniq_t * ensoniq, unsigned int rate)
{
unsigned int n, truncm, freq, result;
@ -1585,6 +1594,7 @@ static int snd_ensoniq_1371_mixer(ensoniq_t * ensoniq)
static ac97_bus_ops_t ops = {
.write = snd_es1371_codec_write,
.read = snd_es1371_codec_read,
.wait = snd_es1371_codec_wait,
};
if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0)
@ -2008,21 +2018,11 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
if (pci->vendor == es1371_ac97_reset_hack[idx].vid &&
pci->device == es1371_ac97_reset_hack[idx].did &&
ensoniq->rev == es1371_ac97_reset_hack[idx].rev) {
unsigned long tmo;
signed long tmo2;
ensoniq->cssr |= ES_1371_ST_AC97_RST;
outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
/* need to delay around 20ms(bleech) to give
some CODECs enough time to wakeup */
tmo = jiffies + (HZ / 50) + 1;
while (1) {
tmo2 = tmo - jiffies;
if (tmo2 <= 0)
break;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(tmo2);
}
msleep(20);
break;
}
/* AC'97 warm reset to start the bitclk */

View File

@ -664,11 +664,6 @@ static inline u16 maestro_read(es1968_t *chip, u16 reg)
return result;
}
#define big_mdelay(msec) do {\
set_current_state(TASK_UNINTERRUPTIBLE);\
schedule_timeout(((msec) * HZ + 999) / 1000);\
} while (0)
/* Wait for the codec bus to be free */
static int snd_es1968_ac97_wait(es1968_t *chip)
{
@ -1809,8 +1804,7 @@ static void __devinit es1968_measure_clock(es1968_t *chip)
snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR);
do_gettimeofday(&start_time);
spin_unlock_irq(&chip->reg_lock);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ / 20); /* 50 msec */
msleep(50);
spin_lock_irq(&chip->reg_lock);
offset = __apu_get_register(chip, apu, 5);
do_gettimeofday(&stop_time);
@ -2093,7 +2087,7 @@ static void snd_es1968_ac97_reset(es1968_t *chip)
outw(0x0000, ioaddr + 0x60); /* write 0 to gpio 0 */
udelay(20);
outw(0x0001, ioaddr + 0x60); /* write 1 to gpio 1 */
big_mdelay(20);
msleep(20);
outw(save_68 | 0x1, ioaddr + 0x68); /* now restore .. */
outw((inw(ioaddr + 0x38) & 0xfffc) | 0x1, ioaddr + 0x38);
@ -2109,7 +2103,7 @@ static void snd_es1968_ac97_reset(es1968_t *chip)
outw(0x0001, ioaddr + 0x60); /* write 1 to gpio */
udelay(20);
outw(0x0009, ioaddr + 0x60); /* write 9 to gpio */
big_mdelay(500);
msleep(500);
//outw(inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38);
outw(inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a);
outw(inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c);
@ -2135,7 +2129,7 @@ static void snd_es1968_ac97_reset(es1968_t *chip)
if (w > 10000) {
outb(inb(ioaddr + 0x37) | 0x08, ioaddr + 0x37); /* do a software reset */
big_mdelay(500); /* oh my.. */
msleep(500); /* oh my.. */
outb(inb(ioaddr + 0x37) & ~0x08,
ioaddr + 0x37);
udelay(1);

View File

@ -262,6 +262,9 @@ enum {
#define AC_PINCTL_OUT_EN (1<<6)
#define AC_PINCTL_HP_EN (1<<7)
/* Unsolicited response - 8bit */
#define AC_USRSP_EN (1<<7)
/* configuration default - 32bit */
#define AC_DEFCFG_SEQUENCE (0xf<<0)
#define AC_DEFCFG_DEF_ASSOC (0xf<<4)

View File

@ -178,6 +178,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */
#define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */
/* GCTL unsolicited response enable bit */
#define ICH6_GCTL_UREN (1<<8)
/* GCTL reset bit */
#define ICH6_GCTL_RESET (1<<0)
@ -562,6 +565,9 @@ static int azx_reset(azx_t *chip)
return -EBUSY;
}
/* Accept unsolicited responses */
azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UREN);
/* detect codecs */
if (! chip->codec_mask) {
chip->codec_mask = azx_readw(chip, STATESTS);

View File

@ -408,7 +408,7 @@ static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec, const struct aut
/* search for an empty channel */
for (j = 0; j < cfg->line_outs; j++) {
if (! assigned[j]) {
spec->dac_nids[i] = i + 0x03;
spec->dac_nids[i] = j + 0x03;
assigned[j] = 1;
break;
}
@ -444,11 +444,10 @@ static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pi
len = snd_hda_get_connections(codec, nid, conn, 4);
for (k = 0; k < len; k++)
if (conn[k] == spec->dac_nids[i]) {
spec->multi_init[j].param = j;
spec->multi_init[j].param = k;
break;
}
j++;
break;
}
}
return 0;

View File

@ -40,6 +40,7 @@ enum {
ALC880_W810,
ALC880_Z71V,
ALC880_AUTO,
ALC880_6ST,
ALC880_6ST_DIG,
ALC880_F1734,
ALC880_ASUS,
@ -119,6 +120,7 @@ struct alc_spec {
unsigned int num_kctl_alloc, num_kctl_used;
snd_kcontrol_new_t *kctl_alloc;
struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[4];
};
@ -1547,9 +1549,10 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG },
{ .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG },
{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG },
{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG },
/* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */
{ .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG },
{ .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG },
/* note subvendor = 0 below */
/* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */
{ .modelname = "w810", .config = ALC880_W810 },
{ .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 },
@ -1557,7 +1560,10 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .modelname = "z71v", .config = ALC880_Z71V },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
{ .modelname = "6statack-digout", .config = ALC880_6ST_DIG },
{ .modelname = "6stack", .config = ALC880_6ST },
{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */
{ .modelname = "6stack-digout", .config = ALC880_6ST_DIG },
{ .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
{ .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
{ .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
@ -1644,6 +1650,15 @@ static struct alc_config_preset alc880_presets[] = {
.channel_mode = alc880_fivestack_modes,
.input_mux = &alc880_capture_source,
},
[ALC880_6ST] = {
.mixers = { alc880_six_stack_mixer },
.init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
.dac_nids = alc880_6st_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
.channel_mode = alc880_sixstack_modes,
.input_mux = &alc880_6stack_capture_source,
},
[ALC880_6ST_DIG] = {
.mixers = { alc880_six_stack_mixer },
.init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
@ -1656,7 +1671,8 @@ static struct alc_config_preset alc880_presets[] = {
},
[ALC880_W810] = {
.mixers = { alc880_w810_base_mixer },
.init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs },
.init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs,
alc880_gpio2_init_verbs },
.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
.dac_nids = alc880_w810_dac_nids,
.dig_out_nid = ALC880_DIGOUT_NID,
@ -1666,8 +1682,7 @@ static struct alc_config_preset alc880_presets[] = {
},
[ALC880_Z71V] = {
.mixers = { alc880_z71v_mixer },
.init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs,
alc880_gpio2_init_verbs },
.init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs },
.num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
.dac_nids = alc880_z71v_dac_nids,
.dig_out_nid = ALC880_DIGOUT_NID,
@ -1809,6 +1824,7 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pi
int i, j;
memset(assigned, 0, sizeof(assigned));
spec->multiout.dac_nids = spec->private_dac_nids;
/* check the pins hardwired to audio widget */
for (i = 0; i < cfg->line_outs; i++) {

File diff suppressed because it is too large Load Diff

View File

@ -424,6 +424,7 @@ struct _snd_intel8x0 {
unsigned xbox: 1; /* workaround for Xbox AC'97 detection */
int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */
unsigned int sdm_saved; /* SDM reg value */
ac97_bus_t *ac97_bus;
ac97_t *ac97[3];
@ -2373,6 +2374,8 @@ static int intel8x0_suspend(snd_card_t *card, pm_message_t state)
for (i = 0; i < 3; i++)
if (chip->ac97[i])
snd_ac97_suspend(chip->ac97[i]);
if (chip->device_type == DEVICE_INTEL_ICH4)
chip->sdm_saved = igetbyte(chip, ICHREG(SDM));
pci_disable_device(chip->pci);
return 0;
}
@ -2386,6 +2389,16 @@ static int intel8x0_resume(snd_card_t *card)
pci_set_master(chip->pci);
snd_intel8x0_chip_init(chip, 0);
/* re-initialize mixer stuff */
if (chip->device_type == DEVICE_INTEL_ICH4) {
/* enable separate SDINs for ICH4 */
iputbyte(chip, ICHREG(SDM), chip->sdm_saved);
/* use slot 10/11 for SPDIF */
iputdword(chip, ICHREG(GLOB_CNT),
(igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK) |
ICH_PCM_SPDIF_1011);
}
/* refill nocache */
if (chip->fix_nocache)
fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1);
@ -2451,8 +2464,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip)
}
do_gettimeofday(&start_time);
spin_unlock_irq(&chip->reg_lock);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ / 20);
msleep(50);
spin_lock_irq(&chip->reg_lock);
/* check the position */
pos = ichdev->fragsize1;

View File

@ -1050,11 +1050,6 @@ static struct m3_hv_quirk m3_hv_quirk_list[] = {
* lowlevel functions
*/
#define big_mdelay(msec) do {\
set_current_state(TASK_UNINTERRUPTIBLE);\
schedule_timeout(((msec) * HZ) / 1000);\
} while (0)
static inline void snd_m3_outw(m3_t *chip, u16 value, unsigned long reg)
{
outw(value, chip->iobase + reg);
@ -1096,7 +1091,7 @@ static void snd_m3_assp_write(m3_t *chip, u16 region, u16 index, u16 data)
static void snd_m3_assp_halt(m3_t *chip)
{
chip->reset_state = snd_m3_inb(chip, DSP_PORT_CONTROL_REG_B) & ~REGB_STOP_CLOCK;
big_mdelay(10);
msleep(10);
snd_m3_outb(chip, chip->reset_state & ~REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B);
}
@ -2108,9 +2103,9 @@ static void snd_m3_ac97_reset(m3_t *chip)
*/
tmp = inw(io + RING_BUS_CTRL_A);
outw(RAC_SDFS_ENABLE|LAC_SDFS_ENABLE, io + RING_BUS_CTRL_A);
big_mdelay(20);
msleep(20);
outw(tmp, io + RING_BUS_CTRL_A);
big_mdelay(50);
msleep(50);
#endif
}
@ -2525,9 +2520,13 @@ static void
snd_m3_enable_ints(m3_t *chip)
{
unsigned long io = chip->iobase;
unsigned short val;
/* TODO: MPU401 not supported yet */
outw(ASSP_INT_ENABLE | HV_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL);
val = ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/;
if (chip->hv_quirk && (chip->hv_quirk->config & HV_CTRL_ENABLE))
val |= HV_INT_ENABLE;
outw(val, io + HOST_INT_CTRL);
outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE,
io + ASSP_CONTROL_C);
}
@ -2589,7 +2588,7 @@ static int m3_suspend(snd_card_t *card, pm_message_t state)
snd_pcm_suspend_all(chip->pcm);
snd_ac97_suspend(chip->ac97);
big_mdelay(10); /* give the assp a chance to idle.. */
msleep(10); /* give the assp a chance to idle.. */
snd_m3_assp_halt(chip);
@ -2697,6 +2696,8 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
}
spin_lock_init(&chip->reg_lock);
spin_lock_init(&chip->ac97_lock);
switch (pci->device) {
case PCI_DEVICE_ID_ESS_ALLEGRO:
case PCI_DEVICE_ID_ESS_ALLEGRO_1:
@ -2765,6 +2766,8 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
snd_m3_assp_init(chip);
snd_m3_amp_enable(chip, 1);
tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
if (request_irq(pci->irq, snd_m3_interrupt, SA_INTERRUPT|SA_SHIRQ,
card->driver, (void *)chip)) {
snd_printk("unable to grab IRQ %d\n", pci->irq);
@ -2786,9 +2789,6 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
return err;
}
spin_lock_init(&chip->ac97_lock);
tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
if ((err = snd_m3_mixer(chip)) < 0)
return err;

View File

@ -445,9 +445,9 @@ static int snd_mixart_trigger(snd_pcm_substream_t *subs, int cmd)
static int mixart_sync_nonblock_events(mixart_mgr_t *mgr)
{
int timeout = HZ;
unsigned long timeout = jiffies + HZ;
while (atomic_read(&mgr->msg_processed) > 0) {
if (! timeout--) {
if (time_after(jiffies, timeout)) {
snd_printk(KERN_ERR "mixart: cannot process nonblock events!\n");
return -EBUSY;
}

View File

@ -445,6 +445,7 @@ struct _hdsp {
u32 control2_register; /* cached value */
u32 creg_spdif;
u32 creg_spdif_stream;
int clock_source_locked;
char *card_name; /* digiface/multiface */
HDSP_IO_Type io_type; /* ditto, but for code use */
unsigned short firmware_rev;
@ -678,8 +679,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
}
if ((1000 / HZ) < 3000) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((3000 * HZ + 999) / 1000);
ssleep(3);
} else {
mdelay(3000);
}
@ -2095,6 +2095,34 @@ static int snd_hdsp_put_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
return change;
}
static int snd_hdsp_info_clock_source_lock(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 1;
return 0;
}
static int snd_hdsp_get_clock_source_lock(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = hdsp->clock_source_locked;
return 0;
}
static int snd_hdsp_put_clock_source_lock(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked;
if (change)
hdsp->clock_source_locked = ucontrol->value.integer.value[0];
return change;
}
#define HDSP_DA_GAIN(xname, xindex) \
{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
.name = xname, \
@ -3117,6 +3145,15 @@ HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0),
HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0),
/* 'Sample Clock Source' complies with the alsa control naming scheme */
HDSP_CLOCK_SOURCE("Sample Clock Source", 0),
{
/* FIXME: should be PCM or MIXER? */
/* .iface = SNDRV_CTL_ELEM_IFACE_PCM, */
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Sample Clock Source Locking",
.info = snd_hdsp_info_clock_source_lock,
.get = snd_hdsp_get_clock_source_lock,
.put = snd_hdsp_put_clock_source_lock,
},
HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0),
HDSP_AUTOSYNC_REF("AutoSync Reference", 0),
@ -3349,6 +3386,7 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode);
snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate);
snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No");
snd_iprintf(buffer, "\n");
@ -3853,13 +3891,14 @@ static int snd_hdsp_hw_params(snd_pcm_substream_t *substream,
*/
spin_lock_irq(&hdsp->lock);
if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) {
spin_unlock_irq(&hdsp->lock);
_snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
return err;
} else {
spin_unlock_irq(&hdsp->lock);
if (! hdsp->clock_source_locked) {
if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) {
spin_unlock_irq(&hdsp->lock);
_snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
return err;
}
}
spin_unlock_irq(&hdsp->lock);
if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) {
_snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
@ -4284,13 +4323,17 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
if (hdsp->io_type == H9632) {
runtime->hw.channels_min = hdsp->qs_out_channels;
runtime->hw.channels_max = hdsp->ss_out_channels;
if (hdsp->clock_source_locked) {
runtime->hw.rate_min = runtime->hw.rate_max = hdsp->system_sample_rate;
} else if (hdsp->io_type == H9632) {
runtime->hw.rate_max = 192000;
runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
}
if (hdsp->io_type == H9632) {
runtime->hw.channels_min = hdsp->qs_out_channels;
runtime->hw.channels_max = hdsp->ss_out_channels;
}
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
snd_hdsp_hw_rule_out_channels, hdsp,
@ -5036,8 +5079,7 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
if (!is_9652 && !is_9632) {
/* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */
if ((1000 / HZ) < 2000) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((2000 * HZ + 999) / 1000);
ssleep(2);
} else {
mdelay(2000);
}

View File

@ -472,6 +472,7 @@ void snd_trident_write_voice_regs(trident_t * trident,
break;
default:
snd_BUG();
return;
}
outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
@ -3152,8 +3153,7 @@ static int snd_trident_gameport_open(struct gameport *gameport, int mode)
switch (mode) {
case GAMEPORT_MODE_COOKED:
outb(GAMEPORT_MODE_ADC, TRID_REG(chip, GAMEPORT_GCR));
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1 + 20 * HZ / 1000); /* 20msec */
msleep(20);
return 0;
case GAMEPORT_MODE_RAW:
outb(0, TRID_REG(chip, GAMEPORT_GCR));

View File

@ -547,8 +547,7 @@ static void snd_via82xx_codec_wait(ac97_t *ac97)
int err;
err = snd_via82xx_codec_ready(chip, ac97->num);
/* here we need to wait fairly for long time.. */
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/2);
msleep(500);
}
static void snd_via82xx_codec_write(ac97_t *ac97,
@ -1847,7 +1846,7 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
static int snd_via82xx_chip_init(via82xx_t *chip)
{
unsigned int val;
int max_count;
unsigned long end_time;
unsigned char pval;
#if 0 /* broken on K7M? */
@ -1889,14 +1888,14 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
}
/* wait until codec ready */
max_count = ((3 * HZ) / 4) + 1;
end_time = jiffies + msecs_to_jiffies(750);
do {
pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval);
if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */
break;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
} while (--max_count > 0);
} while (time_before(jiffies, end_time));
if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
snd_printk("AC'97 codec is not ready [0x%x]\n", val);
@ -1905,7 +1904,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ |
VIA_REG_AC97_SECONDARY_VALID |
(VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT));
max_count = ((3 * HZ) / 4) + 1;
end_time = jiffies + msecs_to_jiffies(750);
snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ |
VIA_REG_AC97_SECONDARY_VALID |
(VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT));
@ -1916,7 +1915,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
} while (--max_count > 0);
} while (time_before(jiffies, end_time));
/* This is ok, the most of motherboards have only one codec */
__ac97_ok2:
@ -2178,7 +2177,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
{ .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */
{ .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
{ .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_NO_VRA }, /* Twinhead mobo */
{ .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_SRC }, /* Twinhead laptop */
{ .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
{ .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
{ .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
@ -2187,6 +2186,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
{ .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
{ .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */
{ .subvendor = 0x4005, .subdevice = 0x4710, .action = VIA_DXS_SRC }, /* MSI K7T266 Pro2 (MS-6380 V2.0) BIOS 3.7 */
{ } /* terminator */
};
struct dxs_whitelist *w;

View File

@ -408,8 +408,7 @@ static void snd_via82xx_codec_wait(ac97_t *ac97)
int err;
err = snd_via82xx_codec_ready(chip, ac97->num);
/* here we need to wait fairly for long time.. */
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/2);
msleep(500);
}
static void snd_via82xx_codec_write(ac97_t *ac97,
@ -923,7 +922,7 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
static int snd_via82xx_chip_init(via82xx_t *chip)
{
unsigned int val;
int max_count;
unsigned long end_time;
unsigned char pval;
pci_read_config_byte(chip->pci, VIA_MC97_CTRL, &pval);
@ -962,14 +961,14 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
}
/* wait until codec ready */
max_count = ((3 * HZ) / 4) + 1;
end_time = jiffies + msecs_to_jiffies(750);
do {
pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval);
if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */
break;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
} while (--max_count > 0);
} while (time_before(jiffies, end_time));
if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
snd_printk("AC'97 codec is not ready [0x%x]\n", val);
@ -977,7 +976,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ |
VIA_REG_AC97_SECONDARY_VALID |
(VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT));
max_count = ((3 * HZ) / 4) + 1;
end_time = jiffies + msecs_to_jiffies(750);
snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ |
VIA_REG_AC97_SECONDARY_VALID |
(VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT));
@ -988,7 +987,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
} while (--max_count > 0);
} while (time_before(jiffies, end_time));
/* This is ok, the most of motherboards have only one codec */
__ac97_ok2:

View File

@ -84,16 +84,16 @@ static inline void snd_ymfpci_writel(ymfpci_t *chip, u32 offset, u32 val)
static int snd_ymfpci_codec_ready(ymfpci_t *chip, int secondary)
{
signed long end_time;
unsigned long end_time;
u32 reg = secondary ? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR;
end_time = (jiffies + ((3 * HZ) / 4)) + 1;
end_time = jiffies + msecs_to_jiffies(750);
do {
if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0)
return 0;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
} while (end_time - (signed long)jiffies >= 0);
} while (time_before(jiffies, end_time));
snd_printk("codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg));
return -EBUSY;
}

View File

@ -8,23 +8,12 @@ config SND_VXPOCKET
depends on SND && PCMCIA && ISA
select SND_VX_LIB
help
Say Y here to include support for Digigram VXpocket
soundcards.
Say Y here to include support for Digigram VXpocket and
VXpocket 440 soundcards.
To compile this driver as a module, choose M here: the module
will be called snd-vxpocket.
config SND_VXP440
tristate "Digigram VXpocket 440"
depends on SND && PCMCIA && ISA
select SND_VX_LIB
help
Say Y here to include support for Digigram VXpocket 440
soundcards.
To compile this driver as a module, choose M here: the module
will be called snd-vxp440.
config SND_PDAUDIOCF
tristate "Sound Core PDAudioCF"
depends on SND && PCMCIA && ISA

View File

@ -3,9 +3,6 @@
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
#
snd-vx-cs-objs := vx_entry.o vxp_ops.o vxp_mixer.o
snd-vxpocket-objs := vxpocket.o
snd-vxp440-objs := vxp440.o
snd-vxpocket-objs := vxpocket.o vxp_ops.o vxp_mixer.o
obj-$(CONFIG_SND_VXPOCKET) += snd-vxpocket.o snd-vx-cs.o
obj-$(CONFIG_SND_VXP440) += snd-vxp440.o snd-vx-cs.o
obj-$(CONFIG_SND_VXPOCKET) += snd-vxpocket.o

View File

@ -1,375 +0,0 @@
/*
* Driver for Digigram VXpocket soundcards
*
* PCMCIA entry part
*
* Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sound/driver.h>
#include <sound/core.h>
#include "vxpocket.h"
#include <pcmcia/ciscode.h>
#include <pcmcia/cisreg.h>
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("Common routines for Digigram PCMCIA VX drivers");
MODULE_LICENSE("GPL");
/*
* prototypes
*/
static void vxpocket_config(dev_link_t *link);
static void vxpocket_release(dev_link_t *link)
{
if (link->state & DEV_CONFIG) {
/* release cs resources */
pcmcia_release_configuration(link->handle);
pcmcia_release_io(link->handle, &link->io);
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
}
}
/*
* destructor
*/
static int snd_vxpocket_free(vx_core_t *chip)
{
struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
struct snd_vxp_entry *hw;
dev_link_t *link = &vxp->link;
vxpocket_release(link);
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
hw = vxp->hw_entry;
if (hw)
hw->card_list[vxp->index] = NULL;
chip->card = NULL;
kfree(chip->dev);
snd_vx_free_firmware(chip);
kfree(chip);
return 0;
}
static int snd_vxpocket_dev_free(snd_device_t *device)
{
vx_core_t *chip = device->device_data;
return snd_vxpocket_free(chip);
}
/*
* snd_vxpocket_attach - attach callback for cs
* @hw: the hardware information
*/
dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw)
{
client_reg_t client_reg; /* Register with cardmgr */
dev_link_t *link; /* Info for cardmgr */
int i, ret;
vx_core_t *chip;
struct snd_vxpocket *vxp;
snd_card_t *card;
static snd_device_ops_t ops = {
.dev_free = snd_vxpocket_dev_free,
};
snd_printdd(KERN_DEBUG "vxpocket_attach called\n");
/* find an empty slot from the card list */
for (i = 0; i < SNDRV_CARDS; i++) {
if (! hw->card_list[i])
break;
}
if (i >= SNDRV_CARDS) {
snd_printk(KERN_ERR "vxpocket: too many cards found\n");
return NULL;
}
if (! hw->enable_table[i])
return NULL; /* disabled explicitly */
/* ok, create a card instance */
card = snd_card_new(hw->index_table[i], hw->id_table[i], THIS_MODULE, 0);
if (card == NULL) {
snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n");
return NULL;
}
chip = snd_vx_create(card, hw->hardware, hw->ops,
sizeof(struct snd_vxpocket) - sizeof(vx_core_t));
if (! chip)
return NULL;
#ifdef SND_VX_FW_LOADER
/* fake a device here since pcmcia doesn't give a valid device... */
chip->dev = kcalloc(1, sizeof(*chip->dev), GFP_KERNEL);
if (! chip->dev) {
snd_printk(KERN_ERR "vxp: can't malloc chip->dev\n");
kfree(chip);
snd_card_free(card);
return NULL;
}
device_initialize(chip->dev);
sprintf(chip->dev->bus_id, "vxpocket%d", i);
#endif
if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) {
kfree(chip);
snd_card_free(card);
return NULL;
}
vxp = (struct snd_vxpocket *)chip;
vxp->index = i;
vxp->hw_entry = hw;
chip->ibl.size = hw->ibl[i];
hw->card_list[i] = chip;
link = &vxp->link;
link->priv = chip;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
link->io.NumPorts1 = 16;
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
// link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &snd_vx_irq_handler;
link->irq.Instance = chip;
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
/* Register with Card Services */
memset(&client_reg, 0, sizeof(client_reg));
client_reg.dev_info = hw->dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
snd_card_free(card);
return NULL;
}
/* Chain drivers */
link->next = hw->dev_list;
hw->dev_list = link;
/* snd_card_set_pm_callback(card, snd_vxpocket_suspend, snd_vxpocket_resume, chip); */
return link;
}
/**
* snd_vxpocket_assign_resources - initialize the hardware and card instance.
* @port: i/o port for the card
* @irq: irq number for the card
*
* this function assigns the specified port and irq, boot the card,
* create pcm and control instances, and initialize the rest hardware.
*
* returns 0 if successful, or a negative error code.
*/
static int snd_vxpocket_assign_resources(vx_core_t *chip, int port, int irq)
{
int err;
snd_card_t *card = chip->card;
struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq);
vxp->port = port;
sprintf(card->shortname, "Digigram %s", card->driver);
sprintf(card->longname, "%s at 0x%x, irq %i",
card->shortname, port, irq);
chip->irq = irq;
if ((err = snd_vx_setup_firmware(chip)) < 0)
return err;
return 0;
}
/*
* snd_vxpocket_detach - detach callback for cs
* @hw: the hardware information
*/
void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link)
{
vx_core_t *chip;
if (! link)
return;
chip = link->priv;
snd_printdd(KERN_DEBUG "vxpocket_detach called\n");
/* Remove the interface data from the linked list */
if (hw) {
dev_link_t **linkp;
/* Locate device structure */
for (linkp = &hw->dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) {
*linkp = link->next;
break;
}
}
chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */
snd_card_disconnect(chip->card);
snd_card_free_in_thread(chip->card);
}
/*
* configuration callback
*/
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static void vxpocket_config(dev_link_t *link)
{
client_handle_t handle = link->handle;
vx_core_t *chip = link->priv;
struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
tuple_t tuple;
cisparse_t *parse = NULL;
u_short buf[32];
int last_fn, last_ret;
snd_printdd(KERN_DEBUG "vxpocket_config called\n");
parse = kmalloc(sizeof(*parse), GFP_KERNEL);
if (! parse) {
snd_printk(KERN_ERR "vx: cannot allocate\n");
return;
}
tuple.Attributes = 0;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
/* Configure card */
link->state |= DEV_CONFIG;
CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
goto failed;
link->dev = &vxp->node;
link->state &= ~DEV_CONFIG_PENDING;
kfree(parse);
return;
cs_failed:
cs_error(link->handle, last_fn, last_ret);
failed:
pcmcia_release_configuration(link->handle);
pcmcia_release_io(link->handle, &link->io);
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
kfree(parse);
}
/*
* event callback
*/
int vxpocket_event(event_t event, int priority, event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
vx_core_t *chip = link->priv;
switch (event) {
case CS_EVENT_CARD_REMOVAL:
snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n");
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
chip->chip_status |= VX_STAT_IS_STALE;
}
break;
case CS_EVENT_CARD_INSERTION:
snd_printdd(KERN_DEBUG "CARD_INSERTION..\n");
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
vxpocket_config(link);
break;
#ifdef CONFIG_PM
case CS_EVENT_PM_SUSPEND:
snd_printdd(KERN_DEBUG "SUSPEND\n");
link->state |= DEV_SUSPEND;
if (chip && chip->card->pm_suspend) {
snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
chip->card->pm_suspend(chip->card, PMSG_SUSPEND);
}
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
snd_printdd(KERN_DEBUG "RESUME\n");
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
snd_printdd(KERN_DEBUG "CARD_RESET\n");
if (DEV_OK(link)) {
//struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
snd_printdd(KERN_DEBUG "requestconfig...\n");
pcmcia_request_configuration(link->handle, &link->conf);
if (chip && chip->card->pm_resume) {
snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
chip->card->pm_resume(chip->card);
}
}
snd_printdd(KERN_DEBUG "resume done!\n");
break;
#endif
}
return 0;
}
/*
* exported stuffs
*/
EXPORT_SYMBOL(snd_vxpocket_ops);
EXPORT_SYMBOL(snd_vxpocket_attach);
EXPORT_SYMBOL(vxpocket_event);
EXPORT_SYMBOL(snd_vxpocket_detach);

View File

@ -1,14 +0,0 @@
#define COMPILE_VXP440
/*
add the following as /etc/pcmcia/vxp440.conf:
device "snd-vxp440"
class "audio" module "snd-vxp440"
card "Digigram VX-POCKET440"
manfid 0x01f1, 0x0100
bind "snd-vxp440"
*/
#include "vxpocket.c"

View File

@ -24,21 +24,17 @@
#include <linux/moduleparam.h>
#include <sound/core.h>
#include "vxpocket.h"
#include <pcmcia/ciscode.h>
#include <pcmcia/cisreg.h>
#include <sound/initval.h>
/*
*/
#ifdef COMPILE_VXP440
#define CARD_NAME "VXPocket440"
#else
#define CARD_NAME "VXPocket"
#endif
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("Digigram " CARD_NAME);
MODULE_DESCRIPTION("Digigram VXPocket");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}");
MODULE_SUPPORTED_DEVICE("{{Digigram,VXPocket},{Digigram,VXPocket440}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
@ -46,82 +42,405 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
static int ibl[SNDRV_CARDS];
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
MODULE_PARM_DESC(index, "Index value for VXPocket soundcard.");
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
MODULE_PARM_DESC(id, "ID string for VXPocket soundcard.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
MODULE_PARM_DESC(enable, "Enable VXPocket soundcard.");
module_param_array(ibl, int, NULL, 0444);
MODULE_PARM_DESC(ibl, "Capture IBL size for " CARD_NAME " soundcard.");
MODULE_PARM_DESC(ibl, "Capture IBL size for VXPocket soundcard.");
/*
*/
#ifdef COMPILE_VXP440
static unsigned int card_alloc;
static dev_link_t *dev_list; /* Linked list of devices */
static dev_info_t dev_info = "snd-vxpocket";
/* 1 DSP, 1 sync UER, 1 sync World Clock (NIY) */
/* SMPTE (NIY) */
/* 2 stereo analog input (line/micro) */
/* 2 stereo analog output */
/* Only output levels can be modified */
/* UER, but only for the first two inputs and outputs. */
#define NUM_CODECS 2
#define CARD_TYPE VX_TYPE_VXP440
#define DEV_INFO "snd-vxp440"
static int vxpocket_event(event_t event, int priority, event_callback_args_t *args);
#else
/* 1 DSP, 1 sync UER */
/* 1 programmable clock (NIY) */
/* 1 stereo analog input (line/micro) */
/* 1 stereo analog output */
/* Only output levels can be modified */
/*
*/
static void vxpocket_release(dev_link_t *link)
{
if (link->state & DEV_CONFIG) {
/* release cs resources */
pcmcia_release_configuration(link->handle);
pcmcia_release_io(link->handle, &link->io);
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
}
if (link->handle) {
/* Break the link with Card Services */
pcmcia_deregister_client(link->handle);
link->handle = NULL;
}
}
#define NUM_CODECS 1
#define CARD_TYPE VX_TYPE_VXPOCKET
#define DEV_INFO "snd-vxpocket"
/*
* destructor, called from snd_card_free_in_thread()
*/
static int snd_vxpocket_dev_free(snd_device_t *device)
{
vx_core_t *chip = device->device_data;
#endif
snd_vx_free_firmware(chip);
kfree(chip);
return 0;
}
static dev_info_t dev_info = DEV_INFO;
static struct snd_vx_hardware vxp_hw = {
.name = CARD_NAME,
.type = CARD_TYPE,
/*
* Hardware information
*/
/* VX-pocket V2
*
* 1 DSP, 1 sync UER
* 1 programmable clock (NIY)
* 1 stereo analog input (line/micro)
* 1 stereo analog output
* Only output levels can be modified
*/
static struct snd_vx_hardware vxpocket_hw = {
.name = "VXPocket",
.type = VX_TYPE_VXPOCKET,
/* hardware specs */
.num_codecs = NUM_CODECS,
.num_ins = NUM_CODECS,
.num_outs = NUM_CODECS,
.num_codecs = 1,
.num_ins = 1,
.num_outs = 1,
.output_level_max = VX_ANALOG_OUT_LEVEL_MAX,
};
static struct snd_vxp_entry hw_entry = {
.dev_info = &dev_info,
/* VX-pocket 440
*
* 1 DSP, 1 sync UER, 1 sync World Clock (NIY)
* SMPTE (NIY)
* 2 stereo analog input (line/micro)
* 2 stereo analog output
* Only output levels can be modified
* UER, but only for the first two inputs and outputs.
*/
/* module parameters */
.index_table = index,
.id_table = id,
.enable_table = enable,
.ibl = ibl,
static struct snd_vx_hardware vxp440_hw = {
.name = "VXPocket440",
.type = VX_TYPE_VXP440,
/* hardware specs */
.num_codecs = 2,
.num_ins = 2,
.num_outs = 2,
.output_level_max = VX_ANALOG_OUT_LEVEL_MAX,
};
/*
* create vxpocket instance
*/
static struct snd_vxpocket *snd_vxpocket_new(snd_card_t *card, int ibl)
{
client_reg_t client_reg; /* Register with cardmgr */
dev_link_t *link; /* Info for cardmgr */
vx_core_t *chip;
struct snd_vxpocket *vxp;
int ret;
static snd_device_ops_t ops = {
.dev_free = snd_vxpocket_dev_free,
};
chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops,
sizeof(struct snd_vxpocket) - sizeof(vx_core_t));
if (! chip)
return NULL;
if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) {
kfree(chip);
return NULL;
}
chip->ibl.size = ibl;
vxp = (struct snd_vxpocket *)chip;
link = &vxp->link;
link->priv = chip;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
link->io.NumPorts1 = 16;
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &snd_vx_irq_handler;
link->irq.Instance = chip;
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
/* Register with Card Services */
memset(&client_reg, 0, sizeof(client_reg));
client_reg.dev_info = &dev_info;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL
#ifdef CONFIG_PM
| CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET
| CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME
#endif
;
client_reg.event_handler = &vxpocket_event;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
return NULL;
}
return vxp;
}
/**
* snd_vxpocket_assign_resources - initialize the hardware and card instance.
* @port: i/o port for the card
* @irq: irq number for the card
*
* this function assigns the specified port and irq, boot the card,
* create pcm and control instances, and initialize the rest hardware.
*
* returns 0 if successful, or a negative error code.
*/
static int snd_vxpocket_assign_resources(vx_core_t *chip, int port, int irq)
{
int err;
snd_card_t *card = chip->card;
struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq);
vxp->port = port;
sprintf(card->shortname, "Digigram %s", card->driver);
sprintf(card->longname, "%s at 0x%x, irq %i",
card->shortname, port, irq);
chip->irq = irq;
if ((err = snd_vx_setup_firmware(chip)) < 0)
return err;
return 0;
}
/*
* configuration callback
*/
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static void vxpocket_config(dev_link_t *link)
{
client_handle_t handle = link->handle;
vx_core_t *chip = link->priv;
struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
tuple_t tuple;
cisparse_t *parse;
u_short buf[32];
int last_fn, last_ret;
snd_printdd(KERN_DEBUG "vxpocket_config called\n");
parse = kmalloc(sizeof(*parse), GFP_KERNEL);
if (! parse) {
snd_printk(KERN_ERR "vx: cannot allocate\n");
return;
}
tuple.Attributes = 0;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
/* redefine hardware record according to the VERSION1 string */
tuple.DesiredTuple = CISTPL_VERS_1;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
if (! strcmp(parse->version_1.str + parse->version_1.ofs[1], "VX-POCKET")) {
snd_printdd("VX-pocket is detected\n");
} else {
snd_printdd("VX-pocket 440 is detected\n");
/* overwrite the hardware information */
chip->hw = &vxp440_hw;
chip->type = vxp440_hw.type;
strcpy(chip->card->driver, vxp440_hw.name);
}
/* Configure card */
link->state |= DEV_CONFIG;
CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io));
CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
chip->dev = &handle_to_dev(link->handle);
if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0)
goto failed;
link->dev = &vxp->node;
link->state &= ~DEV_CONFIG_PENDING;
kfree(parse);
return;
cs_failed:
cs_error(link->handle, last_fn, last_ret);
failed:
pcmcia_release_configuration(link->handle);
pcmcia_release_io(link->handle, &link->io);
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
kfree(parse);
}
/*
* event callback
*/
static int vxpocket_event(event_t event, int priority, event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
vx_core_t *chip = link->priv;
switch (event) {
case CS_EVENT_CARD_REMOVAL:
snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n");
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
chip->chip_status |= VX_STAT_IS_STALE;
break;
case CS_EVENT_CARD_INSERTION:
snd_printdd(KERN_DEBUG "CARD_INSERTION..\n");
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
vxpocket_config(link);
break;
#ifdef CONFIG_PM
case CS_EVENT_PM_SUSPEND:
snd_printdd(KERN_DEBUG "SUSPEND\n");
link->state |= DEV_SUSPEND;
if (chip && chip->card->pm_suspend) {
snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
chip->card->pm_suspend(chip->card, PMSG_SUSPEND);
}
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
snd_printdd(KERN_DEBUG "RESUME\n");
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
snd_printdd(KERN_DEBUG "CARD_RESET\n");
if (DEV_OK(link)) {
//struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
snd_printdd(KERN_DEBUG "requestconfig...\n");
pcmcia_request_configuration(link->handle, &link->conf);
if (chip && chip->card->pm_resume) {
snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
chip->card->pm_resume(chip->card);
}
}
snd_printdd(KERN_DEBUG "resume done!\n");
break;
#endif
}
return 0;
}
/* h/w config */
.hardware = &vxp_hw,
.ops = &snd_vxpocket_ops,
};
/*
*/
static dev_link_t *vxp_attach(void)
{
return snd_vxpocket_attach(&hw_entry);
snd_card_t *card;
struct snd_vxpocket *vxp;
int i;
/* find an empty slot from the card list */
for (i = 0; i < SNDRV_CARDS; i++) {
if (! card_alloc & (1 << i))
break;
}
if (i >= SNDRV_CARDS) {
snd_printk(KERN_ERR "vxpocket: too many cards found\n");
return NULL;
}
if (! enable[i])
return NULL; /* disabled explicitly */
/* ok, create a card instance */
card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
if (card == NULL) {
snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n");
return NULL;
}
vxp = snd_vxpocket_new(card, ibl[i]);
if (! vxp) {
snd_card_free(card);
return NULL;
}
vxp->index = index[i];
card_alloc |= 1 << i;
/* Chain drivers */
vxp->link.next = dev_list;
dev_list = &vxp->link;
return &vxp->link;
}
static void vxp_detach(dev_link_t *link)
{
snd_vxpocket_detach(&hw_entry, link);
struct snd_vxpocket *vxp;
vx_core_t *chip;
dev_link_t **linkp;
if (! link)
return;
vxp = link->priv;
chip = (vx_core_t *)vxp;
card_alloc &= ~(1 << vxp->index);
/* Remove the interface data from the linked list */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) {
*linkp = link->next;
break;
}
chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */
snd_card_disconnect(chip->card);
vxpocket_release(link);
snd_card_free_in_thread(chip->card);
}
/*
@ -137,7 +456,7 @@ MODULE_DEVICE_TABLE(pcmcia, vxp_ids);
static struct pcmcia_driver vxp_cs_driver = {
.owner = THIS_MODULE,
.drv = {
.name = DEV_INFO,
.name = "snd-vxpocket",
},
.attach = vxp_attach,
.detach = vxp_detach,
@ -152,7 +471,7 @@ static int __init init_vxpocket(void)
static void __exit exit_vxpocket(void)
{
pcmcia_unregister_driver(&vxp_cs_driver);
BUG_ON(hw_entry.dev_list != NULL);
BUG_ON(dev_list != NULL);
}
module_init(init_vxpocket);

View File

@ -28,24 +28,6 @@
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
struct snd_vxp_entry {
dev_info_t *dev_info;
/* module parameters */
int *index_table;
char **id_table;
int *enable_table;
int *ibl;
/* h/w config */
struct snd_vx_hardware *hardware;
struct snd_vx_ops *ops;
/* slots */
vx_core_t *card_list[SNDRV_CARDS];
dev_link_t *dev_list; /* Linked list of devices */
};
struct snd_vxpocket {
vx_core_t core;
@ -57,8 +39,7 @@ struct snd_vxpocket {
unsigned int regCDSP; /* current CDSP register */
unsigned int regDIALOG; /* current DIALOG register */
int index;
struct snd_vxp_entry *hw_entry;
int index; /* card index */
/* pcmcia stuff */
dev_link_t link;
@ -70,12 +51,6 @@ extern struct snd_vx_ops snd_vxpocket_ops;
void vx_set_mic_boost(vx_core_t *chip, int boost);
void vx_set_mic_level(vx_core_t *chip, int level);
/*
* pcmcia stuff
*/
dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw);
void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link);
int vxp_add_mic_controls(vx_core_t *chip);
/* Constants used to access the CDSP register (0x08). */

View File

@ -103,7 +103,7 @@ static void screamer_recalibrate(pmac_t *chip)
snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
if (chip->manufacturer == 0x1)
/* delay for broken crystal part */
big_mdelay(750);
msleep(750);
snd_pmac_awacs_write_noreg(chip, 1,
chip->awacs_reg[1] | MASK_RECALIBRATE | MASK_CMUTE | MASK_AMUTE);
snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
@ -653,10 +653,10 @@ static void snd_pmac_awacs_resume(pmac_t *chip)
{
if (machine_is_compatible("PowerBook3,1")
|| machine_is_compatible("PowerBook3,2")) {
big_mdelay(100);
msleep(100);
snd_pmac_awacs_write_reg(chip, 1,
chip->awacs_reg[1] & ~MASK_PAROUT);
big_mdelay(300);
msleep(300);
}
awacs_restore_all_regs(chip);

View File

@ -212,9 +212,4 @@ int snd_pmac_boolean_mono_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *ui
int snd_pmac_add_automute(pmac_t *chip);
#define big_mdelay(msec) do {\
set_current_state(TASK_UNINTERRUPTIBLE);\
schedule_timeout(((msec) * HZ + 999) / 1000);\
} while (0)
#endif /* __PMAC_H */

View File

@ -945,7 +945,7 @@ static void device_change_handler(void *self)
check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify,
chip->lineout_sw_ctl);
if (mix->anded_reset)
big_mdelay(10);
msleep(10);
check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify,
chip->speaker_sw_ctl);
mix->drc_enable = 0;
@ -954,7 +954,7 @@ static void device_change_handler(void *self)
check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify,
chip->speaker_sw_ctl);
if (mix->anded_reset)
big_mdelay(10);
msleep(10);
check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify,
chip->master_sw_ctl);
if (mix->line_mute.addr != 0)
@ -1109,22 +1109,22 @@ static void tumbler_reset_audio(pmac_t *chip)
DBG("(I) codec anded reset !\n");
write_audio_gpio(&mix->hp_mute, 0);
write_audio_gpio(&mix->amp_mute, 0);
big_mdelay(200);
msleep(200);
write_audio_gpio(&mix->hp_mute, 1);
write_audio_gpio(&mix->amp_mute, 1);
big_mdelay(100);
msleep(100);
write_audio_gpio(&mix->hp_mute, 0);
write_audio_gpio(&mix->amp_mute, 0);
big_mdelay(100);
msleep(100);
} else {
DBG("(I) codec normal reset !\n");
write_audio_gpio(&mix->audio_reset, 0);
big_mdelay(200);
msleep(200);
write_audio_gpio(&mix->audio_reset, 1);
big_mdelay(100);
msleep(100);
write_audio_gpio(&mix->audio_reset, 0);
big_mdelay(100);
msleep(100);
}
}

View File

@ -7,12 +7,30 @@ config SND_SUN_AMD7930
tristate "Sun AMD7930"
depends on SBUS && SND
select SND_PCM
help
Say Y here to include support for AMD7930 sound device on Sun.
To compile this driver as a module, choose M here: the module
will be called snd-sun-amd7930.
# dep_tristate 'Sun DBRI' CONFIG_SND_SUN_DBRI $CONFIG_SND
config SND_SUN_CS4231
tristate "Sun CS4231"
depends on SND
select SND_PCM
help
Say Y here to include support for CS4231 sound device on Sun.
To compile this driver as a module, choose M here: the module
will be called snd-sun-cs4231.
config SND_SUN_DBRI
tristate "Sun DBRI"
depends on SND && SBUS
select SND_PCM
help
Say Y here to include support for DBRI sound device on Sun.
To compile this driver as a module, choose M here: the module
will be called snd-sun-dbri.
endmenu

View File

@ -4,9 +4,9 @@
#
snd-sun-amd7930-objs := amd7930.o
#snd-sun-dbri-objs := dbri.o
snd-sun-cs4231-objs := cs4231.o
snd-sun-dbri-objs := dbri.o
obj-$(CONFIG_SND_SUN_AMD7930) += snd-sun-amd7930.o
#obj-$(CONFIG_SND_SUN_DBRI) += snd-sun-dbri.o
obj-$(CONFIG_SND_SUN_CS4231) += snd-sun-cs4231.o
obj-$(CONFIG_SND_SUN_DBRI) += snd-sun-dbri.o

2729
sound/sparc/dbri.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -153,6 +153,7 @@ struct snd_usb_substream {
unsigned int format; /* USB data format */
unsigned int datapipe; /* the data i/o pipe */
unsigned int syncpipe; /* 1 - async out or adaptive in */
unsigned int datainterval; /* log_2 of data packet interval */
unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */
unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */
unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */
@ -518,7 +519,8 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
if (subs->fill_max)
counts = subs->maxframesize; /* fixed */
else {
subs->phase = (subs->phase & 0xffff) + subs->freqm;
subs->phase = (subs->phase & 0xffff)
+ (subs->freqm << subs->datainterval);
counts = subs->phase >> 16;
if (counts > subs->maxframesize)
counts = subs->maxframesize;
@ -790,7 +792,7 @@ static int start_urbs(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
*/
static int wait_clear_urbs(snd_usb_substream_t *subs)
{
int timeout = HZ;
unsigned long end_time = jiffies + msecs_to_jiffies(1000);
unsigned int i;
int alive;
@ -810,7 +812,7 @@ static int wait_clear_urbs(snd_usb_substream_t *subs)
break;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
} while (--timeout > 0);
} while (time_before(jiffies, end_time));
if (alive)
snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
return 0;
@ -899,16 +901,19 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
else
subs->freqn = get_usb_high_speed_rate(rate);
subs->freqm = subs->freqn;
subs->freqmax = subs->freqn + (subs->freqn >> 2); /* max. allowed frequency */
subs->phase = 0;
/* calculate the max. size of packet */
maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3)) >> 16;
if (subs->maxpacksize && maxsize > subs->maxpacksize) {
//snd_printd(KERN_DEBUG "maxsize %d is greater than defined size %d\n",
// maxsize, subs->maxpacksize);
/* calculate max. frequency */
if (subs->maxpacksize) {
/* whatever fits into a max. size packet */
maxsize = subs->maxpacksize;
subs->freqmax = (maxsize / (frame_bits >> 3))
<< (16 - subs->datainterval);
} else {
/* no max. packet size: just take 25% higher than nominal */
subs->freqmax = subs->freqn + (subs->freqn >> 2);
maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3))
>> (16 - subs->datainterval);
}
subs->phase = 0;
if (subs->fill_max)
subs->curpacksize = subs->maxpacksize;
@ -918,7 +923,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
urb_packs = nrpacks;
else
urb_packs = nrpacks * 8;
urb_packs = (nrpacks * 8) >> subs->datainterval;
/* allocate a temporary buffer for playback */
if (is_playback) {
@ -991,7 +996,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
u->urb->pipe = subs->datapipe;
u->urb->transfer_flags = URB_ISO_ASAP;
u->urb->number_of_packets = u->packets;
u->urb->interval = 1;
u->urb->interval = 1 << subs->datainterval;
u->urb->context = u;
u->urb->complete = snd_usb_complete_callback(snd_complete_urb);
}
@ -1195,6 +1200,12 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt)
subs->datapipe = usb_sndisocpipe(dev, ep);
else
subs->datapipe = usb_rcvisocpipe(dev, ep);
if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH &&
get_endpoint(alts, 0)->bInterval >= 1 &&
get_endpoint(alts, 0)->bInterval <= 4)
subs->datainterval = get_endpoint(alts, 0)->bInterval - 1;
else
subs->datainterval = 0;
subs->syncpipe = subs->syncinterval = 0;
subs->maxpacksize = fmt->maxpacksize;
subs->fill_max = 0;
@ -2397,10 +2408,9 @@ static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp,
if (chip->usb_id == USB_ID(0x041e, 0x3000) ||
chip->usb_id == USB_ID(0x041e, 0x3020)) {
if (fmt[3] == USB_FORMAT_TYPE_I &&
stream == SNDRV_PCM_STREAM_PLAYBACK &&
fp->rates != SNDRV_PCM_RATE_48000 &&
fp->rates != SNDRV_PCM_RATE_96000)
return -1; /* use 48k only */
return -1;
}
#endif
return 0;
@ -2492,8 +2502,10 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
fp->altset_idx = i;
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
/* FIXME: decode wMaxPacketSize of high bandwith endpoints */
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
* (fp->maxpacksize & 0x7ff);
fp->attributes = csep[3];
/* some quirks for attributes here */
@ -2723,7 +2735,8 @@ static int create_standard_interface_quirk(snd_usb_audio_t *chip,
* to detect the sample rate is by looking at wMaxPacketSize.
*/
static int create_ua700_ua25_quirk(snd_usb_audio_t *chip,
struct usb_interface *iface)
struct usb_interface *iface,
const snd_usb_audio_quirk_t *quirk)
{
static const struct audioformat ua_format = {
.format = SNDRV_PCM_FORMAT_S24_3LE,
@ -2814,7 +2827,9 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip,
/*
* Create a stream for an Edirol UA-1000 interface.
*/
static int create_ua1000_quirk(snd_usb_audio_t *chip, struct usb_interface *iface)
static int create_ua1000_quirk(snd_usb_audio_t *chip,
struct usb_interface *iface,
const snd_usb_audio_quirk_t *quirk)
{
static const struct audioformat ua1000_format = {
.format = SNDRV_PCM_FORMAT_S32_LE,
@ -2891,6 +2906,13 @@ static int create_composite_quirk(snd_usb_audio_t *chip,
return 0;
}
static int ignore_interface_quirk(snd_usb_audio_t *chip,
struct usb_interface *iface,
const snd_usb_audio_quirk_t *quirk)
{
return 0;
}
/*
* boot quirks
@ -2926,8 +2948,6 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
{
#if 0
/* TODO: enable this when high speed synchronization actually works */
u8 buf = 1;
snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a,
@ -2939,7 +2959,6 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
1, 2000, NULL, 0, 1000);
return -ENODEV;
}
#endif
return 0;
}
@ -2956,28 +2975,28 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip,
struct usb_interface *iface,
const snd_usb_audio_quirk_t *quirk)
{
switch (quirk->type) {
case QUIRK_MIDI_FIXED_ENDPOINT:
case QUIRK_MIDI_YAMAHA:
case QUIRK_MIDI_MIDIMAN:
case QUIRK_MIDI_NOVATION:
case QUIRK_MIDI_MOTU:
case QUIRK_MIDI_EMAGIC:
return snd_usb_create_midi_interface(chip, iface, quirk);
case QUIRK_COMPOSITE:
return create_composite_quirk(chip, iface, quirk);
case QUIRK_AUDIO_FIXED_ENDPOINT:
return create_fixed_stream_quirk(chip, iface, quirk);
case QUIRK_AUDIO_STANDARD_INTERFACE:
case QUIRK_MIDI_STANDARD_INTERFACE:
return create_standard_interface_quirk(chip, iface, quirk);
case QUIRK_AUDIO_EDIROL_UA700_UA25:
return create_ua700_ua25_quirk(chip, iface);
case QUIRK_AUDIO_EDIROL_UA1000:
return create_ua1000_quirk(chip, iface);
case QUIRK_IGNORE_INTERFACE:
return 0;
default:
typedef int (*quirk_func_t)(snd_usb_audio_t *, struct usb_interface *,
const snd_usb_audio_quirk_t *);
static const quirk_func_t quirk_funcs[] = {
[QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk,
[QUIRK_COMPOSITE] = create_composite_quirk,
[QUIRK_MIDI_STANDARD_INTERFACE] = snd_usb_create_midi_interface,
[QUIRK_MIDI_FIXED_ENDPOINT] = snd_usb_create_midi_interface,
[QUIRK_MIDI_YAMAHA] = snd_usb_create_midi_interface,
[QUIRK_MIDI_MIDIMAN] = snd_usb_create_midi_interface,
[QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface,
[QUIRK_MIDI_RAW] = snd_usb_create_midi_interface,
[QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface,
[QUIRK_MIDI_MIDITECH] = snd_usb_create_midi_interface,
[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_interface_quirk,
[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
[QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk,
[QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
};
if (quirk->type < QUIRK_TYPE_COUNT) {
return quirk_funcs[quirk->type](chip, iface, quirk);
} else {
snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
return -ENXIO;
}

View File

@ -153,20 +153,24 @@ struct snd_usb_audio {
#define QUIRK_NO_INTERFACE -2
#define QUIRK_ANY_INTERFACE -1
/* quirk type */
#define QUIRK_MIDI_FIXED_ENDPOINT 0
#define QUIRK_MIDI_YAMAHA 1
#define QUIRK_MIDI_MIDIMAN 2
#define QUIRK_COMPOSITE 3
#define QUIRK_AUDIO_FIXED_ENDPOINT 4
#define QUIRK_AUDIO_STANDARD_INTERFACE 5
#define QUIRK_MIDI_STANDARD_INTERFACE 6
#define QUIRK_AUDIO_EDIROL_UA700_UA25 7
#define QUIRK_AUDIO_EDIROL_UA1000 8
#define QUIRK_IGNORE_INTERFACE 9
#define QUIRK_MIDI_NOVATION 10
#define QUIRK_MIDI_MOTU 11
#define QUIRK_MIDI_EMAGIC 12
enum quirk_type {
QUIRK_IGNORE_INTERFACE,
QUIRK_COMPOSITE,
QUIRK_MIDI_STANDARD_INTERFACE,
QUIRK_MIDI_FIXED_ENDPOINT,
QUIRK_MIDI_YAMAHA,
QUIRK_MIDI_MIDIMAN,
QUIRK_MIDI_NOVATION,
QUIRK_MIDI_RAW,
QUIRK_MIDI_EMAGIC,
QUIRK_MIDI_MIDITECH,
QUIRK_AUDIO_STANDARD_INTERFACE,
QUIRK_AUDIO_FIXED_ENDPOINT,
QUIRK_AUDIO_EDIROL_UA700_UA25,
QUIRK_AUDIO_EDIROL_UA1000,
QUIRK_TYPE_COUNT
};
typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t;
typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t;
@ -175,7 +179,7 @@ struct snd_usb_audio_quirk {
const char *vendor_name;
const char *product_name;
int16_t ifnum;
int16_t type;
uint16_t type;
const void *data;
};
@ -205,11 +209,13 @@ struct snd_usb_midi_endpoint_info {
/* for QUIRK_IGNORE_INTERFACE, data is NULL */
/* for QUIRK_MIDI_NOVATION and _MOTU, data is NULL */
/* for QUIRK_MIDI_NOVATION and _RAW, data is NULL */
/* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info
* structure (out_cables and in_cables only) */
/* for QUIRK_MIDI_MIDITECH, data is NULL */
/*
*/

View File

@ -524,16 +524,16 @@ static struct usb_protocol_ops snd_usbmidi_novation_ops = {
};
/*
* Mark of the Unicorn USB MIDI protocol: raw MIDI.
* "raw" protocol: used by the MOTU FastLane.
*/
static void snd_usbmidi_motu_input(snd_usb_midi_in_endpoint_t* ep,
uint8_t* buffer, int buffer_length)
static void snd_usbmidi_raw_input(snd_usb_midi_in_endpoint_t* ep,
uint8_t* buffer, int buffer_length)
{
snd_usbmidi_input_data(ep, 0, buffer, buffer_length);
}
static void snd_usbmidi_motu_output(snd_usb_midi_out_endpoint_t* ep)
static void snd_usbmidi_raw_output(snd_usb_midi_out_endpoint_t* ep)
{
int count;
@ -549,9 +549,9 @@ static void snd_usbmidi_motu_output(snd_usb_midi_out_endpoint_t* ep)
ep->urb->transfer_buffer_length = count;
}
static struct usb_protocol_ops snd_usbmidi_motu_ops = {
.input = snd_usbmidi_motu_input,
.output = snd_usbmidi_motu_output,
static struct usb_protocol_ops snd_usbmidi_raw_ops = {
.input = snd_usbmidi_raw_input,
.output = snd_usbmidi_raw_output,
};
/*
@ -1505,8 +1505,8 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
umidi->usb_protocol_ops = &snd_usbmidi_novation_ops;
err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
break;
case QUIRK_MIDI_MOTU:
umidi->usb_protocol_ops = &snd_usbmidi_motu_ops;
case QUIRK_MIDI_RAW:
umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
break;
case QUIRK_MIDI_EMAGIC:
@ -1515,6 +1515,9 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
sizeof(snd_usb_midi_endpoint_info_t));
err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
break;
case QUIRK_MIDI_MIDITECH:
err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
break;
default:
snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
err = -ENXIO;

View File

@ -116,6 +116,7 @@ YAMAHA_DEVICE(0x1039, NULL),
YAMAHA_DEVICE(0x103a, NULL),
YAMAHA_DEVICE(0x103b, NULL),
YAMAHA_DEVICE(0x103c, NULL),
YAMAHA_DEVICE(0x103d, NULL),
YAMAHA_DEVICE(0x2000, "DGP-7"),
YAMAHA_DEVICE(0x2001, "DGP-5"),
YAMAHA_DEVICE(0x2002, NULL),
@ -1259,7 +1260,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
/* Mark of the Unicorn devices */
{
/* thanks to Robert A. Lerche <ral 'at' msbit.com> */
USB_DEVICE(0x07fd, 0x0001),
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_PRODUCT |
USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
.idVendor = 0x07fd,
.idProduct = 0x0001,
.bDeviceSubClass = 2,
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "MOTU",
.product_name = "Fastlane",
@ -1268,7 +1274,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.data = & (const snd_usb_audio_quirk_t[]) {
{
.ifnum = 0,
.type = QUIRK_MIDI_MOTU
.type = QUIRK_MIDI_RAW
},
{
.ifnum = 1,
@ -1372,6 +1378,25 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
USB_DEVICE(0x4752, 0x0011),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Miditech",
.product_name = "Midistart-2",
.ifnum = 0,
.type = QUIRK_MIDI_MIDITECH
}
},
{
USB_DEVICE(0x7104, 0x2202),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Miditech",
.product_name = "MidiStudio-2",
.ifnum = 0,
.type = QUIRK_MIDI_MIDITECH
}
},
{
/*
* Some USB MIDI devices don't have an audio control interface,

View File

@ -232,8 +232,7 @@ static int snd_usX2Y_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
if (err)
return err;
if (dsp->index == 1) {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/4); // give the device some time
msleep(250); // give the device some time
err = usX2Y_AsyncSeq04_init(priv);
if (err) {
snd_printk("usX2Y_AsyncSeq04_init error \n");

View File

@ -50,6 +50,7 @@
Currently rawusb dma pcm buffer transport (this file) is only available to snd-usb-usx2y.
*/
#include <linux/delay.h>
#include "usbusx2yaudio.c"
#if defined(USX2Y_NRPACKS_VARIABLE) || (!defined(USX2Y_NRPACKS_VARIABLE) && USX2Y_NRPACKS == 1)
@ -520,11 +521,8 @@ static int snd_usX2Y_usbpcm_prepare(snd_pcm_substream_t *substream)
usX2Y->hwdep_pcm_shm->playback_iso_start = -1;
if (atomic_read(&subs->state) < state_PREPARED) {
while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) > usX2Y->hwdep_pcm_shm->captured_iso_frames) {
signed long timeout;
snd_printd("Wait: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", usX2Y_iso_frames_per_buffer(runtime, usX2Y), usX2Y->hwdep_pcm_shm->captured_iso_frames);
set_current_state(TASK_INTERRUPTIBLE);
timeout = schedule_timeout(HZ/100 + 1);
if (signal_pending(current)) {
if (msleep_interruptible(10)) {
err = -ERESTARTSYS;
goto up_prepare_mutex;
}