aboutsummaryrefslogtreecommitdiff
path: root/hw/display/sii9022.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-03-01 15:37:31 +0000
committerPeter Maydell <peter.maydell@linaro.org>2018-03-01 15:37:31 +0000
commit9db0855e8501365334e859370800c240d25322a2 (patch)
treebd4a8f0576258a43bf446035c26f9e5c1b1d2c40 /hw/display/sii9022.c
parent8cb340c613ee3e626b070e0429c589f8a60ac657 (diff)
parentc22e580c2ad1cccef582e1490e732f254d4ac064 (diff)
downloadqemu-9db0855e8501365334e859370800c240d25322a2.zip
qemu-9db0855e8501365334e859370800c240d25322a2.tar.gz
qemu-9db0855e8501365334e859370800c240d25322a2.tar.bz2
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180301' into staging
target-arm queue: * update MAINTAINERS for Alistair's new email address * add Arm v8.2 FP16 arithmetic extension for linux-user * implement display connector emulation for vexpress board * xilinx_spips: Enable only two slaves when reading/writing with stripe * xilinx_spips: Use 8 dummy cycles with the QIOR/QIOR4 commands * hw: register: Run post_write hook on reset # gpg: Signature made Thu 01 Mar 2018 11:22:46 GMT # gpg: using RSA key 3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20180301: (42 commits) MAINTAINERS: Update my email address linux-user: Report AArch64 FP16 support via hwcap bits target/arm: Enable ARM_V8_FP16 feature bit for the AArch64 "any" CPU arm/translate-a64: add all single op FP16 to handle_fp_1src_half arm/translate-a64: implement simd_scalar_three_reg_same_fp16 arm/translate-a64: add all FP16 ops in simd_scalar_pairwise arm/translate-a64: add FP16 FMOV to simd_mod_imm arm/translate-a64: add FP16 FRSQRTE to simd_two_reg_misc_fp16 arm/helper.c: re-factor rsqrte and add rsqrte_f16 arm/translate-a64: add FP16 FSQRT to simd_two_reg_misc_fp16 arm/translate-a64: add FP16 FRCPX to simd_two_reg_misc_fp16 arm/translate-a64: add FP16 FRECPE arm/helper.c: re-factor recpe and add recepe_f16 arm/translate-a64: add FP16 FNEG/FABS to simd_two_reg_misc_fp16 arm/translate-a64: add FP16 SCVTF/UCVFT to simd_two_reg_misc_fp16 arm/translate-a64: add FP16 FCMxx (zero) to simd_two_reg_misc_fp16 arm/translate-a64: add FCVTxx to simd_two_reg_misc_fp16 arm/translate-a64: add FP16 FPRINTx to simd_two_reg_misc_fp16 arm/translate-a64: initial decode for simd_two_reg_misc_fp16 arm/translate-a64: add FP16 x2 ops for simd_indexed ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/display/sii9022.c')
-rw-r--r--hw/display/sii9022.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/hw/display/sii9022.c b/hw/display/sii9022.c
new file mode 100644
index 0000000..eaf11a6
--- /dev/null
+++ b/hw/display/sii9022.c
@@ -0,0 +1,191 @@
+/*
+ * 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;
+ s->ddc_req = false;
+ s->ddc_skip_finish = false;
+ s->ddc = 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)