* Re: Requestirq() = freeze for touchscreendriver
2008-02-07 1:06 Requestirq() = freeze for touchscreendriver Kristoffer Ericson
2008-02-07 2:38 ` Paul Mundt
@ 2008-02-07 13:24 ` Kristoffer Ericson
2008-02-08 2:57 ` Magnus Damm
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Kristoffer Ericson @ 2008-02-07 13:24 UTC (permalink / raw)
To: linux-sh
[-- Attachment #1: Type: text/plain, Size: 11912 bytes --]
Greetings,
These patches are against vanilla 2.6.24, but should apply cleanly to linux-2.6 also. hp6xx_ts_input.patch creates platform_driver for the touchscreen, not much is kept from the old.
The booting comes to "waiting to aquire IRQ" and then freezes. So it happens in one of these lines :
printk(KERN_INFO "ts: waiting to request IRQ\n");
error = request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
IRQF_DISABLED, "HP6XX Touchscreen Driver", pdev);
if (error) {
printk(KERN_INFO "hp680_touchscreen.c: Unable to aquire irq %d\n", HP680_TS_IRQ);
goto fail2;
}
error = input_register_device(jornada_ts->dev);
if (error)
goto fail1;
printk(KERN_INFO "ts: passed probing successfully\n");
return 0;
diff --git a/arch/sh/boards/hp6xx/setup.c b/arch/sh/boards/hp6xx/setup.c
index 2f414ac..7b5b273 100644
--- a/arch/sh/boards/hp6xx/setup.c
+++ b/arch/sh/boards/hp6xx/setup.c
@@ -12,7 +12,7 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <asm/hd64461.h>
+#include <asm/hd6446x.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hp6xx.h>
@@ -21,7 +21,7 @@
#define SCPCR 0xa4000116
#define SCPDR 0xa4000136
-/* CF Slot */
+/* CF slot configured as storage */
static struct resource cf_ide_resources[] = {
[0] = {
.start = 0x15000000 + 0x1f0,
@@ -51,9 +51,21 @@ static struct platform_device jornadakbd_device = {
.id = -1,
};
+static struct platform_device hp6xxled_device = {
+ .name = "hp6xx-led",
+ .id = -1,
+};
+
+static struct platform_device jornadats_device = {
+ .name = "jornada_ts",
+ .id = -1,
+};
+
static struct platform_device *hp6xx_devices[] __initdata = {
&cf_ide_device,
&jornadakbd_device,
+ &jornadats_device,
+ &hp6xxled_device,
};
static void __init hp6xx_init_irq(void)
@@ -72,24 +84,26 @@ static void __init hp6xx_setup(char **cmdline_p)
u8 v8;
u16 v;
- v = inw(HD64461_STBCR);
- v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
- HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
- HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST |
- HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST|
- HD64461_STBCR_SAFECKE_IST;
+ v = inw(HD6446x_STBCR);
+ v |= HD6446x_STBCR_URT | HD6446x_STBCR_IRDA |
+ HD6446x_STBCR_TMU1 | HD6446x_STBCR_TMU0 |
+ HD6446x_STBCR_AFE | HD6446x_STBCR_PCC0 |
+ HD6446x_STBCR_PP | HD6446x_STBCR_SAFECKE_OST|
+ HD6446x_STBCR_ADC;
#ifndef CONFIG_HD64461_ENABLER
- v |= HD64461_STBCR_SPC1ST;
+ v |= HD6446x_STBCR_PCC1;
#endif
- outw(v, HD64461_STBCR);
- v = inw(HD64461_GPADR);
+ outw(v, HD6446x_STBCR);
+ v = inw(HD6446x_GPADR);
v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0;
- outw(v, HD64461_GPADR);
+ outw(v, HD6446x_GPADR);
- outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC0GCR);
+ /* set voltage control pin to high level (PCC0SEL)*/
+ outw(HD6446x_PCCGCR_VCC0 | HD6446x_PCCSCR_VCC1, HD6446x_PCC0GCR);
#ifndef CONFIG_HD64461_ENABLER
- outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC1GCR);
+ /* set voltage control pin to high level (PCC1SEL)*/
+ outw(HD6446x_PCCGCR_VCC0 | HD6446x_PCCSCR_VCC1, HD6446x_PCC1GCR);
#endif
sh_dac_output(0, DAC_SPEAKER_VOLUME);
@@ -107,15 +121,31 @@ static void __init hp6xx_setup(char **cmdline_p)
v &= ~SCPCR_TS_MASK;
v |= SCPCR_TS_ENABLE;
ctrl_outw(v, SCPCR);
+
}
device_initcall(hp6xx_devices_setup);
+static void __iomem *port_map(unsigned long port, unsigned int size)
+{
+ /* this is for all drivers actually accepting io_offset */
+ if (0xf300<=port && port<=0xf31f)
+ port = port - 0xf000;
+
+ /* non-port? then just return it */
+ if (PXSEG(port))
+ return (void __iomem *)(port);
+
+ /* add base value and return it */
+ return (void __iomem *)(0xba000000 + port);
+}
+
static struct sh_machine_vector mv_hp6xx __initmv = {
- .mv_name = "hp6xx",
+ .mv_name = "HP Jornada 6xx",
.mv_setup = hp6xx_setup,
/* IRQ's : CPU(64) + CCHIP(16) + FREE_TO_USE(6) */
- .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM + 6,
- .mv_irq_demux = hd64461_irq_demux,
+ .mv_nr_irqs = HD6446x_IRQBASE + HD6446x_IRQ_NUM + 6,
+ .mv_irq_demux = hd6446x_irq_demux,
/* Enable IRQ0 -> IRQ3 in IRQ_MODE */
.mv_init_irq = hp6xx_init_irq,
+ .mv_ioport_map = port_map,
};
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
index c38d4e0..b658746 100644
--- a/drivers/input/touchscreen/hp680_ts_input.c
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -1,7 +1,12 @@
+
+
+
+
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/adc.h>
@@ -17,113 +22,152 @@
#define PHDR 0xa400012e
#define SCPDR 0xa4000136
-static void do_softint(struct work_struct *work);
-
-static struct input_dev *hp680_ts_dev;
-static DECLARE_DELAYED_WORK(work, do_softint);
+struct jornada_ts {
+ struct input_dev *dev;
+ int x, y;
+};
-static void do_softint(struct work_struct *work)
-{
- int absx = 0, absy = 0;
- u8 scpdr;
+static irqreturn_t hp680_ts_interrupt(int irq, void *dev_id)
+{
+ struct platform_device *pdev = dev_id;
+ struct jornada_ts *jornada_ts = platform_get_drvdata(pdev);
int touched = 0;
+ u8 scpdr;
- if (ctrl_inb(PHDR) & PHDR_TS_PEN_DOWN) {
- scpdr = ctrl_inb(SCPDR);
+ disable_irq(irq);
+ if (inb(PHDR) & PHDR_TS_PEN_DOWN) {
+ scpdr = inb(SCPDR);
scpdr |= SCPDR_TS_SCAN_ENABLE;
scpdr &= ~SCPDR_TS_SCAN_Y;
- ctrl_outb(scpdr, SCPDR);
+ outb(scpdr, SCPDR);
udelay(30);
- absy = adc_single(ADC_CHANNEL_TS_Y);
+ jornada_ts->y = adc_single(ADC_CHANNEL_TS_Y);
- scpdr = ctrl_inb(SCPDR);
+ scpdr = inb(SCPDR);
scpdr |= SCPDR_TS_SCAN_Y;
scpdr &= ~SCPDR_TS_SCAN_X;
- ctrl_outb(scpdr, SCPDR);
+ outb(scpdr, SCPDR);
udelay(30);
- absx = adc_single(ADC_CHANNEL_TS_X);
+ jornada_ts->x = adc_single(ADC_CHANNEL_TS_X);
- scpdr = ctrl_inb(SCPDR);
+ scpdr = inb(SCPDR);
scpdr |= SCPDR_TS_SCAN_X;
scpdr &= ~SCPDR_TS_SCAN_ENABLE;
- ctrl_outb(scpdr, SCPDR);
+ outb(scpdr, SCPDR);
udelay(100);
- touched = ctrl_inb(PHDR) & PHDR_TS_PEN_DOWN;
+ touched = inb(PHDR) & PHDR_TS_PEN_DOWN;
}
if (touched) {
- input_report_key(hp680_ts_dev, BTN_TOUCH, 1);
- input_report_abs(hp680_ts_dev, ABS_X, absx);
- input_report_abs(hp680_ts_dev, ABS_Y, absy);
+ input_report_key(jornada_ts->dev, BTN_TOUCH, 1);
+ input_report_abs(jornada_ts->dev, ABS_X, jornada_ts->x);
+ input_report_abs(jornada_ts->dev, ABS_Y, jornada_ts->y);
} else {
- input_report_key(hp680_ts_dev, BTN_TOUCH, 0);
+ input_report_key(jornada_ts->dev, BTN_TOUCH, 0);
}
- input_sync(hp680_ts_dev);
- enable_irq(HP680_TS_IRQ);
-}
-
-static irqreturn_t hp680_ts_interrupt(int irq, void *dev)
-{
- disable_irq_nosync(irq);
- schedule_delayed_work(&work, HZ / 20);
+ input_sync(jornada_ts->dev);
+ enable_irq(irq);
return IRQ_HANDLED;
}
-static int __init hp680_ts_init(void)
+static int __init jornada680_ts_probe(struct platform_device *pdev)
{
- int err;
+ struct jornada_ts *jornada_ts;
+ struct input_dev *input_dev;
+ int error;
+
+ jornada_ts = kzalloc(sizeof(struct jornada_ts), GFP_KERNEL);
+ if (!jornada_ts) {
+ printk(KERN_INFO "ts :failed to aquire memory\n");
+ return -ENOMEM;
+ }
- hp680_ts_dev = input_allocate_device();
- if (!hp680_ts_dev)
- return -ENOMEM;
+ input_dev = input_allocate_device();
+
+ if (!input_dev) {
+ printk(KERN_INFO "failed to aquire device\n");
+ error = ENODEV;
+ goto fail3;
+ }
- hp680_ts_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
- hp680_ts_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ platform_set_drvdata(pdev, jornada_ts);
+ printk(KERN_INFO "ts: driver + memory allocated\n");
+
+ jornada_ts->dev = input_dev;
+
+ input_dev->name = "HP Jornada 6XX Touchscreen";
+ input_dev->phys = "jornadats/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->dev.parent = &pdev->dev;
+ input_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
+ set_bit(BTN_TOUCH, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_X, 40, 950, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 80, 910, 0, 0);
+
+ printk(KERN_INFO "ts: waiting to request IRQ\n");
+ error = request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
+ IRQF_DISABLED, "HP6XX Touchscreen Driver", pdev);
+
+ if (error) {
+ printk(KERN_INFO "hp680_touchscreen.c: Unable to aquire irq %d\n", HP680_TS_IRQ);
+ goto fail2;
+ }
- input_set_abs_params(hp680_ts_dev, ABS_X,
- HP680_TS_ABS_X_MIN, HP680_TS_ABS_X_MAX, 0, 0);
- input_set_abs_params(hp680_ts_dev, ABS_Y,
- HP680_TS_ABS_Y_MIN, HP680_TS_ABS_Y_MAX, 0, 0);
+ error = input_register_device(jornada_ts->dev);
+ if (error)
+ goto fail1;
- hp680_ts_dev->name = "HP Jornada touchscreen";
- hp680_ts_dev->phys = "hp680_ts/input0";
+ printk(KERN_INFO "ts: passed probing successfully\n");
+ return 0;
- if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
- IRQF_DISABLED, MODNAME, 0) < 0) {
- printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n",
- HP680_TS_IRQ);
- err = -EBUSY;
- goto fail1;
- }
+fail1:
+ free_irq(HP680_TS_IRQ, pdev);
+fail2:
+ platform_set_drvdata(pdev, NULL);
+ input_free_device(input_dev);
+fail3:
+ kfree(jornada_ts);
+ return error;
+}
- err = input_register_device(hp680_ts_dev);
- if (err)
- goto fail2;
+static int __devexit jornada680_ts_remove(struct platform_device *pdev)
+{
+ struct jornada_ts *jornada_ts = platform_get_drvdata(pdev);
+ free_irq(HP680_TS_IRQ, pdev);
+ platform_set_drvdata(pdev, NULL);
+ input_unregister_device(jornada_ts->dev);
+ kfree(jornada_ts);
+
return 0;
+}
+
+static struct platform_driver jornada680_ts_driver = {
+ .probe = jornada680_ts_probe,
+ .remove = jornada680_ts_remove,
+ .driver = {
+ "jornada_ts",
+ }
+};
- fail2: free_irq(HP680_TS_IRQ, NULL);
- cancel_delayed_work(&work);
- flush_scheduled_work();
- fail1: input_free_device(hp680_ts_dev);
- return err;
+static int __devinit hp680_ts_init(void)
+{
+ return platform_driver_register(&jornada680_ts_driver);
}
static void __exit hp680_ts_exit(void)
{
- free_irq(HP680_TS_IRQ, NULL);
- cancel_delayed_work(&work);
- flush_scheduled_work();
- input_unregister_device(hp680_ts_dev);
+ platform_driver_unregister(&jornada680_ts_driver);
}
-
module_init(hp680_ts_init);
module_exit(hp680_ts_exit);
-MODULE_AUTHOR("Andriy Skulysh, askulysh@image.kiev.ua");
-MODULE_DESCRIPTION("HP Jornada 680 touchscreen driver");
+MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>");
+/* Based on original device driver by Andriy Skulysh, askulysh@image.kiev.ua */
+MODULE_DESCRIPTION("HP Jornada 620/660/680/690 touchscreen platform driver");
MODULE_LICENSE("GPL");
On Thu, 7 Feb 2008 11:38:14 +0900
Paul Mundt <lethal@linux-sh.org> wrote:
> On Thu, Feb 07, 2008 at 02:06:00AM +0100, Kristoffer Ericson wrote:
> > Been bugtracking touchscreen driver, seems like it gets stuck on IRQ request. irq = 35 in this case. Im still
> > bad at recalculating but vect 0x660 = 35?
> >
> The math for calculating this can be found in the headers. Write a test
> app to convert for you if you aren't sure.
>
> > static void __init hp6xx_init_irq(void)
> > {
> > /* Gets touchscreen and powerbutton IRQ working */
> > plat_irq_setup_pins(IRQ_MODE_IRQ);
> > }
> >
> > static int __init hp6xx_devices_setup(void)
> > {
> > return platform_add_devices(hp6xx_devices, ARRAY_SIZE(hp6xx_devices));
> > }
> >
> > I got two other likely candidates :
> > 1) the new base io_map I added (strange that nothing else fails though)
> > 2) plat_irq_setup MUST be finished before hp6xx_devices_setup starts, otherwise
> > I suspect the IRQ3 would never reach IRQ_MODE.
> >
> Unfortunately you've not posted enough context to figure out the
> initialization sequence. Please post your patch (and as a patch, not an
> inlined file) if you want feedback.
[-- Attachment #2: hp6xx_setup.patch --]
[-- Type: application/octet-stream, Size: 3508 bytes --]
diff --git a/arch/sh/boards/hp6xx/setup.c b/arch/sh/boards/hp6xx/setup.c
index 2f414ac..7b5b273 100644
--- a/arch/sh/boards/hp6xx/setup.c
+++ b/arch/sh/boards/hp6xx/setup.c
@@ -12,7 +12,7 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <asm/hd64461.h>
+#include <asm/hd6446x.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hp6xx.h>
@@ -21,7 +21,7 @@
#define SCPCR 0xa4000116
#define SCPDR 0xa4000136
-/* CF Slot */
+/* CF slot configured as storage */
static struct resource cf_ide_resources[] = {
[0] = {
.start = 0x15000000 + 0x1f0,
@@ -51,9 +51,21 @@ static struct platform_device jornadakbd_device = {
.id = -1,
};
+static struct platform_device hp6xxled_device = {
+ .name = "hp6xx-led",
+ .id = -1,
+};
+
+static struct platform_device jornadats_device = {
+ .name = "jornada_ts",
+ .id = -1,
+};
+
static struct platform_device *hp6xx_devices[] __initdata = {
&cf_ide_device,
&jornadakbd_device,
+ &jornadats_device,
+ &hp6xxled_device,
};
static void __init hp6xx_init_irq(void)
@@ -72,24 +84,26 @@ static void __init hp6xx_setup(char **cmdline_p)
u8 v8;
u16 v;
- v = inw(HD64461_STBCR);
- v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
- HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
- HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST |
- HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST|
- HD64461_STBCR_SAFECKE_IST;
+ v = inw(HD6446x_STBCR);
+ v |= HD6446x_STBCR_URT | HD6446x_STBCR_IRDA |
+ HD6446x_STBCR_TMU1 | HD6446x_STBCR_TMU0 |
+ HD6446x_STBCR_AFE | HD6446x_STBCR_PCC0 |
+ HD6446x_STBCR_PP | HD6446x_STBCR_SAFECKE_OST|
+ HD6446x_STBCR_ADC;
#ifndef CONFIG_HD64461_ENABLER
- v |= HD64461_STBCR_SPC1ST;
+ v |= HD6446x_STBCR_PCC1;
#endif
- outw(v, HD64461_STBCR);
- v = inw(HD64461_GPADR);
+ outw(v, HD6446x_STBCR);
+ v = inw(HD6446x_GPADR);
v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0;
- outw(v, HD64461_GPADR);
+ outw(v, HD6446x_GPADR);
- outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC0GCR);
+ /* set voltage control pin to high level (PCC0SEL)*/
+ outw(HD6446x_PCCGCR_VCC0 | HD6446x_PCCSCR_VCC1, HD6446x_PCC0GCR);
#ifndef CONFIG_HD64461_ENABLER
- outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC1GCR);
+ /* set voltage control pin to high level (PCC1SEL)*/
+ outw(HD6446x_PCCGCR_VCC0 | HD6446x_PCCSCR_VCC1, HD6446x_PCC1GCR);
#endif
sh_dac_output(0, DAC_SPEAKER_VOLUME);
@@ -107,15 +121,31 @@ static void __init hp6xx_setup(char **cmdline_p)
v &= ~SCPCR_TS_MASK;
v |= SCPCR_TS_ENABLE;
ctrl_outw(v, SCPCR);
+
}
device_initcall(hp6xx_devices_setup);
+static void __iomem *port_map(unsigned long port, unsigned int size)
+{
+ /* this is for all drivers actually accepting io_offset */
+ if (0xf300<=port && port<=0xf31f)
+ port = port - 0xf000;
+
+ /* non-port? then just return it */
+ if (PXSEG(port))
+ return (void __iomem *)(port);
+
+ /* add base value and return it */
+ return (void __iomem *)(0xba000000 + port);
+}
+
static struct sh_machine_vector mv_hp6xx __initmv = {
- .mv_name = "hp6xx",
+ .mv_name = "HP Jornada 6xx",
.mv_setup = hp6xx_setup,
/* IRQ's : CPU(64) + CCHIP(16) + FREE_TO_USE(6) */
- .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM + 6,
- .mv_irq_demux = hd64461_irq_demux,
+ .mv_nr_irqs = HD6446x_IRQBASE + HD6446x_IRQ_NUM + 6,
+ .mv_irq_demux = hd6446x_irq_demux,
/* Enable IRQ0 -> IRQ3 in IRQ_MODE */
.mv_init_irq = hp6xx_init_irq,
+ .mv_ioport_map = port_map,
};
[-- Attachment #3: hp6xx_ts_input.patch --]
[-- Type: application/octet-stream, Size: 6501 bytes --]
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
index c38d4e0..b658746 100644
--- a/drivers/input/touchscreen/hp680_ts_input.c
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -1,7 +1,12 @@
+
+
+
+
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/adc.h>
@@ -17,113 +22,152 @@
#define PHDR 0xa400012e
#define SCPDR 0xa4000136
-static void do_softint(struct work_struct *work);
-
-static struct input_dev *hp680_ts_dev;
-static DECLARE_DELAYED_WORK(work, do_softint);
+struct jornada_ts {
+ struct input_dev *dev;
+ int x, y;
+};
-static void do_softint(struct work_struct *work)
-{
- int absx = 0, absy = 0;
- u8 scpdr;
+static irqreturn_t hp680_ts_interrupt(int irq, void *dev_id)
+{
+ struct platform_device *pdev = dev_id;
+ struct jornada_ts *jornada_ts = platform_get_drvdata(pdev);
int touched = 0;
+ u8 scpdr;
- if (ctrl_inb(PHDR) & PHDR_TS_PEN_DOWN) {
- scpdr = ctrl_inb(SCPDR);
+ disable_irq(irq);
+ if (inb(PHDR) & PHDR_TS_PEN_DOWN) {
+ scpdr = inb(SCPDR);
scpdr |= SCPDR_TS_SCAN_ENABLE;
scpdr &= ~SCPDR_TS_SCAN_Y;
- ctrl_outb(scpdr, SCPDR);
+ outb(scpdr, SCPDR);
udelay(30);
- absy = adc_single(ADC_CHANNEL_TS_Y);
+ jornada_ts->y = adc_single(ADC_CHANNEL_TS_Y);
- scpdr = ctrl_inb(SCPDR);
+ scpdr = inb(SCPDR);
scpdr |= SCPDR_TS_SCAN_Y;
scpdr &= ~SCPDR_TS_SCAN_X;
- ctrl_outb(scpdr, SCPDR);
+ outb(scpdr, SCPDR);
udelay(30);
- absx = adc_single(ADC_CHANNEL_TS_X);
+ jornada_ts->x = adc_single(ADC_CHANNEL_TS_X);
- scpdr = ctrl_inb(SCPDR);
+ scpdr = inb(SCPDR);
scpdr |= SCPDR_TS_SCAN_X;
scpdr &= ~SCPDR_TS_SCAN_ENABLE;
- ctrl_outb(scpdr, SCPDR);
+ outb(scpdr, SCPDR);
udelay(100);
- touched = ctrl_inb(PHDR) & PHDR_TS_PEN_DOWN;
+ touched = inb(PHDR) & PHDR_TS_PEN_DOWN;
}
if (touched) {
- input_report_key(hp680_ts_dev, BTN_TOUCH, 1);
- input_report_abs(hp680_ts_dev, ABS_X, absx);
- input_report_abs(hp680_ts_dev, ABS_Y, absy);
+ input_report_key(jornada_ts->dev, BTN_TOUCH, 1);
+ input_report_abs(jornada_ts->dev, ABS_X, jornada_ts->x);
+ input_report_abs(jornada_ts->dev, ABS_Y, jornada_ts->y);
} else {
- input_report_key(hp680_ts_dev, BTN_TOUCH, 0);
+ input_report_key(jornada_ts->dev, BTN_TOUCH, 0);
}
- input_sync(hp680_ts_dev);
- enable_irq(HP680_TS_IRQ);
-}
-
-static irqreturn_t hp680_ts_interrupt(int irq, void *dev)
-{
- disable_irq_nosync(irq);
- schedule_delayed_work(&work, HZ / 20);
+ input_sync(jornada_ts->dev);
+ enable_irq(irq);
return IRQ_HANDLED;
}
-static int __init hp680_ts_init(void)
+static int __init jornada680_ts_probe(struct platform_device *pdev)
{
- int err;
+ struct jornada_ts *jornada_ts;
+ struct input_dev *input_dev;
+ int error;
+
+ jornada_ts = kzalloc(sizeof(struct jornada_ts), GFP_KERNEL);
+ if (!jornada_ts) {
+ printk(KERN_INFO "ts :failed to aquire memory\n");
+ return -ENOMEM;
+ }
- hp680_ts_dev = input_allocate_device();
- if (!hp680_ts_dev)
- return -ENOMEM;
+ input_dev = input_allocate_device();
+
+ if (!input_dev) {
+ printk(KERN_INFO "failed to aquire device\n");
+ error = ENODEV;
+ goto fail3;
+ }
- hp680_ts_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
- hp680_ts_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ platform_set_drvdata(pdev, jornada_ts);
+ printk(KERN_INFO "ts: driver + memory allocated\n");
+
+ jornada_ts->dev = input_dev;
+
+ input_dev->name = "HP Jornada 6XX Touchscreen";
+ input_dev->phys = "jornadats/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->dev.parent = &pdev->dev;
+ input_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
+ set_bit(BTN_TOUCH, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_X, 40, 950, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 80, 910, 0, 0);
+
+ printk(KERN_INFO "ts: waiting to request IRQ\n");
+ error = request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
+ IRQF_DISABLED, "HP6XX Touchscreen Driver", pdev);
+
+ if (error) {
+ printk(KERN_INFO "hp680_touchscreen.c: Unable to aquire irq %d\n", HP680_TS_IRQ);
+ goto fail2;
+ }
- input_set_abs_params(hp680_ts_dev, ABS_X,
- HP680_TS_ABS_X_MIN, HP680_TS_ABS_X_MAX, 0, 0);
- input_set_abs_params(hp680_ts_dev, ABS_Y,
- HP680_TS_ABS_Y_MIN, HP680_TS_ABS_Y_MAX, 0, 0);
+ error = input_register_device(jornada_ts->dev);
+ if (error)
+ goto fail1;
- hp680_ts_dev->name = "HP Jornada touchscreen";
- hp680_ts_dev->phys = "hp680_ts/input0";
+ printk(KERN_INFO "ts: passed probing successfully\n");
+ return 0;
- if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
- IRQF_DISABLED, MODNAME, 0) < 0) {
- printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n",
- HP680_TS_IRQ);
- err = -EBUSY;
- goto fail1;
- }
+fail1:
+ free_irq(HP680_TS_IRQ, pdev);
+fail2:
+ platform_set_drvdata(pdev, NULL);
+ input_free_device(input_dev);
+fail3:
+ kfree(jornada_ts);
+ return error;
+}
- err = input_register_device(hp680_ts_dev);
- if (err)
- goto fail2;
+static int __devexit jornada680_ts_remove(struct platform_device *pdev)
+{
+ struct jornada_ts *jornada_ts = platform_get_drvdata(pdev);
+ free_irq(HP680_TS_IRQ, pdev);
+ platform_set_drvdata(pdev, NULL);
+ input_unregister_device(jornada_ts->dev);
+ kfree(jornada_ts);
+
return 0;
+}
+
+static struct platform_driver jornada680_ts_driver = {
+ .probe = jornada680_ts_probe,
+ .remove = jornada680_ts_remove,
+ .driver = {
+ "jornada_ts",
+ }
+};
- fail2: free_irq(HP680_TS_IRQ, NULL);
- cancel_delayed_work(&work);
- flush_scheduled_work();
- fail1: input_free_device(hp680_ts_dev);
- return err;
+static int __devinit hp680_ts_init(void)
+{
+ return platform_driver_register(&jornada680_ts_driver);
}
static void __exit hp680_ts_exit(void)
{
- free_irq(HP680_TS_IRQ, NULL);
- cancel_delayed_work(&work);
- flush_scheduled_work();
- input_unregister_device(hp680_ts_dev);
+ platform_driver_unregister(&jornada680_ts_driver);
}
-
module_init(hp680_ts_init);
module_exit(hp680_ts_exit);
-MODULE_AUTHOR("Andriy Skulysh, askulysh@image.kiev.ua");
-MODULE_DESCRIPTION("HP Jornada 680 touchscreen driver");
+MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>");
+/* Based on original device driver by Andriy Skulysh, askulysh@image.kiev.ua */
+MODULE_DESCRIPTION("HP Jornada 620/660/680/690 touchscreen platform driver");
MODULE_LICENSE("GPL");
^ permalink raw reply related [flat|nested] 7+ messages in thread