~ubuntu-branches/ubuntu/trusty/qemu/trusty

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-10-22 22:47:07 UTC
  • mfrom: (1.8.3) (10.1.42 sid)
  • Revision ID: package-import@ubuntu.com-20131022224707-1lya34fw3k3f24tv
Tags: 1.6.0+dfsg-2ubuntu1
* Merge 1.6.0~rc0+dfsg-2exp from debian experimental.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
      - drop openbios-ppc and openhackware Depends to Suggests (for now)
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - New linaro patches from qemu-linaro rebasing branch
  - Dropped patches:
    * xen-simplify-xen_enabled.patch
    * sparc-linux-user-fix-missing-symbols-in-.rel-.rela.plt-sections.patch
    * main_loop-do-not-set-nonblocking-if-xen_enabled.patch
    * xen_machine_pv-do-not-create-a-dummy-CPU-in-machine-.patch
    * virtio-rng-fix-crash
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * linaro arm patches from qemu-linaro rebasing branch
  - New patches:
    * fix-pci-add: change CONFIG variable in ifdef to make sure that
      pci_add is defined.
* Add linaro patches
* Add experimental mach-virt patches for arm virtualization.
* qemu-system-common.install: add debian/tmp/usr/lib to install the
  qemu-bridge-helper

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
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
-- 
 
333
1.8.3.2
 
334