0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/init.h>
0011 #include <linux/input.h>
0012 #include <linux/io.h>
0013 #include "pcsp.h"
0014 #include "pcsp_input.h"
0015
0016 static void pcspkr_do_sound(unsigned int count)
0017 {
0018 unsigned long flags;
0019
0020 raw_spin_lock_irqsave(&i8253_lock, flags);
0021
0022 if (count) {
0023
0024 outb_p(0xB6, 0x43);
0025
0026 outb_p(count & 0xff, 0x42);
0027 outb((count >> 8) & 0xff, 0x42);
0028
0029 outb_p(inb_p(0x61) | 3, 0x61);
0030 } else {
0031
0032 outb(inb_p(0x61) & 0xFC, 0x61);
0033 }
0034
0035 raw_spin_unlock_irqrestore(&i8253_lock, flags);
0036 }
0037
0038 void pcspkr_stop_sound(void)
0039 {
0040 pcspkr_do_sound(0);
0041 }
0042
0043 static int pcspkr_input_event(struct input_dev *dev, unsigned int type,
0044 unsigned int code, int value)
0045 {
0046 unsigned int count = 0;
0047
0048 if (atomic_read(&pcsp_chip.timer_active) || !pcsp_chip.pcspkr)
0049 return 0;
0050
0051 switch (type) {
0052 case EV_SND:
0053 switch (code) {
0054 case SND_BELL:
0055 if (value)
0056 value = 1000;
0057 break;
0058 case SND_TONE:
0059 break;
0060 default:
0061 return -1;
0062 }
0063 break;
0064
0065 default:
0066 return -1;
0067 }
0068
0069 if (value > 20 && value < 32767)
0070 count = PIT_TICK_RATE / value;
0071
0072 pcspkr_do_sound(count);
0073
0074 return 0;
0075 }
0076
0077 int pcspkr_input_init(struct input_dev **rdev, struct device *dev)
0078 {
0079 int err;
0080
0081 struct input_dev *input_dev = devm_input_allocate_device(dev);
0082 if (!input_dev)
0083 return -ENOMEM;
0084
0085 input_dev->name = "PC Speaker";
0086 input_dev->phys = "isa0061/input0";
0087 input_dev->id.bustype = BUS_ISA;
0088 input_dev->id.vendor = 0x001f;
0089 input_dev->id.product = 0x0001;
0090 input_dev->id.version = 0x0100;
0091 input_dev->dev.parent = dev;
0092
0093 input_dev->evbit[0] = BIT(EV_SND);
0094 input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
0095 input_dev->event = pcspkr_input_event;
0096
0097 err = input_register_device(input_dev);
0098 if (err)
0099 return err;
0100
0101 *rdev = input_dev;
0102 return 0;
0103 }