Commit 3efda49d150def64f69a79cbd8da760ea15a79b7

Authored by balrog
1 parent 8c9d7f83

Add a TI TSC2102 chip (touchscreen/ADC/audio-CODEC controller).

Fix GPIO memory mapping address and register width.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3484 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -518,8 +518,8 @@ VL_OBJS+= arm_gic.o realview.o arm_sysctl.o
518 518 VL_OBJS+= arm-semi.o
519 519 VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
520 520 VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o max7310.o
521   -VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o $(AUDIODRV) wm8750.o
522   -VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o palm.o ecc.o
  521 +VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o ecc.o $(AUDIODRV) wm8750.o
  522 +VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o palm.o tsc210x.o
523 523 CPPFLAGS += -DHAS_AUDIO
524 524 endif
525 525 ifeq ($(TARGET_BASE_ARCH), sh4)
... ...
hw/omap.c
... ... @@ -3184,16 +3184,17 @@ static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
3184 3184 }
3185 3185 }
3186 3186  
  3187 +/* *Some* sources say the memory region is 32-bit. */
3187 3188 static CPUReadMemoryFunc *omap_gpio_readfn[] = {
  3189 + omap_badwidth_read16,
3188 3190 omap_gpio_read,
3189   - omap_badwidth_read32,
3190   - omap_badwidth_read32,
  3191 + omap_badwidth_read16,
3191 3192 };
3192 3193  
3193 3194 static CPUWriteMemoryFunc *omap_gpio_writefn[] = {
  3195 + omap_badwidth_write16,
3194 3196 omap_gpio_write,
3195   - omap_badwidth_write32,
3196   - omap_badwidth_write32,
  3197 + omap_badwidth_write16,
3197 3198 };
3198 3199  
3199 3200 void omap_gpio_reset(struct omap_gpio_s *s)
... ... @@ -3551,7 +3552,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
3551 3552 s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
3552 3553 s->wakeup, omap_findclk(s, "clk32-kHz"));
3553 3554  
3554   - s->gpio = omap_gpio_init(0xfffcf000, s->irq[0][OMAP_INT_GPIO_BANK1],
  3555 + s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1],
3555 3556 omap_findclk(s, "mpuper_ck"));
3556 3557  
3557 3558 s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
... ...
hw/palm.c
... ... @@ -76,8 +76,21 @@ static CPUWriteMemoryFunc *static_writefn[] = {
76 76 #define PALMTE_MMC2_GPIO 7
77 77 #define PALMTE_MMC3_GPIO 11
78 78  
  79 +static void palmte_pintdav(void *opaque, int line, int level)
  80 +{
  81 + struct omap_mpu_state_s *cpu = (struct omap_mpu_state_s *) opaque;
  82 +
  83 + qemu_set_irq(omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO],
  84 + !level);
  85 +}
  86 +
79 87 static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
80 88 {
  89 + omap_uwire_attach(
  90 + cpu->microwire,
  91 + tsc2102_init(
  92 + qemu_allocate_irqs(palmte_pintdav, cpu, 1)[0]),
  93 + 0);
81 94 }
82 95  
83 96 static struct {
... ...
hw/pxa.h
... ... @@ -4,7 +4,7 @@
4 4 * Copyright (c) 2006 Openedhand Ltd.
5 5 * Written by Andrzej Zaborowski <balrog@zabor.org>
6 6 *
7   - * This code is licenced under the GPL.
  7 + * This code is licenced under the GNU GPL v2.
8 8 */
9 9 #ifndef PXA_H
10 10 # define PXA_H "pxa.h"
... ...
hw/tsc210x.c 0 → 100644
  1 +/*
  2 + * TI TSC2102 (touchscreen/sensors/audio controller) controller.
  3 + *
  4 + * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
  5 + *
  6 + * This program is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU General Public License as
  8 + * published by the Free Software Foundation; either version 2 of
  9 + * the License, or (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  19 + * MA 02111-1307 USA
  20 + */
  21 +
  22 +#include "vl.h"
  23 +
  24 +#define TSC_DATA_REGISTERS_PAGE 0x0
  25 +#define TSC_CONTROL_REGISTERS_PAGE 0x1
  26 +#define TSC_AUDIO_REGISTERS_PAGE 0x2
  27 +
  28 +#define TSC_VERBOSE
  29 +
  30 +#define TSC_CUT_RESOLUTION(value, p) ((value) >> (16 - resolution[p]))
  31 +
  32 +struct tsc210x_state_s {
  33 + qemu_irq pint;
  34 + QEMUTimer *timer;
  35 + struct uwire_slave_s chip;
  36 +
  37 + int x, y;
  38 + int pressure;
  39 +
  40 + int state, page, offset, irq;
  41 + uint16_t command, dav;
  42 +
  43 + int busy;
  44 + int enabled;
  45 + int host_mode;
  46 + int function;
  47 + int nextfunction;
  48 + int precision;
  49 + int nextprecision;
  50 + int filter;
  51 + int pin_func;
  52 + int ref;
  53 + int timing;
  54 + int noise;
  55 +
  56 + uint16_t audio_ctrl1;
  57 + uint16_t audio_ctrl2;
  58 + uint16_t audio_ctrl3;
  59 + uint16_t pll[2];
  60 + uint16_t volume;
  61 + int64_t volume_change;
  62 + int softstep;
  63 + uint16_t dac_power;
  64 + int64_t powerdown;
  65 + uint16_t filter_data[0x14];
  66 +};
  67 +
  68 +static const int resolution[4] = { 12, 8, 10, 12 };
  69 +
  70 +#define TSC_MODE_NO_SCAN 0x0
  71 +#define TSC_MODE_XY_SCAN 0x1
  72 +#define TSC_MODE_XYZ_SCAN 0x2
  73 +#define TSC_MODE_X 0x3
  74 +#define TSC_MODE_Y 0x4
  75 +#define TSC_MODE_Z 0x5
  76 +#define TSC_MODE_BAT1 0x6
  77 +#define TSC_MODE_BAT2 0x7
  78 +#define TSC_MODE_AUX 0x8
  79 +#define TSC_MODE_AUX_SCAN 0x9
  80 +#define TSC_MODE_TEMP1 0xa
  81 +#define TSC_MODE_PORT_SCAN 0xb
  82 +#define TSC_MODE_TEMP2 0xc
  83 +#define TSC_MODE_XX_DRV 0xd
  84 +#define TSC_MODE_YY_DRV 0xe
  85 +#define TSC_MODE_YX_DRV 0xf
  86 +
  87 +static const uint16_t mode_regs[16] = {
  88 + 0x0000, /* No scan */
  89 + 0x0600, /* X, Y scan */
  90 + 0x0780, /* X, Y, Z scan */
  91 + 0x0400, /* X */
  92 + 0x0200, /* Y */
  93 + 0x0180, /* Z */
  94 + 0x0040, /* BAT1 */
  95 + 0x0030, /* BAT2 */
  96 + 0x0010, /* AUX */
  97 + 0x0010, /* AUX scan */
  98 + 0x0004, /* TEMP1 */
  99 + 0x0070, /* Port scan */
  100 + 0x0002, /* TEMP2 */
  101 + 0x0000, /* X+, X- drivers */
  102 + 0x0000, /* Y+, Y- drivers */
  103 + 0x0000, /* Y+, X- drivers */
  104 +};
  105 +
  106 +/*
  107 + * Convert screen coordinates to arbitrary values that the
  108 + * touchscreen in my Palm Tungsten E device returns.
  109 + * This shouldn't really matter (because the guest system
  110 + * should calibrate the touchscreen anyway), but let's
  111 + * imitate some real hardware.
  112 + */
  113 +#define X_TRANSFORM(value) \
  114 + ((3850 - ((int) (value) * (3850 - 250) / 32768)) << 4)
  115 +#define Y_TRANSFORM(value) \
  116 + ((150 + ((int) (value) * (3037 - 150) / 32768)) << 4)
  117 +#define Z1_TRANSFORM(s) \
  118 + ((400 - (s)->x + ((s)->pressure << 9)) << 4)
  119 +#define Z2_TRANSFORM(s) \
  120 + ((4000 + (s)->y - ((s)->pressure << 10)) << 4)
  121 +#define BAT1_VAL 0x8660
  122 +#define BAT2_VAL 0x0000
  123 +#define AUX1_VAL 0x35c0
  124 +#define AUX2_VAL 0xffff
  125 +#define TEMP1_VAL 0x8c70
  126 +#define TEMP2_VAL 0xa5b0
  127 +
  128 +#define TSC_POWEROFF_DELAY 50
  129 +#define TSC_SOFTSTEP_DELAY 50
  130 +
  131 +static void tsc210x_reset(struct tsc210x_state_s *s)
  132 +{
  133 + s->state = 0;
  134 + s->pin_func = 2;
  135 + s->enabled = 0;
  136 + s->busy = 0;
  137 + s->nextfunction = 0;
  138 + s->ref = 0;
  139 + s->timing = 0;
  140 + s->irq = 0;
  141 + s->dav = 0;
  142 +
  143 + s->audio_ctrl1 = 0x0000;
  144 + s->audio_ctrl2 = 0x4410;
  145 + s->audio_ctrl3 = 0x0000;
  146 + s->pll[0] = 0x1004;
  147 + s->pll[1] = 0x0000;
  148 + s->volume = 0xffff;
  149 + s->dac_power = 0x8540;
  150 + s->softstep = 1;
  151 + s->volume_change = 0;
  152 + s->powerdown = 0;
  153 + s->filter_data[0x00] = 0x6be3;
  154 + s->filter_data[0x01] = 0x9666;
  155 + s->filter_data[0x02] = 0x675d;
  156 + s->filter_data[0x03] = 0x6be3;
  157 + s->filter_data[0x04] = 0x9666;
  158 + s->filter_data[0x05] = 0x675d;
  159 + s->filter_data[0x06] = 0x7d83;
  160 + s->filter_data[0x07] = 0x84ee;
  161 + s->filter_data[0x08] = 0x7d83;
  162 + s->filter_data[0x09] = 0x84ee;
  163 + s->filter_data[0x0a] = 0x6be3;
  164 + s->filter_data[0x0b] = 0x9666;
  165 + s->filter_data[0x0c] = 0x675d;
  166 + s->filter_data[0x0d] = 0x6be3;
  167 + s->filter_data[0x0e] = 0x9666;
  168 + s->filter_data[0x0f] = 0x675d;
  169 + s->filter_data[0x10] = 0x7d83;
  170 + s->filter_data[0x11] = 0x84ee;
  171 + s->filter_data[0x12] = 0x7d83;
  172 + s->filter_data[0x13] = 0x84ee;
  173 +
  174 + qemu_set_irq(s->pint, s->irq);
  175 +}
  176 +
  177 +static uint16_t tsc2102_data_register_read(struct tsc210x_state_s *s, int reg)
  178 +{
  179 + switch (reg) {
  180 + case 0x00: /* X */
  181 + s->dav &= 0xfbff;
  182 + return TSC_CUT_RESOLUTION(X_TRANSFORM(s->x), s->precision) +
  183 + (s->noise & 3);
  184 +
  185 + case 0x01: /* Y */
  186 + s->noise ++;
  187 + s->dav &= 0xfdff;
  188 + return TSC_CUT_RESOLUTION(Y_TRANSFORM(s->y), s->precision) ^
  189 + (s->noise & 3);
  190 +
  191 + case 0x02: /* Z1 */
  192 + s->dav &= 0xfeff;
  193 + return TSC_CUT_RESOLUTION(Z1_TRANSFORM(s), s->precision) -
  194 + (s->noise & 3);
  195 +
  196 + case 0x03: /* Z2 */
  197 + s->dav &= 0xff7f;
  198 + return TSC_CUT_RESOLUTION(Z2_TRANSFORM(s), s->precision) |
  199 + (s->noise & 3);
  200 +
  201 + case 0x04: /* KPData */
  202 + return 0xffff;
  203 +
  204 + case 0x05: /* BAT1 */
  205 + s->dav &= 0xffbf;
  206 + return TSC_CUT_RESOLUTION(BAT1_VAL, s->precision);
  207 +
  208 + case 0x06: /* BAT2 */
  209 + s->dav &= 0xffdf;
  210 + return TSC_CUT_RESOLUTION(BAT2_VAL, s->precision);
  211 +
  212 + case 0x07: /* AUX1 */
  213 + s->dav &= 0xffef;
  214 + return TSC_CUT_RESOLUTION(AUX1_VAL, s->precision);
  215 +
  216 + case 0x08: /* AUX2 */
  217 + s->dav &= 0xfff7;
  218 + return 0xffff;
  219 +
  220 + case 0x09: /* TEMP1 */
  221 + s->dav &= 0xfffb;
  222 + return TSC_CUT_RESOLUTION(TEMP1_VAL, s->precision);
  223 +
  224 + case 0x0a: /* TEMP2 */
  225 + s->dav &= 0xfffd;
  226 + return TSC_CUT_RESOLUTION(TEMP2_VAL, s->precision);
  227 +
  228 + case 0x0b: /* DAC */
  229 + s->dav &= 0xfffe;
  230 + return 0xffff;
  231 +
  232 + default:
  233 +#ifdef TSC_VERBOSE
  234 + fprintf(stderr, "tsc2102_data_register_read: "
  235 + "no such register: 0x%02x\n", reg);
  236 +#endif
  237 + return 0xffff;
  238 + }
  239 +}
  240 +
  241 +static uint16_t tsc2102_control_register_read(
  242 + struct tsc210x_state_s *s, int reg)
  243 +{
  244 + switch (reg) {
  245 + case 0x00: /* TSC ADC */
  246 + return (s->pressure << 15) | ((!s->busy) << 14) |
  247 + (s->nextfunction << 10) | (s->nextprecision << 8) | s->filter;
  248 +
  249 + case 0x01: /* Status */
  250 + return (s->pin_func << 14) | ((!s->enabled) << 13) |
  251 + (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav;
  252 +
  253 + case 0x03: /* Reference */
  254 + return s->ref;
  255 +
  256 + case 0x04: /* Reset */
  257 + return 0xffff;
  258 +
  259 + case 0x05: /* Configuration */
  260 + return s->timing;
  261 +
  262 + default:
  263 +#ifdef TSC_VERBOSE
  264 + fprintf(stderr, "tsc2102_control_register_read: "
  265 + "no such register: 0x%02x\n", reg);
  266 +#endif
  267 + return 0xffff;
  268 + }
  269 +}
  270 +
  271 +static uint16_t tsc2102_audio_register_read(struct tsc210x_state_s *s, int reg)
  272 +{
  273 + int l_ch, r_ch;
  274 + uint16_t val;
  275 +
  276 + switch (reg) {
  277 + case 0x00: /* Audio Control 1 */
  278 + return s->audio_ctrl1;
  279 +
  280 + case 0x01:
  281 + return 0xff00;
  282 +
  283 + case 0x02: /* DAC Volume Control */
  284 + return s->volume;
  285 +
  286 + case 0x03:
  287 + return 0x8b00;
  288 +
  289 + case 0x04: /* Audio Control 2 */
  290 + l_ch = 1;
  291 + r_ch = 1;
  292 + if (s->softstep && !(s->dac_power & (1 << 10))) {
  293 + l_ch = (qemu_get_clock(vm_clock) >
  294 + s->volume_change + TSC_SOFTSTEP_DELAY);
  295 + r_ch = (qemu_get_clock(vm_clock) >
  296 + s->volume_change + TSC_SOFTSTEP_DELAY);
  297 + }
  298 +
  299 + return s->audio_ctrl2 | (l_ch << 3) | (r_ch << 2);
  300 +
  301 + case 0x05: /* Stereo DAC Power Control */
  302 + return 0x2aa0 | s->dac_power |
  303 + (((s->dac_power & (1 << 10)) &&
  304 + (qemu_get_clock(vm_clock) >
  305 + s->powerdown + TSC_POWEROFF_DELAY)) << 6);
  306 +
  307 + case 0x06: /* Audio Control 3 */
  308 + val = s->audio_ctrl3 | 0x0001;
  309 + s->audio_ctrl3 &= 0xff3f;
  310 + return val;
  311 +
  312 + case 0x07: /* LCH_BASS_BOOST_N0 */
  313 + case 0x08: /* LCH_BASS_BOOST_N1 */
  314 + case 0x09: /* LCH_BASS_BOOST_N2 */
  315 + case 0x0a: /* LCH_BASS_BOOST_N3 */
  316 + case 0x0b: /* LCH_BASS_BOOST_N4 */
  317 + case 0x0c: /* LCH_BASS_BOOST_N5 */
  318 + case 0x0d: /* LCH_BASS_BOOST_D1 */
  319 + case 0x0e: /* LCH_BASS_BOOST_D2 */
  320 + case 0x0f: /* LCH_BASS_BOOST_D4 */
  321 + case 0x10: /* LCH_BASS_BOOST_D5 */
  322 + case 0x11: /* RCH_BASS_BOOST_N0 */
  323 + case 0x12: /* RCH_BASS_BOOST_N1 */
  324 + case 0x13: /* RCH_BASS_BOOST_N2 */
  325 + case 0x14: /* RCH_BASS_BOOST_N3 */
  326 + case 0x15: /* RCH_BASS_BOOST_N4 */
  327 + case 0x16: /* RCH_BASS_BOOST_N5 */
  328 + case 0x17: /* RCH_BASS_BOOST_D1 */
  329 + case 0x18: /* RCH_BASS_BOOST_D2 */
  330 + case 0x19: /* RCH_BASS_BOOST_D4 */
  331 + case 0x1a: /* RCH_BASS_BOOST_D5 */
  332 + return s->filter_data[reg - 0x07];
  333 +
  334 + case 0x1b: /* PLL Programmability 1 */
  335 + return s->pll[0];
  336 +
  337 + case 0x1c: /* PLL Programmability 2 */
  338 + return s->pll[1];
  339 +
  340 + case 0x1d: /* Audio Control 4 */
  341 + return (!s->softstep) << 14;
  342 +
  343 + default:
  344 +#ifdef TSC_VERBOSE
  345 + fprintf(stderr, "tsc2102_audio_register_read: "
  346 + "no such register: 0x%02x\n", reg);
  347 +#endif
  348 + return 0xffff;
  349 + }
  350 +}
  351 +
  352 +static void tsc2102_data_register_write(
  353 + struct tsc210x_state_s *s, int reg, uint16_t value)
  354 +{
  355 + switch (reg) {
  356 + case 0x00: /* X */
  357 + case 0x01: /* Y */
  358 + case 0x02: /* Z1 */
  359 + case 0x03: /* Z2 */
  360 + case 0x05: /* BAT1 */
  361 + case 0x06: /* BAT2 */
  362 + case 0x07: /* AUX1 */
  363 + case 0x08: /* AUX2 */
  364 + case 0x09: /* TEMP1 */
  365 + case 0x0a: /* TEMP2 */
  366 + return;
  367 +
  368 + default:
  369 +#ifdef TSC_VERBOSE
  370 + fprintf(stderr, "tsc2102_data_register_write: "
  371 + "no such register: 0x%02x\n", reg);
  372 +#endif
  373 + }
  374 +}
  375 +
  376 +static void tsc2102_control_register_write(
  377 + struct tsc210x_state_s *s, int reg, uint16_t value)
  378 +{
  379 + switch (reg) {
  380 + case 0x00: /* TSC ADC */
  381 + s->host_mode = value >> 15;
  382 + s->enabled = !(value & 0x4000);
  383 + if (s->busy && !s->enabled)
  384 + qemu_del_timer(s->timer);
  385 + s->busy &= s->enabled;
  386 + s->nextfunction = (value >> 10) & 0xf;
  387 + s->nextprecision = (value >> 8) & 3;
  388 + s->filter = value & 0xff;
  389 + return;
  390 +
  391 + case 0x01: /* Status */
  392 + s->pin_func = value >> 14;
  393 + return;
  394 +
  395 + case 0x03: /* Reference */
  396 + s->ref = value & 0x1f;
  397 + return;
  398 +
  399 + case 0x04: /* Reset */
  400 + if (value == 0xbb00) {
  401 + if (s->busy)
  402 + qemu_del_timer(s->timer);
  403 + tsc210x_reset(s);
  404 +#ifdef TSC_VERBOSE
  405 + } else {
  406 + fprintf(stderr, "tsc2102_control_register_write: "
  407 + "wrong value written into RESET\n");
  408 +#endif
  409 + }
  410 + return;
  411 +
  412 + case 0x05: /* Configuration */
  413 + s->timing = value & 0x3f;
  414 +#ifdef TSC_VERBOSE
  415 + if (value & ~0x3f)
  416 + fprintf(stderr, "tsc2102_control_register_write: "
  417 + "wrong value written into CONFIG\n");
  418 +#endif
  419 + return;
  420 +
  421 + default:
  422 +#ifdef TSC_VERBOSE
  423 + fprintf(stderr, "tsc2102_control_register_write: "
  424 + "no such register: 0x%02x\n", reg);
  425 +#endif
  426 + }
  427 +}
  428 +
  429 +static void tsc2102_audio_register_write(
  430 + struct tsc210x_state_s *s, int reg, uint16_t value)
  431 +{
  432 + switch (reg) {
  433 + case 0x00: /* Audio Control 1 */
  434 + s->audio_ctrl1 = value & 0x0f3f;
  435 +#ifdef TSC_VERBOSE
  436 + if ((value & ~0x0f3f) || ((value & 7) != ((value >> 3) & 7)))
  437 + fprintf(stderr, "tsc2102_audio_register_write: "
  438 + "wrong value written into Audio 1\n");
  439 +#endif
  440 + return;
  441 +
  442 + case 0x01:
  443 +#ifdef TSC_VERBOSE
  444 + if (value != 0xff00)
  445 + fprintf(stderr, "tsc2102_audio_register_write: "
  446 + "wrong value written into reg 0x01\n");
  447 +#endif
  448 + return;
  449 +
  450 + case 0x02: /* DAC Volume Control */
  451 + s->volume = value;
  452 + s->volume_change = qemu_get_clock(vm_clock);
  453 + return;
  454 +
  455 + case 0x03:
  456 +#ifdef TSC_VERBOSE
  457 + if (value != 0x8b00)
  458 + fprintf(stderr, "tsc2102_audio_register_write: "
  459 + "wrong value written into reg 0x03\n");
  460 +#endif
  461 + return;
  462 +
  463 + case 0x04: /* Audio Control 2 */
  464 + s->audio_ctrl2 = value & 0xf7f2;
  465 +#ifdef TSC_VERBOSE
  466 + if (value & ~0xf7fd)
  467 + fprintf(stderr, "tsc2102_audio_register_write: "
  468 + "wrong value written into Audio 2\n");
  469 +#endif
  470 + return;
  471 +
  472 + case 0x05: /* Stereo DAC Power Control */
  473 + if ((value & ~s->dac_power) & (1 << 10))
  474 + s->powerdown = qemu_get_clock(vm_clock);
  475 +
  476 + s->dac_power = value & 0x9543;
  477 +#ifdef TSC_VERBOSE
  478 + if ((value & ~0x9543) != 0x2aa0)
  479 + fprintf(stderr, "tsc2102_audio_register_write: "
  480 + "wrong value written into Power\n");
  481 +#endif
  482 + return;
  483 +
  484 + case 0x06: /* Audio Control 3 */
  485 + s->audio_ctrl3 &= 0x00c0;
  486 + s->audio_ctrl3 |= value & 0xf800;
  487 +#ifdef TSC_VERBOSE
  488 + if (value & ~0xf8c7)
  489 + fprintf(stderr, "tsc2102_audio_register_write: "
  490 + "wrong value written into Audio 3\n");
  491 +#endif
  492 + return;
  493 +
  494 + case 0x07: /* LCH_BASS_BOOST_N0 */
  495 + case 0x08: /* LCH_BASS_BOOST_N1 */
  496 + case 0x09: /* LCH_BASS_BOOST_N2 */
  497 + case 0x0a: /* LCH_BASS_BOOST_N3 */
  498 + case 0x0b: /* LCH_BASS_BOOST_N4 */
  499 + case 0x0c: /* LCH_BASS_BOOST_N5 */
  500 + case 0x0d: /* LCH_BASS_BOOST_D1 */
  501 + case 0x0e: /* LCH_BASS_BOOST_D2 */
  502 + case 0x0f: /* LCH_BASS_BOOST_D4 */
  503 + case 0x10: /* LCH_BASS_BOOST_D5 */
  504 + case 0x11: /* RCH_BASS_BOOST_N0 */
  505 + case 0x12: /* RCH_BASS_BOOST_N1 */
  506 + case 0x13: /* RCH_BASS_BOOST_N2 */
  507 + case 0x14: /* RCH_BASS_BOOST_N3 */
  508 + case 0x15: /* RCH_BASS_BOOST_N4 */
  509 + case 0x16: /* RCH_BASS_BOOST_N5 */
  510 + case 0x17: /* RCH_BASS_BOOST_D1 */
  511 + case 0x18: /* RCH_BASS_BOOST_D2 */
  512 + case 0x19: /* RCH_BASS_BOOST_D4 */
  513 + case 0x1a: /* RCH_BASS_BOOST_D5 */
  514 + s->filter_data[reg - 0x07] = value;
  515 + return;
  516 +
  517 + case 0x1b: /* PLL Programmability 1 */
  518 + s->pll[0] = value & 0xfffc;
  519 +#ifdef TSC_VERBOSE
  520 + if (value & ~0xfffc)
  521 + fprintf(stderr, "tsc2102_audio_register_write: "
  522 + "wrong value written into PLL 1\n");
  523 +#endif
  524 + return;
  525 +
  526 + case 0x1c: /* PLL Programmability 2 */
  527 + s->pll[1] = value & 0xfffc;
  528 +#ifdef TSC_VERBOSE
  529 + if (value & ~0xfffc)
  530 + fprintf(stderr, "tsc2102_audio_register_write: "
  531 + "wrong value written into PLL 2\n");
  532 +#endif
  533 + return;
  534 +
  535 + case 0x1d: /* Audio Control 4 */
  536 + s->softstep = !(value & 0x4000);
  537 +#ifdef TSC_VERBOSE
  538 + if (value & ~0x4000)
  539 + fprintf(stderr, "tsc2102_audio_register_write: "
  540 + "wrong value written into Audio 4\n");
  541 +#endif
  542 + return;
  543 +
  544 + default:
  545 +#ifdef TSC_VERBOSE
  546 + fprintf(stderr, "tsc2102_audio_register_write: "
  547 + "no such register: 0x%02x\n", reg);
  548 +#endif
  549 + }
  550 +}
  551 +
  552 +/* This handles most of the chip logic. */
  553 +static void tsc210x_pin_update(struct tsc210x_state_s *s)
  554 +{
  555 + int64_t expires;
  556 + int pin_state;
  557 +
  558 + switch (s->pin_func) {
  559 + case 0:
  560 + pin_state = s->pressure;
  561 + break;
  562 + case 1:
  563 + pin_state = !!s->dav;
  564 + break;
  565 + case 2:
  566 + default:
  567 + pin_state = s->pressure && !s->dav;
  568 + }
  569 +
  570 + if (!s->enabled)
  571 + pin_state = 0;
  572 +
  573 + if (pin_state != s->irq) {
  574 + s->irq = pin_state;
  575 + qemu_set_irq(s->pint, s->irq);
  576 + }
  577 +
  578 + switch (s->nextfunction) {
  579 + case TSC_MODE_XY_SCAN:
  580 + case TSC_MODE_XYZ_SCAN:
  581 + if (!s->pressure)
  582 + return;
  583 + break;
  584 +
  585 + case TSC_MODE_X:
  586 + case TSC_MODE_Y:
  587 + case TSC_MODE_Z:
  588 + if (!s->pressure)
  589 + return;
  590 + /* Fall through */
  591 + case TSC_MODE_BAT1:
  592 + case TSC_MODE_BAT2:
  593 + case TSC_MODE_AUX:
  594 + case TSC_MODE_TEMP1:
  595 + case TSC_MODE_TEMP2:
  596 + if (s->dav)
  597 + s->enabled = 0;
  598 + break;
  599 +
  600 + case TSC_MODE_AUX_SCAN:
  601 + case TSC_MODE_PORT_SCAN:
  602 + break;
  603 +
  604 + case TSC_MODE_NO_SCAN:
  605 + case TSC_MODE_XX_DRV:
  606 + case TSC_MODE_YY_DRV:
  607 + case TSC_MODE_YX_DRV:
  608 + default:
  609 + return;
  610 + }
  611 +
  612 + if (!s->enabled || s->busy)
  613 + return;
  614 +
  615 + s->busy = 1;
  616 + s->precision = s->nextprecision;
  617 + s->function = s->nextfunction;
  618 + expires = qemu_get_clock(vm_clock) + (ticks_per_sec >> 10);
  619 + qemu_mod_timer(s->timer, expires);
  620 +}
  621 +
  622 +static uint16_t tsc210x_read(struct tsc210x_state_s *s)
  623 +{
  624 + uint16_t ret = 0x0000;
  625 +
  626 + if (!s->command)
  627 + fprintf(stderr, "tsc210x_read: SPI underrun!\n");
  628 +
  629 + switch (s->page) {
  630 + case TSC_DATA_REGISTERS_PAGE:
  631 + ret = tsc2102_data_register_read(s, s->offset);
  632 + break;
  633 + case TSC_CONTROL_REGISTERS_PAGE:
  634 + ret = tsc2102_control_register_read(s, s->offset);
  635 + break;
  636 + case TSC_AUDIO_REGISTERS_PAGE:
  637 + ret = tsc2102_audio_register_read(s, s->offset);
  638 + break;
  639 + default:
  640 + cpu_abort(cpu_single_env, "tsc210x_read: wrong memory page\n");
  641 + }
  642 +
  643 + tsc210x_pin_update(s);
  644 +
  645 + /* Allow sequential reads. */
  646 + s->offset ++;
  647 + s->state = 0;
  648 + return ret;
  649 +}
  650 +
  651 +static void tsc210x_write(struct tsc210x_state_s *s, uint16_t value)
  652 +{
  653 + /*
  654 + * This is a two-state state machine for reading
  655 + * command and data every second time.
  656 + */
  657 + if (!s->state) {
  658 + s->command = value >> 15;
  659 + s->page = (value >> 11) & 0x0f;
  660 + s->offset = (value >> 5) & 0x3f;
  661 + s->state = 1;
  662 + } else {
  663 + if (s->command)
  664 + fprintf(stderr, "tsc210x_write: SPI overrun!\n");
  665 + else
  666 + switch (s->page) {
  667 + case TSC_DATA_REGISTERS_PAGE:
  668 + tsc2102_data_register_write(s, s->offset, value);
  669 + break;
  670 + case TSC_CONTROL_REGISTERS_PAGE:
  671 + tsc2102_control_register_write(s, s->offset, value);
  672 + break;
  673 + case TSC_AUDIO_REGISTERS_PAGE:
  674 + tsc2102_audio_register_write(s, s->offset, value);
  675 + break;
  676 + default:
  677 + cpu_abort(cpu_single_env,
  678 + "tsc210x_write: wrong memory page\n");
  679 + }
  680 +
  681 + tsc210x_pin_update(s);
  682 + s->state = 0;
  683 + }
  684 +}
  685 +
  686 +static void tsc210x_timer_tick(void *opaque)
  687 +{
  688 + struct tsc210x_state_s *s = opaque;
  689 +
  690 + /* Timer ticked -- a set of conversions has been finished. */
  691 +
  692 + if (!s->busy)
  693 + return;
  694 +
  695 + s->busy = 0;
  696 + s->dav |= mode_regs[s->function];
  697 + tsc210x_pin_update(s);
  698 +}
  699 +
  700 +static void tsc210x_touchscreen_event(void *opaque,
  701 + int x, int y, int z, int buttons_state)
  702 +{
  703 + struct tsc210x_state_s *s = opaque;
  704 + int p = s->pressure;
  705 +
  706 + if (buttons_state) {
  707 + s->x = x;
  708 + s->y = y;
  709 + }
  710 + s->pressure = !!buttons_state;
  711 +
  712 + /*
  713 + * Note: We would get better responsiveness in the guest by
  714 + * signaling TS events immediately, but for now we simulate
  715 + * the first conversion delay for sake of correctness.
  716 + */
  717 + if (p != s->pressure)
  718 + tsc210x_pin_update(s);
  719 +}
  720 +
  721 +static void tsc210x_save(QEMUFile *f, void *opaque)
  722 +{
  723 + struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
  724 + int64_t now = qemu_get_clock(vm_clock);
  725 + int i;
  726 +
  727 + qemu_put_be16(f, s->x);
  728 + qemu_put_be16(f, s->y);
  729 + qemu_put_byte(f, s->pressure);
  730 +
  731 + qemu_put_byte(f, s->state);
  732 + qemu_put_byte(f, s->page);
  733 + qemu_put_byte(f, s->offset);
  734 + qemu_put_byte(f, s->command);
  735 +
  736 + qemu_put_byte(f, s->irq);
  737 + qemu_put_be16s(f, &s->dav);
  738 +
  739 + qemu_put_timer(f, s->timer);
  740 + qemu_put_byte(f, s->enabled);
  741 + qemu_put_byte(f, s->host_mode);
  742 + qemu_put_byte(f, s->function);
  743 + qemu_put_byte(f, s->nextfunction);
  744 + qemu_put_byte(f, s->precision);
  745 + qemu_put_byte(f, s->nextprecision);
  746 + qemu_put_byte(f, s->filter);
  747 + qemu_put_byte(f, s->pin_func);
  748 + qemu_put_byte(f, s->ref);
  749 + qemu_put_byte(f, s->timing);
  750 + qemu_put_be32(f, s->noise);
  751 +
  752 + qemu_put_be16s(f, &s->audio_ctrl1);
  753 + qemu_put_be16s(f, &s->audio_ctrl2);
  754 + qemu_put_be16s(f, &s->audio_ctrl3);
  755 + qemu_put_be16s(f, &s->pll[0]);
  756 + qemu_put_be16s(f, &s->pll[1]);
  757 + qemu_put_be16s(f, &s->volume);
  758 + qemu_put_be64(f, (uint64_t) (s->volume_change - now));
  759 + qemu_put_be64(f, (uint64_t) (s->powerdown - now));
  760 + qemu_put_byte(f, s->softstep);
  761 + qemu_put_be16s(f, &s->dac_power);
  762 +
  763 + for (i = 0; i < 0x14; i ++)
  764 + qemu_put_be16s(f, &s->filter_data[i]);
  765 +}
  766 +
  767 +static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
  768 +{
  769 + struct tsc210x_state_s *s = (struct tsc210x_state_s *) opaque;
  770 + int64_t now = qemu_get_clock(vm_clock);
  771 + int i;
  772 +
  773 + s->x = qemu_get_be16(f);
  774 + s->y = qemu_get_be16(f);
  775 + s->pressure = qemu_get_byte(f);
  776 +
  777 + s->state = qemu_get_byte(f);
  778 + s->page = qemu_get_byte(f);
  779 + s->offset = qemu_get_byte(f);
  780 + s->command = qemu_get_byte(f);
  781 +
  782 + s->irq = qemu_get_byte(f);
  783 + qemu_get_be16s(f, &s->dav);
  784 +
  785 + qemu_get_timer(f, s->timer);
  786 + s->enabled = qemu_get_byte(f);
  787 + s->host_mode = qemu_get_byte(f);
  788 + s->function = qemu_get_byte(f);
  789 + s->nextfunction = qemu_get_byte(f);
  790 + s->precision = qemu_get_byte(f);
  791 + s->nextprecision = qemu_get_byte(f);
  792 + s->filter = qemu_get_byte(f);
  793 + s->pin_func = qemu_get_byte(f);
  794 + s->ref = qemu_get_byte(f);
  795 + s->timing = qemu_get_byte(f);
  796 + s->noise = qemu_get_be32(f);
  797 +
  798 + qemu_get_be16s(f, &s->audio_ctrl1);
  799 + qemu_get_be16s(f, &s->audio_ctrl2);
  800 + qemu_get_be16s(f, &s->audio_ctrl3);
  801 + qemu_get_be16s(f, &s->pll[0]);
  802 + qemu_get_be16s(f, &s->pll[1]);
  803 + qemu_get_be16s(f, &s->volume);
  804 + s->volume_change = (int64_t) qemu_get_be64(f) + now;
  805 + s->powerdown = (int64_t) qemu_get_be64(f) + now;
  806 + s->softstep = qemu_get_byte(f);
  807 + qemu_get_be16s(f, &s->dac_power);
  808 +
  809 + for (i = 0; i < 0x14; i ++)
  810 + qemu_get_be16s(f, &s->filter_data[i]);
  811 +
  812 + s->busy = qemu_timer_pending(s->timer);
  813 + qemu_set_irq(s->pint, s->irq);
  814 +
  815 + return 0;
  816 +}
  817 +
  818 +static int tsc2102_iid = 0;
  819 +
  820 +struct uwire_slave_s *tsc2102_init(qemu_irq pint)
  821 +{
  822 + struct tsc210x_state_s *s;
  823 +
  824 + s = (struct tsc210x_state_s *)
  825 + qemu_mallocz(sizeof(struct tsc210x_state_s));
  826 + memset(s, 0, sizeof(struct tsc210x_state_s));
  827 + s->x = 160;
  828 + s->y = 160;
  829 + s->pressure = 0;
  830 + s->precision = s->nextprecision = 0;
  831 + s->timer = qemu_new_timer(vm_clock, tsc210x_timer_tick, s);
  832 + s->pint = pint;
  833 +
  834 + s->chip.opaque = s;
  835 + s->chip.send = (void *) tsc210x_write;
  836 + s->chip.receive = (void *) tsc210x_read;
  837 +
  838 + tsc210x_reset(s);
  839 +
  840 + qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1,
  841 + "QEMU TSC2102-driven Touchscreen");
  842 +
  843 + qemu_register_reset((void *) tsc210x_reset, s);
  844 + register_savevm("tsc2102", tsc2102_iid ++, 0,
  845 + tsc210x_save, tsc210x_load, s);
  846 +
  847 + return &s->chip;
  848 +}
... ...
... ... @@ -1663,6 +1663,9 @@ void qemu_get_ptimer(QEMUFile *f, ptimer_state *s);
1663 1663  
1664 1664 #include "hw/omap.h"
1665 1665  
  1666 +/* tsc210x.c */
  1667 +struct uwire_slave_s *tsc2102_init(qemu_irq pint);
  1668 +
1666 1669 /* mcf_uart.c */
1667 1670 uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr);
1668 1671 void mcf_uart_write(void *opaque, target_phys_addr_t addr, uint32_t val);
... ...