root/drivers/input/misc/ixp4xx-beeper.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ixp4xx_spkr_control
  2. ixp4xx_spkr_event
  3. ixp4xx_spkr_interrupt
  4. ixp4xx_spkr_probe
  5. ixp4xx_spkr_remove
  6. ixp4xx_spkr_shutdown

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Generic IXP4xx beeper driver
   4  *
   5  * Copyright (C) 2005 Tower Technologies
   6  *
   7  * based on nslu2-io.c
   8  *  Copyright (C) 2004 Karen Spearel
   9  *
  10  * Author: Alessandro Zummo <a.zummo@towertech.it>
  11  * Maintainers: http://www.nslu2-linux.org/
  12  */
  13 
  14 #include <linux/module.h>
  15 #include <linux/input.h>
  16 #include <linux/delay.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/interrupt.h>
  19 #include <linux/gpio.h>
  20 #include <mach/hardware.h>
  21 
  22 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
  23 MODULE_DESCRIPTION("ixp4xx beeper driver");
  24 MODULE_LICENSE("GPL");
  25 MODULE_ALIAS("platform:ixp4xx-beeper");
  26 
  27 static DEFINE_SPINLOCK(beep_lock);
  28 
  29 static int ixp4xx_timer2_irq;
  30 
  31 static void ixp4xx_spkr_control(unsigned int pin, unsigned int count)
  32 {
  33         unsigned long flags;
  34 
  35         spin_lock_irqsave(&beep_lock, flags);
  36 
  37         if (count) {
  38                 gpio_direction_output(pin, 0);
  39                 *IXP4XX_OSRT2 = (count & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE;
  40         } else {
  41                 gpio_direction_output(pin, 1);
  42                 gpio_direction_input(pin);
  43                 *IXP4XX_OSRT2 = 0;
  44         }
  45 
  46         spin_unlock_irqrestore(&beep_lock, flags);
  47 }
  48 
  49 static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
  50 {
  51         unsigned int pin = (unsigned int) input_get_drvdata(dev);
  52         unsigned int count = 0;
  53 
  54         if (type != EV_SND)
  55                 return -1;
  56 
  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 
  67         if (value > 20 && value < 32767)
  68                 count = (ixp4xx_timer_freq / (value * 4)) - 1;
  69 
  70         ixp4xx_spkr_control(pin, count);
  71 
  72         return 0;
  73 }
  74 
  75 static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id)
  76 {
  77         unsigned int pin = (unsigned int) dev_id;
  78 
  79         /* clear interrupt */
  80         *IXP4XX_OSST = IXP4XX_OSST_TIMER_2_PEND;
  81 
  82         /* flip the beeper output */
  83         gpio_set_value(pin, !gpio_get_value(pin));
  84 
  85         return IRQ_HANDLED;
  86 }
  87 
  88 static int ixp4xx_spkr_probe(struct platform_device *dev)
  89 {
  90         struct input_dev *input_dev;
  91         int irq;
  92         int err;
  93 
  94         input_dev = input_allocate_device();
  95         if (!input_dev)
  96                 return -ENOMEM;
  97 
  98         input_set_drvdata(input_dev, (void *) dev->id);
  99 
 100         input_dev->name = "ixp4xx beeper",
 101         input_dev->phys = "ixp4xx/gpio";
 102         input_dev->id.bustype = BUS_HOST;
 103         input_dev->id.vendor  = 0x001f;
 104         input_dev->id.product = 0x0001;
 105         input_dev->id.version = 0x0100;
 106         input_dev->dev.parent = &dev->dev;
 107 
 108         input_dev->evbit[0] = BIT_MASK(EV_SND);
 109         input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
 110         input_dev->event = ixp4xx_spkr_event;
 111 
 112         irq = platform_get_irq(dev, 0);
 113         if (irq < 0) {
 114                 err = irq;
 115                 goto err_free_device;
 116         }
 117 
 118         err = gpio_request(dev->id, "ixp4-beeper");
 119         if (err)
 120                 goto err_free_device;
 121 
 122         err = request_irq(irq, &ixp4xx_spkr_interrupt,
 123                           IRQF_NO_SUSPEND, "ixp4xx-beeper",
 124                           (void *) dev->id);
 125         if (err)
 126                 goto err_free_gpio;
 127         ixp4xx_timer2_irq = irq;
 128 
 129         err = input_register_device(input_dev);
 130         if (err)
 131                 goto err_free_irq;
 132 
 133         platform_set_drvdata(dev, input_dev);
 134 
 135         return 0;
 136 
 137  err_free_irq:
 138         free_irq(irq, (void *)dev->id);
 139  err_free_gpio:
 140         gpio_free(dev->id);
 141  err_free_device:
 142         input_free_device(input_dev);
 143 
 144         return err;
 145 }
 146 
 147 static int ixp4xx_spkr_remove(struct platform_device *dev)
 148 {
 149         struct input_dev *input_dev = platform_get_drvdata(dev);
 150         unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
 151 
 152         input_unregister_device(input_dev);
 153 
 154         /* turn the speaker off */
 155         disable_irq(ixp4xx_timer2_irq);
 156         ixp4xx_spkr_control(pin, 0);
 157 
 158         free_irq(ixp4xx_timer2_irq, (void *)dev->id);
 159         gpio_free(dev->id);
 160 
 161         return 0;
 162 }
 163 
 164 static void ixp4xx_spkr_shutdown(struct platform_device *dev)
 165 {
 166         struct input_dev *input_dev = platform_get_drvdata(dev);
 167         unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
 168 
 169         /* turn off the speaker */
 170         disable_irq(ixp4xx_timer2_irq);
 171         ixp4xx_spkr_control(pin, 0);
 172 }
 173 
 174 static struct platform_driver ixp4xx_spkr_platform_driver = {
 175         .driver         = {
 176                 .name   = "ixp4xx-beeper",
 177         },
 178         .probe          = ixp4xx_spkr_probe,
 179         .remove         = ixp4xx_spkr_remove,
 180         .shutdown       = ixp4xx_spkr_shutdown,
 181 };
 182 module_platform_driver(ixp4xx_spkr_platform_driver);
 183 

/* [<][>][^][v][top][bottom][index][help] */