Linux Audio

Check our new training course

Loading...
v3.15
  1/*
  2 *  PC Speaker beeper driver for Linux
  3 *
  4 *  Copyright (c) 2002 Vojtech Pavlik
  5 *  Copyright (c) 1992 Orest Zborowski
  6 *
  7 */
  8
  9/*
 10 * This program is free software; you can redistribute it and/or modify it
 11 * under the terms of the GNU General Public License version 2 as published by
 12 * the Free Software Foundation
 13 */
 14
 15#include <linux/init.h>
 16#include <linux/input.h>
 17#include <asm/io.h>
 18#include "pcsp.h"
 19#include "pcsp_input.h"
 20
 21static void pcspkr_do_sound(unsigned int count)
 22{
 23	unsigned long flags;
 24
 25	raw_spin_lock_irqsave(&i8253_lock, flags);
 26
 27	if (count) {
 28		/* set command for counter 2, 2 byte write */
 29		outb_p(0xB6, 0x43);
 30		/* select desired HZ */
 31		outb_p(count & 0xff, 0x42);
 32		outb((count >> 8) & 0xff, 0x42);
 33		/* enable counter 2 */
 34		outb_p(inb_p(0x61) | 3, 0x61);
 35	} else {
 36		/* disable counter 2 */
 37		outb(inb_p(0x61) & 0xFC, 0x61);
 38	}
 39
 40	raw_spin_unlock_irqrestore(&i8253_lock, flags);
 41}
 42
 43void pcspkr_stop_sound(void)
 44{
 45	pcspkr_do_sound(0);
 46}
 47
 48static int pcspkr_input_event(struct input_dev *dev, unsigned int type,
 49			      unsigned int code, int value)
 50{
 51	unsigned int count = 0;
 52
 53	if (atomic_read(&pcsp_chip.timer_active) || !pcsp_chip.pcspkr)
 54		return 0;
 55
 56	switch (type) {
 57	case EV_SND:
 58		switch (code) {
 59		case SND_BELL:
 60			if (value)
 61				value = 1000;
 62		case SND_TONE:
 63			break;
 64		default:
 65			return -1;
 66		}
 67		break;
 68
 69	default:
 70		return -1;
 71	}
 72
 73	if (value > 20 && value < 32767)
 74		count = PIT_TICK_RATE / value;
 75
 76	pcspkr_do_sound(count);
 77
 78	return 0;
 79}
 80
 81int pcspkr_input_init(struct input_dev **rdev, struct device *dev)
 82{
 83	int err;
 84
 85	struct input_dev *input_dev = input_allocate_device();
 86	if (!input_dev)
 87		return -ENOMEM;
 88
 89	input_dev->name = "PC Speaker";
 90	input_dev->phys = "isa0061/input0";
 91	input_dev->id.bustype = BUS_ISA;
 92	input_dev->id.vendor = 0x001f;
 93	input_dev->id.product = 0x0001;
 94	input_dev->id.version = 0x0100;
 95	input_dev->dev.parent = dev;
 96
 97	input_dev->evbit[0] = BIT(EV_SND);
 98	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
 99	input_dev->event = pcspkr_input_event;
100
101	err = input_register_device(input_dev);
102	if (err) {
103		input_free_device(input_dev);
104		return err;
105	}
106
107	*rdev = input_dev;
108	return 0;
109}
110
111int pcspkr_input_remove(struct input_dev *dev)
112{
113	pcspkr_stop_sound();
114	input_unregister_device(dev);	/* this also does kfree() */
115
116	return 0;
117}
v3.1
  1/*
  2 *  PC Speaker beeper driver for Linux
  3 *
  4 *  Copyright (c) 2002 Vojtech Pavlik
  5 *  Copyright (c) 1992 Orest Zborowski
  6 *
  7 */
  8
  9/*
 10 * This program is free software; you can redistribute it and/or modify it
 11 * under the terms of the GNU General Public License version 2 as published by
 12 * the Free Software Foundation
 13 */
 14
 15#include <linux/init.h>
 16#include <linux/input.h>
 17#include <asm/io.h>
 18#include "pcsp.h"
 
 19
 20static void pcspkr_do_sound(unsigned int count)
 21{
 22	unsigned long flags;
 23
 24	raw_spin_lock_irqsave(&i8253_lock, flags);
 25
 26	if (count) {
 27		/* set command for counter 2, 2 byte write */
 28		outb_p(0xB6, 0x43);
 29		/* select desired HZ */
 30		outb_p(count & 0xff, 0x42);
 31		outb((count >> 8) & 0xff, 0x42);
 32		/* enable counter 2 */
 33		outb_p(inb_p(0x61) | 3, 0x61);
 34	} else {
 35		/* disable counter 2 */
 36		outb(inb_p(0x61) & 0xFC, 0x61);
 37	}
 38
 39	raw_spin_unlock_irqrestore(&i8253_lock, flags);
 40}
 41
 42void pcspkr_stop_sound(void)
 43{
 44	pcspkr_do_sound(0);
 45}
 46
 47static int pcspkr_input_event(struct input_dev *dev, unsigned int type,
 48			      unsigned int code, int value)
 49{
 50	unsigned int count = 0;
 51
 52	if (atomic_read(&pcsp_chip.timer_active) || !pcsp_chip.pcspkr)
 53		return 0;
 54
 55	switch (type) {
 56	case EV_SND:
 57		switch (code) {
 58		case SND_BELL:
 59			if (value)
 60				value = 1000;
 61		case SND_TONE:
 62			break;
 63		default:
 64			return -1;
 65		}
 66		break;
 67
 68	default:
 69		return -1;
 70	}
 71
 72	if (value > 20 && value < 32767)
 73		count = PIT_TICK_RATE / value;
 74
 75	pcspkr_do_sound(count);
 76
 77	return 0;
 78}
 79
 80int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev)
 81{
 82	int err;
 83
 84	struct input_dev *input_dev = input_allocate_device();
 85	if (!input_dev)
 86		return -ENOMEM;
 87
 88	input_dev->name = "PC Speaker";
 89	input_dev->phys = "isa0061/input0";
 90	input_dev->id.bustype = BUS_ISA;
 91	input_dev->id.vendor = 0x001f;
 92	input_dev->id.product = 0x0001;
 93	input_dev->id.version = 0x0100;
 94	input_dev->dev.parent = dev;
 95
 96	input_dev->evbit[0] = BIT(EV_SND);
 97	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
 98	input_dev->event = pcspkr_input_event;
 99
100	err = input_register_device(input_dev);
101	if (err) {
102		input_free_device(input_dev);
103		return err;
104	}
105
106	*rdev = input_dev;
107	return 0;
108}
109
110int pcspkr_input_remove(struct input_dev *dev)
111{
112	pcspkr_stop_sound();
113	input_unregister_device(dev);	/* this also does kfree() */
114
115	return 0;
116}