2 * OMAP2 Display Subsystem.
4 * Copyright (C) 2008 Nokia Corporation
5 * Written by Andrzej Zaborowski <andrew@openedhand.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 or
10 * (at your option) version 3 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "qemu-common.h"
28 #include "pixel_ops.h"
30 #define OMAP_DSS_DEBUG
31 //#define OMAP_DSS_DEBUG_REG
34 #define TRACE(fmt,...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
39 #ifdef OMAP_DSS_DEBUG_REG
40 #define TRACEREG(fmt,...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
41 #define LAYERNAME(n) ((!(n)) ? "GFX" : ((n)==1) ? "VID1" : "VID2")
46 struct omap3_lcd_panel_s {
47 struct omap_dss_s *dss;
49 omap3_lcd_panel_fn_t *line_fn_tab[2];
50 omap3_lcd_panel_fn_t line_fn;
65 struct omap_dss_panel_s {
73 struct omap3_lcd_panel_s *omap_lcd_panel[2];
87 uint32_t global_alpha;
92 struct omap_dss_plane_s {
104 target_phys_addr_t addr[3];
114 /* following for l1 & l2 only (VID1 and VID2) */
116 uint32_t fir_coef_h[8];
117 uint32_t fir_coef_hv[8];
118 uint32_t fir_coef_v[8];
119 uint32_t conv_coef[5];
120 uint32_t picture_size;
125 uint16_t palette[256];
141 struct rfbi_chip_s *chip[2];
150 static void omap_dss_interrupt_update(struct omap_dss_s *s)
153 (s->dsi.irqst & s->dsi.irqen)
154 | (s->dispc.irqst & s->dispc.irqen));
157 static void omap_rfbi_reset(struct omap_dss_s *s)
159 s->rfbi.idlemode = 0;
163 s->rfbi.skiplines = 0;
165 s->rfbi.config[0] = 0x00310000;
166 s->rfbi.config[1] = 0x00310000;
181 void omap_dss_reset(struct omap_dss_s *s)
185 s->autoidle = 0x10; /* was 0 for OMAP2 but bit4 must be set for OMAP3 */
199 s->dispc.idlemode = 0;
202 s->dispc.control = 0;
204 s->dispc.capable = 0x161;
205 s->dispc.timing[0] = 0;
206 s->dispc.timing[1] = 0;
207 s->dispc.timing[2] = 0;
208 s->dispc.timing[3] = 0x00010002;
212 s->dispc.trans[0] = 0;
213 s->dispc.trans[1] = 0;
214 s->dispc.global_alpha = 0;
215 s->dispc.cpr_coef_r = 0;
216 s->dispc.cpr_coef_g = 0;
217 s->dispc.cpr_coef_b = 0;
219 for (i = 0; i < 3; i++) {
220 s->dispc.l[i].enable = 0;
221 s->dispc.l[i].bpp = 0;
222 s->dispc.l[i].addr[0] = 0;
223 s->dispc.l[i].addr[1] = 0;
224 s->dispc.l[i].addr[2] = 0;
225 s->dispc.l[i].posx = 0;
226 s->dispc.l[i].posy = 0;
227 s->dispc.l[i].nx = 1;
228 s->dispc.l[i].ny = 1;
229 s->dispc.l[i].attr = 0;
230 s->dispc.l[i].tresh = (s->dispc.rev < 0x30) ? 0 : 0x03ff03c0;
231 s->dispc.l[i].rowinc = 1;
232 s->dispc.l[i].colinc = 1;
233 s->dispc.l[i].wininc = 0;
234 s->dispc.l[i].preload = 0x100;
235 s->dispc.l[i].fir = 0;
236 s->dispc.l[i].picture_size = 0;
237 s->dispc.l[i].accu[0] = 0;
238 s->dispc.l[i].accu[1] = 0;
239 for (j = 0; j < 5; j++)
240 s->dispc.l[i].conv_coef[j] = 0;
241 for (j = 0; j < 8; j++) {
242 s->dispc.l[i].fir_coef_h[j] = 0;
243 s->dispc.l[i].fir_coef_hv[j] = 0;
244 s->dispc.l[i].fir_coef_v[j] = 0;
252 omap_dss_interrupt_update(s);
255 static uint32_t omap_diss_read(void *opaque, target_phys_addr_t addr)
257 struct omap_dss_s *s = (struct omap_dss_s *) opaque;
261 case 0x00: /* DSS_REVISIONNUMBER */
262 TRACEREG("DSS_REVISIONNUMBER: 0x20");
265 case 0x10: /* DSS_SYSCONFIG */
266 TRACEREG("DSS_SYSCONFIG: 0x%08x", s->autoidle);
269 case 0x14: /* DSS_SYSSTATUS */
270 TRACEREG("DSS_SYSSTATUS: 0x1");
271 return 1; /* RESETDONE */
273 case 0x18: /* DSS_IRQSTATUS */
274 TRACEREG("DSS_IRQSTATUS: 0x%08x",
275 ((s->dsi.irqst & s->dsi.irqen) ? 2 : 0)
276 | ((s->dispc.irqst & s->dispc.irqen) ? 1 : 0));
277 return ((s->dsi.irqst & s->dsi.irqen) ? 2 : 0)
278 | ((s->dispc.irqst & s->dispc.irqen) ? 1 : 0);
280 case 0x40: /* DSS_CONTROL */
281 TRACEREG("DSS_CONTROL: 0x%08x", s->control);
284 case 0x44: /* DSS_SDI_CONTROL */
285 TRACEREG("DSS_SDI_CONTROL: 0x%08x", s->sdi_control);
286 return s->sdi_control;
288 case 0x48: /* DSS_PLL_CONTROL */
289 TRACEREG("DSS_PLL_CONTROL: 0x%08x", s->pll_control);
290 return s->pll_control;
292 case 0x50: /* DSS_PSA_LCD_REG_1 */
293 case 0x54: /* DSS_PSA_LCD_REG_2 */
294 case 0x58: /* DSS_PSA_VIDEO_REG */
295 TRACEREG("DSS_PSA_xxx: 0");
296 /* TODO: fake some values when appropriate s->control bits are set */
299 case 0x5c: /* DSS_SDI_STATUS */
300 /* TODO: check and implement missing OMAP3 bits */
301 TRACEREG("DSS_STATUS: 0x%08x", 1 + (s->control & 1));
302 return 1 + (s->control & 1);
311 static void omap_diss_write(void *opaque, target_phys_addr_t addr,
314 struct omap_dss_s *s = (struct omap_dss_s *) opaque;
317 case 0x00: /* DSS_REVISIONNUMBER */
318 case 0x14: /* DSS_SYSSTATUS */
319 case 0x18: /* DSS_IRQSTATUS */
320 case 0x50: /* DSS_PSA_LCD_REG_1 */
321 case 0x54: /* DSS_PSA_LCD_REG_2 */
322 case 0x58: /* DSS_PSA_VIDEO_REG */
323 case 0x5c: /* DSS_STATUS */
325 /*OMAP_RO_REGV(addr, value);*/
328 case 0x10: /* DSS_SYSCONFIG */
329 TRACEREG("DSS_SYSCONFIG = 0x%08x", value);
330 if (value & 2) /* SOFTRESET */
332 s->autoidle = value & 0x19; /* was 0x01 for OMAP2 */
335 case 0x40: /* DSS_CONTROL */
336 TRACEREG("DSS_CONTROL = 0x%08x", value);
337 s->control = value & 0x3ff; /* was 0x3dd for OMAP2 */
340 case 0x44: /* DSS_SDI_CONTROL */
341 TRACEREG("DSS_SDI_CONTROL = 0x%08x", value);
342 s->sdi_control = value & 0x000ff80f;
345 case 0x48: /* DSS_PLL_CONTROL */
346 TRACEREG("DSS_PLL_CONTROL = 0x%08x", value);
347 s->pll_control = value;
351 OMAP_BAD_REGV(addr, value);
356 static CPUReadMemoryFunc *omap_diss1_readfn[] = {
357 omap_badwidth_read32,
358 omap_badwidth_read32,
362 static CPUWriteMemoryFunc *omap_diss1_writefn[] = {
363 omap_badwidth_write32,
364 omap_badwidth_write32,
368 static uint32_t omap_disc_read(void *opaque, target_phys_addr_t addr)
370 struct omap_dss_s *s = (struct omap_dss_s *) opaque;
374 case 0x000: /* DISPC_REVISION */
375 TRACEREG("DISPC_REVISION: 0x%08x", s->dispc.rev);
377 case 0x010: /* DISPC_SYSCONFIG */
378 TRACEREG("DISPC_SYSCONFIG: 0x%08x", s->dispc.idlemode);
379 return s->dispc.idlemode;
380 case 0x014: /* DISPC_SYSSTATUS */
381 TRACEREG("DISPC_SYSSTATUS: 1");
382 return 1; /* RESETDONE */
383 case 0x018: /* DISPC_IRQSTATUS */
384 TRACEREG("DISPC_IRQSTATUS: 0x%08x", s->dispc.irqst);
385 return s->dispc.irqst;
386 case 0x01c: /* DISPC_IRQENABLE */
387 TRACEREG("DISPC_IRQENABLE: 0x%08x", s->dispc.irqen);
388 return s->dispc.irqen;
389 case 0x040: /* DISPC_CONTROL */
390 TRACEREG("DISPC_CONTROL: 0x%08x", s->dispc.control);
391 return s->dispc.control;
392 case 0x044: /* DISPC_CONFIG */
393 TRACEREG("DISPC_CONFIG: 0x%08x", s->dispc.config);
394 return s->dispc.config;
395 case 0x048: /* DISPC_CAPABLE */
396 TRACEREG("DISPC_CAPABLE: 0x%08x", s->dispc.capable);
397 return s->dispc.capable;
398 case 0x04c: /* DISPC_DEFAULT_COLOR0 */
399 TRACEREG("DISPC_DEFAULT_COLOR0: 0x%08x", s->dispc.bg[0]);
400 return s->dispc.bg[0];
401 case 0x050: /* DISPC_DEFAULT_COLOR1 */
402 TRACEREG("DISPC_DEFAULT_COLOR0: 0x%08x", s->dispc.bg[1]);
403 return s->dispc.bg[1];
404 case 0x054: /* DISPC_TRANS_COLOR0 */
405 TRACEREG("DISPC_TRANS_COLOR0: 0x%08x", s->dispc.trans[0]);
406 return s->dispc.trans[0];
407 case 0x058: /* DISPC_TRANS_COLOR1 */
408 TRACEREG("DISPC_TRANS_COLOR0: 0x%08x", s->dispc.trans[1]);
409 return s->dispc.trans[1];
410 case 0x05c: /* DISPC_LINE_STATUS */
411 TRACEREG("DISPC_LINE_STATUS: 0x7ff");
413 case 0x060: /* DISPC_LINE_NUMBER */
414 TRACEREG("DISPC_LINE_NUMBER: 0x%08x", s->dispc.line);
415 return s->dispc.line;
416 case 0x064: /* DISPC_TIMING_H */
417 TRACEREG("DISPC_TIMING_H: 0x%08x", s->dispc.timing[0]);
418 return s->dispc.timing[0];
419 case 0x068: /* DISPC_TIMING_V */
420 TRACEREG("DISPC_TIMING_H: 0x%08x", s->dispc.timing[1]);
421 return s->dispc.timing[1];
422 case 0x06c: /* DISPC_POL_FREQ */
423 TRACEREG("DISPC_POL_FREQ: 0x%08x", s->dispc.timing[2]);
424 return s->dispc.timing[2];
425 case 0x070: /* DISPC_DIVISOR */
426 TRACEREG("DISPC_DIVISOR: 0x%08x", s->dispc.timing[3]);
427 return s->dispc.timing[3];
428 case 0x074: /* DISPC_GLOBAL_ALPHA */
429 TRACEREG("DISPC_GLOBAL_ALPHA: 0x%08x", s->dispc.global_alpha);
430 return s->dispc.global_alpha;
431 case 0x078: /* DISPC_SIZE_DIG */
432 TRACEREG("DISPC_SIZE_DIG: 0x%08x", ((s->dig.ny - 1) << 16) | (s->dig.nx - 1));
433 return ((s->dig.ny - 1) << 16) | (s->dig.nx - 1);
434 case 0x07c: /* DISPC_SIZE_LCD */
435 TRACEREG("DISPC_SIZE_LCD: 0x%08x", ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1));
436 return ((s->lcd.ny - 1) << 16) | (s->lcd.nx - 1);
437 case 0x14c: /* DISPC_VID2_BA0 */
439 case 0x0bc: /* DISPC_VID1_BA0 */
441 case 0x080: /* DISPC_GFX_BA0 */
442 TRACEREG("DISPC_%s_BA0: 0x%08x", LAYERNAME(n), s->dispc.l[n].addr[0]);
443 return s->dispc.l[n].addr[0];
444 case 0x150: /* DISPC_VID2_BA1 */
446 case 0x0c0: /* DISPC_VID1_BA1 */
448 case 0x084: /* DISPC_GFX_BA1 */
449 TRACEREG("DISPC_%s_BA1: 0x%08x", LAYERNAME(n), s->dispc.l[n].addr[1]);
450 return s->dispc.l[n].addr[1];
451 case 0x154: /* DISPC_VID2_POSITION */
453 case 0x0c4: /* DISPC_VID1_POSITION */
455 case 0x088: /* DISPC_GFX_POSITION */
456 TRACEREG("DISPC_%s_POSITION: 0x%08x", LAYERNAME(n),
457 (s->dispc.l[n].posy << 16) | s->dispc.l[n].posx);
458 return (s->dispc.l[n].posy << 16) | s->dispc.l[n].posx;
459 case 0x158: /* DISPC_VID2_SIZE */
461 case 0x0c8: /* DISPC_VID1_SIZE */
463 case 0x08c: /* DISPC_GFX_SIZE */
464 TRACEREG("DISPC_%s_SIZE: 0x%08x", LAYERNAME(n),
465 ((s->dispc.l[n].ny - 1) << 16) | (s->dispc.l[n].nx - 1));
466 return ((s->dispc.l[n].ny - 1) << 16) | (s->dispc.l[n].nx - 1);
467 case 0x15c: /* DISPC_VID2_ATTRIBUTES */
469 case 0x0cc: /* DISPC_VID1_ATTRIBUTES */
471 case 0x0a0: /* DISPC_GFX_ATTRIBUTES */
472 TRACEREG("DISPC_%s_ATTRIBUTES: 0x%08x", LAYERNAME(n),
474 return s->dispc.l[n].attr;
475 case 0x160: /* DISPC_VID2_FIFO_THRESHOLD */
477 case 0x0d0: /* DISPC_VID1_FIFO_THRESHOLD */
479 case 0x0a4: /* DISPC_GFX_FIFO_TRESHOLD */
480 TRACEREG("DISPC_%s_THRESHOLD: 0x%08x", LAYERNAME(n),
481 s->dispc.l[n].tresh);
482 return s->dispc.l[n].tresh;
483 case 0x164: /* DISPC_VID2_FIFO_SIZE_STATUS */
485 case 0x0d4: /* DISPC_VID1_FIFO_SIZE_STATUS */
487 case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */
488 TRACEREG("DISPC_%s_FIFO_SIZE_STATUS: 0x%08x", LAYERNAME(n),
489 s->dispc.rev < 0x30 ? 256 : 1024);
490 return s->dispc.rev < 0x30 ? 256 : 1024;
491 case 0x168: /* DISPC_VID2_ROW_INC */
493 case 0x0d8: /* DISPC_VID1_ROW_INC */
495 case 0x0ac: /* DISPC_GFX_ROW_INC */
496 TRACEREG("DISPC_%s_ROW_INC: 0x%08x", LAYERNAME(n),
497 s->dispc.l[n].rowinc);
498 return s->dispc.l[n].rowinc;
499 case 0x16c: /* DISPC_VID2_PIXEL_INC */
501 case 0x0dc: /* DISPC_VID1_PIXEL_INC */
503 case 0x0b0: /* DISPC_GFX_PIXEL_INC */
504 TRACEREG("DISPC_%s_PIXEL_INC: 0x%08x", LAYERNAME(n),
505 s->dispc.l[n].colinc);
506 return s->dispc.l[n].colinc;
507 case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */
508 TRACEREG("DISPC_GFX_WINDOW_SKIP: 0x%08x", s->dispc.l[0].wininc);
509 return s->dispc.l[0].wininc;
510 case 0x0b8: /* DISPC_GFX_TABLE_BA */
511 TRACEREG("DISPC_GFX_TABLE_BA: 0x%08x", s->dispc.l[0].addr[2]);
512 return s->dispc.l[0].addr[2];
513 case 0x170: /* DISPC_VID2_FIR */
515 case 0x0e0: /* DISPC_VID1_FIR */
517 TRACEREG("DISPC_%s_FIR: 0x%08x", LAYERNAME(n),
519 return s->dispc.l[n].fir;
520 case 0x174: /* DISPC_VID2_PICTURE_SIZE */
522 case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */
524 TRACEREG("DISPC_%s_PICTURE_SIZE: 0x%08x", LAYERNAME(n),
525 s->dispc.l[n].picture_size);
526 return s->dispc.l[n].picture_size;
527 case 0x178: /* DISPC_VID2_ACCU0 */
528 case 0x17c: /* DISPC_VID2_ACCU1 */
530 case 0x0e8: /* DISPC_VID1_ACCU0 */
531 case 0x0ec: /* DISPC_VID1_ACCU1 */
533 TRACEREG("DISPC_%s_ACCU%d: 0x%08x", LAYERNAME(n),
534 (addr >> 1) & 1, s->dispc.l[n].accu[(addr >> 1 ) & 1]);
535 return s->dispc.l[n].accu[(addr >> 1) & 1];
536 case 0x180 ... 0x1bc: /* DISPC_VID2_FIR_COEF */
538 case 0x0f0 ... 0x12c: /* DISPC_VID1_FIR_COEF */
541 TRACEREG("DISPC_%s_FIR_COEF_HV%d: 0x%08x", LAYERNAME(n),
542 (addr - ((n > 1) ? 0x180 : 0xf0)) / 8,
543 s->dispc.l[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8]);
544 return s->dispc.l[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8];
546 TRACEREG("DISPC_%s_FIR_COEF_H%d: 0x%08x", LAYERNAME(n),
547 (addr - ((n > 1) ? 0x180 : 0xf0)) / 8,
548 s->dispc.l[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8]);
549 return s->dispc.l[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8];
550 case 0x1c0 ... 0x1d0: /* DISPC_VID2_CONV_COEFi */
552 case 0x130 ... 0x140: /* DISPC_VID1_CONV_COEFi */
554 TRACEREG("DISPC_%s_CONV_COEF%d: 0x%08x", LAYERNAME(n),
555 (addr - ((n > 1) ? 0x1c0 : 0x130)) / 4,
556 s->dispc.l[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4]);
557 return s->dispc.l[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4];
558 case 0x1d4: /* DISPC_DATA_CYCLE1 */
559 case 0x1d8: /* DISPC_DATA_CYCLE2 */
560 case 0x1dc: /* DISPC_DATA_CYCLE3 */
561 TRACEREG("DISPC_DATA_CYCLE%d: 0", (addr - 0x1d4) / 4);
563 case 0x200 ... 0x21c: /* DISPC_VID2_FIR_COEF_Vi */
565 case 0x1e0 ... 0x1fc: /* DISPC_VID1_FIR_COEF_Vi */
567 TRACEREG("DISPC_%s_FIR_COEF_V%d: 0x%08x", LAYERNAME(n),
569 s->dispc.l[n].fir_coef_v[(addr & 0x01f) / 4]);
570 return s->dispc.l[n].fir_coef_v[(addr & 0x01f) / 4];
571 case 0x220: /* DISPC_CPR_COEF_R */
572 TRACEREG("DISPC_CPR_COEF_R: 0x%08x", s->dispc.cpr_coef_r);
573 return s->dispc.cpr_coef_r;
574 case 0x224: /* DISPC_CPR_COEF_G */
575 TRACEREG("DISPC_CPR_COEF_G: 0x%08x", s->dispc.cpr_coef_g);
576 return s->dispc.cpr_coef_g;
577 case 0x228: /* DISPC_CPR_COEF_B */
578 TRACEREG("DISPC_CPR_COEF_B: 0x%08x", s->dispc.cpr_coef_b);
579 return s->dispc.cpr_coef_b;
580 case 0x234: /* DISPC_VID2_PRELOAD */
582 case 0x230: /* DISPC_VID1_PRELOAD */
584 case 0x22c: /* DISPC_GFX_PRELOAD */
585 TRACEREG("DISPC_%s_PRELOAD: 0x%08x", LAYERNAME(n),
586 s->dispc.l[n].preload);
587 return s->dispc.l[n].preload;
595 static void omap_disc_write(void *opaque, target_phys_addr_t addr,
598 struct omap_dss_s *s = (struct omap_dss_s *) opaque;
602 case 0x000: /* DISPC_REVISION */
603 case 0x014: /* DISPC_SYSSTATUS */
604 case 0x05c: /* DISPC_LINE_STATUS */
605 case 0x0a8: /* DISPC_GFX_FIFO_SIZE_STATUS */
607 /*OMAP_RO_REGV(addr, value);*/
609 case 0x010: /* DISPC_SYSCONFIG */
610 TRACEREG("DISPC_SYSCONFIG = 0x%08x", value);
611 if (value & 2) /* SOFTRESET */
613 s->dispc.idlemode = value & ((s->dispc.rev < 0x30) ? 0x301b : 0x331f);
615 case 0x018: /* DISPC_IRQSTATUS */
616 TRACEREG("DISPC_IRQSTATUS = 0x%08x", value);
617 s->dispc.irqst &= ~value;
618 omap_dss_interrupt_update(s);
620 case 0x01c: /* DISPC_IRQENABLE */
621 TRACEREG("DISPC_IRQENABLE = 0x%08x", value);
622 s->dispc.irqen = value & ((s->dispc.rev < 0x30) ? 0xffff : 0x1ffff);
623 omap_dss_interrupt_update(s);
625 case 0x040: /* DISPC_CONTROL */
626 TRACEREG("DISPC_CONTROL = 0x%08x", value);
627 if (s->dispc.rev < 0x30)
628 s->dispc.control = value & 0x07ff9fff;
630 s->dispc.control = (value & 0xffff9bff) | (s->dispc.control & 0x6000);
631 s->dig.enable = (value >> 1) & 1;
632 s->lcd.enable = (value >> 0) & 1;
633 if (value & (1 << 12)) /* OVERLAY_OPTIMIZATION */
634 if (~((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1))
635 fprintf(stderr, "%s: Overlay Optimization when no overlay "
636 "region effectively exists leads to "
637 "unpredictable behaviour!\n", __FUNCTION__);
638 if (value & (1 << 6)) { /* GODIGITAL */
639 /* XXX: Shadowed fields are:
655 * s->dispc.l[0].addr[0]
656 * s->dispc.l[0].addr[1]
657 * s->dispc.l[0].addr[2]
662 * s->dispc.l[0].tresh
663 * s->dispc.l[0].rowinc
664 * s->dispc.l[0].colinc
665 * s->dispc.l[0].wininc
666 * All they need to be loaded here from their shadow registers.
668 s->dispc.control &= ~(1 << 6); /* GODIGITAL finished */
670 if (value & (1 << 5)) { /* GOLCD */
671 /* XXX: Likewise for LCD here. */
672 s->dispc.control &= ~(1 << 5); /* GOLCD finished */
674 s->dispc.invalidate = 1;
676 case 0x044: /* DISPC_CONFIG */
677 TRACEREG("DISPC_CONFIG = 0x%08x", value);
678 s->dispc.config = value & 0x3fff;
680 * bits 2:1 (LOADMODE) reset to 0 after set to 1 and palette loaded
681 * bits 2:1 (LOADMODE) reset to 2 after set to 3 and palette loaded
683 s->dispc.invalidate = 1;
685 case 0x048: /* DISPC_CAPABLE */
686 TRACEREG("DISPC_CAPABLE = 0x%08x", value);
687 s->dispc.capable = value & 0x3ff;
689 case 0x04c: /* DISPC_DEFAULT_COLOR0 */
690 TRACEREG("DISPC_DEFAULT_COLOR0 = 0x%08x", value);
691 s->dispc.bg[0] = value & 0xffffff;
692 s->dispc.invalidate = 1;
694 case 0x050: /* DISPC_DEFAULT_COLOR1 */
695 TRACEREG("DISPC_DEFAULT_COLOR1 = 0x%08x", value);
696 s->dispc.bg[1] = value & 0xffffff;
697 s->dispc.invalidate = 1;
699 case 0x054: /* DISPC_TRANS_COLOR0 */
700 TRACEREG("DISPC_TRANS_COLOR0 = 0x%08x", value);
701 s->dispc.trans[0] = value & 0xffffff;
702 s->dispc.invalidate = 1;
704 case 0x058: /* DISPC_TRANS_COLOR1 */
705 TRACEREG("DISPC_TRANS_COLOR1 = 0x%08x", value);
706 s->dispc.trans[1] = value & 0xffffff;
707 s->dispc.invalidate = 1;
709 case 0x060: /* DISPC_LINE_NUMBER */
710 TRACEREG("DISPC_LINE_NUMBER = 0x%08x", value);
711 s->dispc.line = value & 0x7ff;
713 case 0x064: /* DISPC_TIMING_H */
714 TRACEREG("DISPC_TIMING_H = 0x%08x", value);
715 s->dispc.timing[0] = value & 0x0ff0ff3f;
717 case 0x068: /* DISPC_TIMING_V */
718 TRACEREG("DISPC_TIMING_V = 0x%08x", value);
719 s->dispc.timing[1] = value & 0x0ff0ff3f;
721 case 0x06c: /* DISPC_POL_FREQ */
722 TRACEREG("DISPC_POL_FREQ = 0x%08x", value);
723 s->dispc.timing[2] = value & 0x0003ffff;
725 case 0x070: /* DISPC_DIVISOR */
726 TRACEREG("DISPC_DIVISOR = 0x%08x", value);
727 s->dispc.timing[3] = value & 0x00ff00ff;
729 case 0x074: /* DISPC_GLOBAL_ALPHA */
730 TRACEREG("DISPC_GLOBAL_ALPHA = 0x%08x", value);
731 s->dispc.global_alpha = value & 0x00ff00ff;
733 case 0x078: /* DISPC_SIZE_DIG */
734 s->dig.nx = ((value >> 0) & 0x7ff) + 1; /* PPL */
735 s->dig.ny = ((value >> 16) & 0x7ff) + 1; /* LPP */
736 s->dispc.invalidate = 1;
737 TRACEREG("DISPC_SIZE_DIG = 0x%08x (%dx%d)", value, s->dig.nx, s->dig.ny);
739 case 0x07c: /* DISPC_SIZE_LCD */
740 s->lcd.nx = ((value >> 0) & 0x7ff) + 1; /* PPL */
741 s->lcd.ny = ((value >> 16) & 0x7ff) + 1; /* LPP */
742 s->dispc.invalidate = 1;
743 TRACEREG("DISPC_SIZE_LCD = 0x%08x (%dx%d)", value, s->lcd.nx, s->lcd.ny);
745 case 0x14c: /* DISPC_VID2_BA0 */
747 case 0x0bc: /* DISPC_VID1_BA0 */
749 case 0x080: /* DISPC_GFX_BA0 */
750 TRACEREG("DISPC_%s_BA0 = 0x%08x", LAYERNAME(n), value);
751 s->dispc.l[n].addr[0] = (target_phys_addr_t) value;
752 s->dispc.invalidate = 1;
754 case 0x150: /* DISPC_VID2_BA1 */
756 case 0x0c0: /* DISPC_VID1_BA1 */
758 case 0x084: /* DISPC_GFX_BA1 */
759 TRACEREG("DISPC_%s_BA1 = 0x%08x", LAYERNAME(n), value);
760 s->dispc.l[n].addr[1] = (target_phys_addr_t) value;
761 s->dispc.invalidate = 1;
763 case 0x154: /* DISPC_VID2_POSITION */
765 case 0x0c4: /* DISPC_VID1_POSITION */
767 case 0x088: /* DISPC_GFX_POSITION */
768 s->dispc.l[n].posx = ((value >> 0) & 0x7ff); /* GFXPOSX */
769 s->dispc.l[n].posy = ((value >> 16) & 0x7ff); /* GFXPOSY */
770 s->dispc.invalidate = 1;
771 TRACEREG("DISPC_%s_POSITION = 0x%08x (%d,%d)", LAYERNAME(n),
772 value, s->dispc.l[n].posx, s->dispc.l[n].posy);
774 case 0x158: /* DISPC_VID2_SIZE */
776 case 0x0c8: /* DISPC_VID1_SIZE */
778 case 0x08c: /* DISPC_GFX_SIZE */
779 s->dispc.l[n].nx = ((value >> 0) & 0x7ff) + 1; /* GFXSIZEX */
780 s->dispc.l[n].ny = ((value >> 16) & 0x7ff) + 1; /* GFXSIZEY */
781 TRACEREG("DISPC_%s_SIZE = 0x%08x (%dx%d)", LAYERNAME(n),
782 value, s->dispc.l[n].nx, s->dispc.l[n].ny);
783 s->dispc.invalidate = 1;
786 case 0x0a0: /* DISPC_GFX_ATTRIBUTES */
787 TRACEREG("DISPC_GFX_ATTRIBUTES = 0x%08x", value);
788 s->dispc.l[0].attr = value & 0xffff;
789 if (value & (3 << 9))
790 fprintf(stderr, "%s: Big-endian pixel format not supported\n",
792 s->dispc.l[0].enable = value & 1;
793 s->dispc.l[0].bpp = (value >> 1) & 0xf;
794 s->dispc.l[0].rotation_flag = (value >> 12) & 0x3;
795 s->dispc.l[0].gfx_format = (value >> 1) & 0xf;
796 s->dispc.l[0].gfx_channel = (value >> 8) & 0x1;
797 s->dispc.invalidate = 1;
799 case 0x160: /* DISPC_VID2_FIFO_TRESHOLD */
801 case 0x0d0: /* DISPC_VID1_FIFO_TRESHOLD */
803 case 0x0a4: /* DISPC_GFX_FIFO_THRESHOLD */
804 TRACEREG("DISPC_%s_FIFO_THRESHOLD = 0x%08x", LAYERNAME(n), value);
805 s->dispc.l[n].tresh = value & ((s->dispc.rev < 0x30)
806 ? 0x01ff01ff : 0x0fff0fff);
808 case 0x168: /* DISPC_VID2_ROW_INC */
810 case 0x0d8: /* DISPC_VID1_ROW_INC */
812 case 0x0ac: /* DISPC_GFX_ROW_INC */
813 TRACEREG("DISPC_%s_ROW_INC = 0x%08x", LAYERNAME(n), value);
814 s->dispc.l[n].rowinc = value;
815 s->dispc.invalidate = 1;
817 case 0x16c: /* DISPC_VID2_PIXEL_INC */
819 case 0x0dc: /* DISPC_VID1_PIXEL_INC */
821 case 0x0b0: /* DISPC_GFX_PIXEL_INC */
822 TRACEREG("DISPC_%s_PIXEL_INC = 0x%08x", LAYERNAME(n), value);
823 s->dispc.l[n].colinc = value;
824 s->dispc.invalidate = 1;
826 case 0x0b4: /* DISPC_GFX_WINDOW_SKIP */
827 TRACEREG("DISPC_GFX_WINDOW_SKIP = 0x%08x", value);
828 s->dispc.l[0].wininc = value;
830 case 0x0b8: /* DISPC_GFX_TABLE_BA */
831 TRACEREG("DISPC_GFX_TABLE_BA = 0x%08x", value);
832 s->dispc.l[0].addr[2] = (target_phys_addr_t) value;
833 s->dispc.invalidate = 1;
835 case 0x15c: /* DISPC_VID2_ATTRIBUTES */
837 case 0x0cc: /* DISPC_VID1_ATTRIBUTES */
839 TRACEREG("DISPC_%s_ATTRIBUTES = 0x%08x", LAYERNAME(n), value);
840 s->dispc.l[n].attr = value & 0x1fffffff;
842 case 0x170: /* DISPC_VID2_FIR */
844 case 0x0e0: /* DISPC_VID1_FIR */
846 TRACEREG("DISPC_%s_FIR = 0x%08x", LAYERNAME(n), value);
847 s->dispc.l[n].fir = value & 0x1fff1fff;
849 case 0x174: /* DISPC_VID2_PICTURE_SIZE */
851 case 0x0e4: /* DISPC_VID1_PICTURE_SIZE */
853 TRACEREG("DISPC_%s_PICTURE_SIZE = 0x%08x", LAYERNAME(n), value);
854 s->dispc.l[n].picture_size = value & 0x07ff07ff;
856 case 0x178: /* DISPC_VID2_ACCU0 */
857 case 0x17c: /* DISPC_VID2_ACCU1 */
859 case 0x0e8: /* DISPC_VID1_ACCU0 */
860 case 0x0ec: /* DISPC_VID1_ACCU1 */
862 TRACEREG("DISPC_%s_ACCU%d = 0x%08x", LAYERNAME(n),
863 (addr >> 1) & 1, value);
864 s->dispc.l[n].accu[(addr >> 1) & 1] = value & 0x03ff03ff;
866 case 0x180 ... 0x1bc: /* DISPC_VID2_FIR_COEF */
868 case 0x0f0 ... 0x12c: /* DISPC_VID1_FIR_COEF */
871 TRACEREG("DISPC_%s_FIR_COEF_HV%d = 0x%08x", LAYERNAME(n),
872 (addr - ((n > 1) ? 0x180 : 0xf0)) / 8, value);
873 s->dispc.l[n].fir_coef_hv[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8] = value;
875 TRACEREG("DISPC_%s_FIR_COEF_H%d = 0x%08x", LAYERNAME(n),
876 (addr - ((n > 1) ? 0x180 : 0xf0)) / 8, value);
877 s->dispc.l[n].fir_coef_h[(addr - ((n > 1) ? 0x180 : 0xf0)) / 8] = value;
880 case 0x1c0 ... 0x1d0: /* DISPC_VID2_CONV_COEFi */
882 case 0x130 ... 0x140: /* DISPC_VID1_CONV_COEFi */
884 TRACEREG("DISPC_%s_CONV_COEF%d = 0x%08x", LAYERNAME(n),
885 (addr - ((n > 1) ? 0x1c0 : 0x130)) / 4, value);
886 s->dispc.l[n].conv_coef[(addr - ((n > 1) ? 0x1c0 : 0x130)) / 4] = value;
888 case 0x1d4: /* DISPC_DATA_CYCLE1 */
889 case 0x1d8: /* DISPC_DATA_CYCLE2 */
890 case 0x1dc: /* DISPC_DATA_CYCLE3 */
891 TRACEREG("DISPC_DATA_CYCLE%d = 0x%08x (ignored)", (addr - 0x1d4) / 4, value);
893 case 0x200 ... 0x21c: /* DISPC_VID2_FIR_COEF_Vi */
895 case 0x1e0 ... 0x1fc: /* DISPC_VID1_FIR_COEF_Vi */
897 TRACEREG("DISPC_%s_FIR_COEF_V%d = 0x%08x", LAYERNAME(n),
898 (addr & 0x01f) / 4, value);
899 s->dispc.l[n].fir_coef_v[(addr & 0x01f) / 4] = value & 0x0000ffff;
901 case 0x220: /* DISPC_CPR_COEF_R */
902 TRACEREG("DISPC_CPR_COEF_R = 0x%08x", value);
903 s->dispc.cpr_coef_r = value & 0xffbffbff;
905 case 0x224: /* DISPC_CPR_COEF_G */
906 TRACEREG("DISPC_CPR_COEF_G = 0x%08x", value);
907 s->dispc.cpr_coef_g = value & 0xffbffbff;
909 case 0x228: /* DISPC_CPR_COEF_B */
910 TRACEREG("DISPC_CPR_COEF_B = 0x%08x", value);
911 s->dispc.cpr_coef_b = value & 0xffbffbff;
913 case 0x234: /* DISPC_VID2_PRELOAD */
915 case 0x230: /* DISPC_VID1_PRELOAD */
917 case 0x22c: /* DISPC_GFX_PRELOAD */
918 TRACEREG("DISPC_%s_PRELOAD = 0x%08x", LAYERNAME(n), value);
919 s->dispc.l[n].preload = value & 0x0fff;
922 OMAP_BAD_REGV(addr, value);
927 static CPUReadMemoryFunc *omap_disc1_readfn[] = {
928 omap_badwidth_read32,
929 omap_badwidth_read32,
933 static CPUWriteMemoryFunc *omap_disc1_writefn[] = {
934 omap_badwidth_write32,
935 omap_badwidth_write32,
939 static void *omap_rfbi_get_buffer(struct omap_dss_s *s)
941 target_phys_addr_t fb;
945 fb = s->dispc.l[0].addr[0];
947 pd = cpu_get_physical_page_desc(fb);
948 if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
950 cpu_abort(cpu_single_env, "%s: framebuffer outside RAM!\n",
953 return phys_ram_base +
954 (pd & TARGET_PAGE_MASK) +
955 (fb & ~TARGET_PAGE_MASK);
958 static void omap_rfbi_transfer_stop(struct omap_dss_s *s)
963 /* TODO: in non-Bypass mode we probably need to just deassert the DRQ. */
968 static void omap_rfbi_transfer_start(struct omap_dss_s *s)
974 if (!s->rfbi.enable || s->rfbi.busy)
977 if (s->rfbi.control & (1 << 1)) { /* BYPASS */
978 /* TODO: in non-Bypass mode we probably need to just assert the
979 * DRQ and wait for DMA to write the pixels. */
980 fprintf(stderr, "%s: Bypass mode unimplemented\n", __FUNCTION__);
984 if (!(s->dispc.control & (1 << 11))) /* RFBIMODE */
986 /* TODO: check that LCD output is enabled in DISPC. */
990 data = omap_rfbi_get_buffer(s);
993 len = s->rfbi.pixels * 2;
996 /* TODO: negative values */
997 pitch = s->dispc.l[0].nx + (s->dispc.l[0].rowinc - 1) / 2;
999 if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1000 s->rfbi.chip[0]->block(s->rfbi.chip[0]->opaque, 1, data, len, pitch);
1001 if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1002 s->rfbi.chip[1]->block(s->rfbi.chip[1]->opaque, 1, data, len, pitch);
1004 omap_rfbi_transfer_stop(s);
1007 s->dispc.irqst |= 1; /* FRAMEDONE */
1008 omap_dss_interrupt_update(s);
1011 static uint32_t omap_rfbi_read(void *opaque, target_phys_addr_t addr)
1013 struct omap_dss_s *s = (struct omap_dss_s *) opaque;
1016 case 0x00: /* RFBI_REVISION */
1017 TRACEREG("RFBI_REVISION: 0x10");
1020 case 0x10: /* RFBI_SYSCONFIG */
1021 TRACEREG("RFBI_SYSCONFIG: 0x%08x", s->rfbi.idlemode);
1022 return s->rfbi.idlemode;
1024 case 0x14: /* RFBI_SYSSTATUS */
1025 TRACEREG("RFBI_SYSSTATUS: 0x%08x", 1 | (s->rfbi.busy << 8));
1026 return 1 | (s->rfbi.busy << 8); /* RESETDONE */
1028 case 0x40: /* RFBI_CONTROL */
1029 TRACEREG("RFBI_CONTROL: 0x%08x", s->rfbi.control);
1030 return s->rfbi.control;
1032 case 0x44: /* RFBI_PIXELCNT */
1033 TRACEREG("RFBI_PIXELCNT: 0x%08x", s->rfbi.pixels);
1034 return s->rfbi.pixels;
1036 case 0x48: /* RFBI_LINE_NUMBER */
1037 TRACEREG("RFBI_LINE_NUMBER: 0x%08x", s->rfbi.skiplines);
1038 return s->rfbi.skiplines;
1040 case 0x58: /* RFBI_READ */
1041 case 0x5c: /* RFBI_STATUS */
1042 TRACEREG("RFBI_READ/STATUS: 0x%08x", s->rfbi.rxbuf);
1043 return s->rfbi.rxbuf;
1045 case 0x60: /* RFBI_CONFIG0 */
1046 TRACEREG("RFBI_CONFIG0: 0x%08x", s->rfbi.config[0]);
1047 return s->rfbi.config[0];
1048 case 0x64: /* RFBI_ONOFF_TIME0 */
1049 TRACEREG("RFBI_ONOFF_TIME0: 0x%08x", s->rfbi.time[0]);
1050 return s->rfbi.time[0];
1051 case 0x68: /* RFBI_CYCLE_TIME0 */
1052 TRACEREG("RFBI_CYCLE_TIME0: 0x%08x", s->rfbi.time[1]);
1053 return s->rfbi.time[1];
1054 case 0x6c: /* RFBI_DATA_CYCLE1_0 */
1055 TRACEREG("RFBI_DATA_CYCLE1_0: 0x%08x", s->rfbi.data[0]);
1056 return s->rfbi.data[0];
1057 case 0x70: /* RFBI_DATA_CYCLE2_0 */
1058 TRACEREG("RFBI_DATA_CYCLE2_0: 0x%08x", s->rfbi.data[1]);
1059 return s->rfbi.data[1];
1060 case 0x74: /* RFBI_DATA_CYCLE3_0 */
1061 TRACEREG("RFBI_DATA_CYCLE3_0: 0x%08x", s->rfbi.data[2]);
1062 return s->rfbi.data[2];
1064 case 0x78: /* RFBI_CONFIG1 */
1065 TRACEREG("RFBI_CONFIG1: 0x%08x", s->rfbi.config[1]);
1066 return s->rfbi.config[1];
1067 case 0x7c: /* RFBI_ONOFF_TIME1 */
1068 TRACEREG("RFBI_ONOFF_TIME1: 0x%08x", s->rfbi.time[2]);
1069 return s->rfbi.time[2];
1070 case 0x80: /* RFBI_CYCLE_TIME1 */
1071 TRACEREG("RFBI_CYCLE_TIME1: 0x%08x", s->rfbi.time[3]);
1072 return s->rfbi.time[3];
1073 case 0x84: /* RFBI_DATA_CYCLE1_1 */
1074 TRACEREG("RFBI_DATA_CYCLE1_1: 0x%08x", s->rfbi.data[3]);
1075 return s->rfbi.data[3];
1076 case 0x88: /* RFBI_DATA_CYCLE2_1 */
1077 TRACEREG("RFBI_DATA_CYCLE2_1: 0x%08x", s->rfbi.data[4]);
1078 return s->rfbi.data[4];
1079 case 0x8c: /* RFBI_DATA_CYCLE3_1 */
1080 TRACEREG("RFBI_DATA_CYCLE3_1: 0x%08x", s->rfbi.data[5]);
1081 return s->rfbi.data[5];
1083 case 0x90: /* RFBI_VSYNC_WIDTH */
1084 TRACEREG("RFBI_VSYNC_WIDTH: 0x%08x", s->rfbi.vsync);
1085 return s->rfbi.vsync;
1086 case 0x94: /* RFBI_HSYNC_WIDTH */
1087 TRACEREG("RFBI_HSYNC_WIDTH: 0x%08x", s->rfbi.hsync);
1088 return s->rfbi.hsync;
1094 static void omap_rfbi_write(void *opaque, target_phys_addr_t addr,
1097 struct omap_dss_s *s = (struct omap_dss_s *) opaque;
1100 case 0x10: /* RFBI_SYSCONFIG */
1101 TRACEREG("RFBI_SYSCONFIG = 0x%08x", value);
1102 if (value & 2) /* SOFTRESET */
1104 s->rfbi.idlemode = value & 0x19;
1107 case 0x40: /* RFBI_CONTROL */
1108 TRACEREG("RFBI_CONTROL = 0x%08x", value);
1109 s->rfbi.control = value & 0xf;
1110 s->rfbi.enable = value & 1;
1111 if (value & (1 << 4) && /* ITE */
1112 !(s->rfbi.config[0] & s->rfbi.config[1] & 0xc))
1113 omap_rfbi_transfer_start(s);
1116 case 0x44: /* RFBI_PIXELCNT */
1117 TRACEREG("RFBI_PIXELCNT = 0x%08x", value);
1118 s->rfbi.pixels = value;
1121 case 0x48: /* RFBI_LINE_NUMBER */
1122 TRACEREG("RFBI_LINE_NUMBER = 0x%08x", value);
1123 s->rfbi.skiplines = value & 0x7ff;
1126 case 0x4c: /* RFBI_CMD */
1127 TRACEREG("RFBI_CMD = 0x%08x", value);
1128 if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1129 s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 0, value & 0xffff);
1130 if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1131 s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 0, value & 0xffff);
1133 case 0x50: /* RFBI_PARAM */
1134 TRACEREG("RFBI_PARAM = 0x%08x", value);
1135 if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1136 s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
1137 if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1138 s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
1140 case 0x54: /* RFBI_DATA */
1141 TRACEREG("RFBI_DATA = 0x%08x", value);
1142 /* TODO: take into account the format set up in s->rfbi.config[?] and
1143 * s->rfbi.data[?], but special-case the most usual scenario so that
1144 * speed doesn't suffer. */
1145 if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0]) {
1146 s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value & 0xffff);
1147 s->rfbi.chip[0]->write(s->rfbi.chip[0]->opaque, 1, value >> 16);
1149 if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1]) {
1150 s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value & 0xffff);
1151 s->rfbi.chip[1]->write(s->rfbi.chip[1]->opaque, 1, value >> 16);
1153 if (!-- s->rfbi.pixels)
1154 omap_rfbi_transfer_stop(s);
1156 case 0x58: /* RFBI_READ */
1157 TRACEREG("RFBI_READ = 0x%08x", value);
1158 if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1159 s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
1160 else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1161 s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 1);
1162 if (!-- s->rfbi.pixels)
1163 omap_rfbi_transfer_stop(s);
1166 case 0x5c: /* RFBI_STATUS */
1167 TRACEREG("RFBI_STATUS = 0x%08x", value);
1168 if ((s->rfbi.control & (1 << 2)) && s->rfbi.chip[0])
1169 s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
1170 else if ((s->rfbi.control & (1 << 3)) && s->rfbi.chip[1])
1171 s->rfbi.rxbuf = s->rfbi.chip[0]->read(s->rfbi.chip[0]->opaque, 0);
1172 if (!-- s->rfbi.pixels)
1173 omap_rfbi_transfer_stop(s);
1176 case 0x60: /* RFBI_CONFIG0 */
1177 TRACEREG("RFBI_CONFIG0 = 0x%08x", value);
1178 s->rfbi.config[0] = value & 0x003f1fff;
1181 case 0x64: /* RFBI_ONOFF_TIME0 */
1182 TRACEREG("RFBI_ONOFF_TIME0 = 0x%08x", value);
1183 s->rfbi.time[0] = value & 0x3fffffff;
1185 case 0x68: /* RFBI_CYCLE_TIME0 */
1186 TRACEREG("RFBI_CYCLE_TIME0 = 0x%08x", value);
1187 s->rfbi.time[1] = value & 0x0fffffff;
1189 case 0x6c: /* RFBI_DATA_CYCLE1_0 */
1190 TRACEREG("RFBI_DATA_CYCLE1_0 = 0x%08x", value);
1191 s->rfbi.data[0] = value & 0x0f1f0f1f;
1193 case 0x70: /* RFBI_DATA_CYCLE2_0 */
1194 TRACEREG("RFBI_DATA_CYCLE2_0 = 0x%08x", value);
1195 s->rfbi.data[1] = value & 0x0f1f0f1f;
1197 case 0x74: /* RFBI_DATA_CYCLE3_0 */
1198 TRACEREG("RFBI_DATA_CYCLE3_0 = 0x%08x", value);
1199 s->rfbi.data[2] = value & 0x0f1f0f1f;
1201 case 0x78: /* RFBI_CONFIG1 */
1202 TRACEREG("RFBI_CONFIG1 = 0x%08x", value);
1203 s->rfbi.config[1] = value & 0x003f1fff;
1206 case 0x7c: /* RFBI_ONOFF_TIME1 */
1207 TRACEREG("RFBI_ONOFF_TIME1 = 0x%08x", value);
1208 s->rfbi.time[2] = value & 0x3fffffff;
1210 case 0x80: /* RFBI_CYCLE_TIME1 */
1211 TRACEREG("RFBI_CYCLE_TIME1 = 0x%08x", value);
1212 s->rfbi.time[3] = value & 0x0fffffff;
1214 case 0x84: /* RFBI_DATA_CYCLE1_1 */
1215 TRACEREG("RFBI_DATA_CYCLE1_1 = 0x%08x", value);
1216 s->rfbi.data[3] = value & 0x0f1f0f1f;
1218 case 0x88: /* RFBI_DATA_CYCLE2_1 */
1219 TRACEREG("RFBI_DATA_CYCLE2_1 = 0x%08x", value);
1220 s->rfbi.data[4] = value & 0x0f1f0f1f;
1222 case 0x8c: /* RFBI_DATA_CYCLE3_1 */
1223 TRACEREG("RFBI_DATA_CYCLE3_1 = 0x%08x", value);
1224 s->rfbi.data[5] = value & 0x0f1f0f1f;
1227 case 0x90: /* RFBI_VSYNC_WIDTH */
1228 TRACEREG("RFBI_VSYNC_WIDTH = 0x%08x", value);
1229 s->rfbi.vsync = value & 0xffff;
1231 case 0x94: /* RFBI_HSYNC_WIDTH */
1232 TRACEREG("RFBI_HSYNC_WIDTH = 0x%08x", value);
1233 s->rfbi.hsync = value & 0xffff;
1237 OMAP_BAD_REGV(addr, value);
1242 static CPUReadMemoryFunc *omap_rfbi1_readfn[] = {
1243 omap_badwidth_read32,
1244 omap_badwidth_read32,
1248 static CPUWriteMemoryFunc *omap_rfbi1_writefn[] = {
1249 omap_badwidth_write32,
1250 omap_badwidth_write32,
1254 static uint32_t omap_venc_read(void *opaque, target_phys_addr_t addr)
1257 case 0x00: /* REV_ID */
1258 case 0x04: /* STATUS */
1259 case 0x08: /* F_CONTROL */
1260 case 0x10: /* VIDOUT_CTRL */
1261 case 0x14: /* SYNC_CTRL */
1262 case 0x1c: /* LLEN */
1263 case 0x20: /* FLENS */
1264 case 0x24: /* HFLTR_CTRL */
1265 case 0x28: /* CC_CARR_WSS_CARR */
1266 case 0x2c: /* C_PHASE */
1267 case 0x30: /* GAIN_U */
1268 case 0x34: /* GAIN_V */
1269 case 0x38: /* GAIN_Y */
1270 case 0x3c: /* BLACK_LEVEL */
1271 case 0x40: /* BLANK_LEVEL */
1272 case 0x44: /* X_COLOR */
1273 case 0x48: /* M_CONTROL */
1274 case 0x4c: /* BSTAMP_WSS_DATA */
1275 case 0x50: /* S_CARR */
1276 case 0x54: /* LINE21 */
1277 case 0x58: /* LN_SEL */
1278 case 0x5c: /* L21__WC_CTL */
1279 case 0x60: /* HTRIGGER_VTRIGGER */
1280 case 0x64: /* SAVID__EAVID */
1281 case 0x68: /* FLEN__FAL */
1282 case 0x6c: /* LAL__PHASE_RESET */
1283 case 0x70: /* HS_INT_START_STOP_X */
1284 case 0x74: /* HS_EXT_START_STOP_X */
1285 case 0x78: /* VS_INT_START_X */
1286 case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */
1287 case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */
1288 case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */
1289 case 0x88: /* VS_EXT_STOP_Y */
1290 case 0x90: /* AVID_START_STOP_X */
1291 case 0x94: /* AVID_START_STOP_Y */
1292 case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */
1293 case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */
1294 case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
1295 case 0xb0: /* TVDETGP_INT_START_STOP_X */
1296 case 0xb4: /* TVDETGP_INT_START_STOP_Y */
1297 case 0xb8: /* GEN_CTRL */
1298 case 0xc4: /* DAC_TST__DAC_A */
1299 case 0xc8: /* DAC_B__DAC_C */
1309 static void omap_venc_write(void *opaque, target_phys_addr_t addr,
1313 case 0x08: /* F_CONTROL */
1314 case 0x10: /* VIDOUT_CTRL */
1315 case 0x14: /* SYNC_CTRL */
1316 case 0x1c: /* LLEN */
1317 case 0x20: /* FLENS */
1318 case 0x24: /* HFLTR_CTRL */
1319 case 0x28: /* CC_CARR_WSS_CARR */
1320 case 0x2c: /* C_PHASE */
1321 case 0x30: /* GAIN_U */
1322 case 0x34: /* GAIN_V */
1323 case 0x38: /* GAIN_Y */
1324 case 0x3c: /* BLACK_LEVEL */
1325 case 0x40: /* BLANK_LEVEL */
1326 case 0x44: /* X_COLOR */
1327 case 0x48: /* M_CONTROL */
1328 case 0x4c: /* BSTAMP_WSS_DATA */
1329 case 0x50: /* S_CARR */
1330 case 0x54: /* LINE21 */
1331 case 0x58: /* LN_SEL */
1332 case 0x5c: /* L21__WC_CTL */
1333 case 0x60: /* HTRIGGER_VTRIGGER */
1334 case 0x64: /* SAVID__EAVID */
1335 case 0x68: /* FLEN__FAL */
1336 case 0x6c: /* LAL__PHASE_RESET */
1337 case 0x70: /* HS_INT_START_STOP_X */
1338 case 0x74: /* HS_EXT_START_STOP_X */
1339 case 0x78: /* VS_INT_START_X */
1340 case 0x7c: /* VS_INT_STOP_X__VS_INT_START_Y */
1341 case 0x80: /* VS_INT_STOP_Y__VS_INT_START_X */
1342 case 0x84: /* VS_EXT_STOP_X__VS_EXT_START_Y */
1343 case 0x88: /* VS_EXT_STOP_Y */
1344 case 0x90: /* AVID_START_STOP_X */
1345 case 0x94: /* AVID_START_STOP_Y */
1346 case 0xa0: /* FID_INT_START_X__FID_INT_START_Y */
1347 case 0xa4: /* FID_INT_OFFSET_Y__FID_EXT_START_X */
1348 case 0xa8: /* FID_EXT_START_Y__FID_EXT_OFFSET_Y */
1349 case 0xb0: /* TVDETGP_INT_START_STOP_X */
1350 case 0xb4: /* TVDETGP_INT_START_STOP_Y */
1351 case 0xb8: /* GEN_CTRL */
1352 case 0xc4: /* DAC_TST__DAC_A */
1353 case 0xc8: /* DAC_B__DAC_C */
1357 OMAP_BAD_REGV(addr, value);
1362 static CPUReadMemoryFunc *omap_venc1_readfn[] = {
1363 omap_badwidth_read32,
1364 omap_badwidth_read32,
1368 static CPUWriteMemoryFunc *omap_venc1_writefn[] = {
1369 omap_badwidth_write32,
1370 omap_badwidth_write32,
1374 static uint32_t omap_im3_read(void *opaque, target_phys_addr_t addr)
1377 case 0x0a8: /* SBIMERRLOGA */
1378 case 0x0b0: /* SBIMERRLOG */
1379 case 0x190: /* SBIMSTATE */
1380 case 0x198: /* SBTMSTATE_L */
1381 case 0x19c: /* SBTMSTATE_H */
1382 case 0x1a8: /* SBIMCONFIG_L */
1383 case 0x1ac: /* SBIMCONFIG_H */
1384 case 0x1f8: /* SBID_L */
1385 case 0x1fc: /* SBID_H */
1395 static void omap_im3_write(void *opaque, target_phys_addr_t addr,
1399 case 0x0b0: /* SBIMERRLOG */
1400 case 0x190: /* SBIMSTATE */
1401 case 0x198: /* SBTMSTATE_L */
1402 case 0x19c: /* SBTMSTATE_H */
1403 case 0x1a8: /* SBIMCONFIG_L */
1404 case 0x1ac: /* SBIMCONFIG_H */
1408 OMAP_BAD_REGV(addr, value);
1413 static CPUReadMemoryFunc *omap_im3_readfn[] = {
1414 omap_badwidth_read32,
1415 omap_badwidth_read32,
1419 static CPUWriteMemoryFunc *omap_im3_writefn[] = {
1420 omap_badwidth_write32,
1421 omap_badwidth_write32,
1425 static uint32_t omap_dsi_read(void *opaque, target_phys_addr_t addr)
1427 fprintf(stderr, "%s: DSI register " OMAP_FMT_plx " not implemented!\n",
1428 __FUNCTION__, addr);
1432 static void omap_dsi_write(void *opaque, target_phys_addr_t addr,
1435 fprintf(stderr, "%s: DSI register " OMAP_FMT_plx " not implemented!\n",
1436 __FUNCTION__, addr);
1439 static CPUReadMemoryFunc *omap_dsi_readfn[] = {
1440 omap_badwidth_read32,
1441 omap_badwidth_read32,
1445 static CPUWriteMemoryFunc *omap_dsi_writefn[] = {
1446 omap_badwidth_write32,
1447 omap_badwidth_write32,
1451 struct omap_dss_s *omap_dss_init(struct omap_mpu_state_s *mpu,
1452 struct omap_target_agent_s *ta,
1453 qemu_irq irq, qemu_irq drq,
1454 omap_clk fck1, omap_clk fck2, omap_clk ck54m,
1455 omap_clk ick1, omap_clk ick2)
1458 int region_base = 0;
1459 struct omap_dss_s *s = (struct omap_dss_s *)
1460 qemu_mallocz(sizeof(struct omap_dss_s));
1465 iomemtype[0] = l4_register_io_memory(0, omap_diss1_readfn,
1466 omap_diss1_writefn, s);
1467 iomemtype[1] = l4_register_io_memory(0, omap_disc1_readfn,
1468 omap_disc1_writefn, s);
1469 iomemtype[2] = l4_register_io_memory(0, omap_rfbi1_readfn,
1470 omap_rfbi1_writefn, s);
1471 iomemtype[3] = l4_register_io_memory(0, omap_venc1_readfn,
1472 omap_venc1_writefn, s);
1474 if (cpu_class_omap3(mpu)) {
1475 s->dispc.rev = 0x30;
1477 iomemtype[4] = l4_register_io_memory(0, omap_dsi_readfn,
1478 omap_dsi_writefn, s);
1479 omap_l4_attach(ta, 0, iomemtype[4]);
1482 s->dispc.rev = 0x20;
1484 iomemtype[4] = cpu_register_io_memory(0, omap_im3_readfn,
1485 omap_im3_writefn, s);
1486 cpu_register_physical_memory(0x68000800, 0x1000, iomemtype[4]);
1489 omap_l4_attach(ta, region_base+0, iomemtype[0]); /* DISS */
1490 omap_l4_attach(ta, region_base+1, iomemtype[1]); /* DISC */
1491 omap_l4_attach(ta, region_base+2, iomemtype[2]); /* RFBI */
1492 omap_l4_attach(ta, region_base+3, iomemtype[3]); /* VENC */
1497 s->state = graphic_console_init(omap_update_display,
1498 omap_invalidate_display, omap_screen_dump, s);
1504 void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip)
1506 if (cs < 0 || cs > 1)
1507 cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
1508 s->rfbi.chip[cs] = chip;
1511 void omap3_lcd_panel_attach(struct omap_dss_s *dss,
1513 struct omap3_lcd_panel_s *lcd_panel)
1515 if (cs < 0 || cs > 1)
1516 cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
1517 dss->omap_lcd_panel[cs] = lcd_panel;
1518 lcd_panel->dss = dss;
1521 /*omap3 lcd panel stuff*/
1523 /* Bytes(!) per pixel */
1524 static const int omap3_lcd_panel_bpp[0x10] = {
1525 0, /* 0x0: BITMAP1 (CLUT) */
1526 0, /* 0x1: BITMAP2 (CLUT) */
1527 0, /* 0x2: BITMAP4 (CLUT) */
1528 0, /* 0x3: BITMAP8 (CLUT) */
1529 2, /* 0x4: RGB12 (unpacked 16-bit container)*/
1530 2, /* 0x5: ARGB16 */
1532 0, /* 0x7: reserved */
1533 4, /* 0x8: RGB24 (unpacked in 32-bit container) */
1534 3, /* 0x9: RGB24 (packed in 24-bit container) */
1535 0, /* 0xa: reserved */
1536 0, /* 0xb: reserved */
1537 4, /* 0xc: ARGB32 */
1538 4, /* 0xd: RGBA32 */
1539 4, /* 0xe: RGBx32 (24-bit RGB aligned on MSB of the 32-bit container) */
1540 0, /* 0xf: reserved */
1543 static inline void omap3_lcd_panel_invalidate_display(void *opaque)
1545 struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque;
1549 static void omap3_lcd_panel_update_display(void *opaque)
1551 struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque;
1552 struct omap_dss_s *dss = s->dss;
1553 const uint32_t lcd_width = dss->lcd.nx;
1554 const uint32_t lcd_height = dss->lcd.ny;
1555 uint32_t graphic_width, graphic_height;
1556 uint32_t start_x, start_y;
1557 const uint32_t lcd_Bpp = omap3_lcd_panel_bpp[dss->dispc.l[0].gfx_format];
1559 uint32_t linesize, y;
1560 uint32_t copy_width, copy_height;
1561 uint8_t *src, *dest;
1563 if (!dss->lcd.enable
1564 || dss->dispc.l[0].gfx_channel /* 24bit digital out */
1565 || ((dss->dispc.control & (1 << 11))) /* RFBI */
1569 /* check for setup changes since last visit only if flagged */
1570 if (dss->dispc.invalidate) {
1571 dss->dispc.invalidate = 0;
1572 if (!(dss->dispc.l[0].rotation_flag)) { /* rotation*/
1573 s->line_fn = s->line_fn_tab[0][dss->dispc.l[0].gfx_format];
1575 fprintf(stderr, "%s: rotation is not supported \n", __FUNCTION__);
1579 fprintf(stderr, "%s:s->line_fn is NULL. Not supported gfx_format \n", __FUNCTION__);
1582 if (lcd_width != ds_get_width(s->state)
1583 || lcd_height != ds_get_height(s->state)) {
1584 qemu_console_resize(s->state, lcd_width, lcd_height);
1590 graphic_width = dss->dispc.l[0].nx;
1591 graphic_height = dss->dispc.l[0].ny;
1592 start_x = dss->dispc.l[0].posx;
1593 start_y = dss->dispc.l[0].posy;
1595 /*use the rfbi function*/
1596 src = (uint8_t *)omap_rfbi_get_buffer(dss);
1597 dest = ds_get_data(s->state);
1598 linesize = ds_get_linesize(s->state);
1600 dss_Bpp = linesize / ds_get_width(s->state);
1602 dest += linesize * start_y;
1603 dest += start_x * dss_Bpp;
1605 if ((start_x + graphic_width) > lcd_width)
1606 copy_width = lcd_width - start_x;
1608 copy_width = graphic_width;
1609 copy_height = lcd_height>graphic_height ? graphic_height:lcd_height;
1611 for (y = start_y; y < copy_height; y++) {
1612 s->line_fn(dest, src, copy_width * lcd_Bpp);
1613 src += graphic_width * lcd_Bpp;
1617 dpy_update(s->state, start_x, start_y, graphic_width, graphic_height);
1620 dss->dispc.irqst |= 1; /* FRAMEDONE */
1621 omap_dss_interrupt_update(dss);
1626 #include "omap3_lcd_panel_template.h"
1628 #include "omap3_lcd_panel_template.h"
1630 #include "omap3_lcd_panel_template.h"
1632 #include "omap3_lcd_panel_template.h"
1634 #include "omap3_lcd_panel_template.h"
1636 void *omap3_lcd_panel_init()
1638 struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *) qemu_mallocz(sizeof(*s));
1640 s->state = graphic_console_init(omap3_lcd_panel_update_display,
1641 omap3_lcd_panel_invalidate_display,
1644 switch (ds_get_bits_per_pixel(s->state)) {
1646 s->line_fn_tab[0] = s->line_fn_tab[1] =
1647 qemu_mallocz(sizeof(omap3_lcd_panel_fn_t) * 0x10);
1650 s->line_fn_tab[0] = omap3_lcd_panel_draw_fn_8;
1651 s->line_fn_tab[1] = omap3_lcd_panel_draw_fn_r_8;
1654 s->line_fn_tab[0] = omap3_lcd_panel_draw_fn_15;
1655 s->line_fn_tab[1] = omap3_lcd_panel_draw_fn_r_15;
1658 s->line_fn_tab[0] = omap3_lcd_panel_draw_fn_16;
1659 s->line_fn_tab[1] = omap3_lcd_panel_draw_fn_r_16;
1662 s->line_fn_tab[0] = omap3_lcd_panel_draw_fn_24;
1663 s->line_fn_tab[1] = omap3_lcd_panel_draw_fn_r_24;
1666 s->line_fn_tab[0] = omap3_lcd_panel_draw_fn_32;
1667 s->line_fn_tab[1] = omap3_lcd_panel_draw_fn_r_32;
1670 fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);