149ab747fSPaolo Bonzini /*
249ab747fSPaolo Bonzini * SSD0323 OLED controller with OSRAM Pictiva 128x64 display.
349ab747fSPaolo Bonzini *
449ab747fSPaolo Bonzini * Copyright (c) 2006-2007 CodeSourcery.
549ab747fSPaolo Bonzini * Written by Paul Brook
649ab747fSPaolo Bonzini *
749ab747fSPaolo Bonzini * This code is licensed under the GPL.
849ab747fSPaolo Bonzini */
949ab747fSPaolo Bonzini
1049ab747fSPaolo Bonzini /* The controller can support a variety of different displays, but we only
1133a52307SMichael Tokarev implement one. Most of the commands relating to brightness and geometry
1249ab747fSPaolo Bonzini setup are ignored. */
130b8fa32fSMarkus Armbruster
1447df5154SPeter Maydell #include "qemu/osdep.h"
158fd06719SAlistair Francis #include "hw/ssi/ssi.h"
16d6454270SMarkus Armbruster #include "migration/vmstate.h"
170b8fa32fSMarkus Armbruster #include "qemu/module.h"
1849ab747fSPaolo Bonzini #include "ui/console.h"
19db1015e9SEduardo Habkost #include "qom/object.h"
2049ab747fSPaolo Bonzini
2149ab747fSPaolo Bonzini //#define DEBUG_SSD0323 1
2249ab747fSPaolo Bonzini
2349ab747fSPaolo Bonzini #ifdef DEBUG_SSD0323
2449ab747fSPaolo Bonzini #define DPRINTF(fmt, ...) \
2549ab747fSPaolo Bonzini do { printf("ssd0323: " fmt , ## __VA_ARGS__); } while (0)
2649ab747fSPaolo Bonzini #define BADF(fmt, ...) \
2749ab747fSPaolo Bonzini do { \
2849ab747fSPaolo Bonzini fprintf(stderr, "ssd0323: error: " fmt , ## __VA_ARGS__); abort(); \
2949ab747fSPaolo Bonzini } while (0)
3049ab747fSPaolo Bonzini #else
3149ab747fSPaolo Bonzini #define DPRINTF(fmt, ...) do {} while(0)
3249ab747fSPaolo Bonzini #define BADF(fmt, ...) \
3349ab747fSPaolo Bonzini do { fprintf(stderr, "ssd0323: error: " fmt , ## __VA_ARGS__);} while (0)
3449ab747fSPaolo Bonzini #endif
3549ab747fSPaolo Bonzini
3649ab747fSPaolo Bonzini /* Scaling factor for pixels. */
3749ab747fSPaolo Bonzini #define MAGNIFY 4
3849ab747fSPaolo Bonzini
3949ab747fSPaolo Bonzini #define REMAP_SWAP_COLUMN 0x01
4049ab747fSPaolo Bonzini #define REMAP_SWAP_NYBBLE 0x02
4149ab747fSPaolo Bonzini #define REMAP_VERTICAL 0x04
4249ab747fSPaolo Bonzini #define REMAP_SWAP_COM 0x10
4349ab747fSPaolo Bonzini #define REMAP_SPLIT_COM 0x40
4449ab747fSPaolo Bonzini
4549ab747fSPaolo Bonzini enum ssd0323_mode
4649ab747fSPaolo Bonzini {
4749ab747fSPaolo Bonzini SSD0323_CMD,
4849ab747fSPaolo Bonzini SSD0323_DATA
4949ab747fSPaolo Bonzini };
5049ab747fSPaolo Bonzini
51db1015e9SEduardo Habkost struct ssd0323_state {
52ec7e429bSPhilippe Mathieu-Daudé SSIPeripheral ssidev;
5349ab747fSPaolo Bonzini QemuConsole *con;
5449ab747fSPaolo Bonzini
55e7f76c52SDr. David Alan Gilbert uint32_t cmd_len;
56e7f76c52SDr. David Alan Gilbert int32_t cmd;
57e7f76c52SDr. David Alan Gilbert int32_t cmd_data[8];
58e7f76c52SDr. David Alan Gilbert int32_t row;
59e7f76c52SDr. David Alan Gilbert int32_t row_start;
60e7f76c52SDr. David Alan Gilbert int32_t row_end;
61e7f76c52SDr. David Alan Gilbert int32_t col;
62e7f76c52SDr. David Alan Gilbert int32_t col_start;
63e7f76c52SDr. David Alan Gilbert int32_t col_end;
64e7f76c52SDr. David Alan Gilbert int32_t redraw;
65e7f76c52SDr. David Alan Gilbert int32_t remap;
66e7f76c52SDr. David Alan Gilbert uint32_t mode;
6749ab747fSPaolo Bonzini uint8_t framebuffer[128 * 80 / 2];
68db1015e9SEduardo Habkost };
6949ab747fSPaolo Bonzini
70213f63dfSPeter Maydell #define TYPE_SSD0323 "ssd0323"
OBJECT_DECLARE_SIMPLE_TYPE(ssd0323_state,SSD0323)718063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(ssd0323_state, SSD0323)
72213f63dfSPeter Maydell
73213f63dfSPeter Maydell
74ec7e429bSPhilippe Mathieu-Daudé static uint32_t ssd0323_transfer(SSIPeripheral *dev, uint32_t data)
7549ab747fSPaolo Bonzini {
76213f63dfSPeter Maydell ssd0323_state *s = SSD0323(dev);
7749ab747fSPaolo Bonzini
7849ab747fSPaolo Bonzini switch (s->mode) {
7949ab747fSPaolo Bonzini case SSD0323_DATA:
8049ab747fSPaolo Bonzini DPRINTF("data 0x%02x\n", data);
8149ab747fSPaolo Bonzini s->framebuffer[s->col + s->row * 64] = data;
8249ab747fSPaolo Bonzini if (s->remap & REMAP_VERTICAL) {
8349ab747fSPaolo Bonzini s->row++;
8449ab747fSPaolo Bonzini if (s->row > s->row_end) {
8549ab747fSPaolo Bonzini s->row = s->row_start;
8649ab747fSPaolo Bonzini s->col++;
8749ab747fSPaolo Bonzini }
8849ab747fSPaolo Bonzini if (s->col > s->col_end) {
8949ab747fSPaolo Bonzini s->col = s->col_start;
9049ab747fSPaolo Bonzini }
9149ab747fSPaolo Bonzini } else {
9249ab747fSPaolo Bonzini s->col++;
9349ab747fSPaolo Bonzini if (s->col > s->col_end) {
9449ab747fSPaolo Bonzini s->row++;
9549ab747fSPaolo Bonzini s->col = s->col_start;
9649ab747fSPaolo Bonzini }
9749ab747fSPaolo Bonzini if (s->row > s->row_end) {
9849ab747fSPaolo Bonzini s->row = s->row_start;
9949ab747fSPaolo Bonzini }
10049ab747fSPaolo Bonzini }
10149ab747fSPaolo Bonzini s->redraw = 1;
10249ab747fSPaolo Bonzini break;
10349ab747fSPaolo Bonzini case SSD0323_CMD:
10449ab747fSPaolo Bonzini DPRINTF("cmd 0x%02x\n", data);
10549ab747fSPaolo Bonzini if (s->cmd_len == 0) {
10649ab747fSPaolo Bonzini s->cmd = data;
10749ab747fSPaolo Bonzini } else {
10849ab747fSPaolo Bonzini s->cmd_data[s->cmd_len - 1] = data;
10949ab747fSPaolo Bonzini }
11049ab747fSPaolo Bonzini s->cmd_len++;
11149ab747fSPaolo Bonzini switch (s->cmd) {
11249ab747fSPaolo Bonzini #define DATA(x) if (s->cmd_len <= (x)) return 0
11349ab747fSPaolo Bonzini case 0x15: /* Set column. */
11449ab747fSPaolo Bonzini DATA(2);
11549ab747fSPaolo Bonzini s->col = s->col_start = s->cmd_data[0] % 64;
11649ab747fSPaolo Bonzini s->col_end = s->cmd_data[1] % 64;
11749ab747fSPaolo Bonzini break;
11849ab747fSPaolo Bonzini case 0x75: /* Set row. */
11949ab747fSPaolo Bonzini DATA(2);
12049ab747fSPaolo Bonzini s->row = s->row_start = s->cmd_data[0] % 80;
12149ab747fSPaolo Bonzini s->row_end = s->cmd_data[1] % 80;
12249ab747fSPaolo Bonzini break;
12349ab747fSPaolo Bonzini case 0x81: /* Set contrast */
12449ab747fSPaolo Bonzini DATA(1);
12549ab747fSPaolo Bonzini break;
12649ab747fSPaolo Bonzini case 0x84: case 0x85: case 0x86: /* Max current. */
12749ab747fSPaolo Bonzini DATA(0);
12849ab747fSPaolo Bonzini break;
12949ab747fSPaolo Bonzini case 0xa0: /* Set remapping. */
13049ab747fSPaolo Bonzini /* FIXME: Implement this. */
13149ab747fSPaolo Bonzini DATA(1);
13249ab747fSPaolo Bonzini s->remap = s->cmd_data[0];
13349ab747fSPaolo Bonzini break;
13449ab747fSPaolo Bonzini case 0xa1: /* Set display start line. */
13549ab747fSPaolo Bonzini case 0xa2: /* Set display offset. */
13649ab747fSPaolo Bonzini /* FIXME: Implement these. */
13749ab747fSPaolo Bonzini DATA(1);
13849ab747fSPaolo Bonzini break;
13949ab747fSPaolo Bonzini case 0xa4: /* Normal mode. */
14049ab747fSPaolo Bonzini case 0xa5: /* All on. */
14149ab747fSPaolo Bonzini case 0xa6: /* All off. */
14249ab747fSPaolo Bonzini case 0xa7: /* Inverse. */
14349ab747fSPaolo Bonzini /* FIXME: Implement these. */
14449ab747fSPaolo Bonzini DATA(0);
14549ab747fSPaolo Bonzini break;
14649ab747fSPaolo Bonzini case 0xa8: /* Set multiplex ratio. */
14749ab747fSPaolo Bonzini case 0xad: /* Set DC-DC converter. */
14849ab747fSPaolo Bonzini DATA(1);
14949ab747fSPaolo Bonzini /* Ignored. Don't care. */
15049ab747fSPaolo Bonzini break;
15149ab747fSPaolo Bonzini case 0xae: /* Display off. */
15249ab747fSPaolo Bonzini case 0xaf: /* Display on. */
15349ab747fSPaolo Bonzini DATA(0);
15449ab747fSPaolo Bonzini /* TODO: Implement power control. */
15549ab747fSPaolo Bonzini break;
15649ab747fSPaolo Bonzini case 0xb1: /* Set phase length. */
15749ab747fSPaolo Bonzini case 0xb2: /* Set row period. */
15849ab747fSPaolo Bonzini case 0xb3: /* Set clock rate. */
15949ab747fSPaolo Bonzini case 0xbc: /* Set precharge. */
16049ab747fSPaolo Bonzini case 0xbe: /* Set VCOMH. */
16149ab747fSPaolo Bonzini case 0xbf: /* Set segment low. */
16249ab747fSPaolo Bonzini DATA(1);
16349ab747fSPaolo Bonzini /* Ignored. Don't care. */
16449ab747fSPaolo Bonzini break;
16549ab747fSPaolo Bonzini case 0xb8: /* Set grey scale table. */
16649ab747fSPaolo Bonzini /* FIXME: Implement this. */
16749ab747fSPaolo Bonzini DATA(8);
16849ab747fSPaolo Bonzini break;
16949ab747fSPaolo Bonzini case 0xe3: /* NOP. */
17049ab747fSPaolo Bonzini DATA(0);
17149ab747fSPaolo Bonzini break;
17249ab747fSPaolo Bonzini case 0xff: /* Nasty hack because we don't handle chip selects
17349ab747fSPaolo Bonzini properly. */
17449ab747fSPaolo Bonzini break;
17549ab747fSPaolo Bonzini default:
17649ab747fSPaolo Bonzini BADF("Unknown command: 0x%x\n", data);
17749ab747fSPaolo Bonzini }
17849ab747fSPaolo Bonzini s->cmd_len = 0;
17949ab747fSPaolo Bonzini return 0;
18049ab747fSPaolo Bonzini }
18149ab747fSPaolo Bonzini return 0;
18249ab747fSPaolo Bonzini }
18349ab747fSPaolo Bonzini
ssd0323_update_display(void * opaque)18449ab747fSPaolo Bonzini static void ssd0323_update_display(void *opaque)
18549ab747fSPaolo Bonzini {
18649ab747fSPaolo Bonzini ssd0323_state *s = (ssd0323_state *)opaque;
18749ab747fSPaolo Bonzini DisplaySurface *surface = qemu_console_surface(s->con);
18849ab747fSPaolo Bonzini uint8_t *dest;
18949ab747fSPaolo Bonzini uint8_t *src;
19049ab747fSPaolo Bonzini int x;
19149ab747fSPaolo Bonzini int y;
19249ab747fSPaolo Bonzini int i;
19349ab747fSPaolo Bonzini int line;
19449ab747fSPaolo Bonzini char *colors[16];
19549ab747fSPaolo Bonzini char colortab[MAGNIFY * 64];
19649ab747fSPaolo Bonzini char *p;
19749ab747fSPaolo Bonzini int dest_width;
19849ab747fSPaolo Bonzini
19949ab747fSPaolo Bonzini if (!s->redraw)
20049ab747fSPaolo Bonzini return;
20149ab747fSPaolo Bonzini
20249ab747fSPaolo Bonzini switch (surface_bits_per_pixel(surface)) {
20349ab747fSPaolo Bonzini case 0:
20449ab747fSPaolo Bonzini return;
20549ab747fSPaolo Bonzini case 15:
20649ab747fSPaolo Bonzini dest_width = 2;
20749ab747fSPaolo Bonzini break;
20849ab747fSPaolo Bonzini case 16:
20949ab747fSPaolo Bonzini dest_width = 2;
21049ab747fSPaolo Bonzini break;
21149ab747fSPaolo Bonzini case 24:
21249ab747fSPaolo Bonzini dest_width = 3;
21349ab747fSPaolo Bonzini break;
21449ab747fSPaolo Bonzini case 32:
21549ab747fSPaolo Bonzini dest_width = 4;
21649ab747fSPaolo Bonzini break;
21749ab747fSPaolo Bonzini default:
21849ab747fSPaolo Bonzini BADF("Bad color depth\n");
21949ab747fSPaolo Bonzini return;
22049ab747fSPaolo Bonzini }
22149ab747fSPaolo Bonzini p = colortab;
22249ab747fSPaolo Bonzini for (i = 0; i < 16; i++) {
22349ab747fSPaolo Bonzini int n;
22449ab747fSPaolo Bonzini colors[i] = p;
22549ab747fSPaolo Bonzini switch (surface_bits_per_pixel(surface)) {
22649ab747fSPaolo Bonzini case 15:
22749ab747fSPaolo Bonzini n = i * 2 + (i >> 3);
22849ab747fSPaolo Bonzini p[0] = n | (n << 5);
22949ab747fSPaolo Bonzini p[1] = (n << 2) | (n >> 3);
23049ab747fSPaolo Bonzini break;
23149ab747fSPaolo Bonzini case 16:
23249ab747fSPaolo Bonzini n = i * 2 + (i >> 3);
23349ab747fSPaolo Bonzini p[0] = n | (n << 6) | ((n << 1) & 0x20);
23449ab747fSPaolo Bonzini p[1] = (n << 3) | (n >> 2);
23549ab747fSPaolo Bonzini break;
23649ab747fSPaolo Bonzini case 24:
23749ab747fSPaolo Bonzini case 32:
23849ab747fSPaolo Bonzini n = (i << 4) | i;
23949ab747fSPaolo Bonzini p[0] = p[1] = p[2] = n;
24049ab747fSPaolo Bonzini break;
24149ab747fSPaolo Bonzini default:
24249ab747fSPaolo Bonzini BADF("Bad color depth\n");
24349ab747fSPaolo Bonzini return;
24449ab747fSPaolo Bonzini }
24549ab747fSPaolo Bonzini p += dest_width;
24649ab747fSPaolo Bonzini }
24749ab747fSPaolo Bonzini /* TODO: Implement row/column remapping. */
24849ab747fSPaolo Bonzini dest = surface_data(surface);
24949ab747fSPaolo Bonzini for (y = 0; y < 64; y++) {
25049ab747fSPaolo Bonzini line = y;
25149ab747fSPaolo Bonzini src = s->framebuffer + 64 * line;
25249ab747fSPaolo Bonzini for (x = 0; x < 64; x++) {
25349ab747fSPaolo Bonzini int val;
25449ab747fSPaolo Bonzini val = *src >> 4;
25549ab747fSPaolo Bonzini for (i = 0; i < MAGNIFY; i++) {
25649ab747fSPaolo Bonzini memcpy(dest, colors[val], dest_width);
25749ab747fSPaolo Bonzini dest += dest_width;
25849ab747fSPaolo Bonzini }
25949ab747fSPaolo Bonzini val = *src & 0xf;
26049ab747fSPaolo Bonzini for (i = 0; i < MAGNIFY; i++) {
26149ab747fSPaolo Bonzini memcpy(dest, colors[val], dest_width);
26249ab747fSPaolo Bonzini dest += dest_width;
26349ab747fSPaolo Bonzini }
26449ab747fSPaolo Bonzini src++;
26549ab747fSPaolo Bonzini }
26649ab747fSPaolo Bonzini for (i = 1; i < MAGNIFY; i++) {
26749ab747fSPaolo Bonzini memcpy(dest, dest - dest_width * MAGNIFY * 128,
26849ab747fSPaolo Bonzini dest_width * 128 * MAGNIFY);
26949ab747fSPaolo Bonzini dest += dest_width * 128 * MAGNIFY;
27049ab747fSPaolo Bonzini }
27149ab747fSPaolo Bonzini }
27249ab747fSPaolo Bonzini s->redraw = 0;
27349ab747fSPaolo Bonzini dpy_gfx_update(s->con, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
27449ab747fSPaolo Bonzini }
27549ab747fSPaolo Bonzini
ssd0323_invalidate_display(void * opaque)27649ab747fSPaolo Bonzini static void ssd0323_invalidate_display(void * opaque)
27749ab747fSPaolo Bonzini {
27849ab747fSPaolo Bonzini ssd0323_state *s = (ssd0323_state *)opaque;
27949ab747fSPaolo Bonzini s->redraw = 1;
28049ab747fSPaolo Bonzini }
28149ab747fSPaolo Bonzini
28249ab747fSPaolo Bonzini /* Command/data input. */
ssd0323_cd(void * opaque,int n,int level)28349ab747fSPaolo Bonzini static void ssd0323_cd(void *opaque, int n, int level)
28449ab747fSPaolo Bonzini {
28549ab747fSPaolo Bonzini ssd0323_state *s = (ssd0323_state *)opaque;
28649ab747fSPaolo Bonzini DPRINTF("%s mode\n", level ? "Data" : "Command");
28749ab747fSPaolo Bonzini s->mode = level ? SSD0323_DATA : SSD0323_CMD;
28849ab747fSPaolo Bonzini }
28949ab747fSPaolo Bonzini
ssd0323_post_load(void * opaque,int version_id)290e7f76c52SDr. David Alan Gilbert static int ssd0323_post_load(void *opaque, int version_id)
29149ab747fSPaolo Bonzini {
29249ab747fSPaolo Bonzini ssd0323_state *s = (ssd0323_state *)opaque;
29349ab747fSPaolo Bonzini
294e7f76c52SDr. David Alan Gilbert if (s->cmd_len > ARRAY_SIZE(s->cmd_data)) {
295ead7a57dSMichael S. Tsirkin return -EINVAL;
296ead7a57dSMichael S. Tsirkin }
297ead7a57dSMichael S. Tsirkin if (s->row < 0 || s->row >= 80) {
298ead7a57dSMichael S. Tsirkin return -EINVAL;
299ead7a57dSMichael S. Tsirkin }
300ead7a57dSMichael S. Tsirkin if (s->row_start < 0 || s->row_start >= 80) {
301ead7a57dSMichael S. Tsirkin return -EINVAL;
302ead7a57dSMichael S. Tsirkin }
303ead7a57dSMichael S. Tsirkin if (s->row_end < 0 || s->row_end >= 80) {
304ead7a57dSMichael S. Tsirkin return -EINVAL;
305ead7a57dSMichael S. Tsirkin }
306ead7a57dSMichael S. Tsirkin if (s->col < 0 || s->col >= 64) {
307ead7a57dSMichael S. Tsirkin return -EINVAL;
308ead7a57dSMichael S. Tsirkin }
309ead7a57dSMichael S. Tsirkin if (s->col_start < 0 || s->col_start >= 64) {
310ead7a57dSMichael S. Tsirkin return -EINVAL;
311ead7a57dSMichael S. Tsirkin }
312ead7a57dSMichael S. Tsirkin if (s->col_end < 0 || s->col_end >= 64) {
313ead7a57dSMichael S. Tsirkin return -EINVAL;
314ead7a57dSMichael S. Tsirkin }
315ead7a57dSMichael S. Tsirkin if (s->mode != SSD0323_CMD && s->mode != SSD0323_DATA) {
316ead7a57dSMichael S. Tsirkin return -EINVAL;
317ead7a57dSMichael S. Tsirkin }
31849ab747fSPaolo Bonzini
31949ab747fSPaolo Bonzini return 0;
32049ab747fSPaolo Bonzini }
32149ab747fSPaolo Bonzini
322e7f76c52SDr. David Alan Gilbert static const VMStateDescription vmstate_ssd0323 = {
323e7f76c52SDr. David Alan Gilbert .name = "ssd0323_oled",
324e7f76c52SDr. David Alan Gilbert .version_id = 2,
325e7f76c52SDr. David Alan Gilbert .minimum_version_id = 2,
326e7f76c52SDr. David Alan Gilbert .post_load = ssd0323_post_load,
327*f0613160SRichard Henderson .fields = (const VMStateField []) {
328e7f76c52SDr. David Alan Gilbert VMSTATE_UINT32(cmd_len, ssd0323_state),
329e7f76c52SDr. David Alan Gilbert VMSTATE_INT32(cmd, ssd0323_state),
330e7f76c52SDr. David Alan Gilbert VMSTATE_INT32_ARRAY(cmd_data, ssd0323_state, 8),
331e7f76c52SDr. David Alan Gilbert VMSTATE_INT32(row, ssd0323_state),
332e7f76c52SDr. David Alan Gilbert VMSTATE_INT32(row_start, ssd0323_state),
333e7f76c52SDr. David Alan Gilbert VMSTATE_INT32(row_end, ssd0323_state),
334e7f76c52SDr. David Alan Gilbert VMSTATE_INT32(col, ssd0323_state),
335e7f76c52SDr. David Alan Gilbert VMSTATE_INT32(col_start, ssd0323_state),
336e7f76c52SDr. David Alan Gilbert VMSTATE_INT32(col_end, ssd0323_state),
337e7f76c52SDr. David Alan Gilbert VMSTATE_INT32(redraw, ssd0323_state),
338e7f76c52SDr. David Alan Gilbert VMSTATE_INT32(remap, ssd0323_state),
339e7f76c52SDr. David Alan Gilbert VMSTATE_UINT32(mode, ssd0323_state),
340e7f76c52SDr. David Alan Gilbert VMSTATE_BUFFER(framebuffer, ssd0323_state),
341ec7e429bSPhilippe Mathieu-Daudé VMSTATE_SSI_PERIPHERAL(ssidev, ssd0323_state),
342e7f76c52SDr. David Alan Gilbert VMSTATE_END_OF_LIST()
343e7f76c52SDr. David Alan Gilbert }
344e7f76c52SDr. David Alan Gilbert };
345e7f76c52SDr. David Alan Gilbert
346380cd056SGerd Hoffmann static const GraphicHwOps ssd0323_ops = {
347380cd056SGerd Hoffmann .invalidate = ssd0323_invalidate_display,
348380cd056SGerd Hoffmann .gfx_update = ssd0323_update_display,
349380cd056SGerd Hoffmann };
350380cd056SGerd Hoffmann
ssd0323_realize(SSIPeripheral * d,Error ** errp)351ec7e429bSPhilippe Mathieu-Daudé static void ssd0323_realize(SSIPeripheral *d, Error **errp)
35249ab747fSPaolo Bonzini {
3531a7d9ee6SPeter Crosthwaite DeviceState *dev = DEVICE(d);
354213f63dfSPeter Maydell ssd0323_state *s = SSD0323(d);
35549ab747fSPaolo Bonzini
35649ab747fSPaolo Bonzini s->col_end = 63;
35749ab747fSPaolo Bonzini s->row_end = 79;
3581a7d9ee6SPeter Crosthwaite s->con = graphic_console_init(dev, 0, &ssd0323_ops, s);
35949ab747fSPaolo Bonzini qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
36049ab747fSPaolo Bonzini
3611a7d9ee6SPeter Crosthwaite qdev_init_gpio_in(dev, ssd0323_cd, 1);
36249ab747fSPaolo Bonzini }
36349ab747fSPaolo Bonzini
ssd0323_class_init(ObjectClass * klass,void * data)36449ab747fSPaolo Bonzini static void ssd0323_class_init(ObjectClass *klass, void *data)
36549ab747fSPaolo Bonzini {
366e7f76c52SDr. David Alan Gilbert DeviceClass *dc = DEVICE_CLASS(klass);
367ec7e429bSPhilippe Mathieu-Daudé SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass);
36849ab747fSPaolo Bonzini
3697673bb4cSCédric Le Goater k->realize = ssd0323_realize;
37049ab747fSPaolo Bonzini k->transfer = ssd0323_transfer;
37149ab747fSPaolo Bonzini k->cs_polarity = SSI_CS_HIGH;
372e7f76c52SDr. David Alan Gilbert dc->vmsd = &vmstate_ssd0323;
37313527115SGan Qixin set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
37449ab747fSPaolo Bonzini }
37549ab747fSPaolo Bonzini
37649ab747fSPaolo Bonzini static const TypeInfo ssd0323_info = {
377213f63dfSPeter Maydell .name = TYPE_SSD0323,
378ec7e429bSPhilippe Mathieu-Daudé .parent = TYPE_SSI_PERIPHERAL,
37949ab747fSPaolo Bonzini .instance_size = sizeof(ssd0323_state),
38049ab747fSPaolo Bonzini .class_init = ssd0323_class_init,
38149ab747fSPaolo Bonzini };
38249ab747fSPaolo Bonzini
ssd03232_register_types(void)38349ab747fSPaolo Bonzini static void ssd03232_register_types(void)
38449ab747fSPaolo Bonzini {
38549ab747fSPaolo Bonzini type_register_static(&ssd0323_info);
38649ab747fSPaolo Bonzini }
38749ab747fSPaolo Bonzini
38849ab747fSPaolo Bonzini type_init(ssd03232_register_types)
389