From patchwork Tue Feb 27 10:49:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 10244765 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id CFDF960208 for ; Tue, 27 Feb 2018 10:50:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C3ED62022B for ; Tue, 27 Feb 2018 10:50:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B8D17286E3; Tue, 27 Feb 2018 10:50:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id DAAD52022B for ; Tue, 27 Feb 2018 10:50:47 +0000 (UTC) Received: from localhost ([::1]:36174 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqcqN-0007Up-2R for patchwork-qemu-devel@patchwork.kernel.org; Tue, 27 Feb 2018 05:50:47 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54773) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqcow-0006MO-H9 for qemu-devel@nongnu.org; Tue, 27 Feb 2018 05:49:24 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eqcov-0004DW-81 for qemu-devel@nongnu.org; Tue, 27 Feb 2018 05:49:18 -0500 Received: from mail-lf0-x234.google.com ([2a00:1450:4010:c07::234]:33090) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eqcou-0004Cw-Sf for qemu-devel@nongnu.org; Tue, 27 Feb 2018 05:49:17 -0500 Received: by mail-lf0-x234.google.com with SMTP id o145so23588954lff.0 for ; Tue, 27 Feb 2018 02:49:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=zj13AenJ6oUb9CSbGAylVOy8XTzH/fVL67zcJq0NUxg=; b=Ql296rb+EuV/P1JhqDrKkfDVNKDJ1o++THP9/0rFbU+X/hwQi244cNukzaymcZtv+K kBZv3gGOHi5JIr6EWS8L/7dLrE5OGVDlmSs2Fupa2b+9XYIRxrXmqo1laua+QkyE9WoP Ej3Ro1bIJvjiK5cUIaDQ309yiPUbq7YLuF2Mc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=zj13AenJ6oUb9CSbGAylVOy8XTzH/fVL67zcJq0NUxg=; b=eCP4AWKj4iRLZu1Z2Zn/AmlwcHllBJ7kDNTvP6q0HEII++5Hpyq05kb/Hm01xjPYpO +B/l/+kwxjBN2LK6jXnao2YC+b8XpGKUbu6pJD5WJcHVLRWpNn5MXX+Wy0pCcWduYqma 5EPpGn3eKeSwwLmjruPWTA4Md5f9EknLFlBFH1ebPLKfwA5hXxo/z8U+tjfLzgtoCx1w EJdGzG86M73m0X3zYdkxEYzdMFAW80uxP0AK2hb5sbHgj6jGv4ueaX1UWH47zNBACM1i ySSz9pSN0hCjSXPunqZO2tUq/9COx3HMbz1Bh1N2mx4SwIpgDHXkTgFMLm8YCQ5ImwmH 7/Cw== X-Gm-Message-State: APf1xPD/in7HZ4b7wfyRkm3pxcje4jRmVRnytAlM1x2jx2PbHmqGsBRj pjTn0uhk7j14UHiKR+R9/V1Q62EXKGI= X-Google-Smtp-Source: AG47ELudHEaUE4XXp1OOBMRmXRUUwB+dE8gJLcA0F46lTrc8G0cwx5dFJEkMpODemn1D2RvQ4uu9OQ== X-Received: by 10.25.206.143 with SMTP id e137mr10463329lfg.95.1519728555086; Tue, 27 Feb 2018 02:49:15 -0800 (PST) Received: from genomnajs.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id 74sm2484148ljq.32.2018.02.27.02.49.13 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 27 Feb 2018 02:49:14 -0800 (PST) From: Linus Walleij To: qemu-devel@nongnu.org, Peter Maydell Date: Tue, 27 Feb 2018 11:49:02 +0100 Message-Id: <20180227104903.21353-5-linus.walleij@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180227104903.21353-1-linus.walleij@linaro.org> References: <20180227104903.21353-1-linus.walleij@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4010:c07::234 Subject: [Qemu-devel] [PATCH 4/5] hw/sii9022: Add support for Silicon Image SII9022 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Corey Minyard , Linus Walleij , qemu-arm@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP This adds support for emulating the Silicon Image SII9022 DVI/HDMI bridge. It's not very clever right now, it just acknowledges the switch into DDC I2C mode and back. Combining this with the existing DDC I2C emulation gives the right behavior on the Versatile Express emulation passing through the QEMU EDID to the emulated platform. Cc: Peter Maydell Signed-off-by: Linus Walleij --- ChangeLog v1->v2: - Update license to GPLv2 or later + SPDX identifier - Instantiate the DDC I2C as part of the class realization so we do not need to add the DDC "on the side" in machines using SII9022. - Switch to using trace events instead of debug prints. --- hw/display/Makefile.objs | 1 + hw/display/sii9022.c | 188 +++++++++++++++++++++++++++++++++++++++++++++++ hw/display/trace-events | 5 ++ 3 files changed, 194 insertions(+) create mode 100644 hw/display/sii9022.c diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs index d3a4cb396eb9..3c7c75b94da5 100644 --- a/hw/display/Makefile.objs +++ b/hw/display/Makefile.objs @@ -3,6 +3,7 @@ common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o common-obj-$(CONFIG_G364FB) += g364fb.o common-obj-$(CONFIG_JAZZ_LED) += jazz_led.o common-obj-$(CONFIG_PL110) += pl110.o +common-obj-$(CONFIG_SII9022) += sii9022.o common-obj-$(CONFIG_SSD0303) += ssd0303.o common-obj-$(CONFIG_SSD0323) += ssd0323.o common-obj-$(CONFIG_XEN) += xenfb.o diff --git a/hw/display/sii9022.c b/hw/display/sii9022.c new file mode 100644 index 000000000000..b019ac0ca880 --- /dev/null +++ b/hw/display/sii9022.c @@ -0,0 +1,188 @@ +/* + * Silicon Image SiI9022 + * + * This is a pretty hollow emulation: all we do is acknowledge that we + * exist (chip ID) and confirm that we get switched over into DDC mode + * so the emulated host can proceed to read out EDID data. All subsequent + * set-up of connectors etc will be acknowledged and ignored. + * + * Copyright (C) 2018 Linus Walleij + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "hw/i2c/i2c.h" +#include "hw/i2c/i2c-ddc.h" +#include "trace.h" + +#define SII9022_SYS_CTRL_DATA 0x1a +#define SII9022_SYS_CTRL_PWR_DWN 0x10 +#define SII9022_SYS_CTRL_AV_MUTE 0x08 +#define SII9022_SYS_CTRL_DDC_BUS_REQ 0x04 +#define SII9022_SYS_CTRL_DDC_BUS_GRTD 0x02 +#define SII9022_SYS_CTRL_OUTPUT_MODE 0x01 +#define SII9022_SYS_CTRL_OUTPUT_HDMI 1 +#define SII9022_SYS_CTRL_OUTPUT_DVI 0 +#define SII9022_REG_CHIPID 0x1b +#define SII9022_INT_ENABLE 0x3c +#define SII9022_INT_STATUS 0x3d +#define SII9022_INT_STATUS_HOTPLUG 0x01; +#define SII9022_INT_STATUS_PLUGGED 0x04; + +#define TYPE_SII9022 "sii9022" +#define SII9022(obj) OBJECT_CHECK(sii9022_state, (obj), TYPE_SII9022) + +typedef struct sii9022_state { + I2CSlave parent_obj; + uint8_t ptr; + bool addr_byte; + bool ddc_req; + bool ddc_skip_finish; + bool ddc; +} sii9022_state; + +static const VMStateDescription vmstate_sii9022 = { + .name = "sii9022", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_I2C_SLAVE(parent_obj, sii9022_state), + VMSTATE_UINT8(ptr, sii9022_state), + VMSTATE_BOOL(addr_byte, sii9022_state), + VMSTATE_BOOL(ddc_req, sii9022_state), + VMSTATE_BOOL(ddc_skip_finish, sii9022_state), + VMSTATE_BOOL(ddc, sii9022_state), + VMSTATE_END_OF_LIST() + } +}; + +static int sii9022_event(I2CSlave *i2c, enum i2c_event event) +{ + sii9022_state *s = SII9022(i2c); + + switch (event) { + case I2C_START_SEND: + s->addr_byte = true; + break; + case I2C_START_RECV: + break; + case I2C_FINISH: + break; + case I2C_NACK: + break; + } + + return 0; +} + +static int sii9022_rx(I2CSlave *i2c) +{ + sii9022_state *s = SII9022(i2c); + uint8_t res = 0x00; + + switch (s->ptr) { + case SII9022_SYS_CTRL_DATA: + if (s->ddc_req) { + /* Acknowledge DDC bus request */ + res = SII9022_SYS_CTRL_DDC_BUS_GRTD | SII9022_SYS_CTRL_DDC_BUS_REQ; + } + break; + case SII9022_REG_CHIPID: + res = 0xb0; + break; + case SII9022_INT_STATUS: + /* Something is cold-plugged in, no interrupts */ + res = SII9022_INT_STATUS_PLUGGED; + break; + default: + break; + } + + trace_sii9022_read_reg(s->ptr, res); + s->ptr++; + + return res; +} + +static int sii9022_tx(I2CSlave *i2c, uint8_t data) +{ + sii9022_state *s = SII9022(i2c); + + if (s->addr_byte) { + s->ptr = data; + s->addr_byte = false; + return 0; + } + + switch (s->ptr) { + case SII9022_SYS_CTRL_DATA: + if (data & SII9022_SYS_CTRL_DDC_BUS_REQ) { + s->ddc_req = true; + if (data & SII9022_SYS_CTRL_DDC_BUS_GRTD) { + s->ddc = true; + /* Skip this finish since we just switched to DDC */ + s->ddc_skip_finish = true; + trace_sii9022_switch_mode("DDC"); + } + } else { + s->ddc_req = false; + s->ddc = false; + trace_sii9022_switch_mode("normal"); + } + break; + default: + break; + } + + trace_sii9022_write_reg(s->ptr, data); + s->ptr++; + + return 0; +} + +static void sii9022_reset(DeviceState *dev) +{ + sii9022_state *s = SII9022(dev); + + s->ptr = 0; + s->addr_byte = false; +} + +static void sii9022_realize(DeviceState *dev, Error **errp) +{ + I2CBus *bus; + + bus = I2C_BUS(qdev_get_parent_bus(dev)); + i2c_create_slave(bus, TYPE_I2CDDC, 0x50); +} + +static void sii9022_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); + + k->event = sii9022_event; + k->recv = sii9022_rx; + k->send = sii9022_tx; + dc->reset = sii9022_reset; + dc->realize = sii9022_realize; + dc->vmsd = &vmstate_sii9022; +} + +static const TypeInfo sii9022_info = { + .name = TYPE_SII9022, + .parent = TYPE_I2C_SLAVE, + .instance_size = sizeof(sii9022_state), + .class_init = sii9022_class_init, +}; + +static void sii9022_register_types(void) +{ + type_register_static(&sii9022_info); +} + +type_init(sii9022_register_types) diff --git a/hw/display/trace-events b/hw/display/trace-events index da498c1def45..5a48c6cb6a6d 100644 --- a/hw/display/trace-events +++ b/hw/display/trace-events @@ -132,3 +132,8 @@ vga_cirrus_read_io(uint32_t addr, uint32_t val) "addr 0x%x, val 0x%x" vga_cirrus_write_io(uint32_t addr, uint32_t val) "addr 0x%x, val 0x%x" vga_cirrus_read_blt(uint32_t offset, uint32_t val) "offset 0x%x, val 0x%x" vga_cirrus_write_blt(uint32_t offset, uint32_t val) "offset 0x%x, val 0x%x" + +# hw/display/sii9022.c +sii9022_read_reg(uint8_t addr, uint8_t val) "addr 0x%02x, val 0x%02x" +sii9022_write_reg(uint8_t addr, uint8_t val) "addr 0x%02x, val 0x%02x" +sii9022_switch_mode(const char *mode) "mode: %s"