diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.4/0532-rpi-ft5406-Create-coherent-buffer-and-push-to-firmwa.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.4/0532-rpi-ft5406-Create-coherent-buffer-and-push-to-firmwa.patch | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.4/0532-rpi-ft5406-Create-coherent-buffer-and-push-to-firmwa.patch b/target/linux/brcm2708/patches-4.4/0532-rpi-ft5406-Create-coherent-buffer-and-push-to-firmwa.patch new file mode 100644 index 0000000000..a2e8768782 --- /dev/null +++ b/target/linux/brcm2708/patches-4.4/0532-rpi-ft5406-Create-coherent-buffer-and-push-to-firmwa.patch @@ -0,0 +1,244 @@ +From bfc9d5f243f9202b699a2716b528be866039d6a4 Mon Sep 17 00:00:00 2001 +From: popcornmix <popcornmix@gmail.com> +Date: Fri, 11 Nov 2016 19:32:54 +0000 +Subject: [PATCH] rpi-ft5406: Create coherent buffer and push to firmware + +--- + drivers/input/touchscreen/rpi-ft5406.c | 152 +++++++++++++++++++---------- + include/soc/bcm2835/raspberrypi-firmware.h | 1 + + 2 files changed, 101 insertions(+), 52 deletions(-) + +--- a/drivers/input/touchscreen/rpi-ft5406.c ++++ b/drivers/input/touchscreen/rpi-ft5406.c +@@ -21,6 +21,7 @@ + #include <linux/kthread.h> + #include <linux/platform_device.h> + #include <asm/io.h> ++#include <linux/dma-mapping.h> + #include <soc/bcm2835/raspberrypi-firmware.h> + + #define MAXIMUM_SUPPORTED_POINTS 10 +@@ -45,6 +46,7 @@ struct ft5406 { + struct platform_device * pdev; + struct input_dev * input_dev; + void __iomem * ts_base; ++ dma_addr_t bus_addr; + struct ft5406_regs * regs; + struct task_struct * thread; + }; +@@ -117,18 +119,19 @@ static int ft5406_thread(void *arg) + + static int ft5406_probe(struct platform_device *pdev) + { +- int ret; +- struct input_dev * input_dev = input_allocate_device(); ++ int err = 0; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; + struct ft5406 * ts; + struct device_node *fw_node; + struct rpi_firmware *fw; + u32 touchbuf; + +- dev_info(&pdev->dev, "Probing device\n"); ++ dev_info(dev, "Probing device\n"); + +- fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); ++ fw_node = of_parse_phandle(np, "firmware", 0); + if (!fw_node) { +- dev_err(&pdev->dev, "Missing firmware node\n"); ++ dev_err(dev, "Missing firmware node\n"); + return -ENOENT; + } + +@@ -136,62 +139,88 @@ static int ft5406_probe(struct platform_ + if (!fw) + return -EPROBE_DEFER; + +- ret = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF, +- &touchbuf, sizeof(touchbuf)); +- if (ret) { +- dev_err(&pdev->dev, "Failed to get touch buffer\n"); +- return ret; ++ ts = devm_kzalloc(dev, sizeof(struct ft5406), GFP_KERNEL); ++ if (!ts) { ++ dev_err(dev, "Failed to allocate memory\n"); ++ return -ENOMEM; + } + +- if (!touchbuf) { +- dev_err(&pdev->dev, "Touchscreen not detected\n"); +- return -ENODEV; ++ ts->input_dev = input_allocate_device(); ++ if (!ts->input_dev) { ++ dev_err(dev, "Failed to allocate input device\n"); ++ return -ENOMEM; + } + +- dev_dbg(&pdev->dev, "Got TS buffer 0x%x\n", touchbuf); ++ ts->ts_base = dma_zalloc_coherent(NULL, PAGE_SIZE, &ts->bus_addr, GFP_KERNEL); ++ if (!ts->ts_base) { ++ pr_err("[%s]: failed to dma_alloc_coherent(%ld)\n", ++ __func__, PAGE_SIZE); ++ err = -ENOMEM; ++ goto out; ++ } + +- ts = kzalloc(sizeof(struct ft5406), GFP_KERNEL); ++ touchbuf = (u32)ts->bus_addr; ++ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF, ++ &touchbuf, sizeof(touchbuf)); + +- if (!ts || !input_dev) { +- ret = -ENOMEM; +- dev_err(&pdev->dev, "Failed to allocate memory\n"); +- return ret; ++ if (err || touchbuf != 0) { ++ dev_warn(dev, "Failed to set touchbuf, trying to get err:%x\n", err); ++ dma_free_coherent(NULL, PAGE_SIZE, ts->ts_base, ts->bus_addr); ++ ts->ts_base = 0; ++ ts->bus_addr = 0; ++ } ++ ++ if (!ts->ts_base) { ++ dev_warn(dev, "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%x)\n", err, touchbuf, ts->ts_base, ts->bus_addr); ++ ++ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF, ++ &touchbuf, sizeof(touchbuf)); ++ if (err) { ++ dev_err(dev, "Failed to get touch buffer\n"); ++ goto out; ++ } ++ ++ if (!touchbuf) { ++ dev_err(dev, "Touchscreen not detected\n"); ++ err = -ENODEV; ++ goto out; ++ } ++ ++ dev_dbg(dev, "Got TS buffer 0x%x\n", touchbuf); ++ ++ // mmap the physical memory ++ touchbuf &= ~0xc0000000; ++ ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs)); ++ if (ts->ts_base == NULL) ++ { ++ dev_err(dev, "Failed to map physical address\n"); ++ err = -ENOMEM; ++ goto out; ++ } + } +- ts->input_dev = input_dev; + platform_set_drvdata(pdev, ts); + ts->pdev = pdev; + +- input_dev->name = "FT5406 memory based driver"; ++ ts->input_dev->name = "FT5406 memory based driver"; + +- __set_bit(EV_KEY, input_dev->evbit); +- __set_bit(EV_SYN, input_dev->evbit); +- __set_bit(EV_ABS, input_dev->evbit); ++ __set_bit(EV_KEY, ts->input_dev->evbit); ++ __set_bit(EV_SYN, ts->input_dev->evbit); ++ __set_bit(EV_ABS, ts->input_dev->evbit); + +- input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ++ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, + SCREEN_WIDTH, 0, 0); +- input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ++ input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, + SCREEN_HEIGHT, 0, 0); + +- input_mt_init_slots(input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT); ++ input_mt_init_slots(ts->input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT); + +- input_set_drvdata(input_dev, ts); ++ input_set_drvdata(ts->input_dev, ts); + +- ret = input_register_device(input_dev); +- if (ret) { +- dev_err(&pdev->dev, "could not register input device, %d\n", +- ret); +- return ret; +- } +- +- // mmap the physical memory +- touchbuf &= ~0xc0000000; +- ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs)); +- if(ts->ts_base == NULL) +- { +- dev_err(&pdev->dev, "Failed to map physical address\n"); +- input_unregister_device(input_dev); +- kzfree(ts); +- return -ENOMEM; ++ err = input_register_device(ts->input_dev); ++ if (err) { ++ dev_err(dev, "could not register input device, %d\n", ++ err); ++ goto out; + } + + ts->regs = (struct ft5406_regs *) ts->ts_base; +@@ -200,25 +229,44 @@ static int ft5406_probe(struct platform_ + ts->thread = kthread_run(ft5406_thread, ts, "ft5406"); + if(ts->thread == NULL) + { +- dev_err(&pdev->dev, "Failed to create kernel thread"); +- iounmap(ts->ts_base); +- input_unregister_device(input_dev); +- kzfree(ts); ++ dev_err(dev, "Failed to create kernel thread"); ++ err = -ENOMEM; ++ goto out; + } + + return 0; ++ ++out: ++ if (ts->bus_addr) { ++ dma_free_coherent(NULL, PAGE_SIZE, ts->ts_base, ts->bus_addr); ++ ts->bus_addr = 0; ++ ts->ts_base = NULL; ++ } else if (ts->ts_base) { ++ iounmap(ts->ts_base); ++ ts->ts_base = NULL; ++ } ++ if (ts->input_dev) { ++ input_unregister_device(ts->input_dev); ++ ts->input_dev = NULL; ++ } ++ return err; + } + + static int ft5406_remove(struct platform_device *pdev) + { ++ struct device *dev = &pdev->dev; + struct ft5406 *ts = (struct ft5406 *) platform_get_drvdata(pdev); + +- dev_info(&pdev->dev, "Removing rpi-ft5406\n"); ++ dev_info(dev, "Removing rpi-ft5406\n"); + + kthread_stop(ts->thread); +- iounmap(ts->ts_base); +- input_unregister_device(ts->input_dev); +- kzfree(ts); ++ ++ if (ts->bus_addr) ++ dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr); ++ else if (ts->ts_base) ++ iounmap(ts->ts_base); ++ if (ts->input_dev) ++ input_unregister_device(ts->input_dev); + + return 0; + } +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -117,6 +117,7 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, + RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, + RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + |