1
From 8cd2501518d5ea8a16d3a8e03b1a0e0ecad8426b Mon Sep 17 00:00:00 2001
2
From: Peter Maydell <peter.maydell@linaro.org>
3
Date: Mon, 18 Feb 2013 16:58:33 +0000
4
Subject: [PATCH 56/71] hw/i2c-ddc.c: Implement DDC I2C slave
6
Implement an I2C slave which implements DDC and returns the
7
EDID data for an attached monitor.
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
hw/i2c/Makefile.objs | 1 +
12
hw/i2c/ddc.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++
13
2 files changed, 301 insertions(+)
14
create mode 100644 hw/i2c/ddc.c
16
diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
17
index 648278e..9d984ff 100644
18
--- a/hw/i2c/Makefile.objs
19
+++ b/hw/i2c/Makefile.objs
20
@@ -4,4 +4,5 @@ common-obj-$(CONFIG_ACPI) += smbus_ich9.o
21
common-obj-$(CONFIG_APM) += pm_smbus.o
22
common-obj-$(CONFIG_BITBANG_I2C) += bitbang_i2c.o
23
common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
24
+common-obj-$(CONFIG_OMAP) += ddc.o
25
obj-$(CONFIG_OMAP) += omap_i2c.o
26
diff --git a/hw/i2c/ddc.c b/hw/i2c/ddc.c
28
index 0000000..05f5501
32
+/* A simple I2C slave for returning monitor EDID data via DDC.
34
+ * Copyright (c) 2011 Linaro Limited
35
+ * Written by Peter Maydell
37
+ * This program is free software; you can redistribute it and/or modify
38
+ * it under the terms of the GNU General Public License version 2 as
39
+ * published by the Free Software Foundation.
41
+ * This program is distributed in the hope that it will be useful,
42
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
43
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44
+ * GNU General Public License for more details.
46
+ * You should have received a copy of the GNU General Public License along
47
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
49
+#include "hw/i2c/i2c.h"
51
+//#define DEBUG_I2CDDC
53
+#define DPRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
55
+#define DPRINTF(fmt, ...) do {} while(0)
58
+/* Structure defining a monitor's characteristics in a
59
+ * readable format: this should be passed to build_edid_blob()
60
+ * to convert it into the 128 byte binary EDID blob.
61
+ * Not all bits of the EDID are customisable here.
64
+ char manuf_id[3]; /* three upper case letters */
65
+ uint16_t product_id;
72
+ char monitor_name[14];
73
+ char serial_no_string[14];
75
+ uint8_t vmin; /* Hz */
76
+ uint8_t vmax; /* Hz */
77
+ uint8_t hmin; /* kHz */
78
+ uint8_t hmax; /* kHz */
79
+ uint8_t pixclock; /* MHz / 10 */
80
+ uint8_t timing_data[18];
83
+/* EDID data for a simple LCD monitor */
84
+static const edid_data lcd_edid = {
85
+ /* The manuf_id ought really to be an assigned EISA ID */
94
+ .monitor_name = "QEMU monitor",
95
+ .serial_no_string = "1",
102
+ /* Borrowed from a 21" LCD */
103
+ 0x48, 0x3f, 0x40, 0x30, 0x62, 0xb0, 0x32, 0x40, 0x40,
104
+ 0xc0, 0x13, 0x00, 0x98, 0x32, 0x11, 0x00, 0x00, 0x1e
108
+static uint8_t manuf_char_to_int(char c)
110
+ return (c - 'A') & 0x1f;
113
+static void write_ascii_descriptor_block(uint8_t *descblob, uint8_t blocktype,
114
+ const char *string)
116
+ /* Write an EDID Descriptor Block of the "ascii string" type */
118
+ descblob[0] = descblob[1] = descblob[2] = descblob[4] = 0;
119
+ descblob[3] = blocktype;
120
+ /* The rest is 13 bytes of ASCII; if less then the rest must
121
+ * be filled with newline then spaces
123
+ for (i = 5; i < 19; i++) {
124
+ descblob[i] = string[i - 5];
125
+ if (!descblob[i]) {
130
+ descblob[i++] = '\n';
132
+ for ( ; i < 19; i++) {
137
+static void write_range_limits_descriptor(const edid_data *edid,
141
+ descblob[0] = descblob[1] = descblob[2] = descblob[4] = 0;
142
+ descblob[3] = 0xfd;
143
+ descblob[5] = edid->vmin;
144
+ descblob[6] = edid->vmax;
145
+ descblob[7] = edid->hmin;
146
+ descblob[8] = edid->hmax;
147
+ descblob[9] = edid->pixclock;
149
+ descblob[11] = 0xa;
150
+ for (i = 12; i < 19; i++) {
151
+ descblob[i] = 0x20;
155
+static void build_edid_blob(const edid_data *edid, uint8_t *blob)
157
+ /* Write an EDID 1.3 format blob (128 bytes) based
158
+ * on the edid_data structure.
163
+ /* 00-07 : header */
164
+ blob[0] = blob[7] = 0;
165
+ for (i = 1 ; i < 7; i++) {
168
+ /* 08-09 : manufacturer ID */
169
+ blob[8] = (manuf_char_to_int(edid->manuf_id[0]) << 2)
170
+ | (manuf_char_to_int(edid->manuf_id[1]) >> 3);
171
+ blob[9] = (manuf_char_to_int(edid->manuf_id[1]) << 5)
172
+ | manuf_char_to_int(edid->manuf_id[2]);
173
+ /* 10-11 : product ID code */
174
+ blob[10] = edid->product_id;
175
+ blob[11] = edid->product_id >> 8;
176
+ blob[12] = edid->serial_no;
177
+ blob[13] = edid->serial_no >> 8;
178
+ blob[14] = edid->serial_no >> 16;
179
+ blob[15] = edid->serial_no >> 24;
180
+ /* 16 : week of manufacture */
181
+ blob[16] = edid->manuf_week;
182
+ /* 17 : year of manufacture - 1990 */
183
+ blob[17] = edid->manuf_year - 1990;
184
+ /* 18, 19 : EDID version and revision */
187
+ /* 20 - 24 : basic display parameters */
188
+ /* We are always a digital display */
190
+ /* 21, 22 : max h/v size in cm */
191
+ blob[21] = edid->h_cm;
192
+ blob[22] = edid->v_cm;
193
+ /* 23 : gamma (divide by 100 then add 1 for actual value) */
194
+ blob[23] = edid->gamma;
195
+ /* 24 feature support: no power management, RGB, preferred timing mode,
196
+ * standard colour space
199
+ /* 25 - 34 : chromaticity coordinates. These are the
200
+ * standard sRGB chromaticity values
212
+ /* 35, 36 : Established timings: claim to support everything */
213
+ blob[35] = blob[36] = 0xff;
214
+ /* 37 : manufacturer's reserved timing: none */
216
+ /* 38 - 53 : standard timing identification
217
+ * don't claim anything beyond what the 'established timings'
218
+ * already provide. Unused slots must be (0x1, 0x1)
220
+ for (i = 38; i < 54; i++) {
223
+ /* 54 - 71 : descriptor block 1 : must be preferred timing data */
224
+ memcpy(blob + 54, edid->timing_data, 18);
225
+ /* 72 - 89, 90 - 107, 108 - 125 : descriptor block 2, 3, 4
226
+ * Order not important, but we must have a monitor name and a
227
+ * range limits descriptor.
229
+ write_range_limits_descriptor(edid, blob + 72);
230
+ write_ascii_descriptor_block(blob + 90, 0xfc, edid->monitor_name);
231
+ write_ascii_descriptor_block(blob + 108, 0xff, edid->serial_no_string);
233
+ /* 126 : extension flag */
237
+ DPRINTF("EDID blob:");
238
+ for (i = 0; i < 127; i++) {
240
+ DPRINTF("%c0x%02x,", i % 8 ? ' ' : '\n', blob[i]);
242
+ /* 127 : checksum */
243
+ blob[127] = -cksum;
244
+ DPRINTF(" 0x%02x\n", blob[127]);
249
+/* A simple I2C slave which just returns the contents of its EDID blob. */
251
+typedef struct I2CDDCState_s {
255
+ uint8_t edid_blob[128];
258
+static void i2c_ddc_reset(DeviceState *ds)
260
+ I2CDDCState *s = FROM_I2C_SLAVE(I2CDDCState, I2C_SLAVE(ds));
265
+static void i2c_ddc_event(I2CSlave *i2c, enum i2c_event event)
267
+ I2CDDCState *s = FROM_I2C_SLAVE(I2CDDCState, i2c);
268
+ if (event == I2C_START_SEND) {
273
+static int i2c_ddc_rx(I2CSlave *i2c)
275
+ I2CDDCState *s = FROM_I2C_SLAVE(I2CDDCState, i2c);
277
+ if (s->reg < sizeof(s->edid_blob)) {
278
+ value = s->edid_blob[s->reg];
286
+static int i2c_ddc_tx(I2CSlave *i2c, uint8_t data)
288
+ I2CDDCState *s = FROM_I2C_SLAVE(I2CDDCState, i2c);
289
+ if (s->firstbyte) {
295
+ /* Ignore all writes */
300
+static int i2c_ddc_init(I2CSlave *i2c)
302
+ I2CDDCState *s = FROM_I2C_SLAVE(I2CDDCState, i2c);
303
+ build_edid_blob(&lcd_edid, s->edid_blob);
307
+static void i2c_ddc_class_init(ObjectClass *klass, void *data)
309
+ DeviceClass *dc = DEVICE_CLASS(klass);
310
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
311
+ k->init = i2c_ddc_init;
312
+ k->event = i2c_ddc_event;
313
+ k->recv = i2c_ddc_rx;
314
+ k->send = i2c_ddc_tx;
315
+ dc->reset = i2c_ddc_reset;
319
+static TypeInfo i2c_ddc_info = {
321
+ .parent = TYPE_I2C_SLAVE,
322
+ .instance_size = sizeof(I2CDDCState),
323
+ .class_init = i2c_ddc_class_init,
326
+static void ddc_register_types(void)
328
+ type_register_static(&i2c_ddc_info);
331
+type_init(ddc_register_types);