提交 101e4d91 编写于 作者: L Linus Torvalds

Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa

* 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa:
  [ALSA] version 1.0.15
  [ALSA] hda-codec - Fix possible array overflow
  [ALSA] sound/core/control.c: hard-irq-safe -> hard-irq-unsafe lock warning
  [ALSA] usb-audio: Another USB mic quirk for Logitech Communicator webcam
  [ALSA] hda-codec - Fix build without CONFIG_SND_HDA_GENERIC
  [ALSA] hda-codec - Fix Conexant 5045 volumes
  [ALSA] hda-codec - Fix conflict of Master volume in STAC92xx codec
  [ALSA] snd-bt87x: Make the load_all option work correctly
  [ALSA] protect Dreamcast PCM driver (AICA) from G2 bus effects
  [ALSA] bt87x - Fix section mismatch
  [ALSA] hda-codec - Fix AD1986A Lenovo auto-mute
  [ALSA] This simplifies and fixes waiting loops of the mce_down()
/* include/version.h. Generated by alsa/ksync script. */ /* include/version.h. Generated by alsa/ksync script. */
#define CONFIG_SND_VERSION "1.0.15" #define CONFIG_SND_VERSION "1.0.15"
#define CONFIG_SND_DATE " (Tue Oct 16 14:57:44 2007 UTC)" #define CONFIG_SND_DATE " (Tue Oct 23 06:09:18 2007 UTC)"
...@@ -93,15 +93,16 @@ static int snd_ctl_open(struct inode *inode, struct file *file) ...@@ -93,15 +93,16 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl) static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl)
{ {
unsigned long flags;
struct snd_kctl_event *cread; struct snd_kctl_event *cread;
spin_lock(&ctl->read_lock); spin_lock_irqsave(&ctl->read_lock, flags);
while (!list_empty(&ctl->events)) { while (!list_empty(&ctl->events)) {
cread = snd_kctl_event(ctl->events.next); cread = snd_kctl_event(ctl->events.next);
list_del(&cread->list); list_del(&cread->list);
kfree(cread); kfree(cread);
} }
spin_unlock(&ctl->read_lock); spin_unlock_irqrestore(&ctl->read_lock, flags);
} }
static int snd_ctl_release(struct inode *inode, struct file *file) static int snd_ctl_release(struct inode *inode, struct file *file)
......
...@@ -165,7 +165,7 @@ struct snd_bt87x_board { ...@@ -165,7 +165,7 @@ struct snd_bt87x_board {
unsigned no_digital:1; /* No digital input */ unsigned no_digital:1; /* No digital input */
}; };
static const __devinitdata struct snd_bt87x_board snd_bt87x_boards[] = { static __devinitdata struct snd_bt87x_board snd_bt87x_boards[] = {
[SND_BT87X_BOARD_UNKNOWN] = { [SND_BT87X_BOARD_UNKNOWN] = {
.dig_rate = 32000, /* just a guess */ .dig_rate = 32000, /* just a guess */
}, },
...@@ -848,7 +848,7 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) ...@@ -848,7 +848,7 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
int i; int i;
const struct pci_device_id *supported; const struct pci_device_id *supported;
supported = pci_match_device(&driver, pci); supported = pci_match_id(snd_bt87x_ids, pci);
if (supported && supported->driver_data > 0) if (supported && supported->driver_data > 0)
return supported->driver_data; return supported->driver_data;
......
...@@ -626,24 +626,19 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, ...@@ -626,24 +626,19 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
snd_hda_get_codec_name(codec, bus->card->mixername, snd_hda_get_codec_name(codec, bus->card->mixername,
sizeof(bus->card->mixername)); sizeof(bus->card->mixername));
#ifdef CONFIG_SND_HDA_GENERIC
if (is_generic_config(codec)) { if (is_generic_config(codec)) {
err = snd_hda_parse_generic_codec(codec); err = snd_hda_parse_generic_codec(codec);
goto patched; goto patched;
} }
#endif
if (codec->preset && codec->preset->patch) { if (codec->preset && codec->preset->patch) {
err = codec->preset->patch(codec); err = codec->preset->patch(codec);
goto patched; goto patched;
} }
/* call the default parser */ /* call the default parser */
#ifdef CONFIG_SND_HDA_GENERIC
err = snd_hda_parse_generic_codec(codec); err = snd_hda_parse_generic_codec(codec);
#else if (err < 0)
printk(KERN_ERR "hda-codec: No codec parser is available\n"); printk(KERN_ERR "hda-codec: No codec parser is available\n");
err = -ENODEV;
#endif
patched: patched:
if (err < 0) { if (err < 0) {
......
...@@ -245,7 +245,14 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, ...@@ -245,7 +245,14 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
/* /*
* generic codec parser * generic codec parser
*/ */
#ifdef CONFIG_SND_HDA_GENERIC
int snd_hda_parse_generic_codec(struct hda_codec *codec); int snd_hda_parse_generic_codec(struct hda_codec *codec);
#else
static inline int snd_hda_parse_generic_codec(struct hda_codec *codec)
{
return -ENODEV;
}
#endif
/* /*
* generic proc interface * generic proc interface
...@@ -303,16 +310,17 @@ enum { ...@@ -303,16 +310,17 @@ enum {
extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST];
#define AUTO_CFG_MAX_OUTS 5
struct auto_pin_cfg { struct auto_pin_cfg {
int line_outs; int line_outs;
hda_nid_t line_out_pins[5]; /* sorted in the order of /* sorted in the order of Front/Surr/CLFE/Side */
* Front/Surr/CLFE/Side hda_nid_t line_out_pins[AUTO_CFG_MAX_OUTS];
*/
int speaker_outs; int speaker_outs;
hda_nid_t speaker_pins[5]; hda_nid_t speaker_pins[AUTO_CFG_MAX_OUTS];
int hp_outs; int hp_outs;
int line_out_type; /* AUTO_PIN_XXX_OUT */ int line_out_type; /* AUTO_PIN_XXX_OUT */
hda_nid_t hp_pins[5]; hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];
hda_nid_t input_pins[AUTO_PIN_LAST]; hda_nid_t input_pins[AUTO_PIN_LAST];
hda_nid_t dig_out_pin; hda_nid_t dig_out_pin;
hda_nid_t dig_in_pin; hda_nid_t dig_in_pin;
......
...@@ -72,7 +72,7 @@ struct ad198x_spec { ...@@ -72,7 +72,7 @@ struct ad198x_spec {
unsigned int num_kctl_alloc, num_kctl_used; unsigned int num_kctl_alloc, num_kctl_used;
struct snd_kcontrol_new *kctl_alloc; struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux; struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[4]; hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
unsigned int jack_present :1; unsigned int jack_present :1;
...@@ -612,7 +612,8 @@ static void ad1986a_hp_automute(struct hda_codec *codec) ...@@ -612,7 +612,8 @@ static void ad1986a_hp_automute(struct hda_codec *codec)
unsigned int present; unsigned int present;
present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0); present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0);
spec->jack_present = (present & 0x80000000) != 0; /* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
spec->jack_present = !(present & 0x80000000);
ad1986a_update_hp(codec); ad1986a_update_hp(codec);
} }
......
...@@ -50,7 +50,7 @@ struct cmi_spec { ...@@ -50,7 +50,7 @@ struct cmi_spec {
/* playback */ /* playback */
struct hda_multi_out multiout; struct hda_multi_out multiout;
hda_nid_t dac_nids[4]; /* NID for each DAC */ hda_nid_t dac_nids[AUTO_CFG_MAX_OUTS]; /* NID for each DAC */
int num_dacs; int num_dacs;
/* capture */ /* capture */
...@@ -73,7 +73,6 @@ struct cmi_spec { ...@@ -73,7 +73,6 @@ struct cmi_spec {
unsigned int pin_def_confs; unsigned int pin_def_confs;
/* multichannel pins */ /* multichannel pins */
hda_nid_t multich_pin[4]; /* max 8-channel */
struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */ struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */
}; };
......
...@@ -85,7 +85,7 @@ struct conexant_spec { ...@@ -85,7 +85,7 @@ struct conexant_spec {
unsigned int num_kctl_alloc, num_kctl_used; unsigned int num_kctl_alloc, num_kctl_used;
struct snd_kcontrol_new *kctl_alloc; struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux; struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[4]; hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
}; };
...@@ -554,10 +554,16 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { ...@@ -554,10 +554,16 @@ static struct snd_kcontrol_new cxt5045_mixers[] = {
.get = conexant_mux_enum_get, .get = conexant_mux_enum_get,
.put = conexant_mux_enum_put .put = conexant_mux_enum_put
}, },
HDA_CODEC_VOLUME("Int Mic Volume", 0x1a, 0x01, HDA_INPUT), HDA_CODEC_VOLUME("Int Mic Capture Volume", 0x1a, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic Switch", 0x1a, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Int Mic Capture Switch", 0x1a, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("Ext Mic Volume", 0x1a, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Ext Mic Capture Volume", 0x1a, 0x02, HDA_INPUT),
HDA_CODEC_MUTE("Ext Mic Switch", 0x1a, 0x02, HDA_INPUT), HDA_CODEC_MUTE("Ext Mic Capture Switch", 0x1a, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol), HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
{ {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
...@@ -576,16 +582,15 @@ static struct hda_verb cxt5045_init_verbs[] = { ...@@ -576,16 +582,15 @@ static struct hda_verb cxt5045_init_verbs[] = {
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
{0x14, 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 */ /* HP, Amp */
{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x17, AC_VERB_SET_CONNECT_SEL,0x01}, {0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x01}, {0x11, AC_VERB_SET_CONNECT_SEL, 0x1},
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x02}, {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03}, {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x04},
/* Record selector: Int mic */ /* Record selector: Int mic */
{0x1a, AC_VERB_SET_CONNECT_SEL,0x1}, {0x1a, AC_VERB_SET_CONNECT_SEL,0x1},
{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, {0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
......
...@@ -238,7 +238,7 @@ struct alc_spec { ...@@ -238,7 +238,7 @@ struct alc_spec {
unsigned int num_kctl_alloc, num_kctl_used; unsigned int num_kctl_alloc, num_kctl_used;
struct snd_kcontrol_new *kctl_alloc; struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux; struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[5]; hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
/* hooks */ /* hooks */
void (*init_hook)(struct hda_codec *codec); void (*init_hook)(struct hda_codec *codec);
......
...@@ -111,6 +111,7 @@ struct sigmatel_spec { ...@@ -111,6 +111,7 @@ struct sigmatel_spec {
unsigned int alt_switch: 1; unsigned int alt_switch: 1;
unsigned int hp_detect: 1; unsigned int hp_detect: 1;
unsigned int gpio_mute: 1; unsigned int gpio_mute: 1;
unsigned int no_vol_knob :1;
unsigned int gpio_mask, gpio_data; unsigned int gpio_mask, gpio_data;
...@@ -1930,7 +1931,8 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, ...@@ -1930,7 +1931,8 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
} }
if (spec->multiout.hp_nid) { if (spec->multiout.hp_nid) {
const char *pfx; const char *pfx;
if (old_num_dacs == spec->multiout.num_dacs) if (old_num_dacs == spec->multiout.num_dacs &&
spec->no_vol_knob)
pfx = "Master"; pfx = "Master";
else else
pfx = "Headphone"; pfx = "Headphone";
...@@ -2487,6 +2489,7 @@ static int patch_stac9200(struct hda_codec *codec) ...@@ -2487,6 +2489,7 @@ static int patch_stac9200(struct hda_codec *codec)
codec->spec = spec; codec->spec = spec;
spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); spec->num_pins = ARRAY_SIZE(stac9200_pin_nids);
spec->pin_nids = stac9200_pin_nids; spec->pin_nids = stac9200_pin_nids;
spec->no_vol_knob = 1;
spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
stac9200_models, stac9200_models,
stac9200_cfg_tbl); stac9200_cfg_tbl);
...@@ -2541,6 +2544,7 @@ static int patch_stac925x(struct hda_codec *codec) ...@@ -2541,6 +2544,7 @@ static int patch_stac925x(struct hda_codec *codec)
codec->spec = spec; codec->spec = spec;
spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); spec->num_pins = ARRAY_SIZE(stac925x_pin_nids);
spec->pin_nids = stac925x_pin_nids; spec->pin_nids = stac925x_pin_nids;
spec->no_vol_knob = 1;
spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS, spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS,
stac925x_models, stac925x_models,
stac925x_cfg_tbl); stac925x_cfg_tbl);
......
...@@ -114,7 +114,7 @@ struct via_spec { ...@@ -114,7 +114,7 @@ struct via_spec {
unsigned int num_kctl_alloc, num_kctl_used; unsigned int num_kctl_alloc, num_kctl_used;
struct snd_kcontrol_new *kctl_alloc; struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux; struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[4]; hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback; struct hda_loopback_check loopback;
......
...@@ -106,11 +106,14 @@ static void spu_write_wait(void) ...@@ -106,11 +106,14 @@ static void spu_write_wait(void)
static void spu_memset(u32 toi, u32 what, int length) static void spu_memset(u32 toi, u32 what, int length)
{ {
int i; int i;
unsigned long flags;
snd_assert(length % 4 == 0, return); snd_assert(length % 4 == 0, return);
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
if (!(i % 8)) if (!(i % 8))
spu_write_wait(); spu_write_wait();
local_irq_save(flags);
writel(what, toi + SPU_MEMORY_BASE); writel(what, toi + SPU_MEMORY_BASE);
local_irq_restore(flags);
toi++; toi++;
} }
} }
...@@ -118,6 +121,7 @@ static void spu_memset(u32 toi, u32 what, int length) ...@@ -118,6 +121,7 @@ static void spu_memset(u32 toi, u32 what, int length)
/* spu_memload - write to SPU address space */ /* spu_memload - write to SPU address space */
static void spu_memload(u32 toi, void *from, int length) static void spu_memload(u32 toi, void *from, int length)
{ {
unsigned long flags;
u32 *froml = from; u32 *froml = from;
u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi); u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi);
int i; int i;
...@@ -128,7 +132,9 @@ static void spu_memload(u32 toi, void *from, int length) ...@@ -128,7 +132,9 @@ static void spu_memload(u32 toi, void *from, int length)
if (!(i % 8)) if (!(i % 8))
spu_write_wait(); spu_write_wait();
val = *froml; val = *froml;
local_irq_save(flags);
writel(val, to); writel(val, to);
local_irq_restore(flags);
froml++; froml++;
to++; to++;
} }
...@@ -138,28 +144,36 @@ static void spu_memload(u32 toi, void *from, int length) ...@@ -138,28 +144,36 @@ static void spu_memload(u32 toi, void *from, int length)
static void spu_disable(void) static void spu_disable(void)
{ {
int i; int i;
unsigned long flags;
u32 regval; u32 regval;
spu_write_wait(); spu_write_wait();
regval = readl(ARM_RESET_REGISTER); regval = readl(ARM_RESET_REGISTER);
regval |= 1; regval |= 1;
spu_write_wait(); spu_write_wait();
local_irq_save(flags);
writel(regval, ARM_RESET_REGISTER); writel(regval, ARM_RESET_REGISTER);
local_irq_restore(flags);
for (i = 0; i < 64; i++) { for (i = 0; i < 64; i++) {
spu_write_wait(); spu_write_wait();
regval = readl(SPU_REGISTER_BASE + (i * 0x80)); regval = readl(SPU_REGISTER_BASE + (i * 0x80));
regval = (regval & ~0x4000) | 0x8000; regval = (regval & ~0x4000) | 0x8000;
spu_write_wait(); spu_write_wait();
local_irq_save(flags);
writel(regval, SPU_REGISTER_BASE + (i * 0x80)); writel(regval, SPU_REGISTER_BASE + (i * 0x80));
local_irq_restore(flags);
} }
} }
/* spu_enable - set spu registers to enable sound output */ /* spu_enable - set spu registers to enable sound output */
static void spu_enable(void) static void spu_enable(void)
{ {
unsigned long flags;
u32 regval = readl(ARM_RESET_REGISTER); u32 regval = readl(ARM_RESET_REGISTER);
regval &= ~1; regval &= ~1;
spu_write_wait(); spu_write_wait();
local_irq_save(flags);
writel(regval, ARM_RESET_REGISTER); writel(regval, ARM_RESET_REGISTER);
local_irq_restore(flags);
} }
/* /*
...@@ -168,25 +182,34 @@ static void spu_enable(void) ...@@ -168,25 +182,34 @@ static void spu_enable(void)
*/ */
static void spu_reset(void) static void spu_reset(void)
{ {
unsigned long flags;
spu_disable(); spu_disable();
spu_memset(0, 0, 0x200000 / 4); spu_memset(0, 0, 0x200000 / 4);
/* Put ARM7 in endless loop */ /* Put ARM7 in endless loop */
local_irq_save(flags);
ctrl_outl(0xea000002, SPU_MEMORY_BASE); ctrl_outl(0xea000002, SPU_MEMORY_BASE);
local_irq_restore(flags);
spu_enable(); spu_enable();
} }
/* aica_chn_start - write to spu to start playback */ /* aica_chn_start - write to spu to start playback */
static void aica_chn_start(void) static void aica_chn_start(void)
{ {
unsigned long flags;
spu_write_wait(); spu_write_wait();
local_irq_save(flags);
writel(AICA_CMD_KICK | AICA_CMD_START, (u32 *) AICA_CONTROL_POINT); writel(AICA_CMD_KICK | AICA_CMD_START, (u32 *) AICA_CONTROL_POINT);
local_irq_restore(flags);
} }
/* aica_chn_halt - write to spu to halt playback */ /* aica_chn_halt - write to spu to halt playback */
static void aica_chn_halt(void) static void aica_chn_halt(void)
{ {
unsigned long flags;
spu_write_wait(); spu_write_wait();
local_irq_save(flags);
writel(AICA_CMD_KICK | AICA_CMD_STOP, (u32 *) AICA_CONTROL_POINT); writel(AICA_CMD_KICK | AICA_CMD_STOP, (u32 *) AICA_CONTROL_POINT);
local_irq_restore(flags);
} }
/* ALSA code below */ /* ALSA code below */
...@@ -213,12 +236,13 @@ static int aica_dma_transfer(int channels, int buffer_size, ...@@ -213,12 +236,13 @@ static int aica_dma_transfer(int channels, int buffer_size,
int q, err, period_offset; int q, err, period_offset;
struct snd_card_aica *dreamcastcard; struct snd_card_aica *dreamcastcard;
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
err = 0; unsigned long flags;
dreamcastcard = substream->pcm->private_data; dreamcastcard = substream->pcm->private_data;
period_offset = dreamcastcard->clicks; period_offset = dreamcastcard->clicks;
period_offset %= (AICA_PERIOD_NUMBER / channels); period_offset %= (AICA_PERIOD_NUMBER / channels);
runtime = substream->runtime; runtime = substream->runtime;
for (q = 0; q < channels; q++) { for (q = 0; q < channels; q++) {
local_irq_save(flags);
err = dma_xfer(AICA_DMA_CHANNEL, err = dma_xfer(AICA_DMA_CHANNEL,
(unsigned long) (runtime->dma_area + (unsigned long) (runtime->dma_area +
(AICA_BUFFER_SIZE * q) / (AICA_BUFFER_SIZE * q) /
...@@ -228,9 +252,12 @@ static int aica_dma_transfer(int channels, int buffer_size, ...@@ -228,9 +252,12 @@ static int aica_dma_transfer(int channels, int buffer_size,
AICA_CHANNEL0_OFFSET + q * CHANNEL_OFFSET + AICA_CHANNEL0_OFFSET + q * CHANNEL_OFFSET +
AICA_PERIOD_SIZE * period_offset, AICA_PERIOD_SIZE * period_offset,
buffer_size / channels, AICA_DMA_MODE); buffer_size / channels, AICA_DMA_MODE);
if (unlikely(err < 0)) if (unlikely(err < 0)) {
local_irq_restore(flags);
break; break;
}
dma_wait_for_completion(AICA_DMA_CHANNEL); dma_wait_for_completion(AICA_DMA_CHANNEL);
local_irq_restore(flags);
} }
return err; return err;
} }
......
...@@ -400,65 +400,44 @@ static void snd_cs4231_mce_up(struct snd_cs4231 *chip) ...@@ -400,65 +400,44 @@ static void snd_cs4231_mce_up(struct snd_cs4231 *chip)
static void snd_cs4231_mce_down(struct snd_cs4231 *chip) static void snd_cs4231_mce_down(struct snd_cs4231 *chip)
{ {
unsigned long flags; unsigned long flags, timeout;
unsigned long end_time; int reg;
int timeout;
spin_lock_irqsave(&chip->lock, flags);
snd_cs4231_busy_wait(chip); snd_cs4231_busy_wait(chip);
spin_lock_irqsave(&chip->lock, flags);
#ifdef CONFIG_SND_DEBUG #ifdef CONFIG_SND_DEBUG
if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT)
snd_printdd("mce_down [%p] - auto calibration time out (0)\n", snd_printdd("mce_down [%p] - auto calibration time out (0)\n",
CS4231U(chip, REGSEL)); CS4231U(chip, REGSEL));
#endif #endif
chip->mce_bit &= ~CS4231_MCE; chip->mce_bit &= ~CS4231_MCE;
timeout = __cs4231_readb(chip, CS4231U(chip, REGSEL)); reg = __cs4231_readb(chip, CS4231U(chip, REGSEL));
__cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), __cs4231_writeb(chip, chip->mce_bit | (reg & 0x1f),
CS4231U(chip, REGSEL)); CS4231U(chip, REGSEL));
if (timeout == 0x80) if (reg == 0x80)
snd_printdd("mce_down [%p]: serious init problem - " snd_printdd("mce_down [%p]: serious init problem "
"codec still busy\n", "- codec still busy\n", chip->port);
chip->port); if ((reg & CS4231_MCE) == 0) {
if ((timeout & CS4231_MCE) == 0) {
spin_unlock_irqrestore(&chip->lock, flags); spin_unlock_irqrestore(&chip->lock, flags);
return; return;
} }
/* /*
* Wait for (possible -- during init auto-calibration may not be set) * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low.
* calibration process to start. Needs upto 5 sample periods on AD1848
* which at the slowest possible rate of 5.5125 kHz means 907 us.
*/ */
msleep(1); timeout = jiffies + msecs_to_jiffies(250);
do {
/* check condition up to 250ms */
end_time = jiffies + msecs_to_jiffies(250);
while (snd_cs4231_in(chip, CS4231_TEST_INIT) &
CS4231_CALIB_IN_PROGRESS) {
spin_unlock_irqrestore(&chip->lock, flags); spin_unlock_irqrestore(&chip->lock, flags);
if (time_after(jiffies, end_time)) {
snd_printk("mce_down - "
"auto calibration time out (2)\n");
return;
}
msleep(1);
spin_lock_irqsave(&chip->lock, flags);
}
/* check condition up to 100ms */
end_time = jiffies + msecs_to_jiffies(100);
while (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) {
spin_unlock_irqrestore(&chip->lock, flags);
if (time_after(jiffies, end_time)) {
snd_printk("mce_down - "
"auto calibration time out (3)\n");
return;
}
msleep(1); msleep(1);
spin_lock_irqsave(&chip->lock, flags); spin_lock_irqsave(&chip->lock, flags);
} reg = snd_cs4231_in(chip, CS4231_TEST_INIT);
reg &= CS4231_CALIB_IN_PROGRESS;
} while (reg && time_before(jiffies, timeout));
spin_unlock_irqrestore(&chip->lock, flags); spin_unlock_irqrestore(&chip->lock, flags);
if (reg)
snd_printk(KERN_ERR
"mce_down - auto calibration time out (2)\n");
} }
static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont, static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont,
......
...@@ -79,6 +79,15 @@ ...@@ -79,6 +79,15 @@
.bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
}, },
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.idVendor = 0x046d,
.idProduct = 0x08f5,
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
},
{ {
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_CLASS |
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册