root / hw / ssd0323.c @ 84dfb926
History | View | Annotate | Download (9.3 kB)
1 | 9ee6e8bb | pbrook | /*
|
---|---|---|---|
2 | 9ee6e8bb | pbrook | * SSD0323 OLED controller with OSRAM Pictiva 128x64 display.
|
3 | 9ee6e8bb | pbrook | *
|
4 | 9ee6e8bb | pbrook | * Copyright (c) 2006-2007 CodeSourcery.
|
5 | 9ee6e8bb | pbrook | * Written by Paul Brook
|
6 | 9ee6e8bb | pbrook | *
|
7 | 8e31bf38 | Matthew Fernandez | * This code is licensed under the GPL.
|
8 | 9ee6e8bb | pbrook | */
|
9 | 9ee6e8bb | pbrook | |
10 | 9ee6e8bb | pbrook | /* The controller can support a variety of different displays, but we only
|
11 | 9ee6e8bb | pbrook | implement one. Most of the commends relating to brightness and geometry
|
12 | 9ee6e8bb | pbrook | setup are ignored. */
|
13 | 5493e33f | Paul Brook | #include "ssi.h" |
14 | 87ecb68b | pbrook | #include "console.h" |
15 | 9ee6e8bb | pbrook | |
16 | 9ee6e8bb | pbrook | //#define DEBUG_SSD0323 1
|
17 | 9ee6e8bb | pbrook | |
18 | 9ee6e8bb | pbrook | #ifdef DEBUG_SSD0323
|
19 | 001faf32 | Blue Swirl | #define DPRINTF(fmt, ...) \
|
20 | 001faf32 | Blue Swirl | do { printf("ssd0323: " fmt , ## __VA_ARGS__); } while (0) |
21 | 001faf32 | Blue Swirl | #define BADF(fmt, ...) \
|
22 | 001faf32 | Blue Swirl | do { fprintf(stderr, "ssd0323: error: " fmt , ## __VA_ARGS__); exit(1);} while (0) |
23 | 9ee6e8bb | pbrook | #else
|
24 | 001faf32 | Blue Swirl | #define DPRINTF(fmt, ...) do {} while(0) |
25 | 001faf32 | Blue Swirl | #define BADF(fmt, ...) \
|
26 | 001faf32 | Blue Swirl | do { fprintf(stderr, "ssd0323: error: " fmt , ## __VA_ARGS__);} while (0) |
27 | 9ee6e8bb | pbrook | #endif
|
28 | 9ee6e8bb | pbrook | |
29 | 9ee6e8bb | pbrook | /* Scaling factor for pixels. */
|
30 | 9ee6e8bb | pbrook | #define MAGNIFY 4 |
31 | 9ee6e8bb | pbrook | |
32 | 7ac56ff0 | pbrook | #define REMAP_SWAP_COLUMN 0x01 |
33 | 7ac56ff0 | pbrook | #define REMAP_SWAP_NYBBLE 0x02 |
34 | 7ac56ff0 | pbrook | #define REMAP_VERTICAL 0x04 |
35 | 7ac56ff0 | pbrook | #define REMAP_SWAP_COM 0x10 |
36 | 7ac56ff0 | pbrook | #define REMAP_SPLIT_COM 0x40 |
37 | 7ac56ff0 | pbrook | |
38 | 9ee6e8bb | pbrook | enum ssd0323_mode
|
39 | 9ee6e8bb | pbrook | { |
40 | 9ee6e8bb | pbrook | SSD0323_CMD, |
41 | 9ee6e8bb | pbrook | SSD0323_DATA |
42 | 9ee6e8bb | pbrook | }; |
43 | 9ee6e8bb | pbrook | |
44 | 9ee6e8bb | pbrook | typedef struct { |
45 | 5493e33f | Paul Brook | SSISlave ssidev; |
46 | 9ee6e8bb | pbrook | DisplayState *ds; |
47 | 9ee6e8bb | pbrook | |
48 | 9ee6e8bb | pbrook | int cmd_len;
|
49 | 9ee6e8bb | pbrook | int cmd;
|
50 | 9ee6e8bb | pbrook | int cmd_data[8]; |
51 | 9ee6e8bb | pbrook | int row;
|
52 | 9ee6e8bb | pbrook | int row_start;
|
53 | 9ee6e8bb | pbrook | int row_end;
|
54 | 9ee6e8bb | pbrook | int col;
|
55 | 9ee6e8bb | pbrook | int col_start;
|
56 | 9ee6e8bb | pbrook | int col_end;
|
57 | 9ee6e8bb | pbrook | int redraw;
|
58 | 7ac56ff0 | pbrook | int remap;
|
59 | 9ee6e8bb | pbrook | enum ssd0323_mode mode;
|
60 | 9ee6e8bb | pbrook | uint8_t framebuffer[128 * 80 / 2]; |
61 | 9ee6e8bb | pbrook | } ssd0323_state; |
62 | 9ee6e8bb | pbrook | |
63 | 5493e33f | Paul Brook | static uint32_t ssd0323_transfer(SSISlave *dev, uint32_t data)
|
64 | 9ee6e8bb | pbrook | { |
65 | 5493e33f | Paul Brook | ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev); |
66 | 5493e33f | Paul Brook | |
67 | 9ee6e8bb | pbrook | switch (s->mode) {
|
68 | 9ee6e8bb | pbrook | case SSD0323_DATA:
|
69 | 9ee6e8bb | pbrook | DPRINTF("data 0x%02x\n", data);
|
70 | 9ee6e8bb | pbrook | s->framebuffer[s->col + s->row * 64] = data;
|
71 | 7ac56ff0 | pbrook | if (s->remap & REMAP_VERTICAL) {
|
72 | 9ee6e8bb | pbrook | s->row++; |
73 | 7ac56ff0 | pbrook | if (s->row > s->row_end) {
|
74 | 7ac56ff0 | pbrook | s->row = s->row_start; |
75 | 7ac56ff0 | pbrook | s->col++; |
76 | 7ac56ff0 | pbrook | } |
77 | 7ac56ff0 | pbrook | if (s->col > s->col_end) {
|
78 | 7ac56ff0 | pbrook | s->col = s->col_start; |
79 | 7ac56ff0 | pbrook | } |
80 | 7ac56ff0 | pbrook | } else {
|
81 | 7ac56ff0 | pbrook | s->col++; |
82 | 7ac56ff0 | pbrook | if (s->col > s->col_end) {
|
83 | 7ac56ff0 | pbrook | s->row++; |
84 | 7ac56ff0 | pbrook | s->col = s->col_start; |
85 | 7ac56ff0 | pbrook | } |
86 | 7ac56ff0 | pbrook | if (s->row > s->row_end) {
|
87 | 7ac56ff0 | pbrook | s->row = s->row_start; |
88 | 7ac56ff0 | pbrook | } |
89 | 9ee6e8bb | pbrook | } |
90 | 9ee6e8bb | pbrook | s->redraw = 1;
|
91 | 9ee6e8bb | pbrook | break;
|
92 | 9ee6e8bb | pbrook | case SSD0323_CMD:
|
93 | 9ee6e8bb | pbrook | DPRINTF("cmd 0x%02x\n", data);
|
94 | 9ee6e8bb | pbrook | if (s->cmd_len == 0) { |
95 | 9ee6e8bb | pbrook | s->cmd = data; |
96 | 9ee6e8bb | pbrook | } else {
|
97 | 9ee6e8bb | pbrook | s->cmd_data[s->cmd_len - 1] = data;
|
98 | 9ee6e8bb | pbrook | } |
99 | 9ee6e8bb | pbrook | s->cmd_len++; |
100 | 9ee6e8bb | pbrook | switch (s->cmd) {
|
101 | 9ee6e8bb | pbrook | #define DATA(x) if (s->cmd_len <= (x)) return 0 |
102 | 9ee6e8bb | pbrook | case 0x15: /* Set column. */ |
103 | 9ee6e8bb | pbrook | DATA(2);
|
104 | 7ac56ff0 | pbrook | s->col = s->col_start = s->cmd_data[0] % 64; |
105 | 9ee6e8bb | pbrook | s->col_end = s->cmd_data[1] % 64; |
106 | 9ee6e8bb | pbrook | break;
|
107 | 9ee6e8bb | pbrook | case 0x75: /* Set row. */ |
108 | 9ee6e8bb | pbrook | DATA(2);
|
109 | 7ac56ff0 | pbrook | s->row = s->row_start = s->cmd_data[0] % 80; |
110 | 9ee6e8bb | pbrook | s->row_end = s->cmd_data[1] % 80; |
111 | 9ee6e8bb | pbrook | break;
|
112 | 9ee6e8bb | pbrook | case 0x81: /* Set contrast */ |
113 | 9ee6e8bb | pbrook | DATA(1);
|
114 | 9ee6e8bb | pbrook | break;
|
115 | 9ee6e8bb | pbrook | case 0x84: case 0x85: case 0x86: /* Max current. */ |
116 | 9ee6e8bb | pbrook | DATA(0);
|
117 | 9ee6e8bb | pbrook | break;
|
118 | 9ee6e8bb | pbrook | case 0xa0: /* Set remapping. */ |
119 | 9ee6e8bb | pbrook | /* FIXME: Implement this. */
|
120 | 9ee6e8bb | pbrook | DATA(1);
|
121 | 7ac56ff0 | pbrook | s->remap = s->cmd_data[0];
|
122 | 9ee6e8bb | pbrook | break;
|
123 | 9ee6e8bb | pbrook | case 0xa1: /* Set display start line. */ |
124 | 9ee6e8bb | pbrook | case 0xa2: /* Set display offset. */ |
125 | 9ee6e8bb | pbrook | /* FIXME: Implement these. */
|
126 | 9ee6e8bb | pbrook | DATA(1);
|
127 | 9ee6e8bb | pbrook | break;
|
128 | 9ee6e8bb | pbrook | case 0xa4: /* Normal mode. */ |
129 | 9ee6e8bb | pbrook | case 0xa5: /* All on. */ |
130 | 9ee6e8bb | pbrook | case 0xa6: /* All off. */ |
131 | 9ee6e8bb | pbrook | case 0xa7: /* Inverse. */ |
132 | 9ee6e8bb | pbrook | /* FIXME: Implement these. */
|
133 | 9ee6e8bb | pbrook | DATA(0);
|
134 | 9ee6e8bb | pbrook | break;
|
135 | 9ee6e8bb | pbrook | case 0xa8: /* Set multiplex ratio. */ |
136 | 9ee6e8bb | pbrook | case 0xad: /* Set DC-DC converter. */ |
137 | 9ee6e8bb | pbrook | DATA(1);
|
138 | 9ee6e8bb | pbrook | /* Ignored. Don't care. */
|
139 | 9ee6e8bb | pbrook | break;
|
140 | 9ee6e8bb | pbrook | case 0xae: /* Display off. */ |
141 | 9ee6e8bb | pbrook | case 0xaf: /* Display on. */ |
142 | 9ee6e8bb | pbrook | DATA(0);
|
143 | 9ee6e8bb | pbrook | /* TODO: Implement power control. */
|
144 | 9ee6e8bb | pbrook | break;
|
145 | 9ee6e8bb | pbrook | case 0xb1: /* Set phase length. */ |
146 | 9ee6e8bb | pbrook | case 0xb2: /* Set row period. */ |
147 | 9ee6e8bb | pbrook | case 0xb3: /* Set clock rate. */ |
148 | 9ee6e8bb | pbrook | case 0xbc: /* Set precharge. */ |
149 | 9ee6e8bb | pbrook | case 0xbe: /* Set VCOMH. */ |
150 | 9ee6e8bb | pbrook | case 0xbf: /* Set segment low. */ |
151 | 9ee6e8bb | pbrook | DATA(1);
|
152 | 9ee6e8bb | pbrook | /* Ignored. Don't care. */
|
153 | 9ee6e8bb | pbrook | break;
|
154 | 9ee6e8bb | pbrook | case 0xb8: /* Set grey scale table. */ |
155 | 9ee6e8bb | pbrook | /* FIXME: Implement this. */
|
156 | 9ee6e8bb | pbrook | DATA(8);
|
157 | 9ee6e8bb | pbrook | break;
|
158 | 9ee6e8bb | pbrook | case 0xe3: /* NOP. */ |
159 | 9ee6e8bb | pbrook | DATA(0);
|
160 | 9ee6e8bb | pbrook | break;
|
161 | 775616c3 | pbrook | case 0xff: /* Nasty hack because we don't handle chip selects |
162 | 775616c3 | pbrook | properly. */
|
163 | 775616c3 | pbrook | break;
|
164 | 9ee6e8bb | pbrook | default:
|
165 | 9ee6e8bb | pbrook | BADF("Unknown command: 0x%x\n", data);
|
166 | 9ee6e8bb | pbrook | } |
167 | 9ee6e8bb | pbrook | s->cmd_len = 0;
|
168 | 9ee6e8bb | pbrook | return 0; |
169 | 9ee6e8bb | pbrook | } |
170 | 9ee6e8bb | pbrook | return 0; |
171 | 9ee6e8bb | pbrook | } |
172 | 9ee6e8bb | pbrook | |
173 | 9ee6e8bb | pbrook | static void ssd0323_update_display(void *opaque) |
174 | 9ee6e8bb | pbrook | { |
175 | 9ee6e8bb | pbrook | ssd0323_state *s = (ssd0323_state *)opaque; |
176 | 9ee6e8bb | pbrook | uint8_t *dest; |
177 | 9ee6e8bb | pbrook | uint8_t *src; |
178 | 9ee6e8bb | pbrook | int x;
|
179 | 9ee6e8bb | pbrook | int y;
|
180 | 9ee6e8bb | pbrook | int i;
|
181 | 9ee6e8bb | pbrook | int line;
|
182 | 9ee6e8bb | pbrook | char *colors[16]; |
183 | 9ee6e8bb | pbrook | char colortab[MAGNIFY * 64]; |
184 | 9ee6e8bb | pbrook | char *p;
|
185 | 9ee6e8bb | pbrook | int dest_width;
|
186 | 9ee6e8bb | pbrook | |
187 | b115bb3f | pbrook | if (!s->redraw)
|
188 | b115bb3f | pbrook | return;
|
189 | b115bb3f | pbrook | |
190 | 0e1f5a0c | aliguori | switch (ds_get_bits_per_pixel(s->ds)) {
|
191 | b115bb3f | pbrook | case 0: |
192 | b115bb3f | pbrook | return;
|
193 | b115bb3f | pbrook | case 15: |
194 | b115bb3f | pbrook | dest_width = 2;
|
195 | b115bb3f | pbrook | break;
|
196 | b115bb3f | pbrook | case 16: |
197 | b115bb3f | pbrook | dest_width = 2;
|
198 | b115bb3f | pbrook | break;
|
199 | b115bb3f | pbrook | case 24: |
200 | b115bb3f | pbrook | dest_width = 3;
|
201 | b115bb3f | pbrook | break;
|
202 | b115bb3f | pbrook | case 32: |
203 | b115bb3f | pbrook | dest_width = 4;
|
204 | b115bb3f | pbrook | break;
|
205 | b115bb3f | pbrook | default:
|
206 | b115bb3f | pbrook | BADF("Bad color depth\n");
|
207 | b115bb3f | pbrook | return;
|
208 | b115bb3f | pbrook | } |
209 | b115bb3f | pbrook | p = colortab; |
210 | b115bb3f | pbrook | for (i = 0; i < 16; i++) { |
211 | b115bb3f | pbrook | int n;
|
212 | b115bb3f | pbrook | colors[i] = p; |
213 | 0e1f5a0c | aliguori | switch (ds_get_bits_per_pixel(s->ds)) {
|
214 | 9ee6e8bb | pbrook | case 15: |
215 | b115bb3f | pbrook | n = i * 2 + (i >> 3); |
216 | b115bb3f | pbrook | p[0] = n | (n << 5); |
217 | b115bb3f | pbrook | p[1] = (n << 2) | (n >> 3); |
218 | 9ee6e8bb | pbrook | break;
|
219 | 9ee6e8bb | pbrook | case 16: |
220 | b115bb3f | pbrook | n = i * 2 + (i >> 3); |
221 | b115bb3f | pbrook | p[0] = n | (n << 6) | ((n << 1) & 0x20); |
222 | b115bb3f | pbrook | p[1] = (n << 3) | (n >> 2); |
223 | 9ee6e8bb | pbrook | break;
|
224 | 9ee6e8bb | pbrook | case 24: |
225 | 9ee6e8bb | pbrook | case 32: |
226 | b115bb3f | pbrook | n = (i << 4) | i;
|
227 | b115bb3f | pbrook | p[0] = p[1] = p[2] = n; |
228 | 9ee6e8bb | pbrook | break;
|
229 | 9ee6e8bb | pbrook | default:
|
230 | 9ee6e8bb | pbrook | BADF("Bad color depth\n");
|
231 | 9ee6e8bb | pbrook | return;
|
232 | 9ee6e8bb | pbrook | } |
233 | b115bb3f | pbrook | p += dest_width; |
234 | b115bb3f | pbrook | } |
235 | b115bb3f | pbrook | /* TODO: Implement row/column remapping. */
|
236 | 0e1f5a0c | aliguori | dest = ds_get_data(s->ds); |
237 | b115bb3f | pbrook | for (y = 0; y < 64; y++) { |
238 | b115bb3f | pbrook | line = y; |
239 | b115bb3f | pbrook | src = s->framebuffer + 64 * line;
|
240 | b115bb3f | pbrook | for (x = 0; x < 64; x++) { |
241 | b115bb3f | pbrook | int val;
|
242 | b115bb3f | pbrook | val = *src >> 4;
|
243 | b115bb3f | pbrook | for (i = 0; i < MAGNIFY; i++) { |
244 | b115bb3f | pbrook | memcpy(dest, colors[val], dest_width); |
245 | b115bb3f | pbrook | dest += dest_width; |
246 | 9ee6e8bb | pbrook | } |
247 | b115bb3f | pbrook | val = *src & 0xf;
|
248 | b115bb3f | pbrook | for (i = 0; i < MAGNIFY; i++) { |
249 | b115bb3f | pbrook | memcpy(dest, colors[val], dest_width); |
250 | b115bb3f | pbrook | dest += dest_width; |
251 | 9ee6e8bb | pbrook | } |
252 | b115bb3f | pbrook | src++; |
253 | b115bb3f | pbrook | } |
254 | b115bb3f | pbrook | for (i = 1; i < MAGNIFY; i++) { |
255 | b115bb3f | pbrook | memcpy(dest, dest - dest_width * MAGNIFY * 128,
|
256 | b115bb3f | pbrook | dest_width * 128 * MAGNIFY);
|
257 | b115bb3f | pbrook | dest += dest_width * 128 * MAGNIFY;
|
258 | 9ee6e8bb | pbrook | } |
259 | 9ee6e8bb | pbrook | } |
260 | b115bb3f | pbrook | s->redraw = 0;
|
261 | 9ee6e8bb | pbrook | dpy_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY); |
262 | 9ee6e8bb | pbrook | } |
263 | 9ee6e8bb | pbrook | |
264 | 9ee6e8bb | pbrook | static void ssd0323_invalidate_display(void * opaque) |
265 | 9ee6e8bb | pbrook | { |
266 | 9ee6e8bb | pbrook | ssd0323_state *s = (ssd0323_state *)opaque; |
267 | 9ee6e8bb | pbrook | s->redraw = 1;
|
268 | 9ee6e8bb | pbrook | } |
269 | 9ee6e8bb | pbrook | |
270 | 9ee6e8bb | pbrook | /* Command/data input. */
|
271 | 9ee6e8bb | pbrook | static void ssd0323_cd(void *opaque, int n, int level) |
272 | 9ee6e8bb | pbrook | { |
273 | 9ee6e8bb | pbrook | ssd0323_state *s = (ssd0323_state *)opaque; |
274 | 9ee6e8bb | pbrook | DPRINTF("%s mode\n", level ? "Data" : "Command"); |
275 | 9ee6e8bb | pbrook | s->mode = level ? SSD0323_DATA : SSD0323_CMD; |
276 | 9ee6e8bb | pbrook | } |
277 | 9ee6e8bb | pbrook | |
278 | 23e39294 | pbrook | static void ssd0323_save(QEMUFile *f, void *opaque) |
279 | 23e39294 | pbrook | { |
280 | 23e39294 | pbrook | ssd0323_state *s = (ssd0323_state *)opaque; |
281 | 23e39294 | pbrook | int i;
|
282 | 23e39294 | pbrook | |
283 | 23e39294 | pbrook | qemu_put_be32(f, s->cmd_len); |
284 | 23e39294 | pbrook | qemu_put_be32(f, s->cmd); |
285 | 23e39294 | pbrook | for (i = 0; i < 8; i++) |
286 | 23e39294 | pbrook | qemu_put_be32(f, s->cmd_data[i]); |
287 | 23e39294 | pbrook | qemu_put_be32(f, s->row); |
288 | 23e39294 | pbrook | qemu_put_be32(f, s->row_start); |
289 | 23e39294 | pbrook | qemu_put_be32(f, s->row_end); |
290 | 23e39294 | pbrook | qemu_put_be32(f, s->col); |
291 | 23e39294 | pbrook | qemu_put_be32(f, s->col_start); |
292 | 23e39294 | pbrook | qemu_put_be32(f, s->col_end); |
293 | 23e39294 | pbrook | qemu_put_be32(f, s->redraw); |
294 | 23e39294 | pbrook | qemu_put_be32(f, s->remap); |
295 | 23e39294 | pbrook | qemu_put_be32(f, s->mode); |
296 | 23e39294 | pbrook | qemu_put_buffer(f, s->framebuffer, sizeof(s->framebuffer));
|
297 | 23e39294 | pbrook | } |
298 | 23e39294 | pbrook | |
299 | 23e39294 | pbrook | static int ssd0323_load(QEMUFile *f, void *opaque, int version_id) |
300 | 23e39294 | pbrook | { |
301 | 23e39294 | pbrook | ssd0323_state *s = (ssd0323_state *)opaque; |
302 | 23e39294 | pbrook | int i;
|
303 | 23e39294 | pbrook | |
304 | 23e39294 | pbrook | if (version_id != 1) |
305 | 23e39294 | pbrook | return -EINVAL;
|
306 | 23e39294 | pbrook | |
307 | 23e39294 | pbrook | s->cmd_len = qemu_get_be32(f); |
308 | 23e39294 | pbrook | s->cmd = qemu_get_be32(f); |
309 | 23e39294 | pbrook | for (i = 0; i < 8; i++) |
310 | 23e39294 | pbrook | s->cmd_data[i] = qemu_get_be32(f); |
311 | 23e39294 | pbrook | s->row = qemu_get_be32(f); |
312 | 23e39294 | pbrook | s->row_start = qemu_get_be32(f); |
313 | 23e39294 | pbrook | s->row_end = qemu_get_be32(f); |
314 | 23e39294 | pbrook | s->col = qemu_get_be32(f); |
315 | 23e39294 | pbrook | s->col_start = qemu_get_be32(f); |
316 | 23e39294 | pbrook | s->col_end = qemu_get_be32(f); |
317 | 23e39294 | pbrook | s->redraw = qemu_get_be32(f); |
318 | 23e39294 | pbrook | s->remap = qemu_get_be32(f); |
319 | 23e39294 | pbrook | s->mode = qemu_get_be32(f); |
320 | 23e39294 | pbrook | qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer));
|
321 | 23e39294 | pbrook | |
322 | 23e39294 | pbrook | return 0; |
323 | 23e39294 | pbrook | } |
324 | 23e39294 | pbrook | |
325 | 81a322d4 | Gerd Hoffmann | static int ssd0323_init(SSISlave *dev) |
326 | 9ee6e8bb | pbrook | { |
327 | 5493e33f | Paul Brook | ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev); |
328 | 9ee6e8bb | pbrook | |
329 | 9ee6e8bb | pbrook | s->col_end = 63;
|
330 | 9ee6e8bb | pbrook | s->row_end = 79;
|
331 | 3023f332 | aliguori | s->ds = graphic_console_init(ssd0323_update_display, |
332 | 3023f332 | aliguori | ssd0323_invalidate_display, |
333 | 3023f332 | aliguori | NULL, NULL, s); |
334 | 3023f332 | aliguori | qemu_console_resize(s->ds, 128 * MAGNIFY, 64 * MAGNIFY); |
335 | 9ee6e8bb | pbrook | |
336 | 5493e33f | Paul Brook | qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
|
337 | 9ee6e8bb | pbrook | |
338 | 0be71e32 | Alex Williamson | register_savevm(&dev->qdev, "ssd0323_oled", -1, 1, |
339 | 0be71e32 | Alex Williamson | ssd0323_save, ssd0323_load, s); |
340 | 81a322d4 | Gerd Hoffmann | return 0; |
341 | 5493e33f | Paul Brook | } |
342 | 23e39294 | pbrook | |
343 | 5493e33f | Paul Brook | static SSISlaveInfo ssd0323_info = {
|
344 | 074f2fff | Gerd Hoffmann | .qdev.name = "ssd0323",
|
345 | 074f2fff | Gerd Hoffmann | .qdev.size = sizeof(ssd0323_state),
|
346 | 5493e33f | Paul Brook | .init = ssd0323_init, |
347 | 5493e33f | Paul Brook | .transfer = ssd0323_transfer |
348 | 5493e33f | Paul Brook | }; |
349 | 5493e33f | Paul Brook | |
350 | 5493e33f | Paul Brook | static void ssd03232_register_devices(void) |
351 | 5493e33f | Paul Brook | { |
352 | 074f2fff | Gerd Hoffmann | ssi_register_slave(&ssd0323_info); |
353 | 9ee6e8bb | pbrook | } |
354 | 5493e33f | Paul Brook | |
355 | 5493e33f | Paul Brook | device_init(ssd03232_register_devices) |