brintos

brintos / linux-shallow public Read only

0
0
Text · 1.9 KiB · 5a799f7 Raw
104 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 *  PC Speaker beeper driver for Linux4 *5 *  Copyright (c) 2002 Vojtech Pavlik6 *  Copyright (c) 1992 Orest Zborowski7 */8 9 10#include <linux/init.h>11#include <linux/input.h>12#include <linux/io.h>13#include "pcsp.h"14#include "pcsp_input.h"15 16static void pcspkr_do_sound(unsigned int count)17{18	unsigned long flags;19 20	raw_spin_lock_irqsave(&i8253_lock, flags);21 22	if (count) {23		/* set command for counter 2, 2 byte write */24		outb_p(0xB6, 0x43);25		/* select desired HZ */26		outb_p(count & 0xff, 0x42);27		outb((count >> 8) & 0xff, 0x42);28		/* enable counter 2 */29		outb_p(inb_p(0x61) | 3, 0x61);30	} else {31		/* disable counter 2 */32		outb(inb_p(0x61) & 0xFC, 0x61);33	}34 35	raw_spin_unlock_irqrestore(&i8253_lock, flags);36}37 38void pcspkr_stop_sound(void)39{40	pcspkr_do_sound(0);41}42 43static int pcspkr_input_event(struct input_dev *dev, unsigned int type,44			      unsigned int code, int value)45{46	unsigned int count = 0;47 48	if (atomic_read(&pcsp_chip.timer_active) || !pcsp_chip.pcspkr)49		return 0;50 51	switch (type) {52	case EV_SND:53		switch (code) {54		case SND_BELL:55			if (value)56				value = 1000;57			break;58		case SND_TONE:59			break;60		default:61			return -1;62		}63		break;64 65	default:66		return -1;67	}68 69	if (value > 20 && value < 32767)70		count = PIT_TICK_RATE / value;71 72	pcspkr_do_sound(count);73 74	return 0;75}76 77int pcspkr_input_init(struct input_dev **rdev, struct device *dev)78{79	int err;80 81	struct input_dev *input_dev = devm_input_allocate_device(dev);82	if (!input_dev)83		return -ENOMEM;84 85	input_dev->name = "PC Speaker";86	input_dev->phys = "isa0061/input0";87	input_dev->id.bustype = BUS_ISA;88	input_dev->id.vendor = 0x001f;89	input_dev->id.product = 0x0001;90	input_dev->id.version = 0x0100;91	input_dev->dev.parent = dev;92 93	input_dev->evbit[0] = BIT(EV_SND);94	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);95	input_dev->event = pcspkr_input_event;96 97	err = input_register_device(input_dev);98	if (err)99		return err;100 101	*rdev = input_dev;102	return 0;103}104