Merge branch 'for-linus' of git://git.alsa-project.org/alsa-kernel
* 'for-linus' of git://git.alsa-project.org/alsa-kernel: (179 commits) ALSA: Release v1.0.17 ALSA: correct kcalloc usage ALSA: ALSA driver for SGI O2 audio board ALSA: asoc: kbuild - only show menus for the current ASoC CPU platform. ALSA: ALSA driver for SGI HAL2 audio device ALSA: hda - Fix FSC V5505 model ALSA: hda - Fix missing init for unsol events on micsense model ALSA: hda - Fix internal mic vref pin setup ALSA: hda: 92hd71bxx PC Beep ALSA: HDA - HP dc7600 with pci sub IDs 0x103c/0x3011 belongs to hp-3013 model ALSA: usb-audio: add some Yamaha USB MIDI quirks ALSA: usb-audio: fix Yamaha KX quirk ALSA: ASoC: Au12x0/Au1550 PSC Audio support ALSA: Add Yamaha KX49 (USB MIDI controller) to usbquirks.h ALSA: ASoC: pxa2xx-ac97: fix warning due to missing argument in fuction declaration ALSA: tosa: fix compilation with new DAPM API ALSA: wavefront - add const ALSA: remove CONFIG_KMOD from sound ALSA: Fix a const to non-const assignment in the Digigram VXpocket sound driver ALSA: Fix a const pointer usage warning in the Digigram VX soundcard driver ...
This commit is contained in:
commit
b5cf43c47b
|
@ -753,8 +753,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
[Multiple options for each card instance]
|
||||
model - force the model name
|
||||
position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)
|
||||
position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF)
|
||||
probe_mask - Bitmask to probe codecs (default = -1, meaning all slots)
|
||||
bdl_pos_adj - Specifies the DMA IRQ timing delay in samples.
|
||||
Passing -1 will make the driver to choose the appropriate
|
||||
value based on the controller chip.
|
||||
|
||||
[Single (global) options]
|
||||
single_cmd - Use single immediate commands to communicate with
|
||||
|
@ -845,7 +848,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
ALC269
|
||||
basic Basic preset
|
||||
|
||||
ALC662
|
||||
ALC662/663
|
||||
3stack-dig 3-stack (2-channel) with SPDIF
|
||||
3stack-6ch 3-stack (6-channel)
|
||||
3stack-6ch-dig 3-stack (6-channel) with SPDIF
|
||||
|
@ -853,6 +856,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
lenovo-101e Lenovo laptop
|
||||
eeepc-p701 ASUS Eeepc P701
|
||||
eeepc-ep20 ASUS Eeepc EP20
|
||||
m51va ASUS M51VA
|
||||
g71v ASUS G71V
|
||||
h13 ASUS H13
|
||||
g50v ASUS G50V
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC882/885
|
||||
|
@ -1091,7 +1098,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
This occurs when the access to non-existing or non-working codec slot
|
||||
(likely a modem one) causes a stall of the communication via HD-audio
|
||||
bus. You can see which codec slots are probed by enabling
|
||||
CONFIG_SND_DEBUG_DETECT, or simply from the file name of the codec
|
||||
CONFIG_SND_DEBUG_VERBOSE, or simply from the file name of the codec
|
||||
proc files. Then limit the slots to probe by probe_mask option.
|
||||
For example, probe_mask=1 means to probe only the first slot, and
|
||||
probe_mask=4 means only the third slot.
|
||||
|
@ -2267,6 +2274,10 @@ case above again, the first two slots are already reserved. If any
|
|||
other driver (e.g. snd-usb-audio) is loaded before snd-interwave or
|
||||
snd-ens1371, it will be assigned to the third or later slot.
|
||||
|
||||
When a module name is given with '!', the slot will be given for any
|
||||
modules but that name. For example, "slots=!snd-pcsp" will reserve
|
||||
the first slot for any modules but snd-pcsp.
|
||||
|
||||
|
||||
ALSA PCM devices to OSS devices mapping
|
||||
=======================================
|
||||
|
|
|
@ -6127,8 +6127,8 @@ struct _snd_pcm_runtime {
|
|||
|
||||
<para>
|
||||
<function>snd_printdd()</function> is compiled in only when
|
||||
<constant>CONFIG_SND_DEBUG_DETECT</constant> is set. Please note
|
||||
that <constant>DEBUG_DETECT</constant> is not set as default
|
||||
<constant>CONFIG_SND_DEBUG_VERBOSE</constant> is set. Please note
|
||||
that <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is not set as default
|
||||
even if you configure the alsa-driver with
|
||||
<option>--with-debug=full</option> option. You need to give
|
||||
explicitly <option>--with-debug=detect</option> option instead.
|
||||
|
|
|
@ -204,6 +204,14 @@ typedef struct psc_i2s {
|
|||
u32 psc_i2sudf;
|
||||
} psc_i2s_t;
|
||||
|
||||
#define PSC_I2SCFG_OFFSET 0x08
|
||||
#define PSC_I2SMASK_OFFSET 0x0C
|
||||
#define PSC_I2SPCR_OFFSET 0x10
|
||||
#define PSC_I2SSTAT_OFFSET 0x14
|
||||
#define PSC_I2SEVENT_OFFSET 0x18
|
||||
#define PSC_I2SRXTX_OFFSET 0x1C
|
||||
#define PSC_I2SUDF_OFFSET 0x20
|
||||
|
||||
/* I2S Config Register. */
|
||||
#define PSC_I2SCFG_RT_MASK (3 << 30)
|
||||
#define PSC_I2SCFG_RT_FIFO1 (0 << 30)
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright 2003 Vivien Chappelier <vivien.chappelier@linux-mips.org>
|
||||
* Copyright 2008 Thomas Bogendoerfer <tsbogend@franken.de>
|
||||
*/
|
||||
|
||||
#ifndef __SOUND_AD1843_H
|
||||
#define __SOUND_AD1843_H
|
||||
|
||||
struct snd_ad1843 {
|
||||
void *chip;
|
||||
int (*read)(void *chip, int reg);
|
||||
int (*write)(void *chip, int reg, int val);
|
||||
};
|
||||
|
||||
#define AD1843_GAIN_RECLEV 0
|
||||
#define AD1843_GAIN_LINE 1
|
||||
#define AD1843_GAIN_LINE_2 2
|
||||
#define AD1843_GAIN_MIC 3
|
||||
#define AD1843_GAIN_PCM_0 4
|
||||
#define AD1843_GAIN_PCM_1 5
|
||||
#define AD1843_GAIN_SIZE (AD1843_GAIN_PCM_1+1)
|
||||
|
||||
int ad1843_get_gain_max(struct snd_ad1843 *ad1843, int id);
|
||||
int ad1843_get_gain(struct snd_ad1843 *ad1843, int id);
|
||||
int ad1843_set_gain(struct snd_ad1843 *ad1843, int id, int newval);
|
||||
int ad1843_get_recsrc(struct snd_ad1843 *ad1843);
|
||||
int ad1843_set_recsrc(struct snd_ad1843 *ad1843, int newsrc);
|
||||
void ad1843_setup_dac(struct snd_ad1843 *ad1843,
|
||||
unsigned int id,
|
||||
unsigned int framerate,
|
||||
snd_pcm_format_t fmt,
|
||||
unsigned int channels);
|
||||
void ad1843_shutdown_dac(struct snd_ad1843 *ad1843,
|
||||
unsigned int id);
|
||||
void ad1843_setup_adc(struct snd_ad1843 *ad1843,
|
||||
unsigned int framerate,
|
||||
snd_pcm_format_t fmt,
|
||||
unsigned int channels);
|
||||
void ad1843_shutdown_adc(struct snd_ad1843 *ad1843);
|
||||
int ad1843_init(struct snd_ad1843 *ad1843);
|
||||
|
||||
#endif /* __SOUND_AD1843_H */
|
|
@ -129,9 +129,6 @@ int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
|
|||
#define snd_ctl_unregister_ioctl_compat(fcn)
|
||||
#endif
|
||||
|
||||
int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control);
|
||||
int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, struct snd_ctl_elem_value *control);
|
||||
|
||||
static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
|
||||
{
|
||||
return id->numid - kctl->id.numid;
|
||||
|
|
|
@ -412,13 +412,13 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
|
|||
|
||||
#endif /* CONFIG_SND_DEBUG */
|
||||
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
/**
|
||||
* snd_printdd - debug printk
|
||||
* @format: format string
|
||||
*
|
||||
* Works like snd_printk() for debugging purposes.
|
||||
* Ignored when CONFIG_SND_DEBUG_DETECT is not set.
|
||||
* Ignored when CONFIG_SND_DEBUG_VERBOSE is not set.
|
||||
*/
|
||||
#define snd_printdd(format, args...) snd_printk(format, ##args)
|
||||
#else
|
||||
|
@ -442,7 +442,7 @@ struct snd_pci_quirk {
|
|||
unsigned short subvendor; /* PCI subvendor ID */
|
||||
unsigned short subdevice; /* PCI subdevice ID */
|
||||
int value; /* value */
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
const char *name; /* name of the device (optional) */
|
||||
#endif
|
||||
};
|
||||
|
@ -450,7 +450,7 @@ struct snd_pci_quirk {
|
|||
#define _SND_PCI_QUIRK_ID(vend,dev) \
|
||||
.subvendor = (vend), .subdevice = (dev)
|
||||
#define SND_PCI_QUIRK_ID(vend,dev) {_SND_PCI_QUIRK_ID(vend, dev)}
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
#define SND_PCI_QUIRK(vend,dev,xname,val) \
|
||||
{_SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname)}
|
||||
#else
|
||||
|
|
|
@ -177,4 +177,12 @@
|
|||
#define CS4236_RIGHT_WAVE 0x1c /* right wavetable serial port volume */
|
||||
#define CS4236_VERSION 0x9c /* chip version and ID */
|
||||
|
||||
/* definitions for extended registers - OPTI93X */
|
||||
#define OPTi931_AUX_LEFT_INPUT 0x10
|
||||
#define OPTi931_AUX_RIGHT_INPUT 0x11
|
||||
#define OPTi93X_MIC_LEFT_INPUT 0x14
|
||||
#define OPTi93X_MIC_RIGHT_INPUT 0x15
|
||||
#define OPTi93X_OUT_LEFT 0x16
|
||||
#define OPTi93X_OUT_RIGHT 0x17
|
||||
|
||||
#endif /* __SOUND_CS4231_REGS_H */
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
/* compatible, but clones */
|
||||
#define CS4231_HW_INTERWAVE 0x1000 /* InterWave chip */
|
||||
#define CS4231_HW_OPL3SA2 0x1101 /* OPL3-SA2 chip, similar to cs4231 */
|
||||
#define CS4231_HW_OPTI93X 0x1102 /* Opti 930/931/933 */
|
||||
|
||||
/* defines for codec.hwshare */
|
||||
#define CS4231_HWSHARE_IRQ (1<<0)
|
||||
|
@ -120,6 +121,8 @@ unsigned char snd_cs4236_ext_in(struct snd_cs4231 *chip, unsigned char reg);
|
|||
void snd_cs4231_mce_up(struct snd_cs4231 *chip);
|
||||
void snd_cs4231_mce_down(struct snd_cs4231 *chip);
|
||||
|
||||
void snd_cs4231_overrange(struct snd_cs4231 *chip);
|
||||
|
||||
irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id);
|
||||
|
||||
const char *snd_cs4231_chip_id(struct snd_cs4231 *chip);
|
||||
|
|
|
@ -1670,6 +1670,7 @@ struct snd_emu_chip_details {
|
|||
unsigned char spi_dac; /* SPI interface for DAC */
|
||||
unsigned char i2c_adc; /* I2C interface for ADC */
|
||||
unsigned char adc_1361t; /* Use Philips 1361T ADC */
|
||||
unsigned char invert_shared_spdif; /* analog/digital switch inverted */
|
||||
const char *driver;
|
||||
const char *name;
|
||||
const char *id; /* for backward compatibility - can be NULL if not needed */
|
||||
|
|
|
@ -105,7 +105,7 @@ int snd_seq_event_port_attach(int client, struct snd_seq_port_callback *pcbp,
|
|||
int cap, int type, int midi_channels, int midi_voices, char *portname);
|
||||
int snd_seq_event_port_detach(int client, int port);
|
||||
|
||||
#ifdef CONFIG_KMOD
|
||||
#ifdef CONFIG_MODULES
|
||||
void snd_seq_autoload_lock(void);
|
||||
void snd_seq_autoload_unlock(void);
|
||||
#else
|
||||
|
|
|
@ -130,6 +130,13 @@
|
|||
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
|
||||
.shift = wshift, .invert = winvert}
|
||||
|
||||
/* generic register modifier widget */
|
||||
#define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \
|
||||
{ .id = wid, .name = wname, .kcontrols = NULL, .num_kcontrols = 0, \
|
||||
.reg = -((wreg) + 1), .shift = wshift, .mask = wmask, \
|
||||
.on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \
|
||||
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
|
||||
|
||||
/* dapm kcontrol types */
|
||||
#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
|
@ -193,6 +200,7 @@ struct snd_soc_dapm_widget;
|
|||
enum snd_soc_dapm_type;
|
||||
struct snd_soc_dapm_path;
|
||||
struct snd_soc_dapm_pin;
|
||||
struct snd_soc_dapm_route;
|
||||
|
||||
/* dapm controls */
|
||||
int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
|
||||
|
@ -205,25 +213,32 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
|
||||
const struct snd_soc_dapm_widget *widget);
|
||||
int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
|
||||
const struct snd_soc_dapm_widget *widget,
|
||||
int num);
|
||||
|
||||
/* dapm path setup */
|
||||
int snd_soc_dapm_connect_input(struct snd_soc_codec *codec,
|
||||
int __deprecated snd_soc_dapm_connect_input(struct snd_soc_codec *codec,
|
||||
const char *sink_name, const char *control_name, const char *src_name);
|
||||
int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
|
||||
void snd_soc_dapm_free(struct snd_soc_device *socdev);
|
||||
int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
|
||||
const struct snd_soc_dapm_route *route, int num);
|
||||
|
||||
/* dapm events */
|
||||
int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream,
|
||||
int event);
|
||||
int snd_soc_dapm_device_event(struct snd_soc_device *socdev, int event);
|
||||
int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
|
||||
enum snd_soc_bias_level level);
|
||||
|
||||
/* dapm sys fs - used by the core */
|
||||
int snd_soc_dapm_sys_add(struct device *dev);
|
||||
|
||||
/* dapm audio endpoint control */
|
||||
int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
|
||||
char *pin, int status);
|
||||
int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec);
|
||||
/* dapm audio pin control and status */
|
||||
int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin);
|
||||
int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin);
|
||||
int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin);
|
||||
int snd_soc_dapm_sync(struct snd_soc_codec *codec);
|
||||
|
||||
/* dapm widget types */
|
||||
enum snd_soc_dapm_type {
|
||||
|
@ -245,6 +260,18 @@ enum snd_soc_dapm_type {
|
|||
snd_soc_dapm_post, /* machine specific post widget - exec last */
|
||||
};
|
||||
|
||||
/*
|
||||
* DAPM audio route definition.
|
||||
*
|
||||
* Defines an audio route originating at source via control and finishing
|
||||
* at sink.
|
||||
*/
|
||||
struct snd_soc_dapm_route {
|
||||
const char *sink;
|
||||
const char *control;
|
||||
const char *source;
|
||||
};
|
||||
|
||||
/* dapm audio path between two widgets */
|
||||
struct snd_soc_dapm_path {
|
||||
char *name;
|
||||
|
@ -277,6 +304,9 @@ struct snd_soc_dapm_widget {
|
|||
unsigned char shift; /* bits to shift */
|
||||
unsigned int saved_value; /* widget saved value */
|
||||
unsigned int value; /* widget current value */
|
||||
unsigned int mask; /* non-shifted mask */
|
||||
unsigned int on_val; /* on state value */
|
||||
unsigned int off_val; /* off state value */
|
||||
unsigned char power:1; /* block power status */
|
||||
unsigned char invert:1; /* invert the power bit */
|
||||
unsigned char active:1; /* active stream on DAC, ADC's */
|
||||
|
|
|
@ -73,6 +73,15 @@
|
|||
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
|
||||
.private_value = (reg_left) | ((shift) << 8) | \
|
||||
((max) << 12) | ((invert) << 20) | ((reg_right) << 24) }
|
||||
#define SOC_DOUBLE_S8_TLV(xname, reg, min, max, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw_s8, .get = snd_soc_get_volsw_s8, \
|
||||
.put = snd_soc_put_volsw_s8, \
|
||||
.private_value = (reg) | (((signed char)max) << 16) | \
|
||||
(((signed char)min) << 24) }
|
||||
#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
|
||||
{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
|
||||
.mask = xmask, .texts = xtexts }
|
||||
|
@ -91,6 +100,15 @@
|
|||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmask, xinvert) }
|
||||
#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmask, xinvert,\
|
||||
xhandler_get, xhandler_put, tlv_array) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
|
||||
SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.info = snd_soc_info_volsw, \
|
||||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmask, xinvert) }
|
||||
#define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
|
||||
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
|
||||
.info = snd_soc_info_bool_ext, \
|
||||
|
@ -102,6 +120,24 @@
|
|||
.get = xhandler_get, .put = xhandler_put, \
|
||||
.private_value = (unsigned long)&xenum }
|
||||
|
||||
/*
|
||||
* Bias levels
|
||||
*
|
||||
* @ON: Bias is fully on for audio playback and capture operations.
|
||||
* @PREPARE: Prepare for audio operations. Called before DAPM switching for
|
||||
* stream start and stop operations.
|
||||
* @STANDBY: Low power standby state when no playback/capture operations are
|
||||
* in progress. NOTE: The transition time between STANDBY and ON
|
||||
* should be as fast as possible and no longer than 10ms.
|
||||
* @OFF: Power Off. No restrictions on transition times.
|
||||
*/
|
||||
enum snd_soc_bias_level {
|
||||
SND_SOC_BIAS_ON,
|
||||
SND_SOC_BIAS_PREPARE,
|
||||
SND_SOC_BIAS_STANDBY,
|
||||
SND_SOC_BIAS_OFF,
|
||||
};
|
||||
|
||||
/*
|
||||
* Digital Audio Interface (DAI) types
|
||||
*/
|
||||
|
@ -185,8 +221,7 @@ struct snd_soc_pcm_stream;
|
|||
struct snd_soc_ops;
|
||||
struct snd_soc_dai_mode;
|
||||
struct snd_soc_pcm_runtime;
|
||||
struct snd_soc_codec_dai;
|
||||
struct snd_soc_cpu_dai;
|
||||
struct snd_soc_dai;
|
||||
struct snd_soc_codec;
|
||||
struct snd_soc_machine_config;
|
||||
struct soc_enum;
|
||||
|
@ -221,6 +256,27 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
|
|||
struct snd_ac97_bus_ops *ops, int num);
|
||||
void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
|
||||
|
||||
/* Digital Audio Interface clocking API.*/
|
||||
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||
unsigned int freq, int dir);
|
||||
|
||||
int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
|
||||
int div_id, int div);
|
||||
|
||||
int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
|
||||
int pll_id, unsigned int freq_in, unsigned int freq_out);
|
||||
|
||||
/* Digital Audio interface formatting */
|
||||
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
|
||||
|
||||
int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
|
||||
unsigned int mask, int slots);
|
||||
|
||||
int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
|
||||
|
||||
/* Digital Audio Interface mute */
|
||||
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
|
||||
|
||||
/*
|
||||
*Controls
|
||||
*/
|
||||
|
@ -249,6 +305,12 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo);
|
||||
int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
/* SoC PCM stream information */
|
||||
struct snd_soc_pcm_stream {
|
||||
|
@ -272,87 +334,45 @@ struct snd_soc_ops {
|
|||
int (*trigger)(struct snd_pcm_substream *, int);
|
||||
};
|
||||
|
||||
/* ASoC codec DAI ops */
|
||||
struct snd_soc_codec_ops {
|
||||
/* codec DAI clocking configuration */
|
||||
int (*set_sysclk)(struct snd_soc_codec_dai *codec_dai,
|
||||
/* ASoC DAI ops */
|
||||
struct snd_soc_dai_ops {
|
||||
/* DAI clocking configuration */
|
||||
int (*set_sysclk)(struct snd_soc_dai *dai,
|
||||
int clk_id, unsigned int freq, int dir);
|
||||
int (*set_pll)(struct snd_soc_codec_dai *codec_dai,
|
||||
int (*set_pll)(struct snd_soc_dai *dai,
|
||||
int pll_id, unsigned int freq_in, unsigned int freq_out);
|
||||
int (*set_clkdiv)(struct snd_soc_codec_dai *codec_dai,
|
||||
int div_id, int div);
|
||||
int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
|
||||
|
||||
/* CPU DAI format configuration */
|
||||
int (*set_fmt)(struct snd_soc_codec_dai *codec_dai,
|
||||
unsigned int fmt);
|
||||
int (*set_tdm_slot)(struct snd_soc_codec_dai *codec_dai,
|
||||
/* DAI format configuration */
|
||||
int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
|
||||
int (*set_tdm_slot)(struct snd_soc_dai *dai,
|
||||
unsigned int mask, int slots);
|
||||
int (*set_tristate)(struct snd_soc_codec_dai *, int tristate);
|
||||
int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
|
||||
|
||||
/* digital mute */
|
||||
int (*digital_mute)(struct snd_soc_codec_dai *, int mute);
|
||||
int (*digital_mute)(struct snd_soc_dai *dai, int mute);
|
||||
};
|
||||
|
||||
/* ASoC cpu DAI ops */
|
||||
struct snd_soc_cpu_ops {
|
||||
/* CPU DAI clocking configuration */
|
||||
int (*set_sysclk)(struct snd_soc_cpu_dai *cpu_dai,
|
||||
int clk_id, unsigned int freq, int dir);
|
||||
int (*set_clkdiv)(struct snd_soc_cpu_dai *cpu_dai,
|
||||
int div_id, int div);
|
||||
int (*set_pll)(struct snd_soc_cpu_dai *cpu_dai,
|
||||
int pll_id, unsigned int freq_in, unsigned int freq_out);
|
||||
|
||||
/* CPU DAI format configuration */
|
||||
int (*set_fmt)(struct snd_soc_cpu_dai *cpu_dai,
|
||||
unsigned int fmt);
|
||||
int (*set_tdm_slot)(struct snd_soc_cpu_dai *cpu_dai,
|
||||
unsigned int mask, int slots);
|
||||
int (*set_tristate)(struct snd_soc_cpu_dai *, int tristate);
|
||||
};
|
||||
|
||||
/* SoC Codec DAI */
|
||||
struct snd_soc_codec_dai {
|
||||
char *name;
|
||||
int id;
|
||||
unsigned char type;
|
||||
|
||||
/* DAI capabilities */
|
||||
struct snd_soc_pcm_stream playback;
|
||||
struct snd_soc_pcm_stream capture;
|
||||
|
||||
/* DAI runtime info */
|
||||
struct snd_soc_codec *codec;
|
||||
unsigned int active;
|
||||
unsigned char pop_wait:1;
|
||||
|
||||
/* ops */
|
||||
struct snd_soc_ops ops;
|
||||
struct snd_soc_codec_ops dai_ops;
|
||||
|
||||
/* DAI private data */
|
||||
void *private_data;
|
||||
};
|
||||
|
||||
/* SoC CPU DAI */
|
||||
struct snd_soc_cpu_dai {
|
||||
|
||||
/* SoC DAI (Digital Audio Interface) */
|
||||
struct snd_soc_dai {
|
||||
/* DAI description */
|
||||
char *name;
|
||||
unsigned int id;
|
||||
unsigned char type;
|
||||
|
||||
/* DAI callbacks */
|
||||
int (*probe)(struct platform_device *pdev);
|
||||
void (*remove)(struct platform_device *pdev);
|
||||
int (*probe)(struct platform_device *pdev,
|
||||
struct snd_soc_dai *dai);
|
||||
void (*remove)(struct platform_device *pdev,
|
||||
struct snd_soc_dai *dai);
|
||||
int (*suspend)(struct platform_device *pdev,
|
||||
struct snd_soc_cpu_dai *cpu_dai);
|
||||
struct snd_soc_dai *dai);
|
||||
int (*resume)(struct platform_device *pdev,
|
||||
struct snd_soc_cpu_dai *cpu_dai);
|
||||
struct snd_soc_dai *dai);
|
||||
|
||||
/* ops */
|
||||
struct snd_soc_ops ops;
|
||||
struct snd_soc_cpu_ops dai_ops;
|
||||
struct snd_soc_dai_ops dai_ops;
|
||||
|
||||
/* DAI capabilities */
|
||||
struct snd_soc_pcm_stream capture;
|
||||
|
@ -360,7 +380,9 @@ struct snd_soc_cpu_dai {
|
|||
|
||||
/* DAI runtime info */
|
||||
struct snd_pcm_runtime *runtime;
|
||||
unsigned char active:1;
|
||||
struct snd_soc_codec *codec;
|
||||
unsigned int active;
|
||||
unsigned char pop_wait:1;
|
||||
void *dma_data;
|
||||
|
||||
/* DAI private data */
|
||||
|
@ -374,7 +396,8 @@ struct snd_soc_codec {
|
|||
struct mutex mutex;
|
||||
|
||||
/* callbacks */
|
||||
int (*dapm_event)(struct snd_soc_codec *codec, int event);
|
||||
int (*set_bias_level)(struct snd_soc_codec *,
|
||||
enum snd_soc_bias_level level);
|
||||
|
||||
/* runtime */
|
||||
struct snd_card *card;
|
||||
|
@ -396,12 +419,12 @@ struct snd_soc_codec {
|
|||
/* dapm */
|
||||
struct list_head dapm_widgets;
|
||||
struct list_head dapm_paths;
|
||||
unsigned int dapm_state;
|
||||
unsigned int suspend_dapm_state;
|
||||
enum snd_soc_bias_level bias_level;
|
||||
enum snd_soc_bias_level suspend_bias_level;
|
||||
struct delayed_work delayed_work;
|
||||
|
||||
/* codec DAI's */
|
||||
struct snd_soc_codec_dai *dai;
|
||||
struct snd_soc_dai *dai;
|
||||
unsigned int num_dai;
|
||||
};
|
||||
|
||||
|
@ -420,12 +443,12 @@ struct snd_soc_platform {
|
|||
int (*probe)(struct platform_device *pdev);
|
||||
int (*remove)(struct platform_device *pdev);
|
||||
int (*suspend)(struct platform_device *pdev,
|
||||
struct snd_soc_cpu_dai *cpu_dai);
|
||||
struct snd_soc_dai *dai);
|
||||
int (*resume)(struct platform_device *pdev,
|
||||
struct snd_soc_cpu_dai *cpu_dai);
|
||||
struct snd_soc_dai *dai);
|
||||
|
||||
/* pcm creation and destruction */
|
||||
int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *,
|
||||
int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
|
||||
struct snd_pcm *);
|
||||
void (*pcm_free)(struct snd_pcm *);
|
||||
|
||||
|
@ -439,8 +462,8 @@ struct snd_soc_dai_link {
|
|||
char *stream_name; /* Stream name */
|
||||
|
||||
/* DAI */
|
||||
struct snd_soc_codec_dai *codec_dai;
|
||||
struct snd_soc_cpu_dai *cpu_dai;
|
||||
struct snd_soc_dai *codec_dai;
|
||||
struct snd_soc_dai *cpu_dai;
|
||||
|
||||
/* machine stream operations */
|
||||
struct snd_soc_ops *ops;
|
||||
|
@ -467,7 +490,8 @@ struct snd_soc_machine {
|
|||
int (*resume_post)(struct platform_device *pdev);
|
||||
|
||||
/* callbacks */
|
||||
int (*dapm_event)(struct snd_soc_machine *, int event);
|
||||
int (*set_bias_level)(struct snd_soc_machine *,
|
||||
enum snd_soc_bias_level level);
|
||||
|
||||
/* CPU <--> Codec DAI links */
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
|
@ -482,6 +506,7 @@ struct snd_soc_device {
|
|||
struct snd_soc_codec *codec;
|
||||
struct snd_soc_codec_device *codec_dev;
|
||||
struct delayed_work delayed_work;
|
||||
struct work_struct deferred_resume_work;
|
||||
void *codec_data;
|
||||
};
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
* features support
|
||||
*/
|
||||
|
||||
/* $Id: uda1341.h,v 1.8 2005/11/17 14:17:21 tiwai Exp $ */
|
||||
|
||||
#define UDA1341_ALSA_NAME "snd-uda1341"
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
/* include/version.h. Generated by alsa/ksync script. */
|
||||
#define CONFIG_SND_VERSION "1.0.16"
|
||||
/* include/version.h */
|
||||
#define CONFIG_SND_VERSION "1.0.17"
|
||||
#define CONFIG_SND_DATE ""
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
# sound/Config.in
|
||||
#
|
||||
|
||||
menu "Sound"
|
||||
depends on HAS_IOMEM
|
||||
|
||||
config SOUND
|
||||
menuconfig SOUND
|
||||
tristate "Sound card support"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
If you have a sound card in your computer, i.e. if it can say more
|
||||
than an occasional beep, say Y. Be sure to have all the information
|
||||
|
@ -28,22 +26,22 @@ config SOUND
|
|||
and read <file:Documentation/sound/oss/README.modules>; the module
|
||||
will be called soundcore.
|
||||
|
||||
if SOUND
|
||||
|
||||
source "sound/oss/dmasound/Kconfig"
|
||||
|
||||
if !M68K
|
||||
|
||||
menu "Advanced Linux Sound Architecture"
|
||||
depends on SOUND!=n
|
||||
|
||||
config SND
|
||||
menuconfig SND
|
||||
tristate "Advanced Linux Sound Architecture"
|
||||
depends on SOUND
|
||||
help
|
||||
Say 'Y' or 'M' to enable ALSA (Advanced Linux Sound Architecture),
|
||||
the new base sound system.
|
||||
|
||||
For more information, see <http://www.alsa-project.org/>
|
||||
|
||||
if SND
|
||||
|
||||
source "sound/core/Kconfig"
|
||||
|
||||
source "sound/drivers/Kconfig"
|
||||
|
@ -58,9 +56,7 @@ source "sound/aoa/Kconfig"
|
|||
|
||||
source "sound/arm/Kconfig"
|
||||
|
||||
if SPI
|
||||
source "sound/spi/Kconfig"
|
||||
endif
|
||||
|
||||
source "sound/mips/Kconfig"
|
||||
|
||||
|
@ -80,22 +76,20 @@ source "sound/parisc/Kconfig"
|
|||
|
||||
source "sound/soc/Kconfig"
|
||||
|
||||
endmenu
|
||||
endif # SND
|
||||
|
||||
menu "Open Sound System"
|
||||
depends on SOUND!=n
|
||||
|
||||
config SOUND_PRIME
|
||||
menuconfig SOUND_PRIME
|
||||
tristate "Open Sound System (DEPRECATED)"
|
||||
depends on SOUND
|
||||
help
|
||||
Say 'Y' or 'M' to enable Open Sound System drivers.
|
||||
|
||||
if SOUND_PRIME
|
||||
|
||||
source "sound/oss/Kconfig"
|
||||
|
||||
endmenu
|
||||
endif # SOUND_PRIME
|
||||
|
||||
endif
|
||||
endif # !M68K
|
||||
|
||||
config AC97_BUS
|
||||
tristate
|
||||
|
@ -105,4 +99,4 @@ config AC97_BUS
|
|||
sound although they're sharing the AC97 bus. Concerned drivers
|
||||
should "select" this.
|
||||
|
||||
endmenu
|
||||
endif # SOUND
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
menu "Apple Onboard Audio driver"
|
||||
depends on SND!=n && PPC_PMAC
|
||||
|
||||
config SND_AOA
|
||||
menuconfig SND_AOA
|
||||
tristate "Apple Onboard Audio driver"
|
||||
depends on SND
|
||||
depends on PPC_PMAC
|
||||
select SND_PCM
|
||||
---help---
|
||||
This option enables the new driver for the various
|
||||
Apple Onboard Audio components.
|
||||
|
||||
if SND_AOA
|
||||
|
||||
source "sound/aoa/fabrics/Kconfig"
|
||||
|
||||
source "sound/aoa/codecs/Kconfig"
|
||||
|
||||
source "sound/aoa/soundbus/Kconfig"
|
||||
|
||||
endmenu
|
||||
endif # SND_AOA
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
config SND_AOA_ONYX
|
||||
tristate "support Onyx chip"
|
||||
depends on SND_AOA
|
||||
select I2C
|
||||
select I2C_POWERMAC
|
||||
---help---
|
||||
|
@ -10,7 +9,6 @@ config SND_AOA_ONYX
|
|||
|
||||
#config SND_AOA_TOPAZ
|
||||
# tristate "support Topaz chips"
|
||||
# depends on SND_AOA
|
||||
# ---help---
|
||||
# This option enables support for the Topaz (CS84xx)
|
||||
# codec chips found in the latest Apple machines,
|
||||
|
@ -19,7 +17,6 @@ config SND_AOA_ONYX
|
|||
|
||||
config SND_AOA_TAS
|
||||
tristate "support TAS chips"
|
||||
depends on SND_AOA
|
||||
select I2C
|
||||
select I2C_POWERMAC
|
||||
---help---
|
||||
|
@ -29,7 +26,6 @@ config SND_AOA_TAS
|
|||
|
||||
config SND_AOA_TOONIE
|
||||
tristate "support Toonie chip"
|
||||
depends on SND_AOA
|
||||
---help---
|
||||
This option enables support for the toonie codec
|
||||
found in the Mac Mini. If you have a Mac Mini and
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
config SND_AOA_FABRIC_LAYOUT
|
||||
tristate "layout-id fabric"
|
||||
depends on SND_AOA
|
||||
select SND_AOA_SOUNDBUS
|
||||
select SND_AOA_SOUNDBUS_I2S
|
||||
---help---
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
config SND_AOA_SOUNDBUS
|
||||
tristate "Apple Soundbus support"
|
||||
depends on SOUND
|
||||
select SND_PCM
|
||||
---help---
|
||||
This option enables the generic driver for the soundbus
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
# ALSA ARM drivers
|
||||
|
||||
menu "ALSA ARM devices"
|
||||
depends on SND!=n && ARM
|
||||
menuconfig SND_ARM
|
||||
bool "ARM sound devices"
|
||||
depends on ARM
|
||||
default y
|
||||
help
|
||||
Support for sound devices specific to ARM architectures.
|
||||
Drivers that are implemented on ASoC can be found in
|
||||
"ALSA for SoC audio support" section.
|
||||
|
||||
if SND_ARM
|
||||
|
||||
config SND_SA11XX_UDA1341
|
||||
tristate "SA11xx UDA1341TS driver (iPaq H3600)"
|
||||
depends on ARCH_SA1100 && SND && L3
|
||||
depends on ARCH_SA1100 && L3
|
||||
select SND_PCM
|
||||
help
|
||||
Say Y here if you have a Compaq iPaq H3x00 handheld computer
|
||||
|
@ -16,7 +24,7 @@ config SND_SA11XX_UDA1341
|
|||
|
||||
config SND_ARMAACI
|
||||
tristate "ARM PrimeCell PL041 AC Link support"
|
||||
depends on SND && ARM_AMBA
|
||||
depends on ARM_AMBA
|
||||
select SND_PCM
|
||||
select SND_AC97_CODEC
|
||||
|
||||
|
@ -26,11 +34,12 @@ config SND_PXA2XX_PCM
|
|||
|
||||
config SND_PXA2XX_AC97
|
||||
tristate "AC97 driver for the Intel PXA2xx chip"
|
||||
depends on ARCH_PXA && SND
|
||||
depends on ARCH_PXA
|
||||
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
|
||||
endif # SND_ARM
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
* merged HAL layer (patches from Brian)
|
||||
*/
|
||||
|
||||
/* $Id: sa11xx-uda1341.c,v 1.27 2005/12/07 09:13:42 cladisch Exp $ */
|
||||
|
||||
/***************************************************************************************************
|
||||
*
|
||||
* To understand what Alsa Drivers should be doing look at "Writing an Alsa Driver" by Takashi Iwai
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
# ALSA soundcard-configuration
|
||||
config SND_TIMER
|
||||
tristate
|
||||
depends on SND
|
||||
|
||||
config SND_PCM
|
||||
tristate
|
||||
select SND_TIMER
|
||||
depends on SND
|
||||
|
||||
config SND_HWDEP
|
||||
tristate
|
||||
depends on SND
|
||||
|
||||
config SND_RAWMIDI
|
||||
tristate
|
||||
depends on SND
|
||||
|
||||
config SND_SEQUENCER
|
||||
tristate "Sequencer support"
|
||||
depends on SND
|
||||
select SND_TIMER
|
||||
help
|
||||
Say Y or M to enable MIDI sequencer and router support. This
|
||||
|
@ -44,11 +39,9 @@ config SND_SEQ_DUMMY
|
|||
|
||||
config SND_OSSEMUL
|
||||
bool
|
||||
depends on SND
|
||||
|
||||
config SND_MIXER_OSS
|
||||
tristate "OSS Mixer API"
|
||||
depends on SND
|
||||
select SND_OSSEMUL
|
||||
help
|
||||
To enable OSS mixer API emulation (/dev/mixer*), say Y here
|
||||
|
@ -61,7 +54,6 @@ config SND_MIXER_OSS
|
|||
|
||||
config SND_PCM_OSS
|
||||
tristate "OSS PCM (digital audio) API"
|
||||
depends on SND
|
||||
select SND_OSSEMUL
|
||||
select SND_PCM
|
||||
help
|
||||
|
@ -84,7 +76,7 @@ config SND_PCM_OSS_PLUGINS
|
|||
|
||||
config SND_SEQUENCER_OSS
|
||||
bool "OSS Sequencer API"
|
||||
depends on SND && SND_SEQUENCER
|
||||
depends on SND_SEQUENCER
|
||||
select SND_OSSEMUL
|
||||
help
|
||||
Say Y here to enable OSS sequencer emulation (both
|
||||
|
@ -98,7 +90,7 @@ config SND_SEQUENCER_OSS
|
|||
|
||||
config SND_RTCTIMER
|
||||
tristate "RTC Timer support"
|
||||
depends on SND && RTC
|
||||
depends on RTC
|
||||
select SND_TIMER
|
||||
help
|
||||
Say Y here to enable RTC timer support for ALSA. ALSA uses
|
||||
|
@ -123,7 +115,6 @@ config SND_SEQ_RTCTIMER_DEFAULT
|
|||
|
||||
config SND_DYNAMIC_MINORS
|
||||
bool "Dynamic device file minor numbers"
|
||||
depends on SND
|
||||
help
|
||||
If you say Y here, the minor numbers of ALSA device files in
|
||||
/dev/snd/ are allocated dynamically. This allows you to have
|
||||
|
@ -134,7 +125,6 @@ config SND_DYNAMIC_MINORS
|
|||
|
||||
config SND_SUPPORT_OLD_API
|
||||
bool "Support old ALSA API"
|
||||
depends on SND
|
||||
default y
|
||||
help
|
||||
Say Y here to support the obsolete ALSA PCM API (ver.0.9.0 rc3
|
||||
|
@ -142,7 +132,7 @@ config SND_SUPPORT_OLD_API
|
|||
|
||||
config SND_VERBOSE_PROCFS
|
||||
bool "Verbose procfs contents"
|
||||
depends on SND && PROC_FS
|
||||
depends on PROC_FS
|
||||
default y
|
||||
help
|
||||
Say Y here to include code for verbose procfs contents (provides
|
||||
|
@ -151,7 +141,6 @@ config SND_VERBOSE_PROCFS
|
|||
|
||||
config SND_VERBOSE_PRINTK
|
||||
bool "Verbose printk"
|
||||
depends on SND
|
||||
help
|
||||
Say Y here to enable verbose log messages. These messages
|
||||
will help to identify source file and position containing
|
||||
|
@ -161,16 +150,17 @@ config SND_VERBOSE_PRINTK
|
|||
|
||||
config SND_DEBUG
|
||||
bool "Debug"
|
||||
depends on SND
|
||||
help
|
||||
Say Y here to enable ALSA debug code.
|
||||
|
||||
config SND_DEBUG_DETECT
|
||||
bool "Debug detection"
|
||||
config SND_DEBUG_VERBOSE
|
||||
bool "More verbose debug"
|
||||
depends on SND_DEBUG
|
||||
help
|
||||
Say Y here to enable extra-verbose log messages printed when
|
||||
detecting devices.
|
||||
Say Y here to enable extra-verbose debugging messages.
|
||||
|
||||
Let me repeat: it enables EXTRA-VERBOSE DEBUGGING messages.
|
||||
So, say Y only if you are ready to be annoyed.
|
||||
|
||||
config SND_PCM_XRUN_DEBUG
|
||||
bool "Enable PCM ring buffer overrun/underrun debugging"
|
||||
|
@ -184,4 +174,3 @@ config SND_PCM_XRUN_DEBUG
|
|||
|
||||
config SND_VMASTER
|
||||
bool
|
||||
depends on SND
|
||||
|
|
|
@ -684,7 +684,8 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
|
|||
return result;
|
||||
}
|
||||
|
||||
int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control)
|
||||
static int snd_ctl_elem_read(struct snd_card *card,
|
||||
struct snd_ctl_elem_value *control)
|
||||
{
|
||||
struct snd_kcontrol *kctl;
|
||||
struct snd_kcontrol_volatile *vd;
|
||||
|
@ -734,8 +735,8 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
|
|||
return result;
|
||||
}
|
||||
|
||||
int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
||||
struct snd_ctl_elem_value *control)
|
||||
static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
||||
struct snd_ctl_elem_value *control)
|
||||
{
|
||||
struct snd_kcontrol *kctl;
|
||||
struct snd_kcontrol_volatile *vd;
|
||||
|
|
|
@ -46,17 +46,24 @@ static char *slots[SNDRV_CARDS];
|
|||
module_param_array(slots, charp, NULL, 0444);
|
||||
MODULE_PARM_DESC(slots, "Module names assigned to the slots.");
|
||||
|
||||
/* return non-zero if the given index is already reserved for another
|
||||
/* return non-zero if the given index is reserved for the given
|
||||
* module via slots option
|
||||
*/
|
||||
static int module_slot_mismatch(struct module *module, int idx)
|
||||
static int module_slot_match(struct module *module, int idx)
|
||||
{
|
||||
int match = 1;
|
||||
#ifdef MODULE
|
||||
char *s1, *s2;
|
||||
const char *s1, *s2;
|
||||
|
||||
if (!module || !module->name || !slots[idx])
|
||||
return 0;
|
||||
s1 = slots[idx];
|
||||
s2 = module->name;
|
||||
|
||||
s1 = module->name;
|
||||
s2 = slots[idx];
|
||||
if (*s2 == '!') {
|
||||
match = 0; /* negative match */
|
||||
s2++;
|
||||
}
|
||||
/* compare module name strings
|
||||
* hyphens are handled as equivalent with underscore
|
||||
*/
|
||||
|
@ -68,12 +75,12 @@ static int module_slot_mismatch(struct module *module, int idx)
|
|||
if (c2 == '-')
|
||||
c2 = '_';
|
||||
if (c1 != c2)
|
||||
return 1;
|
||||
return !match;
|
||||
if (!c1)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
#endif /* MODULE */
|
||||
return match;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
|
||||
|
@ -129,7 +136,7 @@ struct snd_card *snd_card_new(int idx, const char *xid,
|
|||
struct module *module, int extra_size)
|
||||
{
|
||||
struct snd_card *card;
|
||||
int err;
|
||||
int err, idx2;
|
||||
|
||||
if (extra_size < 0)
|
||||
extra_size = 0;
|
||||
|
@ -144,35 +151,41 @@ struct snd_card *snd_card_new(int idx, const char *xid,
|
|||
err = 0;
|
||||
mutex_lock(&snd_card_mutex);
|
||||
if (idx < 0) {
|
||||
int idx2;
|
||||
for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
|
||||
/* idx == -1 == 0xffff means: take any free slot */
|
||||
if (~snd_cards_lock & idx & 1<<idx2) {
|
||||
if (module_slot_mismatch(module, idx2))
|
||||
continue;
|
||||
idx = idx2;
|
||||
if (idx >= snd_ecards_limit)
|
||||
snd_ecards_limit = idx + 1;
|
||||
break;
|
||||
if (module_slot_match(module, idx2)) {
|
||||
idx = idx2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (idx < snd_ecards_limit) {
|
||||
if (snd_cards_lock & (1 << idx))
|
||||
err = -EBUSY; /* invalid */
|
||||
} else {
|
||||
if (idx < SNDRV_CARDS)
|
||||
snd_ecards_limit = idx + 1; /* increase the limit */
|
||||
else
|
||||
err = -ENODEV;
|
||||
}
|
||||
}
|
||||
if (idx < 0 || err < 0) {
|
||||
if (idx < 0) {
|
||||
for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
|
||||
/* idx == -1 == 0xffff means: take any free slot */
|
||||
if (~snd_cards_lock & idx & 1<<idx2) {
|
||||
if (!slots[idx2] || !*slots[idx2]) {
|
||||
idx = idx2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (idx < 0)
|
||||
err = -ENODEV;
|
||||
else if (idx < snd_ecards_limit) {
|
||||
if (snd_cards_lock & (1 << idx))
|
||||
err = -EBUSY; /* invalid */
|
||||
} else if (idx >= SNDRV_CARDS)
|
||||
err = -ENODEV;
|
||||
if (err < 0) {
|
||||
mutex_unlock(&snd_card_mutex);
|
||||
snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",
|
||||
idx, snd_ecards_limit - 1, err);
|
||||
goto __error;
|
||||
}
|
||||
snd_cards_lock |= 1 << idx; /* lock it */
|
||||
if (idx >= snd_ecards_limit)
|
||||
snd_ecards_limit = idx + 1; /* increase the limit */
|
||||
mutex_unlock(&snd_card_mutex);
|
||||
card->number = idx;
|
||||
card->module = module;
|
||||
|
|
|
@ -79,68 +79,6 @@ struct snd_mem_list {
|
|||
#define snd_assert(expr, args...) /**/
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Hacks
|
||||
*/
|
||||
|
||||
#if defined(__i386__)
|
||||
/*
|
||||
* A hack to allocate large buffers via dma_alloc_coherent()
|
||||
*
|
||||
* since dma_alloc_coherent always tries GFP_DMA when the requested
|
||||
* pci memory region is below 32bit, it happens quite often that even
|
||||
* 2 order of pages cannot be allocated.
|
||||
*
|
||||
* so in the following, we allocate at first without dma_mask, so that
|
||||
* allocation will be done without GFP_DMA. if the area doesn't match
|
||||
* with the requested region, then realloate with the original dma_mask
|
||||
* again.
|
||||
*
|
||||
* Really, we want to move this type of thing into dma_alloc_coherent()
|
||||
* so dma_mask doesn't have to be messed with.
|
||||
*/
|
||||
|
||||
static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle,
|
||||
gfp_t flags)
|
||||
{
|
||||
void *ret;
|
||||
u64 dma_mask, coherent_dma_mask;
|
||||
|
||||
if (dev == NULL || !dev->dma_mask)
|
||||
return dma_alloc_coherent(dev, size, dma_handle, flags);
|
||||
dma_mask = *dev->dma_mask;
|
||||
coherent_dma_mask = dev->coherent_dma_mask;
|
||||
*dev->dma_mask = 0xffffffff; /* do without masking */
|
||||
dev->coherent_dma_mask = 0xffffffff; /* do without masking */
|
||||
ret = dma_alloc_coherent(dev, size, dma_handle, flags);
|
||||
*dev->dma_mask = dma_mask; /* restore */
|
||||
dev->coherent_dma_mask = coherent_dma_mask; /* restore */
|
||||
if (ret) {
|
||||
/* obtained address is out of range? */
|
||||
if (((unsigned long)*dma_handle + size - 1) & ~dma_mask) {
|
||||
/* reallocate with the proper mask */
|
||||
dma_free_coherent(dev, size, ret, *dma_handle);
|
||||
ret = dma_alloc_coherent(dev, size, dma_handle, flags);
|
||||
}
|
||||
} else {
|
||||
/* wish to success now with the proper mask... */
|
||||
if (dma_mask != 0xffffffffUL) {
|
||||
/* allocation with GFP_ATOMIC to avoid the long stall */
|
||||
flags &= ~GFP_KERNEL;
|
||||
flags |= GFP_ATOMIC;
|
||||
ret = dma_alloc_coherent(dev, size, dma_handle, flags);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* redefine dma_alloc_coherent for some architectures */
|
||||
#undef dma_alloc_coherent
|
||||
#define dma_alloc_coherent snd_dma_hack_alloc_coherent
|
||||
|
||||
#endif /* arch */
|
||||
|
||||
/*
|
||||
*
|
||||
* Generic memory allocators
|
||||
|
|
|
@ -148,7 +148,7 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
|
|||
return NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&clients_lock, flags);
|
||||
#ifdef CONFIG_KMOD
|
||||
#ifdef CONFIG_MODULES
|
||||
if (!in_interrupt()) {
|
||||
static char client_requested[SNDRV_SEQ_GLOBAL_CLIENTS];
|
||||
static char card_requested[SNDRV_CARDS];
|
||||
|
|
|
@ -124,7 +124,7 @@ static void snd_seq_device_info(struct snd_info_entry *entry,
|
|||
* load all registered drivers (called from seq_clientmgr.c)
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_KMOD
|
||||
#ifdef CONFIG_MODULES
|
||||
/* avoid auto-loading during module_init() */
|
||||
static int snd_seq_in_init;
|
||||
void snd_seq_autoload_lock(void)
|
||||
|
@ -140,7 +140,7 @@ void snd_seq_autoload_unlock(void)
|
|||
|
||||
void snd_seq_device_load_drivers(void)
|
||||
{
|
||||
#ifdef CONFIG_KMOD
|
||||
#ifdef CONFIG_MODULES
|
||||
struct ops_list *ops;
|
||||
|
||||
/* Calling request_module during module_init()
|
||||
|
@ -566,7 +566,5 @@ EXPORT_SYMBOL(snd_seq_device_load_drivers);
|
|||
EXPORT_SYMBOL(snd_seq_device_new);
|
||||
EXPORT_SYMBOL(snd_seq_device_register_driver);
|
||||
EXPORT_SYMBOL(snd_seq_device_unregister_driver);
|
||||
#ifdef CONFIG_KMOD
|
||||
EXPORT_SYMBOL(snd_seq_autoload_lock);
|
||||
EXPORT_SYMBOL(snd_seq_autoload_unlock);
|
||||
#endif
|
||||
|
|
|
@ -60,14 +60,14 @@ EXPORT_SYMBOL(snd_ecards_limit);
|
|||
static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
|
||||
static DEFINE_MUTEX(sound_mutex);
|
||||
|
||||
#ifdef CONFIG_KMOD
|
||||
#ifdef CONFIG_MODULES
|
||||
|
||||
/**
|
||||
* snd_request_card - try to load the card module
|
||||
* @card: the card number
|
||||
*
|
||||
* Tries to load the module "snd-card-X" for the given card number
|
||||
* via KMOD. Returns immediately if already loaded.
|
||||
* via request_module. Returns immediately if already loaded.
|
||||
*/
|
||||
void snd_request_card(int card)
|
||||
{
|
||||
|
@ -92,7 +92,7 @@ static void snd_request_other(int minor)
|
|||
request_module(str);
|
||||
}
|
||||
|
||||
#endif /* request_module support */
|
||||
#endif /* modular kernel */
|
||||
|
||||
/**
|
||||
* snd_lookup_minor_data - get user data of a registered device
|
||||
|
@ -132,7 +132,7 @@ static int snd_open(struct inode *inode, struct file *file)
|
|||
return -ENODEV;
|
||||
mptr = snd_minors[minor];
|
||||
if (mptr == NULL) {
|
||||
#ifdef CONFIG_KMOD
|
||||
#ifdef CONFIG_MODULES
|
||||
int dev = SNDRV_MINOR_DEVICE(minor);
|
||||
if (dev == SNDRV_MINOR_CONTROL) {
|
||||
/* /dev/aloadC? */
|
||||
|
|
|
@ -146,7 +146,7 @@ static struct snd_timer *snd_timer_find(struct snd_timer_id *tid)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KMOD
|
||||
#ifdef CONFIG_MODULES
|
||||
|
||||
static void snd_timer_request(struct snd_timer_id *tid)
|
||||
{
|
||||
|
@ -259,8 +259,8 @@ int snd_timer_open(struct snd_timer_instance **ti,
|
|||
/* open a master instance */
|
||||
mutex_lock(®ister_mutex);
|
||||
timer = snd_timer_find(tid);
|
||||
#ifdef CONFIG_KMOD
|
||||
if (timer == NULL) {
|
||||
#ifdef CONFIG_MODULES
|
||||
if (!timer) {
|
||||
mutex_unlock(®ister_mutex);
|
||||
snd_timer_request(tid);
|
||||
mutex_lock(®ister_mutex);
|
||||
|
|
|
@ -1,15 +1,41 @@
|
|||
# ALSA generic drivers
|
||||
config SND_MPU401_UART
|
||||
tristate
|
||||
select SND_RAWMIDI
|
||||
|
||||
menu "Generic devices"
|
||||
depends on SND!=n
|
||||
config SND_OPL3_LIB
|
||||
tristate
|
||||
select SND_TIMER
|
||||
select SND_HWDEP
|
||||
|
||||
config SND_OPL4_LIB
|
||||
tristate
|
||||
select SND_TIMER
|
||||
select SND_HWDEP
|
||||
|
||||
config SND_VX_LIB
|
||||
tristate
|
||||
select SND_HWDEP
|
||||
select SND_PCM
|
||||
|
||||
config SND_AC97_CODEC
|
||||
tristate
|
||||
select SND_PCM
|
||||
select AC97_BUS
|
||||
select SND_VMASTER
|
||||
|
||||
menuconfig SND_DRIVERS
|
||||
bool "Generic sound devices"
|
||||
default y
|
||||
help
|
||||
Support for generic sound devices.
|
||||
|
||||
if SND_DRIVERS
|
||||
|
||||
config SND_PCSP
|
||||
tristate "PC-Speaker support (READ HELP!)"
|
||||
depends on PCSPKR_PLATFORM && X86_PC && HIGH_RES_TIMERS
|
||||
depends on INPUT
|
||||
depends on EXPERIMENTAL
|
||||
depends on SND
|
||||
select SND_PCM
|
||||
help
|
||||
If you don't have a sound card in your computer, you can include a
|
||||
|
@ -35,33 +61,8 @@ config SND_PCSP
|
|||
Say M if you don't.
|
||||
Say Y only if you really know what you do.
|
||||
|
||||
config SND_MPU401_UART
|
||||
tristate
|
||||
select SND_RAWMIDI
|
||||
|
||||
config SND_OPL3_LIB
|
||||
tristate
|
||||
select SND_TIMER
|
||||
select SND_HWDEP
|
||||
|
||||
config SND_OPL4_LIB
|
||||
tristate
|
||||
select SND_TIMER
|
||||
select SND_HWDEP
|
||||
|
||||
config SND_VX_LIB
|
||||
tristate
|
||||
select SND_HWDEP
|
||||
select SND_PCM
|
||||
|
||||
config SND_AC97_CODEC
|
||||
tristate
|
||||
select SND_PCM
|
||||
select AC97_BUS
|
||||
|
||||
config SND_DUMMY
|
||||
tristate "Dummy (/dev/null) soundcard"
|
||||
depends on SND
|
||||
select SND_PCM
|
||||
help
|
||||
Say Y here to include the dummy driver. This driver does
|
||||
|
@ -90,7 +91,6 @@ config SND_VIRMIDI
|
|||
|
||||
config SND_MTPAV
|
||||
tristate "MOTU MidiTimePiece AV multiport MIDI"
|
||||
depends on SND
|
||||
select SND_RAWMIDI
|
||||
help
|
||||
To use a MOTU MidiTimePiece AV multiport MIDI adapter
|
||||
|
@ -102,7 +102,7 @@ config SND_MTPAV
|
|||
|
||||
config SND_MTS64
|
||||
tristate "ESI Miditerminal 4140 driver"
|
||||
depends on SND && PARPORT
|
||||
depends on PARPORT
|
||||
select SND_RAWMIDI
|
||||
help
|
||||
The ESI Miditerminal 4140 is a 4 In 4 Out MIDI Interface with
|
||||
|
@ -115,7 +115,6 @@ config SND_MTS64
|
|||
|
||||
config SND_SERIAL_U16550
|
||||
tristate "UART16550 serial MIDI driver"
|
||||
depends on SND
|
||||
select SND_RAWMIDI
|
||||
help
|
||||
To include support for MIDI serial port interfaces, say Y here
|
||||
|
@ -131,7 +130,6 @@ config SND_SERIAL_U16550
|
|||
|
||||
config SND_MPU401
|
||||
tristate "Generic MPU-401 UART driver"
|
||||
depends on SND
|
||||
select SND_MPU401_UART
|
||||
help
|
||||
Say Y here to include support for MIDI ports compatible with
|
||||
|
@ -142,7 +140,7 @@ config SND_MPU401
|
|||
|
||||
config SND_PORTMAN2X4
|
||||
tristate "Portman 2x4 driver"
|
||||
depends on SND && PARPORT
|
||||
depends on PARPORT
|
||||
select SND_RAWMIDI
|
||||
help
|
||||
Say Y here to include support for Midiman Portman 2x4 parallel
|
||||
|
@ -153,7 +151,7 @@ config SND_PORTMAN2X4
|
|||
|
||||
config SND_ML403_AC97CR
|
||||
tristate "Xilinx ML403 AC97 Controller Reference"
|
||||
depends on SND && XILINX_VIRTEX
|
||||
depends on XILINX_VIRTEX
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
Say Y here to include support for the
|
||||
|
@ -163,4 +161,25 @@ config SND_ML403_AC97CR
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-ml403_ac97cr.
|
||||
|
||||
endmenu
|
||||
config SND_AC97_POWER_SAVE
|
||||
bool "AC97 Power-Saving Mode"
|
||||
depends on SND_AC97_CODEC && EXPERIMENTAL
|
||||
default n
|
||||
help
|
||||
Say Y here to enable the aggressive power-saving support of
|
||||
AC97 codecs. In this mode, the power-mode is dynamically
|
||||
controlled at each open/close.
|
||||
|
||||
The mode is activated by passing power_save=1 option to
|
||||
snd-ac97-codec driver. You can toggle it dynamically over
|
||||
sysfs, too.
|
||||
|
||||
config SND_AC97_POWER_SAVE_DEFAULT
|
||||
int "Default time-out for AC97 power-save mode"
|
||||
depends on SND_AC97_POWER_SAVE
|
||||
default 0
|
||||
help
|
||||
The default time-out value in seconds for AC97 automatic
|
||||
power-save mode. 0 means to disable the power-save mode.
|
||||
|
||||
endif # SND_DRIVERS
|
||||
|
|
|
@ -183,7 +183,7 @@ static int vx_hwdep_dsp_load(struct snd_hwdep *hw,
|
|||
kfree(fw);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (copy_from_user(fw->data, dsp->image, dsp->length)) {
|
||||
if (copy_from_user((void *)fw->data, dsp->image, dsp->length)) {
|
||||
free_fw(fw);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/pcm.h>
|
||||
|
@ -264,10 +265,7 @@ int snd_cs8427_create(struct snd_i2c_bus *bus,
|
|||
goto __fail;
|
||||
}
|
||||
/* write default channel status bytes */
|
||||
buf[0] = ((unsigned char)(SNDRV_PCM_DEFAULT_CON_SPDIF >> 0));
|
||||
buf[1] = ((unsigned char)(SNDRV_PCM_DEFAULT_CON_SPDIF >> 8));
|
||||
buf[2] = ((unsigned char)(SNDRV_PCM_DEFAULT_CON_SPDIF >> 16));
|
||||
buf[3] = ((unsigned char)(SNDRV_PCM_DEFAULT_CON_SPDIF >> 24));
|
||||
put_unaligned_le32(SNDRV_PCM_DEFAULT_CON_SPDIF, buf);
|
||||
memset(buf + 4, 0, 24 - 4);
|
||||
if (snd_cs8427_send_corudata(device, 0, buf, 24) < 0)
|
||||
goto __fail;
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
* 2002-05-12 Tomas Kasparek another code cleanup
|
||||
*/
|
||||
|
||||
/* $Id: uda1341.c,v 1.18 2005/11/17 14:17:21 tiwai Exp $ */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
|
|
|
@ -21,12 +21,17 @@ config SND_SB16_DSP
|
|||
select SND_PCM
|
||||
select SND_SB_COMMON
|
||||
|
||||
menu "ISA devices"
|
||||
depends on SND!=n && ISA && ISA_DMA_API
|
||||
menuconfig SND_ISA
|
||||
bool "ISA sound devices"
|
||||
depends on ISA && ISA_DMA_API
|
||||
default y
|
||||
help
|
||||
Support for sound devices connected via the ISA bus.
|
||||
|
||||
if SND_ISA
|
||||
|
||||
config SND_ADLIB
|
||||
tristate "AdLib FM card"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
help
|
||||
Say Y here to include support for AdLib FM cards.
|
||||
|
@ -36,7 +41,7 @@ config SND_ADLIB
|
|||
|
||||
config SND_AD1816A
|
||||
tristate "Analog Devices SoundPort AD1816A"
|
||||
depends on SND && PNP && ISA
|
||||
depends on PNP
|
||||
select ISAPNP
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
|
@ -50,7 +55,6 @@ config SND_AD1816A
|
|||
|
||||
config SND_AD1848
|
||||
tristate "Generic AD1848/CS4248 driver"
|
||||
depends on SND
|
||||
select SND_AD1848_LIB
|
||||
help
|
||||
Say Y here to include support for AD1848 (Analog Devices) or
|
||||
|
@ -64,7 +68,7 @@ config SND_AD1848
|
|||
|
||||
config SND_ALS100
|
||||
tristate "Avance Logic ALS100/ALS120"
|
||||
depends on SND && PNP && ISA
|
||||
depends on PNP
|
||||
select ISAPNP
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
|
@ -78,7 +82,7 @@ config SND_ALS100
|
|||
|
||||
config SND_AZT2320
|
||||
tristate "Aztech Systems AZT2320"
|
||||
depends on SND && PNP && ISA
|
||||
depends on PNP
|
||||
select ISAPNP
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
|
@ -92,7 +96,6 @@ config SND_AZT2320
|
|||
|
||||
config SND_CMI8330
|
||||
tristate "C-Media CMI8330"
|
||||
depends on SND
|
||||
select SND_AD1848_LIB
|
||||
select SND_SB16_DSP
|
||||
help
|
||||
|
@ -104,7 +107,6 @@ config SND_CMI8330
|
|||
|
||||
config SND_CS4231
|
||||
tristate "Generic Cirrus Logic CS4231 driver"
|
||||
depends on SND
|
||||
select SND_MPU401_UART
|
||||
select SND_CS4231_LIB
|
||||
help
|
||||
|
@ -116,7 +118,6 @@ config SND_CS4231
|
|||
|
||||
config SND_CS4232
|
||||
tristate "Generic Cirrus Logic CS4232 driver"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_CS4231_LIB
|
||||
|
@ -129,7 +130,6 @@ config SND_CS4232
|
|||
|
||||
config SND_CS4236
|
||||
tristate "Generic Cirrus Logic CS4236+ driver"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_CS4231_LIB
|
||||
|
@ -142,7 +142,7 @@ config SND_CS4236
|
|||
|
||||
config SND_DT019X
|
||||
tristate "Diamond Technologies DT-019X, Avance Logic ALS-007"
|
||||
depends on SND && PNP && ISA
|
||||
depends on PNP
|
||||
select ISAPNP
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
|
@ -156,7 +156,7 @@ config SND_DT019X
|
|||
|
||||
config SND_ES968
|
||||
tristate "Generic ESS ES968 driver"
|
||||
depends on SND && PNP && ISA
|
||||
depends on PNP
|
||||
select ISAPNP
|
||||
select SND_MPU401_UART
|
||||
select SND_SB8_DSP
|
||||
|
@ -168,7 +168,6 @@ config SND_ES968
|
|||
|
||||
config SND_ES1688
|
||||
tristate "Generic ESS ES688/ES1688 driver"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_PCM
|
||||
|
@ -181,7 +180,6 @@ config SND_ES1688
|
|||
|
||||
config SND_ES18XX
|
||||
tristate "Generic ESS ES18xx driver"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_PCM
|
||||
|
@ -193,7 +191,7 @@ config SND_ES18XX
|
|||
|
||||
config SND_SC6000
|
||||
tristate "Gallant SC-6000, Audio Excel DSP 16"
|
||||
depends on SND && HAS_IOPORT
|
||||
depends on HAS_IOPORT
|
||||
select SND_AD1848_LIB
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
|
@ -204,15 +202,10 @@ config SND_SC6000
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-sc6000.
|
||||
|
||||
config SND_GUS_SYNTH
|
||||
tristate
|
||||
|
||||
config SND_GUSCLASSIC
|
||||
tristate "Gravis UltraSound Classic"
|
||||
depends on SND
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
select SND_GUS_SYNTH
|
||||
help
|
||||
Say Y here to include support for Gravis UltraSound Classic
|
||||
soundcards.
|
||||
|
@ -222,11 +215,9 @@ config SND_GUSCLASSIC
|
|||
|
||||
config SND_GUSEXTREME
|
||||
tristate "Gravis UltraSound Extreme"
|
||||
depends on SND
|
||||
select SND_HWDEP
|
||||
select SND_MPU401_UART
|
||||
select SND_PCM
|
||||
select SND_GUS_SYNTH
|
||||
help
|
||||
Say Y here to include support for Gravis UltraSound Extreme
|
||||
soundcards.
|
||||
|
@ -236,10 +227,8 @@ config SND_GUSEXTREME
|
|||
|
||||
config SND_GUSMAX
|
||||
tristate "Gravis UltraSound MAX"
|
||||
depends on SND
|
||||
select SND_RAWMIDI
|
||||
select SND_CS4231_LIB
|
||||
select SND_GUS_SYNTH
|
||||
help
|
||||
Say Y here to include support for Gravis UltraSound MAX
|
||||
soundcards.
|
||||
|
@ -249,10 +238,9 @@ config SND_GUSMAX
|
|||
|
||||
config SND_INTERWAVE
|
||||
tristate "AMD InterWave, Gravis UltraSound PnP"
|
||||
depends on SND && PNP && ISA
|
||||
depends on PNP
|
||||
select SND_RAWMIDI
|
||||
select SND_CS4231_LIB
|
||||
select SND_GUS_SYNTH
|
||||
help
|
||||
Say Y here to include support for AMD InterWave based
|
||||
soundcards (Gravis UltraSound Plug & Play, STB SoundRage32,
|
||||
|
@ -263,10 +251,9 @@ config SND_INTERWAVE
|
|||
|
||||
config SND_INTERWAVE_STB
|
||||
tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)"
|
||||
depends on SND && PNP && ISA
|
||||
depends on PNP
|
||||
select SND_RAWMIDI
|
||||
select SND_CS4231_LIB
|
||||
select SND_GUS_SYNTH
|
||||
help
|
||||
Say Y here to include support for AMD InterWave based
|
||||
soundcards with a TEA6330T bass and treble regulator
|
||||
|
@ -277,7 +264,6 @@ config SND_INTERWAVE_STB
|
|||
|
||||
config SND_OPL3SA2
|
||||
tristate "Yamaha OPL3-SA2/SA3"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_CS4231_LIB
|
||||
|
@ -290,7 +276,6 @@ config SND_OPL3SA2
|
|||
|
||||
config SND_OPTI92X_AD1848
|
||||
tristate "OPTi 82C92x - AD1848"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_OPL4_LIB
|
||||
select SND_MPU401_UART
|
||||
|
@ -304,7 +289,6 @@ config SND_OPTI92X_AD1848
|
|||
|
||||
config SND_OPTI92X_CS4231
|
||||
tristate "OPTi 82C92x - CS4231"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_OPL4_LIB
|
||||
select SND_MPU401_UART
|
||||
|
@ -318,10 +302,9 @@ config SND_OPTI92X_CS4231
|
|||
|
||||
config SND_OPTI93X
|
||||
tristate "OPTi 82C93x"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_PCM
|
||||
select SND_CS4231_LIB
|
||||
help
|
||||
Say Y here to include support for soundcards based on Opti
|
||||
82C93x chips.
|
||||
|
@ -331,7 +314,6 @@ config SND_OPTI93X
|
|||
|
||||
config SND_MIRO
|
||||
tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver"
|
||||
depends on SND
|
||||
select SND_OPL4_LIB
|
||||
select SND_CS4231_LIB
|
||||
select SND_MPU401_UART
|
||||
|
@ -345,7 +327,6 @@ config SND_MIRO
|
|||
|
||||
config SND_SB8
|
||||
tristate "Sound Blaster 1.0/2.0/Pro (8-bit)"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_RAWMIDI
|
||||
select SND_SB8_DSP
|
||||
|
@ -358,7 +339,6 @@ config SND_SB8
|
|||
|
||||
config SND_SB16
|
||||
tristate "Sound Blaster 16 (PnP)"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_SB16_DSP
|
||||
|
@ -371,7 +351,6 @@ config SND_SB16
|
|||
|
||||
config SND_SBAWE
|
||||
tristate "Sound Blaster AWE (32,64) (PnP)"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_SB16_DSP
|
||||
|
@ -402,7 +381,6 @@ config SND_SB16_CSP_FIRMWARE_IN_KERNEL
|
|||
|
||||
config SND_SGALAXY
|
||||
tristate "Aztech Sound Galaxy"
|
||||
depends on SND
|
||||
select SND_AD1848_LIB
|
||||
help
|
||||
Say Y here to include support for Aztech Sound Galaxy
|
||||
|
@ -413,7 +391,6 @@ config SND_SGALAXY
|
|||
|
||||
config SND_SSCAPE
|
||||
tristate "Ensoniq SoundScape PnP driver"
|
||||
depends on SND
|
||||
select SND_HWDEP
|
||||
select SND_MPU401_UART
|
||||
select SND_CS4231_LIB
|
||||
|
@ -426,7 +403,6 @@ config SND_SSCAPE
|
|||
|
||||
config SND_WAVEFRONT
|
||||
tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
|
@ -448,4 +424,5 @@ config SND_WAVEFRONT_FIRMWARE_IN_KERNEL
|
|||
you need to install the firmware files from the
|
||||
alsa-firmware package.
|
||||
|
||||
endmenu
|
||||
endif # SND_ISA
|
||||
|
||||
|
|
|
@ -119,6 +119,42 @@ static unsigned char snd_cs4231_original_image[32] =
|
|||
0x00, /* 1f/31 - cbrl */
|
||||
};
|
||||
|
||||
static unsigned char snd_opti93x_original_image[32] =
|
||||
{
|
||||
0x00, /* 00/00 - l_mixout_outctrl */
|
||||
0x00, /* 01/01 - r_mixout_outctrl */
|
||||
0x88, /* 02/02 - l_cd_inctrl */
|
||||
0x88, /* 03/03 - r_cd_inctrl */
|
||||
0x88, /* 04/04 - l_a1/fm_inctrl */
|
||||
0x88, /* 05/05 - r_a1/fm_inctrl */
|
||||
0x80, /* 06/06 - l_dac_inctrl */
|
||||
0x80, /* 07/07 - r_dac_inctrl */
|
||||
0x00, /* 08/08 - ply_dataform_reg */
|
||||
0x00, /* 09/09 - if_conf */
|
||||
0x00, /* 0a/10 - pin_ctrl */
|
||||
0x00, /* 0b/11 - err_init_reg */
|
||||
0x0a, /* 0c/12 - id_reg */
|
||||
0x00, /* 0d/13 - reserved */
|
||||
0x00, /* 0e/14 - ply_upcount_reg */
|
||||
0x00, /* 0f/15 - ply_lowcount_reg */
|
||||
0x88, /* 10/16 - reserved/l_a1_inctrl */
|
||||
0x88, /* 11/17 - reserved/r_a1_inctrl */
|
||||
0x88, /* 12/18 - l_line_inctrl */
|
||||
0x88, /* 13/19 - r_line_inctrl */
|
||||
0x88, /* 14/20 - l_mic_inctrl */
|
||||
0x88, /* 15/21 - r_mic_inctrl */
|
||||
0x80, /* 16/22 - l_out_outctrl */
|
||||
0x80, /* 17/23 - r_out_outctrl */
|
||||
0x00, /* 18/24 - reserved */
|
||||
0x00, /* 19/25 - reserved */
|
||||
0x00, /* 1a/26 - reserved */
|
||||
0x00, /* 1b/27 - reserved */
|
||||
0x00, /* 1c/28 - cap_dataform_reg */
|
||||
0x00, /* 1d/29 - reserved */
|
||||
0x00, /* 1e/30 - cap_upcount_reg */
|
||||
0x00 /* 1f/31 - cap_lowcount_reg */
|
||||
};
|
||||
|
||||
/*
|
||||
* Basic I/O functions
|
||||
*/
|
||||
|
@ -895,7 +931,7 @@ static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void snd_cs4231_overrange(struct snd_cs4231 *chip)
|
||||
void snd_cs4231_overrange(struct snd_cs4231 *chip)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned char res;
|
||||
|
@ -1054,8 +1090,11 @@ static int snd_cs4231_probe(struct snd_cs4231 *chip)
|
|||
chip->image[CS4231_IFACE_CTRL] =
|
||||
(chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) |
|
||||
(chip->single_dma ? CS4231_SINGLE_DMA : 0);
|
||||
chip->image[CS4231_ALT_FEATURE_1] = 0x80;
|
||||
chip->image[CS4231_ALT_FEATURE_2] = chip->hardware == CS4231_HW_INTERWAVE ? 0xc2 : 0x01;
|
||||
if (chip->hardware != CS4231_HW_OPTI93X) {
|
||||
chip->image[CS4231_ALT_FEATURE_1] = 0x80;
|
||||
chip->image[CS4231_ALT_FEATURE_2] =
|
||||
chip->hardware == CS4231_HW_INTERWAVE ? 0xc2 : 0x01;
|
||||
}
|
||||
ptr = (unsigned char *) &chip->image;
|
||||
snd_cs4231_mce_down(chip);
|
||||
spin_lock_irqsave(&chip->reg_lock, flags);
|
||||
|
@ -1376,6 +1415,7 @@ const char *snd_cs4231_chip_id(struct snd_cs4231 *chip)
|
|||
case CS4231_HW_INTERWAVE: return "AMD InterWave";
|
||||
case CS4231_HW_OPL3SA2: return chip->card->shortname;
|
||||
case CS4231_HW_AD1845: return "AD1845";
|
||||
case CS4231_HW_OPTI93X: return "OPTi 93x";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
|
@ -1401,8 +1441,13 @@ static int snd_cs4231_new(struct snd_card *card,
|
|||
chip->rate_constraint = snd_cs4231_xrate;
|
||||
chip->set_playback_format = snd_cs4231_playback_format;
|
||||
chip->set_capture_format = snd_cs4231_capture_format;
|
||||
memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image));
|
||||
|
||||
if (chip->hardware == CS4231_HW_OPTI93X)
|
||||
memcpy(&chip->image, &snd_opti93x_original_image,
|
||||
sizeof(snd_opti93x_original_image));
|
||||
else
|
||||
memcpy(&chip->image, &snd_cs4231_original_image,
|
||||
sizeof(snd_cs4231_original_image));
|
||||
|
||||
*rchip = chip;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1790,6 +1835,48 @@ CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
|
|||
CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1)
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new snd_opti93x_controls[] = {
|
||||
CS4231_DOUBLE("Master Playback Switch", 0,
|
||||
OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
|
||||
CS4231_DOUBLE("Master Playback Volume", 0,
|
||||
OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
|
||||
CS4231_DOUBLE("PCM Playback Switch", 0,
|
||||
CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
|
||||
CS4231_DOUBLE("PCM Playback Volume", 0,
|
||||
CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1),
|
||||
CS4231_DOUBLE("FM Playback Switch", 0,
|
||||
CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
|
||||
CS4231_DOUBLE("FM Playback Volume", 0,
|
||||
CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1),
|
||||
CS4231_DOUBLE("Line Playback Switch", 0,
|
||||
CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
|
||||
CS4231_DOUBLE("Line Playback Volume", 0,
|
||||
CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1),
|
||||
CS4231_DOUBLE("Mic Playback Switch", 0,
|
||||
OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
|
||||
CS4231_DOUBLE("Mic Playback Volume", 0,
|
||||
OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1),
|
||||
CS4231_DOUBLE("Mic Boost", 0,
|
||||
CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
|
||||
CS4231_DOUBLE("CD Playback Switch", 0,
|
||||
CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
|
||||
CS4231_DOUBLE("CD Playback Volume", 0,
|
||||
CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1),
|
||||
CS4231_DOUBLE("Aux Playback Switch", 0,
|
||||
OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
|
||||
CS4231_DOUBLE("Aux Playback Volume", 0,
|
||||
OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1),
|
||||
CS4231_DOUBLE("Capture Volume", 0,
|
||||
CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "Capture Source",
|
||||
.info = snd_cs4231_info_mux,
|
||||
.get = snd_cs4231_get_mux,
|
||||
.put = snd_cs4231_put_mux,
|
||||
}
|
||||
};
|
||||
|
||||
int snd_cs4231_mixer(struct snd_cs4231 *chip)
|
||||
{
|
||||
struct snd_card *card;
|
||||
|
@ -1802,10 +1889,22 @@ int snd_cs4231_mixer(struct snd_cs4231 *chip)
|
|||
|
||||
strcpy(card->mixername, chip->pcm->name);
|
||||
|
||||
for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
|
||||
if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4231_controls[idx], chip))) < 0)
|
||||
return err;
|
||||
}
|
||||
if (chip->hardware == CS4231_HW_OPTI93X)
|
||||
for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
|
||||
err = snd_ctl_add(card,
|
||||
snd_ctl_new1(&snd_opti93x_controls[idx],
|
||||
chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
else
|
||||
for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
|
||||
err = snd_ctl_add(card,
|
||||
snd_ctl_new1(&snd_cs4231_controls[idx],
|
||||
chip));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1815,6 +1914,7 @@ EXPORT_SYMBOL(snd_cs4236_ext_out);
|
|||
EXPORT_SYMBOL(snd_cs4236_ext_in);
|
||||
EXPORT_SYMBOL(snd_cs4231_mce_up);
|
||||
EXPORT_SYMBOL(snd_cs4231_mce_down);
|
||||
EXPORT_SYMBOL(snd_cs4231_overrange);
|
||||
EXPORT_SYMBOL(snd_cs4231_interrupt);
|
||||
EXPORT_SYMBOL(snd_cs4231_chip_id);
|
||||
EXPORT_SYMBOL(snd_cs4231_create);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -34,5 +34,3 @@ ifeq ($(CONFIG_SND_SB16_CSP),y)
|
|||
obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o
|
||||
endif
|
||||
obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-emu8000-synth.o
|
||||
|
||||
obj-m := $(sort $(obj-m))
|
||||
|
|
|
@ -1939,7 +1939,7 @@ static int __devinit
|
|||
wavefront_download_firmware (snd_wavefront_t *dev, char *path)
|
||||
|
||||
{
|
||||
unsigned char *buf;
|
||||
const unsigned char *buf;
|
||||
int len, err;
|
||||
int section_cnt_downloaded = 0;
|
||||
const struct firmware *firmware;
|
||||
|
|
|
@ -1,15 +1,34 @@
|
|||
# ALSA MIPS drivers
|
||||
|
||||
menu "ALSA MIPS devices"
|
||||
depends on SND!=n && MIPS
|
||||
menuconfig SND_MIPS
|
||||
bool "MIPS sound devices"
|
||||
depends on MIPS
|
||||
default y
|
||||
help
|
||||
Support for sound devices of MIPS architectures.
|
||||
|
||||
if SND_MIPS
|
||||
|
||||
config SND_SGI_O2
|
||||
tristate "SGI O2 Audio"
|
||||
depends on SGI_IP32
|
||||
help
|
||||
Sound support for the SGI O2 Workstation.
|
||||
|
||||
config SND_SGI_HAL2
|
||||
tristate "SGI HAL2 Audio"
|
||||
depends on SGI_HAS_HAL2
|
||||
help
|
||||
Sound support for the SGI Indy and Indigo2 Workstation.
|
||||
|
||||
|
||||
config SND_AU1X00
|
||||
tristate "Au1x00 AC97 Port Driver"
|
||||
depends on (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && SND
|
||||
depends on SOC_AU1000 || SOC_AU1100 || SOC_AU1500
|
||||
select SND_PCM
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
ALSA Sound driver for the Au1x00's AC97 port.
|
||||
|
||||
endmenu
|
||||
endif # SND_MIPS
|
||||
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
#
|
||||
|
||||
snd-au1x00-objs := au1x00.o
|
||||
snd-sgi-o2-objs := sgio2audio.o ad1843.o
|
||||
snd-sgi-hal2-objs := hal2.o
|
||||
|
||||
# Toplevel Module Dependency
|
||||
obj-$(CONFIG_SND_AU1X00) += snd-au1x00.o
|
||||
obj-$(CONFIG_SND_SGI_O2) += snd-sgi-o2.o
|
||||
obj-$(CONFIG_SND_SGI_HAL2) += snd-sgi-hal2.o
|
||||
|
|
|
@ -0,0 +1,561 @@
|
|||
/*
|
||||
* AD1843 low level driver
|
||||
*
|
||||
* Copyright 2003 Vivien Chappelier <vivien.chappelier@linux-mips.org>
|
||||
* Copyright 2008 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
|
||||
*
|
||||
* inspired from vwsnd.c (SGI VW audio driver)
|
||||
* Copyright 1999 Silicon Graphics, Inc. All rights reserved.
|
||||
*
|
||||
* 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 <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/ad1843.h>
|
||||
|
||||
/*
|
||||
* AD1843 bitfield definitions. All are named as in the AD1843 data
|
||||
* sheet, with ad1843_ prepended and individual bit numbers removed.
|
||||
*
|
||||
* E.g., bits LSS0 through LSS2 become ad1843_LSS.
|
||||
*
|
||||
* Only the bitfields we need are defined.
|
||||
*/
|
||||
|
||||
struct ad1843_bitfield {
|
||||
char reg;
|
||||
char lo_bit;
|
||||
char nbits;
|
||||
};
|
||||
|
||||
static const struct ad1843_bitfield
|
||||
ad1843_PDNO = { 0, 14, 1 }, /* Converter Power-Down Flag */
|
||||
ad1843_INIT = { 0, 15, 1 }, /* Clock Initialization Flag */
|
||||
ad1843_RIG = { 2, 0, 4 }, /* Right ADC Input Gain */
|
||||
ad1843_RMGE = { 2, 4, 1 }, /* Right ADC Mic Gain Enable */
|
||||
ad1843_RSS = { 2, 5, 3 }, /* Right ADC Source Select */
|
||||
ad1843_LIG = { 2, 8, 4 }, /* Left ADC Input Gain */
|
||||
ad1843_LMGE = { 2, 12, 1 }, /* Left ADC Mic Gain Enable */
|
||||
ad1843_LSS = { 2, 13, 3 }, /* Left ADC Source Select */
|
||||
ad1843_RD2M = { 3, 0, 5 }, /* Right DAC 2 Mix Gain/Atten */
|
||||
ad1843_RD2MM = { 3, 7, 1 }, /* Right DAC 2 Mix Mute */
|
||||
ad1843_LD2M = { 3, 8, 5 }, /* Left DAC 2 Mix Gain/Atten */
|
||||
ad1843_LD2MM = { 3, 15, 1 }, /* Left DAC 2 Mix Mute */
|
||||
ad1843_RX1M = { 4, 0, 5 }, /* Right Aux 1 Mix Gain/Atten */
|
||||
ad1843_RX1MM = { 4, 7, 1 }, /* Right Aux 1 Mix Mute */
|
||||
ad1843_LX1M = { 4, 8, 5 }, /* Left Aux 1 Mix Gain/Atten */
|
||||
ad1843_LX1MM = { 4, 15, 1 }, /* Left Aux 1 Mix Mute */
|
||||
ad1843_RX2M = { 5, 0, 5 }, /* Right Aux 2 Mix Gain/Atten */
|
||||
ad1843_RX2MM = { 5, 7, 1 }, /* Right Aux 2 Mix Mute */
|
||||
ad1843_LX2M = { 5, 8, 5 }, /* Left Aux 2 Mix Gain/Atten */
|
||||
ad1843_LX2MM = { 5, 15, 1 }, /* Left Aux 2 Mix Mute */
|
||||
ad1843_RMCM = { 7, 0, 5 }, /* Right Mic Mix Gain/Atten */
|
||||
ad1843_RMCMM = { 7, 7, 1 }, /* Right Mic Mix Mute */
|
||||
ad1843_LMCM = { 7, 8, 5 }, /* Left Mic Mix Gain/Atten */
|
||||
ad1843_LMCMM = { 7, 15, 1 }, /* Left Mic Mix Mute */
|
||||
ad1843_HPOS = { 8, 4, 1 }, /* Headphone Output Voltage Swing */
|
||||
ad1843_HPOM = { 8, 5, 1 }, /* Headphone Output Mute */
|
||||
ad1843_MPOM = { 8, 6, 1 }, /* Mono Output Mute */
|
||||
ad1843_RDA1G = { 9, 0, 6 }, /* Right DAC1 Analog/Digital Gain */
|
||||
ad1843_RDA1GM = { 9, 7, 1 }, /* Right DAC1 Analog Mute */
|
||||
ad1843_LDA1G = { 9, 8, 6 }, /* Left DAC1 Analog/Digital Gain */
|
||||
ad1843_LDA1GM = { 9, 15, 1 }, /* Left DAC1 Analog Mute */
|
||||
ad1843_RDA2G = { 10, 0, 6 }, /* Right DAC2 Analog/Digital Gain */
|
||||
ad1843_RDA2GM = { 10, 7, 1 }, /* Right DAC2 Analog Mute */
|
||||
ad1843_LDA2G = { 10, 8, 6 }, /* Left DAC2 Analog/Digital Gain */
|
||||
ad1843_LDA2GM = { 10, 15, 1 }, /* Left DAC2 Analog Mute */
|
||||
ad1843_RDA1AM = { 11, 7, 1 }, /* Right DAC1 Digital Mute */
|
||||
ad1843_LDA1AM = { 11, 15, 1 }, /* Left DAC1 Digital Mute */
|
||||
ad1843_RDA2AM = { 12, 7, 1 }, /* Right DAC2 Digital Mute */
|
||||
ad1843_LDA2AM = { 12, 15, 1 }, /* Left DAC2 Digital Mute */
|
||||
ad1843_ADLC = { 15, 0, 2 }, /* ADC Left Sample Rate Source */
|
||||
ad1843_ADRC = { 15, 2, 2 }, /* ADC Right Sample Rate Source */
|
||||
ad1843_DA1C = { 15, 8, 2 }, /* DAC1 Sample Rate Source */
|
||||
ad1843_DA2C = { 15, 10, 2 }, /* DAC2 Sample Rate Source */
|
||||
ad1843_C1C = { 17, 0, 16 }, /* Clock 1 Sample Rate Select */
|
||||
ad1843_C2C = { 20, 0, 16 }, /* Clock 2 Sample Rate Select */
|
||||
ad1843_C3C = { 23, 0, 16 }, /* Clock 3 Sample Rate Select */
|
||||
ad1843_DAADL = { 25, 4, 2 }, /* Digital ADC Left Source Select */
|
||||
ad1843_DAADR = { 25, 6, 2 }, /* Digital ADC Right Source Select */
|
||||
ad1843_DAMIX = { 25, 14, 1 }, /* DAC Digital Mix Enable */
|
||||
ad1843_DRSFLT = { 25, 15, 1 }, /* Digital Reampler Filter Mode */
|
||||
ad1843_ADLF = { 26, 0, 2 }, /* ADC Left Channel Data Format */
|
||||
ad1843_ADRF = { 26, 2, 2 }, /* ADC Right Channel Data Format */
|
||||
ad1843_ADTLK = { 26, 4, 1 }, /* ADC Transmit Lock Mode Select */
|
||||
ad1843_SCF = { 26, 7, 1 }, /* SCLK Frequency Select */
|
||||
ad1843_DA1F = { 26, 8, 2 }, /* DAC1 Data Format Select */
|
||||
ad1843_DA2F = { 26, 10, 2 }, /* DAC2 Data Format Select */
|
||||
ad1843_DA1SM = { 26, 14, 1 }, /* DAC1 Stereo/Mono Mode Select */
|
||||
ad1843_DA2SM = { 26, 15, 1 }, /* DAC2 Stereo/Mono Mode Select */
|
||||
ad1843_ADLEN = { 27, 0, 1 }, /* ADC Left Channel Enable */
|
||||
ad1843_ADREN = { 27, 1, 1 }, /* ADC Right Channel Enable */
|
||||
ad1843_AAMEN = { 27, 4, 1 }, /* Analog to Analog Mix Enable */
|
||||
ad1843_ANAEN = { 27, 7, 1 }, /* Analog Channel Enable */
|
||||
ad1843_DA1EN = { 27, 8, 1 }, /* DAC1 Enable */
|
||||
ad1843_DA2EN = { 27, 9, 1 }, /* DAC2 Enable */
|
||||
ad1843_DDMEN = { 27, 12, 1 }, /* DAC2 to DAC1 Mix Enable */
|
||||
ad1843_C1EN = { 28, 11, 1 }, /* Clock Generator 1 Enable */
|
||||
ad1843_C2EN = { 28, 12, 1 }, /* Clock Generator 2 Enable */
|
||||
ad1843_C3EN = { 28, 13, 1 }, /* Clock Generator 3 Enable */
|
||||
ad1843_PDNI = { 28, 15, 1 }; /* Converter Power Down */
|
||||
|
||||
/*
|
||||
* The various registers of the AD1843 use three different formats for
|
||||
* specifying gain. The ad1843_gain structure parameterizes the
|
||||
* formats.
|
||||
*/
|
||||
|
||||
struct ad1843_gain {
|
||||
int negative; /* nonzero if gain is negative. */
|
||||
const struct ad1843_bitfield *lfield;
|
||||
const struct ad1843_bitfield *rfield;
|
||||
const struct ad1843_bitfield *lmute;
|
||||
const struct ad1843_bitfield *rmute;
|
||||
};
|
||||
|
||||
static const struct ad1843_gain ad1843_gain_RECLEV = {
|
||||
.negative = 0,
|
||||
.lfield = &ad1843_LIG,
|
||||
.rfield = &ad1843_RIG
|
||||
};
|
||||
static const struct ad1843_gain ad1843_gain_LINE = {
|
||||
.negative = 1,
|
||||
.lfield = &ad1843_LX1M,
|
||||
.rfield = &ad1843_RX1M,
|
||||
.lmute = &ad1843_LX1MM,
|
||||
.rmute = &ad1843_RX1MM
|
||||
};
|
||||
static const struct ad1843_gain ad1843_gain_LINE_2 = {
|
||||
.negative = 1,
|
||||
.lfield = &ad1843_LDA2G,
|
||||
.rfield = &ad1843_RDA2G,
|
||||
.lmute = &ad1843_LDA2GM,
|
||||
.rmute = &ad1843_RDA2GM
|
||||
};
|
||||
static const struct ad1843_gain ad1843_gain_MIC = {
|
||||
.negative = 1,
|
||||
.lfield = &ad1843_LMCM,
|
||||
.rfield = &ad1843_RMCM,
|
||||
.lmute = &ad1843_LMCMM,
|
||||
.rmute = &ad1843_RMCMM
|
||||
};
|
||||
static const struct ad1843_gain ad1843_gain_PCM_0 = {
|
||||
.negative = 1,
|
||||
.lfield = &ad1843_LDA1G,
|
||||
.rfield = &ad1843_RDA1G,
|
||||
.lmute = &ad1843_LDA1GM,
|
||||
.rmute = &ad1843_RDA1GM
|
||||
};
|
||||
static const struct ad1843_gain ad1843_gain_PCM_1 = {
|
||||
.negative = 1,
|
||||
.lfield = &ad1843_LD2M,
|
||||
.rfield = &ad1843_RD2M,
|
||||
.lmute = &ad1843_LD2MM,
|
||||
.rmute = &ad1843_RD2MM
|
||||
};
|
||||
|
||||
static const struct ad1843_gain *ad1843_gain[AD1843_GAIN_SIZE] =
|
||||
{
|
||||
&ad1843_gain_RECLEV,
|
||||
&ad1843_gain_LINE,
|
||||
&ad1843_gain_LINE_2,
|
||||
&ad1843_gain_MIC,
|
||||
&ad1843_gain_PCM_0,
|
||||
&ad1843_gain_PCM_1,
|
||||
};
|
||||
|
||||
/* read the current value of an AD1843 bitfield. */
|
||||
|
||||
static int ad1843_read_bits(struct snd_ad1843 *ad1843,
|
||||
const struct ad1843_bitfield *field)
|
||||
{
|
||||
int w;
|
||||
|
||||
w = ad1843->read(ad1843->chip, field->reg);
|
||||
return w >> field->lo_bit & ((1 << field->nbits) - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* write a new value to an AD1843 bitfield and return the old value.
|
||||
*/
|
||||
|
||||
static int ad1843_write_bits(struct snd_ad1843 *ad1843,
|
||||
const struct ad1843_bitfield *field,
|
||||
int newval)
|
||||
{
|
||||
int w, mask, oldval, newbits;
|
||||
|
||||
w = ad1843->read(ad1843->chip, field->reg);
|
||||
mask = ((1 << field->nbits) - 1) << field->lo_bit;
|
||||
oldval = (w & mask) >> field->lo_bit;
|
||||
newbits = (newval << field->lo_bit) & mask;
|
||||
w = (w & ~mask) | newbits;
|
||||
ad1843->write(ad1843->chip, field->reg, w);
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
||||
/*
|
||||
* ad1843_read_multi reads multiple bitfields from the same AD1843
|
||||
* register. It uses a single read cycle to do it. (Reading the
|
||||
* ad1843 requires 256 bit times at 12.288 MHz, or nearly 20
|
||||
* microseconds.)
|
||||
*
|
||||
* Called like this.
|
||||
*
|
||||
* ad1843_read_multi(ad1843, nfields,
|
||||
* &ad1843_FIELD1, &val1,
|
||||
* &ad1843_FIELD2, &val2, ...);
|
||||
*/
|
||||
|
||||
static void ad1843_read_multi(struct snd_ad1843 *ad1843, int argcount, ...)
|
||||
{
|
||||
va_list ap;
|
||||
const struct ad1843_bitfield *fp;
|
||||
int w = 0, mask, *value, reg = -1;
|
||||
|
||||
va_start(ap, argcount);
|
||||
while (--argcount >= 0) {
|
||||
fp = va_arg(ap, const struct ad1843_bitfield *);
|
||||
value = va_arg(ap, int *);
|
||||
if (reg == -1) {
|
||||
reg = fp->reg;
|
||||
w = ad1843->read(ad1843->chip, reg);
|
||||
}
|
||||
|
||||
mask = (1 << fp->nbits) - 1;
|
||||
*value = w >> fp->lo_bit & mask;
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* ad1843_write_multi stores multiple bitfields into the same AD1843
|
||||
* register. It uses one read and one write cycle to do it.
|
||||
*
|
||||
* Called like this.
|
||||
*
|
||||
* ad1843_write_multi(ad1843, nfields,
|
||||
* &ad1843_FIELD1, val1,
|
||||
* &ad1843_FIELF2, val2, ...);
|
||||
*/
|
||||
|
||||
static void ad1843_write_multi(struct snd_ad1843 *ad1843, int argcount, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int reg;
|
||||
const struct ad1843_bitfield *fp;
|
||||
int value;
|
||||
int w, m, mask, bits;
|
||||
|
||||
mask = 0;
|
||||
bits = 0;
|
||||
reg = -1;
|
||||
|
||||
va_start(ap, argcount);
|
||||
while (--argcount >= 0) {
|
||||
fp = va_arg(ap, const struct ad1843_bitfield *);
|
||||
value = va_arg(ap, int);
|
||||
if (reg == -1)
|
||||
reg = fp->reg;
|
||||
else
|
||||
BUG_ON(reg != fp->reg);
|
||||
m = ((1 << fp->nbits) - 1) << fp->lo_bit;
|
||||
mask |= m;
|
||||
bits |= (value << fp->lo_bit) & m;
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
if (~mask & 0xFFFF)
|
||||
w = ad1843->read(ad1843->chip, reg);
|
||||
else
|
||||
w = 0;
|
||||
w = (w & ~mask) | bits;
|
||||
ad1843->write(ad1843->chip, reg, w);
|
||||
}
|
||||
|
||||
int ad1843_get_gain_max(struct snd_ad1843 *ad1843, int id)
|
||||
{
|
||||
const struct ad1843_gain *gp = ad1843_gain[id];
|
||||
int ret;
|
||||
|
||||
ret = (1 << gp->lfield->nbits);
|
||||
if (!gp->lmute)
|
||||
ret -= 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* ad1843_get_gain reads the specified register and extracts the gain value
|
||||
* using the supplied gain type.
|
||||
*/
|
||||
|
||||
int ad1843_get_gain(struct snd_ad1843 *ad1843, int id)
|
||||
{
|
||||
int lg, rg, lm, rm;
|
||||
const struct ad1843_gain *gp = ad1843_gain[id];
|
||||
unsigned short mask = (1 << gp->lfield->nbits) - 1;
|
||||
|
||||
ad1843_read_multi(ad1843, 2, gp->lfield, &lg, gp->rfield, &rg);
|
||||
if (gp->negative) {
|
||||
lg = mask - lg;
|
||||
rg = mask - rg;
|
||||
}
|
||||
if (gp->lmute) {
|
||||
ad1843_read_multi(ad1843, 2, gp->lmute, &lm, gp->rmute, &rm);
|
||||
if (lm)
|
||||
lg = 0;
|
||||
if (rm)
|
||||
rg = 0;
|
||||
}
|
||||
return lg << 0 | rg << 8;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set an audio channel's gain.
|
||||
*
|
||||
* Returns the new gain, which may be lower than the old gain.
|
||||
*/
|
||||
|
||||
int ad1843_set_gain(struct snd_ad1843 *ad1843, int id, int newval)
|
||||
{
|
||||
const struct ad1843_gain *gp = ad1843_gain[id];
|
||||
unsigned short mask = (1 << gp->lfield->nbits) - 1;
|
||||
|
||||
int lg = (newval >> 0) & mask;
|
||||
int rg = (newval >> 8) & mask;
|
||||
int lm = (lg == 0) ? 1 : 0;
|
||||
int rm = (rg == 0) ? 1 : 0;
|
||||
|
||||
if (gp->negative) {
|
||||
lg = mask - lg;
|
||||
rg = mask - rg;
|
||||
}
|
||||
if (gp->lmute)
|
||||
ad1843_write_multi(ad1843, 2, gp->lmute, lm, gp->rmute, rm);
|
||||
ad1843_write_multi(ad1843, 2, gp->lfield, lg, gp->rfield, rg);
|
||||
return ad1843_get_gain(ad1843, id);
|
||||
}
|
||||
|
||||
/* Returns the current recording source */
|
||||
|
||||
int ad1843_get_recsrc(struct snd_ad1843 *ad1843)
|
||||
{
|
||||
int val = ad1843_read_bits(ad1843, &ad1843_LSS);
|
||||
|
||||
if (val < 0 || val > 2) {
|
||||
val = 2;
|
||||
ad1843_write_multi(ad1843, 2,
|
||||
&ad1843_LSS, val, &ad1843_RSS, val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set recording source.
|
||||
*
|
||||
* Returns newsrc on success, -errno on failure.
|
||||
*/
|
||||
|
||||
int ad1843_set_recsrc(struct snd_ad1843 *ad1843, int newsrc)
|
||||
{
|
||||
if (newsrc < 0 || newsrc > 2)
|
||||
return -EINVAL;
|
||||
|
||||
ad1843_write_multi(ad1843, 2, &ad1843_LSS, newsrc, &ad1843_RSS, newsrc);
|
||||
return newsrc;
|
||||
}
|
||||
|
||||
/* Setup ad1843 for D/A conversion. */
|
||||
|
||||
void ad1843_setup_dac(struct snd_ad1843 *ad1843,
|
||||
unsigned int id,
|
||||
unsigned int framerate,
|
||||
snd_pcm_format_t fmt,
|
||||
unsigned int channels)
|
||||
{
|
||||
int ad_fmt = 0, ad_mode = 0;
|
||||
|
||||
switch (fmt) {
|
||||
case SNDRV_PCM_FORMAT_S8:
|
||||
ad_fmt = 0;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_U8:
|
||||
ad_fmt = 0;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
ad_fmt = 1;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_MU_LAW:
|
||||
ad_fmt = 2;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_A_LAW:
|
||||
ad_fmt = 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (channels) {
|
||||
case 2:
|
||||
ad_mode = 0;
|
||||
break;
|
||||
case 1:
|
||||
ad_mode = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (id) {
|
||||
ad1843_write_bits(ad1843, &ad1843_C2C, framerate);
|
||||
ad1843_write_multi(ad1843, 2,
|
||||
&ad1843_DA2SM, ad_mode,
|
||||
&ad1843_DA2F, ad_fmt);
|
||||
} else {
|
||||
ad1843_write_bits(ad1843, &ad1843_C1C, framerate);
|
||||
ad1843_write_multi(ad1843, 2,
|
||||
&ad1843_DA1SM, ad_mode,
|
||||
&ad1843_DA1F, ad_fmt);
|
||||
}
|
||||
}
|
||||
|
||||
void ad1843_shutdown_dac(struct snd_ad1843 *ad1843, unsigned int id)
|
||||
{
|
||||
if (id)
|
||||
ad1843_write_bits(ad1843, &ad1843_DA2F, 1);
|
||||
else
|
||||
ad1843_write_bits(ad1843, &ad1843_DA1F, 1);
|
||||
}
|
||||
|
||||
void ad1843_setup_adc(struct snd_ad1843 *ad1843,
|
||||
unsigned int framerate,
|
||||
snd_pcm_format_t fmt,
|
||||
unsigned int channels)
|
||||
{
|
||||
int da_fmt = 0;
|
||||
|
||||
switch (fmt) {
|
||||
case SNDRV_PCM_FORMAT_S8: da_fmt = 0; break;
|
||||
case SNDRV_PCM_FORMAT_U8: da_fmt = 0; break;
|
||||
case SNDRV_PCM_FORMAT_S16_LE: da_fmt = 1; break;
|
||||
case SNDRV_PCM_FORMAT_MU_LAW: da_fmt = 2; break;
|
||||
case SNDRV_PCM_FORMAT_A_LAW: da_fmt = 3; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
ad1843_write_bits(ad1843, &ad1843_C3C, framerate);
|
||||
ad1843_write_multi(ad1843, 2,
|
||||
&ad1843_ADLF, da_fmt, &ad1843_ADRF, da_fmt);
|
||||
}
|
||||
|
||||
void ad1843_shutdown_adc(struct snd_ad1843 *ad1843)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
/*
|
||||
* Fully initialize the ad1843. As described in the AD1843 data
|
||||
* sheet, section "START-UP SEQUENCE". The numbered comments are
|
||||
* subsection headings from the data sheet. See the data sheet, pages
|
||||
* 52-54, for more info.
|
||||
*
|
||||
* return 0 on success, -errno on failure. */
|
||||
|
||||
int ad1843_init(struct snd_ad1843 *ad1843)
|
||||
{
|
||||
unsigned long later;
|
||||
|
||||
if (ad1843_read_bits(ad1843, &ad1843_INIT) != 0) {
|
||||
printk(KERN_ERR "ad1843: AD1843 won't initialize\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ad1843_write_bits(ad1843, &ad1843_SCF, 1);
|
||||
|
||||
/* 4. Put the conversion resources into standby. */
|
||||
ad1843_write_bits(ad1843, &ad1843_PDNI, 0);
|
||||
later = jiffies + msecs_to_jiffies(500);
|
||||
|
||||
while (ad1843_read_bits(ad1843, &ad1843_PDNO)) {
|
||||
if (time_after(jiffies, later)) {
|
||||
printk(KERN_ERR
|
||||
"ad1843: AD1843 won't power up\n");
|
||||
return -EIO;
|
||||
}
|
||||
schedule_timeout_interruptible(5);
|
||||
}
|
||||
|
||||
/* 5. Power up the clock generators and enable clock output pins. */
|
||||
ad1843_write_multi(ad1843, 3,
|
||||
&ad1843_C1EN, 1,
|
||||
&ad1843_C2EN, 1,
|
||||
&ad1843_C3EN, 1);
|
||||
|
||||
/* 6. Configure conversion resources while they are in standby. */
|
||||
|
||||
/* DAC1/2 use clock 1/2 as source, ADC uses clock 3. Always. */
|
||||
ad1843_write_multi(ad1843, 4,
|
||||
&ad1843_DA1C, 1,
|
||||
&ad1843_DA2C, 2,
|
||||
&ad1843_ADLC, 3,
|
||||
&ad1843_ADRC, 3);
|
||||
|
||||
/* 7. Enable conversion resources. */
|
||||
ad1843_write_bits(ad1843, &ad1843_ADTLK, 1);
|
||||
ad1843_write_multi(ad1843, 7,
|
||||
&ad1843_ANAEN, 1,
|
||||
&ad1843_AAMEN, 1,
|
||||
&ad1843_DA1EN, 1,
|
||||
&ad1843_DA2EN, 1,
|
||||
&ad1843_DDMEN, 1,
|
||||
&ad1843_ADLEN, 1,
|
||||
&ad1843_ADREN, 1);
|
||||
|
||||
/* 8. Configure conversion resources while they are enabled. */
|
||||
|
||||
/* set gain to 0 for all channels */
|
||||
ad1843_set_gain(ad1843, AD1843_GAIN_RECLEV, 0);
|
||||
ad1843_set_gain(ad1843, AD1843_GAIN_LINE, 0);
|
||||
ad1843_set_gain(ad1843, AD1843_GAIN_LINE_2, 0);
|
||||
ad1843_set_gain(ad1843, AD1843_GAIN_MIC, 0);
|
||||
ad1843_set_gain(ad1843, AD1843_GAIN_PCM_0, 0);
|
||||
ad1843_set_gain(ad1843, AD1843_GAIN_PCM_1, 0);
|
||||
|
||||
/* Unmute all channels. */
|
||||
/* DAC1 */
|
||||
ad1843_write_multi(ad1843, 2, &ad1843_LDA1GM, 0, &ad1843_RDA1GM, 0);
|
||||
/* DAC2 */
|
||||
ad1843_write_multi(ad1843, 2, &ad1843_LDA2GM, 0, &ad1843_RDA2GM, 0);
|
||||
|
||||
/* Set default recording source to Line In and set
|
||||
* mic gain to +20 dB.
|
||||
*/
|
||||
ad1843_set_recsrc(ad1843, 2);
|
||||
ad1843_write_multi(ad1843, 2, &ad1843_LMGE, 1, &ad1843_RMGE, 1);
|
||||
|
||||
/* Set Speaker Out level to +/- 4V and unmute it. */
|
||||
ad1843_write_multi(ad1843, 3,
|
||||
&ad1843_HPOS, 1,
|
||||
&ad1843_HPOM, 0,
|
||||
&ad1843_MPOM, 0);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,947 @@
|
|||
/*
|
||||
* Driver for A2 audio system used in SGI machines
|
||||
* Copyright (c) 2008 Thomas Bogendoerfer <tsbogend@alpha.fanken.de>
|
||||
*
|
||||
* Based on OSS code from Ladislav Michl <ladis@linux-mips.org>, which
|
||||
* was based on code from Ulf Carlsson
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/sgi/hpc3.h>
|
||||
#include <asm/sgi/ip22.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm-indirect.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
#include "hal2.h"
|
||||
|
||||
static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
|
||||
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
|
||||
|
||||
module_param(index, int, 0444);
|
||||
MODULE_PARM_DESC(index, "Index value for SGI HAL2 soundcard.");
|
||||
module_param(id, charp, 0444);
|
||||
MODULE_PARM_DESC(id, "ID string for SGI HAL2 soundcard.");
|
||||
MODULE_DESCRIPTION("ALSA driver for SGI HAL2 audio");
|
||||
MODULE_AUTHOR("Thomas Bogendoerfer");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
#define H2_BLOCK_SIZE 1024
|
||||
#define H2_BUF_SIZE 16384
|
||||
|
||||
struct hal2_pbus {
|
||||
struct hpc3_pbus_dmacregs *pbus;
|
||||
int pbusnr;
|
||||
unsigned int ctrl; /* Current state of pbus->pbdma_ctrl */
|
||||
};
|
||||
|
||||
struct hal2_desc {
|
||||
struct hpc_dma_desc desc;
|
||||
u32 pad; /* padding */
|
||||
};
|
||||
|
||||
struct hal2_codec {
|
||||
struct snd_pcm_indirect pcm_indirect;
|
||||
struct snd_pcm_substream *substream;
|
||||
|
||||
unsigned char *buffer;
|
||||
dma_addr_t buffer_dma;
|
||||
struct hal2_desc *desc;
|
||||
dma_addr_t desc_dma;
|
||||
int desc_count;
|
||||
struct hal2_pbus pbus;
|
||||
int voices; /* mono/stereo */
|
||||
unsigned int sample_rate;
|
||||
unsigned int master; /* Master frequency */
|
||||
unsigned short mod; /* MOD value */
|
||||
unsigned short inc; /* INC value */
|
||||
};
|
||||
|
||||
#define H2_MIX_OUTPUT_ATT 0
|
||||
#define H2_MIX_INPUT_GAIN 1
|
||||
|
||||
struct snd_hal2 {
|
||||
struct snd_card *card;
|
||||
|
||||
struct hal2_ctl_regs *ctl_regs; /* HAL2 ctl registers */
|
||||
struct hal2_aes_regs *aes_regs; /* HAL2 aes registers */
|
||||
struct hal2_vol_regs *vol_regs; /* HAL2 vol registers */
|
||||
struct hal2_syn_regs *syn_regs; /* HAL2 syn registers */
|
||||
|
||||
struct hal2_codec dac;
|
||||
struct hal2_codec adc;
|
||||
};
|
||||
|
||||
#define H2_INDIRECT_WAIT(regs) while (hal2_read(®s->isr) & H2_ISR_TSTATUS);
|
||||
|
||||
#define H2_READ_ADDR(addr) (addr | (1<<7))
|
||||
#define H2_WRITE_ADDR(addr) (addr)
|
||||
|
||||
static inline u32 hal2_read(u32 *reg)
|
||||
{
|
||||
return __raw_readl(reg);
|
||||
}
|
||||
|
||||
static inline void hal2_write(u32 val, u32 *reg)
|
||||
{
|
||||
__raw_writel(val, reg);
|
||||
}
|
||||
|
||||
|
||||
static u32 hal2_i_read32(struct snd_hal2 *hal2, u16 addr)
|
||||
{
|
||||
u32 ret;
|
||||
struct hal2_ctl_regs *regs = hal2->ctl_regs;
|
||||
|
||||
hal2_write(H2_READ_ADDR(addr), ®s->iar);
|
||||
H2_INDIRECT_WAIT(regs);
|
||||
ret = hal2_read(®s->idr0) & 0xffff;
|
||||
hal2_write(H2_READ_ADDR(addr) | 0x1, ®s->iar);
|
||||
H2_INDIRECT_WAIT(regs);
|
||||
ret |= (hal2_read(®s->idr0) & 0xffff) << 16;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hal2_i_write16(struct snd_hal2 *hal2, u16 addr, u16 val)
|
||||
{
|
||||
struct hal2_ctl_regs *regs = hal2->ctl_regs;
|
||||
|
||||
hal2_write(val, ®s->idr0);
|
||||
hal2_write(0, ®s->idr1);
|
||||
hal2_write(0, ®s->idr2);
|
||||
hal2_write(0, ®s->idr3);
|
||||
hal2_write(H2_WRITE_ADDR(addr), ®s->iar);
|
||||
H2_INDIRECT_WAIT(regs);
|
||||
}
|
||||
|
||||
static void hal2_i_write32(struct snd_hal2 *hal2, u16 addr, u32 val)
|
||||
{
|
||||
struct hal2_ctl_regs *regs = hal2->ctl_regs;
|
||||
|
||||
hal2_write(val & 0xffff, ®s->idr0);
|
||||
hal2_write(val >> 16, ®s->idr1);
|
||||
hal2_write(0, ®s->idr2);
|
||||
hal2_write(0, ®s->idr3);
|
||||
hal2_write(H2_WRITE_ADDR(addr), ®s->iar);
|
||||
H2_INDIRECT_WAIT(regs);
|
||||
}
|
||||
|
||||
static void hal2_i_setbit16(struct snd_hal2 *hal2, u16 addr, u16 bit)
|
||||
{
|
||||
struct hal2_ctl_regs *regs = hal2->ctl_regs;
|
||||
|
||||
hal2_write(H2_READ_ADDR(addr), ®s->iar);
|
||||
H2_INDIRECT_WAIT(regs);
|
||||
hal2_write((hal2_read(®s->idr0) & 0xffff) | bit, ®s->idr0);
|
||||
hal2_write(0, ®s->idr1);
|
||||
hal2_write(0, ®s->idr2);
|
||||
hal2_write(0, ®s->idr3);
|
||||
hal2_write(H2_WRITE_ADDR(addr), ®s->iar);
|
||||
H2_INDIRECT_WAIT(regs);
|
||||
}
|
||||
|
||||
static void hal2_i_clearbit16(struct snd_hal2 *hal2, u16 addr, u16 bit)
|
||||
{
|
||||
struct hal2_ctl_regs *regs = hal2->ctl_regs;
|
||||
|
||||
hal2_write(H2_READ_ADDR(addr), ®s->iar);
|
||||
H2_INDIRECT_WAIT(regs);
|
||||
hal2_write((hal2_read(®s->idr0) & 0xffff) & ~bit, ®s->idr0);
|
||||
hal2_write(0, ®s->idr1);
|
||||
hal2_write(0, ®s->idr2);
|
||||
hal2_write(0, ®s->idr3);
|
||||
hal2_write(H2_WRITE_ADDR(addr), ®s->iar);
|
||||
H2_INDIRECT_WAIT(regs);
|
||||
}
|
||||
|
||||
static int hal2_gain_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->count = 2;
|
||||
uinfo->value.integer.min = 0;
|
||||
switch ((int)kcontrol->private_value) {
|
||||
case H2_MIX_OUTPUT_ATT:
|
||||
uinfo->value.integer.max = 31;
|
||||
break;
|
||||
case H2_MIX_INPUT_GAIN:
|
||||
uinfo->value.integer.max = 15;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hal2_gain_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_kcontrol_chip(kcontrol);
|
||||
u32 tmp;
|
||||
int l, r;
|
||||
|
||||
switch ((int)kcontrol->private_value) {
|
||||
case H2_MIX_OUTPUT_ATT:
|
||||
tmp = hal2_i_read32(hal2, H2I_DAC_C2);
|
||||
if (tmp & H2I_C2_MUTE) {
|
||||
l = 0;
|
||||
r = 0;
|
||||
} else {
|
||||
l = 31 - ((tmp >> H2I_C2_L_ATT_SHIFT) & 31);
|
||||
r = 31 - ((tmp >> H2I_C2_R_ATT_SHIFT) & 31);
|
||||
}
|
||||
break;
|
||||
case H2_MIX_INPUT_GAIN:
|
||||
tmp = hal2_i_read32(hal2, H2I_ADC_C2);
|
||||
l = (tmp >> H2I_C2_L_GAIN_SHIFT) & 15;
|
||||
r = (tmp >> H2I_C2_R_GAIN_SHIFT) & 15;
|
||||
break;
|
||||
}
|
||||
ucontrol->value.integer.value[0] = l;
|
||||
ucontrol->value.integer.value[1] = r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hal2_gain_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_kcontrol_chip(kcontrol);
|
||||
u32 old, new;
|
||||
int l, r;
|
||||
|
||||
l = ucontrol->value.integer.value[0];
|
||||
r = ucontrol->value.integer.value[1];
|
||||
|
||||
switch ((int)kcontrol->private_value) {
|
||||
case H2_MIX_OUTPUT_ATT:
|
||||
old = hal2_i_read32(hal2, H2I_DAC_C2);
|
||||
new = old & ~(H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE);
|
||||
if (l | r) {
|
||||
l = 31 - l;
|
||||
r = 31 - r;
|
||||
new |= (l << H2I_C2_L_ATT_SHIFT);
|
||||
new |= (r << H2I_C2_R_ATT_SHIFT);
|
||||
} else
|
||||
new |= H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE;
|
||||
hal2_i_write32(hal2, H2I_DAC_C2, new);
|
||||
break;
|
||||
case H2_MIX_INPUT_GAIN:
|
||||
old = hal2_i_read32(hal2, H2I_ADC_C2);
|
||||
new = old & ~(H2I_C2_L_GAIN_M | H2I_C2_R_GAIN_M);
|
||||
new |= (l << H2I_C2_L_GAIN_SHIFT);
|
||||
new |= (r << H2I_C2_R_GAIN_SHIFT);
|
||||
hal2_i_write32(hal2, H2I_ADC_C2, new);
|
||||
break;
|
||||
}
|
||||
return old != new;
|
||||
}
|
||||
|
||||
static struct snd_kcontrol_new hal2_ctrl_headphone __devinitdata = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "Headphone Playback Volume",
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.private_value = H2_MIX_OUTPUT_ATT,
|
||||
.info = hal2_gain_info,
|
||||
.get = hal2_gain_get,
|
||||
.put = hal2_gain_put,
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new hal2_ctrl_mic __devinitdata = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "Mic Capture Volume",
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.private_value = H2_MIX_INPUT_GAIN,
|
||||
.info = hal2_gain_info,
|
||||
.get = hal2_gain_get,
|
||||
.put = hal2_gain_put,
|
||||
};
|
||||
|
||||
static int __devinit hal2_mixer_create(struct snd_hal2 *hal2)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* mute DAC */
|
||||
hal2_i_write32(hal2, H2I_DAC_C2,
|
||||
H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE);
|
||||
/* mute ADC */
|
||||
hal2_i_write32(hal2, H2I_ADC_C2, 0);
|
||||
|
||||
err = snd_ctl_add(hal2->card,
|
||||
snd_ctl_new1(&hal2_ctrl_headphone, hal2));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = snd_ctl_add(hal2->card,
|
||||
snd_ctl_new1(&hal2_ctrl_mic, hal2));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t hal2_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct snd_hal2 *hal2 = dev_id;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
/* decide what caused this interrupt */
|
||||
if (hal2->dac.pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_INT) {
|
||||
snd_pcm_period_elapsed(hal2->dac.substream);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
if (hal2->adc.pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_INT) {
|
||||
snd_pcm_period_elapsed(hal2->adc.substream);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hal2_compute_rate(struct hal2_codec *codec, unsigned int rate)
|
||||
{
|
||||
unsigned short mod;
|
||||
|
||||
if (44100 % rate < 48000 % rate) {
|
||||
mod = 4 * 44100 / rate;
|
||||
codec->master = 44100;
|
||||
} else {
|
||||
mod = 4 * 48000 / rate;
|
||||
codec->master = 48000;
|
||||
}
|
||||
|
||||
codec->inc = 4;
|
||||
codec->mod = mod;
|
||||
rate = 4 * codec->master / mod;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static void hal2_set_dac_rate(struct snd_hal2 *hal2)
|
||||
{
|
||||
unsigned int master = hal2->dac.master;
|
||||
int inc = hal2->dac.inc;
|
||||
int mod = hal2->dac.mod;
|
||||
|
||||
hal2_i_write16(hal2, H2I_BRES1_C1, (master == 44100) ? 1 : 0);
|
||||
hal2_i_write32(hal2, H2I_BRES1_C2,
|
||||
((0xffff & (inc - mod - 1)) << 16) | inc);
|
||||
}
|
||||
|
||||
static void hal2_set_adc_rate(struct snd_hal2 *hal2)
|
||||
{
|
||||
unsigned int master = hal2->adc.master;
|
||||
int inc = hal2->adc.inc;
|
||||
int mod = hal2->adc.mod;
|
||||
|
||||
hal2_i_write16(hal2, H2I_BRES2_C1, (master == 44100) ? 1 : 0);
|
||||
hal2_i_write32(hal2, H2I_BRES2_C2,
|
||||
((0xffff & (inc - mod - 1)) << 16) | inc);
|
||||
}
|
||||
|
||||
static void hal2_setup_dac(struct snd_hal2 *hal2)
|
||||
{
|
||||
unsigned int fifobeg, fifoend, highwater, sample_size;
|
||||
struct hal2_pbus *pbus = &hal2->dac.pbus;
|
||||
|
||||
/* Now we set up some PBUS information. The PBUS needs information about
|
||||
* what portion of the fifo it will use. If it's receiving or
|
||||
* transmitting, and finally whether the stream is little endian or big
|
||||
* endian. The information is written later, on the start call.
|
||||
*/
|
||||
sample_size = 2 * hal2->dac.voices;
|
||||
/* Fifo should be set to hold exactly four samples. Highwater mark
|
||||
* should be set to two samples. */
|
||||
highwater = (sample_size * 2) >> 1; /* halfwords */
|
||||
fifobeg = 0; /* playback is first */
|
||||
fifoend = (sample_size * 4) >> 3; /* doublewords */
|
||||
pbus->ctrl = HPC3_PDMACTRL_RT | HPC3_PDMACTRL_LD |
|
||||
(highwater << 8) | (fifobeg << 16) | (fifoend << 24);
|
||||
/* We disable everything before we do anything at all */
|
||||
pbus->pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
|
||||
hal2_i_clearbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX);
|
||||
/* Setup the HAL2 for playback */
|
||||
hal2_set_dac_rate(hal2);
|
||||
/* Set endianess */
|
||||
hal2_i_clearbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECTX);
|
||||
/* Set DMA bus */
|
||||
hal2_i_setbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr));
|
||||
/* We are using 1st Bresenham clock generator for playback */
|
||||
hal2_i_write16(hal2, H2I_DAC_C1, (pbus->pbusnr << H2I_C1_DMA_SHIFT)
|
||||
| (1 << H2I_C1_CLKID_SHIFT)
|
||||
| (hal2->dac.voices << H2I_C1_DATAT_SHIFT));
|
||||
}
|
||||
|
||||
static void hal2_setup_adc(struct snd_hal2 *hal2)
|
||||
{
|
||||
unsigned int fifobeg, fifoend, highwater, sample_size;
|
||||
struct hal2_pbus *pbus = &hal2->adc.pbus;
|
||||
|
||||
sample_size = 2 * hal2->adc.voices;
|
||||
highwater = (sample_size * 2) >> 1; /* halfwords */
|
||||
fifobeg = (4 * 4) >> 3; /* record is second */
|
||||
fifoend = (4 * 4 + sample_size * 4) >> 3; /* doublewords */
|
||||
pbus->ctrl = HPC3_PDMACTRL_RT | HPC3_PDMACTRL_RCV | HPC3_PDMACTRL_LD |
|
||||
(highwater << 8) | (fifobeg << 16) | (fifoend << 24);
|
||||
pbus->pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
|
||||
hal2_i_clearbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR);
|
||||
/* Setup the HAL2 for record */
|
||||
hal2_set_adc_rate(hal2);
|
||||
/* Set endianess */
|
||||
hal2_i_clearbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECR);
|
||||
/* Set DMA bus */
|
||||
hal2_i_setbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr));
|
||||
/* We are using 2nd Bresenham clock generator for record */
|
||||
hal2_i_write16(hal2, H2I_ADC_C1, (pbus->pbusnr << H2I_C1_DMA_SHIFT)
|
||||
| (2 << H2I_C1_CLKID_SHIFT)
|
||||
| (hal2->adc.voices << H2I_C1_DATAT_SHIFT));
|
||||
}
|
||||
|
||||
static void hal2_start_dac(struct snd_hal2 *hal2)
|
||||
{
|
||||
struct hal2_pbus *pbus = &hal2->dac.pbus;
|
||||
|
||||
pbus->pbus->pbdma_dptr = hal2->dac.desc_dma;
|
||||
pbus->pbus->pbdma_ctrl = pbus->ctrl | HPC3_PDMACTRL_ACT;
|
||||
/* enable DAC */
|
||||
hal2_i_setbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX);
|
||||
}
|
||||
|
||||
static void hal2_start_adc(struct snd_hal2 *hal2)
|
||||
{
|
||||
struct hal2_pbus *pbus = &hal2->adc.pbus;
|
||||
|
||||
pbus->pbus->pbdma_dptr = hal2->adc.desc_dma;
|
||||
pbus->pbus->pbdma_ctrl = pbus->ctrl | HPC3_PDMACTRL_ACT;
|
||||
/* enable ADC */
|
||||
hal2_i_setbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR);
|
||||
}
|
||||
|
||||
static inline void hal2_stop_dac(struct snd_hal2 *hal2)
|
||||
{
|
||||
hal2->dac.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
|
||||
/* The HAL2 itself may remain enabled safely */
|
||||
}
|
||||
|
||||
static inline void hal2_stop_adc(struct snd_hal2 *hal2)
|
||||
{
|
||||
hal2->adc.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
|
||||
}
|
||||
|
||||
static int hal2_alloc_dmabuf(struct hal2_codec *codec)
|
||||
{
|
||||
struct hal2_desc *desc;
|
||||
dma_addr_t desc_dma, buffer_dma;
|
||||
int count = H2_BUF_SIZE / H2_BLOCK_SIZE;
|
||||
int i;
|
||||
|
||||
codec->buffer = dma_alloc_noncoherent(NULL, H2_BUF_SIZE,
|
||||
&buffer_dma, GFP_KERNEL);
|
||||
if (!codec->buffer)
|
||||
return -ENOMEM;
|
||||
desc = dma_alloc_noncoherent(NULL, count * sizeof(struct hal2_desc),
|
||||
&desc_dma, GFP_KERNEL);
|
||||
if (!desc) {
|
||||
dma_free_noncoherent(NULL, H2_BUF_SIZE,
|
||||
codec->buffer, buffer_dma);
|
||||
return -ENOMEM;
|
||||
}
|
||||
codec->buffer_dma = buffer_dma;
|
||||
codec->desc_dma = desc_dma;
|
||||
codec->desc = desc;
|
||||
for (i = 0; i < count; i++) {
|
||||
desc->desc.pbuf = buffer_dma + i * H2_BLOCK_SIZE;
|
||||
desc->desc.cntinfo = HPCDMA_XIE | H2_BLOCK_SIZE;
|
||||
desc->desc.pnext = (i == count - 1) ?
|
||||
desc_dma : desc_dma + (i + 1) * sizeof(struct hal2_desc);
|
||||
desc++;
|
||||
}
|
||||
dma_cache_sync(NULL, codec->desc, count * sizeof(struct hal2_desc),
|
||||
DMA_TO_DEVICE);
|
||||
codec->desc_count = count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hal2_free_dmabuf(struct hal2_codec *codec)
|
||||
{
|
||||
dma_free_noncoherent(NULL, codec->desc_count * sizeof(struct hal2_desc),
|
||||
codec->desc, codec->desc_dma);
|
||||
dma_free_noncoherent(NULL, H2_BUF_SIZE, codec->buffer,
|
||||
codec->buffer_dma);
|
||||
}
|
||||
|
||||
static struct snd_pcm_hardware hal2_pcm_hw = {
|
||||
.info = (SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_BLOCK_TRANSFER),
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_BE,
|
||||
.rates = SNDRV_PCM_RATE_8000_48000,
|
||||
.rate_min = 8000,
|
||||
.rate_max = 48000,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.buffer_bytes_max = 65536,
|
||||
.period_bytes_min = 1024,
|
||||
.period_bytes_max = 65536,
|
||||
.periods_min = 2,
|
||||
.periods_max = 1024,
|
||||
};
|
||||
|
||||
static int hal2_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hal2_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
return snd_pcm_lib_free_pages(substream);
|
||||
}
|
||||
|
||||
static int hal2_playback_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
int err;
|
||||
|
||||
runtime->hw = hal2_pcm_hw;
|
||||
|
||||
err = hal2_alloc_dmabuf(&hal2->dac);
|
||||
if (err)
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hal2_playback_close(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
|
||||
hal2_free_dmabuf(&hal2->dac);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hal2_playback_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct hal2_codec *dac = &hal2->dac;
|
||||
|
||||
dac->voices = runtime->channels;
|
||||
dac->sample_rate = hal2_compute_rate(dac, runtime->rate);
|
||||
memset(&dac->pcm_indirect, 0, sizeof(dac->pcm_indirect));
|
||||
dac->pcm_indirect.hw_buffer_size = H2_BUF_SIZE;
|
||||
dac->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
|
||||
dac->substream = substream;
|
||||
hal2_setup_dac(hal2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hal2_playback_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
hal2->dac.pcm_indirect.hw_io = hal2->dac.buffer_dma;
|
||||
hal2->dac.pcm_indirect.hw_data = 0;
|
||||
substream->ops->ack(substream);
|
||||
hal2_start_dac(hal2);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
hal2_stop_dac(hal2);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static snd_pcm_uframes_t
|
||||
hal2_playback_pointer(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
struct hal2_codec *dac = &hal2->dac;
|
||||
|
||||
return snd_pcm_indirect_playback_pointer(substream, &dac->pcm_indirect,
|
||||
dac->pbus.pbus->pbdma_bptr);
|
||||
}
|
||||
|
||||
static void hal2_playback_transfer(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_indirect *rec, size_t bytes)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
unsigned char *buf = hal2->dac.buffer + rec->hw_data;
|
||||
|
||||
memcpy(buf, substream->runtime->dma_area + rec->sw_data, bytes);
|
||||
dma_cache_sync(NULL, buf, bytes, DMA_TO_DEVICE);
|
||||
|
||||
}
|
||||
|
||||
static int hal2_playback_ack(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
struct hal2_codec *dac = &hal2->dac;
|
||||
|
||||
dac->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2;
|
||||
snd_pcm_indirect_playback_transfer(substream,
|
||||
&dac->pcm_indirect,
|
||||
hal2_playback_transfer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hal2_capture_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
struct hal2_codec *adc = &hal2->adc;
|
||||
int err;
|
||||
|
||||
runtime->hw = hal2_pcm_hw;
|
||||
|
||||
err = hal2_alloc_dmabuf(adc);
|
||||
if (err)
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hal2_capture_close(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
|
||||
hal2_free_dmabuf(&hal2->adc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hal2_capture_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct hal2_codec *adc = &hal2->adc;
|
||||
|
||||
adc->voices = runtime->channels;
|
||||
adc->sample_rate = hal2_compute_rate(adc, runtime->rate);
|
||||
memset(&adc->pcm_indirect, 0, sizeof(adc->pcm_indirect));
|
||||
adc->pcm_indirect.hw_buffer_size = H2_BUF_SIZE;
|
||||
adc->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2;
|
||||
adc->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
|
||||
adc->substream = substream;
|
||||
hal2_setup_adc(hal2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hal2_capture_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
hal2->adc.pcm_indirect.hw_io = hal2->adc.buffer_dma;
|
||||
hal2->adc.pcm_indirect.hw_data = 0;
|
||||
printk(KERN_DEBUG "buffer_dma %x\n", hal2->adc.buffer_dma);
|
||||
hal2_start_adc(hal2);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
hal2_stop_adc(hal2);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static snd_pcm_uframes_t
|
||||
hal2_capture_pointer(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
struct hal2_codec *adc = &hal2->adc;
|
||||
|
||||
return snd_pcm_indirect_capture_pointer(substream, &adc->pcm_indirect,
|
||||
adc->pbus.pbus->pbdma_bptr);
|
||||
}
|
||||
|
||||
static void hal2_capture_transfer(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_indirect *rec, size_t bytes)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
unsigned char *buf = hal2->adc.buffer + rec->hw_data;
|
||||
|
||||
dma_cache_sync(NULL, buf, bytes, DMA_FROM_DEVICE);
|
||||
memcpy(substream->runtime->dma_area + rec->sw_data, buf, bytes);
|
||||
}
|
||||
|
||||
static int hal2_capture_ack(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
|
||||
struct hal2_codec *adc = &hal2->adc;
|
||||
|
||||
snd_pcm_indirect_capture_transfer(substream,
|
||||
&adc->pcm_indirect,
|
||||
hal2_capture_transfer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_pcm_ops hal2_playback_ops = {
|
||||
.open = hal2_playback_open,
|
||||
.close = hal2_playback_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = hal2_pcm_hw_params,
|
||||
.hw_free = hal2_pcm_hw_free,
|
||||
.prepare = hal2_playback_prepare,
|
||||
.trigger = hal2_playback_trigger,
|
||||
.pointer = hal2_playback_pointer,
|
||||
.ack = hal2_playback_ack,
|
||||
};
|
||||
|
||||
static struct snd_pcm_ops hal2_capture_ops = {
|
||||
.open = hal2_capture_open,
|
||||
.close = hal2_capture_close,
|
||||
.ioctl = snd_pcm_lib_ioctl,
|
||||
.hw_params = hal2_pcm_hw_params,
|
||||
.hw_free = hal2_pcm_hw_free,
|
||||
.prepare = hal2_capture_prepare,
|
||||
.trigger = hal2_capture_trigger,
|
||||
.pointer = hal2_capture_pointer,
|
||||
.ack = hal2_capture_ack,
|
||||
};
|
||||
|
||||
static int __devinit hal2_pcm_create(struct snd_hal2 *hal2)
|
||||
{
|
||||
struct snd_pcm *pcm;
|
||||
int err;
|
||||
|
||||
/* create first pcm device with one outputs and one input */
|
||||
err = snd_pcm_new(hal2->card, "SGI HAL2 Audio", 0, 1, 1, &pcm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
pcm->private_data = hal2;
|
||||
strcpy(pcm->name, "SGI HAL2");
|
||||
|
||||
/* set operators */
|
||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
|
||||
&hal2_playback_ops);
|
||||
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
|
||||
&hal2_capture_ops);
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
|
||||
snd_dma_continuous_data(GFP_KERNEL),
|
||||
0, 1024 * 1024);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hal2_dev_free(struct snd_device *device)
|
||||
{
|
||||
struct snd_hal2 *hal2 = device->device_data;
|
||||
|
||||
free_irq(SGI_HPCDMA_IRQ, hal2);
|
||||
kfree(hal2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_device_ops hal2_ops = {
|
||||
.dev_free = hal2_dev_free,
|
||||
};
|
||||
|
||||
static void hal2_init_codec(struct hal2_codec *codec, struct hpc3_regs *hpc3,
|
||||
int index)
|
||||
{
|
||||
codec->pbus.pbusnr = index;
|
||||
codec->pbus.pbus = &hpc3->pbdma[index];
|
||||
}
|
||||
|
||||
static int hal2_detect(struct snd_hal2 *hal2)
|
||||
{
|
||||
unsigned short board, major, minor;
|
||||
unsigned short rev;
|
||||
|
||||
/* reset HAL2 */
|
||||
hal2_write(0, &hal2->ctl_regs->isr);
|
||||
|
||||
/* release reset */
|
||||
hal2_write(H2_ISR_GLOBAL_RESET_N | H2_ISR_CODEC_RESET_N,
|
||||
&hal2->ctl_regs->isr);
|
||||
|
||||
|
||||
hal2_i_write16(hal2, H2I_RELAY_C, H2I_RELAY_C_STATE);
|
||||
rev = hal2_read(&hal2->ctl_regs->rev);
|
||||
if (rev & H2_REV_AUDIO_PRESENT)
|
||||
return -ENODEV;
|
||||
|
||||
board = (rev & H2_REV_BOARD_M) >> 12;
|
||||
major = (rev & H2_REV_MAJOR_CHIP_M) >> 4;
|
||||
minor = (rev & H2_REV_MINOR_CHIP_M);
|
||||
|
||||
printk(KERN_INFO "SGI HAL2 revision %i.%i.%i\n",
|
||||
board, major, minor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hal2_create(struct snd_card *card, struct snd_hal2 **rchip)
|
||||
{
|
||||
struct snd_hal2 *hal2;
|
||||
struct hpc3_regs *hpc3 = hpc3c0;
|
||||
int err;
|
||||
|
||||
hal2 = kzalloc(sizeof(struct snd_hal2), GFP_KERNEL);
|
||||
if (!hal2)
|
||||
return -ENOMEM;
|
||||
|
||||
hal2->card = card;
|
||||
|
||||
if (request_irq(SGI_HPCDMA_IRQ, hal2_interrupt, IRQF_SHARED,
|
||||
"SGI HAL2", hal2)) {
|
||||
printk(KERN_ERR "HAL2: Can't get irq %d\n", SGI_HPCDMA_IRQ);
|
||||
kfree(hal2);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
hal2->ctl_regs = (struct hal2_ctl_regs *)hpc3->pbus_extregs[0];
|
||||
hal2->aes_regs = (struct hal2_aes_regs *)hpc3->pbus_extregs[1];
|
||||
hal2->vol_regs = (struct hal2_vol_regs *)hpc3->pbus_extregs[2];
|
||||
hal2->syn_regs = (struct hal2_syn_regs *)hpc3->pbus_extregs[3];
|
||||
|
||||
if (hal2_detect(hal2) < 0) {
|
||||
kfree(hal2);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hal2_init_codec(&hal2->dac, hpc3, 0);
|
||||
hal2_init_codec(&hal2->adc, hpc3, 1);
|
||||
|
||||
/*
|
||||
* All DMA channel interfaces in HAL2 are designed to operate with
|
||||
* PBUS programmed for 2 cycles in D3, 2 cycles in D4 and 2 cycles
|
||||
* in D5. HAL2 is a 16-bit device which can accept both big and little
|
||||
* endian format. It assumes that even address bytes are on high
|
||||
* portion of PBUS (15:8) and assumes that HPC3 is programmed to
|
||||
* accept a live (unsynchronized) version of P_DREQ_N from HAL2.
|
||||
*/
|
||||
#define HAL2_PBUS_DMACFG ((0 << HPC3_DMACFG_D3R_SHIFT) | \
|
||||
(2 << HPC3_DMACFG_D4R_SHIFT) | \
|
||||
(2 << HPC3_DMACFG_D5R_SHIFT) | \
|
||||
(0 << HPC3_DMACFG_D3W_SHIFT) | \
|
||||
(2 << HPC3_DMACFG_D4W_SHIFT) | \
|
||||
(2 << HPC3_DMACFG_D5W_SHIFT) | \
|
||||
HPC3_DMACFG_DS16 | \
|
||||
HPC3_DMACFG_EVENHI | \
|
||||
HPC3_DMACFG_RTIME | \
|
||||
(8 << HPC3_DMACFG_BURST_SHIFT) | \
|
||||
HPC3_DMACFG_DRQLIVE)
|
||||
/*
|
||||
* Ignore what's mentioned in the specification and write value which
|
||||
* works in The Real World (TM)
|
||||
*/
|
||||
hpc3->pbus_dmacfg[hal2->dac.pbus.pbusnr][0] = 0x8208844;
|
||||
hpc3->pbus_dmacfg[hal2->adc.pbus.pbusnr][0] = 0x8208844;
|
||||
|
||||
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, hal2, &hal2_ops);
|
||||
if (err < 0) {
|
||||
free_irq(SGI_HPCDMA_IRQ, hal2);
|
||||
kfree(hal2);
|
||||
return err;
|
||||
}
|
||||
*rchip = hal2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit hal2_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_card *card;
|
||||
struct snd_hal2 *chip;
|
||||
int err;
|
||||
|
||||
card = snd_card_new(index, id, THIS_MODULE, 0);
|
||||
if (card == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
err = hal2_create(card, &chip);
|
||||
if (err < 0) {
|
||||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
snd_card_set_dev(card, &pdev->dev);
|
||||
|
||||
err = hal2_pcm_create(chip);
|
||||
if (err < 0) {
|
||||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
err = hal2_mixer_create(chip);
|
||||
if (err < 0) {
|
||||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
|
||||
strcpy(card->driver, "SGI HAL2 Audio");
|
||||
strcpy(card->shortname, "SGI HAL2 Audio");
|
||||
sprintf(card->longname, "%s irq %i",
|
||||
card->shortname,
|
||||
SGI_HPCDMA_IRQ);
|
||||
|
||||
err = snd_card_register(card);
|
||||
if (err < 0) {
|
||||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
platform_set_drvdata(pdev, card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __exit hal2_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_card *card = platform_get_drvdata(pdev);
|
||||
|
||||
snd_card_free(card);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver hal2_driver = {
|
||||
.probe = hal2_probe,
|
||||
.remove = __devexit_p(hal2_remove),
|
||||
.driver = {
|
||||
.name = "sgihal2",
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init alsa_card_hal2_init(void)
|
||||
{
|
||||
return platform_driver_register(&hal2_driver);
|
||||
}
|
||||
|
||||
static void __exit alsa_card_hal2_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&hal2_driver);
|
||||
}
|
||||
|
||||
module_init(alsa_card_hal2_init);
|
||||
module_exit(alsa_card_hal2_exit);
|
|
@ -0,0 +1,245 @@
|
|||
#ifndef __HAL2_H
|
||||
#define __HAL2_H
|
||||
|
||||
/*
|
||||
* Driver for HAL2 sound processors
|
||||
* Copyright (c) 1999 Ulf Carlsson <ulfc@bun.falkenberg.se>
|
||||
* Copyright (c) 2001, 2002, 2003 Ladislav Michl <ladis@linux-mips.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Indirect status register */
|
||||
|
||||
#define H2_ISR_TSTATUS 0x01 /* RO: transaction status 1=busy */
|
||||
#define H2_ISR_USTATUS 0x02 /* RO: utime status bit 1=armed */
|
||||
#define H2_ISR_QUAD_MODE 0x04 /* codec mode 0=indigo 1=quad */
|
||||
#define H2_ISR_GLOBAL_RESET_N 0x08 /* chip global reset 0=reset */
|
||||
#define H2_ISR_CODEC_RESET_N 0x10 /* codec/synth reset 0=reset */
|
||||
|
||||
/* Revision register */
|
||||
|
||||
#define H2_REV_AUDIO_PRESENT 0x8000 /* RO: audio present 0=present */
|
||||
#define H2_REV_BOARD_M 0x7000 /* RO: bits 14:12, board revision */
|
||||
#define H2_REV_MAJOR_CHIP_M 0x00F0 /* RO: bits 7:4, major chip revision */
|
||||
#define H2_REV_MINOR_CHIP_M 0x000F /* RO: bits 3:0, minor chip revision */
|
||||
|
||||
/* Indirect address register */
|
||||
|
||||
/*
|
||||
* Address of indirect internal register to be accessed. A write to this
|
||||
* register initiates read or write access to the indirect registers in the
|
||||
* HAL2. Note that there af four indirect data registers for write access to
|
||||
* registers larger than 16 byte.
|
||||
*/
|
||||
|
||||
#define H2_IAR_TYPE_M 0xF000 /* bits 15:12, type of functional */
|
||||
/* block the register resides in */
|
||||
/* 1=DMA Port */
|
||||
/* 9=Global DMA Control */
|
||||
/* 2=Bresenham */
|
||||
/* 3=Unix Timer */
|
||||
#define H2_IAR_NUM_M 0x0F00 /* bits 11:8 instance of the */
|
||||
/* blockin which the indirect */
|
||||
/* register resides */
|
||||
/* If IAR_TYPE_M=DMA Port: */
|
||||
/* 1=Synth In */
|
||||
/* 2=AES In */
|
||||
/* 3=AES Out */
|
||||
/* 4=DAC Out */
|
||||
/* 5=ADC Out */
|
||||
/* 6=Synth Control */
|
||||
/* If IAR_TYPE_M=Global DMA Control: */
|
||||
/* 1=Control */
|
||||
/* If IAR_TYPE_M=Bresenham: */
|
||||
/* 1=Bresenham Clock Gen 1 */
|
||||
/* 2=Bresenham Clock Gen 2 */
|
||||
/* 3=Bresenham Clock Gen 3 */
|
||||
/* If IAR_TYPE_M=Unix Timer: */
|
||||
/* 1=Unix Timer */
|
||||
#define H2_IAR_ACCESS_SELECT 0x0080 /* 1=read 0=write */
|
||||
#define H2_IAR_PARAM 0x000C /* Parameter Select */
|
||||
#define H2_IAR_RB_INDEX_M 0x0003 /* Read Back Index */
|
||||
/* 00:word0 */
|
||||
/* 01:word1 */
|
||||
/* 10:word2 */
|
||||
/* 11:word3 */
|
||||
/*
|
||||
* HAL2 internal addressing
|
||||
*
|
||||
* The HAL2 has "indirect registers" (idr) which are accessed by writing to the
|
||||
* Indirect Data registers. Write the address to the Indirect Address register
|
||||
* to transfer the data.
|
||||
*
|
||||
* We define the H2IR_* to the read address and H2IW_* to the write address and
|
||||
* H2I_* to be fields in whatever register is referred to.
|
||||
*
|
||||
* When we write to indirect registers which are larger than one word (16 bit)
|
||||
* we have to fill more than one indirect register before writing. When we read
|
||||
* back however we have to read several times, each time with different Read
|
||||
* Back Indexes (there are defs for doing this easily).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Relay Control
|
||||
*/
|
||||
#define H2I_RELAY_C 0x9100
|
||||
#define H2I_RELAY_C_STATE 0x01 /* state of RELAY pin signal */
|
||||
|
||||
/* DMA port enable */
|
||||
|
||||
#define H2I_DMA_PORT_EN 0x9104
|
||||
#define H2I_DMA_PORT_EN_SY_IN 0x01 /* Synth_in DMA port */
|
||||
#define H2I_DMA_PORT_EN_AESRX 0x02 /* AES receiver DMA port */
|
||||
#define H2I_DMA_PORT_EN_AESTX 0x04 /* AES transmitter DMA port */
|
||||
#define H2I_DMA_PORT_EN_CODECTX 0x08 /* CODEC transmit DMA port */
|
||||
#define H2I_DMA_PORT_EN_CODECR 0x10 /* CODEC receive DMA port */
|
||||
|
||||
#define H2I_DMA_END 0x9108 /* global dma endian select */
|
||||
#define H2I_DMA_END_SY_IN 0x01 /* Synth_in DMA port */
|
||||
#define H2I_DMA_END_AESRX 0x02 /* AES receiver DMA port */
|
||||
#define H2I_DMA_END_AESTX 0x04 /* AES transmitter DMA port */
|
||||
#define H2I_DMA_END_CODECTX 0x08 /* CODEC transmit DMA port */
|
||||
#define H2I_DMA_END_CODECR 0x10 /* CODEC receive DMA port */
|
||||
/* 0=b_end 1=l_end */
|
||||
|
||||
#define H2I_DMA_DRV 0x910C /* global PBUS DMA enable */
|
||||
|
||||
#define H2I_SYNTH_C 0x1104 /* Synth DMA control */
|
||||
|
||||
#define H2I_AESRX_C 0x1204 /* AES RX dma control */
|
||||
|
||||
#define H2I_C_TS_EN 0x20 /* Timestamp enable */
|
||||
#define H2I_C_TS_FRMT 0x40 /* Timestamp format */
|
||||
#define H2I_C_NAUDIO 0x80 /* Sign extend */
|
||||
|
||||
/* AESRX CTL, 16 bit */
|
||||
|
||||
#define H2I_AESTX_C 0x1304 /* AES TX DMA control */
|
||||
#define H2I_AESTX_C_CLKID_SHIFT 3 /* Bresenham Clock Gen 1-3 */
|
||||
#define H2I_AESTX_C_CLKID_M 0x18
|
||||
#define H2I_AESTX_C_DATAT_SHIFT 8 /* 1=mono 2=stereo (3=quad) */
|
||||
#define H2I_AESTX_C_DATAT_M 0x300
|
||||
|
||||
/* CODEC registers */
|
||||
|
||||
#define H2I_DAC_C1 0x1404 /* DAC DMA control, 16 bit */
|
||||
#define H2I_DAC_C2 0x1408 /* DAC DMA control, 32 bit */
|
||||
#define H2I_ADC_C1 0x1504 /* ADC DMA control, 16 bit */
|
||||
#define H2I_ADC_C2 0x1508 /* ADC DMA control, 32 bit */
|
||||
|
||||
/* Bits in CTL1 register */
|
||||
|
||||
#define H2I_C1_DMA_SHIFT 0 /* DMA channel */
|
||||
#define H2I_C1_DMA_M 0x7
|
||||
#define H2I_C1_CLKID_SHIFT 3 /* Bresenham Clock Gen 1-3 */
|
||||
#define H2I_C1_CLKID_M 0x18
|
||||
#define H2I_C1_DATAT_SHIFT 8 /* 1=mono 2=stereo (3=quad) */
|
||||
#define H2I_C1_DATAT_M 0x300
|
||||
|
||||
/* Bits in CTL2 register */
|
||||
|
||||
#define H2I_C2_R_GAIN_SHIFT 0 /* right a/d input gain */
|
||||
#define H2I_C2_R_GAIN_M 0xf
|
||||
#define H2I_C2_L_GAIN_SHIFT 4 /* left a/d input gain */
|
||||
#define H2I_C2_L_GAIN_M 0xf0
|
||||
#define H2I_C2_R_SEL 0x100 /* right input select */
|
||||
#define H2I_C2_L_SEL 0x200 /* left input select */
|
||||
#define H2I_C2_MUTE 0x400 /* mute */
|
||||
#define H2I_C2_DO1 0x00010000 /* digital output port bit 0 */
|
||||
#define H2I_C2_DO2 0x00020000 /* digital output port bit 1 */
|
||||
#define H2I_C2_R_ATT_SHIFT 18 /* right d/a output - */
|
||||
#define H2I_C2_R_ATT_M 0x007c0000 /* attenuation */
|
||||
#define H2I_C2_L_ATT_SHIFT 23 /* left d/a output - */
|
||||
#define H2I_C2_L_ATT_M 0x0f800000 /* attenuation */
|
||||
|
||||
#define H2I_SYNTH_MAP_C 0x1104 /* synth dma handshake ctrl */
|
||||
|
||||
/* Clock generator CTL 1, 16 bit */
|
||||
|
||||
#define H2I_BRES1_C1 0x2104
|
||||
#define H2I_BRES2_C1 0x2204
|
||||
#define H2I_BRES3_C1 0x2304
|
||||
|
||||
#define H2I_BRES_C1_SHIFT 0 /* 0=48.0 1=44.1 2=aes_rx */
|
||||
#define H2I_BRES_C1_M 0x03
|
||||
|
||||
/* Clock generator CTL 2, 32 bit */
|
||||
|
||||
#define H2I_BRES1_C2 0x2108
|
||||
#define H2I_BRES2_C2 0x2208
|
||||
#define H2I_BRES3_C2 0x2308
|
||||
|
||||
#define H2I_BRES_C2_INC_SHIFT 0 /* increment value */
|
||||
#define H2I_BRES_C2_INC_M 0xffff
|
||||
#define H2I_BRES_C2_MOD_SHIFT 16 /* modcontrol value */
|
||||
#define H2I_BRES_C2_MOD_M 0xffff0000 /* modctrl=0xffff&(modinc-1) */
|
||||
|
||||
/* Unix timer, 64 bit */
|
||||
|
||||
#define H2I_UTIME 0x3104
|
||||
#define H2I_UTIME_0_LD 0xffff /* microseconds, LSB's */
|
||||
#define H2I_UTIME_1_LD0 0x0f /* microseconds, MSB's */
|
||||
#define H2I_UTIME_1_LD1 0xf0 /* tenths of microseconds */
|
||||
#define H2I_UTIME_2_LD 0xffff /* seconds, LSB's */
|
||||
#define H2I_UTIME_3_LD 0xffff /* seconds, MSB's */
|
||||
|
||||
struct hal2_ctl_regs {
|
||||
u32 _unused0[4];
|
||||
u32 isr; /* 0x10 Status Register */
|
||||
u32 _unused1[3];
|
||||
u32 rev; /* 0x20 Revision Register */
|
||||
u32 _unused2[3];
|
||||
u32 iar; /* 0x30 Indirect Address Register */
|
||||
u32 _unused3[3];
|
||||
u32 idr0; /* 0x40 Indirect Data Register 0 */
|
||||
u32 _unused4[3];
|
||||
u32 idr1; /* 0x50 Indirect Data Register 1 */
|
||||
u32 _unused5[3];
|
||||
u32 idr2; /* 0x60 Indirect Data Register 2 */
|
||||
u32 _unused6[3];
|
||||
u32 idr3; /* 0x70 Indirect Data Register 3 */
|
||||
};
|
||||
|
||||
struct hal2_aes_regs {
|
||||
u32 rx_stat[2]; /* Status registers */
|
||||
u32 rx_cr[2]; /* Control registers */
|
||||
u32 rx_ud[4]; /* User data window */
|
||||
u32 rx_st[24]; /* Channel status data */
|
||||
|
||||
u32 tx_stat[1]; /* Status register */
|
||||
u32 tx_cr[3]; /* Control registers */
|
||||
u32 tx_ud[4]; /* User data window */
|
||||
u32 tx_st[24]; /* Channel status data */
|
||||
};
|
||||
|
||||
struct hal2_vol_regs {
|
||||
u32 right; /* Right volume */
|
||||
u32 left; /* Left volume */
|
||||
};
|
||||
|
||||
struct hal2_syn_regs {
|
||||
u32 _unused0[2];
|
||||
u32 page; /* DOC Page register */
|
||||
u32 regsel; /* DOC Register selection */
|
||||
u32 dlow; /* DOC Data low */
|
||||
u32 dhigh; /* DOC Data high */
|
||||
u32 irq; /* IRQ Status */
|
||||
u32 dram; /* DRAM Access */
|
||||
};
|
||||
|
||||
#endif /* __HAL2_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -7,7 +7,7 @@
|
|||
|
||||
config SOUND_BCM_CS4297A
|
||||
tristate "Crystal Sound CS4297a (for Swarm)"
|
||||
depends on SOUND_PRIME && SIBYTE_SWARM
|
||||
depends on SIBYTE_SWARM
|
||||
help
|
||||
The BCM91250A has a Crystal CS4297a on synchronous serial
|
||||
port B (in addition to the DB-9 serial port). Say Y or M
|
||||
|
@ -17,7 +17,7 @@ config SOUND_BCM_CS4297A
|
|||
|
||||
config SOUND_VWSND
|
||||
tristate "SGI Visual Workstation Sound"
|
||||
depends on SOUND_PRIME && X86_VISWS
|
||||
depends on X86_VISWS
|
||||
help
|
||||
Say Y or M if you have an SGI Visual Workstation and you want to be
|
||||
able to use its on-board audio. Read
|
||||
|
@ -26,19 +26,18 @@ config SOUND_VWSND
|
|||
|
||||
config SOUND_HAL2
|
||||
tristate "SGI HAL2 sound (EXPERIMENTAL)"
|
||||
depends on SOUND_PRIME && SGI_IP22 && EXPERIMENTAL
|
||||
depends on SGI_IP22 && EXPERIMENTAL
|
||||
help
|
||||
Say Y or M if you have an SGI Indy or Indigo2 system and want to be able to
|
||||
use its on-board A2 audio system.
|
||||
|
||||
config SOUND_AU1550_AC97
|
||||
tristate "Au1550/Au1200 AC97 Sound"
|
||||
select SND_AC97_CODEC
|
||||
depends on SOUND_PRIME && (SOC_AU1550 || SOC_AU1200)
|
||||
depends on SOC_AU1550 || SOC_AU1200
|
||||
|
||||
config SOUND_TRIDENT
|
||||
tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core"
|
||||
depends on SOUND_PRIME && PCI
|
||||
depends on PCI
|
||||
---help---
|
||||
Say Y or M if you have a PCI sound card utilizing the Trident
|
||||
4DWave-DX/NX chipset or your mother board chipset has SiS 7018
|
||||
|
@ -79,7 +78,7 @@ config SOUND_TRIDENT
|
|||
|
||||
config SOUND_MSNDCLAS
|
||||
tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
|
||||
depends on SOUND_PRIME && (m || !STANDALONE) && ISA
|
||||
depends on (m || !STANDALONE) && ISA
|
||||
help
|
||||
Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or
|
||||
Monterey (not for the Pinnacle or Fiji).
|
||||
|
@ -143,7 +142,7 @@ config MSNDCLAS_IO
|
|||
|
||||
config SOUND_MSNDPIN
|
||||
tristate "Support for Turtle Beach MultiSound Pinnacle, Fiji"
|
||||
depends on SOUND_PRIME && (m || !STANDALONE) && ISA
|
||||
depends on (m || !STANDALONE) && ISA
|
||||
help
|
||||
Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji.
|
||||
See <file:Documentation/sound/oss/MultiSound> for important information
|
||||
|
@ -229,7 +228,7 @@ config MSNDPIN_NONPNP
|
|||
configure the card's resources.
|
||||
|
||||
comment "MSND Pinnacle DSP section will be configured to above parameters."
|
||||
depends on SOUND_PRIME && SOUND_MSNDPIN=y && MSNDPIN_NONPNP
|
||||
depends on SOUND_MSNDPIN=y && MSNDPIN_NONPNP
|
||||
|
||||
config MSNDPIN_CFG
|
||||
hex "MSND Pinnacle config port 250,260,270"
|
||||
|
@ -242,7 +241,7 @@ config MSNDPIN_CFG
|
|||
Mode".
|
||||
|
||||
comment "Pinnacle-specific Device Configuration (0 disables)"
|
||||
depends on SOUND_PRIME && SOUND_MSNDPIN=y && MSNDPIN_NONPNP
|
||||
depends on SOUND_MSNDPIN=y && MSNDPIN_NONPNP
|
||||
|
||||
config MSNDPIN_MPU_IO
|
||||
hex "MSND Pinnacle MPU I/O (e.g. 330)"
|
||||
|
@ -294,7 +293,7 @@ config MSNDPIN_JOYSTICK_IO
|
|||
|
||||
config MSND_FIFOSIZE
|
||||
int "MSND buffer size (kB)"
|
||||
depends on SOUND_PRIME && (SOUND_MSNDPIN=y || SOUND_MSNDCLAS=y)
|
||||
depends on SOUND_MSNDPIN=y || SOUND_MSNDCLAS=y
|
||||
default "128"
|
||||
help
|
||||
Configures the size of each audio buffer, in kilobytes, for
|
||||
|
@ -302,9 +301,9 @@ config MSND_FIFOSIZE
|
|||
and Pinnacle). Larger values reduce the chance of data overruns at
|
||||
the expense of overall latency. If unsure, use the default.
|
||||
|
||||
config SOUND_OSS
|
||||
menuconfig SOUND_OSS
|
||||
tristate "OSS sound modules"
|
||||
depends on SOUND_PRIME && ISA_DMA_API && VIRT_TO_BUS
|
||||
depends on ISA_DMA_API && VIRT_TO_BUS
|
||||
help
|
||||
OSS is the Open Sound System suite of sound card drivers. They make
|
||||
sound programming easier since they provide a common API. Say Y or
|
||||
|
@ -312,16 +311,16 @@ config SOUND_OSS
|
|||
driver for your sound card above, then pick your driver from the
|
||||
list below.
|
||||
|
||||
if SOUND_OSS
|
||||
|
||||
config SOUND_TRACEINIT
|
||||
bool "Verbose initialisation"
|
||||
depends on SOUND_OSS
|
||||
help
|
||||
Verbose soundcard initialization -- affects the format of autoprobe
|
||||
and initialization messages at boot time.
|
||||
|
||||
config SOUND_DMAP
|
||||
bool "Persistent DMA buffers"
|
||||
depends on SOUND_OSS
|
||||
---help---
|
||||
Linux can often have problems allocating DMA buffers for ISA sound
|
||||
cards on machines with more than 16MB of RAM. This is because ISA
|
||||
|
@ -338,8 +337,6 @@ config SOUND_DMAP
|
|||
|
||||
config SOUND_SSCAPE
|
||||
tristate "Ensoniq SoundScape support"
|
||||
depends on SOUND_OSS
|
||||
depends on VIRT_TO_BUS
|
||||
help
|
||||
Answer Y if you have a sound card based on the Ensoniq SoundScape
|
||||
chipset. Such cards are being manufactured at least by Ensoniq, Spea
|
||||
|
@ -352,13 +349,11 @@ config SOUND_SSCAPE
|
|||
|
||||
config SOUND_VMIDI
|
||||
tristate "Loopback MIDI device support"
|
||||
depends on SOUND_OSS
|
||||
help
|
||||
Support for MIDI loopback on port 1 or 2.
|
||||
|
||||
config SOUND_TRIX
|
||||
tristate "MediaTrix AudioTrix Pro support"
|
||||
depends on SOUND_OSS
|
||||
help
|
||||
Answer Y if you have the AudioTriX Pro sound card manufactured
|
||||
by MediaTrix.
|
||||
|
@ -382,7 +377,6 @@ config TRIX_BOOT_FILE
|
|||
|
||||
config SOUND_MSS
|
||||
tristate "Microsoft Sound System support"
|
||||
depends on SOUND_OSS
|
||||
---help---
|
||||
Again think carefully before answering Y to this question. It's
|
||||
safe to answer Y if you have the original Windows Sound System card
|
||||
|
@ -414,7 +408,6 @@ config SOUND_MSS
|
|||
|
||||
config SOUND_MPU401
|
||||
tristate "MPU-401 support (NOT for SB16)"
|
||||
depends on SOUND_OSS
|
||||
---help---
|
||||
Be careful with this question. The MPU401 interface is supported by
|
||||
all sound cards. However, some natively supported cards have their
|
||||
|
@ -430,7 +423,6 @@ config SOUND_MPU401
|
|||
|
||||
config SOUND_PAS
|
||||
tristate "ProAudioSpectrum 16 support"
|
||||
depends on SOUND_OSS
|
||||
---help---
|
||||
Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio
|
||||
16 or Logitech SoundMan 16 sound card. Answer N if you have some
|
||||
|
@ -452,7 +444,6 @@ config PAS_JOYSTICK
|
|||
|
||||
config SOUND_PSS
|
||||
tristate "PSS (AD1848, ADSP-2115, ESC614) support"
|
||||
depends on SOUND_OSS
|
||||
help
|
||||
Answer Y or M if you have an Orchid SW32, Cardinal DSP16, Beethoven
|
||||
ADSP-16 or some other card based on the PSS chipset (AD1848 codec +
|
||||
|
@ -495,7 +486,6 @@ config PSS_BOOT_FILE
|
|||
|
||||
config SOUND_SB
|
||||
tristate "100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support"
|
||||
depends on SOUND_OSS
|
||||
---help---
|
||||
Answer Y if you have an original Sound Blaster card made by Creative
|
||||
Labs or a 100% hardware compatible clone (like the Thunderboard or
|
||||
|
@ -522,7 +512,6 @@ config SOUND_SB
|
|||
|
||||
config SOUND_YM3812
|
||||
tristate "Yamaha FM synthesizer (YM3812/OPL-3) support"
|
||||
depends on SOUND_OSS
|
||||
---help---
|
||||
Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
|
||||
Answering Y is usually a safe and recommended choice, however some
|
||||
|
@ -538,7 +527,6 @@ config SOUND_YM3812
|
|||
|
||||
config SOUND_UART6850
|
||||
tristate "6850 UART support"
|
||||
depends on SOUND_OSS
|
||||
help
|
||||
This option enables support for MIDI interfaces based on the 6850
|
||||
UART chip. This interface is rarely found on sound cards. It's safe
|
||||
|
@ -549,7 +537,6 @@ config SOUND_UART6850
|
|||
|
||||
config SOUND_AEDSP16
|
||||
tristate "Gallant Audio Cards (SC-6000 and SC-6600 based)"
|
||||
depends on SOUND_OSS
|
||||
---help---
|
||||
Answer Y if you have a Gallant's Audio Excel DSP 16 card. This
|
||||
driver supports Audio Excel DSP 16 but not the III nor PnP versions
|
||||
|
@ -630,14 +617,14 @@ endchoice
|
|||
|
||||
config SOUND_VIDC
|
||||
tristate "VIDC 16-bit sound"
|
||||
depends on ARM && (ARCH_ACORN || ARCH_CLPS7500) && SOUND_OSS
|
||||
depends on ARM && (ARCH_ACORN || ARCH_CLPS7500)
|
||||
help
|
||||
16-bit support for the VIDC onboard sound hardware found on Acorn
|
||||
machines.
|
||||
|
||||
config SOUND_WAVEARTIST
|
||||
tristate "Netwinder WaveArtist"
|
||||
depends on ARM && SOUND_OSS && ARCH_NETWINDER
|
||||
depends on ARM && ARCH_NETWINDER
|
||||
help
|
||||
Say Y here to include support for the Rockwell WaveArtist sound
|
||||
system. This driver is mainly for the NetWinder.
|
||||
|
@ -646,9 +633,11 @@ config SOUND_KAHLUA
|
|||
tristate "XpressAudio Sound Blaster emulation"
|
||||
depends on SOUND_SB
|
||||
|
||||
endif # SOUND_OSS
|
||||
|
||||
config SOUND_SH_DAC_AUDIO
|
||||
tristate "SuperH DAC audio support"
|
||||
depends on SOUND_PRIME && CPU_SH3
|
||||
depends on CPU_SH3
|
||||
|
||||
config SOUND_SH_DAC_AUDIO_CHANNEL
|
||||
int "DAC channel"
|
||||
|
|
|
@ -211,10 +211,6 @@ static int state_unit = -1;
|
|||
static int irq_installed;
|
||||
#endif /* MODULE */
|
||||
|
||||
/* software implemented recording volume! */
|
||||
uint software_input_volume = SW_INPUT_VOLUME_SCALE * SW_INPUT_VOLUME_DEFAULT;
|
||||
EXPORT_SYMBOL(software_input_volume);
|
||||
|
||||
/* control over who can modify resources shared between play/record */
|
||||
static mode_t shared_resource_owner;
|
||||
static int shared_resources_initialised;
|
||||
|
@ -1188,7 +1184,7 @@ static struct {
|
|||
|
||||
/* publish this function for use by low-level code, if required */
|
||||
|
||||
char *get_afmt_string(int afmt)
|
||||
static char *get_afmt_string(int afmt)
|
||||
{
|
||||
switch(afmt) {
|
||||
case AFMT_MU_LAW:
|
||||
|
@ -1551,4 +1547,3 @@ EXPORT_SYMBOL(dmasound_catchRadius);
|
|||
EXPORT_SYMBOL(dmasound_ulaw2dma8);
|
||||
EXPORT_SYMBOL(dmasound_alaw2dma8);
|
||||
#endif
|
||||
EXPORT_SYMBOL(get_afmt_string) ;
|
||||
|
|
|
@ -710,7 +710,7 @@ static MACHINE machAmiga = {
|
|||
/*** Config & Setup **********************************************************/
|
||||
|
||||
|
||||
int __init dmasound_paula_init(void)
|
||||
static int __init dmasound_paula_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
|
|
@ -611,7 +611,7 @@ static MACHINE machQ40 = {
|
|||
/*** Config & Setup **********************************************************/
|
||||
|
||||
|
||||
int __init dmasound_q40_init(void)
|
||||
static int __init dmasound_q40_init(void)
|
||||
{
|
||||
if (MACH_IS_Q40) {
|
||||
dmasound.mach = machQ40;
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: msnd.c,v 1.17 1999/03/21 16:50:09 andrewtv Exp $
|
||||
*
|
||||
********************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: msnd.h,v 1.36 1999/03/21 17:05:42 andrewtv Exp $
|
||||
*
|
||||
********************************************************************/
|
||||
#ifndef __MSND_H
|
||||
#define __MSND_H
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: msnd_classic.h,v 1.10 1999/03/21 17:36:09 andrewtv Exp $
|
||||
*
|
||||
********************************************************************/
|
||||
#ifndef __MSND_CLASSIC_H
|
||||
#define __MSND_CLASSIC_H
|
||||
|
|
|
@ -29,13 +29,8 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: msnd_pinnacle.c,v 1.8 2000/12/30 00:33:21 sycamore Exp $
|
||||
*
|
||||
* 12-3-2000 Modified IO port validation Steve Sycamore
|
||||
*
|
||||
*
|
||||
* $$$: msnd_pinnacle.c,v 1.75 1999/03/21 16:50:09 andrewtv $$$ $
|
||||
*
|
||||
********************************************************************/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: msnd_pinnacle.h,v 1.11 1999/03/21 17:36:09 andrewtv Exp $
|
||||
*
|
||||
********************************************************************/
|
||||
#ifndef __MSND_PINNACLE_H
|
||||
#define __MSND_PINNACLE_H
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
# ALSA PA-RISC drivers
|
||||
|
||||
menu "GSC devices"
|
||||
depends on SND!=n && GSC
|
||||
menuconfig SND_GSC
|
||||
bool "GSC sound devices"
|
||||
depends on GSC
|
||||
default y
|
||||
help
|
||||
Support for GSC sound devices on PA-RISC architectures.
|
||||
|
||||
if SND_GSC
|
||||
|
||||
config SND_HARMONY
|
||||
tristate "Harmony/Vivace sound chip"
|
||||
depends on SND
|
||||
select SND_PCM
|
||||
help
|
||||
Say 'Y' or 'M' to include support for the Harmony/Vivace sound
|
||||
chip found in most GSC-based PA-RISC workstations. It's frequently
|
||||
provided as part of the Lasi multi-function IC.
|
||||
|
||||
endmenu
|
||||
endif # SND_GSC
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
# ALSA PCI drivers
|
||||
|
||||
menu "PCI devices"
|
||||
depends on SND!=n && PCI
|
||||
menuconfig SND_PCI
|
||||
bool "PCI sound devices"
|
||||
depends on PCI
|
||||
default y
|
||||
help
|
||||
Support for sound devices connected via the PCI bus.
|
||||
|
||||
if SND_PCI
|
||||
|
||||
config SND_AD1889
|
||||
tristate "Analog Devices AD1889"
|
||||
depends on SND
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
Say Y here to include support for the integrated AC97 sound
|
||||
|
@ -17,7 +22,6 @@ config SND_AD1889
|
|||
|
||||
config SND_ALS300
|
||||
tristate "Avance Logic ALS300/ALS300+"
|
||||
depends on SND
|
||||
select SND_PCM
|
||||
select SND_AC97_CODEC
|
||||
select SND_OPL3_LIB
|
||||
|
@ -29,7 +33,7 @@ config SND_ALS300
|
|||
|
||||
config SND_ALS4000
|
||||
tristate "Avance Logic ALS4000"
|
||||
depends on SND && ISA_DMA_API
|
||||
depends on ISA_DMA_API
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_PCM
|
||||
|
@ -43,7 +47,6 @@ config SND_ALS4000
|
|||
|
||||
config SND_ALI5451
|
||||
tristate "ALi M5451 PCI Audio Controller"
|
||||
depends on SND
|
||||
select SND_MPU401_UART
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
|
@ -57,7 +60,6 @@ config SND_ALI5451
|
|||
|
||||
config SND_ATIIXP
|
||||
tristate "ATI IXP AC97 Controller"
|
||||
depends on SND
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
Say Y here to include support for the integrated AC97 sound
|
||||
|
@ -69,7 +71,6 @@ config SND_ATIIXP
|
|||
|
||||
config SND_ATIIXP_MODEM
|
||||
tristate "ATI IXP Modem"
|
||||
depends on SND
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
Say Y here to include support for the integrated MC97 modem on
|
||||
|
@ -80,7 +81,6 @@ config SND_ATIIXP_MODEM
|
|||
|
||||
config SND_AU8810
|
||||
tristate "Aureal Advantage"
|
||||
depends on SND
|
||||
select SND_MPU401_UART
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
|
@ -95,7 +95,6 @@ config SND_AU8810
|
|||
|
||||
config SND_AU8820
|
||||
tristate "Aureal Vortex"
|
||||
depends on SND
|
||||
select SND_MPU401_UART
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
|
@ -109,7 +108,6 @@ config SND_AU8820
|
|||
|
||||
config SND_AU8830
|
||||
tristate "Aureal Vortex 2"
|
||||
depends on SND
|
||||
select SND_MPU401_UART
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
|
@ -124,7 +122,6 @@ config SND_AU8830
|
|||
|
||||
config SND_AW2
|
||||
tristate "Emagic Audiowerk 2"
|
||||
depends on SND
|
||||
help
|
||||
Say Y here to include support for Emagic Audiowerk 2 soundcards.
|
||||
|
||||
|
@ -139,7 +136,7 @@ config SND_AW2
|
|||
|
||||
config SND_AZT3328
|
||||
tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)"
|
||||
depends on SND && EXPERIMENTAL
|
||||
depends on EXPERIMENTAL
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_PCM
|
||||
|
@ -152,7 +149,6 @@ config SND_AZT3328
|
|||
|
||||
config SND_BT87X
|
||||
tristate "Bt87x Audio Capture"
|
||||
depends on SND
|
||||
select SND_PCM
|
||||
help
|
||||
If you want to record audio from TV cards based on
|
||||
|
@ -174,7 +170,6 @@ config SND_BT87X_OVERCLOCK
|
|||
|
||||
config SND_CA0106
|
||||
tristate "SB Audigy LS / Live 24bit"
|
||||
depends on SND
|
||||
select SND_AC97_CODEC
|
||||
select SND_RAWMIDI
|
||||
select SND_VMASTER
|
||||
|
@ -187,7 +182,6 @@ config SND_CA0106
|
|||
|
||||
config SND_CMIPCI
|
||||
tristate "C-Media 8338, 8738, 8768, 8770"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_PCM
|
||||
|
@ -201,13 +195,11 @@ config SND_CMIPCI
|
|||
|
||||
config SND_OXYGEN_LIB
|
||||
tristate
|
||||
depends on SND
|
||||
select SND_PCM
|
||||
select SND_MPU401_UART
|
||||
|
||||
config SND_OXYGEN
|
||||
tristate "C-Media 8788 (Oxygen)"
|
||||
depends on SND
|
||||
select SND_OXYGEN_LIB
|
||||
help
|
||||
Say Y here to include support for sound cards based on the
|
||||
|
@ -225,7 +217,6 @@ config SND_OXYGEN
|
|||
|
||||
config SND_CS4281
|
||||
tristate "Cirrus Logic (Sound Fusion) CS4281"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_RAWMIDI
|
||||
select SND_AC97_CODEC
|
||||
|
@ -237,7 +228,6 @@ config SND_CS4281
|
|||
|
||||
config SND_CS46XX
|
||||
tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x"
|
||||
depends on SND
|
||||
select SND_RAWMIDI
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
|
@ -258,7 +248,7 @@ config SND_CS46XX_NEW_DSP
|
|||
|
||||
config SND_CS5530
|
||||
tristate "CS5530 Audio"
|
||||
depends on SND && ISA_DMA_API
|
||||
depends on ISA_DMA_API
|
||||
select SND_SB16_DSP
|
||||
help
|
||||
Say Y here to include support for audio on Cyrix/NatSemi CS5530 chips.
|
||||
|
@ -268,7 +258,7 @@ config SND_CS5530
|
|||
|
||||
config SND_CS5535AUDIO
|
||||
tristate "CS5535/CS5536 Audio"
|
||||
depends on SND && X86 && !X86_64
|
||||
depends on X86 && !X86_64
|
||||
select SND_PCM
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
|
@ -286,7 +276,6 @@ config SND_CS5535AUDIO
|
|||
|
||||
config SND_DARLA20
|
||||
tristate "(Echoaudio) Darla20"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
|
@ -297,7 +286,6 @@ config SND_DARLA20
|
|||
|
||||
config SND_GINA20
|
||||
tristate "(Echoaudio) Gina20"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
|
@ -308,7 +296,6 @@ config SND_GINA20
|
|||
|
||||
config SND_LAYLA20
|
||||
tristate "(Echoaudio) Layla20"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
|
@ -320,7 +307,6 @@ config SND_LAYLA20
|
|||
|
||||
config SND_DARLA24
|
||||
tristate "(Echoaudio) Darla24"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
|
@ -331,7 +317,6 @@ config SND_DARLA24
|
|||
|
||||
config SND_GINA24
|
||||
tristate "(Echoaudio) Gina24"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
|
@ -342,7 +327,6 @@ config SND_GINA24
|
|||
|
||||
config SND_LAYLA24
|
||||
tristate "(Echoaudio) Layla24"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
|
@ -354,7 +338,6 @@ config SND_LAYLA24
|
|||
|
||||
config SND_MONA
|
||||
tristate "(Echoaudio) Mona"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
|
@ -366,7 +349,6 @@ config SND_MONA
|
|||
|
||||
config SND_MIA
|
||||
tristate "(Echoaudio) Mia"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
|
@ -378,7 +360,6 @@ config SND_MIA
|
|||
|
||||
config SND_ECHO3G
|
||||
tristate "(Echoaudio) 3G cards"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
|
@ -390,7 +371,6 @@ config SND_ECHO3G
|
|||
|
||||
config SND_INDIGO
|
||||
tristate "(Echoaudio) Indigo"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
|
@ -401,7 +381,6 @@ config SND_INDIGO
|
|||
|
||||
config SND_INDIGOIO
|
||||
tristate "(Echoaudio) Indigo IO"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
|
@ -412,7 +391,6 @@ config SND_INDIGOIO
|
|||
|
||||
config SND_INDIGODJ
|
||||
tristate "(Echoaudio) Indigo DJ"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_PCM
|
||||
help
|
||||
|
@ -423,7 +401,6 @@ config SND_INDIGODJ
|
|||
|
||||
config SND_EMU10K1
|
||||
tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_HWDEP
|
||||
select SND_RAWMIDI
|
||||
|
@ -441,7 +418,6 @@ config SND_EMU10K1
|
|||
|
||||
config SND_EMU10K1X
|
||||
tristate "Emu10k1X (Dell OEM Version)"
|
||||
depends on SND
|
||||
select SND_AC97_CODEC
|
||||
select SND_RAWMIDI
|
||||
help
|
||||
|
@ -453,7 +429,6 @@ config SND_EMU10K1X
|
|||
|
||||
config SND_ENS1370
|
||||
tristate "(Creative) Ensoniq AudioPCI 1370"
|
||||
depends on SND
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
help
|
||||
|
@ -464,7 +439,6 @@ config SND_ENS1370
|
|||
|
||||
config SND_ENS1371
|
||||
tristate "(Creative) Ensoniq AudioPCI 1371/1373"
|
||||
depends on SND
|
||||
select SND_RAWMIDI
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
|
@ -476,7 +450,6 @@ config SND_ENS1371
|
|||
|
||||
config SND_ES1938
|
||||
tristate "ESS ES1938/1946/1969 (Solo-1)"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_AC97_CODEC
|
||||
|
@ -489,7 +462,6 @@ config SND_ES1938
|
|||
|
||||
config SND_ES1968
|
||||
tristate "ESS ES1968/1978 (Maestro-1/2/2E)"
|
||||
depends on SND
|
||||
select SND_MPU401_UART
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
|
@ -501,7 +473,6 @@ config SND_ES1968
|
|||
|
||||
config SND_FM801
|
||||
tristate "ForteMedia FM801"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_AC97_CODEC
|
||||
|
@ -528,7 +499,6 @@ config SND_FM801_TEA575X
|
|||
|
||||
config SND_HDA_INTEL
|
||||
tristate "Intel HD Audio"
|
||||
depends on SND
|
||||
select SND_PCM
|
||||
select SND_VMASTER
|
||||
help
|
||||
|
@ -637,7 +607,6 @@ config SND_HDA_POWER_SAVE_DEFAULT
|
|||
|
||||
config SND_HDSP
|
||||
tristate "RME Hammerfall DSP Audio"
|
||||
depends on SND
|
||||
select SND_HWDEP
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
|
@ -650,7 +619,6 @@ config SND_HDSP
|
|||
|
||||
config SND_HDSPM
|
||||
tristate "RME Hammerfall DSP MADI"
|
||||
depends on SND
|
||||
select SND_HWDEP
|
||||
select SND_RAWMIDI
|
||||
select SND_PCM
|
||||
|
@ -663,7 +631,6 @@ config SND_HDSPM
|
|||
|
||||
config SND_HIFIER
|
||||
tristate "TempoTec HiFier Fantasia"
|
||||
depends on SND
|
||||
select SND_OXYGEN_LIB
|
||||
help
|
||||
Say Y here to include support for the MediaTek/TempoTec HiFier
|
||||
|
@ -674,7 +641,6 @@ config SND_HIFIER
|
|||
|
||||
config SND_ICE1712
|
||||
tristate "ICEnsemble ICE1712 (Envy24)"
|
||||
depends on SND
|
||||
select SND_MPU401_UART
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
|
@ -691,8 +657,7 @@ config SND_ICE1712
|
|||
|
||||
config SND_ICE1724
|
||||
tristate "ICE/VT1724/1720 (Envy24HT/PT)"
|
||||
depends on SND
|
||||
select SND_MPU401_UART
|
||||
select SND_RAWMIDI
|
||||
select SND_AC97_CODEC
|
||||
select SND_VMASTER
|
||||
help
|
||||
|
@ -709,7 +674,6 @@ config SND_ICE1724
|
|||
|
||||
config SND_INTEL8X0
|
||||
tristate "Intel/SiS/nVidia/AMD/ALi AC97 Controller"
|
||||
depends on SND
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
Say Y here to include support for the integrated AC97 sound
|
||||
|
@ -722,7 +686,6 @@ config SND_INTEL8X0
|
|||
|
||||
config SND_INTEL8X0M
|
||||
tristate "Intel/SiS/nVidia/AMD MC97 Modem"
|
||||
depends on SND
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
Say Y here to include support for the integrated MC97 modem on
|
||||
|
@ -733,7 +696,6 @@ config SND_INTEL8X0M
|
|||
|
||||
config SND_KORG1212
|
||||
tristate "Korg 1212 IO"
|
||||
depends on SND
|
||||
select FW_LOADER if !SND_KORG1212_FIRMWARE_IN_KERNEL
|
||||
select SND_PCM
|
||||
help
|
||||
|
@ -753,7 +715,6 @@ config SND_KORG1212_FIRMWARE_IN_KERNEL
|
|||
|
||||
config SND_MAESTRO3
|
||||
tristate "ESS Allegro/Maestro3"
|
||||
depends on SND
|
||||
select FW_LOADER if !SND_MAESTRO3_FIRMWARE_IN_KERNEL
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
|
@ -774,7 +735,6 @@ config SND_MAESTRO3_FIRMWARE_IN_KERNEL
|
|||
|
||||
config SND_MIXART
|
||||
tristate "Digigram miXart"
|
||||
depends on SND
|
||||
select SND_HWDEP
|
||||
select SND_PCM
|
||||
help
|
||||
|
@ -786,7 +746,6 @@ config SND_MIXART
|
|||
|
||||
config SND_NM256
|
||||
tristate "NeoMagic NM256AV/ZX"
|
||||
depends on SND
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
Say Y here to include support for NeoMagic NM256AV/ZX chips.
|
||||
|
@ -796,7 +755,6 @@ config SND_NM256
|
|||
|
||||
config SND_PCXHR
|
||||
tristate "Digigram PCXHR"
|
||||
depends on SND
|
||||
select SND_PCM
|
||||
select SND_HWDEP
|
||||
help
|
||||
|
@ -807,7 +765,6 @@ config SND_PCXHR
|
|||
|
||||
config SND_RIPTIDE
|
||||
tristate "Conexant Riptide"
|
||||
depends on SND
|
||||
select FW_LOADER
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
|
@ -820,7 +777,6 @@ config SND_RIPTIDE
|
|||
|
||||
config SND_RME32
|
||||
tristate "RME Digi32, 32/8, 32 PRO"
|
||||
depends on SND
|
||||
select SND_PCM
|
||||
help
|
||||
Say Y to include support for RME Digi32, Digi32 PRO and
|
||||
|
@ -832,7 +788,6 @@ config SND_RME32
|
|||
|
||||
config SND_RME96
|
||||
tristate "RME Digi96, 96/8, 96/8 PRO"
|
||||
depends on SND
|
||||
select SND_PCM
|
||||
help
|
||||
Say Y here to include support for RME Digi96, Digi96/8 and
|
||||
|
@ -843,7 +798,6 @@ config SND_RME96
|
|||
|
||||
config SND_RME9652
|
||||
tristate "RME Digi9652 (Hammerfall)"
|
||||
depends on SND
|
||||
select SND_PCM
|
||||
help
|
||||
Say Y here to include support for RME Hammerfall (RME
|
||||
|
@ -854,7 +808,7 @@ config SND_RME9652
|
|||
|
||||
config SND_SIS7019
|
||||
tristate "SiS 7019 Audio Accelerator"
|
||||
depends on SND && X86 && !X86_64
|
||||
depends on X86 && !X86_64
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
Say Y here to include support for the SiS 7019 Audio Accelerator.
|
||||
|
@ -864,7 +818,6 @@ config SND_SIS7019
|
|||
|
||||
config SND_SONICVIBES
|
||||
tristate "S3 SonicVibes"
|
||||
depends on SND
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
select SND_AC97_CODEC
|
||||
|
@ -877,7 +830,6 @@ config SND_SONICVIBES
|
|||
|
||||
config SND_TRIDENT
|
||||
tristate "Trident 4D-Wave DX/NX; SiS 7018"
|
||||
depends on SND
|
||||
select SND_MPU401_UART
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
|
@ -889,7 +841,6 @@ config SND_TRIDENT
|
|||
|
||||
config SND_VIA82XX
|
||||
tristate "VIA 82C686A/B, 8233/8235 AC97 Controller"
|
||||
depends on SND
|
||||
select SND_MPU401_UART
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
|
@ -901,7 +852,6 @@ config SND_VIA82XX
|
|||
|
||||
config SND_VIA82XX_MODEM
|
||||
tristate "VIA 82C686A/B, 8233 based Modems"
|
||||
depends on SND
|
||||
select SND_AC97_CODEC
|
||||
help
|
||||
Say Y here to include support for the integrated MC97 modem on
|
||||
|
@ -912,7 +862,6 @@ config SND_VIA82XX_MODEM
|
|||
|
||||
config SND_VIRTUOSO
|
||||
tristate "Asus Virtuoso 100/200 (Xonar)"
|
||||
depends on SND
|
||||
select SND_OXYGEN_LIB
|
||||
help
|
||||
Say Y here to include support for sound cards based on the
|
||||
|
@ -923,7 +872,6 @@ config SND_VIRTUOSO
|
|||
|
||||
config SND_VX222
|
||||
tristate "Digigram VX222"
|
||||
depends on SND
|
||||
select SND_VX_LIB
|
||||
help
|
||||
Say Y here to include support for Digigram VX222 soundcards.
|
||||
|
@ -933,7 +881,6 @@ config SND_VX222
|
|||
|
||||
config SND_YMFPCI
|
||||
tristate "Yamaha YMF724/740/744/754"
|
||||
depends on SND
|
||||
select FW_LOADER if !SND_YMFPCI_FIRMWARE_IN_KERNEL
|
||||
select SND_OPL3_LIB
|
||||
select SND_MPU401_UART
|
||||
|
@ -954,25 +901,4 @@ config SND_YMFPCI_FIRMWARE_IN_KERNEL
|
|||
for the YMFPCI driver. If you choose N here, you need to
|
||||
install the firmware files from the alsa-firmware package.
|
||||
|
||||
config SND_AC97_POWER_SAVE
|
||||
bool "AC97 Power-Saving Mode"
|
||||
depends on SND_AC97_CODEC && EXPERIMENTAL
|
||||
default n
|
||||
help
|
||||
Say Y here to enable the aggressive power-saving support of
|
||||
AC97 codecs. In this mode, the power-mode is dynamically
|
||||
controlled at each open/close.
|
||||
|
||||
The mode is activated by passing power_save=1 option to
|
||||
snd-ac97-codec driver. You can toggle it dynamically over
|
||||
sysfs, too.
|
||||
|
||||
config SND_AC97_POWER_SAVE_DEFAULT
|
||||
int "Default time-out for AC97 power-save mode"
|
||||
depends on SND_AC97_POWER_SAVE
|
||||
default 0
|
||||
help
|
||||
The default time-out value in seconds for AC97 automatic
|
||||
power-save mode. 0 means to disable the power-save mode.
|
||||
|
||||
endmenu
|
||||
endif # SND_PCI
|
||||
|
|
|
@ -13,7 +13,7 @@ snd-bt87x-objs := bt87x.o
|
|||
snd-cmipci-objs := cmipci.o
|
||||
snd-cs4281-objs := cs4281.o
|
||||
snd-cs5530-objs := cs5530.o
|
||||
snd-ens1370-objs := ens1370.o
|
||||
snd-ens1370-objs := ens1370.o ak4531_codec.o
|
||||
snd-ens1371-objs := ens1371.o
|
||||
snd-es1938-objs := es1938.o
|
||||
snd-es1968-objs := es1968.o
|
||||
|
|
|
@ -3,16 +3,8 @@
|
|||
# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
|
||||
#
|
||||
|
||||
snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o
|
||||
|
||||
ifneq ($(CONFIG_PROC_FS),)
|
||||
snd-ac97-codec-objs += ac97_proc.o
|
||||
endif
|
||||
|
||||
snd-ak4531-codec-objs := ak4531_codec.o
|
||||
snd-ac97-codec-y := ac97_codec.o ac97_pcm.o
|
||||
snd-ac97-codec-$(CONFIG_PROC_FS) += ac97_proc.o
|
||||
|
||||
# Toplevel Module Dependency
|
||||
obj-$(CONFIG_SND_AC97_CODEC) += snd-ac97-codec.o
|
||||
obj-$(CONFIG_SND_ENS1370) += snd-ak4531-codec.o
|
||||
|
||||
obj-m := $(sort $(obj-m))
|
||||
|
|
|
@ -49,8 +49,9 @@ MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control");
|
|||
|
||||
#ifdef CONFIG_SND_AC97_POWER_SAVE
|
||||
static int power_save = CONFIG_SND_AC97_POWER_SAVE_DEFAULT;
|
||||
module_param(power_save, bool, 0644);
|
||||
MODULE_PARM_DESC(power_save, "Enable AC97 power-saving control");
|
||||
module_param(power_save, int, 0644);
|
||||
MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
|
||||
"(in second, 0 = disable).");
|
||||
#endif
|
||||
/*
|
||||
|
||||
|
@ -2294,9 +2295,11 @@ static void snd_ac97_powerdown(struct snd_ac97 *ac97)
|
|||
power |= AC97_PD_PR0 | AC97_PD_PR1; /* ADC & DAC powerdown */
|
||||
snd_ac97_write(ac97, AC97_POWERDOWN, power);
|
||||
udelay(100);
|
||||
power |= AC97_PD_PR2 | AC97_PD_PR3; /* Analog Mixer powerdown */
|
||||
power |= AC97_PD_PR2; /* Analog Mixer powerdown (Vref on) */
|
||||
snd_ac97_write(ac97, AC97_POWERDOWN, power);
|
||||
if (ac97_is_power_save_mode(ac97)) {
|
||||
power |= AC97_PD_PR3; /* Analog Mixer powerdown */
|
||||
snd_ac97_write(ac97, AC97_POWERDOWN, power);
|
||||
udelay(100);
|
||||
/* AC-link powerdown, internal Clk disable */
|
||||
/* FIXME: this may cause click noises on some boards */
|
||||
|
@ -2362,7 +2365,7 @@ int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup)
|
|||
* that open/close frequently)
|
||||
*/
|
||||
schedule_delayed_work(&ac97->power_work,
|
||||
msecs_to_jiffies(2000));
|
||||
msecs_to_jiffies(power_save * 1000));
|
||||
else {
|
||||
cancel_delayed_work(&ac97->power_work);
|
||||
update_power_regs(ac97);
|
||||
|
|
|
@ -669,6 +669,7 @@ AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
|
|||
AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
|
||||
AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
|
||||
|
||||
AC97_SINGLE("Master Left Inv Switch", AC97_MASTER, 6, 1, 0),
|
||||
AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0),
|
||||
AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0),
|
||||
AC97_SINGLE("Mono ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
|
||||
|
@ -3352,8 +3353,66 @@ AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
|
|||
AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
|
||||
};
|
||||
|
||||
static const char *slave_vols_vt1616[] = {
|
||||
"Front Playback Volume",
|
||||
"Surround Playback Volume",
|
||||
"Center Playback Volume",
|
||||
"LFE Playback Volume",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *slave_sws_vt1616[] = {
|
||||
"Front Playback Switch",
|
||||
"Surround Playback Switch",
|
||||
"Center Playback Switch",
|
||||
"LFE Playback Switch",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* find a mixer control element with the given name */
|
||||
static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
|
||||
const char *name)
|
||||
{
|
||||
struct snd_ctl_elem_id id;
|
||||
memset(&id, 0, sizeof(id));
|
||||
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||
strcpy(id.name, name);
|
||||
return snd_ctl_find_id(ac97->bus->card, &id);
|
||||
}
|
||||
|
||||
/* create a virtual master control and add slaves */
|
||||
int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
|
||||
const unsigned int *tlv, const char **slaves)
|
||||
{
|
||||
struct snd_kcontrol *kctl;
|
||||
const char **s;
|
||||
int err;
|
||||
|
||||
kctl = snd_ctl_make_virtual_master(name, tlv);
|
||||
if (!kctl)
|
||||
return -ENOMEM;
|
||||
err = snd_ctl_add(ac97->bus->card, kctl);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (s = slaves; *s; s++) {
|
||||
struct snd_kcontrol *sctl;
|
||||
|
||||
sctl = snd_ac97_find_mixer_ctl(ac97, *s);
|
||||
if (!sctl) {
|
||||
snd_printdd("Cannot find slave %s, skipped\n", *s);
|
||||
continue;
|
||||
}
|
||||
err = snd_ctl_add_slave(kctl, sctl);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int patch_vt1616_specific(struct snd_ac97 * ac97)
|
||||
{
|
||||
struct snd_kcontrol *kctl;
|
||||
int err;
|
||||
|
||||
if (snd_ac97_try_bit(ac97, 0x5a, 9))
|
||||
|
@ -3361,6 +3420,24 @@ static int patch_vt1616_specific(struct snd_ac97 * ac97)
|
|||
return err;
|
||||
if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0)
|
||||
return err;
|
||||
|
||||
/* There is already a misnamed master switch. Rename it. */
|
||||
kctl = snd_ac97_find_mixer_ctl(ac97, "Master Playback Volume");
|
||||
if (!kctl)
|
||||
return -EINVAL;
|
||||
|
||||
snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Front Playback");
|
||||
|
||||
err = snd_ac97_add_vmaster(ac97, "Master Playback Volume",
|
||||
kctl->tlv.p, slave_vols_vt1616);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = snd_ac97_add_vmaster(ac97, "Master Playback Switch",
|
||||
NULL, slave_sws_vt1616);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3633,7 +3710,7 @@ static int patch_ucb1400(struct snd_ac97 * ac97)
|
|||
{
|
||||
ac97->build_ops = &patch_ucb1400_ops;
|
||||
/* enable headphone driver and smart low power mode by default */
|
||||
snd_ac97_write(ac97, 0x6a, 0x0050);
|
||||
snd_ac97_write(ac97, 0x6c, 0x0030);
|
||||
snd_ac97_write_cache(ac97, 0x6a, 0x0050);
|
||||
snd_ac97_write_cache(ac97, 0x6c, 0x0030);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -28,9 +28,11 @@
|
|||
#include <sound/ak4531_codec.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
/*
|
||||
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
|
||||
MODULE_DESCRIPTION("Universal routines for AK4531 codec");
|
||||
MODULE_LICENSE("GPL");
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531);
|
||||
|
@ -270,7 +272,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0);
|
|||
static const DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0);
|
||||
|
||||
static struct snd_kcontrol_new snd_ak4531_controls[] = {
|
||||
static struct snd_kcontrol_new snd_ak4531_controls[] __devinitdata = {
|
||||
|
||||
AK4531_DOUBLE_TLV("Master Playback Switch", 0,
|
||||
AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1,
|
||||
|
@ -379,8 +381,9 @@ static u8 snd_ak4531_initial_map[0x19 + 1] = {
|
|||
0x01 /* 19: Mic Amp Setup */
|
||||
};
|
||||
|
||||
int snd_ak4531_mixer(struct snd_card *card, struct snd_ak4531 *_ak4531,
|
||||
struct snd_ak4531 **rak4531)
|
||||
int __devinit snd_ak4531_mixer(struct snd_card *card,
|
||||
struct snd_ak4531 *_ak4531,
|
||||
struct snd_ak4531 **rak4531)
|
||||
{
|
||||
unsigned int idx;
|
||||
int err;
|
||||
|
@ -476,7 +479,8 @@ static void snd_ak4531_proc_read(struct snd_info_entry *entry,
|
|||
ak4531->regs[AK4531_MIC_GAIN] & 1 ? "+30dB" : "+0dB");
|
||||
}
|
||||
|
||||
static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531)
|
||||
static void __devinit
|
||||
snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531)
|
||||
{
|
||||
struct snd_info_entry *entry;
|
||||
|
||||
|
@ -484,25 +488,3 @@ static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak453
|
|||
snd_info_set_text_ops(entry, ak4531, snd_ak4531_proc_read);
|
||||
}
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(snd_ak4531_mixer);
|
||||
#ifdef CONFIG_PM
|
||||
EXPORT_SYMBOL(snd_ak4531_suspend);
|
||||
EXPORT_SYMBOL(snd_ak4531_resume);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* INIT part
|
||||
*/
|
||||
|
||||
static int __init alsa_ak4531_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit alsa_ak4531_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
module_init(alsa_ak4531_init)
|
||||
module_exit(alsa_ak4531_exit)
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* $Id: au88x0_game.c,v 1.9 2003/09/22 03:51:28 mjander Exp $
|
||||
*
|
||||
* Manuel Jander.
|
||||
*
|
||||
* Based on the work of:
|
||||
|
|
1243
sound/pci/azt3328.c
1243
sound/pci/azt3328.c
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,8 @@
|
|||
#ifndef __SOUND_AZT3328_H
|
||||
#define __SOUND_AZT3328_H
|
||||
|
||||
/* "PU" == "power-up value", as tested on PCI168 PCI rev. 10 */
|
||||
/* "PU" == "power-up value", as tested on PCI168 PCI rev. 10
|
||||
* "WRITE_ONLY" == register does not indicate actual bit values */
|
||||
|
||||
/*** main I/O area port indices ***/
|
||||
/* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */
|
||||
|
@ -54,7 +55,10 @@
|
|||
#define SOUNDFORMAT_XTAL1 0x00
|
||||
#define SOUNDFORMAT_XTAL2 0x01
|
||||
/* all _SUSPECTED_ values are not used by Windows drivers, so we don't
|
||||
* have any hard facts, only rough measurements */
|
||||
* have any hard facts, only rough measurements.
|
||||
* All we know is that the crystal used on the board has 24.576MHz,
|
||||
* like many soundcards (which results in the frequencies below when
|
||||
* using certain divider values selected by the values below) */
|
||||
#define SOUNDFORMAT_FREQ_SUSPECTED_4000 0x0c | SOUNDFORMAT_XTAL1
|
||||
#define SOUNDFORMAT_FREQ_SUSPECTED_4800 0x0a | SOUNDFORMAT_XTAL1
|
||||
#define SOUNDFORMAT_FREQ_5510 0x0c | SOUNDFORMAT_XTAL2
|
||||
|
@ -72,6 +76,26 @@
|
|||
#define SOUNDFORMAT_FLAG_16BIT 0x0010
|
||||
#define SOUNDFORMAT_FLAG_2CHANNELS 0x0020
|
||||
|
||||
/* define frequency helpers, for maximum value safety */
|
||||
enum azf_freq_t {
|
||||
#define AZF_FREQ(rate) AZF_FREQ_##rate = rate
|
||||
AZF_FREQ(4000),
|
||||
AZF_FREQ(4800),
|
||||
AZF_FREQ(5512),
|
||||
AZF_FREQ(6620),
|
||||
AZF_FREQ(8000),
|
||||
AZF_FREQ(9600),
|
||||
AZF_FREQ(11025),
|
||||
AZF_FREQ(13240),
|
||||
AZF_FREQ(16000),
|
||||
AZF_FREQ(22050),
|
||||
AZF_FREQ(32000),
|
||||
AZF_FREQ(44100),
|
||||
AZF_FREQ(48000),
|
||||
AZF_FREQ(66200),
|
||||
#undef AZF_FREQ
|
||||
} AZF_FREQUENCIES;
|
||||
|
||||
/** recording area (see also: playback bit flag definitions) **/
|
||||
#define IDX_IO_REC_FLAGS 0x20 /* ??, PU:0x0000 */
|
||||
#define IDX_IO_REC_IRQTYPE 0x22 /* ??, PU:0x0000 */
|
||||
|
@ -97,40 +121,171 @@
|
|||
|
||||
/** DirectX timer, main interrupt area (FIXME: and something else?) **/
|
||||
#define IDX_IO_TIMER_VALUE 0x60 /* found this timer area by pure luck :-) */
|
||||
#define TIMER_VALUE_MASK 0x000fffffUL /* timer countdown value; triggers IRQ when timer is finished */
|
||||
#define TIMER_ENABLE_COUNTDOWN 0x01000000UL /* activate the timer countdown */
|
||||
#define TIMER_ENABLE_IRQ 0x02000000UL /* trigger timer IRQ on zero transition */
|
||||
#define TIMER_ACK_IRQ 0x04000000UL /* being set in IRQ handler in case port 0x00 (hmm, not port 0x64!?!?) had 0x0020 set upon IRQ handler */
|
||||
/* timer countdown value; triggers IRQ when timer is finished */
|
||||
#define TIMER_VALUE_MASK 0x000fffffUL
|
||||
/* activate timer countdown */
|
||||
#define TIMER_COUNTDOWN_ENABLE 0x01000000UL
|
||||
/* trigger timer IRQ on zero transition */
|
||||
#define TIMER_IRQ_ENABLE 0x02000000UL
|
||||
/* being set in IRQ handler in case port 0x00 (hmm, not port 0x64!?!?)
|
||||
* had 0x0020 set upon IRQ handler */
|
||||
#define TIMER_IRQ_ACK 0x04000000UL
|
||||
#define IDX_IO_IRQSTATUS 0x64
|
||||
#define IRQ_PLAYBACK 0x0001
|
||||
#define IRQ_RECORDING 0x0002
|
||||
#define IRQ_MPU401 0x0010
|
||||
#define IRQ_TIMER 0x0020 /* DirectX timer */
|
||||
#define IRQ_UNKNOWN1 0x0040 /* probably unused, or possibly I2S port? or gameport IRQ? */
|
||||
#define IRQ_UNKNOWN2 0x0080 /* probably unused, or possibly I2S port? or gameport IRQ? */
|
||||
/* some IRQ bit in here might also be used to signal a power-management timer
|
||||
* timeout, to request shutdown of the chip (e.g. AD1815JS has such a thing).
|
||||
* Some OPL3 hardware (e.g. in LM4560) has some special timer hardware which
|
||||
* can trigger an OPL3 timer IRQ, so maybe there's such a thing as well... */
|
||||
|
||||
#define IRQ_PLAYBACK 0x0001
|
||||
#define IRQ_RECORDING 0x0002
|
||||
#define IRQ_UNKNOWN1 0x0004 /* most probably I2S port */
|
||||
#define IRQ_GAMEPORT 0x0008 /* Interrupt of Digital(ly) Enhanced Game Port */
|
||||
#define IRQ_MPU401 0x0010
|
||||
#define IRQ_TIMER 0x0020 /* DirectX timer */
|
||||
#define IRQ_UNKNOWN2 0x0040 /* probably unused, or possibly I2S port? */
|
||||
#define IRQ_UNKNOWN3 0x0080 /* probably unused, or possibly I2S port? */
|
||||
#define IDX_IO_66H 0x66 /* writing 0xffff returns 0x0000 */
|
||||
#define IDX_IO_SOME_VALUE 0x68 /* this is set to e.g. 0x3ff or 0x300, and writable; maybe some buffer limit, but I couldn't find out more, PU:0x00ff */
|
||||
#define IDX_IO_6AH 0x6A /* this WORD can be set to have bits 0x0028 activated (FIXME: correct??); actually inhibits PCM playback!!! maybe power management?? */
|
||||
#define IO_6A_PAUSE_PLAYBACK 0x0200 /* bit 9; sure, this pauses playback, but what the heck is this really about?? */
|
||||
#define IDX_IO_6CH 0x6C
|
||||
#define IDX_IO_6EH 0x6E /* writing 0xffff returns 0x83fe */
|
||||
/* further I/O indices not saved/restored, so probably not used */
|
||||
/* this is set to e.g. 0x3ff or 0x300, and writable;
|
||||
* maybe some buffer limit, but I couldn't find out more, PU:0x00ff: */
|
||||
#define IDX_IO_SOME_VALUE 0x68
|
||||
#define IO_68_RANDOM_TOGGLE1 0x0100 /* toggles randomly */
|
||||
#define IO_68_RANDOM_TOGGLE2 0x0200 /* toggles randomly */
|
||||
/* umm, nope, behaviour of these bits changes depending on what we wrote
|
||||
* to 0x6b!!
|
||||
* And they change upon playback/stop, too:
|
||||
* Writing a value to 0x68 will display this exact value during playback,
|
||||
* too but when stopped it can fall back to a rather different
|
||||
* seemingly random value). Hmm, possibly this is a register which
|
||||
* has a remote shadow which needs proper device supply which only exists
|
||||
* in case playback is active? Or is this driver-induced?
|
||||
*/
|
||||
|
||||
/* this WORD can be set to have bits 0x0028 activated (FIXME: correct??);
|
||||
* actually inhibits PCM playback!!! maybe power management??: */
|
||||
#define IDX_IO_6AH 0x6A /* WRITE_ONLY! */
|
||||
/* bit 5: enabling this will activate permanent counting of bytes 2/3
|
||||
* at gameport I/O (0xb402/3) (equal values each) and cause
|
||||
* gameport legacy I/O at 0x0200 to be _DISABLED_!
|
||||
* Is this Digital Enhanced Game Port Enable??? Or maybe it's Testmode
|
||||
* for Enhanced Digital Gameport (see 4D Wave DX card): */
|
||||
#define IO_6A_SOMETHING1_GAMEPORT 0x0020
|
||||
/* bit 8; sure, this _pauses_ playback (later resumes at same spot!),
|
||||
* but what the heck is this really about??: */
|
||||
#define IO_6A_PAUSE_PLAYBACK_BIT8 0x0100
|
||||
/* bit 9; sure, this _pauses_ playback (later resumes at same spot!),
|
||||
* but what the heck is this really about??: */
|
||||
#define IO_6A_PAUSE_PLAYBACK_BIT9 0x0200
|
||||
/* BIT8 and BIT9 are _NOT_ able to affect OPL3 MIDI playback,
|
||||
* thus it suggests influence on PCM only!!
|
||||
* However OTOH there seems to be no bit anywhere around here
|
||||
* which is able to disable OPL3... */
|
||||
/* bit 10: enabling this actually changes values at legacy gameport
|
||||
* I/O address (0x200); is this enabling of the Digital Enhanced Game Port???
|
||||
* Or maybe this simply switches off the NE558 circuit, since enabling this
|
||||
* still lets us evaluate button states, but not axis states */
|
||||
#define IO_6A_SOMETHING2_GAMEPORT 0x0400
|
||||
/* writing 0x0300: causes quite some crackling during
|
||||
* PC activity such as switching windows (PCI traffic??
|
||||
* --> FIFO/timing settings???) */
|
||||
/* writing 0x0100 plus/or 0x0200 inhibits playback */
|
||||
/* since the Windows .INF file has Flag_Enable_JoyStick and
|
||||
* Flag_Enable_SB_DOS_Emulation directly together, it stands to reason
|
||||
* that some other bit in this same register might be responsible
|
||||
* for SB DOS Emulation activation (note that the file did NOT define
|
||||
* a switch for OPL3!) */
|
||||
#define IDX_IO_6CH 0x6C /* unknown; fully read-writable */
|
||||
#define IDX_IO_6EH 0x6E
|
||||
/* writing 0xffff returns 0x83fe (or 0x03fe only).
|
||||
* writing 0x83 (and only 0x83!!) to 0x6f will cause 0x6c to switch
|
||||
* from 0000 to ffff. */
|
||||
|
||||
/* further I/O indices not saved/restored and not readable after writing,
|
||||
* so probably not used */
|
||||
|
||||
|
||||
/*** I/O 2 area port indices ***/
|
||||
/*** Gameport area port indices ***/
|
||||
/* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */
|
||||
#define AZF_IO_SIZE_IO2 0x08
|
||||
#define AZF_IO_SIZE_IO2_PM 0x06
|
||||
#define AZF_IO_SIZE_GAME 0x08
|
||||
#define AZF_IO_SIZE_GAME_PM 0x06
|
||||
|
||||
#define IDX_IO2_LEGACY_ADDR 0x04
|
||||
#define LEGACY_SOMETHING 0x01 /* OPL3?? */
|
||||
#define LEGACY_JOY 0x08
|
||||
enum {
|
||||
AZF_GAME_LEGACY_IO_PORT = 0x200
|
||||
} AZF_GAME_CONFIGS;
|
||||
|
||||
#define IDX_GAME_LEGACY_COMPATIBLE 0x00
|
||||
/* in some operation mode, writing anything to this port
|
||||
* triggers an interrupt:
|
||||
* yup, that's in case IDX_GAME_01H has one of the
|
||||
* axis measurement bits enabled
|
||||
* (and of course one needs to have GAME_HWCFG_IRQ_ENABLE, too) */
|
||||
|
||||
#define IDX_GAME_AXES_CONFIG 0x01
|
||||
/* NOTE: layout of this register awfully similar (read: "identical??")
|
||||
* to AD1815JS.pdf (p.29) */
|
||||
|
||||
/* enables axis 1 (X axis) measurement: */
|
||||
#define GAME_AXES_ENABLE_1 0x01
|
||||
/* enables axis 2 (Y axis) measurement: */
|
||||
#define GAME_AXES_ENABLE_2 0x02
|
||||
/* enables axis 3 (X axis) measurement: */
|
||||
#define GAME_AXES_ENABLE_3 0x04
|
||||
/* enables axis 4 (Y axis) measurement: */
|
||||
#define GAME_AXES_ENABLE_4 0x08
|
||||
/* selects the current axis to read the measured value of
|
||||
* (at IDX_GAME_AXIS_VALUE):
|
||||
* 00 = axis 1, 01 = axis 2, 10 = axis 3, 11 = axis 4: */
|
||||
#define GAME_AXES_READ_MASK 0x30
|
||||
/* enable to have the latch continuously accept ADC values
|
||||
* (and continuously cause interrupts in case interrupts are enabled);
|
||||
* AD1815JS.pdf says it's ~16ms interval there: */
|
||||
#define GAME_AXES_LATCH_ENABLE 0x40
|
||||
/* joystick data (measured axes) ready for reading: */
|
||||
#define GAME_AXES_SAMPLING_READY 0x80
|
||||
|
||||
/* NOTE: other card specs (SiS960 and others!) state that the
|
||||
* game position latches should be frozen when reading and be freed
|
||||
* (== reset?) after reading!!!
|
||||
* Freezing most likely means disabling 0x40 (GAME_AXES_LATCH_ENABLE),
|
||||
* but how to free the value? */
|
||||
/* An internet search for "gameport latch ADC" should provide some insight
|
||||
* into how to program such a gameport system. */
|
||||
|
||||
/* writing 0xf0 to 01H once reset both counters to 0, in some special mode!?
|
||||
* yup, in case 6AH 0x20 is not enabled
|
||||
* (and 0x40 is sufficient, 0xf0 is not needed) */
|
||||
|
||||
#define IDX_GAME_AXIS_VALUE 0x02
|
||||
/* R: value of currently configured axis (word value!);
|
||||
* W: trigger axis measurement */
|
||||
|
||||
#define IDX_GAME_HWCONFIG 0x04
|
||||
/* note: bits 4 to 7 are never set (== 0) when reading!
|
||||
* --> reserved bits? */
|
||||
/* enables IRQ notification upon axes measurement ready: */
|
||||
#define GAME_HWCFG_IRQ_ENABLE 0x01
|
||||
/* these bits choose a different frequency for the
|
||||
* internal ADC counter increment.
|
||||
* hmm, seems to be a combo of bits:
|
||||
* 00 --> standard frequency
|
||||
* 10 --> 1/2
|
||||
* 01 --> 1/20
|
||||
* 11 --> 1/200: */
|
||||
#define GAME_HWCFG_ADC_COUNTER_FREQ_MASK 0x06
|
||||
|
||||
/* enable gameport legacy I/O address (0x200)
|
||||
* I was unable to locate any configurability for a different address: */
|
||||
#define GAME_HWCFG_LEGACY_ADDRESS_ENABLE 0x08
|
||||
|
||||
/*** MPU401 ***/
|
||||
#define AZF_IO_SIZE_MPU 0x04
|
||||
#define AZF_IO_SIZE_MPU_PM 0x04
|
||||
|
||||
#define AZF_IO_SIZE_SYNTH 0x08
|
||||
#define AZF_IO_SIZE_SYNTH_PM 0x06
|
||||
/*** OPL3 synth ***/
|
||||
#define AZF_IO_SIZE_OPL3 0x08
|
||||
#define AZF_IO_SIZE_OPL3_PM 0x06
|
||||
/* hmm, given that a standard OPL3 has 4 registers only,
|
||||
* there might be some enhanced functionality lurking at the end
|
||||
* (especially since register 0x04 has a "non-empty" value 0xfe) */
|
||||
|
||||
/*** mixer I/O area port indices ***/
|
||||
/* (only 0x22 of 0x40 bytes saved/restored by Windows driver)
|
||||
|
|
|
@ -249,6 +249,11 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
|
|||
.name = "MSI K8N Diamond MB [SB0438]",
|
||||
.gpio_type = 2,
|
||||
.i2c_adc = 1 } ,
|
||||
/* Another MSI K8N Diamond MB, which has apprently a different SSID */
|
||||
{ .serial = 0x10091102,
|
||||
.name = "MSI K8N Diamond MB",
|
||||
.gpio_type = 2,
|
||||
.i2c_adc = 1 } ,
|
||||
/* Shuttle XPC SD31P which has an onboard Creative Labs
|
||||
* Sound Blaster Live! 24-bit EAX
|
||||
* high-definition 7.1 audio processor".
|
||||
|
|
|
@ -1528,6 +1528,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
|
|||
.ca0151_chip = 1,
|
||||
.spk71 = 1,
|
||||
.spdif_bug = 1,
|
||||
.invert_shared_spdif = 1, /* digital/analog switch swapped */
|
||||
.adc_1361t = 1, /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */
|
||||
.ac97_chip = 1} ,
|
||||
{.vendor = 0x1102, .device = 0x0004, .revision = 0x04,
|
||||
|
|
|
@ -1578,6 +1578,10 @@ static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
|
|||
ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
|
||||
else
|
||||
ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
|
||||
if (emu->card_capabilities->invert_shared_spdif)
|
||||
ucontrol->value.integer.value[0] =
|
||||
!ucontrol->value.integer.value[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1586,15 +1590,18 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
|
|||
{
|
||||
unsigned long flags;
|
||||
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
|
||||
unsigned int reg, val;
|
||||
unsigned int reg, val, sw;
|
||||
int change = 0;
|
||||
|
||||
sw = ucontrol->value.integer.value[0];
|
||||
if (emu->card_capabilities->invert_shared_spdif)
|
||||
sw = !sw;
|
||||
spin_lock_irqsave(&emu->reg_lock, flags);
|
||||
if ( emu->card_capabilities->i2c_adc) {
|
||||
/* Do nothing for Audigy 2 ZS Notebook */
|
||||
} else if (emu->audigy) {
|
||||
reg = inl(emu->port + A_IOCFG);
|
||||
val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
|
||||
val = sw ? A_IOCFG_GPOUT0 : 0;
|
||||
change = (reg & A_IOCFG_GPOUT0) != val;
|
||||
if (change) {
|
||||
reg &= ~A_IOCFG_GPOUT0;
|
||||
|
@ -1603,7 +1610,7 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
|
|||
}
|
||||
}
|
||||
reg = inl(emu->port + HCFG);
|
||||
val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
|
||||
val = sw ? HCFG_GPOUT0 : 0;
|
||||
change |= (reg & HCFG_GPOUT0) != val;
|
||||
if (change) {
|
||||
reg &= ~HCFG_GPOUT0;
|
||||
|
|
|
@ -437,43 +437,49 @@ static void get_single_page_range(struct snd_util_memhdr *hdr,
|
|||
*last_page_ret = last_page;
|
||||
}
|
||||
|
||||
/* release allocated pages */
|
||||
static void __synth_free_pages(struct snd_emu10k1 *emu, int first_page,
|
||||
int last_page)
|
||||
{
|
||||
int page;
|
||||
|
||||
for (page = first_page; page <= last_page; page++) {
|
||||
free_page((unsigned long)emu->page_ptr_table[page]);
|
||||
emu->page_addr_table[page] = 0;
|
||||
emu->page_ptr_table[page] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate kernel pages
|
||||
*/
|
||||
static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
|
||||
{
|
||||
int page, first_page, last_page;
|
||||
struct snd_dma_buffer dmab;
|
||||
|
||||
emu10k1_memblk_init(blk);
|
||||
get_single_page_range(emu->memhdr, blk, &first_page, &last_page);
|
||||
/* allocate kernel pages */
|
||||
for (page = first_page; page <= last_page; page++) {
|
||||
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci),
|
||||
PAGE_SIZE, &dmab) < 0)
|
||||
goto __fail;
|
||||
if (! is_valid_page(emu, dmab.addr)) {
|
||||
snd_dma_free_pages(&dmab);
|
||||
goto __fail;
|
||||
/* first try to allocate from <4GB zone */
|
||||
struct page *p = alloc_page(GFP_KERNEL | GFP_DMA32 |
|
||||
__GFP_NOWARN);
|
||||
if (!p || (page_to_pfn(p) & ~(emu->dma_mask >> PAGE_SHIFT))) {
|
||||
if (p)
|
||||
__free_page(p);
|
||||
/* try to allocate from <16MB zone */
|
||||
p = alloc_page(GFP_ATOMIC | GFP_DMA |
|
||||
__GFP_NORETRY | /* no OOM-killer */
|
||||
__GFP_NOWARN);
|
||||
}
|
||||
emu->page_addr_table[page] = dmab.addr;
|
||||
emu->page_ptr_table[page] = dmab.area;
|
||||
if (!p) {
|
||||
__synth_free_pages(emu, first_page, page - 1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
emu->page_addr_table[page] = page_to_phys(p);
|
||||
emu->page_ptr_table[page] = page_address(p);
|
||||
}
|
||||
return 0;
|
||||
|
||||
__fail:
|
||||
/* release allocated pages */
|
||||
last_page = page - 1;
|
||||
for (page = first_page; page <= last_page; page++) {
|
||||
dmab.area = emu->page_ptr_table[page];
|
||||
dmab.addr = emu->page_addr_table[page];
|
||||
dmab.bytes = PAGE_SIZE;
|
||||
snd_dma_free_pages(&dmab);
|
||||
emu->page_addr_table[page] = 0;
|
||||
emu->page_ptr_table[page] = NULL;
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -481,23 +487,10 @@ __fail:
|
|||
*/
|
||||
static int synth_free_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
|
||||
{
|
||||
int page, first_page, last_page;
|
||||
struct snd_dma_buffer dmab;
|
||||
int first_page, last_page;
|
||||
|
||||
get_single_page_range(emu->memhdr, blk, &first_page, &last_page);
|
||||
dmab.dev.type = SNDRV_DMA_TYPE_DEV;
|
||||
dmab.dev.dev = snd_dma_pci_data(emu->pci);
|
||||
for (page = first_page; page <= last_page; page++) {
|
||||
if (emu->page_ptr_table[page] == NULL)
|
||||
continue;
|
||||
dmab.area = emu->page_ptr_table[page];
|
||||
dmab.addr = emu->page_addr_table[page];
|
||||
dmab.bytes = PAGE_SIZE;
|
||||
snd_dma_free_pages(&dmab);
|
||||
emu->page_addr_table[page] = 0;
|
||||
emu->page_ptr_table[page] = NULL;
|
||||
}
|
||||
|
||||
__synth_free_pages(emu, first_page, last_page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -2335,7 +2335,7 @@ int snd_hda_check_board_config(struct hda_codec *codec,
|
|||
if (!tbl)
|
||||
return -1;
|
||||
if (tbl->value >= 0 && tbl->value < num_configs) {
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
char tmp[10];
|
||||
const char *model = NULL;
|
||||
if (models)
|
||||
|
|
|
@ -78,7 +78,7 @@ enum {
|
|||
#define AC_VERB_GET_BEEP_CONTROL 0x0f0a
|
||||
#define AC_VERB_GET_EAPD_BTLENABLE 0x0f0c
|
||||
#define AC_VERB_GET_DIGI_CONVERT_1 0x0f0d
|
||||
#define AC_VERB_GET_DIGI_CONVERT_2 0x0f0e
|
||||
#define AC_VERB_GET_DIGI_CONVERT_2 0x0f0e /* unused */
|
||||
#define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f
|
||||
/* f10-f1a: GPIO */
|
||||
#define AC_VERB_GET_GPIO_DATA 0x0f15
|
||||
|
|
|
@ -88,7 +88,7 @@ static int hda_hwdep_ioctl_compat(struct snd_hwdep *hw, struct file *file,
|
|||
|
||||
static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
|
||||
{
|
||||
#ifndef CONFIG_SND_DEBUG_DETECT
|
||||
#ifndef CONFIG_SND_DEBUG_VERBOSE
|
||||
if (!capable(CAP_SYS_RAWIO))
|
||||
return -EACCES;
|
||||
#endif
|
||||
|
|
|
@ -55,6 +55,7 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
|
|||
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
|
||||
static char *model[SNDRV_CARDS];
|
||||
static int position_fix[SNDRV_CARDS];
|
||||
static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
|
||||
static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
|
||||
static int single_cmd;
|
||||
static int enable_msi;
|
||||
|
@ -69,7 +70,9 @@ module_param_array(model, charp, NULL, 0444);
|
|||
MODULE_PARM_DESC(model, "Use the given board model.");
|
||||
module_param_array(position_fix, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(position_fix, "Fix DMA pointer "
|
||||
"(0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size).");
|
||||
"(0 = auto, 1 = none, 2 = POSBUF).");
|
||||
module_param_array(bdl_pos_adj, int, NULL, 0644);
|
||||
MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
|
||||
module_param_array(probe_mask, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
|
||||
module_param(single_cmd, bool, 0444);
|
||||
|
@ -197,6 +200,10 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
|
|||
#define ATIHDMI_NUM_CAPTURE 0
|
||||
#define ATIHDMI_NUM_PLAYBACK 1
|
||||
|
||||
/* TERA has 4 playback and 3 capture */
|
||||
#define TERA_NUM_CAPTURE 3
|
||||
#define TERA_NUM_PLAYBACK 4
|
||||
|
||||
/* this number is statically defined for simplicity */
|
||||
#define MAX_AZX_DEV 16
|
||||
|
||||
|
@ -259,9 +266,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
|
|||
/* position fix mode */
|
||||
enum {
|
||||
POS_FIX_AUTO,
|
||||
POS_FIX_NONE,
|
||||
POS_FIX_LPIB,
|
||||
POS_FIX_POSBUF,
|
||||
POS_FIX_FIFO,
|
||||
};
|
||||
|
||||
/* Defines for ATI HD Audio support in SB450 south bridge */
|
||||
|
@ -285,6 +291,7 @@ struct azx_dev {
|
|||
u32 *posbuf; /* position buffer pointer */
|
||||
|
||||
unsigned int bufsize; /* size of the play buffer in bytes */
|
||||
unsigned int period_bytes; /* size of the period in bytes */
|
||||
unsigned int frags; /* number for period in the play buffer */
|
||||
unsigned int fifo_size; /* FIFO size */
|
||||
|
||||
|
@ -301,11 +308,11 @@ struct azx_dev {
|
|||
*/
|
||||
unsigned char stream_tag; /* assigned stream */
|
||||
unsigned char index; /* stream index */
|
||||
/* for sanity check of position buffer */
|
||||
unsigned int period_intr;
|
||||
|
||||
unsigned int opened :1;
|
||||
unsigned int running :1;
|
||||
unsigned int irq_pending :1;
|
||||
unsigned int irq_ignore :1;
|
||||
};
|
||||
|
||||
/* CORB/RIRB */
|
||||
|
@ -323,6 +330,7 @@ struct azx_rb {
|
|||
struct azx {
|
||||
struct snd_card *card;
|
||||
struct pci_dev *pci;
|
||||
int dev_index;
|
||||
|
||||
/* chip type specific */
|
||||
int driver_type;
|
||||
|
@ -366,9 +374,13 @@ struct azx {
|
|||
unsigned int single_cmd :1;
|
||||
unsigned int polling_mode :1;
|
||||
unsigned int msi :1;
|
||||
unsigned int irq_pending_warned :1;
|
||||
|
||||
/* for debugging */
|
||||
unsigned int last_cmd; /* last issued command (to sync) */
|
||||
|
||||
/* for pending irqs */
|
||||
struct work_struct irq_pending_work;
|
||||
};
|
||||
|
||||
/* driver types */
|
||||
|
@ -381,6 +393,7 @@ enum {
|
|||
AZX_DRIVER_SIS,
|
||||
AZX_DRIVER_ULI,
|
||||
AZX_DRIVER_NVIDIA,
|
||||
AZX_DRIVER_TERA,
|
||||
};
|
||||
|
||||
static char *driver_short_names[] __devinitdata = {
|
||||
|
@ -392,6 +405,7 @@ static char *driver_short_names[] __devinitdata = {
|
|||
[AZX_DRIVER_SIS] = "HDA SIS966",
|
||||
[AZX_DRIVER_ULI] = "HDA ULI M5461",
|
||||
[AZX_DRIVER_NVIDIA] = "HDA NVidia",
|
||||
[AZX_DRIVER_TERA] = "HDA Teradici",
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -426,11 +440,6 @@ static char *driver_short_names[] __devinitdata = {
|
|||
/* for pcm support */
|
||||
#define get_azx_dev(substream) (substream->runtime->private_data)
|
||||
|
||||
/* Get the upper 32bit of the given dma_addr_t
|
||||
* Compiler should optimize and eliminate the code if dma_addr_t is 32bit
|
||||
*/
|
||||
#define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0)
|
||||
|
||||
static int azx_acquire_irq(struct azx *chip, int do_disconnect);
|
||||
|
||||
/*
|
||||
|
@ -461,7 +470,7 @@ static void azx_init_cmd_io(struct azx *chip)
|
|||
chip->corb.addr = chip->rb.addr;
|
||||
chip->corb.buf = (u32 *)chip->rb.area;
|
||||
azx_writel(chip, CORBLBASE, (u32)chip->corb.addr);
|
||||
azx_writel(chip, CORBUBASE, upper_32bit(chip->corb.addr));
|
||||
azx_writel(chip, CORBUBASE, upper_32_bits(chip->corb.addr));
|
||||
|
||||
/* set the corb size to 256 entries (ULI requires explicitly) */
|
||||
azx_writeb(chip, CORBSIZE, 0x02);
|
||||
|
@ -476,7 +485,7 @@ static void azx_init_cmd_io(struct azx *chip)
|
|||
chip->rirb.addr = chip->rb.addr + 2048;
|
||||
chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
|
||||
azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr);
|
||||
azx_writel(chip, RIRBUBASE, upper_32bit(chip->rirb.addr));
|
||||
azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr));
|
||||
|
||||
/* set the rirb size to 256 entries (ULI requires explicitly) */
|
||||
azx_writeb(chip, RIRBSIZE, 0x02);
|
||||
|
@ -847,7 +856,7 @@ static void azx_init_chip(struct azx *chip)
|
|||
|
||||
/* program the position buffer */
|
||||
azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
|
||||
azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
|
||||
azx_writel(chip, DPUBASE, upper_32_bits(chip->posbuf.addr));
|
||||
|
||||
chip->initialized = 1;
|
||||
}
|
||||
|
@ -908,6 +917,8 @@ static void azx_init_pci(struct azx *chip)
|
|||
}
|
||||
|
||||
|
||||
static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
|
||||
|
||||
/*
|
||||
* interrupt handler
|
||||
*/
|
||||
|
@ -930,11 +941,23 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
|
|||
azx_dev = &chip->azx_dev[i];
|
||||
if (status & azx_dev->sd_int_sta_mask) {
|
||||
azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
|
||||
if (azx_dev->substream && azx_dev->running) {
|
||||
azx_dev->period_intr++;
|
||||
if (!azx_dev->substream || !azx_dev->running)
|
||||
continue;
|
||||
/* ignore the first dummy IRQ (due to pos_adj) */
|
||||
if (azx_dev->irq_ignore) {
|
||||
azx_dev->irq_ignore = 0;
|
||||
continue;
|
||||
}
|
||||
/* check whether this IRQ is really acceptable */
|
||||
if (azx_position_ok(chip, azx_dev)) {
|
||||
azx_dev->irq_pending = 0;
|
||||
spin_unlock(&chip->reg_lock);
|
||||
snd_pcm_period_elapsed(azx_dev->substream);
|
||||
spin_lock(&chip->reg_lock);
|
||||
} else {
|
||||
/* bogus IRQ, process it later */
|
||||
azx_dev->irq_pending = 1;
|
||||
schedule_work(&chip->irq_pending_work);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -959,59 +982,107 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
|
|||
|
||||
|
||||
/*
|
||||
* set up BDL entries
|
||||
* set up a BDL entry
|
||||
*/
|
||||
static int azx_setup_periods(struct snd_pcm_substream *substream,
|
||||
struct azx_dev *azx_dev)
|
||||
static int setup_bdle(struct snd_pcm_substream *substream,
|
||||
struct azx_dev *azx_dev, u32 **bdlp,
|
||||
int ofs, int size, int with_ioc)
|
||||
{
|
||||
struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
|
||||
u32 *bdl = *bdlp;
|
||||
|
||||
while (size > 0) {
|
||||
dma_addr_t addr;
|
||||
int chunk;
|
||||
|
||||
if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES)
|
||||
return -EINVAL;
|
||||
|
||||
addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs);
|
||||
/* program the address field of the BDL entry */
|
||||
bdl[0] = cpu_to_le32((u32)addr);
|
||||
bdl[1] = cpu_to_le32(upper_32_bits(addr));
|
||||
/* program the size field of the BDL entry */
|
||||
chunk = PAGE_SIZE - (ofs % PAGE_SIZE);
|
||||
if (size < chunk)
|
||||
chunk = size;
|
||||
bdl[2] = cpu_to_le32(chunk);
|
||||
/* program the IOC to enable interrupt
|
||||
* only when the whole fragment is processed
|
||||
*/
|
||||
size -= chunk;
|
||||
bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01);
|
||||
bdl += 4;
|
||||
azx_dev->frags++;
|
||||
ofs += chunk;
|
||||
}
|
||||
*bdlp = bdl;
|
||||
return ofs;
|
||||
}
|
||||
|
||||
/*
|
||||
* set up BDL entries
|
||||
*/
|
||||
static int azx_setup_periods(struct azx *chip,
|
||||
struct snd_pcm_substream *substream,
|
||||
struct azx_dev *azx_dev)
|
||||
{
|
||||
u32 *bdl;
|
||||
int i, ofs, periods, period_bytes;
|
||||
int pos_adj;
|
||||
|
||||
/* reset BDL address */
|
||||
azx_sd_writel(azx_dev, SD_BDLPL, 0);
|
||||
azx_sd_writel(azx_dev, SD_BDLPU, 0);
|
||||
|
||||
period_bytes = snd_pcm_lib_period_bytes(substream);
|
||||
azx_dev->period_bytes = period_bytes;
|
||||
periods = azx_dev->bufsize / period_bytes;
|
||||
|
||||
/* program the initial BDL entries */
|
||||
bdl = (u32 *)azx_dev->bdl.area;
|
||||
ofs = 0;
|
||||
azx_dev->frags = 0;
|
||||
for (i = 0; i < periods; i++) {
|
||||
int size, rest;
|
||||
if (i >= AZX_MAX_BDL_ENTRIES) {
|
||||
snd_printk(KERN_ERR "Too many BDL entries: "
|
||||
"buffer=%d, period=%d\n",
|
||||
azx_dev->bufsize, period_bytes);
|
||||
/* reset */
|
||||
azx_sd_writel(azx_dev, SD_BDLPL, 0);
|
||||
azx_sd_writel(azx_dev, SD_BDLPU, 0);
|
||||
return -EINVAL;
|
||||
azx_dev->irq_ignore = 0;
|
||||
pos_adj = bdl_pos_adj[chip->dev_index];
|
||||
if (pos_adj > 0) {
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
pos_adj = (pos_adj * runtime->rate + 47999) / 48000;
|
||||
if (!pos_adj)
|
||||
pos_adj = 1;
|
||||
pos_adj = frames_to_bytes(runtime, pos_adj);
|
||||
if (pos_adj >= period_bytes) {
|
||||
snd_printk(KERN_WARNING "Too big adjustment %d\n",
|
||||
bdl_pos_adj[chip->dev_index]);
|
||||
pos_adj = 0;
|
||||
} else {
|
||||
ofs = setup_bdle(substream, azx_dev,
|
||||
&bdl, ofs, pos_adj, 1);
|
||||
if (ofs < 0)
|
||||
goto error;
|
||||
azx_dev->irq_ignore = 1;
|
||||
}
|
||||
rest = period_bytes;
|
||||
do {
|
||||
dma_addr_t addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs);
|
||||
/* program the address field of the BDL entry */
|
||||
bdl[0] = cpu_to_le32((u32)addr);
|
||||
bdl[1] = cpu_to_le32(upper_32bit(addr));
|
||||
/* program the size field of the BDL entry */
|
||||
size = PAGE_SIZE - (ofs % PAGE_SIZE);
|
||||
if (rest < size)
|
||||
size = rest;
|
||||
bdl[2] = cpu_to_le32(size);
|
||||
/* program the IOC to enable interrupt
|
||||
* only when the whole fragment is processed
|
||||
*/
|
||||
rest -= size;
|
||||
bdl[3] = rest ? 0 : cpu_to_le32(0x01);
|
||||
bdl += 4;
|
||||
azx_dev->frags++;
|
||||
ofs += size;
|
||||
} while (rest > 0);
|
||||
} else
|
||||
pos_adj = 0;
|
||||
for (i = 0; i < periods; i++) {
|
||||
if (i == periods - 1 && pos_adj)
|
||||
ofs = setup_bdle(substream, azx_dev, &bdl, ofs,
|
||||
period_bytes - pos_adj, 0);
|
||||
else
|
||||
ofs = setup_bdle(substream, azx_dev, &bdl, ofs,
|
||||
period_bytes, 1);
|
||||
if (ofs < 0)
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
|
||||
error:
|
||||
snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n",
|
||||
azx_dev->bufsize, period_bytes);
|
||||
/* reset */
|
||||
azx_sd_writel(azx_dev, SD_BDLPL, 0);
|
||||
azx_sd_writel(azx_dev, SD_BDLPU, 0);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1062,7 +1133,7 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
|
|||
/* lower BDL address */
|
||||
azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr);
|
||||
/* upper BDL address */
|
||||
azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl.addr));
|
||||
azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr));
|
||||
|
||||
/* enable the position buffer */
|
||||
if (chip->position_fix == POS_FIX_POSBUF ||
|
||||
|
@ -1085,7 +1156,7 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
|
|||
*/
|
||||
|
||||
static unsigned int azx_max_codecs[] __devinitdata = {
|
||||
[AZX_DRIVER_ICH] = 3,
|
||||
[AZX_DRIVER_ICH] = 4, /* Some ICH9 boards use SD3 */
|
||||
[AZX_DRIVER_SCH] = 3,
|
||||
[AZX_DRIVER_ATI] = 4,
|
||||
[AZX_DRIVER_ATIHDMI] = 4,
|
||||
|
@ -1093,6 +1164,7 @@ static unsigned int azx_max_codecs[] __devinitdata = {
|
|||
[AZX_DRIVER_SIS] = 3, /* FIXME: correct? */
|
||||
[AZX_DRIVER_ULI] = 3, /* FIXME: correct? */
|
||||
[AZX_DRIVER_NVIDIA] = 3, /* FIXME: correct? */
|
||||
[AZX_DRIVER_TERA] = 1,
|
||||
};
|
||||
|
||||
static int __devinit azx_codec_create(struct azx *chip, const char *model,
|
||||
|
@ -1316,7 +1388,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
|
|||
|
||||
snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
|
||||
azx_dev->bufsize, azx_dev->format_val);
|
||||
if (azx_setup_periods(substream, azx_dev) < 0)
|
||||
if (azx_setup_periods(chip, substream, azx_dev) < 0)
|
||||
return -EINVAL;
|
||||
azx_setup_controller(chip, azx_dev);
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
|
@ -1421,35 +1493,113 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
|
||||
static unsigned int azx_get_position(struct azx *chip,
|
||||
struct azx_dev *azx_dev)
|
||||
{
|
||||
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
|
||||
struct azx *chip = apcm->chip;
|
||||
struct azx_dev *azx_dev = get_azx_dev(substream);
|
||||
unsigned int pos;
|
||||
|
||||
if (chip->position_fix == POS_FIX_POSBUF ||
|
||||
chip->position_fix == POS_FIX_AUTO) {
|
||||
/* use the position buffer */
|
||||
pos = le32_to_cpu(*azx_dev->posbuf);
|
||||
if (chip->position_fix == POS_FIX_AUTO &&
|
||||
azx_dev->period_intr == 1 && !pos) {
|
||||
printk(KERN_WARNING
|
||||
"hda-intel: Invalid position buffer, "
|
||||
"using LPIB read method instead.\n");
|
||||
chip->position_fix = POS_FIX_NONE;
|
||||
goto read_lpib;
|
||||
}
|
||||
} else {
|
||||
read_lpib:
|
||||
/* read LPIB */
|
||||
pos = azx_sd_readl(azx_dev, SD_LPIB);
|
||||
if (chip->position_fix == POS_FIX_FIFO)
|
||||
pos += azx_dev->fifo_size;
|
||||
}
|
||||
if (pos >= azx_dev->bufsize)
|
||||
pos = 0;
|
||||
return bytes_to_frames(substream->runtime, pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
|
||||
struct azx *chip = apcm->chip;
|
||||
struct azx_dev *azx_dev = get_azx_dev(substream);
|
||||
return bytes_to_frames(substream->runtime,
|
||||
azx_get_position(chip, azx_dev));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the current DMA position is acceptable for updating
|
||||
* periods. Returns non-zero if it's OK.
|
||||
*
|
||||
* Many HD-audio controllers appear pretty inaccurate about
|
||||
* the update-IRQ timing. The IRQ is issued before actually the
|
||||
* data is processed. So, we need to process it afterwords in a
|
||||
* workqueue.
|
||||
*/
|
||||
static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
|
||||
{
|
||||
unsigned int pos;
|
||||
|
||||
pos = azx_get_position(chip, azx_dev);
|
||||
if (chip->position_fix == POS_FIX_AUTO) {
|
||||
if (!pos) {
|
||||
printk(KERN_WARNING
|
||||
"hda-intel: Invalid position buffer, "
|
||||
"using LPIB read method instead.\n");
|
||||
chip->position_fix = POS_FIX_LPIB;
|
||||
pos = azx_get_position(chip, azx_dev);
|
||||
} else
|
||||
chip->position_fix = POS_FIX_POSBUF;
|
||||
}
|
||||
|
||||
if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2)
|
||||
return 0; /* NG - it's below the period boundary */
|
||||
return 1; /* OK, it's fine */
|
||||
}
|
||||
|
||||
/*
|
||||
* The work for pending PCM period updates.
|
||||
*/
|
||||
static void azx_irq_pending_work(struct work_struct *work)
|
||||
{
|
||||
struct azx *chip = container_of(work, struct azx, irq_pending_work);
|
||||
int i, pending;
|
||||
|
||||
if (!chip->irq_pending_warned) {
|
||||
printk(KERN_WARNING
|
||||
"hda-intel: IRQ timing workaround is activated "
|
||||
"for card #%d. Suggest a bigger bdl_pos_adj.\n",
|
||||
chip->card->number);
|
||||
chip->irq_pending_warned = 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
pending = 0;
|
||||
spin_lock_irq(&chip->reg_lock);
|
||||
for (i = 0; i < chip->num_streams; i++) {
|
||||
struct azx_dev *azx_dev = &chip->azx_dev[i];
|
||||
if (!azx_dev->irq_pending ||
|
||||
!azx_dev->substream ||
|
||||
!azx_dev->running)
|
||||
continue;
|
||||
if (azx_position_ok(chip, azx_dev)) {
|
||||
azx_dev->irq_pending = 0;
|
||||
spin_unlock(&chip->reg_lock);
|
||||
snd_pcm_period_elapsed(azx_dev->substream);
|
||||
spin_lock(&chip->reg_lock);
|
||||
} else
|
||||
pending++;
|
||||
}
|
||||
spin_unlock_irq(&chip->reg_lock);
|
||||
if (!pending)
|
||||
return;
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
|
||||
/* clear irq_pending flags and assure no on-going workq */
|
||||
static void azx_clear_irq_pending(struct azx *chip)
|
||||
{
|
||||
int i;
|
||||
|
||||
spin_lock_irq(&chip->reg_lock);
|
||||
for (i = 0; i < chip->num_streams; i++)
|
||||
chip->azx_dev[i].irq_pending = 0;
|
||||
spin_unlock_irq(&chip->reg_lock);
|
||||
flush_scheduled_work();
|
||||
}
|
||||
|
||||
static struct snd_pcm_ops azx_pcm_ops = {
|
||||
|
@ -1676,6 +1826,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
|
|||
int i;
|
||||
|
||||
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
|
||||
azx_clear_irq_pending(chip);
|
||||
for (i = 0; i < AZX_MAX_PCMS; i++)
|
||||
snd_pcm_suspend_all(chip->pcm[i]);
|
||||
if (chip->initialized)
|
||||
|
@ -1732,6 +1883,7 @@ static int azx_free(struct azx *chip)
|
|||
int i;
|
||||
|
||||
if (chip->initialized) {
|
||||
azx_clear_irq_pending(chip);
|
||||
for (i = 0; i < chip->num_streams; i++)
|
||||
azx_stream_stop(chip, &chip->azx_dev[i]);
|
||||
azx_stop_chip(chip);
|
||||
|
@ -1770,9 +1922,9 @@ static int azx_dev_free(struct snd_device *device)
|
|||
* white/black-listing for position_fix
|
||||
*/
|
||||
static struct snd_pci_quirk position_fix_list[] __devinitdata = {
|
||||
SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE),
|
||||
SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_NONE),
|
||||
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_NONE),
|
||||
SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
|
||||
SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
|
||||
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -1857,12 +2009,25 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
|
|||
chip->irq = -1;
|
||||
chip->driver_type = driver_type;
|
||||
chip->msi = enable_msi;
|
||||
chip->dev_index = dev;
|
||||
INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
|
||||
|
||||
chip->position_fix = check_position_fix(chip, position_fix[dev]);
|
||||
check_probe_mask(chip, dev);
|
||||
|
||||
chip->single_cmd = single_cmd;
|
||||
|
||||
if (bdl_pos_adj[dev] < 0) {
|
||||
switch (chip->driver_type) {
|
||||
case AZX_DRIVER_ICH:
|
||||
bdl_pos_adj[dev] = 1;
|
||||
break;
|
||||
default:
|
||||
bdl_pos_adj[dev] = 32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if BITS_PER_LONG != 64
|
||||
/* Fix up base address on ULI M5461 */
|
||||
if (chip->driver_type == AZX_DRIVER_ULI) {
|
||||
|
@ -2089,6 +2254,7 @@ static struct pci_device_id azx_ids[] = {
|
|||
{ PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH },
|
||||
{ PCI_DEVICE(0x8086, 0x269a), .driver_data = AZX_DRIVER_ICH },
|
||||
{ PCI_DEVICE(0x8086, 0x284b), .driver_data = AZX_DRIVER_ICH },
|
||||
{ PCI_DEVICE(0x8086, 0x2911), .driver_data = AZX_DRIVER_ICH },
|
||||
{ PCI_DEVICE(0x8086, 0x293e), .driver_data = AZX_DRIVER_ICH },
|
||||
{ PCI_DEVICE(0x8086, 0x293f), .driver_data = AZX_DRIVER_ICH },
|
||||
{ PCI_DEVICE(0x8086, 0x3a3e), .driver_data = AZX_DRIVER_ICH },
|
||||
|
@ -2141,6 +2307,8 @@ static struct pci_device_id azx_ids[] = {
|
|||
{ PCI_DEVICE(0x10de, 0x0bd5), .driver_data = AZX_DRIVER_NVIDIA },
|
||||
{ PCI_DEVICE(0x10de, 0x0bd6), .driver_data = AZX_DRIVER_NVIDIA },
|
||||
{ PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA },
|
||||
/* Teradici */
|
||||
{ PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
|
||||
{ 0, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, azx_ids);
|
||||
|
|
|
@ -366,8 +366,6 @@ static void print_digital_conv(struct snd_info_buffer *buffer,
|
|||
{
|
||||
unsigned int digi1 = snd_hda_codec_read(codec, nid, 0,
|
||||
AC_VERB_GET_DIGI_CONVERT_1, 0);
|
||||
unsigned int digi2 = snd_hda_codec_read(codec, nid, 0,
|
||||
AC_VERB_GET_DIGI_CONVERT_2, 0);
|
||||
snd_iprintf(buffer, " Digital:");
|
||||
if (digi1 & AC_DIG1_ENABLE)
|
||||
snd_iprintf(buffer, " Enabled");
|
||||
|
@ -386,7 +384,8 @@ static void print_digital_conv(struct snd_info_buffer *buffer,
|
|||
if (digi1 & AC_DIG1_LEVEL)
|
||||
snd_iprintf(buffer, " GenLevel");
|
||||
snd_iprintf(buffer, "\n");
|
||||
snd_iprintf(buffer, " Digital category: 0x%x\n", digi2 & AC_DIG2_CC);
|
||||
snd_iprintf(buffer, " Digital category: 0x%x\n",
|
||||
(digi1 >> 8) & AC_DIG2_CC);
|
||||
}
|
||||
|
||||
static const char *get_pwr_state(u32 state)
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include "hda_codec.h"
|
||||
|
@ -64,7 +63,6 @@ struct ad198x_spec {
|
|||
/* PCM information */
|
||||
struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
|
||||
|
||||
struct mutex amp_mutex; /* PCM volume/mute control mutex */
|
||||
unsigned int spdif_route;
|
||||
|
||||
/* dynamic controls, init_verbs and input_mux */
|
||||
|
@ -1618,6 +1616,7 @@ static const char *ad1981_models[AD1981_MODELS] = {
|
|||
|
||||
static struct snd_pci_quirk ad1981_cfg_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
|
||||
SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
|
||||
/* All HP models */
|
||||
SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP),
|
||||
SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
|
||||
|
@ -2623,7 +2622,7 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
|
|||
{
|
||||
struct ad198x_spec *spec = codec->spec;
|
||||
hda_nid_t nid;
|
||||
int idx, err;
|
||||
int i, idx, err;
|
||||
char name[32];
|
||||
|
||||
if (! pin)
|
||||
|
@ -2631,16 +2630,26 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
|
|||
|
||||
idx = ad1988_pin_idx(pin);
|
||||
nid = ad1988_idx_to_dac(codec, idx);
|
||||
/* specify the DAC as the extra output */
|
||||
if (! spec->multiout.hp_nid)
|
||||
spec->multiout.hp_nid = nid;
|
||||
else
|
||||
spec->multiout.extra_out_nid[0] = nid;
|
||||
/* control HP volume/switch on the output mixer amp */
|
||||
sprintf(name, "%s Playback Volume", pfx);
|
||||
if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
|
||||
HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
|
||||
return err;
|
||||
/* check whether the corresponding DAC was already taken */
|
||||
for (i = 0; i < spec->autocfg.line_outs; i++) {
|
||||
hda_nid_t pin = spec->autocfg.line_out_pins[i];
|
||||
hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
|
||||
if (dac == nid)
|
||||
break;
|
||||
}
|
||||
if (i >= spec->autocfg.line_outs) {
|
||||
/* specify the DAC as the extra output */
|
||||
if (!spec->multiout.hp_nid)
|
||||
spec->multiout.hp_nid = nid;
|
||||
else
|
||||
spec->multiout.extra_out_nid[0] = nid;
|
||||
/* control HP volume/switch on the output mixer amp */
|
||||
sprintf(name, "%s Playback Volume", pfx);
|
||||
err = add_control(spec, AD_CTL_WIDGET_VOL, name,
|
||||
HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
nid = ad1988_mixer_nids[idx];
|
||||
sprintf(name, "%s Playback Switch", pfx);
|
||||
if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
|
||||
|
@ -3177,7 +3186,6 @@ static int patch_ad1884(struct hda_codec *codec)
|
|||
if (spec == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&spec->amp_mutex);
|
||||
codec->spec = spec;
|
||||
|
||||
spec->multiout.max_channels = 2;
|
||||
|
@ -3847,7 +3855,6 @@ static int patch_ad1884a(struct hda_codec *codec)
|
|||
if (spec == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&spec->amp_mutex);
|
||||
codec->spec = spec;
|
||||
|
||||
spec->multiout.max_channels = 2;
|
||||
|
@ -4152,7 +4159,6 @@ static int patch_ad1882(struct hda_codec *codec)
|
|||
if (spec == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&spec->amp_mutex);
|
||||
codec->spec = spec;
|
||||
|
||||
spec->multiout.max_channels = 6;
|
||||
|
|
|
@ -82,7 +82,6 @@ struct conexant_spec {
|
|||
/* PCM information */
|
||||
struct hda_pcm pcm_rec[2]; /* used in build_pcms() */
|
||||
|
||||
struct mutex amp_mutex; /* PCM volume/mute control mutex */
|
||||
unsigned int spdif_route;
|
||||
|
||||
/* dynamic controls, init_verbs and input_mux */
|
||||
|
@ -687,7 +686,7 @@ static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
|
|||
|
||||
static struct hda_verb cxt5045_init_verbs[] = {
|
||||
/* Line in, Mic */
|
||||
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
|
||||
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
|
||||
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
|
||||
/* HP, Amp */
|
||||
{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
|
||||
|
@ -907,10 +906,12 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV9533EG", CXT5045_LAPTOP_HPSENSE),
|
||||
SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530),
|
||||
SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP_HPSENSE),
|
||||
SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE),
|
||||
SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
|
||||
SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
|
||||
SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE),
|
||||
SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505", CXT5045_LAPTOP_HPSENSE),
|
||||
SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505",
|
||||
CXT5045_LAPTOP_HPMICSENSE),
|
||||
SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE),
|
||||
SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE),
|
||||
SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE),
|
||||
|
@ -928,7 +929,6 @@ static int patch_cxt5045(struct hda_codec *codec)
|
|||
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (!spec)
|
||||
return -ENOMEM;
|
||||
mutex_init(&spec->amp_mutex);
|
||||
codec->spec = spec;
|
||||
|
||||
spec->multiout.max_channels = 2;
|
||||
|
@ -963,6 +963,7 @@ static int patch_cxt5045(struct hda_codec *codec)
|
|||
codec->patch_ops.init = cxt5045_init;
|
||||
break;
|
||||
case CXT5045_LAPTOP_MICSENSE:
|
||||
codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
|
||||
spec->input_mux = &cxt5045_capture_source;
|
||||
spec->num_init_verbs = 2;
|
||||
spec->init_verbs[1] = cxt5045_mic_sense_init_verbs;
|
||||
|
@ -1007,15 +1008,19 @@ static int patch_cxt5045(struct hda_codec *codec)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix max PCM level to 0 dB
|
||||
* (originall it has 0x2b steps with 0dB offset 0x14)
|
||||
*/
|
||||
snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
|
||||
(0x14 << AC_AMPCAP_OFFSET_SHIFT) |
|
||||
(0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) |
|
||||
(0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
|
||||
(1 << AC_AMPCAP_MUTE_SHIFT));
|
||||
switch (codec->subsystem_id >> 16) {
|
||||
case 0x103c:
|
||||
/* HP laptop has a really bad sound over 0dB on NID 0x17.
|
||||
* Fix max PCM level to 0 dB
|
||||
* (originall it has 0x2b steps with 0dB offset 0x14)
|
||||
*/
|
||||
snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
|
||||
(0x14 << AC_AMPCAP_OFFSET_SHIFT) |
|
||||
(0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) |
|
||||
(0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
|
||||
(1 << AC_AMPCAP_MUTE_SHIFT));
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1477,7 +1482,6 @@ static int patch_cxt5047(struct hda_codec *codec)
|
|||
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (!spec)
|
||||
return -ENOMEM;
|
||||
mutex_init(&spec->amp_mutex);
|
||||
codec->spec = spec;
|
||||
|
||||
spec->multiout.max_channels = 2;
|
||||
|
@ -1736,7 +1740,6 @@ static int patch_cxt5051(struct hda_codec *codec)
|
|||
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (!spec)
|
||||
return -ENOMEM;
|
||||
mutex_init(&spec->amp_mutex);
|
||||
codec->spec = spec;
|
||||
|
||||
codec->patch_ops = conexant_patch_ops;
|
||||
|
|
|
@ -163,6 +163,10 @@ enum {
|
|||
ALC662_LENOVO_101E,
|
||||
ALC662_ASUS_EEEPC_P701,
|
||||
ALC662_ASUS_EEEPC_EP20,
|
||||
ALC663_ASUS_M51VA,
|
||||
ALC663_ASUS_G71V,
|
||||
ALC663_ASUS_H13,
|
||||
ALC663_ASUS_G50V,
|
||||
ALC662_AUTO,
|
||||
ALC662_MODEL_LAST,
|
||||
};
|
||||
|
@ -205,6 +209,7 @@ enum {
|
|||
ALC883_MITAC,
|
||||
ALC883_CLEVO_M720,
|
||||
ALC883_FUJITSU_PI2515,
|
||||
ALC883_3ST_6ch_INTEL,
|
||||
ALC883_AUTO,
|
||||
ALC883_MODEL_LAST,
|
||||
};
|
||||
|
@ -280,6 +285,10 @@ struct alc_spec {
|
|||
#ifdef CONFIG_SND_HDA_POWER_SAVE
|
||||
struct hda_loopback_check loopback;
|
||||
#endif
|
||||
|
||||
/* for PLL fix */
|
||||
hda_nid_t pll_nid;
|
||||
unsigned int pll_coef_idx, pll_coef_bit;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -747,6 +756,38 @@ static struct hda_verb alc_gpio3_init_verbs[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
/*
|
||||
* Fix hardware PLL issue
|
||||
* On some codecs, the analog PLL gating control must be off while
|
||||
* the default value is 1.
|
||||
*/
|
||||
static void alc_fix_pll(struct hda_codec *codec)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
unsigned int val;
|
||||
|
||||
if (!spec->pll_nid)
|
||||
return;
|
||||
snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
|
||||
spec->pll_coef_idx);
|
||||
val = snd_hda_codec_read(codec, spec->pll_nid, 0,
|
||||
AC_VERB_GET_PROC_COEF, 0);
|
||||
snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
|
||||
spec->pll_coef_idx);
|
||||
snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
|
||||
val & ~(1 << spec->pll_coef_bit));
|
||||
}
|
||||
|
||||
static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
|
||||
unsigned int coef_idx, unsigned int coef_bit)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
spec->pll_nid = nid;
|
||||
spec->pll_coef_idx = coef_idx;
|
||||
spec->pll_coef_bit = coef_bit;
|
||||
alc_fix_pll(codec);
|
||||
}
|
||||
|
||||
static void alc_sku_automute(struct hda_codec *codec)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
|
@ -776,6 +817,24 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
|
|||
alc_sku_automute(codec);
|
||||
}
|
||||
|
||||
/* additional initialization for ALC888 variants */
|
||||
static void alc888_coef_init(struct hda_codec *codec)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
|
||||
tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
|
||||
snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
|
||||
if ((tmp & 0xf0) == 2)
|
||||
/* alc888S-VC */
|
||||
snd_hda_codec_read(codec, 0x20, 0,
|
||||
AC_VERB_SET_PROC_COEF, 0x830);
|
||||
else
|
||||
/* alc888-VB */
|
||||
snd_hda_codec_read(codec, 0x20, 0,
|
||||
AC_VERB_SET_PROC_COEF, 0x3030);
|
||||
}
|
||||
|
||||
/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
|
||||
* 31 ~ 16 : Manufacture ID
|
||||
* 15 ~ 8 : SKU ID
|
||||
|
@ -851,8 +910,10 @@ do_sku:
|
|||
case 0x10ec0267:
|
||||
case 0x10ec0268:
|
||||
case 0x10ec0269:
|
||||
case 0x10ec0660:
|
||||
case 0x10ec0662:
|
||||
case 0x10ec0663:
|
||||
case 0x10ec0862:
|
||||
case 0x10ec0662:
|
||||
case 0x10ec0889:
|
||||
snd_hda_codec_write(codec, 0x14, 0,
|
||||
AC_VERB_SET_EAPD_BTLENABLE, 2);
|
||||
|
@ -877,7 +938,6 @@ do_sku:
|
|||
case 0x10ec0882:
|
||||
case 0x10ec0883:
|
||||
case 0x10ec0885:
|
||||
case 0x10ec0888:
|
||||
case 0x10ec0889:
|
||||
snd_hda_codec_write(codec, 0x20, 0,
|
||||
AC_VERB_SET_COEF_INDEX, 7);
|
||||
|
@ -889,6 +949,9 @@ do_sku:
|
|||
AC_VERB_SET_PROC_COEF,
|
||||
tmp | 0x2010);
|
||||
break;
|
||||
case 0x10ec0888:
|
||||
alc888_coef_init(codec);
|
||||
break;
|
||||
case 0x10ec0267:
|
||||
case 0x10ec0268:
|
||||
snd_hda_codec_write(codec, 0x20, 0,
|
||||
|
@ -2373,6 +2436,8 @@ static int alc_init(struct hda_codec *codec)
|
|||
struct alc_spec *spec = codec->spec;
|
||||
unsigned int i;
|
||||
|
||||
alc_fix_pll(codec);
|
||||
|
||||
for (i = 0; i < spec->num_init_verbs; i++)
|
||||
snd_hda_sequence_write(codec, spec->init_verbs[i]);
|
||||
|
||||
|
@ -3009,6 +3074,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
|
||||
SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
|
||||
SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
|
||||
SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
|
||||
SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL),
|
||||
SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
|
||||
SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
|
||||
|
@ -5101,7 +5167,7 @@ static struct snd_pci_quirk alc260_cfg_tbl[] = {
|
|||
SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
|
||||
SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013),
|
||||
SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
|
||||
SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP),
|
||||
SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013),
|
||||
SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_3013),
|
||||
SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
|
||||
SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
|
||||
|
@ -6127,6 +6193,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
|
||||
SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
|
||||
SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
|
||||
SND_PCI_QUIRK(0x106b, 0x00a0, "Apple iMac 24''", ALC885_IMAC24),
|
||||
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
|
||||
SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */
|
||||
SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
|
||||
|
@ -6353,7 +6420,9 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec)
|
|||
continue;
|
||||
vref = PIN_IN;
|
||||
if (1 /*i <= AUTO_PIN_FRONT_MIC*/) {
|
||||
if (snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) &
|
||||
unsigned int pincap;
|
||||
pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
|
||||
if ((pincap >> AC_PINCAP_VREF_SHIFT) &
|
||||
AC_PINCAP_VREF_80)
|
||||
vref = PIN_VREF80;
|
||||
}
|
||||
|
@ -6450,8 +6519,9 @@ static int patch_alc882(struct hda_codec *codec)
|
|||
case 0x106b1000: /* iMac 24 */
|
||||
board_config = ALC885_IMAC24;
|
||||
break;
|
||||
case 0x106b00a1: /* Macbook */
|
||||
case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */
|
||||
case 0x106b2c00: /* Macbook Pro rev3 */
|
||||
case 0x106b3600: /* Macbook 3.1 */
|
||||
board_config = ALC885_MBP3;
|
||||
break;
|
||||
default:
|
||||
|
@ -6485,14 +6555,20 @@ static int patch_alc882(struct hda_codec *codec)
|
|||
if (board_config != ALC882_AUTO)
|
||||
setup_preset(spec, &alc882_presets[board_config]);
|
||||
|
||||
spec->stream_name_analog = "ALC882 Analog";
|
||||
if (codec->vendor_id == 0x10ec0885) {
|
||||
spec->stream_name_analog = "ALC885 Analog";
|
||||
spec->stream_name_digital = "ALC885 Digital";
|
||||
} else {
|
||||
spec->stream_name_analog = "ALC882 Analog";
|
||||
spec->stream_name_digital = "ALC882 Digital";
|
||||
}
|
||||
|
||||
spec->stream_analog_playback = &alc882_pcm_analog_playback;
|
||||
spec->stream_analog_capture = &alc882_pcm_analog_capture;
|
||||
/* FIXME: setup DAC5 */
|
||||
/*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
|
||||
spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
|
||||
|
||||
spec->stream_name_digital = "ALC882 Digital";
|
||||
spec->stream_digital_playback = &alc882_pcm_digital_playback;
|
||||
spec->stream_digital_capture = &alc882_pcm_digital_capture;
|
||||
|
||||
|
@ -6569,6 +6645,16 @@ static struct hda_input_mux alc883_capture_source = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct hda_input_mux alc883_3stack_6ch_intel = {
|
||||
.num_items = 4,
|
||||
.items = {
|
||||
{ "Mic", 0x1 },
|
||||
{ "Front Mic", 0x0 },
|
||||
{ "Line", 0x2 },
|
||||
{ "CD", 0x4 },
|
||||
},
|
||||
};
|
||||
|
||||
static struct hda_input_mux alc883_lenovo_101e_capture_source = {
|
||||
.num_items = 2,
|
||||
.items = {
|
||||
|
@ -6649,6 +6735,48 @@ static struct hda_channel_mode alc883_3ST_6ch_modes[3] = {
|
|||
{ 6, alc883_3ST_ch6_init },
|
||||
};
|
||||
|
||||
/*
|
||||
* 2ch mode
|
||||
*/
|
||||
static struct hda_verb alc883_3ST_ch2_intel_init[] = {
|
||||
{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
|
||||
{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
|
||||
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
|
||||
{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
|
||||
{ } /* end */
|
||||
};
|
||||
|
||||
/*
|
||||
* 4ch mode
|
||||
*/
|
||||
static struct hda_verb alc883_3ST_ch4_intel_init[] = {
|
||||
{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
|
||||
{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
|
||||
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
|
||||
{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
|
||||
{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
|
||||
{ } /* end */
|
||||
};
|
||||
|
||||
/*
|
||||
* 6ch mode
|
||||
*/
|
||||
static struct hda_verb alc883_3ST_ch6_intel_init[] = {
|
||||
{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
|
||||
{ 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
|
||||
{ 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
|
||||
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
|
||||
{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
|
||||
{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
|
||||
{ } /* end */
|
||||
};
|
||||
|
||||
static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
|
||||
{ 2, alc883_3ST_ch2_intel_init },
|
||||
{ 4, alc883_3ST_ch4_intel_init },
|
||||
{ 6, alc883_3ST_ch6_intel_init },
|
||||
};
|
||||
|
||||
/*
|
||||
* 6ch mode
|
||||
*/
|
||||
|
@ -6881,15 +7009,54 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
|
|||
{ } /* end */
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
|
||||
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
|
||||
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
|
||||
HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
|
||||
HDA_OUTPUT),
|
||||
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
|
||||
HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
|
||||
HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
/* .name = "Capture Source", */
|
||||
.name = "Input Source",
|
||||
.count = 2,
|
||||
.info = alc883_mux_enum_info,
|
||||
.get = alc883_mux_enum_get,
|
||||
.put = alc883_mux_enum_put,
|
||||
},
|
||||
{ } /* end */
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
|
||||
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
|
||||
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
|
||||
HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
|
||||
HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
|
||||
HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
|
||||
|
@ -7729,6 +7896,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
|
|||
[ALC883_MITAC] = "mitac",
|
||||
[ALC883_CLEVO_M720] = "clevo-m720",
|
||||
[ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
|
||||
[ALC883_3ST_6ch_INTEL] = "3stack-6ch-intel",
|
||||
[ALC883_AUTO] = "auto",
|
||||
};
|
||||
|
||||
|
@ -7786,6 +7954,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
|
|||
SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2),
|
||||
SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
|
||||
SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
|
||||
SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
|
||||
SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
|
||||
SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
|
||||
{}
|
||||
};
|
||||
|
@ -7824,6 +7994,18 @@ static struct alc_config_preset alc883_presets[] = {
|
|||
.need_dac_fix = 1,
|
||||
.input_mux = &alc883_capture_source,
|
||||
},
|
||||
[ALC883_3ST_6ch_INTEL] = {
|
||||
.mixers = { alc883_3ST_6ch_intel_mixer, alc883_chmode_mixer },
|
||||
.init_verbs = { alc883_init_verbs },
|
||||
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
|
||||
.dac_nids = alc883_dac_nids,
|
||||
.dig_out_nid = ALC883_DIGOUT_NID,
|
||||
.dig_in_nid = ALC883_DIGIN_NID,
|
||||
.num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
|
||||
.channel_mode = alc883_3ST_6ch_intel_modes,
|
||||
.need_dac_fix = 1,
|
||||
.input_mux = &alc883_3stack_6ch_intel,
|
||||
},
|
||||
[ALC883_6ST_DIG] = {
|
||||
.mixers = { alc883_base_mixer, alc883_chmode_mixer },
|
||||
.init_verbs = { alc883_init_verbs },
|
||||
|
@ -8145,6 +8327,8 @@ static int patch_alc883(struct hda_codec *codec)
|
|||
|
||||
codec->spec = spec;
|
||||
|
||||
alc_fix_pll_init(codec, 0x20, 0x0a, 10);
|
||||
|
||||
board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST,
|
||||
alc883_models,
|
||||
alc883_cfg_tbl);
|
||||
|
@ -8171,12 +8355,25 @@ static int patch_alc883(struct hda_codec *codec)
|
|||
if (board_config != ALC883_AUTO)
|
||||
setup_preset(spec, &alc883_presets[board_config]);
|
||||
|
||||
spec->stream_name_analog = "ALC883 Analog";
|
||||
switch (codec->vendor_id) {
|
||||
case 0x10ec0888:
|
||||
spec->stream_name_analog = "ALC888 Analog";
|
||||
spec->stream_name_digital = "ALC888 Digital";
|
||||
break;
|
||||
case 0x10ec0889:
|
||||
spec->stream_name_analog = "ALC889 Analog";
|
||||
spec->stream_name_digital = "ALC889 Digital";
|
||||
break;
|
||||
default:
|
||||
spec->stream_name_analog = "ALC883 Analog";
|
||||
spec->stream_name_digital = "ALC883 Digital";
|
||||
break;
|
||||
}
|
||||
|
||||
spec->stream_analog_playback = &alc883_pcm_analog_playback;
|
||||
spec->stream_analog_capture = &alc883_pcm_analog_capture;
|
||||
spec->stream_analog_alt_capture = &alc883_pcm_analog_alt_capture;
|
||||
|
||||
spec->stream_name_digital = "ALC883 Digital";
|
||||
spec->stream_digital_playback = &alc883_pcm_digital_playback;
|
||||
spec->stream_digital_capture = &alc883_pcm_digital_capture;
|
||||
|
||||
|
@ -8189,6 +8386,9 @@ static int patch_alc883(struct hda_codec *codec)
|
|||
codec->patch_ops = alc_patch_ops;
|
||||
if (board_config == ALC883_AUTO)
|
||||
spec->init_hook = alc883_auto_init;
|
||||
else if (codec->vendor_id == 0x10ec0888)
|
||||
spec->init_hook = alc888_coef_init;
|
||||
|
||||
#ifdef CONFIG_SND_HDA_POWER_SAVE
|
||||
if (!spec->loopback.amplist)
|
||||
spec->loopback.amplist = alc883_loopbacks;
|
||||
|
@ -9522,6 +9722,8 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
|
|||
SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
|
||||
SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD),
|
||||
SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
|
||||
SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
|
||||
ALC262_SONY_ASSAMD),
|
||||
SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
|
||||
SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
|
||||
SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),
|
||||
|
@ -9729,6 +9931,8 @@ static int patch_alc262(struct hda_codec *codec)
|
|||
}
|
||||
#endif
|
||||
|
||||
alc_fix_pll_init(codec, 0x20, 0x0a, 10);
|
||||
|
||||
board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
|
||||
alc262_models,
|
||||
alc262_cfg_tbl);
|
||||
|
@ -10674,12 +10878,18 @@ static int patch_alc268(struct hda_codec *codec)
|
|||
if (board_config != ALC268_AUTO)
|
||||
setup_preset(spec, &alc268_presets[board_config]);
|
||||
|
||||
spec->stream_name_analog = "ALC268 Analog";
|
||||
if (codec->vendor_id == 0x10ec0267) {
|
||||
spec->stream_name_analog = "ALC267 Analog";
|
||||
spec->stream_name_digital = "ALC267 Digital";
|
||||
} else {
|
||||
spec->stream_name_analog = "ALC268 Analog";
|
||||
spec->stream_name_digital = "ALC268 Digital";
|
||||
}
|
||||
|
||||
spec->stream_analog_playback = &alc268_pcm_analog_playback;
|
||||
spec->stream_analog_capture = &alc268_pcm_analog_capture;
|
||||
spec->stream_analog_alt_capture = &alc268_pcm_analog_alt_capture;
|
||||
|
||||
spec->stream_name_digital = "ALC268 Digital";
|
||||
spec->stream_digital_playback = &alc268_pcm_digital_playback;
|
||||
|
||||
if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
|
||||
|
@ -11033,6 +11243,8 @@ static int patch_alc269(struct hda_codec *codec)
|
|||
|
||||
codec->spec = spec;
|
||||
|
||||
alc_fix_pll_init(codec, 0x20, 0x04, 15);
|
||||
|
||||
board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
|
||||
alc269_models,
|
||||
alc269_cfg_tbl);
|
||||
|
@ -12631,6 +12843,12 @@ static struct hda_verb alc861vd_eapd_verbs[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
static struct hda_verb alc660vd_eapd_verbs[] = {
|
||||
{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
|
||||
{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
|
||||
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
|
||||
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
|
||||
|
@ -12786,6 +13004,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
|
|||
SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
|
||||
SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
|
||||
SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 N200", ALC861VD_LENOVO),
|
||||
SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
|
||||
{}
|
||||
};
|
||||
|
@ -13168,11 +13387,19 @@ static int patch_alc861vd(struct hda_codec *codec)
|
|||
if (board_config != ALC861VD_AUTO)
|
||||
setup_preset(spec, &alc861vd_presets[board_config]);
|
||||
|
||||
spec->stream_name_analog = "ALC861VD Analog";
|
||||
if (codec->vendor_id == 0x10ec0660) {
|
||||
spec->stream_name_analog = "ALC660-VD Analog";
|
||||
spec->stream_name_digital = "ALC660-VD Digital";
|
||||
/* always turn on EAPD */
|
||||
spec->init_verbs[spec->num_init_verbs++] = alc660vd_eapd_verbs;
|
||||
} else {
|
||||
spec->stream_name_analog = "ALC861VD Analog";
|
||||
spec->stream_name_digital = "ALC861VD Digital";
|
||||
}
|
||||
|
||||
spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
|
||||
spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
|
||||
|
||||
spec->stream_name_digital = "ALC861VD Digital";
|
||||
spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
|
||||
spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
|
||||
|
||||
|
@ -13251,6 +13478,23 @@ static struct hda_input_mux alc662_eeepc_capture_source = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct hda_input_mux alc663_capture_source = {
|
||||
.num_items = 3,
|
||||
.items = {
|
||||
{ "Mic", 0x0 },
|
||||
{ "Front Mic", 0x1 },
|
||||
{ "Line", 0x2 },
|
||||
},
|
||||
};
|
||||
|
||||
static struct hda_input_mux alc663_m51va_capture_source = {
|
||||
.num_items = 2,
|
||||
.items = {
|
||||
{ "Ext-Mic", 0x0 },
|
||||
{ "D-Mic", 0x9 },
|
||||
},
|
||||
};
|
||||
|
||||
#define alc662_mux_enum_info alc_mux_enum_info
|
||||
#define alc662_mux_enum_get alc_mux_enum_get
|
||||
#define alc662_mux_enum_put alc882_mux_enum_put
|
||||
|
@ -13431,6 +13675,44 @@ static struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
|
|||
{ } /* end */
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new alc663_m51va_mixer[] = {
|
||||
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("DMic Playback Switch", 0x23, 0x9, HDA_INPUT),
|
||||
{ } /* end */
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new alc663_g71v_mixer[] = {
|
||||
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
|
||||
|
||||
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
|
||||
{ } /* end */
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new alc663_g50v_mixer[] = {
|
||||
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
|
||||
|
||||
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
|
||||
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
|
||||
{ } /* end */
|
||||
};
|
||||
|
||||
static struct snd_kcontrol_new alc662_chmode_mixer[] = {
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
|
@ -13501,6 +13783,11 @@ static struct hda_verb alc662_init_verbs[] = {
|
|||
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
|
||||
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
|
||||
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
|
||||
|
||||
/* always trun on EAPD */
|
||||
{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
|
||||
{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
|
||||
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -13571,6 +13858,43 @@ static struct hda_verb alc662_auto_init_verbs[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
static struct hda_verb alc663_m51va_init_verbs[] = {
|
||||
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
|
||||
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
|
||||
{0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
|
||||
|
||||
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
|
||||
|
||||
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
|
||||
{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct hda_verb alc663_g71v_init_verbs[] = {
|
||||
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
|
||||
/* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
|
||||
/* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
|
||||
|
||||
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
|
||||
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
|
||||
{0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
|
||||
|
||||
{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
|
||||
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_MIC_EVENT},
|
||||
{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct hda_verb alc663_g50v_init_verbs[] = {
|
||||
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
|
||||
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
|
||||
{0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
|
||||
|
||||
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
|
||||
{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
|
||||
{}
|
||||
};
|
||||
|
||||
/* capture mixer elements */
|
||||
static struct snd_kcontrol_new alc662_capture_mixer[] = {
|
||||
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
|
||||
|
@ -13692,6 +14016,125 @@ static void alc662_eeepc_ep20_inithook(struct hda_codec *codec)
|
|||
alc662_eeepc_ep20_automute(codec);
|
||||
}
|
||||
|
||||
static void alc663_m51va_speaker_automute(struct hda_codec *codec)
|
||||
{
|
||||
unsigned int present;
|
||||
unsigned char bits;
|
||||
|
||||
present = snd_hda_codec_read(codec, 0x21, 0,
|
||||
AC_VERB_GET_PIN_SENSE, 0)
|
||||
& AC_PINSENSE_PRESENCE;
|
||||
bits = present ? HDA_AMP_MUTE : 0;
|
||||
snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
|
||||
HDA_AMP_MUTE, bits);
|
||||
}
|
||||
|
||||
static void alc663_m51va_mic_automute(struct hda_codec *codec)
|
||||
{
|
||||
unsigned int present;
|
||||
|
||||
present = snd_hda_codec_read(codec, 0x18, 0,
|
||||
AC_VERB_GET_PIN_SENSE, 0)
|
||||
& AC_PINSENSE_PRESENCE;
|
||||
snd_hda_codec_write_cache(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
|
||||
0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
|
||||
snd_hda_codec_write_cache(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
|
||||
0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
|
||||
snd_hda_codec_write_cache(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
|
||||
0x7000 | (0x09 << 8) | (present ? 0x80 : 0));
|
||||
snd_hda_codec_write_cache(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
|
||||
0x7000 | (0x09 << 8) | (present ? 0x80 : 0));
|
||||
}
|
||||
|
||||
static void alc663_m51va_unsol_event(struct hda_codec *codec,
|
||||
unsigned int res)
|
||||
{
|
||||
switch (res >> 26) {
|
||||
case ALC880_HP_EVENT:
|
||||
alc663_m51va_speaker_automute(codec);
|
||||
break;
|
||||
case ALC880_MIC_EVENT:
|
||||
alc663_m51va_mic_automute(codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc663_m51va_inithook(struct hda_codec *codec)
|
||||
{
|
||||
alc663_m51va_speaker_automute(codec);
|
||||
alc663_m51va_mic_automute(codec);
|
||||
}
|
||||
|
||||
static void alc663_g71v_hp_automute(struct hda_codec *codec)
|
||||
{
|
||||
unsigned int present;
|
||||
unsigned char bits;
|
||||
|
||||
present = snd_hda_codec_read(codec, 0x21, 0,
|
||||
AC_VERB_GET_PIN_SENSE, 0)
|
||||
& AC_PINSENSE_PRESENCE;
|
||||
bits = present ? HDA_AMP_MUTE : 0;
|
||||
snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
|
||||
HDA_AMP_MUTE, bits);
|
||||
snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
|
||||
HDA_AMP_MUTE, bits);
|
||||
}
|
||||
|
||||
static void alc663_g71v_front_automute(struct hda_codec *codec)
|
||||
{
|
||||
unsigned int present;
|
||||
unsigned char bits;
|
||||
|
||||
present = snd_hda_codec_read(codec, 0x15, 0,
|
||||
AC_VERB_GET_PIN_SENSE, 0)
|
||||
& AC_PINSENSE_PRESENCE;
|
||||
bits = present ? HDA_AMP_MUTE : 0;
|
||||
snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
|
||||
HDA_AMP_MUTE, bits);
|
||||
}
|
||||
|
||||
static void alc663_g71v_unsol_event(struct hda_codec *codec,
|
||||
unsigned int res)
|
||||
{
|
||||
switch (res >> 26) {
|
||||
case ALC880_HP_EVENT:
|
||||
alc663_g71v_hp_automute(codec);
|
||||
break;
|
||||
case ALC880_FRONT_EVENT:
|
||||
alc663_g71v_front_automute(codec);
|
||||
break;
|
||||
case ALC880_MIC_EVENT:
|
||||
alc662_eeepc_mic_automute(codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc663_g71v_inithook(struct hda_codec *codec)
|
||||
{
|
||||
alc663_g71v_front_automute(codec);
|
||||
alc663_g71v_hp_automute(codec);
|
||||
alc662_eeepc_mic_automute(codec);
|
||||
}
|
||||
|
||||
static void alc663_g50v_unsol_event(struct hda_codec *codec,
|
||||
unsigned int res)
|
||||
{
|
||||
switch (res >> 26) {
|
||||
case ALC880_HP_EVENT:
|
||||
alc663_m51va_speaker_automute(codec);
|
||||
break;
|
||||
case ALC880_MIC_EVENT:
|
||||
alc662_eeepc_mic_automute(codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void alc663_g50v_inithook(struct hda_codec *codec)
|
||||
{
|
||||
alc663_m51va_speaker_automute(codec);
|
||||
alc662_eeepc_mic_automute(codec);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_HDA_POWER_SAVE
|
||||
#define alc662_loopbacks alc880_loopbacks
|
||||
#endif
|
||||
|
@ -13714,14 +14157,24 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
|
|||
[ALC662_LENOVO_101E] = "lenovo-101e",
|
||||
[ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
|
||||
[ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
|
||||
[ALC663_ASUS_M51VA] = "m51va",
|
||||
[ALC663_ASUS_G71V] = "g71v",
|
||||
[ALC663_ASUS_H13] = "h13",
|
||||
[ALC663_ASUS_G50V] = "g50v",
|
||||
[ALC662_AUTO] = "auto",
|
||||
};
|
||||
|
||||
static struct snd_pci_quirk alc662_cfg_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS G71V", ALC663_ASUS_G71V),
|
||||
SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
|
||||
SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS M51VA", ALC663_ASUS_G50V),
|
||||
SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
|
||||
SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
|
||||
SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
|
||||
SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
|
||||
SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13),
|
||||
SND_PCI_QUIRK(0x1854, 0x2001, "ASUS H13-2001", ALC663_ASUS_H13),
|
||||
SND_PCI_QUIRK(0x1854, 0x2002, "ASUS H13-2002", ALC663_ASUS_H13),
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -13809,7 +14262,53 @@ static struct alc_config_preset alc662_presets[] = {
|
|||
.unsol_event = alc662_eeepc_ep20_unsol_event,
|
||||
.init_hook = alc662_eeepc_ep20_inithook,
|
||||
},
|
||||
|
||||
[ALC663_ASUS_M51VA] = {
|
||||
.mixers = { alc663_m51va_mixer, alc662_capture_mixer},
|
||||
.init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
|
||||
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
|
||||
.dac_nids = alc662_dac_nids,
|
||||
.dig_out_nid = ALC662_DIGOUT_NID,
|
||||
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
|
||||
.channel_mode = alc662_3ST_2ch_modes,
|
||||
.input_mux = &alc663_m51va_capture_source,
|
||||
.unsol_event = alc663_m51va_unsol_event,
|
||||
.init_hook = alc663_m51va_inithook,
|
||||
},
|
||||
[ALC663_ASUS_G71V] = {
|
||||
.mixers = { alc663_g71v_mixer, alc662_capture_mixer},
|
||||
.init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
|
||||
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
|
||||
.dac_nids = alc662_dac_nids,
|
||||
.dig_out_nid = ALC662_DIGOUT_NID,
|
||||
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
|
||||
.channel_mode = alc662_3ST_2ch_modes,
|
||||
.input_mux = &alc662_eeepc_capture_source,
|
||||
.unsol_event = alc663_g71v_unsol_event,
|
||||
.init_hook = alc663_g71v_inithook,
|
||||
},
|
||||
[ALC663_ASUS_H13] = {
|
||||
.mixers = { alc663_m51va_mixer, alc662_capture_mixer},
|
||||
.init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
|
||||
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
|
||||
.dac_nids = alc662_dac_nids,
|
||||
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
|
||||
.channel_mode = alc662_3ST_2ch_modes,
|
||||
.input_mux = &alc663_m51va_capture_source,
|
||||
.unsol_event = alc663_m51va_unsol_event,
|
||||
.init_hook = alc663_m51va_inithook,
|
||||
},
|
||||
[ALC663_ASUS_G50V] = {
|
||||
.mixers = { alc663_g50v_mixer, alc662_capture_mixer},
|
||||
.init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
|
||||
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
|
||||
.dac_nids = alc662_dac_nids,
|
||||
.dig_out_nid = ALC662_DIGOUT_NID,
|
||||
.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
|
||||
.channel_mode = alc662_3ST_6ch_modes,
|
||||
.input_mux = &alc663_capture_source,
|
||||
.unsol_event = alc663_g50v_unsol_event,
|
||||
.init_hook = alc663_g50v_inithook,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
@ -14082,6 +14581,8 @@ static int patch_alc662(struct hda_codec *codec)
|
|||
|
||||
codec->spec = spec;
|
||||
|
||||
alc_fix_pll_init(codec, 0x20, 0x04, 15);
|
||||
|
||||
board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
|
||||
alc662_models,
|
||||
alc662_cfg_tbl);
|
||||
|
@ -14108,11 +14609,17 @@ static int patch_alc662(struct hda_codec *codec)
|
|||
if (board_config != ALC662_AUTO)
|
||||
setup_preset(spec, &alc662_presets[board_config]);
|
||||
|
||||
spec->stream_name_analog = "ALC662 Analog";
|
||||
if (codec->vendor_id == 0x10ec0663) {
|
||||
spec->stream_name_analog = "ALC663 Analog";
|
||||
spec->stream_name_digital = "ALC663 Digital";
|
||||
} else {
|
||||
spec->stream_name_analog = "ALC662 Analog";
|
||||
spec->stream_name_digital = "ALC662 Digital";
|
||||
}
|
||||
|
||||
spec->stream_analog_playback = &alc662_pcm_analog_playback;
|
||||
spec->stream_analog_capture = &alc662_pcm_analog_capture;
|
||||
|
||||
spec->stream_name_digital = "ALC662 Digital";
|
||||
spec->stream_digital_playback = &alc662_pcm_digital_playback;
|
||||
spec->stream_digital_capture = &alc662_pcm_digital_capture;
|
||||
|
||||
|
@ -14151,6 +14658,7 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
|
|||
.patch = patch_alc883 },
|
||||
{ .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
|
||||
.patch = patch_alc662 },
|
||||
{ .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
|
||||
{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
|
||||
{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
|
||||
{ .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
|
||||
|
|
|
@ -636,21 +636,28 @@ static struct hda_verb stac92hd71bxx_core_init[] = {
|
|||
{ 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
|
||||
};
|
||||
|
||||
#define HD_DISABLE_PORTF 3
|
||||
static struct hda_verb stac92hd71bxx_analog_core_init[] = {
|
||||
/* start of config #1 */
|
||||
|
||||
/* connect port 0f to audio mixer */
|
||||
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2},
|
||||
{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Speaker */
|
||||
/* unmute right and left channels for node 0x0f */
|
||||
{ 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
|
||||
/* start of config #2 */
|
||||
|
||||
/* set master volume and direct control */
|
||||
{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
|
||||
/* connect headphone jack to dac1 */
|
||||
{ 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
|
||||
/* connect ports 0d and 0f to audio mixer */
|
||||
/* connect port 0d to audio mixer */
|
||||
{ 0x0d, AC_VERB_SET_CONNECT_SEL, 0x2},
|
||||
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2},
|
||||
{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Speaker */
|
||||
/* unmute dac0 input in audio mixer */
|
||||
{ 0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
|
||||
/* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */
|
||||
/* unmute right and left channels for nodes 0x0a, 0xd */
|
||||
{ 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
|
||||
{ 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
|
||||
{ 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -818,6 +825,9 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
|
|||
HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT),
|
||||
HDA_CODEC_VOLUME_IDX("Capture Mux Volume", 0x1, 0x1b, 0x0, HDA_OUTPUT),
|
||||
|
||||
HDA_CODEC_VOLUME("PC Beep Volume", 0x17, 0x2, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("PC Beep Switch", 0x17, 0x2, HDA_INPUT),
|
||||
|
||||
HDA_CODEC_MUTE("Analog Loopback 1", 0x17, 0x3, HDA_INPUT),
|
||||
HDA_CODEC_MUTE("Analog Loopback 2", 0x17, 0x4, HDA_INPUT),
|
||||
{ } /* end */
|
||||
|
@ -1317,13 +1327,13 @@ static unsigned int ref92hd71bxx_pin_configs[10] = {
|
|||
0x90a000f0, 0x01452050,
|
||||
};
|
||||
|
||||
static unsigned int dell_m4_1_pin_configs[13] = {
|
||||
static unsigned int dell_m4_1_pin_configs[10] = {
|
||||
0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110,
|
||||
0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0,
|
||||
0x40f000f0, 0x4f0000f0,
|
||||
};
|
||||
|
||||
static unsigned int dell_m4_2_pin_configs[13] = {
|
||||
static unsigned int dell_m4_2_pin_configs[10] = {
|
||||
0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
|
||||
0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0,
|
||||
0x40f000f0, 0x044413b0,
|
||||
|
@ -1754,12 +1764,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
|
|||
"unknown Dell", STAC_9205_DELL_M42),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f8,
|
||||
"Dell Precision", STAC_9205_DELL_M43),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c,
|
||||
"Dell Precision", STAC_9205_DELL_M43),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f9,
|
||||
"Dell Precision", STAC_9205_DELL_M43),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b,
|
||||
"Dell Precision", STAC_9205_DELL_M43),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fa,
|
||||
"Dell Precision", STAC_9205_DELL_M43),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc,
|
||||
|
@ -1770,18 +1776,14 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
|
|||
"Dell Precision", STAC_9205_DELL_M43),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ff,
|
||||
"Dell Precision M4300", STAC_9205_DELL_M43),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206,
|
||||
"Dell Precision", STAC_9205_DELL_M43),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1,
|
||||
"Dell Inspiron", STAC_9205_DELL_M44),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2,
|
||||
"Dell Inspiron", STAC_9205_DELL_M44),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc,
|
||||
"Dell Inspiron", STAC_9205_DELL_M44),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd,
|
||||
"Dell Inspiron", STAC_9205_DELL_M44),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0204,
|
||||
"unknown Dell", STAC_9205_DELL_M42),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206,
|
||||
"Dell Precision", STAC_9205_DELL_M43),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b,
|
||||
"Dell Precision", STAC_9205_DELL_M43),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c,
|
||||
"Dell Precision", STAC_9205_DELL_M43),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f,
|
||||
"Dell Inspiron", STAC_9205_DELL_M44),
|
||||
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228,
|
||||
|
@ -3103,13 +3105,16 @@ static int stac92xx_init(struct hda_codec *codec)
|
|||
0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
|
||||
int def_conf = snd_hda_codec_read(codec, spec->pwr_nids[i],
|
||||
0, AC_VERB_GET_CONFIG_DEFAULT, 0);
|
||||
def_conf = get_defcfg_connect(def_conf);
|
||||
/* outputs are only ports capable of power management
|
||||
* any attempts on powering down a input port cause the
|
||||
* referenced VREF to act quirky.
|
||||
*/
|
||||
if (pinctl & AC_PINCTL_IN_EN)
|
||||
continue;
|
||||
if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED)
|
||||
/* skip any ports that don't have jacks since presence
|
||||
* detection is useless */
|
||||
if (def_conf && def_conf != AC_JACK_PORT_FIXED)
|
||||
continue;
|
||||
enable_pin_detect(codec, spec->pwr_nids[i], event | i);
|
||||
codec->patch_ops.unsol_event(codec, (event | i) << 26);
|
||||
|
@ -3614,6 +3619,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
|
|||
|
||||
codec->spec = spec;
|
||||
spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids);
|
||||
spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
|
||||
spec->pin_nids = stac92hd71bxx_pin_nids;
|
||||
spec->board_config = snd_hda_check_board_config(codec,
|
||||
STAC_92HD71BXX_MODELS,
|
||||
|
@ -3642,6 +3648,19 @@ again:
|
|||
spec->mixer = stac92hd71bxx_mixer;
|
||||
spec->init = stac92hd71bxx_core_init;
|
||||
break;
|
||||
case 0x111d7608: /* 5 Port with Analog Mixer */
|
||||
/* no output amps */
|
||||
spec->num_pwrs = 0;
|
||||
spec->mixer = stac92hd71bxx_analog_mixer;
|
||||
|
||||
/* disable VSW */
|
||||
spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
|
||||
stac92xx_set_config_reg(codec, 0xf, 0x40f000f0);
|
||||
break;
|
||||
case 0x111d7603: /* 6 Port with Analog Mixer */
|
||||
/* no output amps */
|
||||
spec->num_pwrs = 0;
|
||||
/* fallthru */
|
||||
default:
|
||||
spec->mixer = stac92hd71bxx_analog_mixer;
|
||||
spec->init = stac92hd71bxx_analog_core_init;
|
||||
|
@ -3653,22 +3672,19 @@ again:
|
|||
/* GPIO0 High = EAPD */
|
||||
spec->gpio_mask = 0x01;
|
||||
spec->gpio_dir = 0x01;
|
||||
spec->gpio_mask = 0x01;
|
||||
spec->gpio_data = 0x01;
|
||||
|
||||
spec->mux_nids = stac92hd71bxx_mux_nids;
|
||||
spec->adc_nids = stac92hd71bxx_adc_nids;
|
||||
spec->dmic_nids = stac92hd71bxx_dmic_nids;
|
||||
spec->dmux_nids = stac92hd71bxx_dmux_nids;
|
||||
spec->pwr_nids = stac92hd71bxx_pwr_nids;
|
||||
|
||||
spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids);
|
||||
spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids);
|
||||
spec->num_dmics = STAC92HD71BXX_NUM_DMICS;
|
||||
spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
|
||||
|
||||
spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
|
||||
spec->pwr_nids = stac92hd71bxx_pwr_nids;
|
||||
|
||||
spec->multiout.num_dacs = 1;
|
||||
spec->multiout.hp_nid = 0x11;
|
||||
spec->multiout.dac_nids = stac92hd71bxx_dac_nids;
|
||||
|
@ -4306,10 +4322,11 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = {
|
|||
{ .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 },
|
||||
{ .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 },
|
||||
{ .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 },
|
||||
{ .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx},
|
||||
{ .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx},
|
||||
{ .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx },
|
||||
{ .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx },
|
||||
{ .id = 0x111d7676, .name = "92HD73E1X5", .patch = patch_stac92hd73xx },
|
||||
{ .id = 0x111d7608, .name = "92HD71BXX", .patch = patch_stac92hd71bxx },
|
||||
{ .id = 0x111d76b0, .name = "92HD71B8X", .patch = patch_stac92hd71bxx },
|
||||
{ .id = 0x111d76b1, .name = "92HD71B8X", .patch = patch_stac92hd71bxx },
|
||||
{ .id = 0x111d76b2, .name = "92HD71B7X", .patch = patch_stac92hd71bxx },
|
||||
|
|
|
@ -93,9 +93,13 @@ enum {
|
|||
#define VT1724_REG_MPU_TXFIFO 0x0a /*byte ro. number of bytes in TX fifo*/
|
||||
#define VT1724_REG_MPU_RXFIFO 0x0b /*byte ro. number of bytes in RX fifo*/
|
||||
|
||||
//are these 2 the wrong way around? they don't seem to be used yet anyway
|
||||
#define VT1724_REG_MPU_CTRL 0x0c /* byte */
|
||||
#define VT1724_REG_MPU_DATA 0x0d /* byte */
|
||||
#define VT1724_REG_MPU_DATA 0x0c /* byte */
|
||||
#define VT1724_REG_MPU_CTRL 0x0d /* byte */
|
||||
#define VT1724_MPU_UART 0x01
|
||||
#define VT1724_MPU_TX_EMPTY 0x02
|
||||
#define VT1724_MPU_TX_FULL 0x04
|
||||
#define VT1724_MPU_RX_EMPTY 0x08
|
||||
#define VT1724_MPU_RX_FULL 0x10
|
||||
|
||||
#define VT1724_REG_MPU_FIFO_WM 0x0e /*byte set the high/low watermarks for RX/TX fifos*/
|
||||
#define VT1724_MPU_RX_FIFO 0x20 //1=rx fifo watermark 0=tx fifo watermark
|
||||
|
|
|
@ -333,6 +333,8 @@ struct snd_ice1712 {
|
|||
unsigned int has_spdif: 1; /* VT1720/4 - has SPDIF I/O */
|
||||
unsigned int force_pdma4: 1; /* VT1720/4 - PDMA4 as non-spdif */
|
||||
unsigned int force_rdma1: 1; /* VT1720/4 - RDMA1 as non-spdif */
|
||||
unsigned int midi_output: 1; /* VT1720/4: MIDI output triggered */
|
||||
unsigned int midi_input: 1; /* VT1720/4: MIDI input triggered */
|
||||
unsigned int num_total_dacs; /* total DACs */
|
||||
unsigned int num_total_adcs; /* total ADCs */
|
||||
unsigned int cur_rate; /* current rate */
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <linux/mutex.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/info.h>
|
||||
#include <sound/mpu401.h>
|
||||
#include <sound/rawmidi.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
#include <sound/asoundef.h>
|
||||
|
@ -223,30 +223,153 @@ static unsigned int snd_vt1724_get_gpio_data(struct snd_ice1712 *ice)
|
|||
}
|
||||
|
||||
/*
|
||||
* MPU401 accessor
|
||||
* MIDI
|
||||
*/
|
||||
static unsigned char snd_vt1724_mpu401_read(struct snd_mpu401 *mpu,
|
||||
unsigned long addr)
|
||||
|
||||
static void vt1724_midi_clear_rx(struct snd_ice1712 *ice)
|
||||
{
|
||||
/* fix status bits to the standard position */
|
||||
/* only RX_EMPTY and TX_FULL are checked */
|
||||
if (addr == MPU401C(mpu))
|
||||
return (inb(addr) & 0x0c) << 4;
|
||||
else
|
||||
return inb(addr);
|
||||
unsigned int count;
|
||||
|
||||
for (count = inb(ICEREG1724(ice, MPU_RXFIFO)); count > 0; --count)
|
||||
inb(ICEREG1724(ice, MPU_DATA));
|
||||
}
|
||||
|
||||
static void snd_vt1724_mpu401_write(struct snd_mpu401 *mpu,
|
||||
unsigned char data, unsigned long addr)
|
||||
static inline struct snd_rawmidi_substream *
|
||||
get_rawmidi_substream(struct snd_ice1712 *ice, unsigned int stream)
|
||||
{
|
||||
if (addr == MPU401C(mpu)) {
|
||||
if (data == MPU401_ENTER_UART)
|
||||
outb(0x01, addr);
|
||||
/* what else? */
|
||||
} else
|
||||
outb(data, addr);
|
||||
return list_first_entry(&ice->rmidi[0]->streams[stream].substreams,
|
||||
struct snd_rawmidi_substream, list);
|
||||
}
|
||||
|
||||
static void vt1724_midi_write(struct snd_ice1712 *ice)
|
||||
{
|
||||
struct snd_rawmidi_substream *s;
|
||||
int count, i;
|
||||
u8 buffer[32];
|
||||
|
||||
s = get_rawmidi_substream(ice, SNDRV_RAWMIDI_STREAM_OUTPUT);
|
||||
count = 31 - inb(ICEREG1724(ice, MPU_TXFIFO));
|
||||
if (count > 0) {
|
||||
count = snd_rawmidi_transmit(s, buffer, count);
|
||||
for (i = 0; i < count; ++i)
|
||||
outb(buffer[i], ICEREG1724(ice, MPU_DATA));
|
||||
}
|
||||
}
|
||||
|
||||
static void vt1724_midi_read(struct snd_ice1712 *ice)
|
||||
{
|
||||
struct snd_rawmidi_substream *s;
|
||||
int count, i;
|
||||
u8 buffer[32];
|
||||
|
||||
s = get_rawmidi_substream(ice, SNDRV_RAWMIDI_STREAM_INPUT);
|
||||
count = inb(ICEREG1724(ice, MPU_RXFIFO));
|
||||
if (count > 0) {
|
||||
count = min(count, 32);
|
||||
for (i = 0; i < count; ++i)
|
||||
buffer[i] = inb(ICEREG1724(ice, MPU_DATA));
|
||||
snd_rawmidi_receive(s, buffer, count);
|
||||
}
|
||||
}
|
||||
|
||||
static void vt1724_enable_midi_irq(struct snd_rawmidi_substream *substream,
|
||||
u8 flag, int enable)
|
||||
{
|
||||
struct snd_ice1712 *ice = substream->rmidi->private_data;
|
||||
u8 mask;
|
||||
|
||||
spin_lock_irq(&ice->reg_lock);
|
||||
mask = inb(ICEREG1724(ice, IRQMASK));
|
||||
if (enable)
|
||||
mask &= ~flag;
|
||||
else
|
||||
mask |= flag;
|
||||
outb(mask, ICEREG1724(ice, IRQMASK));
|
||||
spin_unlock_irq(&ice->reg_lock);
|
||||
}
|
||||
|
||||
static int vt1724_midi_output_open(struct snd_rawmidi_substream *s)
|
||||
{
|
||||
vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vt1724_midi_output_close(struct snd_rawmidi_substream *s)
|
||||
{
|
||||
vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vt1724_midi_output_trigger(struct snd_rawmidi_substream *s, int up)
|
||||
{
|
||||
struct snd_ice1712 *ice = s->rmidi->private_data;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ice->reg_lock, flags);
|
||||
if (up) {
|
||||
ice->midi_output = 1;
|
||||
vt1724_midi_write(ice);
|
||||
} else {
|
||||
ice->midi_output = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&ice->reg_lock, flags);
|
||||
}
|
||||
|
||||
static void vt1724_midi_output_drain(struct snd_rawmidi_substream *s)
|
||||
{
|
||||
struct snd_ice1712 *ice = s->rmidi->private_data;
|
||||
unsigned long timeout;
|
||||
|
||||
/* 32 bytes should be transmitted in less than about 12 ms */
|
||||
timeout = jiffies + msecs_to_jiffies(15);
|
||||
do {
|
||||
if (inb(ICEREG1724(ice, MPU_CTRL)) & VT1724_MPU_TX_EMPTY)
|
||||
break;
|
||||
schedule_timeout_uninterruptible(1);
|
||||
} while (time_after(timeout, jiffies));
|
||||
}
|
||||
|
||||
static struct snd_rawmidi_ops vt1724_midi_output_ops = {
|
||||
.open = vt1724_midi_output_open,
|
||||
.close = vt1724_midi_output_close,
|
||||
.trigger = vt1724_midi_output_trigger,
|
||||
.drain = vt1724_midi_output_drain,
|
||||
};
|
||||
|
||||
static int vt1724_midi_input_open(struct snd_rawmidi_substream *s)
|
||||
{
|
||||
vt1724_midi_clear_rx(s->rmidi->private_data);
|
||||
vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_RX, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vt1724_midi_input_close(struct snd_rawmidi_substream *s)
|
||||
{
|
||||
vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_RX, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vt1724_midi_input_trigger(struct snd_rawmidi_substream *s, int up)
|
||||
{
|
||||
struct snd_ice1712 *ice = s->rmidi->private_data;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ice->reg_lock, flags);
|
||||
if (up) {
|
||||
ice->midi_input = 1;
|
||||
vt1724_midi_read(ice);
|
||||
} else {
|
||||
ice->midi_input = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&ice->reg_lock, flags);
|
||||
}
|
||||
|
||||
static struct snd_rawmidi_ops vt1724_midi_input_ops = {
|
||||
.open = vt1724_midi_input_open,
|
||||
.close = vt1724_midi_input_close,
|
||||
.trigger = vt1724_midi_input_trigger,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Interrupt handler
|
||||
|
@ -278,13 +401,10 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
|
|||
#endif
|
||||
handled = 1;
|
||||
if (status & VT1724_IRQ_MPU_TX) {
|
||||
if (ice->rmidi[0])
|
||||
snd_mpu401_uart_interrupt_tx(irq,
|
||||
ice->rmidi[0]->private_data);
|
||||
else /* disable TX to be sure */
|
||||
outb(inb(ICEREG1724(ice, IRQMASK)) |
|
||||
VT1724_IRQ_MPU_TX,
|
||||
ICEREG1724(ice, IRQMASK));
|
||||
spin_lock(&ice->reg_lock);
|
||||
if (ice->midi_output)
|
||||
vt1724_midi_write(ice);
|
||||
spin_unlock(&ice->reg_lock);
|
||||
/* Due to mysterical reasons, MPU_TX is always
|
||||
* generated (and can't be cleared) when a PCM
|
||||
* playback is going. So let's ignore at the
|
||||
|
@ -293,13 +413,12 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
|
|||
status_mask &= ~VT1724_IRQ_MPU_TX;
|
||||
}
|
||||
if (status & VT1724_IRQ_MPU_RX) {
|
||||
if (ice->rmidi[0])
|
||||
snd_mpu401_uart_interrupt(irq,
|
||||
ice->rmidi[0]->private_data);
|
||||
else /* disable RX to be sure */
|
||||
outb(inb(ICEREG1724(ice, IRQMASK)) |
|
||||
VT1724_IRQ_MPU_RX,
|
||||
ICEREG1724(ice, IRQMASK));
|
||||
spin_lock(&ice->reg_lock);
|
||||
if (ice->midi_input)
|
||||
vt1724_midi_read(ice);
|
||||
else
|
||||
vt1724_midi_clear_rx(ice);
|
||||
spin_unlock(&ice->reg_lock);
|
||||
}
|
||||
/* ack MPU irq */
|
||||
outb(status, ICEREG1724(ice, IRQSTAT));
|
||||
|
@ -2425,28 +2544,30 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
|
|||
|
||||
if (! c->no_mpu401) {
|
||||
if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
|
||||
struct snd_mpu401 *mpu;
|
||||
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
|
||||
ICEREG1724(ice, MPU_CTRL),
|
||||
(MPU401_INFO_INTEGRATED |
|
||||
MPU401_INFO_NO_ACK |
|
||||
MPU401_INFO_TX_IRQ),
|
||||
ice->irq, 0,
|
||||
&ice->rmidi[0])) < 0) {
|
||||
struct snd_rawmidi *rmidi;
|
||||
|
||||
err = snd_rawmidi_new(card, "MIDI", 0, 1, 1, &rmidi);
|
||||
if (err < 0) {
|
||||
snd_card_free(card);
|
||||
return err;
|
||||
}
|
||||
mpu = ice->rmidi[0]->private_data;
|
||||
mpu->read = snd_vt1724_mpu401_read;
|
||||
mpu->write = snd_vt1724_mpu401_write;
|
||||
/* unmask MPU RX/TX irqs */
|
||||
outb(inb(ICEREG1724(ice, IRQMASK)) &
|
||||
~(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX),
|
||||
ICEREG1724(ice, IRQMASK));
|
||||
ice->rmidi[0] = rmidi;
|
||||
rmidi->private_data = ice;
|
||||
strcpy(rmidi->name, "ICE1724 MIDI");
|
||||
rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
|
||||
SNDRV_RAWMIDI_INFO_INPUT |
|
||||
SNDRV_RAWMIDI_INFO_DUPLEX;
|
||||
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
|
||||
&vt1724_midi_output_ops);
|
||||
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
|
||||
&vt1724_midi_input_ops);
|
||||
|
||||
/* set watermarks */
|
||||
outb(VT1724_MPU_RX_FIFO | 0x1,
|
||||
ICEREG1724(ice, MPU_FIFO_WM));
|
||||
outb(0x1, ICEREG1724(ice, MPU_FIFO_WM));
|
||||
/* set UART mode */
|
||||
outb(VT1724_MPU_UART, ICEREG1724(ice, MPU_CTRL));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2427,6 +2427,29 @@ snd_m3_amp_enable(struct snd_m3 *chip, int enable)
|
|||
outw(0xffff, io + GPIO_MASK);
|
||||
}
|
||||
|
||||
static void
|
||||
snd_m3_hv_init(struct snd_m3 *chip)
|
||||
{
|
||||
unsigned long io = chip->iobase;
|
||||
u16 val = GPI_VOL_DOWN | GPI_VOL_UP;
|
||||
|
||||
if (!chip->is_omnibook)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Volume buttons on some HP OmniBook laptops
|
||||
* require some GPIO magic to work correctly.
|
||||
*/
|
||||
outw(0xffff, io + GPIO_MASK);
|
||||
outw(0x0000, io + GPIO_DATA);
|
||||
|
||||
outw(~val, io + GPIO_MASK);
|
||||
outw(inw(io + GPIO_DIRECTION) & ~val, io + GPIO_DIRECTION);
|
||||
outw(val, io + GPIO_MASK);
|
||||
|
||||
outw(0xffff, io + GPIO_MASK);
|
||||
}
|
||||
|
||||
static int
|
||||
snd_m3_chip_init(struct snd_m3 *chip)
|
||||
{
|
||||
|
@ -2442,21 +2465,6 @@ snd_m3_chip_init(struct snd_m3 *chip)
|
|||
DISABLE_LEGACY);
|
||||
pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w);
|
||||
|
||||
if (chip->is_omnibook) {
|
||||
/*
|
||||
* Volume buttons on some HP OmniBook laptops don't work
|
||||
* correctly. This makes them work for the most part.
|
||||
*
|
||||
* Volume up and down buttons on the laptop side work.
|
||||
* Fn+cursor_up (volme up) works.
|
||||
* Fn+cursor_down (volume down) doesn't work.
|
||||
* Fn+F7 (mute) works acts as volume up.
|
||||
*/
|
||||
outw(~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_MASK);
|
||||
outw(inw(io + GPIO_DIRECTION) & ~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DIRECTION);
|
||||
outw((GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DATA);
|
||||
outw(0xffff, io + GPIO_MASK);
|
||||
}
|
||||
pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n);
|
||||
n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD);
|
||||
n |= chip->hv_config;
|
||||
|
@ -2642,6 +2650,8 @@ static int m3_resume(struct pci_dev *pci)
|
|||
snd_m3_enable_ints(chip);
|
||||
snd_m3_amp_enable(chip, 1);
|
||||
|
||||
snd_m3_hv_init(chip);
|
||||
|
||||
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2781,6 +2791,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
|
|||
|
||||
snd_m3_amp_enable(chip, 1);
|
||||
|
||||
snd_m3_hv_init(chip);
|
||||
|
||||
tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
|
||||
|
||||
if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED,
|
||||
|
|
|
@ -1302,8 +1302,8 @@ snd_nm256_mixer(struct nm256 *chip)
|
|||
.read = snd_nm256_ac97_read,
|
||||
};
|
||||
|
||||
chip->ac97_regs = kcalloc(sizeof(short),
|
||||
ARRAY_SIZE(nm256_ac97_init_val), GFP_KERNEL);
|
||||
chip->ac97_regs = kcalloc(ARRAY_SIZE(nm256_ac97_init_val),
|
||||
sizeof(short), GFP_KERNEL);
|
||||
if (! chip->ac97_regs)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
|
||||
MODULE_DESCRIPTION("TempoTec HiFier driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
|
||||
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
|
||||
|
@ -62,16 +62,28 @@ static void ak4396_write(struct oxygen *chip, u8 reg, u8 value)
|
|||
AK4396_WRITE | (reg << 8) | value);
|
||||
}
|
||||
|
||||
static void update_ak4396_volume(struct oxygen *chip)
|
||||
{
|
||||
ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]);
|
||||
ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]);
|
||||
}
|
||||
|
||||
static void hifier_registers_init(struct oxygen *chip)
|
||||
{
|
||||
struct hifier_data *data = chip->model_data;
|
||||
|
||||
ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
|
||||
ak4396_write(chip, AK4396_CONTROL_2, data->ak4396_ctl2);
|
||||
ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM);
|
||||
update_ak4396_volume(chip);
|
||||
}
|
||||
|
||||
static void hifier_init(struct oxygen *chip)
|
||||
{
|
||||
struct hifier_data *data = chip->model_data;
|
||||
|
||||
data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
|
||||
ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
|
||||
ak4396_write(chip, AK4396_CONTROL_2, data->ak4396_ctl2);
|
||||
ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM);
|
||||
ak4396_write(chip, AK4396_LCH_ATT, 0);
|
||||
ak4396_write(chip, AK4396_RCH_ATT, 0);
|
||||
hifier_registers_init(chip);
|
||||
|
||||
snd_component_add(chip->card, "AK4396");
|
||||
snd_component_add(chip->card, "CS5340");
|
||||
|
@ -100,12 +112,6 @@ static void set_ak4396_params(struct oxygen *chip,
|
|||
ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
|
||||
}
|
||||
|
||||
static void update_ak4396_volume(struct oxygen *chip)
|
||||
{
|
||||
ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]);
|
||||
ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]);
|
||||
}
|
||||
|
||||
static void update_ak4396_mute(struct oxygen *chip)
|
||||
{
|
||||
struct hifier_data *data = chip->model_data;
|
||||
|
@ -140,6 +146,7 @@ static const struct oxygen_model model_hifier = {
|
|||
.init = hifier_init,
|
||||
.control_filter = hifier_control_filter,
|
||||
.cleanup = hifier_cleanup,
|
||||
.resume = hifier_registers_init,
|
||||
.set_dac_params = set_ak4396_params,
|
||||
.set_adc_params = set_cs5340_params,
|
||||
.update_dac_volume = update_ak4396_volume,
|
||||
|
@ -180,6 +187,10 @@ static struct pci_driver hifier_driver = {
|
|||
.id_table = hifier_ids,
|
||||
.probe = hifier_probe,
|
||||
.remove = __devexit_p(oxygen_pci_remove),
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = oxygen_pci_suspend,
|
||||
.resume = oxygen_pci_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init alsa_card_hifier_init(void)
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
|
||||
MODULE_DESCRIPTION("C-Media CMI8788 driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8788}}");
|
||||
|
||||
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
|
||||
|
@ -80,6 +80,7 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
|
|||
|
||||
struct generic_data {
|
||||
u8 ak4396_ctl2;
|
||||
u16 saved_wm8785_registers[2];
|
||||
};
|
||||
|
||||
static void ak4396_write(struct oxygen *chip, unsigned int codec,
|
||||
|
@ -99,20 +100,35 @@ static void ak4396_write(struct oxygen *chip, unsigned int codec,
|
|||
|
||||
static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value)
|
||||
{
|
||||
struct generic_data *data = chip->model_data;
|
||||
|
||||
oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
|
||||
OXYGEN_SPI_DATA_LENGTH_2 |
|
||||
OXYGEN_SPI_CLOCK_160 |
|
||||
(3 << OXYGEN_SPI_CODEC_SHIFT) |
|
||||
OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
|
||||
(reg << 9) | value);
|
||||
if (reg < ARRAY_SIZE(data->saved_wm8785_registers))
|
||||
data->saved_wm8785_registers[reg] = value;
|
||||
}
|
||||
|
||||
static void ak4396_init(struct oxygen *chip)
|
||||
static void update_ak4396_volume(struct oxygen *chip)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
ak4396_write(chip, i,
|
||||
AK4396_LCH_ATT, chip->dac_volume[i * 2]);
|
||||
ak4396_write(chip, i,
|
||||
AK4396_RCH_ATT, chip->dac_volume[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void ak4396_registers_init(struct oxygen *chip)
|
||||
{
|
||||
struct generic_data *data = chip->model_data;
|
||||
unsigned int i;
|
||||
|
||||
data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
ak4396_write(chip, i,
|
||||
AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
|
||||
|
@ -120,9 +136,16 @@ static void ak4396_init(struct oxygen *chip)
|
|||
AK4396_CONTROL_2, data->ak4396_ctl2);
|
||||
ak4396_write(chip, i,
|
||||
AK4396_CONTROL_3, AK4396_PCM);
|
||||
ak4396_write(chip, i, AK4396_LCH_ATT, 0);
|
||||
ak4396_write(chip, i, AK4396_RCH_ATT, 0);
|
||||
}
|
||||
update_ak4396_volume(chip);
|
||||
}
|
||||
|
||||
static void ak4396_init(struct oxygen *chip)
|
||||
{
|
||||
struct generic_data *data = chip->model_data;
|
||||
|
||||
data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
|
||||
ak4396_registers_init(chip);
|
||||
snd_component_add(chip->card, "AK4396");
|
||||
}
|
||||
|
||||
|
@ -133,12 +156,23 @@ static void ak5385_init(struct oxygen *chip)
|
|||
snd_component_add(chip->card, "AK5385");
|
||||
}
|
||||
|
||||
static void wm8785_registers_init(struct oxygen *chip)
|
||||
{
|
||||
struct generic_data *data = chip->model_data;
|
||||
|
||||
wm8785_write(chip, WM8785_R7, 0);
|
||||
wm8785_write(chip, WM8785_R0, data->saved_wm8785_registers[0]);
|
||||
wm8785_write(chip, WM8785_R1, data->saved_wm8785_registers[1]);
|
||||
}
|
||||
|
||||
static void wm8785_init(struct oxygen *chip)
|
||||
{
|
||||
wm8785_write(chip, WM8785_R7, 0);
|
||||
wm8785_write(chip, WM8785_R0, WM8785_MCR_SLAVE |
|
||||
WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST);
|
||||
wm8785_write(chip, WM8785_R1, WM8785_WL_24);
|
||||
struct generic_data *data = chip->model_data;
|
||||
|
||||
data->saved_wm8785_registers[0] = WM8785_MCR_SLAVE |
|
||||
WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST;
|
||||
data->saved_wm8785_registers[1] = WM8785_WL_24;
|
||||
wm8785_registers_init(chip);
|
||||
snd_component_add(chip->card, "WM8785");
|
||||
}
|
||||
|
||||
|
@ -158,6 +192,12 @@ static void generic_cleanup(struct oxygen *chip)
|
|||
{
|
||||
}
|
||||
|
||||
static void generic_resume(struct oxygen *chip)
|
||||
{
|
||||
ak4396_registers_init(chip);
|
||||
wm8785_registers_init(chip);
|
||||
}
|
||||
|
||||
static void set_ak4396_params(struct oxygen *chip,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
|
@ -183,18 +223,6 @@ static void set_ak4396_params(struct oxygen *chip,
|
|||
}
|
||||
}
|
||||
|
||||
static void update_ak4396_volume(struct oxygen *chip)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
ak4396_write(chip, i,
|
||||
AK4396_LCH_ATT, chip->dac_volume[i * 2]);
|
||||
ak4396_write(chip, i,
|
||||
AK4396_RCH_ATT, chip->dac_volume[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_ak4396_mute(struct oxygen *chip)
|
||||
{
|
||||
struct generic_data *data = chip->model_data;
|
||||
|
@ -256,6 +284,7 @@ static const struct oxygen_model model_generic = {
|
|||
.owner = THIS_MODULE,
|
||||
.init = generic_init,
|
||||
.cleanup = generic_cleanup,
|
||||
.resume = generic_resume,
|
||||
.set_dac_params = set_ak4396_params,
|
||||
.set_adc_params = set_wm8785_params,
|
||||
.update_dac_volume = update_ak4396_volume,
|
||||
|
@ -283,6 +312,7 @@ static const struct oxygen_model model_meridian = {
|
|||
.owner = THIS_MODULE,
|
||||
.init = meridian_init,
|
||||
.cleanup = generic_cleanup,
|
||||
.resume = ak4396_registers_init,
|
||||
.set_dac_params = set_ak4396_params,
|
||||
.set_adc_params = set_ak5385_params,
|
||||
.update_dac_volume = update_ak4396_volume,
|
||||
|
@ -331,6 +361,10 @@ static struct pci_driver oxygen_driver = {
|
|||
.id_table = oxygen_ids,
|
||||
.probe = generic_oxygen_probe,
|
||||
.remove = __devexit_p(oxygen_pci_remove),
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = oxygen_pci_suspend,
|
||||
.resume = oxygen_pci_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init alsa_card_oxygen_init(void)
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#define PCM_AC97 5
|
||||
#define PCM_COUNT 6
|
||||
|
||||
#define OXYGEN_IO_SIZE 0x100
|
||||
|
||||
/* model-specific configuration of outputs/inputs */
|
||||
#define PLAYBACK_0_TO_I2S 0x001
|
||||
#define PLAYBACK_1_TO_SPDIF 0x004
|
||||
|
@ -78,6 +80,12 @@ struct oxygen {
|
|||
struct work_struct spdif_input_bits_work;
|
||||
struct work_struct gpio_work;
|
||||
wait_queue_head_t ac97_waitqueue;
|
||||
union {
|
||||
u8 _8[OXYGEN_IO_SIZE];
|
||||
__le16 _16[OXYGEN_IO_SIZE / 2];
|
||||
__le32 _32[OXYGEN_IO_SIZE / 4];
|
||||
} saved_registers;
|
||||
u16 saved_ac97_registers[2][0x40];
|
||||
};
|
||||
|
||||
struct oxygen_model {
|
||||
|
@ -89,6 +97,8 @@ struct oxygen_model {
|
|||
int (*control_filter)(struct snd_kcontrol_new *template);
|
||||
int (*mixer_init)(struct oxygen *chip);
|
||||
void (*cleanup)(struct oxygen *chip);
|
||||
void (*suspend)(struct oxygen *chip);
|
||||
void (*resume)(struct oxygen *chip);
|
||||
void (*pcm_hardware_filter)(unsigned int channel,
|
||||
struct snd_pcm_hardware *hardware);
|
||||
void (*set_dac_params)(struct oxygen *chip,
|
||||
|
@ -117,6 +127,10 @@ struct oxygen_model {
|
|||
int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
|
||||
const struct oxygen_model *model);
|
||||
void oxygen_pci_remove(struct pci_dev *pci);
|
||||
#ifdef CONFIG_PM
|
||||
int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state);
|
||||
int oxygen_pci_resume(struct pci_dev *pci);
|
||||
#endif
|
||||
|
||||
/* oxygen_mixer.c */
|
||||
|
||||
|
|
|
@ -44,18 +44,21 @@ EXPORT_SYMBOL(oxygen_read32);
|
|||
void oxygen_write8(struct oxygen *chip, unsigned int reg, u8 value)
|
||||
{
|
||||
outb(value, chip->addr + reg);
|
||||
chip->saved_registers._8[reg] = value;
|
||||
}
|
||||
EXPORT_SYMBOL(oxygen_write8);
|
||||
|
||||
void oxygen_write16(struct oxygen *chip, unsigned int reg, u16 value)
|
||||
{
|
||||
outw(value, chip->addr + reg);
|
||||
chip->saved_registers._16[reg / 2] = cpu_to_le16(value);
|
||||
}
|
||||
EXPORT_SYMBOL(oxygen_write16);
|
||||
|
||||
void oxygen_write32(struct oxygen *chip, unsigned int reg, u32 value)
|
||||
{
|
||||
outl(value, chip->addr + reg);
|
||||
chip->saved_registers._32[reg / 4] = cpu_to_le32(value);
|
||||
}
|
||||
EXPORT_SYMBOL(oxygen_write32);
|
||||
|
||||
|
@ -63,7 +66,10 @@ void oxygen_write8_masked(struct oxygen *chip, unsigned int reg,
|
|||
u8 value, u8 mask)
|
||||
{
|
||||
u8 tmp = inb(chip->addr + reg);
|
||||
outb((tmp & ~mask) | (value & mask), chip->addr + reg);
|
||||
tmp &= ~mask;
|
||||
tmp |= value & mask;
|
||||
outb(tmp, chip->addr + reg);
|
||||
chip->saved_registers._8[reg] = tmp;
|
||||
}
|
||||
EXPORT_SYMBOL(oxygen_write8_masked);
|
||||
|
||||
|
@ -71,7 +77,10 @@ void oxygen_write16_masked(struct oxygen *chip, unsigned int reg,
|
|||
u16 value, u16 mask)
|
||||
{
|
||||
u16 tmp = inw(chip->addr + reg);
|
||||
outw((tmp & ~mask) | (value & mask), chip->addr + reg);
|
||||
tmp &= ~mask;
|
||||
tmp |= value & mask;
|
||||
outw(tmp, chip->addr + reg);
|
||||
chip->saved_registers._16[reg / 2] = cpu_to_le16(tmp);
|
||||
}
|
||||
EXPORT_SYMBOL(oxygen_write16_masked);
|
||||
|
||||
|
@ -79,7 +88,10 @@ void oxygen_write32_masked(struct oxygen *chip, unsigned int reg,
|
|||
u32 value, u32 mask)
|
||||
{
|
||||
u32 tmp = inl(chip->addr + reg);
|
||||
outl((tmp & ~mask) | (value & mask), chip->addr + reg);
|
||||
tmp &= ~mask;
|
||||
tmp |= value & mask;
|
||||
outl(tmp, chip->addr + reg);
|
||||
chip->saved_registers._32[reg / 4] = cpu_to_le32(tmp);
|
||||
}
|
||||
EXPORT_SYMBOL(oxygen_write32_masked);
|
||||
|
||||
|
@ -128,8 +140,10 @@ void oxygen_write_ac97(struct oxygen *chip, unsigned int codec,
|
|||
oxygen_write32(chip, OXYGEN_AC97_REGS, reg);
|
||||
/* require two "completed" writes, just to be sure */
|
||||
if (oxygen_ac97_wait(chip, OXYGEN_AC97_INT_WRITE_DONE) >= 0 &&
|
||||
++succeeded >= 2)
|
||||
++succeeded >= 2) {
|
||||
chip->saved_ac97_registers[codec][index / 2] = data;
|
||||
return;
|
||||
}
|
||||
}
|
||||
snd_printk(KERN_ERR "AC'97 write timeout\n");
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
|
||||
MODULE_DESCRIPTION("C-Media CMI8788 helper library");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
|
||||
static irqreturn_t oxygen_interrupt(int dummy, void *dev_id)
|
||||
|
@ -173,7 +173,7 @@ static void oxygen_proc_read(struct snd_info_entry *entry,
|
|||
int i, j;
|
||||
|
||||
snd_iprintf(buffer, "CMI8788\n\n");
|
||||
for (i = 0; i < 0x100; i += 0x10) {
|
||||
for (i = 0; i < OXYGEN_IO_SIZE; i += 0x10) {
|
||||
snd_iprintf(buffer, "%02x:", i);
|
||||
for (j = 0; j < 0x10; ++j)
|
||||
snd_iprintf(buffer, " %02x", oxygen_read8(chip, i + j));
|
||||
|
@ -314,6 +314,10 @@ static void oxygen_init(struct oxygen *chip)
|
|||
OXYGEN_SPDIF_LOCK_MASK |
|
||||
OXYGEN_SPDIF_RATE_MASK);
|
||||
oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits);
|
||||
oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
|
||||
OXYGEN_2WIRE_LENGTH_8 |
|
||||
OXYGEN_2WIRE_INTERRUPT_MASK |
|
||||
OXYGEN_2WIRE_SPEED_STANDARD);
|
||||
oxygen_clear_bits8(chip, OXYGEN_MPU401_CONTROL, OXYGEN_MPU401_LOOPBACK);
|
||||
oxygen_write8(chip, OXYGEN_GPI_INTERRUPT_MASK, 0);
|
||||
oxygen_write16(chip, OXYGEN_GPIO_INTERRUPT_MASK, 0);
|
||||
|
@ -455,7 +459,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
|
|||
}
|
||||
|
||||
if (!(pci_resource_flags(pci, 0) & IORESOURCE_IO) ||
|
||||
pci_resource_len(pci, 0) < 0x100) {
|
||||
pci_resource_len(pci, 0) < OXYGEN_IO_SIZE) {
|
||||
snd_printk(KERN_ERR "invalid PCI I/O range\n");
|
||||
err = -ENXIO;
|
||||
goto err_pci_regions;
|
||||
|
@ -534,3 +538,99 @@ void oxygen_pci_remove(struct pci_dev *pci)
|
|||
pci_set_drvdata(pci, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(oxygen_pci_remove);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state)
|
||||
{
|
||||
struct snd_card *card = pci_get_drvdata(pci);
|
||||
struct oxygen *chip = card->private_data;
|
||||
unsigned int i, saved_interrupt_mask;
|
||||
|
||||
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
|
||||
|
||||
for (i = 0; i < PCM_COUNT; ++i)
|
||||
if (chip->streams[i])
|
||||
snd_pcm_suspend(chip->streams[i]);
|
||||
|
||||
if (chip->model->suspend)
|
||||
chip->model->suspend(chip);
|
||||
|
||||
spin_lock_irq(&chip->reg_lock);
|
||||
saved_interrupt_mask = chip->interrupt_mask;
|
||||
chip->interrupt_mask = 0;
|
||||
oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
|
||||
oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
|
||||
spin_unlock_irq(&chip->reg_lock);
|
||||
|
||||
synchronize_irq(chip->irq);
|
||||
flush_scheduled_work();
|
||||
chip->interrupt_mask = saved_interrupt_mask;
|
||||
|
||||
pci_disable_device(pci);
|
||||
pci_save_state(pci);
|
||||
pci_set_power_state(pci, pci_choose_state(pci, state));
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(oxygen_pci_suspend);
|
||||
|
||||
static const u32 registers_to_restore[OXYGEN_IO_SIZE / 32] = {
|
||||
0xffffffff, 0x00ff077f, 0x00011d08, 0x007f00ff,
|
||||
0x00300000, 0x00000fe4, 0x0ff7001f, 0x00000000
|
||||
};
|
||||
static const u32 ac97_registers_to_restore[2][0x40 / 32] = {
|
||||
{ 0x18284fa2, 0x03060000 },
|
||||
{ 0x00007fa6, 0x00200000 }
|
||||
};
|
||||
|
||||
static inline int is_bit_set(const u32 *bitmap, unsigned int bit)
|
||||
{
|
||||
return bitmap[bit / 32] & (1 << (bit & 31));
|
||||
}
|
||||
|
||||
static void oxygen_restore_ac97(struct oxygen *chip, unsigned int codec)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
oxygen_write_ac97(chip, codec, AC97_RESET, 0);
|
||||
msleep(1);
|
||||
for (i = 1; i < 0x40; ++i)
|
||||
if (is_bit_set(ac97_registers_to_restore[codec], i))
|
||||
oxygen_write_ac97(chip, codec, i * 2,
|
||||
chip->saved_ac97_registers[codec][i]);
|
||||
}
|
||||
|
||||
int oxygen_pci_resume(struct pci_dev *pci)
|
||||
{
|
||||
struct snd_card *card = pci_get_drvdata(pci);
|
||||
struct oxygen *chip = card->private_data;
|
||||
unsigned int i;
|
||||
|
||||
pci_set_power_state(pci, PCI_D0);
|
||||
pci_restore_state(pci);
|
||||
if (pci_enable_device(pci) < 0) {
|
||||
snd_printk(KERN_ERR "cannot reenable device");
|
||||
snd_card_disconnect(card);
|
||||
return -EIO;
|
||||
}
|
||||
pci_set_master(pci);
|
||||
|
||||
oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
|
||||
oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
|
||||
for (i = 0; i < OXYGEN_IO_SIZE; ++i)
|
||||
if (is_bit_set(registers_to_restore, i))
|
||||
oxygen_write8(chip, i, chip->saved_registers._8[i]);
|
||||
if (chip->has_ac97_0)
|
||||
oxygen_restore_ac97(chip, 0);
|
||||
if (chip->has_ac97_1)
|
||||
oxygen_restore_ac97(chip, 1);
|
||||
|
||||
if (chip->model->resume)
|
||||
chip->model->resume(chip);
|
||||
|
||||
oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask);
|
||||
|
||||
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(oxygen_pci_resume);
|
||||
#endif /* CONFIG_PM */
|
||||
|
|
|
@ -24,6 +24,16 @@
|
|||
#include <sound/pcm_params.h>
|
||||
#include "oxygen.h"
|
||||
|
||||
/* most DMA channels have a 16-bit counter for 32-bit words */
|
||||
#define BUFFER_BYTES_MAX ((1 << 16) * 4)
|
||||
/* the multichannel DMA channel has a 24-bit counter */
|
||||
#define BUFFER_BYTES_MAX_MULTICH ((1 << 24) * 4)
|
||||
|
||||
#define PERIOD_BYTES_MIN 64
|
||||
|
||||
#define DEFAULT_BUFFER_BYTES (BUFFER_BYTES_MAX / 2)
|
||||
#define DEFAULT_BUFFER_BYTES_MULTICH (1024 * 1024)
|
||||
|
||||
static const struct snd_pcm_hardware oxygen_stereo_hardware = {
|
||||
.info = SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_MMAP_VALID |
|
||||
|
@ -44,11 +54,11 @@ static const struct snd_pcm_hardware oxygen_stereo_hardware = {
|
|||
.rate_max = 192000,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.buffer_bytes_max = 256 * 1024,
|
||||
.period_bytes_min = 128,
|
||||
.period_bytes_max = 128 * 1024,
|
||||
.buffer_bytes_max = BUFFER_BYTES_MAX,
|
||||
.period_bytes_min = PERIOD_BYTES_MIN,
|
||||
.period_bytes_max = BUFFER_BYTES_MAX / 2,
|
||||
.periods_min = 2,
|
||||
.periods_max = 2048,
|
||||
.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
|
||||
};
|
||||
static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
|
||||
.info = SNDRV_PCM_INFO_MMAP |
|
||||
|
@ -70,11 +80,11 @@ static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
|
|||
.rate_max = 192000,
|
||||
.channels_min = 2,
|
||||
.channels_max = 8,
|
||||
.buffer_bytes_max = 2048 * 1024,
|
||||
.period_bytes_min = 128,
|
||||
.period_bytes_max = 256 * 1024,
|
||||
.buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH,
|
||||
.period_bytes_min = PERIOD_BYTES_MIN,
|
||||
.period_bytes_max = BUFFER_BYTES_MAX_MULTICH / 2,
|
||||
.periods_min = 2,
|
||||
.periods_max = 16384,
|
||||
.periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN,
|
||||
};
|
||||
static const struct snd_pcm_hardware oxygen_ac97_hardware = {
|
||||
.info = SNDRV_PCM_INFO_MMAP |
|
||||
|
@ -88,11 +98,11 @@ static const struct snd_pcm_hardware oxygen_ac97_hardware = {
|
|||
.rate_max = 48000,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.buffer_bytes_max = 256 * 1024,
|
||||
.period_bytes_min = 128,
|
||||
.period_bytes_max = 128 * 1024,
|
||||
.buffer_bytes_max = BUFFER_BYTES_MAX,
|
||||
.period_bytes_min = PERIOD_BYTES_MIN,
|
||||
.period_bytes_max = BUFFER_BYTES_MAX / 2,
|
||||
.periods_min = 2,
|
||||
.periods_max = 2048,
|
||||
.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
|
||||
};
|
||||
|
||||
static const struct snd_pcm_hardware *const oxygen_hardware[PCM_COUNT] = {
|
||||
|
@ -155,6 +165,12 @@ static int oxygen_open(struct snd_pcm_substream *substream,
|
|||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (channel == PCM_MULTICH) {
|
||||
err = snd_pcm_hw_constraint_minmax
|
||||
(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 0, 8192000);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
snd_pcm_set_sync(substream);
|
||||
chip->streams[channel] = substream;
|
||||
|
||||
|
@ -517,6 +533,7 @@ static int oxygen_trigger(struct snd_pcm_substream *substream, int cmd)
|
|||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
pausing = 0;
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
|
@ -663,12 +680,14 @@ int oxygen_pcm_init(struct oxygen *chip)
|
|||
snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
|
||||
SNDRV_DMA_TYPE_DEV,
|
||||
snd_dma_pci_data(chip->pci),
|
||||
512 * 1024, 2048 * 1024);
|
||||
DEFAULT_BUFFER_BYTES_MULTICH,
|
||||
BUFFER_BYTES_MAX_MULTICH);
|
||||
if (ins)
|
||||
snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
|
||||
SNDRV_DMA_TYPE_DEV,
|
||||
snd_dma_pci_data(chip->pci),
|
||||
128 * 1024, 256 * 1024);
|
||||
DEFAULT_BUFFER_BYTES,
|
||||
BUFFER_BYTES_MAX);
|
||||
}
|
||||
|
||||
outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_1_TO_SPDIF);
|
||||
|
@ -688,7 +707,8 @@ int oxygen_pcm_init(struct oxygen *chip)
|
|||
strcpy(pcm->name, "Digital");
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
snd_dma_pci_data(chip->pci),
|
||||
128 * 1024, 256 * 1024);
|
||||
DEFAULT_BUFFER_BYTES,
|
||||
BUFFER_BYTES_MAX);
|
||||
}
|
||||
|
||||
if (chip->has_ac97_1) {
|
||||
|
@ -718,7 +738,8 @@ int oxygen_pcm_init(struct oxygen *chip)
|
|||
strcpy(pcm->name, outs ? "Front Panel" : "Analog 2");
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
snd_dma_pci_data(chip->pci),
|
||||
128 * 1024, 256 * 1024);
|
||||
DEFAULT_BUFFER_BYTES,
|
||||
BUFFER_BYTES_MAX);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
|
||||
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
|
||||
MODULE_DESCRIPTION("Asus AVx00 driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_SUPPORTED_DEVICE("{{Asus,AV100},{Asus,AV200}}");
|
||||
|
||||
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
|
||||
|
@ -132,6 +132,9 @@ struct xonar_data {
|
|||
u8 ext_power_int_reg;
|
||||
u8 ext_power_bit;
|
||||
u8 has_power;
|
||||
u8 pcm1796_oversampling;
|
||||
u8 cs4398_fm;
|
||||
u8 cs4362a_fm;
|
||||
};
|
||||
|
||||
static void pcm1796_write(struct oxygen *chip, unsigned int codec,
|
||||
|
@ -159,6 +162,14 @@ static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value)
|
|||
oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value);
|
||||
}
|
||||
|
||||
static void xonar_enable_output(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_data *data = chip->model_data;
|
||||
|
||||
msleep(data->anti_pop_delay);
|
||||
oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
|
||||
}
|
||||
|
||||
static void xonar_common_init(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_data *data = chip->model_data;
|
||||
|
@ -170,32 +181,59 @@ static void xonar_common_init(struct oxygen *chip)
|
|||
data->has_power = !!(oxygen_read8(chip, data->ext_power_reg)
|
||||
& data->ext_power_bit);
|
||||
}
|
||||
oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK);
|
||||
oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
|
||||
GPIO_CS53x1_M_MASK | data->output_enable_bit);
|
||||
oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
|
||||
GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK);
|
||||
oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
|
||||
msleep(data->anti_pop_delay);
|
||||
oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, data->output_enable_bit);
|
||||
oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
|
||||
xonar_enable_output(chip);
|
||||
}
|
||||
|
||||
static void update_pcm1796_volume(struct oxygen *chip)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
pcm1796_write(chip, i, 16, chip->dac_volume[i * 2]);
|
||||
pcm1796_write(chip, i, 17, chip->dac_volume[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_pcm1796_mute(struct oxygen *chip)
|
||||
{
|
||||
unsigned int i;
|
||||
u8 value;
|
||||
|
||||
value = PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD;
|
||||
if (chip->dac_mute)
|
||||
value |= PCM1796_MUTE;
|
||||
for (i = 0; i < 4; ++i)
|
||||
pcm1796_write(chip, i, 18, value);
|
||||
}
|
||||
|
||||
static void pcm1796_init(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_data *data = chip->model_data;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1);
|
||||
pcm1796_write(chip, i, 20, data->pcm1796_oversampling);
|
||||
pcm1796_write(chip, i, 21, 0);
|
||||
}
|
||||
update_pcm1796_mute(chip); /* set ATLD before ATL/ATR */
|
||||
update_pcm1796_volume(chip);
|
||||
}
|
||||
|
||||
static void xonar_d2_init(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_data *data = chip->model_data;
|
||||
unsigned int i;
|
||||
|
||||
data->anti_pop_delay = 300;
|
||||
data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
|
||||
data->pcm1796_oversampling = PCM1796_OS_64;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
pcm1796_write(chip, i, 18, PCM1796_MUTE | PCM1796_DMF_DISABLED |
|
||||
PCM1796_FMT_24_LJUST | PCM1796_ATLD);
|
||||
pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1);
|
||||
pcm1796_write(chip, i, 20, PCM1796_OS_64);
|
||||
pcm1796_write(chip, i, 21, 0);
|
||||
pcm1796_write(chip, i, 16, 0x0f); /* set ATL/ATR after ATLD */
|
||||
pcm1796_write(chip, i, 17, 0x0f);
|
||||
}
|
||||
pcm1796_init(chip);
|
||||
|
||||
oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT);
|
||||
oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D2_ALT);
|
||||
|
@ -217,151 +255,6 @@ static void xonar_d2x_init(struct oxygen *chip)
|
|||
xonar_d2_init(chip);
|
||||
}
|
||||
|
||||
static void xonar_dx_init(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_data *data = chip->model_data;
|
||||
|
||||
data->anti_pop_delay = 800;
|
||||
data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
|
||||
data->ext_power_reg = OXYGEN_GPI_DATA;
|
||||
data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
|
||||
data->ext_power_bit = GPI_DX_EXT_POWER;
|
||||
|
||||
oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
|
||||
OXYGEN_2WIRE_LENGTH_8 |
|
||||
OXYGEN_2WIRE_INTERRUPT_MASK |
|
||||
OXYGEN_2WIRE_SPEED_FAST);
|
||||
|
||||
/* set CPEN (control port mode) and power down */
|
||||
cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN);
|
||||
cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
|
||||
/* configure */
|
||||
cs4398_write(chip, 2, CS4398_FM_SINGLE |
|
||||
CS4398_DEM_NONE | CS4398_DIF_LJUST);
|
||||
cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L);
|
||||
cs4398_write(chip, 4, CS4398_MUTEP_LOW | CS4398_PAMUTE);
|
||||
cs4398_write(chip, 5, 0xfe);
|
||||
cs4398_write(chip, 6, 0xfe);
|
||||
cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP |
|
||||
CS4398_ZERO_CROSS | CS4398_SOFT_RAMP);
|
||||
cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST);
|
||||
cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE |
|
||||
CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP);
|
||||
cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE);
|
||||
cs4362a_write(chip, 0x05, 0);
|
||||
cs4362a_write(chip, 0x06, CS4362A_FM_SINGLE |
|
||||
CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
|
||||
cs4362a_write(chip, 0x07, 0x7f | CS4362A_MUTE);
|
||||
cs4362a_write(chip, 0x08, 0x7f | CS4362A_MUTE);
|
||||
cs4362a_write(chip, 0x09, CS4362A_FM_SINGLE |
|
||||
CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
|
||||
cs4362a_write(chip, 0x0a, 0x7f | CS4362A_MUTE);
|
||||
cs4362a_write(chip, 0x0b, 0x7f | CS4362A_MUTE);
|
||||
cs4362a_write(chip, 0x0c, CS4362A_FM_SINGLE |
|
||||
CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
|
||||
cs4362a_write(chip, 0x0d, 0x7f | CS4362A_MUTE);
|
||||
cs4362a_write(chip, 0x0e, 0x7f | CS4362A_MUTE);
|
||||
/* clear power down */
|
||||
cs4398_write(chip, 8, CS4398_CPEN);
|
||||
cs4362a_write(chip, 0x01, CS4362A_CPEN);
|
||||
|
||||
oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
|
||||
GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
|
||||
oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
|
||||
GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
|
||||
|
||||
xonar_common_init(chip);
|
||||
|
||||
snd_component_add(chip->card, "CS4398");
|
||||
snd_component_add(chip->card, "CS4362A");
|
||||
snd_component_add(chip->card, "CS5361");
|
||||
}
|
||||
|
||||
static void xonar_cleanup(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_data *data = chip->model_data;
|
||||
|
||||
oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
|
||||
}
|
||||
|
||||
static void xonar_dx_cleanup(struct oxygen *chip)
|
||||
{
|
||||
xonar_cleanup(chip);
|
||||
cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
|
||||
oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
|
||||
}
|
||||
|
||||
static void set_pcm1796_params(struct oxygen *chip,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
unsigned int i;
|
||||
u8 value;
|
||||
|
||||
value = params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64;
|
||||
for (i = 0; i < 4; ++i)
|
||||
pcm1796_write(chip, i, 20, value);
|
||||
}
|
||||
|
||||
static void update_pcm1796_volume(struct oxygen *chip)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
pcm1796_write(chip, i, 16, chip->dac_volume[i * 2]);
|
||||
pcm1796_write(chip, i, 17, chip->dac_volume[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_pcm1796_mute(struct oxygen *chip)
|
||||
{
|
||||
unsigned int i;
|
||||
u8 value;
|
||||
|
||||
value = PCM1796_FMT_24_LJUST | PCM1796_ATLD;
|
||||
if (chip->dac_mute)
|
||||
value |= PCM1796_MUTE;
|
||||
for (i = 0; i < 4; ++i)
|
||||
pcm1796_write(chip, i, 18, value);
|
||||
}
|
||||
|
||||
static void set_cs53x1_params(struct oxygen *chip,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
if (params_rate(params) <= 54000)
|
||||
value = GPIO_CS53x1_M_SINGLE;
|
||||
else if (params_rate(params) <= 108000)
|
||||
value = GPIO_CS53x1_M_DOUBLE;
|
||||
else
|
||||
value = GPIO_CS53x1_M_QUAD;
|
||||
oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
|
||||
value, GPIO_CS53x1_M_MASK);
|
||||
}
|
||||
|
||||
static void set_cs43xx_params(struct oxygen *chip,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
u8 fm_cs4398, fm_cs4362a;
|
||||
|
||||
fm_cs4398 = CS4398_DEM_NONE | CS4398_DIF_LJUST;
|
||||
fm_cs4362a = CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
|
||||
if (params_rate(params) <= 50000) {
|
||||
fm_cs4398 |= CS4398_FM_SINGLE;
|
||||
fm_cs4362a |= CS4362A_FM_SINGLE;
|
||||
} else if (params_rate(params) <= 100000) {
|
||||
fm_cs4398 |= CS4398_FM_DOUBLE;
|
||||
fm_cs4362a |= CS4362A_FM_DOUBLE;
|
||||
} else {
|
||||
fm_cs4398 |= CS4398_FM_QUAD;
|
||||
fm_cs4362a |= CS4362A_FM_QUAD;
|
||||
}
|
||||
cs4398_write(chip, 2, fm_cs4398);
|
||||
cs4362a_write(chip, 0x06, fm_cs4362a);
|
||||
cs4362a_write(chip, 0x09, fm_cs4362a);
|
||||
cs4362a_write(chip, 0x0c, fm_cs4362a);
|
||||
}
|
||||
|
||||
static void update_cs4362a_volumes(struct oxygen *chip)
|
||||
{
|
||||
u8 mute;
|
||||
|
@ -393,6 +286,141 @@ static void update_cs43xx_mute(struct oxygen *chip)
|
|||
update_cs4362a_volumes(chip);
|
||||
}
|
||||
|
||||
static void cs43xx_init(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_data *data = chip->model_data;
|
||||
|
||||
/* set CPEN (control port mode) and power down */
|
||||
cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN);
|
||||
cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
|
||||
/* configure */
|
||||
cs4398_write(chip, 2, data->cs4398_fm);
|
||||
cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L);
|
||||
cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP |
|
||||
CS4398_ZERO_CROSS | CS4398_SOFT_RAMP);
|
||||
cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST);
|
||||
cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE |
|
||||
CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP);
|
||||
cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE);
|
||||
cs4362a_write(chip, 0x05, 0);
|
||||
cs4362a_write(chip, 0x06, data->cs4362a_fm);
|
||||
cs4362a_write(chip, 0x09, data->cs4362a_fm);
|
||||
cs4362a_write(chip, 0x0c, data->cs4362a_fm);
|
||||
update_cs43xx_volume(chip);
|
||||
update_cs43xx_mute(chip);
|
||||
/* clear power down */
|
||||
cs4398_write(chip, 8, CS4398_CPEN);
|
||||
cs4362a_write(chip, 0x01, CS4362A_CPEN);
|
||||
}
|
||||
|
||||
static void xonar_dx_init(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_data *data = chip->model_data;
|
||||
|
||||
data->anti_pop_delay = 800;
|
||||
data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
|
||||
data->ext_power_reg = OXYGEN_GPI_DATA;
|
||||
data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
|
||||
data->ext_power_bit = GPI_DX_EXT_POWER;
|
||||
data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST;
|
||||
data->cs4362a_fm = CS4362A_FM_SINGLE |
|
||||
CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
|
||||
|
||||
oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
|
||||
OXYGEN_2WIRE_LENGTH_8 |
|
||||
OXYGEN_2WIRE_INTERRUPT_MASK |
|
||||
OXYGEN_2WIRE_SPEED_FAST);
|
||||
|
||||
cs43xx_init(chip);
|
||||
|
||||
oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
|
||||
GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
|
||||
oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
|
||||
GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
|
||||
|
||||
xonar_common_init(chip);
|
||||
|
||||
snd_component_add(chip->card, "CS4398");
|
||||
snd_component_add(chip->card, "CS4362A");
|
||||
snd_component_add(chip->card, "CS5361");
|
||||
}
|
||||
|
||||
static void xonar_cleanup(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_data *data = chip->model_data;
|
||||
|
||||
oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
|
||||
}
|
||||
|
||||
static void xonar_dx_cleanup(struct oxygen *chip)
|
||||
{
|
||||
xonar_cleanup(chip);
|
||||
cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
|
||||
oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
|
||||
}
|
||||
|
||||
static void xonar_d2_resume(struct oxygen *chip)
|
||||
{
|
||||
pcm1796_init(chip);
|
||||
xonar_enable_output(chip);
|
||||
}
|
||||
|
||||
static void xonar_dx_resume(struct oxygen *chip)
|
||||
{
|
||||
cs43xx_init(chip);
|
||||
xonar_enable_output(chip);
|
||||
}
|
||||
|
||||
static void set_pcm1796_params(struct oxygen *chip,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct xonar_data *data = chip->model_data;
|
||||
unsigned int i;
|
||||
|
||||
data->pcm1796_oversampling =
|
||||
params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64;
|
||||
for (i = 0; i < 4; ++i)
|
||||
pcm1796_write(chip, i, 20, data->pcm1796_oversampling);
|
||||
}
|
||||
|
||||
static void set_cs53x1_params(struct oxygen *chip,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
if (params_rate(params) <= 54000)
|
||||
value = GPIO_CS53x1_M_SINGLE;
|
||||
else if (params_rate(params) <= 108000)
|
||||
value = GPIO_CS53x1_M_DOUBLE;
|
||||
else
|
||||
value = GPIO_CS53x1_M_QUAD;
|
||||
oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
|
||||
value, GPIO_CS53x1_M_MASK);
|
||||
}
|
||||
|
||||
static void set_cs43xx_params(struct oxygen *chip,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct xonar_data *data = chip->model_data;
|
||||
|
||||
data->cs4398_fm = CS4398_DEM_NONE | CS4398_DIF_LJUST;
|
||||
data->cs4362a_fm = CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
|
||||
if (params_rate(params) <= 50000) {
|
||||
data->cs4398_fm |= CS4398_FM_SINGLE;
|
||||
data->cs4362a_fm |= CS4362A_FM_SINGLE;
|
||||
} else if (params_rate(params) <= 100000) {
|
||||
data->cs4398_fm |= CS4398_FM_DOUBLE;
|
||||
data->cs4362a_fm |= CS4362A_FM_DOUBLE;
|
||||
} else {
|
||||
data->cs4398_fm |= CS4398_FM_QUAD;
|
||||
data->cs4362a_fm |= CS4362A_FM_QUAD;
|
||||
}
|
||||
cs4398_write(chip, 2, data->cs4398_fm);
|
||||
cs4362a_write(chip, 0x06, data->cs4362a_fm);
|
||||
cs4362a_write(chip, 0x09, data->cs4362a_fm);
|
||||
cs4362a_write(chip, 0x0c, data->cs4362a_fm);
|
||||
}
|
||||
|
||||
static void xonar_gpio_changed(struct oxygen *chip)
|
||||
{
|
||||
struct xonar_data *data = chip->model_data;
|
||||
|
@ -535,6 +563,8 @@ static const struct oxygen_model xonar_models[] = {
|
|||
.control_filter = xonar_d2_control_filter,
|
||||
.mixer_init = xonar_mixer_init,
|
||||
.cleanup = xonar_cleanup,
|
||||
.suspend = xonar_cleanup,
|
||||
.resume = xonar_d2_resume,
|
||||
.set_dac_params = set_pcm1796_params,
|
||||
.set_adc_params = set_cs53x1_params,
|
||||
.update_dac_volume = update_pcm1796_volume,
|
||||
|
@ -563,6 +593,8 @@ static const struct oxygen_model xonar_models[] = {
|
|||
.control_filter = xonar_d2_control_filter,
|
||||
.mixer_init = xonar_mixer_init,
|
||||
.cleanup = xonar_cleanup,
|
||||
.suspend = xonar_cleanup,
|
||||
.resume = xonar_d2_resume,
|
||||
.set_dac_params = set_pcm1796_params,
|
||||
.set_adc_params = set_cs53x1_params,
|
||||
.update_dac_volume = update_pcm1796_volume,
|
||||
|
@ -592,6 +624,8 @@ static const struct oxygen_model xonar_models[] = {
|
|||
.control_filter = xonar_dx_control_filter,
|
||||
.mixer_init = xonar_dx_mixer_init,
|
||||
.cleanup = xonar_dx_cleanup,
|
||||
.suspend = xonar_dx_cleanup,
|
||||
.resume = xonar_dx_resume,
|
||||
.set_dac_params = set_cs43xx_params,
|
||||
.set_adc_params = set_cs53x1_params,
|
||||
.update_dac_volume = update_cs43xx_volume,
|
||||
|
@ -636,6 +670,10 @@ static struct pci_driver xonar_driver = {
|
|||
.id_table = xonar_ids,
|
||||
.probe = xonar_probe,
|
||||
.remove = __devexit_p(oxygen_pci_remove),
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = oxygen_pci_suspend,
|
||||
.resume = oxygen_pci_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init alsa_card_xonar_init(void)
|
||||
|
|
|
@ -516,7 +516,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
|
|||
int capture_mask = 0;
|
||||
int playback_mask = 0;
|
||||
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
struct timeval my_tv1, my_tv2;
|
||||
do_gettimeofday(&my_tv1);
|
||||
#endif
|
||||
|
@ -623,7 +623,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
|
|||
|
||||
mutex_unlock(&mgr->setup_mutex);
|
||||
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
do_gettimeofday(&my_tv2);
|
||||
snd_printdd("***TRIGGER TASKLET*** TIME = %ld (err = %x)\n",
|
||||
(long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
|
||||
|
|
|
@ -473,7 +473,7 @@ static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = {
|
|||
[CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED },
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
static char* cmd_names[] = {
|
||||
[CMD_VERSION] = "CMD_VERSION",
|
||||
[CMD_SUPPORTED] = "CMD_SUPPORTED",
|
||||
|
@ -549,7 +549,7 @@ static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
|
|||
}
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
if (rmh->cmd_idx < CMD_LAST_INDEX)
|
||||
snd_printdd(" stat[%d]=%x\n", i, data);
|
||||
#endif
|
||||
|
@ -597,7 +597,7 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
|
|||
data |= 0x008000; /* MASK_MORE_THAN_1_WORD_COMMAND */
|
||||
else
|
||||
data &= 0xff7fff; /* MASK_1_WORD_COMMAND */
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
if (rmh->cmd_idx < CMD_LAST_INDEX)
|
||||
snd_printdd("MSG cmd[0]=%x (%s)\n", data, cmd_names[rmh->cmd_idx]);
|
||||
#endif
|
||||
|
@ -624,7 +624,7 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
|
|||
for (i=1; i < rmh->cmd_len; i++) {
|
||||
/* send other words */
|
||||
data = rmh->cmd[i];
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
if (rmh->cmd_idx < CMD_LAST_INDEX)
|
||||
snd_printdd(" cmd[%d]=%x\n", i, data);
|
||||
#endif
|
||||
|
@ -847,7 +847,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_m
|
|||
int state, i, err;
|
||||
int audio_mask;
|
||||
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
struct timeval my_tv1, my_tv2;
|
||||
do_gettimeofday(&my_tv1);
|
||||
#endif
|
||||
|
@ -894,7 +894,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_m
|
|||
if (err)
|
||||
return err;
|
||||
}
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
do_gettimeofday(&my_tv2);
|
||||
snd_printdd("***SET PIPE STATE*** TIME = %ld (err = %x)\n",
|
||||
(long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
|
||||
|
@ -951,7 +951,7 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err,
|
|||
enum pcxhr_async_err_src err_src, int pipe,
|
||||
int is_capture)
|
||||
{
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
static char* err_src_name[] = {
|
||||
[PCXHR_ERR_PIPE] = "Pipe",
|
||||
[PCXHR_ERR_STREAM] = "Stream",
|
||||
|
@ -1169,7 +1169,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
|
|||
mgr->dsp_time_last, dsp_time_new);
|
||||
mgr->dsp_time_err++;
|
||||
}
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
if (dsp_time_diff == 0)
|
||||
snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n", dsp_time_new);
|
||||
else if (dsp_time_diff >= (2*PCXHR_GRANULARITY))
|
||||
|
@ -1208,7 +1208,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
|
|||
mgr->src_it_dsp = reg;
|
||||
tasklet_hi_schedule(&mgr->msg_taskq);
|
||||
}
|
||||
#ifdef CONFIG_SND_DEBUG_DETECT
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
if (reg & PCXHR_FATAL_DSP_ERR)
|
||||
snd_printdd("FATAL DSP ERROR : %x\n", reg);
|
||||
#endif
|
||||
|
|
|
@ -1590,7 +1590,10 @@ static int snd_trident_trigger(struct snd_pcm_substream *substream,
|
|||
if (spdif_flag) {
|
||||
if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
|
||||
outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));
|
||||
outb(trident->spdif_pcm_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
|
||||
val = trident->spdif_pcm_ctrl;
|
||||
if (!go)
|
||||
val &= ~(0x28);
|
||||
outb(val, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
|
||||
} else {
|
||||
outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS));
|
||||
val = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) | SPDIF_EN;
|
||||
|
|
|
@ -310,181 +310,3 @@ int snd_trident_free_pages(struct snd_trident *trident,
|
|||
mutex_unlock(&hdr->block_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
* memory allocation using multiple pages (for synth)
|
||||
*----------------------------------------------------------------
|
||||
* Unlike the DMA allocation above, non-contiguous pages are
|
||||
* assigned to TLB.
|
||||
*----------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
*/
|
||||
static int synth_alloc_pages(struct snd_trident *hw, struct snd_util_memblk *blk);
|
||||
static int synth_free_pages(struct snd_trident *hw, struct snd_util_memblk *blk);
|
||||
|
||||
/*
|
||||
* allocate a synth sample area
|
||||
*/
|
||||
struct snd_util_memblk *
|
||||
snd_trident_synth_alloc(struct snd_trident *hw, unsigned int size)
|
||||
{
|
||||
struct snd_util_memblk *blk;
|
||||
struct snd_util_memhdr *hdr = hw->tlb.memhdr;
|
||||
|
||||
mutex_lock(&hdr->block_mutex);
|
||||
blk = __snd_util_mem_alloc(hdr, size);
|
||||
if (blk == NULL) {
|
||||
mutex_unlock(&hdr->block_mutex);
|
||||
return NULL;
|
||||
}
|
||||
if (synth_alloc_pages(hw, blk)) {
|
||||
__snd_util_mem_free(hdr, blk);
|
||||
mutex_unlock(&hdr->block_mutex);
|
||||
return NULL;
|
||||
}
|
||||
mutex_unlock(&hdr->block_mutex);
|
||||
return blk;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(snd_trident_synth_alloc);
|
||||
|
||||
/*
|
||||
* free a synth sample area
|
||||
*/
|
||||
int
|
||||
snd_trident_synth_free(struct snd_trident *hw, struct snd_util_memblk *blk)
|
||||
{
|
||||
struct snd_util_memhdr *hdr = hw->tlb.memhdr;
|
||||
|
||||
mutex_lock(&hdr->block_mutex);
|
||||
synth_free_pages(hw, blk);
|
||||
__snd_util_mem_free(hdr, blk);
|
||||
mutex_unlock(&hdr->block_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(snd_trident_synth_free);
|
||||
|
||||
/*
|
||||
* reset TLB entry and free kernel page
|
||||
*/
|
||||
static void clear_tlb(struct snd_trident *trident, int page)
|
||||
{
|
||||
void *ptr = page_to_ptr(trident, page);
|
||||
dma_addr_t addr = page_to_addr(trident, page);
|
||||
set_silent_tlb(trident, page);
|
||||
if (ptr) {
|
||||
struct snd_dma_buffer dmab;
|
||||
dmab.dev.type = SNDRV_DMA_TYPE_DEV;
|
||||
dmab.dev.dev = snd_dma_pci_data(trident->pci);
|
||||
dmab.area = ptr;
|
||||
dmab.addr = addr;
|
||||
dmab.bytes = ALIGN_PAGE_SIZE;
|
||||
snd_dma_free_pages(&dmab);
|
||||
}
|
||||
}
|
||||
|
||||
/* check new allocation range */
|
||||
static void get_single_page_range(struct snd_util_memhdr *hdr,
|
||||
struct snd_util_memblk *blk,
|
||||
int *first_page_ret, int *last_page_ret)
|
||||
{
|
||||
struct list_head *p;
|
||||
struct snd_util_memblk *q;
|
||||
int first_page, last_page;
|
||||
first_page = firstpg(blk);
|
||||
if ((p = blk->list.prev) != &hdr->block) {
|
||||
q = list_entry(p, struct snd_util_memblk, list);
|
||||
if (lastpg(q) == first_page)
|
||||
first_page++; /* first page was already allocated */
|
||||
}
|
||||
last_page = lastpg(blk);
|
||||
if ((p = blk->list.next) != &hdr->block) {
|
||||
q = list_entry(p, struct snd_util_memblk, list);
|
||||
if (firstpg(q) == last_page)
|
||||
last_page--; /* last page was already allocated */
|
||||
}
|
||||
*first_page_ret = first_page;
|
||||
*last_page_ret = last_page;
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate kernel pages and assign them to TLB
|
||||
*/
|
||||
static int synth_alloc_pages(struct snd_trident *hw, struct snd_util_memblk *blk)
|
||||
{
|
||||
int page, first_page, last_page;
|
||||
struct snd_dma_buffer dmab;
|
||||
|
||||
firstpg(blk) = get_aligned_page(blk->offset);
|
||||
lastpg(blk) = get_aligned_page(blk->offset + blk->size - 1);
|
||||
get_single_page_range(hw->tlb.memhdr, blk, &first_page, &last_page);
|
||||
|
||||
/* allocate a kernel page for each Trident page -
|
||||
* fortunately Trident page size and kernel PAGE_SIZE is identical!
|
||||
*/
|
||||
for (page = first_page; page <= last_page; page++) {
|
||||
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(hw->pci),
|
||||
ALIGN_PAGE_SIZE, &dmab) < 0)
|
||||
goto __fail;
|
||||
if (! is_valid_page(dmab.addr)) {
|
||||
snd_dma_free_pages(&dmab);
|
||||
goto __fail;
|
||||
}
|
||||
set_tlb_bus(hw, page, (unsigned long)dmab.area, dmab.addr);
|
||||
}
|
||||
return 0;
|
||||
|
||||
__fail:
|
||||
/* release allocated pages */
|
||||
last_page = page - 1;
|
||||
for (page = first_page; page <= last_page; page++)
|
||||
clear_tlb(hw, page);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* free pages
|
||||
*/
|
||||
static int synth_free_pages(struct snd_trident *trident, struct snd_util_memblk *blk)
|
||||
{
|
||||
int page, first_page, last_page;
|
||||
|
||||
get_single_page_range(trident->tlb.memhdr, blk, &first_page, &last_page);
|
||||
for (page = first_page; page <= last_page; page++)
|
||||
clear_tlb(trident, page);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* copy_from_user(blk + offset, data, size)
|
||||
*/
|
||||
int snd_trident_synth_copy_from_user(struct snd_trident *trident,
|
||||
struct snd_util_memblk *blk,
|
||||
int offset, const char __user *data, int size)
|
||||
{
|
||||
int page, nextofs, end_offset, temp, temp1;
|
||||
|
||||
offset += blk->offset;
|
||||
end_offset = offset + size;
|
||||
page = get_aligned_page(offset) + 1;
|
||||
do {
|
||||
nextofs = aligned_page_offset(page);
|
||||
temp = nextofs - offset;
|
||||
temp1 = end_offset - offset;
|
||||
if (temp1 < temp)
|
||||
temp = temp1;
|
||||
if (copy_from_user(offset_ptr(trident, offset), data, temp))
|
||||
return -EFAULT;
|
||||
offset = nextofs;
|
||||
data += temp;
|
||||
page++;
|
||||
} while (offset < end_offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(snd_trident_synth_copy_from_user);
|
||||
|
|
|
@ -1756,6 +1756,12 @@ static struct ac97_quirk ac97_quirks[] = {
|
|||
.name = "ECS L7VMM2",
|
||||
.type = AC97_TUNE_HP_ONLY
|
||||
},
|
||||
{
|
||||
.subvendor = 0x1019,
|
||||
.subdevice = 0x1841,
|
||||
.name = "ECS K7VTA3",
|
||||
.type = AC97_TUNE_HP_ONLY
|
||||
},
|
||||
{
|
||||
.subvendor = 0x1849,
|
||||
.subdevice = 0x3059,
|
||||
|
|
|
@ -2205,6 +2205,7 @@ static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip)
|
|||
for (reg = 0x80; reg < 0xc0; reg += 4)
|
||||
snd_ymfpci_writel(chip, reg, 0);
|
||||
snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff);
|
||||
snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0x3fff3fff);
|
||||
snd_ymfpci_writel(chip, YDSXGR_ZVOUTVOL, 0x3fff3fff);
|
||||
snd_ymfpci_writel(chip, YDSXGR_SPDIFOUTVOL, 0x3fff3fff);
|
||||
snd_ymfpci_writel(chip, YDSXGR_NATIVEADCINVOL, 0x3fff3fff);
|
||||
|
@ -2324,6 +2325,7 @@ int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state)
|
|||
chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]);
|
||||
chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE);
|
||||
snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
|
||||
snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
|
||||
snd_ymfpci_disable_dsp(chip);
|
||||
pci_disable_device(pci);
|
||||
pci_save_state(pci);
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
# ALSA PCMCIA drivers
|
||||
|
||||
menu "PCMCIA devices"
|
||||
depends on SND!=n && PCMCIA
|
||||
menuconfig SND_PCMCIA
|
||||
bool "PCMCIA sound devices"
|
||||
depends on PCMCIA
|
||||
default y
|
||||
help
|
||||
Support for sound devices connected via the PCMCIA bus.
|
||||
|
||||
if SND_PCMCIA && PCMCIA
|
||||
|
||||
config SND_VXPOCKET
|
||||
tristate "Digigram VXpocket"
|
||||
depends on SND && PCMCIA
|
||||
select SND_VX_LIB
|
||||
help
|
||||
Say Y here to include support for Digigram VXpocket and
|
||||
|
@ -16,7 +21,6 @@ config SND_VXPOCKET
|
|||
|
||||
config SND_PDAUDIOCF
|
||||
tristate "Sound Core PDAudioCF"
|
||||
depends on SND && PCMCIA
|
||||
select SND_PCM
|
||||
help
|
||||
Say Y here to include support for Sound Core PDAudioCF
|
||||
|
@ -25,4 +29,5 @@ config SND_PDAUDIOCF
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-pdaudiocf.
|
||||
|
||||
endmenu
|
||||
endif # SND_PCMCIA
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware *
|
|||
unsigned int i;
|
||||
int c;
|
||||
int regCSUER, regRUER;
|
||||
unsigned char *image;
|
||||
const unsigned char *image;
|
||||
unsigned char data;
|
||||
|
||||
/* Switch to programmation mode */
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
# ALSA PowerMac drivers
|
||||
|
||||
menu "ALSA PowerMac devices"
|
||||
depends on SND!=n && PPC
|
||||
menuconfig SND_PPC
|
||||
bool "PowerPC sound devices"
|
||||
depends on PPC64 || PPC32
|
||||
default y
|
||||
help
|
||||
Support for sound devices specific to PowerPC architectures.
|
||||
|
||||
comment "ALSA PowerMac requires I2C"
|
||||
depends on SND && I2C=n
|
||||
|
||||
comment "ALSA PowerMac requires INPUT"
|
||||
depends on SND && INPUT=n
|
||||
if SND_PPC
|
||||
|
||||
config SND_POWERMAC
|
||||
tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)"
|
||||
depends on SND && I2C && INPUT && PPC_PMAC
|
||||
depends on I2C && INPUT && PPC_PMAC
|
||||
select SND_PCM
|
||||
help
|
||||
Say Y here to include support for the integrated sound device.
|
||||
|
@ -32,14 +32,9 @@ config SND_POWERMAC_AUTO_DRC
|
|||
Note that you can turn on/off DRC manually even without this
|
||||
option.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "ALSA PowerPC devices"
|
||||
depends on SND!=n && ( PPC64 || PPC32 )
|
||||
|
||||
config SND_PS3
|
||||
tristate "PS3 Audio support"
|
||||
depends on SND && PS3_PS3AV
|
||||
depends on PS3_PS3AV
|
||||
select SND_PCM
|
||||
default m
|
||||
help
|
||||
|
@ -52,4 +47,5 @@ config SND_PS3_DEFAULT_START_DELAY
|
|||
int "Startup delay time in ms"
|
||||
depends on SND_PS3
|
||||
default "2000"
|
||||
endmenu
|
||||
|
||||
endif # SND_PPC
|
||||
|
|
|
@ -249,9 +249,7 @@ int __init snd_pmac_daca_init(struct snd_pmac *chip)
|
|||
int i, err;
|
||||
struct pmac_daca *mix;
|
||||
|
||||
#ifdef CONFIG_KMOD
|
||||
request_module("i2c-powermac");
|
||||
#endif /* CONFIG_KMOD */
|
||||
|
||||
mix = kzalloc(sizeof(*mix), GFP_KERNEL);
|
||||
if (! mix)
|
||||
|
|
|
@ -1350,9 +1350,7 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip)
|
|||
struct device_node *tas_node, *np;
|
||||
char *chipname;
|
||||
|
||||
#ifdef CONFIG_KMOD
|
||||
request_module("i2c-powermac");
|
||||
#endif /* CONFIG_KMOD */
|
||||
|
||||
mix = kzalloc(sizeof(*mix), GFP_KERNEL);
|
||||
if (! mix)
|
||||
|
|
|
@ -1,14 +1,22 @@
|
|||
# ALSA SH drivers
|
||||
|
||||
menu "SUPERH devices"
|
||||
depends on SND!=n && SUPERH
|
||||
menuconfig SND_SUPERH
|
||||
bool "SUPERH sound devices"
|
||||
depends on SUPERH
|
||||
default y
|
||||
help
|
||||
Support for sound devices specific to SUPERH architectures.
|
||||
Drivers that are implemented on ASoC can be found in
|
||||
"ALSA for SoC audio support" section.
|
||||
|
||||
if SND_SUPERH
|
||||
|
||||
config SND_AICA
|
||||
tristate "Dreamcast Yamaha AICA sound"
|
||||
depends on SH_DREAMCAST && SND
|
||||
depends on SH_DREAMCAST
|
||||
select SND_PCM
|
||||
help
|
||||
ALSA Sound driver for the SEGA Dreamcast console.
|
||||
|
||||
endmenu
|
||||
endif # SND_SUPERH
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue