Linux Audio

Check our new training course

Loading...
v3.1
  1/*
  2 * Driver for the enhanced rotary controller on pxa930 and pxa935
  3 *
  4 * This program is free software; you can redistribute it and/or modify
  5 * it under the terms of the GNU General Public License version 2 as
  6 * published by the Free Software Foundation.
  7 */
  8
  9#include <linux/kernel.h>
 10#include <linux/module.h>
 11#include <linux/init.h>
 12#include <linux/interrupt.h>
 13#include <linux/input.h>
 14#include <linux/platform_device.h>
 15#include <linux/io.h>
 16#include <linux/slab.h>
 17
 18#include <mach/pxa930_rotary.h>
 19
 20#define SBCR	(0x04)
 21#define ERCR	(0x0c)
 22
 23#define SBCR_ERSB	(1 << 5)
 24
 25struct pxa930_rotary {
 26	struct input_dev	*input_dev;
 27	void __iomem		*mmio_base;
 28	int			last_ercr;
 29
 30	struct pxa930_rotary_platform_data *pdata;
 31};
 32
 33static void clear_sbcr(struct pxa930_rotary *r)
 34{
 35	uint32_t sbcr = __raw_readl(r->mmio_base + SBCR);
 36
 37	__raw_writel(sbcr | SBCR_ERSB, r->mmio_base + SBCR);
 38	__raw_writel(sbcr & ~SBCR_ERSB, r->mmio_base + SBCR);
 39}
 40
 41static irqreturn_t rotary_irq(int irq, void *dev_id)
 42{
 43	struct pxa930_rotary *r = dev_id;
 44	struct pxa930_rotary_platform_data *pdata = r->pdata;
 45	int ercr, delta, key;
 46
 47	ercr = __raw_readl(r->mmio_base + ERCR) & 0xf;
 48	clear_sbcr(r);
 49
 50	delta = ercr - r->last_ercr;
 51	if (delta == 0)
 52		return IRQ_HANDLED;
 53
 54	r->last_ercr = ercr;
 55
 56	if (pdata->up_key && pdata->down_key) {
 57		key = (delta > 0) ? pdata->up_key : pdata->down_key;
 58		input_report_key(r->input_dev, key, 1);
 59		input_sync(r->input_dev);
 60		input_report_key(r->input_dev, key, 0);
 61	} else
 62		input_report_rel(r->input_dev, pdata->rel_code, delta);
 63
 64	input_sync(r->input_dev);
 65
 66	return IRQ_HANDLED;
 67}
 68
 69static int pxa930_rotary_open(struct input_dev *dev)
 70{
 71	struct pxa930_rotary *r = input_get_drvdata(dev);
 72
 73	clear_sbcr(r);
 74
 75	return 0;
 76}
 77
 78static void pxa930_rotary_close(struct input_dev *dev)
 79{
 80	struct pxa930_rotary *r = input_get_drvdata(dev);
 81
 82	clear_sbcr(r);
 83}
 84
 85static int __devinit pxa930_rotary_probe(struct platform_device *pdev)
 86{
 87	struct pxa930_rotary_platform_data *pdata = pdev->dev.platform_data;
 88	struct pxa930_rotary *r;
 89	struct input_dev *input_dev;
 90	struct resource *res;
 91	int irq;
 92	int err;
 93
 94	irq = platform_get_irq(pdev, 0);
 95	if (irq < 0) {
 96		dev_err(&pdev->dev, "no irq for rotary controller\n");
 97		return -ENXIO;
 98	}
 99
100	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
101	if (!res) {
102		dev_err(&pdev->dev, "no I/O memory defined\n");
103		return -ENXIO;
104	}
105
106	if (!pdata) {
107		dev_err(&pdev->dev, "no platform data defined\n");
108		return -EINVAL;
109	}
110
111	r = kzalloc(sizeof(struct pxa930_rotary), GFP_KERNEL);
112	if (!r)
113		return -ENOMEM;
114
115	r->mmio_base = ioremap_nocache(res->start, resource_size(res));
116	if (r->mmio_base == NULL) {
117		dev_err(&pdev->dev, "failed to remap IO memory\n");
118		err = -ENXIO;
119		goto failed_free;
120	}
121
122	r->pdata = pdata;
123	platform_set_drvdata(pdev, r);
124
125	/* allocate and register the input device */
126	input_dev = input_allocate_device();
127	if (!input_dev) {
128		dev_err(&pdev->dev, "failed to allocate input device\n");
129		err = -ENOMEM;
130		goto failed_free_io;
131	}
132
133	input_dev->name = pdev->name;
134	input_dev->id.bustype = BUS_HOST;
135	input_dev->open = pxa930_rotary_open;
136	input_dev->close = pxa930_rotary_close;
137	input_dev->dev.parent = &pdev->dev;
138
139	if (pdata->up_key && pdata->down_key) {
140		__set_bit(pdata->up_key, input_dev->keybit);
141		__set_bit(pdata->down_key, input_dev->keybit);
142		__set_bit(EV_KEY, input_dev->evbit);
143	} else {
144		__set_bit(pdata->rel_code, input_dev->relbit);
145		__set_bit(EV_REL, input_dev->evbit);
146	}
147
148	r->input_dev = input_dev;
149	input_set_drvdata(input_dev, r);
150
151	err = request_irq(irq, rotary_irq, IRQF_DISABLED,
152			"enhanced rotary", r);
153	if (err) {
154		dev_err(&pdev->dev, "failed to request IRQ\n");
155		goto failed_free_input;
156	}
157
158	err = input_register_device(input_dev);
159	if (err) {
160		dev_err(&pdev->dev, "failed to register input device\n");
161		goto failed_free_irq;
162	}
163
164	return 0;
165
166failed_free_irq:
167	free_irq(irq, r);
168failed_free_input:
169	input_free_device(input_dev);
170failed_free_io:
171	iounmap(r->mmio_base);
172failed_free:
173	kfree(r);
174	return err;
175}
176
177static int __devexit pxa930_rotary_remove(struct platform_device *pdev)
178{
179	struct pxa930_rotary *r = platform_get_drvdata(pdev);
180
181	free_irq(platform_get_irq(pdev, 0), r);
182	input_unregister_device(r->input_dev);
183	iounmap(r->mmio_base);
184	platform_set_drvdata(pdev, NULL);
185	kfree(r);
186
187	return 0;
188}
189
190static struct platform_driver pxa930_rotary_driver = {
191	.driver		= {
192		.name	= "pxa930-rotary",
193		.owner	= THIS_MODULE,
194	},
195	.probe		= pxa930_rotary_probe,
196	.remove		= __devexit_p(pxa930_rotary_remove),
197};
198
199static int __init pxa930_rotary_init(void)
200{
201	return platform_driver_register(&pxa930_rotary_driver);
202}
203module_init(pxa930_rotary_init);
204
205static void __exit pxa930_rotary_exit(void)
206{
207	platform_driver_unregister(&pxa930_rotary_driver);
208}
209module_exit(pxa930_rotary_exit);
210
211MODULE_LICENSE("GPL");
212MODULE_DESCRIPTION("Driver for PXA93x Enhanced Rotary Controller");
213MODULE_AUTHOR("Yao Yong <yaoyong@marvell.com>");
v3.5.6
  1/*
  2 * Driver for the enhanced rotary controller on pxa930 and pxa935
  3 *
  4 * This program is free software; you can redistribute it and/or modify
  5 * it under the terms of the GNU General Public License version 2 as
  6 * published by the Free Software Foundation.
  7 */
  8
  9#include <linux/kernel.h>
 10#include <linux/module.h>
 11#include <linux/init.h>
 12#include <linux/interrupt.h>
 13#include <linux/input.h>
 14#include <linux/platform_device.h>
 15#include <linux/io.h>
 16#include <linux/slab.h>
 17
 18#include <mach/pxa930_rotary.h>
 19
 20#define SBCR	(0x04)
 21#define ERCR	(0x0c)
 22
 23#define SBCR_ERSB	(1 << 5)
 24
 25struct pxa930_rotary {
 26	struct input_dev	*input_dev;
 27	void __iomem		*mmio_base;
 28	int			last_ercr;
 29
 30	struct pxa930_rotary_platform_data *pdata;
 31};
 32
 33static void clear_sbcr(struct pxa930_rotary *r)
 34{
 35	uint32_t sbcr = __raw_readl(r->mmio_base + SBCR);
 36
 37	__raw_writel(sbcr | SBCR_ERSB, r->mmio_base + SBCR);
 38	__raw_writel(sbcr & ~SBCR_ERSB, r->mmio_base + SBCR);
 39}
 40
 41static irqreturn_t rotary_irq(int irq, void *dev_id)
 42{
 43	struct pxa930_rotary *r = dev_id;
 44	struct pxa930_rotary_platform_data *pdata = r->pdata;
 45	int ercr, delta, key;
 46
 47	ercr = __raw_readl(r->mmio_base + ERCR) & 0xf;
 48	clear_sbcr(r);
 49
 50	delta = ercr - r->last_ercr;
 51	if (delta == 0)
 52		return IRQ_HANDLED;
 53
 54	r->last_ercr = ercr;
 55
 56	if (pdata->up_key && pdata->down_key) {
 57		key = (delta > 0) ? pdata->up_key : pdata->down_key;
 58		input_report_key(r->input_dev, key, 1);
 59		input_sync(r->input_dev);
 60		input_report_key(r->input_dev, key, 0);
 61	} else
 62		input_report_rel(r->input_dev, pdata->rel_code, delta);
 63
 64	input_sync(r->input_dev);
 65
 66	return IRQ_HANDLED;
 67}
 68
 69static int pxa930_rotary_open(struct input_dev *dev)
 70{
 71	struct pxa930_rotary *r = input_get_drvdata(dev);
 72
 73	clear_sbcr(r);
 74
 75	return 0;
 76}
 77
 78static void pxa930_rotary_close(struct input_dev *dev)
 79{
 80	struct pxa930_rotary *r = input_get_drvdata(dev);
 81
 82	clear_sbcr(r);
 83}
 84
 85static int __devinit pxa930_rotary_probe(struct platform_device *pdev)
 86{
 87	struct pxa930_rotary_platform_data *pdata = pdev->dev.platform_data;
 88	struct pxa930_rotary *r;
 89	struct input_dev *input_dev;
 90	struct resource *res;
 91	int irq;
 92	int err;
 93
 94	irq = platform_get_irq(pdev, 0);
 95	if (irq < 0) {
 96		dev_err(&pdev->dev, "no irq for rotary controller\n");
 97		return -ENXIO;
 98	}
 99
100	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
101	if (!res) {
102		dev_err(&pdev->dev, "no I/O memory defined\n");
103		return -ENXIO;
104	}
105
106	if (!pdata) {
107		dev_err(&pdev->dev, "no platform data defined\n");
108		return -EINVAL;
109	}
110
111	r = kzalloc(sizeof(struct pxa930_rotary), GFP_KERNEL);
112	if (!r)
113		return -ENOMEM;
114
115	r->mmio_base = ioremap_nocache(res->start, resource_size(res));
116	if (r->mmio_base == NULL) {
117		dev_err(&pdev->dev, "failed to remap IO memory\n");
118		err = -ENXIO;
119		goto failed_free;
120	}
121
122	r->pdata = pdata;
123	platform_set_drvdata(pdev, r);
124
125	/* allocate and register the input device */
126	input_dev = input_allocate_device();
127	if (!input_dev) {
128		dev_err(&pdev->dev, "failed to allocate input device\n");
129		err = -ENOMEM;
130		goto failed_free_io;
131	}
132
133	input_dev->name = pdev->name;
134	input_dev->id.bustype = BUS_HOST;
135	input_dev->open = pxa930_rotary_open;
136	input_dev->close = pxa930_rotary_close;
137	input_dev->dev.parent = &pdev->dev;
138
139	if (pdata->up_key && pdata->down_key) {
140		__set_bit(pdata->up_key, input_dev->keybit);
141		__set_bit(pdata->down_key, input_dev->keybit);
142		__set_bit(EV_KEY, input_dev->evbit);
143	} else {
144		__set_bit(pdata->rel_code, input_dev->relbit);
145		__set_bit(EV_REL, input_dev->evbit);
146	}
147
148	r->input_dev = input_dev;
149	input_set_drvdata(input_dev, r);
150
151	err = request_irq(irq, rotary_irq, 0,
152			"enhanced rotary", r);
153	if (err) {
154		dev_err(&pdev->dev, "failed to request IRQ\n");
155		goto failed_free_input;
156	}
157
158	err = input_register_device(input_dev);
159	if (err) {
160		dev_err(&pdev->dev, "failed to register input device\n");
161		goto failed_free_irq;
162	}
163
164	return 0;
165
166failed_free_irq:
167	free_irq(irq, r);
168failed_free_input:
169	input_free_device(input_dev);
170failed_free_io:
171	iounmap(r->mmio_base);
172failed_free:
173	kfree(r);
174	return err;
175}
176
177static int __devexit pxa930_rotary_remove(struct platform_device *pdev)
178{
179	struct pxa930_rotary *r = platform_get_drvdata(pdev);
180
181	free_irq(platform_get_irq(pdev, 0), r);
182	input_unregister_device(r->input_dev);
183	iounmap(r->mmio_base);
184	platform_set_drvdata(pdev, NULL);
185	kfree(r);
186
187	return 0;
188}
189
190static struct platform_driver pxa930_rotary_driver = {
191	.driver		= {
192		.name	= "pxa930-rotary",
193		.owner	= THIS_MODULE,
194	},
195	.probe		= pxa930_rotary_probe,
196	.remove		= __devexit_p(pxa930_rotary_remove),
197};
198module_platform_driver(pxa930_rotary_driver);
 
 
 
 
 
 
 
 
 
 
 
199
200MODULE_LICENSE("GPL");
201MODULE_DESCRIPTION("Driver for PXA93x Enhanced Rotary Controller");
202MODULE_AUTHOR("Yao Yong <yaoyong@marvell.com>");