qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 11/18] hw: add QEMU model for Faraday touchscreen co


From: Dante
Subject: [Qemu-devel] [PATCH 11/18] hw: add QEMU model for Faraday touchscreen controller
Date: Fri, 18 Jan 2013 14:31:36 +0800

Signed-off-by: Kuo-Jung Su <address@hidden>
---
 hw/fttsc010.c |  239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/fttsc010.h |   35 +++++++++
 2 files changed, 274 insertions(+)
 create mode 100644 hw/fttsc010.c
 create mode 100644 hw/fttsc010.h

diff --git a/hw/fttsc010.c b/hw/fttsc010.c
new file mode 100644
index 0000000..2f5552e
--- /dev/null
+++ b/hw/fttsc010.c
@@ -0,0 +1,239 @@
+/*
+ * Faraday FTTSC010 emulator.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ *
+ * Written by Dante Su <address@hidden>
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "sysbus.h"
+#include "ui/console.h"
+#include "devices.h"
+
+#include "fttsc010.h"
+
+#define X_AXIS_DMAX    3470
+#define X_AXIS_MIN    290
+#define Y_AXIS_DMAX    3450
+#define Y_AXIS_MIN    200
+
+#define ADS_XPOS(x, y)    (X_AXIS_MIN + ((X_AXIS_DMAX * (x)) >> 15))
+#define ADS_YPOS(x, y)    (Y_AXIS_MIN + ((Y_AXIS_DMAX * (y)) >> 15))
+#define ADS_Z1POS(x, y)    (8)
+#define ADS_Z2POS(x, y)    ((1600 + ADS_XPOS(x, y)) * ADS_Z1POS(x, y) / 
ADS_XPOS(x, y))
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq irq;
+
+    uint64_t interval;
+    QEMUTimer *qtimer;
+
+    int x, y;
+    int z1, z2;
+
+    /* HW registers */
+    uint32_t cr;
+    uint32_t isr;
+    uint32_t imr;
+    uint32_t csr;
+    uint32_t pfr;
+    uint32_t dcr;
+} fttsc010_state;
+
+static inline void fttsc010_update_irq(void *opaque)
+{
+    fttsc010_state *s = (fttsc010_state *) opaque;
+    
+    if (s->imr & s->isr)
+        qemu_irq_raise(s->irq);
+    else
+        qemu_irq_lower(s->irq);
+}
+
+static uint64_t fttsc010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+    fttsc010_state *s = (fttsc010_state *) opaque;
+
+    switch (addr) {
+    case REG_CR:
+        return s->cr;
+    case REG_ISR:
+        return s->isr;
+    case REG_IMR:
+        return s->imr;
+    case REG_VER:
+        return 0x00010000;
+    case REG_CSR:
+        return s->csr;
+    case REG_PFR:
+        return s->pfr;
+    case REG_DCR:
+        return s->dcr;
+    case REG_XYR:
+        return (s->x & 0x0fff) | ((s->y & 0x0fff) << 16);
+    case REG_ZR:
+        return (s->z1 & 0x0fff) | ((s->z2 & 0x0fff) << 16);
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+static void fttsc010_mem_write(void *opaque, hwaddr addr, uint64_t val, 
unsigned size)
+{
+    fttsc010_state *s = (fttsc010_state *) opaque;
+
+    switch (addr) {
+    case REG_CR:
+        s->cr = (uint32_t)val;
+        if (s->cr & (3 << 30))
+            qemu_mod_timer(s->qtimer, s->interval + 
qemu_get_clock_ns(vm_clock));
+        else
+            qemu_del_timer(s->qtimer);
+        break;
+    case REG_ISR:
+        s->isr &= ~((uint32_t)val);
+        fttsc010_update_irq(s);
+        break;
+    case REG_IMR:
+        s->imr = (uint32_t)val;
+        fttsc010_update_irq(s);
+        break;
+    case REG_CSR:
+        s->csr = (uint32_t)val;
+        break;
+    case REG_PFR:
+        s->pfr = (uint32_t)val;
+        break;
+    case REG_DCR:
+        s->dcr = (uint32_t)val;
+        break;
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps fttsc010_mem_ops = {
+    .read  = fttsc010_mem_read,
+    .write = fttsc010_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void fttsc010_timer_tick(void *opaque)
+{
+    fttsc010_state *s = (fttsc010_state *) opaque;
+    
+    /* if auto-scan enabled */    
+    if (s->cr & (3 << 30)) {
+        s->isr |= (1 << 10);
+        /* turn it off, when it's under one-shot mode */
+        if (s->cr & (1 << 30))
+            s->cr &= ~(1 << 30);
+    }
+
+    fttsc010_update_irq(s);
+
+    qemu_mod_timer(s->qtimer, s->interval + qemu_get_clock_ns(vm_clock));
+}
+
+static void fttsc010_touchscreen_event(void *opaque,
+                int x, int y, int z, int buttons_state)
+{
+    fttsc010_state *s = (fttsc010_state *) opaque;
+
+    if (buttons_state) {
+        x = 0x7fff - x;
+        s->x  = ADS_XPOS(x, y);
+        s->y  = ADS_YPOS(x, y);
+        s->z1 = ADS_Z1POS(x, y);
+        s->z2 = ADS_Z2POS(x, y);
+    } else {
+        s->z1 = 0;
+        s->z2 = 0;
+    }
+}
+
+static void fttsc010_reset(DeviceState *d)
+{
+    fttsc010_state *s = DO_UPCAST(fttsc010_state, busdev.qdev, d);
+    
+    s->cr  = 0;
+    s->isr = 0;
+    s->imr = 0;
+    s->csr = 0;
+    s->pfr = 0;
+    s->dcr = 0;
+
+    s->x  = 0;
+    s->y  = 0;
+    s->z1 = 0;
+    s->z2 = 0;
+
+    qemu_irq_lower(s->irq);
+}
+
+static int fttsc010_init(SysBusDevice *dev)
+{
+    fttsc010_state *s = FROM_SYSBUS(fttsc010_state, dev);
+    
+    s->interval = (uint64_t)get_ticks_per_sec() >> 6;
+    s->qtimer   = qemu_new_timer_ns(vm_clock, fttsc010_timer_tick, s);
+
+    memory_region_init_io(&s->iomem, &fttsc010_mem_ops, s, "fttsc010", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq);
+    
+    qemu_add_mouse_event_handler(fttsc010_touchscreen_event, s, 1,
+                    "QEMU FTTSC010-driven Touchscreen");
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_fttsc010_regs = {
+    .name = "fttsc010",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(cr, fttsc010_state),
+        VMSTATE_UINT32(isr, fttsc010_state),
+        VMSTATE_UINT32(imr, fttsc010_state),
+        VMSTATE_UINT32(csr, fttsc010_state),
+        VMSTATE_UINT32(pfr, fttsc010_state),
+        VMSTATE_UINT32(dcr, fttsc010_state),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static void fttsc010_dev_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *k = DEVICE_CLASS(klass);    
+
+    sdc->init  = fttsc010_init;
+    k->vmsd    = &vmstate_fttsc010_regs;
+    k->reset   = fttsc010_reset;
+    k->no_user = 1;
+}
+
+static TypeInfo fttsc010_dev_info = {
+    .name          = "fttsc010",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(fttsc010_state),
+    .class_init    = fttsc010_dev_class_init,
+};
+
+static void fttsc010_register_types(void)
+{
+    type_register_static(&fttsc010_dev_info);
+}
+
+type_init(fttsc010_register_types)
diff --git a/hw/fttsc010.h b/hw/fttsc010.h
new file mode 100644
index 0000000..c3756eb
--- /dev/null
+++ b/hw/fttsc010.h
@@ -0,0 +1,35 @@
+/*
+ * Faraday FTTSC010 touchscreen driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the term of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright 2009 Dante Su <address@hidden>
+ *
+ */
+
+#ifndef FTTSC010_H
+#define FTTSC010_H
+
+#define REG_CR            0x00  /* Control Register */
+#define REG_ISR            0x04  /* Interrupt Status Register */
+#define REG_IMR            0x08  /* Interrupt Mask Register */
+#define REG_VER            0x0C  /* Version Register */
+#define REG_CSR            0x30  /* Clock & Sample Rate Register */
+#define REG_PFR            0x34  /* Panel Function Register */
+#define REG_DCR            0x38  /* Delay Control Register */
+#define REG_XYR            0x3C  /* Touchscreen X,Y-Axis Register */
+#define REG_ZR            0x4C  /* Touchscreen Z-Axis (Pressure) Register */
+
+#endif
-- 
1.7.9.5


********************* Confidentiality Notice ************************
This electronic message and any attachments may contain
confidential and legally privileged information or
information which is otherwise protected from disclosure.
If you are not the intended recipient,please do not disclose
the contents, either in whole or in part, to anyone,and
immediately delete the message and any attachments from
your computer system and destroy all hard copies.
Thank you for your cooperation.
***********************************************************************




reply via email to

[Prev in Thread] Current Thread [Next in Thread]