~ubuntu-branches/ubuntu/vivid/qemu/vivid

« back to all changes in this revision

Viewing changes to debian/patches/ubuntu/linaro/0055-hw-i2c-ddc.c-Implement-DDC-I2C-slave.patch

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-02-25 22:31:43 UTC
  • mfrom: (1.8.5)
  • Revision ID: package-import@ubuntu.com-20140225223143-odhqxfc60wxrjl15
Tags: 2.0.0~rc1+dfsg-0ubuntu1
* Merge 2.0.0-rc1
* debian/rules: consolidate ppc filter entries.
* Move qemu-system-arch64 into qemu-system-arm
* debian/patches/define-trusty-machine-type.patch: define a trusty machine
  type, currently the same as pc-i440fx-2.0, to put is in a better position
  to enable live migrations from trusty onward.  (LP: #1294823)
* debian/control: build-dep on libfdt >= 1.4.0  (LP: #1295072)
* Merge latest upstream git to commit dc9528f
* Debian/rules:
  - remove -enable-uname-release=2.6.32
  - don't make the aarch64 target Ubuntu-specific.
* Remove patches which are now upstream:
  - fix-smb-security-share.patch
  - slirp-smb-redirect-port-445-too.patch 
  - linux-user-Implement-sendmmsg-syscall.patch (better version is upstream)
  - signal-added-a-wrapper-for-sigprocmask-function.patch
  - ubuntu/signal-sigsegv-protection-on-do_sigprocmask.patch
  - ubuntu/Don-t-block-SIGSEGV-at-more-places.patch
  - ubuntu/ppc-force-cpu-threads-count-to-be-power-of-2.patch
* add link for /usr/share/qemu/bios-256k.bin
* Remove all linaro patches.
* Remove all arm64/ patches.  Many but not all are upstream.
* Remove CVE-2013-4377.patch which is upstream.
* debian/control-in: don't make qemu-system-aarch64 ubuntu-specific

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
From 6cc5752d24da5cadc20d6a3bd1cb0bbfeeb80a66 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 55/70] hw/i2c-ddc.c: Implement DDC I2C slave
5
 
 
6
 
Implement an I2C slave which implements DDC and returns the
7
 
EDID data for an attached monitor.
8
 
 
9
 
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
 
---
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
15
 
 
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
27
 
new file mode 100644
28
 
index 0000000..05f5501
29
 
--- /dev/null
30
 
+++ b/hw/i2c/ddc.c
31
 
@@ -0,0 +1,300 @@
32
 
+/* A simple I2C slave for returning monitor EDID data via DDC.
33
 
+ *
34
 
+ * Copyright (c) 2011 Linaro Limited
35
 
+ * Written by Peter Maydell
36
 
+ *
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.
40
 
+ *
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.
45
 
+ *
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/>.
48
 
+ */
49
 
+#include "hw/i2c/i2c.h"
50
 
+
51
 
+//#define DEBUG_I2CDDC
52
 
+#ifdef DEBUG_I2CDDC
53
 
+#define DPRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
54
 
+#else
55
 
+#define DPRINTF(fmt, ...) do {} while(0)
56
 
+#endif
57
 
+
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.
62
 
+ */
63
 
+typedef struct {
64
 
+    char manuf_id[3]; /* three upper case letters */
65
 
+    uint16_t product_id;
66
 
+    uint32_t serial_no;
67
 
+    uint8_t manuf_week;
68
 
+    int manuf_year;
69
 
+    uint8_t h_cm;
70
 
+    uint8_t v_cm;
71
 
+    uint8_t gamma;
72
 
+    char monitor_name[14];
73
 
+    char serial_no_string[14];
74
 
+    /* Range limits */
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];
81
 
+} edid_data;
82
 
+
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 */
86
 
+    .manuf_id = "QMU",
87
 
+    .product_id = 0,
88
 
+    .serial_no = 1,
89
 
+    .manuf_week = 1,
90
 
+    .manuf_year = 2011,
91
 
+    .h_cm = 40,
92
 
+    .v_cm = 30,
93
 
+    .gamma = 0x78,
94
 
+    .monitor_name = "QEMU monitor",
95
 
+    .serial_no_string = "1",
96
 
+    .vmin = 40,
97
 
+    .vmax = 120,
98
 
+    .hmin = 30,
99
 
+    .hmax = 100,
100
 
+    .pixclock = 18,
101
 
+    .timing_data = {
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
105
 
+    }
106
 
+};
107
 
+
108
 
+static uint8_t manuf_char_to_int(char c)
109
 
+{
110
 
+    return (c - 'A') & 0x1f;
111
 
+}
112
 
+
113
 
+static void write_ascii_descriptor_block(uint8_t *descblob, uint8_t blocktype,
114
 
+                                         const char *string)
115
 
+{
116
 
+    /* Write an EDID Descriptor Block of the "ascii string" type */
117
 
+    int i;
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
122
 
+     */
123
 
+    for (i = 5; i < 19; i++) {
124
 
+        descblob[i] = string[i - 5];
125
 
+        if (!descblob[i]) {
126
 
+            break;
127
 
+        }
128
 
+    }
129
 
+    if (i < 19) {
130
 
+        descblob[i++] = '\n';
131
 
+    }
132
 
+    for ( ; i < 19; i++) {
133
 
+        descblob[i] = ' ';
134
 
+    }
135
 
+}
136
 
+
137
 
+static void write_range_limits_descriptor(const edid_data *edid,
138
 
+                                          uint8_t *descblob)
139
 
+{
140
 
+    int i;
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;
148
 
+    descblob[10] = 0;
149
 
+    descblob[11] = 0xa;
150
 
+    for (i = 12; i < 19; i++) {
151
 
+        descblob[i] = 0x20;
152
 
+    }
153
 
+}
154
 
+
155
 
+static void build_edid_blob(const edid_data *edid, uint8_t *blob)
156
 
+{
157
 
+    /* Write an EDID 1.3 format blob (128 bytes) based
158
 
+     * on the edid_data structure.
159
 
+     */
160
 
+    int i;
161
 
+    uint8_t cksum;
162
 
+
163
 
+    /* 00-07 : header */
164
 
+    blob[0] = blob[7] = 0;
165
 
+    for (i = 1 ; i < 7; i++) {
166
 
+        blob[i] = 0xff;
167
 
+    }
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 */
185
 
+    blob[18] = 1;
186
 
+    blob[19] = 3;
187
 
+    /* 20 - 24 : basic display parameters */
188
 
+    /* We are always a digital display */
189
 
+    blob[20] = 0x80;
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
197
 
+     */
198
 
+    blob[24] = 0x0e;
199
 
+    /* 25 - 34 : chromaticity coordinates. These are the
200
 
+     * standard sRGB chromaticity values
201
 
+     */
202
 
+    blob[25] = 0xee;
203
 
+    blob[26] = 0x91;
204
 
+    blob[27] = 0xa3;
205
 
+    blob[28] = 0x54;
206
 
+    blob[29] = 0x4c;
207
 
+    blob[30] = 0x99;
208
 
+    blob[31] = 0x26;
209
 
+    blob[32] = 0x0f;
210
 
+    blob[33] = 0x50;
211
 
+    blob[34] = 0x54;
212
 
+    /* 35, 36 : Established timings: claim to support everything */
213
 
+    blob[35] = blob[36] = 0xff;
214
 
+    /* 37 : manufacturer's reserved timing: none */
215
 
+    blob[37] = 0;
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)
219
 
+     */
220
 
+    for (i = 38; i < 54; i++) {
221
 
+        blob[i] = 0x1;
222
 
+    }
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.
228
 
+     */
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);
232
 
+
233
 
+    /* 126 : extension flag */
234
 
+    blob[126] = 0;
235
 
+
236
 
+    cksum = 0;
237
 
+    DPRINTF("EDID blob:");
238
 
+    for (i = 0; i < 127; i++) {
239
 
+        cksum += blob[i];
240
 
+        DPRINTF("%c0x%02x,", i % 8 ? ' ' : '\n', blob[i]);
241
 
+    }
242
 
+    /* 127 : checksum */
243
 
+    blob[127] = -cksum;
244
 
+    DPRINTF(" 0x%02x\n", blob[127]);
245
 
+}
246
 
+
247
 
+
248
 
+
249
 
+/* A simple I2C slave which just returns the contents of its EDID blob. */
250
 
+
251
 
+typedef struct I2CDDCState_s {
252
 
+    I2CSlave i2c;
253
 
+    int firstbyte;
254
 
+    uint8_t reg;
255
 
+    uint8_t edid_blob[128];
256
 
+} I2CDDCState;
257
 
+
258
 
+static void i2c_ddc_reset(DeviceState *ds)
259
 
+{
260
 
+    I2CDDCState *s = FROM_I2C_SLAVE(I2CDDCState, I2C_SLAVE(ds));
261
 
+    s->firstbyte = 0;
262
 
+    s->reg = 0;
263
 
+}
264
 
+
265
 
+static void i2c_ddc_event(I2CSlave *i2c, enum i2c_event event)
266
 
+{
267
 
+    I2CDDCState *s = FROM_I2C_SLAVE(I2CDDCState, i2c);
268
 
+    if (event == I2C_START_SEND) {
269
 
+        s->firstbyte = 1;
270
 
+    }
271
 
+}
272
 
+
273
 
+static int i2c_ddc_rx(I2CSlave *i2c)
274
 
+{
275
 
+    I2CDDCState *s = FROM_I2C_SLAVE(I2CDDCState, i2c);
276
 
+    int value;
277
 
+    if (s->reg < sizeof(s->edid_blob)) {
278
 
+        value = s->edid_blob[s->reg];
279
 
+    } else {
280
 
+        value = 0;
281
 
+    }
282
 
+    s->reg++;
283
 
+    return value;
284
 
+}
285
 
+
286
 
+static int i2c_ddc_tx(I2CSlave *i2c, uint8_t data)
287
 
+{
288
 
+    I2CDDCState *s = FROM_I2C_SLAVE(I2CDDCState, i2c);
289
 
+    if (s->firstbyte) {
290
 
+        s->reg = data;
291
 
+        s->firstbyte = 0;
292
 
+        return 1;
293
 
+    }
294
 
+
295
 
+    /* Ignore all writes */
296
 
+    s->reg++;
297
 
+    return 1;
298
 
+}
299
 
+
300
 
+static int i2c_ddc_init(I2CSlave *i2c)
301
 
+{
302
 
+    I2CDDCState *s = FROM_I2C_SLAVE(I2CDDCState, i2c);
303
 
+    build_edid_blob(&lcd_edid, s->edid_blob);
304
 
+    return 0;
305
 
+}
306
 
+
307
 
+static void i2c_ddc_class_init(ObjectClass *klass, void *data)
308
 
+{
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;
316
 
+    // XXX vmstate?
317
 
+}
318
 
+
319
 
+static TypeInfo i2c_ddc_info = {
320
 
+    .name = "i2c-ddc",
321
 
+    .parent = TYPE_I2C_SLAVE,
322
 
+    .instance_size = sizeof(I2CDDCState),
323
 
+    .class_init = i2c_ddc_class_init,
324
 
+};
325
 
+
326
 
+static void ddc_register_types(void)
327
 
+{
328
 
+    type_register_static(&i2c_ddc_info);
329
 
+}
330
 
+
331
 
+type_init(ddc_register_types);
332
 
1.8.5.2
333