Version:  2.0.40 2.2.26 2.4.37 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17

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

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us