[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 11/20] arm: add Faraday FTTSC010 touchscreen cont
From: |
Kuo-Jung Su |
Subject: |
[Qemu-devel] [PATCH v2 11/20] arm: add Faraday FTTSC010 touchscreen controller support |
Date: |
Fri, 25 Jan 2013 16:19:47 +0800 |
From: Kuo-Jung Su <address@hidden>
The FTTSC010 provides controlling signals to handle ADC conversion
and panel driver. The control signal is base on Faraday 12-bit ADC
IP of FXADC140HC0H_TPANEL, which is a 12-bit SAR ADC with 8-to-1
multiplexer, IPGA and panel driver. The ADC provides 8-channel analog
input via a multiplexer. There are 4 channels, including the panel
drivers, are used to measure the x-y position. One of the channels
embeds an IPGA, inputs the programmable gain amplifier to record voice.
The other three channels are auxiliary analog inputs, and can be used
to measure the system environment parameter, for example battery, chip
temperature and so on.
The FTTSC010 provides two operation modes to sample the analog input
voltage. The manual operation mode needs to program and control the
panel drivers by software step-by-step for the x-y position measurement.
The auto-scan mode provides a periodic sampling method to convert the
analog input. It also enables the function of auto-position measurement
to automatically control the panel drivers of ADC for the x-y position
measurement. It will auto-store these ADC conversion values that are
X+, X-, Y+, Y- references and the x-y position values from the four
channels of ADC. Users can easily read these values from six registers.
Signed-off-by: Kuo-Jung Su <address@hidden>
---
hw/fttsc010.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/fttsc010.h | 23 +++++
2 files changed, 283 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..40e2c38
--- /dev/null
+++ b/hw/fttsc010.c
@@ -0,0 +1,260 @@
+/*
+ * Faraday FTTSC010 emulator.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su <address@hidden>
+ *
+ * This code is licensed under GNU GPL v2.
+ */
+
+#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))
+
+#define TYPE_FTTSC010 "fttsc010"
+
+typedef struct Fttsc010State {
+ 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;
+
+#define FTTSC010(obj) \
+ OBJECT_CHECK(fttsc010_state, obj, TYPE_FTTSC010)
+
+static void fttsc010_update_irq(fttsc010_state *s)
+{
+ 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(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(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_ops = {
+ .read = fttsc010_mem_read,
+ .write = fttsc010_mem_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void fttsc010_timer_tick(void *opaque)
+{
+ fttsc010_state *s = FTTSC010(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(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 *ds)
+{
+ SysBusDevice *busdev = SYS_BUS_DEVICE(ds);
+ fttsc010_state *s = FTTSC010(FROM_SYSBUS(fttsc010_state, busdev));
+
+ 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 = FTTSC010(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_ops,
+ s,
+ TYPE_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 = {
+ .name = TYPE_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_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = fttsc010_init;
+ dc->reset = fttsc010_reset;
+ dc->vmsd = &vmstate_fttsc010;
+ dc->no_user = 1;
+}
+
+static const TypeInfo fttsc010_info = {
+ .name = TYPE_FTTSC010,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(fttsc010_state),
+ .class_init = fttsc010_class_init,
+};
+
+static void fttsc010_register_types(void)
+{
+ type_register_static(&fttsc010_info);
+}
+
+type_init(fttsc010_register_types)
diff --git a/hw/fttsc010.h b/hw/fttsc010.h
new file mode 100644
index 0000000..8619de3
--- /dev/null
+++ b/hw/fttsc010.h
@@ -0,0 +1,23 @@
+/*
+ * Faraday FTTSC010 touchscreen driver
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su <address@hidden>
+ *
+ * This file is licensed under GNU GPL.
+ */
+
+#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
- Re: [Qemu-devel] [PATCH v2 05/20] arm: add Faraday FTGMAC100 1Gbps ethernet support, (continued)
- [Qemu-devel] [PATCH v2 06/20] arm: add Faraday FTMAC110 10/100Mbps ethernet support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 07/20] arm: add Faraday FTI2C010 I2C controller support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 09/20] arm: add Faraday FTNANDC021 nand flash controller support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 08/20] arm: add Faraday FTLCDC200 LCD controller support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 10/20] arm: add Faraday FTSDC010 MMC/SD controller support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 11/20] arm: add Faraday FTTSC010 touchscreen controller support,
Kuo-Jung Su <=
- [Qemu-devel] [PATCH v2 12/20] arm: add Faraday FTSSP010 multi-function controller support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 16/20] arm: add Faraday FTTMR010 timer support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 15/20] arm: add Faraday FTWDT010 watchdog timer support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 13/20] arm: add Faraday FTSPI020 spi flash controller support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 19/20] arm: add Faraday FTKBC010 support for A369, Kuo-Jung Su, 2013/01/25
[Qemu-devel] [PATCH v2 18/20] arm: add Faraday FTINTC020 interrupt controller, Kuo-Jung Su, 2013/01/25