Linux Audio

Check our new training course

Loading...
v4.6
  1/*
  2 * Generic push-switch framework
  3 *
  4 * Copyright (C) 2006  Paul Mundt
  5 *
  6 * This file is subject to the terms and conditions of the GNU General Public
  7 * License.  See the file "COPYING" in the main directory of this archive
  8 * for more details.
  9 */
 10#include <linux/init.h>
 11#include <linux/slab.h>
 12#include <linux/module.h>
 13#include <linux/interrupt.h>
 14#include <linux/platform_device.h>
 15#include <asm/push-switch.h>
 16
 17#define DRV_NAME "push-switch"
 18#define DRV_VERSION "0.1.1"
 19
 20static ssize_t switch_show(struct device *dev,
 21			   struct device_attribute *attr,
 22			   char *buf)
 23{
 24	struct push_switch_platform_info *psw_info = dev->platform_data;
 25	return sprintf(buf, "%s\n", psw_info->name);
 26}
 27static DEVICE_ATTR(switch, S_IRUGO, switch_show, NULL);
 28
 29static void switch_timer(unsigned long data)
 30{
 31	struct push_switch *psw = (struct push_switch *)data;
 32
 33	schedule_work(&psw->work);
 34}
 35
 36static void switch_work_handler(struct work_struct *work)
 37{
 38	struct push_switch *psw = container_of(work, struct push_switch, work);
 39	struct platform_device *pdev = psw->pdev;
 40
 41	psw->state = 0;
 42
 43	kobject_uevent(&pdev->dev.kobj, KOBJ_CHANGE);
 44}
 45
 46static int switch_drv_probe(struct platform_device *pdev)
 47{
 48	struct push_switch_platform_info *psw_info;
 49	struct push_switch *psw;
 50	int ret, irq;
 51
 52	psw = kzalloc(sizeof(struct push_switch), GFP_KERNEL);
 53	if (unlikely(!psw))
 54		return -ENOMEM;
 55
 56	irq = platform_get_irq(pdev, 0);
 57	if (unlikely(irq < 0)) {
 58		ret = -ENODEV;
 59		goto err;
 60	}
 61
 62	psw_info = pdev->dev.platform_data;
 63	BUG_ON(!psw_info);
 64
 65	ret = request_irq(irq, psw_info->irq_handler,
 66			  psw_info->irq_flags,
 67			  psw_info->name ? psw_info->name : DRV_NAME, pdev);
 68	if (unlikely(ret < 0))
 69		goto err;
 70
 71	if (psw_info->name) {
 72		ret = device_create_file(&pdev->dev, &dev_attr_switch);
 73		if (unlikely(ret)) {
 74			dev_err(&pdev->dev, "Failed creating device attrs\n");
 75			ret = -EINVAL;
 76			goto err_irq;
 77		}
 78	}
 79
 80	INIT_WORK(&psw->work, switch_work_handler);
 81	init_timer(&psw->debounce);
 82
 83	psw->debounce.function = switch_timer;
 84	psw->debounce.data = (unsigned long)psw;
 85
 86	/* Workqueue API brain-damage */
 87	psw->pdev = pdev;
 88
 89	platform_set_drvdata(pdev, psw);
 90
 91	return 0;
 92
 93err_irq:
 94	free_irq(irq, pdev);
 95err:
 96	kfree(psw);
 97	return ret;
 98}
 99
100static int switch_drv_remove(struct platform_device *pdev)
101{
102	struct push_switch *psw = platform_get_drvdata(pdev);
103	struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
104	int irq = platform_get_irq(pdev, 0);
105
106	if (psw_info->name)
107		device_remove_file(&pdev->dev, &dev_attr_switch);
108
109	platform_set_drvdata(pdev, NULL);
110	flush_work(&psw->work);
111	del_timer_sync(&psw->debounce);
112	free_irq(irq, pdev);
113
114	kfree(psw);
115
116	return 0;
117}
118
119static struct platform_driver switch_driver = {
120	.probe		= switch_drv_probe,
121	.remove		= switch_drv_remove,
122	.driver		= {
123		.name	= DRV_NAME,
124	},
125};
126
127static int __init switch_init(void)
128{
129	printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION);
130	return platform_driver_register(&switch_driver);
131}
132
133static void __exit switch_exit(void)
134{
135	platform_driver_unregister(&switch_driver);
136}
137module_init(switch_init);
138module_exit(switch_exit);
139
140MODULE_VERSION(DRV_VERSION);
141MODULE_AUTHOR("Paul Mundt");
142MODULE_LICENSE("GPL v2");
v3.15
  1/*
  2 * Generic push-switch framework
  3 *
  4 * Copyright (C) 2006  Paul Mundt
  5 *
  6 * This file is subject to the terms and conditions of the GNU General Public
  7 * License.  See the file "COPYING" in the main directory of this archive
  8 * for more details.
  9 */
 10#include <linux/init.h>
 11#include <linux/slab.h>
 12#include <linux/module.h>
 13#include <linux/interrupt.h>
 14#include <linux/platform_device.h>
 15#include <asm/push-switch.h>
 16
 17#define DRV_NAME "push-switch"
 18#define DRV_VERSION "0.1.1"
 19
 20static ssize_t switch_show(struct device *dev,
 21			   struct device_attribute *attr,
 22			   char *buf)
 23{
 24	struct push_switch_platform_info *psw_info = dev->platform_data;
 25	return sprintf(buf, "%s\n", psw_info->name);
 26}
 27static DEVICE_ATTR(switch, S_IRUGO, switch_show, NULL);
 28
 29static void switch_timer(unsigned long data)
 30{
 31	struct push_switch *psw = (struct push_switch *)data;
 32
 33	schedule_work(&psw->work);
 34}
 35
 36static void switch_work_handler(struct work_struct *work)
 37{
 38	struct push_switch *psw = container_of(work, struct push_switch, work);
 39	struct platform_device *pdev = psw->pdev;
 40
 41	psw->state = 0;
 42
 43	kobject_uevent(&pdev->dev.kobj, KOBJ_CHANGE);
 44}
 45
 46static int switch_drv_probe(struct platform_device *pdev)
 47{
 48	struct push_switch_platform_info *psw_info;
 49	struct push_switch *psw;
 50	int ret, irq;
 51
 52	psw = kzalloc(sizeof(struct push_switch), GFP_KERNEL);
 53	if (unlikely(!psw))
 54		return -ENOMEM;
 55
 56	irq = platform_get_irq(pdev, 0);
 57	if (unlikely(irq < 0)) {
 58		ret = -ENODEV;
 59		goto err;
 60	}
 61
 62	psw_info = pdev->dev.platform_data;
 63	BUG_ON(!psw_info);
 64
 65	ret = request_irq(irq, psw_info->irq_handler,
 66			  psw_info->irq_flags,
 67			  psw_info->name ? psw_info->name : DRV_NAME, pdev);
 68	if (unlikely(ret < 0))
 69		goto err;
 70
 71	if (psw_info->name) {
 72		ret = device_create_file(&pdev->dev, &dev_attr_switch);
 73		if (unlikely(ret)) {
 74			dev_err(&pdev->dev, "Failed creating device attrs\n");
 75			ret = -EINVAL;
 76			goto err_irq;
 77		}
 78	}
 79
 80	INIT_WORK(&psw->work, switch_work_handler);
 81	init_timer(&psw->debounce);
 82
 83	psw->debounce.function = switch_timer;
 84	psw->debounce.data = (unsigned long)psw;
 85
 86	/* Workqueue API brain-damage */
 87	psw->pdev = pdev;
 88
 89	platform_set_drvdata(pdev, psw);
 90
 91	return 0;
 92
 93err_irq:
 94	free_irq(irq, pdev);
 95err:
 96	kfree(psw);
 97	return ret;
 98}
 99
100static int switch_drv_remove(struct platform_device *pdev)
101{
102	struct push_switch *psw = platform_get_drvdata(pdev);
103	struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
104	int irq = platform_get_irq(pdev, 0);
105
106	if (psw_info->name)
107		device_remove_file(&pdev->dev, &dev_attr_switch);
108
109	platform_set_drvdata(pdev, NULL);
110	flush_work(&psw->work);
111	del_timer_sync(&psw->debounce);
112	free_irq(irq, pdev);
113
114	kfree(psw);
115
116	return 0;
117}
118
119static struct platform_driver switch_driver = {
120	.probe		= switch_drv_probe,
121	.remove		= switch_drv_remove,
122	.driver		= {
123		.name	= DRV_NAME,
124	},
125};
126
127static int __init switch_init(void)
128{
129	printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION);
130	return platform_driver_register(&switch_driver);
131}
132
133static void __exit switch_exit(void)
134{
135	platform_driver_unregister(&switch_driver);
136}
137module_init(switch_init);
138module_exit(switch_exit);
139
140MODULE_VERSION(DRV_VERSION);
141MODULE_AUTHOR("Paul Mundt");
142MODULE_LICENSE("GPL v2");