From nobody Sun Nov 24 03:25:03 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1727801084; cv=none; d=zohomail.com; s=zohoarc; b=e8HfYjke2a1M0JYeUCX0ATiqRXc3dKymZiaJpNi/20yMo25VRo5xUmUEXfXjGlQ/76JqoHjK5du4F3sZuRbfQ2t16+d6kTFEw6QCgH5+q+lpNBx/9YoTEyR8drCDlRXTOMLMabHVChjcNZuGFAwCEbcpg18vOMtB8jHpylFVHTE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1727801084; h=Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To:Cc; bh=zyKGrOkfxY2cUy9ff0r4kHizZYPgrAw+Ie4/0rLLeaY=; b=fXC1yAmYZVesWA1STlbl30xYxIt+VcCtBTu26wW0RM9/hPQkMKxMgOpUiaPsyo1WJL1Ma3lgJBfF8nygmSv10BTVrP1ZE3AlwVz+GVgsN5betXfBIlZ9VdNEsbckFfJtth/m9X2UlcYUOCZMBdgxA01jEUshR/YFTehfJ4d5+8Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1727801084090756.5681350726245; Tue, 1 Oct 2024 09:44:44 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1svfuy-00061n-LZ; Tue, 01 Oct 2024 12:40:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1svfub-0005aC-Ct for qemu-devel@nongnu.org; Tue, 01 Oct 2024 12:39:45 -0400 Received: from mail-wm1-x334.google.com ([2a00:1450:4864:20::334]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1svfuU-000660-PW for qemu-devel@nongnu.org; Tue, 01 Oct 2024 12:39:45 -0400 Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-42cafda818aso55227295e9.2 for ; Tue, 01 Oct 2024 09:39:38 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-37cd56e6547sm12243771f8f.58.2024.10.01.09.39.36 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Oct 2024 09:39:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1727800777; x=1728405577; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=zyKGrOkfxY2cUy9ff0r4kHizZYPgrAw+Ie4/0rLLeaY=; b=Sa7pt0yilpPSYQwISda9gitzzHAb9T6xxPTrjxCJogibZddequAOPOZY4qFcES/M3t kbJj/0zlClJc5Tznw8lEJaTQs3E2IN3kdlnNZf1x790yw9O8qol4nN7D3nmvERpSKiPF oSFs5YrAylZ4sNODQhntgUfcM/Q3BtDj6Ccnm1qcnm/Pt1To/Nz3DtJw2RRv/5EyjnQY x8vjCnsT7fGv76MUzvj5q9rJTOBUD+68d1fgjI+fuQy3ssRMQEX5i1PXrGN+bjdoSV17 BBcouupGcG77RKP4FBCpIuvsWlaz1TsTBEzGTpAqqwgIPGULi2xBPyoHlY9HuKzmTZJO WbMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727800777; x=1728405577; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zyKGrOkfxY2cUy9ff0r4kHizZYPgrAw+Ie4/0rLLeaY=; b=du2oc/GsnJ2nKxNFaNiIXWnqYMEmYL6f/yd0Mk059Fks5gF7I/Bieth6qMk3rekn9B nrxfaFsXej89PVU+yZIxyhmyQFtIzgTzVfCA1CLmy1L9qUgXpQUYvzmQgq0FRWjWIqyd Sf+F9q2qxKYymBN/a/YcgRRh93yBp++BKIi5nNto4oebJ1Yi1nhHoN54TrusqSvP8Qur t739Ca9p8Puv8teIZnUxKvC1M5wRDlMq7A4rXdBO3y/2/ZUEUm/nvjmnBxo3BBrg8ps/ /vKy8K8UCtI67NdPY+qFTI9mmktPwKzpfBBQZuGf3bB5tlK4ElpkN5EASj7tZJlivvoe 8GCQ== X-Gm-Message-State: AOJu0Yx+IT4OFXEFKhSU7qsi1B+jf6ZLUp8a4+9cUiOAQDEKuLrVYHZO H45MG/jEoMTZMll1LnkqH+wQXOyoK8cf5kPoH+G5kLnzqtimpNeD7f/qyaReoHNbuRxkHfYdCEn M X-Google-Smtp-Source: AGHT+IG/vZ4NQDNWU5RR8y3GC/nMAwBuUw84z/1TiIYQ4W1iCj0ic2e1lb4uYqqOT5VThL8q6ClZVA== X-Received: by 2002:a5d:4ace:0:b0:374:c7a3:3349 with SMTP id ffacd0b85a97d-37cfba121edmr112297f8f.51.1727800776923; Tue, 01 Oct 2024 09:39:36 -0700 (PDT) From: Peter Maydell To: qemu-devel@nongnu.org Subject: [PULL 32/54] hw/input: Remove tsc210x device Date: Tue, 1 Oct 2024 17:38:56 +0100 Message-Id: <20241001163918.1275441-33-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241001163918.1275441-1-peter.maydell@linaro.org> References: <20241001163918.1275441-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::334; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x334.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1727801085226116600 Content-Type: text/plain; charset="utf-8" Remove the tsc210x touchscreen controller device, which was only used by the n800 and n810 and cheetah. The uWireSlave struct is still used in omap1.c (at least for compilation purposes -- nothing any longer calls omap_uwire_attach() and so the struct's members will not be used at runtime), so we move it into omap.h so we can delete tsc2xxx.h. Signed-off-by: Peter Maydell Reviewed-by: Thomas Huth Message-id: 20240903160751.4100218-30-peter.maydell@linaro.org --- MAINTAINERS | 2 - include/hw/arm/omap.h | 7 +- include/hw/input/tsc2xxx.h | 36 -- hw/input/tsc210x.c | 1241 ------------------------------------ hw/input/Kconfig | 3 - hw/input/meson.build | 1 - 6 files changed, 6 insertions(+), 1284 deletions(-) delete mode 100644 include/hw/input/tsc2xxx.h delete mode 100644 hw/input/tsc210x.c diff --git a/MAINTAINERS b/MAINTAINERS index 2569bf47a2c..a63df2712ed 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -875,10 +875,8 @@ M: Peter Maydell L: qemu-arm@nongnu.org S: Odd Fixes F: hw/input/lm832x.c -F: hw/input/tsc210x.c F: hw/rtc/twl92230.c F: include/hw/input/lm832x.h -F: include/hw/input/tsc2xxx.h =20 Raspberry Pi M: Peter Maydell diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h index 40ee8ea9e56..0ca7c9604e7 100644 --- a/include/hw/arm/omap.h +++ b/include/hw/arm/omap.h @@ -21,7 +21,6 @@ #define HW_ARM_OMAP_H =20 #include "exec/memory.h" -#include "hw/input/tsc2xxx.h" #include "target/arm/cpu-qom.h" #include "qemu/log.h" #include "qom/object.h" @@ -730,6 +729,12 @@ qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s); void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler= ); void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down); =20 +typedef struct uWireSlave { + uint16_t (*receive)(void *opaque); + void (*send)(void *opaque, uint16_t data); + void *opaque; +} uWireSlave; + struct omap_uwire_s; void omap_uwire_attach(struct omap_uwire_s *s, uWireSlave *slave, int chipselect); diff --git a/include/hw/input/tsc2xxx.h b/include/hw/input/tsc2xxx.h deleted file mode 100644 index dcd4fa7faed..00000000000 --- a/include/hw/input/tsc2xxx.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * TI touchscreen controller - * - * Copyright (c) 2006 Andrzej Zaborowski - * Copyright (C) 2008 Nokia Corporation - * - * This work is licensed under the terms of the GNU GPL, version 2 or late= r. - * See the COPYING file in the top-level directory. - */ - -#ifndef HW_INPUT_TSC2XXX_H -#define HW_INPUT_TSC2XXX_H - -typedef struct MouseTransformInfo { - /* Touchscreen resolution */ - int x; - int y; - /* Calibration values as used/generated by tslib */ - int a[7]; -} MouseTransformInfo; - -typedef struct uWireSlave { - uint16_t (*receive)(void *opaque); - void (*send)(void *opaque, uint16_t data); - void *opaque; -} uWireSlave; - -/* tsc210x.c */ -uWireSlave *tsc2102_init(qemu_irq pint); -uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav); -I2SCodec *tsc210x_codec(uWireSlave *chip); -uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len); -void tsc210x_set_transform(uWireSlave *chip, const MouseTransformInfo *inf= o); -void tsc210x_key_event(uWireSlave *chip, int key, int down); - -#endif diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c deleted file mode 100644 index c4e32c7a42f..00000000000 --- a/hw/input/tsc210x.c +++ /dev/null @@ -1,1241 +0,0 @@ -/* - * TI TSC2102 (touchscreen/sensors/audio controller) emulator. - * TI TSC2301 (touchscreen/sensors/keypad). - * - * Copyright (c) 2006 Andrzej Zaborowski - * Copyright (C) 2008 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * 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, see . - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "audio/audio.h" -#include "qemu/timer.h" -#include "qemu/log.h" -#include "sysemu/reset.h" -#include "ui/console.h" -#include "hw/arm/omap.h" /* For I2SCodec */ -#include "hw/boards.h" /* for current_machine */ -#include "hw/input/tsc2xxx.h" -#include "hw/irq.h" -#include "migration/vmstate.h" -#include "qapi/error.h" - -#define TSC_DATA_REGISTERS_PAGE 0x0 -#define TSC_CONTROL_REGISTERS_PAGE 0x1 -#define TSC_AUDIO_REGISTERS_PAGE 0x2 - -#define TSC_VERBOSE - -#define TSC_CUT_RESOLUTION(value, p) ((value) >> (16 - resolution[p])) - -typedef struct { - qemu_irq pint; - qemu_irq kbint; - qemu_irq davint; - QEMUTimer *timer; - QEMUSoundCard card; - uWireSlave chip; - I2SCodec codec; - uint8_t in_fifo[16384]; - uint8_t out_fifo[16384]; - uint16_t model; - - int32_t x, y; - bool pressure; - - uint8_t page, offset; - uint16_t dav; - - bool state; - bool irq; - bool command; - bool busy; - bool enabled; - bool host_mode; - uint8_t function, nextfunction; - uint8_t precision, nextprecision; - uint8_t filter; - uint8_t pin_func; - uint8_t ref; - uint8_t timing; - uint8_t noise; - - uint16_t audio_ctrl1; - uint16_t audio_ctrl2; - uint16_t audio_ctrl3; - uint16_t pll[3]; - uint16_t volume; - int64_t volume_change; - bool softstep; - uint16_t dac_power; - int64_t powerdown; - uint16_t filter_data[0x14]; - - const char *name; - SWVoiceIn *adc_voice[1]; - SWVoiceOut *dac_voice[1]; - int i2s_rx_rate; - int i2s_tx_rate; - - int tr[8]; - - struct { - uint16_t down; - uint16_t mask; - int scan; - int debounce; - int mode; - int intr; - } kb; - int64_t now; /* Time at migration */ -} TSC210xState; - -static const int resolution[4] =3D { 12, 8, 10, 12 }; - -#define TSC_MODE_NO_SCAN 0x0 -#define TSC_MODE_XY_SCAN 0x1 -#define TSC_MODE_XYZ_SCAN 0x2 -#define TSC_MODE_X 0x3 -#define TSC_MODE_Y 0x4 -#define TSC_MODE_Z 0x5 -#define TSC_MODE_BAT1 0x6 -#define TSC_MODE_BAT2 0x7 -#define TSC_MODE_AUX 0x8 -#define TSC_MODE_AUX_SCAN 0x9 -#define TSC_MODE_TEMP1 0xa -#define TSC_MODE_PORT_SCAN 0xb -#define TSC_MODE_TEMP2 0xc -#define TSC_MODE_XX_DRV 0xd -#define TSC_MODE_YY_DRV 0xe -#define TSC_MODE_YX_DRV 0xf - -static const uint16_t mode_regs[16] =3D { - 0x0000, /* No scan */ - 0x0600, /* X, Y scan */ - 0x0780, /* X, Y, Z scan */ - 0x0400, /* X */ - 0x0200, /* Y */ - 0x0180, /* Z */ - 0x0040, /* BAT1 */ - 0x0030, /* BAT2 */ - 0x0010, /* AUX */ - 0x0010, /* AUX scan */ - 0x0004, /* TEMP1 */ - 0x0070, /* Port scan */ - 0x0002, /* TEMP2 */ - 0x0000, /* X+, X- drivers */ - 0x0000, /* Y+, Y- drivers */ - 0x0000, /* Y+, X- drivers */ -}; - -#define X_TRANSFORM(s) \ - ((s->y * s->tr[0] - s->x * s->tr[1]) / s->tr[2] + s->tr[3]) -#define Y_TRANSFORM(s) \ - ((s->y * s->tr[4] - s->x * s->tr[5]) / s->tr[6] + s->tr[7]) -#define Z1_TRANSFORM(s) \ - ((400 - ((s)->x >> 7) + ((s)->pressure << 10)) << 4) -#define Z2_TRANSFORM(s) \ - ((4000 + ((s)->y >> 7) - ((s)->pressure << 10)) << 4) - -#define BAT1_VAL 0x8660 -#define BAT2_VAL 0x0000 -#define AUX1_VAL 0x35c0 -#define AUX2_VAL 0xffff -#define TEMP1_VAL 0x8c70 -#define TEMP2_VAL 0xa5b0 - -#define TSC_POWEROFF_DELAY 50 -#define TSC_SOFTSTEP_DELAY 50 - -static void tsc210x_reset(TSC210xState *s) -{ - s->state =3D false; - s->pin_func =3D 2; - s->enabled =3D false; - s->busy =3D false; - s->nextfunction =3D 0; - s->ref =3D 0; - s->timing =3D 0; - s->irq =3D false; - s->dav =3D 0; - - s->audio_ctrl1 =3D 0x0000; - s->audio_ctrl2 =3D 0x4410; - s->audio_ctrl3 =3D 0x0000; - s->pll[0] =3D 0x1004; - s->pll[1] =3D 0x0000; - s->pll[2] =3D 0x1fff; - s->volume =3D 0xffff; - s->dac_power =3D 0x8540; - s->softstep =3D true; - s->volume_change =3D 0; - s->powerdown =3D 0; - s->filter_data[0x00] =3D 0x6be3; - s->filter_data[0x01] =3D 0x9666; - s->filter_data[0x02] =3D 0x675d; - s->filter_data[0x03] =3D 0x6be3; - s->filter_data[0x04] =3D 0x9666; - s->filter_data[0x05] =3D 0x675d; - s->filter_data[0x06] =3D 0x7d83; - s->filter_data[0x07] =3D 0x84ee; - s->filter_data[0x08] =3D 0x7d83; - s->filter_data[0x09] =3D 0x84ee; - s->filter_data[0x0a] =3D 0x6be3; - s->filter_data[0x0b] =3D 0x9666; - s->filter_data[0x0c] =3D 0x675d; - s->filter_data[0x0d] =3D 0x6be3; - s->filter_data[0x0e] =3D 0x9666; - s->filter_data[0x0f] =3D 0x675d; - s->filter_data[0x10] =3D 0x7d83; - s->filter_data[0x11] =3D 0x84ee; - s->filter_data[0x12] =3D 0x7d83; - s->filter_data[0x13] =3D 0x84ee; - - s->i2s_tx_rate =3D 0; - s->i2s_rx_rate =3D 0; - - s->kb.scan =3D 1; - s->kb.debounce =3D 0; - s->kb.mask =3D 0x0000; - s->kb.mode =3D 3; - s->kb.intr =3D 0; - - qemu_set_irq(s->pint, !s->irq); - qemu_set_irq(s->davint, !s->dav); - qemu_irq_raise(s->kbint); -} - -typedef struct { - int rate; - int dsor; - int fsref; -} TSC210xRateInfo; - -/* { rate, dsor, fsref } */ -static const TSC210xRateInfo tsc2102_rates[] =3D { - /* Fsref / 6.0 */ - { 7350, 63, 1 }, - { 8000, 63, 0 }, - /* Fsref / 6.0 */ - { 7350, 54, 1 }, - { 8000, 54, 0 }, - /* Fsref / 5.0 */ - { 8820, 45, 1 }, - { 9600, 45, 0 }, - /* Fsref / 4.0 */ - { 11025, 36, 1 }, - { 12000, 36, 0 }, - /* Fsref / 3.0 */ - { 14700, 27, 1 }, - { 16000, 27, 0 }, - /* Fsref / 2.0 */ - { 22050, 18, 1 }, - { 24000, 18, 0 }, - /* Fsref / 1.5 */ - { 29400, 9, 1 }, - { 32000, 9, 0 }, - /* Fsref */ - { 44100, 0, 1 }, - { 48000, 0, 0 }, - - { 0, 0, 0 }, -}; - -static inline void tsc210x_out_flush(TSC210xState *s, int len) -{ - uint8_t *data =3D s->codec.out.fifo + s->codec.out.start; - uint8_t *end =3D data + len; - - while (data < end) - data +=3D AUD_write(s->dac_voice[0], data, end - data) ?: (end - d= ata); - - s->codec.out.len -=3D len; - if (s->codec.out.len) - memmove(s->codec.out.fifo, end, s->codec.out.len); - s->codec.out.start =3D 0; -} - -static void tsc210x_audio_out_cb(TSC210xState *s, int free_b) -{ - if (s->codec.out.len >=3D free_b) { - tsc210x_out_flush(s, free_b); - return; - } - - s->codec.out.size =3D MIN(free_b, 16384); - qemu_irq_raise(s->codec.tx_start); -} - -static void tsc2102_audio_rate_update(TSC210xState *s) -{ - const TSC210xRateInfo *rate; - - s->codec.tx_rate =3D 0; - s->codec.rx_rate =3D 0; - if (s->dac_power & (1 << 15)) /* PWDNC */ - return; - - for (rate =3D tsc2102_rates; rate->rate; rate ++) - if (rate->dsor =3D=3D (s->audio_ctrl1 & 0x3f) && /* DACFS */ - rate->fsref =3D=3D ((s->audio_ctrl3 >> 13) & 1))/*= REFFS */ - break; - if (!rate->rate) { - printf("%s: unknown sampling rate configured\n", __func__); - return; - } - - s->codec.tx_rate =3D rate->rate; -} - -static void tsc2102_audio_output_update(TSC210xState *s) -{ - int enable; - struct audsettings fmt; - - if (s->dac_voice[0]) { - tsc210x_out_flush(s, s->codec.out.len); - s->codec.out.size =3D 0; - AUD_set_active_out(s->dac_voice[0], 0); - AUD_close_out(&s->card, s->dac_voice[0]); - s->dac_voice[0] =3D NULL; - } - s->codec.cts =3D 0; - - enable =3D - (~s->dac_power & (1 << 15)) && /* PWDNC */ - (~s->dac_power & (1 << 10)); /* DAPWDN */ - if (!enable || !s->codec.tx_rate) - return; - - /* Force our own sampling rate even in slave DAC mode */ - fmt.endianness =3D 0; - fmt.nchannels =3D 2; - fmt.freq =3D s->codec.tx_rate; - fmt.fmt =3D AUDIO_FORMAT_S16; - - s->dac_voice[0] =3D AUD_open_out(&s->card, s->dac_voice[0], - "tsc2102.sink", s, (void *) tsc210x_audio_out_cb, &fmt= ); - if (s->dac_voice[0]) { - s->codec.cts =3D 1; - AUD_set_active_out(s->dac_voice[0], 1); - } -} - -static uint16_t tsc2102_data_register_read(TSC210xState *s, int reg) -{ - switch (reg) { - case 0x00: /* X */ - s->dav &=3D 0xfbff; - return TSC_CUT_RESOLUTION(X_TRANSFORM(s), s->precision) + - (s->noise & 3); - - case 0x01: /* Y */ - s->noise ++; - s->dav &=3D 0xfdff; - return TSC_CUT_RESOLUTION(Y_TRANSFORM(s), s->precision) ^ - (s->noise & 3); - - case 0x02: /* Z1 */ - s->dav &=3D 0xfeff; - return TSC_CUT_RESOLUTION(Z1_TRANSFORM(s), s->precision) - - (s->noise & 3); - - case 0x03: /* Z2 */ - s->dav &=3D 0xff7f; - return TSC_CUT_RESOLUTION(Z2_TRANSFORM(s), s->precision) | - (s->noise & 3); - - case 0x04: /* KPData */ - if ((s->model & 0xff00) =3D=3D 0x2300) { - if (s->kb.intr && (s->kb.mode & 2)) { - s->kb.intr =3D 0; - qemu_irq_raise(s->kbint); - } - return s->kb.down; - } - - return 0xffff; - - case 0x05: /* BAT1 */ - s->dav &=3D 0xffbf; - return TSC_CUT_RESOLUTION(BAT1_VAL, s->precision) + - (s->noise & 6); - - case 0x06: /* BAT2 */ - s->dav &=3D 0xffdf; - return TSC_CUT_RESOLUTION(BAT2_VAL, s->precision); - - case 0x07: /* AUX1 */ - s->dav &=3D 0xffef; - return TSC_CUT_RESOLUTION(AUX1_VAL, s->precision); - - case 0x08: /* AUX2 */ - s->dav &=3D 0xfff7; - return 0xffff; - - case 0x09: /* TEMP1 */ - s->dav &=3D 0xfffb; - return TSC_CUT_RESOLUTION(TEMP1_VAL, s->precision) - - (s->noise & 5); - - case 0x0a: /* TEMP2 */ - s->dav &=3D 0xfffd; - return TSC_CUT_RESOLUTION(TEMP2_VAL, s->precision) ^ - (s->noise & 3); - - case 0x0b: /* DAC */ - s->dav &=3D 0xfffe; - return 0xffff; - - default: -#ifdef TSC_VERBOSE - fprintf(stderr, "tsc2102_data_register_read: " - "no such register: 0x%02x\n", reg); -#endif - return 0xffff; - } -} - -static uint16_t tsc2102_control_register_read( - TSC210xState *s, int reg) -{ - switch (reg) { - case 0x00: /* TSC ADC */ - return (s->pressure << 15) | ((!s->busy) << 14) | - (s->nextfunction << 10) | (s->nextprecision << 8) | s->fil= ter;=20 - - case 0x01: /* Status / Keypad Control */ - if ((s->model & 0xff00) =3D=3D 0x2100) - return (s->pin_func << 14) | ((!s->enabled) << 13) | - (s->host_mode << 12) | ((!!s->dav) << 11) | s->dav; - else - return (s->kb.intr << 15) | ((s->kb.scan || !s->kb.down) << 14= ) | - (s->kb.debounce << 11); - - case 0x02: /* DAC Control */ - if ((s->model & 0xff00) =3D=3D 0x2300) - return s->dac_power & 0x8000; - else - goto bad_reg; - - case 0x03: /* Reference */ - return s->ref; - - case 0x04: /* Reset */ - return 0xffff; - - case 0x05: /* Configuration */ - return s->timing; - - case 0x06: /* Secondary configuration */ - if ((s->model & 0xff00) =3D=3D 0x2100) - goto bad_reg; - return ((!s->dav) << 15) | ((s->kb.mode & 1) << 14) | s->pll[2]; - - case 0x10: /* Keypad Mask */ - if ((s->model & 0xff00) =3D=3D 0x2100) - goto bad_reg; - return s->kb.mask; - - default: - bad_reg: -#ifdef TSC_VERBOSE - fprintf(stderr, "tsc2102_control_register_read: " - "no such register: 0x%02x\n", reg); -#endif - return 0xffff; - } -} - -static uint16_t tsc2102_audio_register_read(TSC210xState *s, int reg) -{ - int l_ch, r_ch; - uint16_t val; - - switch (reg) { - case 0x00: /* Audio Control 1 */ - return s->audio_ctrl1; - - case 0x01: - return 0xff00; - - case 0x02: /* DAC Volume Control */ - return s->volume; - - case 0x03: - return 0x8b00; - - case 0x04: /* Audio Control 2 */ - l_ch =3D 1; - r_ch =3D 1; - if (s->softstep && !(s->dac_power & (1 << 10))) { - l_ch =3D (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) > - s->volume_change + TSC_SOFTSTEP_DELAY); - r_ch =3D (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) > - s->volume_change + TSC_SOFTSTEP_DELAY); - } - - return s->audio_ctrl2 | (l_ch << 3) | (r_ch << 2); - - case 0x05: /* Stereo DAC Power Control */ - return 0x2aa0 | s->dac_power | - (((s->dac_power & (1 << 10)) && - (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) > - s->powerdown + TSC_POWEROFF_DELAY)) << 6); - - case 0x06: /* Audio Control 3 */ - val =3D s->audio_ctrl3 | 0x0001; - s->audio_ctrl3 &=3D 0xff3f; - return val; - - case 0x07: /* LCH_BASS_BOOST_N0 */ - case 0x08: /* LCH_BASS_BOOST_N1 */ - case 0x09: /* LCH_BASS_BOOST_N2 */ - case 0x0a: /* LCH_BASS_BOOST_N3 */ - case 0x0b: /* LCH_BASS_BOOST_N4 */ - case 0x0c: /* LCH_BASS_BOOST_N5 */ - case 0x0d: /* LCH_BASS_BOOST_D1 */ - case 0x0e: /* LCH_BASS_BOOST_D2 */ - case 0x0f: /* LCH_BASS_BOOST_D4 */ - case 0x10: /* LCH_BASS_BOOST_D5 */ - case 0x11: /* RCH_BASS_BOOST_N0 */ - case 0x12: /* RCH_BASS_BOOST_N1 */ - case 0x13: /* RCH_BASS_BOOST_N2 */ - case 0x14: /* RCH_BASS_BOOST_N3 */ - case 0x15: /* RCH_BASS_BOOST_N4 */ - case 0x16: /* RCH_BASS_BOOST_N5 */ - case 0x17: /* RCH_BASS_BOOST_D1 */ - case 0x18: /* RCH_BASS_BOOST_D2 */ - case 0x19: /* RCH_BASS_BOOST_D4 */ - case 0x1a: /* RCH_BASS_BOOST_D5 */ - return s->filter_data[reg - 0x07]; - - case 0x1b: /* PLL Programmability 1 */ - return s->pll[0]; - - case 0x1c: /* PLL Programmability 2 */ - return s->pll[1]; - - case 0x1d: /* Audio Control 4 */ - return (!s->softstep) << 14; - - default: -#ifdef TSC_VERBOSE - fprintf(stderr, "tsc2102_audio_register_read: " - "no such register: 0x%02x\n", reg); -#endif - return 0xffff; - } -} - -static void tsc2102_data_register_write( - TSC210xState *s, int reg, uint16_t value) -{ - switch (reg) { - case 0x00: /* X */ - case 0x01: /* Y */ - case 0x02: /* Z1 */ - case 0x03: /* Z2 */ - case 0x05: /* BAT1 */ - case 0x06: /* BAT2 */ - case 0x07: /* AUX1 */ - case 0x08: /* AUX2 */ - case 0x09: /* TEMP1 */ - case 0x0a: /* TEMP2 */ - return; - - default: - qemu_log_mask(LOG_GUEST_ERROR, "tsc2102_data_register_write: " - "no such register: 0x%02x\n", reg); - } -} - -static void tsc2102_control_register_write( - TSC210xState *s, int reg, uint16_t value) -{ - switch (reg) { - case 0x00: /* TSC ADC */ - s->host_mode =3D value >> 15; - s->enabled =3D !(value & 0x4000); - if (s->busy && !s->enabled) - timer_del(s->timer); - s->busy =3D s->busy && s->enabled; - s->nextfunction =3D (value >> 10) & 0xf; - s->nextprecision =3D (value >> 8) & 3; - s->filter =3D value & 0xff; - return; - - case 0x01: /* Status / Keypad Control */ - if ((s->model & 0xff00) =3D=3D 0x2100) - s->pin_func =3D value >> 14; - else { - s->kb.scan =3D (value >> 14) & 1; - s->kb.debounce =3D (value >> 11) & 7; - if (s->kb.intr && s->kb.scan) { - s->kb.intr =3D 0; - qemu_irq_raise(s->kbint); - } - } - return; - - case 0x02: /* DAC Control */ - if ((s->model & 0xff00) =3D=3D 0x2300) { - s->dac_power &=3D 0x7fff; - s->dac_power |=3D 0x8000 & value; - } else - goto bad_reg; - break; - - case 0x03: /* Reference */ - s->ref =3D value & 0x1f; - return; - - case 0x04: /* Reset */ - if (value =3D=3D 0xbb00) { - if (s->busy) - timer_del(s->timer); - tsc210x_reset(s); -#ifdef TSC_VERBOSE - } else { - fprintf(stderr, "tsc2102_control_register_write: " - "wrong value written into RESET\n"); -#endif - } - return; - - case 0x05: /* Configuration */ - s->timing =3D value & 0x3f; -#ifdef TSC_VERBOSE - if (value & ~0x3f) - fprintf(stderr, "tsc2102_control_register_write: " - "wrong value written into CONFIG\n"); -#endif - return; - - case 0x06: /* Secondary configuration */ - if ((s->model & 0xff00) =3D=3D 0x2100) - goto bad_reg; - s->kb.mode =3D value >> 14; - s->pll[2] =3D value & 0x3ffff; - return; - - case 0x10: /* Keypad Mask */ - if ((s->model & 0xff00) =3D=3D 0x2100) - goto bad_reg; - s->kb.mask =3D value; - return; - - default: - bad_reg: - qemu_log_mask(LOG_GUEST_ERROR, "tsc2102_control_register_write: " - "no such register: 0x%02x\n", reg); - } -} - -static void tsc2102_audio_register_write( - TSC210xState *s, int reg, uint16_t value) -{ - switch (reg) { - case 0x00: /* Audio Control 1 */ - s->audio_ctrl1 =3D value & 0x0f3f; -#ifdef TSC_VERBOSE - if ((value & ~0x0f3f) || ((value & 7) !=3D ((value >> 3) & 7))) - fprintf(stderr, "tsc2102_audio_register_write: " - "wrong value written into Audio 1\n"); -#endif - tsc2102_audio_rate_update(s); - tsc2102_audio_output_update(s); - return; - - case 0x01: -#ifdef TSC_VERBOSE - if (value !=3D 0xff00) - fprintf(stderr, "tsc2102_audio_register_write: " - "wrong value written into reg 0x01\n"); -#endif - return; - - case 0x02: /* DAC Volume Control */ - s->volume =3D value; - s->volume_change =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - return; - - case 0x03: -#ifdef TSC_VERBOSE - if (value !=3D 0x8b00) - fprintf(stderr, "tsc2102_audio_register_write: " - "wrong value written into reg 0x03\n"); -#endif - return; - - case 0x04: /* Audio Control 2 */ - s->audio_ctrl2 =3D value & 0xf7f2; -#ifdef TSC_VERBOSE - if (value & ~0xf7fd) - fprintf(stderr, "tsc2102_audio_register_write: " - "wrong value written into Audio 2\n"); -#endif - return; - - case 0x05: /* Stereo DAC Power Control */ - if ((value & ~s->dac_power) & (1 << 10)) - s->powerdown =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - - s->dac_power =3D value & 0x9543; -#ifdef TSC_VERBOSE - if ((value & ~0x9543) !=3D 0x2aa0) - fprintf(stderr, "tsc2102_audio_register_write: " - "wrong value written into Power\n"); -#endif - tsc2102_audio_rate_update(s); - tsc2102_audio_output_update(s); - return; - - case 0x06: /* Audio Control 3 */ - s->audio_ctrl3 &=3D 0x00c0; - s->audio_ctrl3 |=3D value & 0xf800; -#ifdef TSC_VERBOSE - if (value & ~0xf8c7) - fprintf(stderr, "tsc2102_audio_register_write: " - "wrong value written into Audio 3\n"); -#endif - tsc2102_audio_output_update(s); - return; - - case 0x07: /* LCH_BASS_BOOST_N0 */ - case 0x08: /* LCH_BASS_BOOST_N1 */ - case 0x09: /* LCH_BASS_BOOST_N2 */ - case 0x0a: /* LCH_BASS_BOOST_N3 */ - case 0x0b: /* LCH_BASS_BOOST_N4 */ - case 0x0c: /* LCH_BASS_BOOST_N5 */ - case 0x0d: /* LCH_BASS_BOOST_D1 */ - case 0x0e: /* LCH_BASS_BOOST_D2 */ - case 0x0f: /* LCH_BASS_BOOST_D4 */ - case 0x10: /* LCH_BASS_BOOST_D5 */ - case 0x11: /* RCH_BASS_BOOST_N0 */ - case 0x12: /* RCH_BASS_BOOST_N1 */ - case 0x13: /* RCH_BASS_BOOST_N2 */ - case 0x14: /* RCH_BASS_BOOST_N3 */ - case 0x15: /* RCH_BASS_BOOST_N4 */ - case 0x16: /* RCH_BASS_BOOST_N5 */ - case 0x17: /* RCH_BASS_BOOST_D1 */ - case 0x18: /* RCH_BASS_BOOST_D2 */ - case 0x19: /* RCH_BASS_BOOST_D4 */ - case 0x1a: /* RCH_BASS_BOOST_D5 */ - s->filter_data[reg - 0x07] =3D value; - return; - - case 0x1b: /* PLL Programmability 1 */ - s->pll[0] =3D value & 0xfffc; -#ifdef TSC_VERBOSE - if (value & ~0xfffc) - fprintf(stderr, "tsc2102_audio_register_write: " - "wrong value written into PLL 1\n"); -#endif - return; - - case 0x1c: /* PLL Programmability 2 */ - s->pll[1] =3D value & 0xfffc; -#ifdef TSC_VERBOSE - if (value & ~0xfffc) - fprintf(stderr, "tsc2102_audio_register_write: " - "wrong value written into PLL 2\n"); -#endif - return; - - case 0x1d: /* Audio Control 4 */ - s->softstep =3D !(value & 0x4000); -#ifdef TSC_VERBOSE - if (value & ~0x4000) - fprintf(stderr, "tsc2102_audio_register_write: " - "wrong value written into Audio 4\n"); -#endif - return; - - default: - qemu_log_mask(LOG_GUEST_ERROR, "tsc2102_audio_register_write: " - "no such register: 0x%02x\n", reg); - } -} - -/* This handles most of the chip logic. */ -static void tsc210x_pin_update(TSC210xState *s) -{ - int64_t expires; - bool pin_state; - - switch (s->pin_func) { - case 0: - pin_state =3D s->pressure; - break; - case 1: - pin_state =3D !!s->dav; - break; - case 2: - default: - pin_state =3D s->pressure && !s->dav; - } - - if (!s->enabled) - pin_state =3D false; - - if (pin_state !=3D s->irq) { - s->irq =3D pin_state; - qemu_set_irq(s->pint, !s->irq); - } - - switch (s->nextfunction) { - case TSC_MODE_XY_SCAN: - case TSC_MODE_XYZ_SCAN: - if (!s->pressure) - return; - break; - - case TSC_MODE_X: - case TSC_MODE_Y: - case TSC_MODE_Z: - if (!s->pressure) - return; - /* Fall through */ - case TSC_MODE_BAT1: - case TSC_MODE_BAT2: - case TSC_MODE_AUX: - case TSC_MODE_TEMP1: - case TSC_MODE_TEMP2: - if (s->dav) - s->enabled =3D false; - break; - - case TSC_MODE_AUX_SCAN: - case TSC_MODE_PORT_SCAN: - break; - - case TSC_MODE_NO_SCAN: - case TSC_MODE_XX_DRV: - case TSC_MODE_YY_DRV: - case TSC_MODE_YX_DRV: - default: - return; - } - - if (!s->enabled || s->busy || s->dav) - return; - - s->busy =3D true; - s->precision =3D s->nextprecision; - s->function =3D s->nextfunction; - expires =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - (NANOSECONDS_PER_SECOND >> 10); - timer_mod(s->timer, expires); -} - -static uint16_t tsc210x_read(TSC210xState *s) -{ - uint16_t ret =3D 0x0000; - - if (!s->command) - fprintf(stderr, "tsc210x_read: SPI underrun!\n"); - - switch (s->page) { - case TSC_DATA_REGISTERS_PAGE: - ret =3D tsc2102_data_register_read(s, s->offset); - if (!s->dav) - qemu_irq_raise(s->davint); - break; - case TSC_CONTROL_REGISTERS_PAGE: - ret =3D tsc2102_control_register_read(s, s->offset); - break; - case TSC_AUDIO_REGISTERS_PAGE: - ret =3D tsc2102_audio_register_read(s, s->offset); - break; - default: - hw_error("tsc210x_read: wrong memory page\n"); - } - - tsc210x_pin_update(s); - - /* Allow sequential reads. */ - s->offset ++; - s->state =3D false; - return ret; -} - -static void tsc210x_write(TSC210xState *s, uint16_t value) -{ - /* - * This is a two-state state machine for reading - * command and data every second time. - */ - if (!s->state) { - s->command =3D (value >> 15) !=3D 0; - s->page =3D (value >> 11) & 0x0f; - s->offset =3D (value >> 5) & 0x3f; - s->state =3D true; - } else { - if (s->command) - fprintf(stderr, "tsc210x_write: SPI overrun!\n"); - else - switch (s->page) { - case TSC_DATA_REGISTERS_PAGE: - tsc2102_data_register_write(s, s->offset, value); - break; - case TSC_CONTROL_REGISTERS_PAGE: - tsc2102_control_register_write(s, s->offset, value); - break; - case TSC_AUDIO_REGISTERS_PAGE: - tsc2102_audio_register_write(s, s->offset, value); - break; - default: - hw_error("tsc210x_write: wrong memory page\n"); - } - - tsc210x_pin_update(s); - s->state =3D false; - } -} - -uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len) -{ - TSC210xState *s =3D opaque; - uint32_t ret =3D 0; - - if (len !=3D 16) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: bad SPI word width %i\n", __func__, len); - return 0; - } - - /* TODO: sequential reads etc - how do we make sure the host doesn't - * unintentionally read out a conversion result from a register while - * transmitting the command word of the next command? */ - if (!value || (s->state && s->command)) - ret =3D tsc210x_read(s); - if (value || (s->state && !s->command)) - tsc210x_write(s, value); - - return ret; -} - -static void tsc210x_timer_tick(void *opaque) -{ - TSC210xState *s =3D opaque; - - /* Timer ticked -- a set of conversions has been finished. */ - - if (!s->busy) - return; - - s->busy =3D false; - s->dav |=3D mode_regs[s->function]; - tsc210x_pin_update(s); - qemu_irq_lower(s->davint); -} - -static void tsc210x_touchscreen_event(void *opaque, - int x, int y, int z, int buttons_state) -{ - TSC210xState *s =3D opaque; - int p =3D s->pressure; - - if (buttons_state) { - s->x =3D x; - s->y =3D y; - } - s->pressure =3D !!buttons_state; - - /* - * Note: We would get better responsiveness in the guest by - * signaling TS events immediately, but for now we simulate - * the first conversion delay for sake of correctness. - */ - if (p !=3D s->pressure) - tsc210x_pin_update(s); -} - -static void tsc210x_i2s_swallow(TSC210xState *s) -{ - if (s->dac_voice[0]) - tsc210x_out_flush(s, s->codec.out.len); - else - s->codec.out.len =3D 0; -} - -static void tsc210x_i2s_set_rate(TSC210xState *s, int in, int out) -{ - s->i2s_tx_rate =3D out; - s->i2s_rx_rate =3D in; -} - -static int tsc210x_pre_save(void *opaque) -{ - TSC210xState *s =3D (TSC210xState *) opaque; - s->now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - - return 0; -} - -static int tsc210x_post_load(void *opaque, int version_id) -{ - TSC210xState *s =3D (TSC210xState *) opaque; - int64_t now =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - - if (s->function >=3D ARRAY_SIZE(mode_regs)) { - return -EINVAL; - } - if (s->nextfunction >=3D ARRAY_SIZE(mode_regs)) { - return -EINVAL; - } - if (s->precision >=3D ARRAY_SIZE(resolution)) { - return -EINVAL; - } - if (s->nextprecision >=3D ARRAY_SIZE(resolution)) { - return -EINVAL; - } - - s->volume_change -=3D s->now; - s->volume_change +=3D now; - s->powerdown -=3D s->now; - s->powerdown +=3D now; - - s->busy =3D timer_pending(s->timer); - qemu_set_irq(s->pint, !s->irq); - qemu_set_irq(s->davint, !s->dav); - - return 0; -} - -static const VMStateField vmstatefields_tsc210x[] =3D { - VMSTATE_BOOL(enabled, TSC210xState), - VMSTATE_BOOL(host_mode, TSC210xState), - VMSTATE_BOOL(irq, TSC210xState), - VMSTATE_BOOL(command, TSC210xState), - VMSTATE_BOOL(pressure, TSC210xState), - VMSTATE_BOOL(softstep, TSC210xState), - VMSTATE_BOOL(state, TSC210xState), - VMSTATE_UINT16(dav, TSC210xState), - VMSTATE_INT32(x, TSC210xState), - VMSTATE_INT32(y, TSC210xState), - VMSTATE_UINT8(offset, TSC210xState), - VMSTATE_UINT8(page, TSC210xState), - VMSTATE_UINT8(filter, TSC210xState), - VMSTATE_UINT8(pin_func, TSC210xState), - VMSTATE_UINT8(ref, TSC210xState), - VMSTATE_UINT8(timing, TSC210xState), - VMSTATE_UINT8(noise, TSC210xState), - VMSTATE_UINT8(function, TSC210xState), - VMSTATE_UINT8(nextfunction, TSC210xState), - VMSTATE_UINT8(precision, TSC210xState), - VMSTATE_UINT8(nextprecision, TSC210xState), - VMSTATE_UINT16(audio_ctrl1, TSC210xState), - VMSTATE_UINT16(audio_ctrl2, TSC210xState), - VMSTATE_UINT16(audio_ctrl3, TSC210xState), - VMSTATE_UINT16_ARRAY(pll, TSC210xState, 3), - VMSTATE_UINT16(volume, TSC210xState), - VMSTATE_UINT16(dac_power, TSC210xState), - VMSTATE_INT64(volume_change, TSC210xState), - VMSTATE_INT64(powerdown, TSC210xState), - VMSTATE_INT64(now, TSC210xState), - VMSTATE_UINT16_ARRAY(filter_data, TSC210xState, 0x14), - VMSTATE_TIMER_PTR(timer, TSC210xState), - VMSTATE_END_OF_LIST() -}; - -static const VMStateDescription vmstate_tsc2102 =3D { - .name =3D "tsc2102", - .version_id =3D 1, - .minimum_version_id =3D 1, - .pre_save =3D tsc210x_pre_save, - .post_load =3D tsc210x_post_load, - .fields =3D vmstatefields_tsc210x, -}; - -static const VMStateDescription vmstate_tsc2301 =3D { - .name =3D "tsc2301", - .version_id =3D 1, - .minimum_version_id =3D 1, - .pre_save =3D tsc210x_pre_save, - .post_load =3D tsc210x_post_load, - .fields =3D vmstatefields_tsc210x, -}; - -static void tsc210x_init(TSC210xState *s, - const char *name, - const VMStateDescription *vmsd) -{ - s->tr[0] =3D 0; - s->tr[1] =3D 1; - s->tr[2] =3D 1; - s->tr[3] =3D 0; - s->tr[4] =3D 1; - s->tr[5] =3D 0; - s->tr[6] =3D 1; - s->tr[7] =3D 0; - - s->chip.opaque =3D s; - s->chip.send =3D (void *) tsc210x_write; - s->chip.receive =3D (void *) tsc210x_read; - - s->codec.opaque =3D s; - s->codec.tx_swallow =3D (void *) tsc210x_i2s_swallow; - s->codec.set_rate =3D (void *) tsc210x_i2s_set_rate; - s->codec.in.fifo =3D s->in_fifo; - s->codec.out.fifo =3D s->out_fifo; - - tsc210x_reset(s); - - qemu_add_mouse_event_handler(tsc210x_touchscreen_event, s, 1, name); - - if (current_machine->audiodev) { - s->card.name =3D g_strdup(current_machine->audiodev); - s->card.state =3D audio_state_by_name(s->card.name, &error_fatal); - } - AUD_register_card(s->name, &s->card, &error_fatal); - - qemu_register_reset((void *) tsc210x_reset, s); - vmstate_register(NULL, 0, vmsd, s); -} - -uWireSlave *tsc2102_init(qemu_irq pint) -{ - TSC210xState *s; - - s =3D g_new0(TSC210xState, 1); - s->x =3D 160; - s->y =3D 160; - s->pressure =3D 0; - s->precision =3D s->nextprecision =3D 0; - s->timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, tsc210x_timer_tick, s); - s->pint =3D pint; - s->model =3D 0x2102; - s->name =3D "tsc2102"; - - tsc210x_init(s, "QEMU TSC2102-driven Touchscreen", &vmstate_tsc2102); - - return &s->chip; -} - -uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav) -{ - TSC210xState *s; - - s =3D g_new0(TSC210xState, 1); - s->x =3D 400; - s->y =3D 240; - s->pressure =3D 0; - s->precision =3D s->nextprecision =3D 0; - s->timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, tsc210x_timer_tick, s); - s->pint =3D penirq; - s->kbint =3D kbirq; - s->davint =3D dav; - s->model =3D 0x2301; - s->name =3D "tsc2301"; - - tsc210x_init(s, "QEMU TSC2301-driven Touchscreen", &vmstate_tsc2301); - - return &s->chip; -} - -I2SCodec *tsc210x_codec(uWireSlave *chip) -{ - TSC210xState *s =3D (TSC210xState *) chip->opaque; - - return &s->codec; -} - -/* - * Use tslib generated calibration data to generate ADC input values - * from the touchscreen. Assuming 12-bit precision was used during - * tslib calibration. - */ -void tsc210x_set_transform(uWireSlave *chip, const MouseTransformInfo *inf= o) -{ - TSC210xState *s =3D (TSC210xState *) chip->opaque; -#if 0 - int64_t ltr[8]; - - ltr[0] =3D (int64_t) info->a[1] * info->y; - ltr[1] =3D (int64_t) info->a[4] * info->x; - ltr[2] =3D (int64_t) info->a[1] * info->a[3] - - (int64_t) info->a[4] * info->a[0]; - ltr[3] =3D (int64_t) info->a[2] * info->a[4] - - (int64_t) info->a[5] * info->a[1]; - ltr[4] =3D (int64_t) info->a[0] * info->y; - ltr[5] =3D (int64_t) info->a[3] * info->x; - ltr[6] =3D (int64_t) info->a[4] * info->a[0] - - (int64_t) info->a[1] * info->a[3]; - ltr[7] =3D (int64_t) info->a[2] * info->a[3] - - (int64_t) info->a[5] * info->a[0]; - - /* Avoid integer overflow */ - s->tr[0] =3D ltr[0] >> 11; - s->tr[1] =3D ltr[1] >> 11; - s->tr[2] =3D muldiv64(ltr[2], 1, info->a[6]); - s->tr[3] =3D muldiv64(ltr[3], 1 << 4, ltr[2]); - s->tr[4] =3D ltr[4] >> 11; - s->tr[5] =3D ltr[5] >> 11; - s->tr[6] =3D muldiv64(ltr[6], 1, info->a[6]); - s->tr[7] =3D muldiv64(ltr[7], 1 << 4, ltr[6]); -#else - - /* This version assumes touchscreen X & Y axis are parallel or - * perpendicular to LCD's X & Y axis in some way. */ - if (abs(info->a[0]) > abs(info->a[1])) { - s->tr[0] =3D 0; - s->tr[1] =3D -info->a[6] * info->x; - s->tr[2] =3D info->a[0]; - s->tr[3] =3D -info->a[2] / info->a[0]; - s->tr[4] =3D info->a[6] * info->y; - s->tr[5] =3D 0; - s->tr[6] =3D info->a[4]; - s->tr[7] =3D -info->a[5] / info->a[4]; - } else { - s->tr[0] =3D info->a[6] * info->y; - s->tr[1] =3D 0; - s->tr[2] =3D info->a[1]; - s->tr[3] =3D -info->a[2] / info->a[1]; - s->tr[4] =3D 0; - s->tr[5] =3D -info->a[6] * info->x; - s->tr[6] =3D info->a[3]; - s->tr[7] =3D -info->a[5] / info->a[3]; - } - - s->tr[0] >>=3D 11; - s->tr[1] >>=3D 11; - s->tr[3] <<=3D 4; - s->tr[4] >>=3D 11; - s->tr[5] >>=3D 11; - s->tr[7] <<=3D 4; -#endif -} - -void tsc210x_key_event(uWireSlave *chip, int key, int down) -{ - TSC210xState *s =3D (TSC210xState *) chip->opaque; - - if (down) - s->kb.down |=3D 1 << key; - else - s->kb.down &=3D ~(1 << key); - - if (down && (s->kb.down & ~s->kb.mask) && !s->kb.intr) { - s->kb.intr =3D 1; - qemu_irq_lower(s->kbint); - } else if (s->kb.intr && !(s->kb.down & ~s->kb.mask) && - !(s->kb.mode & 1)) { - s->kb.intr =3D 0; - qemu_irq_raise(s->kbint); - } -} diff --git a/hw/input/Kconfig b/hw/input/Kconfig index 01a64a9aa7e..6f3ffbc5aa1 100644 --- a/hw/input/Kconfig +++ b/hw/input/Kconfig @@ -35,8 +35,5 @@ config VHOST_USER_INPUT default y depends on VIRTIO_INPUT && VHOST_USER =20 -config TSC210X - bool - config LASIPS2 select PS2 diff --git a/hw/input/meson.build b/hw/input/meson.build index 064d1e47802..f12796fb695 100644 --- a/hw/input/meson.build +++ b/hw/input/meson.build @@ -10,5 +10,4 @@ system_ss.add(when: 'CONFIG_VIRTIO_INPUT', if_true: files= ('virtio-input.c')) system_ss.add(when: 'CONFIG_VIRTIO_INPUT', if_true: files('virtio-input-hi= d.c')) system_ss.add(when: 'CONFIG_VIRTIO_INPUT_HOST', if_true: files('virtio-inp= ut-host.c')) =20 -system_ss.add(when: 'CONFIG_TSC210X', if_true: files('tsc210x.c')) system_ss.add(when: 'CONFIG_LASIPS2', if_true: files('lasips2.c')) --=20 2.34.1