Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  PC Speaker beeper driver for Linux
0004  *
0005  *  Copyright (c) 2002 Vojtech Pavlik
0006  *  Copyright (c) 1992 Orest Zborowski
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         /* set command for counter 2, 2 byte write */
0024         outb_p(0xB6, 0x43);
0025         /* select desired HZ */
0026         outb_p(count & 0xff, 0x42);
0027         outb((count >> 8) & 0xff, 0x42);
0028         /* enable counter 2 */
0029         outb_p(inb_p(0x61) | 3, 0x61);
0030     } else {
0031         /* disable counter 2 */
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 }