forked from Minki/linux
Merge master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa
This commit is contained in:
commit
7b70888a19
@ -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
|
||||
-----------------
|
||||
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)"
|
||||
|
@ -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
|
||||
|
@ -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
410
sound/arm/pxa2xx-ac97.c
Normal 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
367
sound/arm/pxa2xx-pcm.c
Normal 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
29
sound/arm/pxa2xx-pcm.h
Normal 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 **);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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, }
|
||||
};
|
||||
|
||||
|
@ -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),
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
@ -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"
|
@ -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);
|
||||
|
@ -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). */
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
2729
sound/sparc/dbri.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user