Commit 64b40bc54a92beb5958e78c915629bbe4a9bc28c
1 parent
4ea29f74
tc6393xb: non-accelerated FB support (Dmitry Baryshkov).
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com> Signed-off-by: Andrzej Zaborowski <andrew.zaborowski@intel.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5617 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
207 additions
and
8 deletions
hw/devices.h
| @@ -66,9 +66,11 @@ void tusb6010_power(struct tusb_s *s, int on); | @@ -66,9 +66,11 @@ void tusb6010_power(struct tusb_s *s, int on); | ||
| 66 | 66 | ||
| 67 | /* tc6393xb.c */ | 67 | /* tc6393xb.c */ |
| 68 | struct tc6393xb_s; | 68 | struct tc6393xb_s; |
| 69 | -struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq); | 69 | +#define TC6393XB_RAM 0x110000 /* amount of ram for Video and USB */ |
| 70 | +struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq, DisplayState *ds); | ||
| 70 | void tc6393xb_gpio_out_set(struct tc6393xb_s *s, int line, | 71 | void tc6393xb_gpio_out_set(struct tc6393xb_s *s, int line, |
| 71 | qemu_irq handler); | 72 | qemu_irq handler); |
| 72 | qemu_irq *tc6393xb_gpio_in_get(struct tc6393xb_s *s); | 73 | qemu_irq *tc6393xb_gpio_in_get(struct tc6393xb_s *s); |
| 74 | +qemu_irq tc6393xb_l3v_get(struct tc6393xb_s *s); | ||
| 73 | 75 | ||
| 74 | #endif | 76 | #endif |
hw/tc6393xb.c
| @@ -11,6 +11,8 @@ | @@ -11,6 +11,8 @@ | ||
| 11 | #include "pxa.h" | 11 | #include "pxa.h" |
| 12 | #include "devices.h" | 12 | #include "devices.h" |
| 13 | #include "flash.h" | 13 | #include "flash.h" |
| 14 | +#include "console.h" | ||
| 15 | +#include "pixel_ops.h" | ||
| 14 | 16 | ||
| 15 | #define IRQ_TC6393_NAND 0 | 17 | #define IRQ_TC6393_NAND 0 |
| 16 | #define IRQ_TC6393_MMC 1 | 18 | #define IRQ_TC6393_MMC 1 |
| @@ -119,6 +121,14 @@ struct tc6393xb_s { | @@ -119,6 +121,14 @@ struct tc6393xb_s { | ||
| 119 | uint32_t nand_phys; | 121 | uint32_t nand_phys; |
| 120 | struct nand_flash_s *flash; | 122 | struct nand_flash_s *flash; |
| 121 | struct ecc_state_s ecc; | 123 | struct ecc_state_s ecc; |
| 124 | + | ||
| 125 | + DisplayState *ds; | ||
| 126 | + QEMUConsole *console; | ||
| 127 | + ram_addr_t vram_addr; | ||
| 128 | + uint32_t scr_width, scr_height; /* in pixels */ | ||
| 129 | + qemu_irq l3v; | ||
| 130 | + unsigned blank : 1, | ||
| 131 | + blanked : 1; | ||
| 122 | }; | 132 | }; |
| 123 | 133 | ||
| 124 | qemu_irq *tc6393xb_gpio_in_get(struct tc6393xb_s *s) | 134 | qemu_irq *tc6393xb_gpio_in_get(struct tc6393xb_s *s) |
| @@ -164,6 +174,18 @@ static void tc6393xb_gpio_handler_update(struct tc6393xb_s *s) | @@ -164,6 +174,18 @@ static void tc6393xb_gpio_handler_update(struct tc6393xb_s *s) | ||
| 164 | s->prev_level = level; | 174 | s->prev_level = level; |
| 165 | } | 175 | } |
| 166 | 176 | ||
| 177 | +qemu_irq tc6393xb_l3v_get(struct tc6393xb_s *s) | ||
| 178 | +{ | ||
| 179 | + return s->l3v; | ||
| 180 | +} | ||
| 181 | + | ||
| 182 | +static void tc6393xb_l3v(void *opaque, int line, int level) | ||
| 183 | +{ | ||
| 184 | + struct tc6393xb_s *s = opaque; | ||
| 185 | + s->blank = !level; | ||
| 186 | + fprintf(stderr, "L3V: %d\n", level); | ||
| 187 | +} | ||
| 188 | + | ||
| 167 | static void tc6393xb_sub_irq(void *opaque, int line, int level) { | 189 | static void tc6393xb_sub_irq(void *opaque, int line, int level) { |
| 168 | struct tc6393xb_s *s = opaque; | 190 | struct tc6393xb_s *s = opaque; |
| 169 | uint8_t isr = s->scr.ISR; | 191 | uint8_t isr = s->scr.ISR; |
| @@ -395,6 +417,85 @@ static void tc6393xb_nand_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, | @@ -395,6 +417,85 @@ static void tc6393xb_nand_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, | ||
| 395 | (uint32_t) addr, value & 0xff); | 417 | (uint32_t) addr, value & 0xff); |
| 396 | } | 418 | } |
| 397 | 419 | ||
| 420 | +#define BITS 8 | ||
| 421 | +#include "tc6393xb_template.h" | ||
| 422 | +#define BITS 15 | ||
| 423 | +#include "tc6393xb_template.h" | ||
| 424 | +#define BITS 16 | ||
| 425 | +#include "tc6393xb_template.h" | ||
| 426 | +#define BITS 24 | ||
| 427 | +#include "tc6393xb_template.h" | ||
| 428 | +#define BITS 32 | ||
| 429 | +#include "tc6393xb_template.h" | ||
| 430 | + | ||
| 431 | +static void tc6393xb_draw_graphic(struct tc6393xb_s *s, int full_update) | ||
| 432 | +{ | ||
| 433 | + switch (s->ds->depth) { | ||
| 434 | + case 8: | ||
| 435 | + tc6393xb_draw_graphic8(s); | ||
| 436 | + break; | ||
| 437 | + case 15: | ||
| 438 | + tc6393xb_draw_graphic15(s); | ||
| 439 | + break; | ||
| 440 | + case 16: | ||
| 441 | + tc6393xb_draw_graphic16(s); | ||
| 442 | + break; | ||
| 443 | + case 24: | ||
| 444 | + tc6393xb_draw_graphic24(s); | ||
| 445 | + break; | ||
| 446 | + case 32: | ||
| 447 | + tc6393xb_draw_graphic32(s); | ||
| 448 | + break; | ||
| 449 | + default: | ||
| 450 | + printf("tc6393xb: unknown depth %d\n", s->ds->depth); | ||
| 451 | + return; | ||
| 452 | + } | ||
| 453 | + | ||
| 454 | + dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); | ||
| 455 | +} | ||
| 456 | + | ||
| 457 | +static void tc6393xb_draw_blank(struct tc6393xb_s *s, int full_update) | ||
| 458 | +{ | ||
| 459 | + int i, w; | ||
| 460 | + uint8_t *d; | ||
| 461 | + | ||
| 462 | + if (!full_update) | ||
| 463 | + return; | ||
| 464 | + | ||
| 465 | + w = s->scr_width * ((s->ds->depth + 7) >> 3); | ||
| 466 | + d = s->ds->data; | ||
| 467 | + for(i = 0; i < s->scr_height; i++) { | ||
| 468 | + memset(d, 0, w); | ||
| 469 | + d += s->ds->linesize; | ||
| 470 | + } | ||
| 471 | + | ||
| 472 | + dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); | ||
| 473 | +} | ||
| 474 | + | ||
| 475 | +static void tc6393xb_update_display(void *opaque) | ||
| 476 | +{ | ||
| 477 | + struct tc6393xb_s *s = opaque; | ||
| 478 | + int full_update; | ||
| 479 | + | ||
| 480 | + if (s->scr_width == 0 || s->scr_height == 0) | ||
| 481 | + return; | ||
| 482 | + | ||
| 483 | + full_update = 0; | ||
| 484 | + if (s->blanked != s->blank) { | ||
| 485 | + s->blanked = s->blank; | ||
| 486 | + full_update = 1; | ||
| 487 | + } | ||
| 488 | + if (s->scr_width != s->ds->width || s->scr_height != s->ds->height) { | ||
| 489 | + qemu_console_resize(s->console, s->scr_width, s->scr_height); | ||
| 490 | + full_update = 1; | ||
| 491 | + } | ||
| 492 | + if (s->blanked) | ||
| 493 | + tc6393xb_draw_blank(s, full_update); | ||
| 494 | + else | ||
| 495 | + tc6393xb_draw_graphic(s, full_update); | ||
| 496 | +} | ||
| 497 | + | ||
| 498 | + | ||
| 398 | static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr) { | 499 | static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr) { |
| 399 | struct tc6393xb_s *s = opaque; | 500 | struct tc6393xb_s *s = opaque; |
| 400 | addr -= s->target_base; | 501 | addr -= s->target_base; |
| @@ -465,7 +566,7 @@ static void tc6393xb_writel(void *opaque, target_phys_addr_t addr, uint32_t valu | @@ -465,7 +566,7 @@ static void tc6393xb_writel(void *opaque, target_phys_addr_t addr, uint32_t valu | ||
| 465 | tc6393xb_writeb(opaque, addr + 3, value >> 24); | 566 | tc6393xb_writeb(opaque, addr + 3, value >> 24); |
| 466 | } | 567 | } |
| 467 | 568 | ||
| 468 | -struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq) | 569 | +struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq, DisplayState *ds) |
| 469 | { | 570 | { |
| 470 | int iomemtype; | 571 | int iomemtype; |
| 471 | struct tc6393xb_s *s; | 572 | struct tc6393xb_s *s; |
| @@ -485,13 +586,30 @@ struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq) | @@ -485,13 +586,30 @@ struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq) | ||
| 485 | s->irq = irq; | 586 | s->irq = irq; |
| 486 | s->gpio_in = qemu_allocate_irqs(tc6393xb_gpio_set, s, TC6393XB_GPIOS); | 587 | s->gpio_in = qemu_allocate_irqs(tc6393xb_gpio_set, s, TC6393XB_GPIOS); |
| 487 | 588 | ||
| 589 | + s->l3v = *qemu_allocate_irqs(tc6393xb_l3v, s, 1); | ||
| 590 | + s->blanked = 1; | ||
| 591 | + | ||
| 488 | s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS); | 592 | s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS); |
| 489 | 593 | ||
| 490 | s->flash = nand_init(NAND_MFR_TOSHIBA, 0x76); | 594 | s->flash = nand_init(NAND_MFR_TOSHIBA, 0x76); |
| 491 | 595 | ||
| 492 | iomemtype = cpu_register_io_memory(0, tc6393xb_readfn, | 596 | iomemtype = cpu_register_io_memory(0, tc6393xb_readfn, |
| 493 | tc6393xb_writefn, s); | 597 | tc6393xb_writefn, s); |
| 494 | - cpu_register_physical_memory(s->target_base, 0x200000, iomemtype); | 598 | + cpu_register_physical_memory(s->target_base, 0x10000, iomemtype); |
| 599 | + | ||
| 600 | + if (ds) { | ||
| 601 | + s->ds = ds; | ||
| 602 | + s->vram_addr = qemu_ram_alloc(0x100000); | ||
| 603 | + cpu_register_physical_memory(s->target_base + 0x100000, 0x100000, s->vram_addr); | ||
| 604 | + s->scr_width = 480; | ||
| 605 | + s->scr_height = 640; | ||
| 606 | + s->console = graphic_console_init(ds, | ||
| 607 | + tc6393xb_update_display, | ||
| 608 | + NULL, /* invalidate */ | ||
| 609 | + NULL, /* screen_dump */ | ||
| 610 | + NULL, /* text_update */ | ||
| 611 | + s); | ||
| 612 | + } | ||
| 495 | 613 | ||
| 496 | return s; | 614 | return s; |
| 497 | } | 615 | } |
hw/tc6393xb_template.h
0 โ 100644
| 1 | +/* | ||
| 2 | + * Toshiba TC6393XB I/O Controller. | ||
| 3 | + * Found in Sharp Zaurus SL-6000 (tosa) or some | ||
| 4 | + * Toshiba e-Series PDAs. | ||
| 5 | + * | ||
| 6 | + * FB support code. Based on G364 fb emulator | ||
| 7 | + * | ||
| 8 | + * Copyright (c) 2007 Hervรฉ Poussineau | ||
| 9 | + * | ||
| 10 | + * This program is free software; you can redistribute it and/or | ||
| 11 | + * modify it under the terms of the GNU General Public License as | ||
| 12 | + * published by the Free Software Foundation; either version 2 of | ||
| 13 | + * the License, or (at your option) any later version. | ||
| 14 | + * | ||
| 15 | + * This program is distributed in the hope that it will be useful, | ||
| 16 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | + * GNU General Public License for more details. | ||
| 19 | + * | ||
| 20 | + * You should have received a copy of the GNU General Public License | ||
| 21 | + * along with this program; if not, write to the Free Software | ||
| 22 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
| 23 | + * MA 02111-1307 USA | ||
| 24 | + */ | ||
| 25 | + | ||
| 26 | +#if BITS == 8 | ||
| 27 | +# define SET_PIXEL(addr, color) *(uint8_t*)addr = color; | ||
| 28 | +#elif BITS == 15 || BITS == 16 | ||
| 29 | +# define SET_PIXEL(addr, color) *(uint16_t*)addr = color; | ||
| 30 | +#elif BITS == 24 | ||
| 31 | +# define SET_PIXEL(addr, color) \ | ||
| 32 | + addr[0] = color; addr[1] = (color) >> 8; addr[2] = (color) >> 16; | ||
| 33 | +#elif BITS == 32 | ||
| 34 | +# define SET_PIXEL(addr, color) *(uint32_t*)addr = color; | ||
| 35 | +#else | ||
| 36 | +# error unknown bit depth | ||
| 37 | +#endif | ||
| 38 | + | ||
| 39 | + | ||
| 40 | +static void glue(tc6393xb_draw_graphic, BITS)(struct tc6393xb_s *s) | ||
| 41 | +{ | ||
| 42 | + int i; | ||
| 43 | + int w_display; | ||
| 44 | + uint16_t *data_buffer; | ||
| 45 | + uint8_t *data_display; | ||
| 46 | + | ||
| 47 | + data_buffer = (uint16_t*)(phys_ram_base + s->vram_addr); | ||
| 48 | + w_display = s->scr_width * BITS / 8; | ||
| 49 | + data_display = s->ds->data; | ||
| 50 | + for(i = 0; i < s->scr_height; i++) { | ||
| 51 | +#if (BITS == 16) | ||
| 52 | + memcpy(data_display, data_buffer, s->scr_width * 2); | ||
| 53 | + data_buffer += s->scr_width; | ||
| 54 | + data_display += s->ds->linesize; | ||
| 55 | +#else | ||
| 56 | + int j; | ||
| 57 | + for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) { | ||
| 58 | + uint16_t color = *data_buffer; | ||
| 59 | + uint32_t dest_color = glue(rgb_to_pixel, BITS)( | ||
| 60 | + ((color & 0xf800) * 0x108) >> 11, | ||
| 61 | + ((color & 0x7e0) * 0x41) >> 9, | ||
| 62 | + ((color & 0x1f) * 0x21) >> 2 | ||
| 63 | + ); | ||
| 64 | + SET_PIXEL(data_display, dest_color); | ||
| 65 | + } | ||
| 66 | +#endif | ||
| 67 | + } | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | +#undef BITS | ||
| 71 | +#undef SET_PIXEL | ||
| 72 | + |
hw/tosa.c
| @@ -38,6 +38,7 @@ | @@ -38,6 +38,7 @@ | ||
| 38 | #define TOSA_GPIO_BT_LED (TOSA_SCOOP_JC_GPIO_BASE + 0) | 38 | #define TOSA_GPIO_BT_LED (TOSA_SCOOP_JC_GPIO_BASE + 0) |
| 39 | #define TOSA_GPIO_NOTE_LED (TOSA_SCOOP_JC_GPIO_BASE + 1) | 39 | #define TOSA_GPIO_NOTE_LED (TOSA_SCOOP_JC_GPIO_BASE + 1) |
| 40 | #define TOSA_GPIO_CHRG_ERR_LED (TOSA_SCOOP_JC_GPIO_BASE + 2) | 40 | #define TOSA_GPIO_CHRG_ERR_LED (TOSA_SCOOP_JC_GPIO_BASE + 2) |
| 41 | +#define TOSA_GPIO_TC6393XB_L3V_ON (TOSA_SCOOP_JC_GPIO_BASE + 5) | ||
| 41 | #define TOSA_GPIO_WLAN_LED (TOSA_SCOOP_JC_GPIO_BASE + 7) | 42 | #define TOSA_GPIO_WLAN_LED (TOSA_SCOOP_JC_GPIO_BASE + 7) |
| 42 | 43 | ||
| 43 | #define DAC_BASE 0x4e | 44 | #define DAC_BASE 0x4e |
| @@ -84,7 +85,8 @@ static void tosa_out_switch(void *opaque, int line, int level) | @@ -84,7 +85,8 @@ static void tosa_out_switch(void *opaque, int line, int level) | ||
| 84 | 85 | ||
| 85 | static void tosa_gpio_setup(struct pxa2xx_state_s *cpu, | 86 | static void tosa_gpio_setup(struct pxa2xx_state_s *cpu, |
| 86 | struct scoop_info_s *scp0, | 87 | struct scoop_info_s *scp0, |
| 87 | - struct scoop_info_s *scp1) | 88 | + struct scoop_info_s *scp1, |
| 89 | + struct tc6393xb_s *tmio) | ||
| 88 | { | 90 | { |
| 89 | qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4); | 91 | qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4); |
| 90 | /* MMC/SD host */ | 92 | /* MMC/SD host */ |
| @@ -108,6 +110,8 @@ static void tosa_gpio_setup(struct pxa2xx_state_s *cpu, | @@ -108,6 +110,8 @@ static void tosa_gpio_setup(struct pxa2xx_state_s *cpu, | ||
| 108 | scoop_gpio_out_set(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]); | 110 | scoop_gpio_out_set(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]); |
| 109 | scoop_gpio_out_set(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]); | 111 | scoop_gpio_out_set(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]); |
| 110 | scoop_gpio_out_set(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]); | 112 | scoop_gpio_out_set(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]); |
| 113 | + | ||
| 114 | + scoop_gpio_out_set(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio)); | ||
| 111 | } | 115 | } |
| 112 | 116 | ||
| 113 | static uint32_t tosa_ssp_read(void *opaque) | 117 | static uint32_t tosa_ssp_read(void *opaque) |
| @@ -198,9 +202,10 @@ static void tosa_init(ram_addr_t ram_size, int vga_ram_size, | @@ -198,9 +202,10 @@ static void tosa_init(ram_addr_t ram_size, int vga_ram_size, | ||
| 198 | const char *initrd_filename, const char *cpu_model) | 202 | const char *initrd_filename, const char *cpu_model) |
| 199 | { | 203 | { |
| 200 | struct pxa2xx_state_s *cpu; | 204 | struct pxa2xx_state_s *cpu; |
| 205 | + struct tc6393xb_s *tmio; | ||
| 201 | struct scoop_info_s *scp0, *scp1; | 206 | struct scoop_info_s *scp0, *scp1; |
| 202 | 207 | ||
| 203 | - if (ram_size < (TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE)) { | 208 | + if (ram_size < (TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE + TC6393XB_RAM)) { |
| 204 | fprintf(stderr, "This platform requires %i bytes of memory\n", | 209 | fprintf(stderr, "This platform requires %i bytes of memory\n", |
| 205 | TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE); | 210 | TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE); |
| 206 | exit(1); | 211 | exit(1); |
| @@ -214,12 +219,14 @@ static void tosa_init(ram_addr_t ram_size, int vga_ram_size, | @@ -214,12 +219,14 @@ static void tosa_init(ram_addr_t ram_size, int vga_ram_size, | ||
| 214 | cpu_register_physical_memory(0, TOSA_ROM, | 219 | cpu_register_physical_memory(0, TOSA_ROM, |
| 215 | qemu_ram_alloc(TOSA_ROM) | IO_MEM_ROM); | 220 | qemu_ram_alloc(TOSA_ROM) | IO_MEM_ROM); |
| 216 | 221 | ||
| 217 | - tc6393xb_init(0x10000000, pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_TC6393XB_INT]); | 222 | + tmio = tc6393xb_init(0x10000000, |
| 223 | + pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_TC6393XB_INT], | ||
| 224 | + ds); | ||
| 218 | 225 | ||
| 219 | scp0 = scoop_init(cpu, 0, 0x08800000); | 226 | scp0 = scoop_init(cpu, 0, 0x08800000); |
| 220 | scp1 = scoop_init(cpu, 1, 0x14800040); | 227 | scp1 = scoop_init(cpu, 1, 0x14800040); |
| 221 | 228 | ||
| 222 | - tosa_gpio_setup(cpu, scp0, scp1); | 229 | + tosa_gpio_setup(cpu, scp0, scp1, tmio); |
| 223 | 230 | ||
| 224 | tosa_microdrive_attach(cpu); | 231 | tosa_microdrive_attach(cpu); |
| 225 | 232 | ||
| @@ -240,5 +247,5 @@ QEMUMachine tosapda_machine = { | @@ -240,5 +247,5 @@ QEMUMachine tosapda_machine = { | ||
| 240 | .name = "tosa", | 247 | .name = "tosa", |
| 241 | .desc = "Tosa PDA (PXA255)", | 248 | .desc = "Tosa PDA (PXA255)", |
| 242 | .init = tosa_init, | 249 | .init = tosa_init, |
| 243 | - .ram_require = TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE + RAMSIZE_FIXED, | 250 | + .ram_require = TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE + RAMSIZE_FIXED + TC6393XB_RAM, |
| 244 | }; | 251 | }; |