diff options
Diffstat (limited to 'sound/drivers/pcsp')
| -rw-r--r-- | sound/drivers/pcsp/pcsp.c | 71 | ||||
| -rw-r--r-- | sound/drivers/pcsp/pcsp.h | 10 | ||||
| -rw-r--r-- | sound/drivers/pcsp/pcsp_input.c | 7 | ||||
| -rw-r--r-- | sound/drivers/pcsp/pcsp_input.h | 2 | ||||
| -rw-r--r-- | sound/drivers/pcsp/pcsp_lib.c | 17 | ||||
| -rw-r--r-- | sound/drivers/pcsp/pcsp_mixer.c | 35 |
6 files changed, 83 insertions, 59 deletions
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index b60cef257b5..36808cdab06 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c @@ -6,7 +6,7 @@ */ #include <linux/init.h> -#include <linux/moduleparam.h> +#include <linux/module.h> #include <linux/platform_device.h> #include <sound/core.h> #include <sound/initval.h> @@ -25,7 +25,8 @@ MODULE_ALIAS("platform:pcspkr"); static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -static int enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */ +static bool enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */ +static bool nopcm; /* Disable PCM capability of the driver */ module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for pcsp soundcard."); @@ -33,10 +34,12 @@ module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for pcsp soundcard."); module_param(enable, bool, 0444); MODULE_PARM_DESC(enable, "Enable PC-Speaker sound."); +module_param(nopcm, bool, 0444); +MODULE_PARM_DESC(nopcm, "Disable PC-Speaker PCM sound. Only beeps remain."); struct snd_pcsp pcsp_chip; -static int __devinit snd_pcsp_create(struct snd_card *card) +static int snd_pcsp_create(struct snd_card *card) { static struct snd_device_ops ops = { }; struct timespec tp; @@ -44,12 +47,16 @@ static int __devinit snd_pcsp_create(struct snd_card *card) int div, min_div, order; hrtimer_get_res(CLOCK_MONOTONIC, &tp); - if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) { - printk(KERN_ERR "PCSP: Timer resolution is not sufficient " - "(%linS)\n", tp.tv_nsec); - printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI " - "enabled.\n"); - return -EIO; + + if (!nopcm) { + if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) { + printk(KERN_ERR "PCSP: Timer resolution is not sufficient " + "(%linS)\n", tp.tv_nsec); + printk(KERN_ERR "PCSP: Make sure you have HPET and ACPI " + "enabled.\n"); + printk(KERN_ERR "PCSP: Turned into nopcm mode.\n"); + nopcm = 1; + } } if (loops_per_jiffy >= PCSP_MIN_LPJ && tp.tv_nsec <= PCSP_MIN_PERIOD_NS) @@ -87,7 +94,7 @@ static int __devinit snd_pcsp_create(struct snd_card *card) return 0; } -static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) +static int snd_card_pcsp_probe(int devnum, struct device *dev) { struct snd_card *card; int err; @@ -98,7 +105,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pcsp_chip.timer.function = pcsp_do_timer; - err = snd_card_create(index, id, THIS_MODULE, 0, &card); + err = snd_card_new(dev, index, id, THIS_MODULE, 0, &card); if (err < 0) return err; @@ -107,19 +114,19 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) snd_card_free(card); return err; } - err = snd_pcsp_new_pcm(&pcsp_chip); - if (err < 0) { - snd_card_free(card); - return err; + if (!nopcm) { + err = snd_pcsp_new_pcm(&pcsp_chip); + if (err < 0) { + snd_card_free(card); + return err; + } } - err = snd_pcsp_new_mixer(&pcsp_chip); + err = snd_pcsp_new_mixer(&pcsp_chip, nopcm); if (err < 0) { snd_card_free(card); return err; } - snd_card_set_dev(pcsp_chip.card, dev); - strcpy(card->driver, "PC-Speaker"); strcpy(card->shortname, "pcsp"); sprintf(card->longname, "Internal PC-Speaker at port 0x%x", @@ -134,7 +141,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) return 0; } -static int __devinit alsa_card_pcsp_init(struct device *dev) +static int alsa_card_pcsp_init(struct device *dev) { int err; @@ -153,12 +160,12 @@ static int __devinit alsa_card_pcsp_init(struct device *dev) return 0; } -static void __devexit alsa_card_pcsp_exit(struct snd_pcsp *chip) +static void alsa_card_pcsp_exit(struct snd_pcsp *chip) { snd_card_free(chip->card); } -static int __devinit pcsp_probe(struct platform_device *dev) +static int pcsp_probe(struct platform_device *dev) { int err; @@ -176,12 +183,11 @@ static int __devinit pcsp_probe(struct platform_device *dev) return 0; } -static int __devexit pcsp_remove(struct platform_device *dev) +static int pcsp_remove(struct platform_device *dev) { struct snd_pcsp *chip = platform_get_drvdata(dev); - alsa_card_pcsp_exit(chip); pcspkr_input_remove(chip->input_dev); - platform_set_drvdata(dev, NULL); + alsa_card_pcsp_exit(chip); return 0; } @@ -191,17 +197,20 @@ static void pcsp_stop_beep(struct snd_pcsp *chip) pcspkr_stop_sound(); } -#ifdef CONFIG_PM -static int pcsp_suspend(struct platform_device *dev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int pcsp_suspend(struct device *dev) { - struct snd_pcsp *chip = platform_get_drvdata(dev); + struct snd_pcsp *chip = dev_get_drvdata(dev); pcsp_stop_beep(chip); snd_pcm_suspend_all(chip->pcm); return 0; } + +static SIMPLE_DEV_PM_OPS(pcsp_pm, pcsp_suspend, NULL); +#define PCSP_PM_OPS &pcsp_pm #else -#define pcsp_suspend NULL -#endif /* CONFIG_PM */ +#define PCSP_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ static void pcsp_shutdown(struct platform_device *dev) { @@ -213,10 +222,10 @@ static struct platform_driver pcsp_platform_driver = { .driver = { .name = "pcspkr", .owner = THIS_MODULE, + .pm = PCSP_PM_OPS, }, .probe = pcsp_probe, - .remove = __devexit_p(pcsp_remove), - .suspend = pcsp_suspend, + .remove = pcsp_remove, .shutdown = pcsp_shutdown, }; diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h index 174dd2ff0f2..fc7a2dc410a 100644 --- a/sound/drivers/pcsp/pcsp.h +++ b/sound/drivers/pcsp/pcsp.h @@ -10,14 +10,8 @@ #define __PCSP_H__ #include <linux/hrtimer.h> +#include <linux/i8253.h> #include <linux/timex.h> -#if defined(CONFIG_MIPS) || defined(CONFIG_X86) -/* Use the global PIT lock ! */ -#include <asm/i8253.h> -#else -#include <asm/8253pit.h> -static DEFINE_SPINLOCK(i8253_lock); -#endif #define PCSP_SOUND_VERSION 0x400 /* read 4.00 */ #define PCSP_DEBUG 0 @@ -83,6 +77,6 @@ extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle); extern void pcsp_sync_stop(struct snd_pcsp *chip); extern int snd_pcsp_new_pcm(struct snd_pcsp *chip); -extern int snd_pcsp_new_mixer(struct snd_pcsp *chip); +extern int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm); #endif diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c index 0444cdeb4be..0ecf8a453e0 100644 --- a/sound/drivers/pcsp/pcsp_input.c +++ b/sound/drivers/pcsp/pcsp_input.c @@ -16,12 +16,13 @@ #include <linux/input.h> #include <asm/io.h> #include "pcsp.h" +#include "pcsp_input.h" static void pcspkr_do_sound(unsigned int count) { unsigned long flags; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); if (count) { /* set command for counter 2, 2 byte write */ @@ -36,7 +37,7 @@ static void pcspkr_do_sound(unsigned int count) outb(inb_p(0x61) & 0xFC, 0x61); } - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); } void pcspkr_stop_sound(void) @@ -77,7 +78,7 @@ static int pcspkr_input_event(struct input_dev *dev, unsigned int type, return 0; } -int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev) +int pcspkr_input_init(struct input_dev **rdev, struct device *dev) { int err; diff --git a/sound/drivers/pcsp/pcsp_input.h b/sound/drivers/pcsp/pcsp_input.h index e66738c7833..d692749b8c9 100644 --- a/sound/drivers/pcsp/pcsp_input.h +++ b/sound/drivers/pcsp/pcsp_input.h @@ -7,7 +7,7 @@ #ifndef __PCSP_INPUT_H__ #define __PCSP_INPUT_H__ -int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev); +int pcspkr_input_init(struct input_dev **rdev, struct device *dev); int pcspkr_input_remove(struct input_dev *dev); void pcspkr_stop_sound(void); diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index e1145ac6e90..29ebaa4ec0f 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c @@ -7,13 +7,14 @@ */ #include <linux/module.h> +#include <linux/gfp.h> #include <linux/moduleparam.h> #include <linux/interrupt.h> #include <sound/pcm.h> #include <asm/io.h> #include "pcsp.h" -static int nforce_wa; +static bool nforce_wa; module_param(nforce_wa, bool, 0444); MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround " "(expect bad sound)"); @@ -65,7 +66,7 @@ static u64 pcsp_timer_update(struct snd_pcsp *chip) timer_cnt = val * CUR_DIV() / 256; if (timer_cnt && chip->enable) { - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); if (!nforce_wa) { outb_p(chip->val61, 0x61); outb_p(timer_cnt, 0x42); @@ -74,7 +75,7 @@ static u64 pcsp_timer_update(struct snd_pcsp *chip) outb(chip->val61 ^ 2, 0x61); chip->thalf = 1; } - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); } chip->ns_rem = PCSP_PERIOD_NS(); @@ -158,10 +159,10 @@ static int pcsp_start_playing(struct snd_pcsp *chip) return -EIO; } - spin_lock(&i8253_lock); + raw_spin_lock(&i8253_lock); chip->val61 = inb(0x61) | 0x03; outb_p(0x92, 0x43); /* binary, mode 1, LSB only, ch 2 */ - spin_unlock(&i8253_lock); + raw_spin_unlock(&i8253_lock); atomic_set(&chip->timer_active, 1); chip->thalf = 0; @@ -178,11 +179,11 @@ static void pcsp_stop_playing(struct snd_pcsp *chip) return; atomic_set(&chip->timer_active, 0); - spin_lock(&i8253_lock); + raw_spin_lock(&i8253_lock); /* restore the timer */ outb_p(0xb6, 0x43); /* binary, mode 3, LSB/MSB, ch 2 */ outb(chip->val61 & 0xFC, 0x61); - spin_unlock(&i8253_lock); + raw_spin_unlock(&i8253_lock); } /* @@ -333,7 +334,7 @@ static struct snd_pcm_ops snd_pcsp_playback_ops = { .pointer = snd_pcsp_playback_pointer, }; -int __devinit snd_pcsp_new_pcm(struct snd_pcsp *chip) +int snd_pcsp_new_pcm(struct snd_pcsp *chip) { int err; diff --git a/sound/drivers/pcsp/pcsp_mixer.c b/sound/drivers/pcsp/pcsp_mixer.c index 903bc846763..f1e1defc09b 100644 --- a/sound/drivers/pcsp/pcsp_mixer.c +++ b/sound/drivers/pcsp/pcsp_mixer.c @@ -119,24 +119,43 @@ static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol, .put = pcsp_##ctl_type##_put, \ } -static struct snd_kcontrol_new __devinitdata snd_pcsp_controls[] = { +static struct snd_kcontrol_new snd_pcsp_controls_pcm[] = { PCSP_MIXER_CONTROL(enable, "Master Playback Switch"), PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"), - PCSP_MIXER_CONTROL(pcspkr, "PC Speaker Playback Switch"), }; -int __devinit snd_pcsp_new_mixer(struct snd_pcsp *chip) +static struct snd_kcontrol_new snd_pcsp_controls_spkr[] = { + PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"), +}; + +static int snd_pcsp_ctls_add(struct snd_pcsp *chip, + struct snd_kcontrol_new *ctls, int num) { - struct snd_card *card = chip->card; int i, err; + struct snd_card *card = chip->card; + for (i = 0; i < num; i++) { + err = snd_ctl_add(card, snd_ctl_new1(ctls + i, chip)); + if (err < 0) + return err; + } + return 0; +} + +int snd_pcsp_new_mixer(struct snd_pcsp *chip, int nopcm) +{ + int err; + struct snd_card *card = chip->card; - for (i = 0; i < ARRAY_SIZE(snd_pcsp_controls); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(snd_pcsp_controls + i, - chip)); + if (!nopcm) { + err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_pcm, + ARRAY_SIZE(snd_pcsp_controls_pcm)); if (err < 0) return err; } + err = snd_pcsp_ctls_add(chip, snd_pcsp_controls_spkr, + ARRAY_SIZE(snd_pcsp_controls_spkr)); + if (err < 0) + return err; strcpy(card->mixername, "PC-Speaker"); |
