From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KwcpC-0004XR-VC for qemu-devel@nongnu.org; Sun, 02 Nov 2008 08:17:03 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KwcpB-0004WX-Tz for qemu-devel@nongnu.org; Sun, 02 Nov 2008 08:17:02 -0500 Received: from [199.232.76.173] (port=46446 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KwcpB-0004WP-Dm for qemu-devel@nongnu.org; Sun, 02 Nov 2008 08:17:01 -0500 Received: from ey-out-1920.google.com ([74.125.78.150]:43499) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KwcpB-0002R1-3E for qemu-devel@nongnu.org; Sun, 02 Nov 2008 08:17:01 -0500 Received: by ey-out-1920.google.com with SMTP id 4so687642eyk.4 for ; Sun, 02 Nov 2008 05:17:00 -0800 (PST) From: Dmitry Baryshkov Date: Sun, 2 Nov 2008 16:16:30 +0300 Message-Id: <1225631790-15735-7-git-send-email-dbaryshkov@gmail.com> In-Reply-To: <1225631790-15735-6-git-send-email-dbaryshkov@gmail.com> References: <1225631790-15735-1-git-send-email-dbaryshkov@gmail.com> <1225631790-15735-2-git-send-email-dbaryshkov@gmail.com> <1225631790-15735-3-git-send-email-dbaryshkov@gmail.com> <1225631790-15735-4-git-send-email-dbaryshkov@gmail.com> <1225631790-15735-5-git-send-email-dbaryshkov@gmail.com> <1225631790-15735-6-git-send-email-dbaryshkov@gmail.com> Subject: [Qemu-devel] [PATCH] tc6393xb: non-accelerated FB support Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Dmitry Baryshkov Signed-off-by: Dmitry Baryshkov --- hw/devices.h | 2 +- hw/tc6393xb.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++- hw/tc6393xb_template.h | 52 +++++++++++++++++++ hw/tosa.c | 4 +- 4 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 hw/tc6393xb_template.h diff --git a/hw/devices.h b/hw/devices.h index 45fead9..e8fed68 100644 --- a/hw/devices.h +++ b/hw/devices.h @@ -66,7 +66,7 @@ void tusb6010_power(struct tusb_s *s, int on); /* tc6393xb.c */ struct tc6393xb_s; -struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq); +struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq, DisplayState *ds); void tc6393xb_gpio_out_set(struct tc6393xb_s *s, int line, qemu_irq handler); qemu_irq *tc6393xb_gpio_in_get(struct tc6393xb_s *s); diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c index 919a922..e3897ff 100644 --- a/hw/tc6393xb.c +++ b/hw/tc6393xb.c @@ -11,6 +11,8 @@ #include "pxa.h" #include "devices.h" #include "flash.h" +#include "console.h" +#include "pixel_ops.h" #define IRQ_TC6393_NAND 0 #define IRQ_TC6393_MMC 1 @@ -119,6 +121,11 @@ struct tc6393xb_s { uint32_t nand_phys; struct nand_flash_s *flash; struct ecc_state_s ecc; + + DisplayState *ds; + QEMUConsole *console; + uint8_t *vram; + uint32_t scr_width, scr_height; /* in pixels */ }; qemu_irq *tc6393xb_gpio_in_get(struct tc6393xb_s *s) @@ -395,6 +402,111 @@ static void tc6393xb_nand_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, (uint32_t) addr, value & 0xff); } +#define BITS 8 +#define PIXEL_WIDTH 8 +#include "tc6393xb_template.h" +#define BITS 15 +#define PIXEL_WIDTH 16 +#include "tc6393xb_template.h" +#define BITS 16 +#define PIXEL_WIDTH 16 +#include "tc6393xb_template.h" +#define BITS 24 +#define PIXEL_WIDTH 32 +#include "tc6393xb_template.h" +#define BITS 32 +#define PIXEL_WIDTH 32 +#include "tc6393xb_template.h" + +static void tc6393xb_draw_graphic(struct tc6393xb_s *s) +{ + switch (s->ds->depth) { + case 8: + tc6393xb_draw_graphic8(s); + break; + case 15: + tc6393xb_draw_graphic15(s); + break; + case 16: + tc6393xb_draw_graphic16(s); + break; + case 24: + tc6393xb_draw_graphic24(s); + break; + case 32: + tc6393xb_draw_graphic32(s); + break; + default: + printf("tc6393xb: unknown depth %d\n", s->ds->depth); + return; + } + + dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); +} + +#if 0 +static void tc6393xb_draw_blank(struct tc6393xb_s *s, int full_update) +{ + int i, w; + uint8_t *d; + + if (!full_update) + return; + + w = s->scr_width * ((s->ds->depth + 7) >> 3); + d = s->ds->data; + for(i = 0; i < s->scr_height; i++) { + memset(d, 0, w); + d += s->ds->linesize; + } + + dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height); +} +#endif + +static void tc6393xb_update_display(void *opaque) +{ + struct tc6393xb_s *s = opaque; +#if 0 + int full_update, graphic_mode; +#endif + + if (s->scr_width == 0 || s->scr_height == 0) + return; + +#if 0 + if (s->ctla & CTLA_FORCE_BLANK) + graphic_mode = GMODE_BLANK; + else + graphic_mode = GMODE_GRAPH; + full_update = 0; + if (graphic_mode != s->graphic_mode) { + s->graphic_mode = graphic_mode; + full_update = 1; + } +#endif + if (s->scr_width != s->ds->width || s->scr_height != s->ds->height) { + qemu_console_resize(s->console, s->scr_width, s->scr_height); +#if 0 + full_update = 1; +#endif + } +#if 0 + switch(graphic_mode) { + case GMODE_GRAPH: + tc6393xb_draw_graphic(s, full_update); + break; + case GMODE_BLANK: + default: + tc6393xb_draw_blank(s, full_update); + break; + } +#else + tc6393xb_draw_graphic(s); +#endif +} + + static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr) { struct tc6393xb_s *s = opaque; addr -= s->target_base; @@ -404,6 +516,8 @@ static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr) { return tc6393xb_scr_readb(s, addr & 0xff); case 1: return tc6393xb_nand_cfg_readb(s, addr & 0xff); + case 0x1000 ... 0x1fff: + return s->vram[addr - 0x100000]; }; if ((addr &~0xff) == s->nand_phys && s->nand_enable) { @@ -428,6 +542,9 @@ static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t valu case 1: tc6393xb_nand_cfg_writeb(s, addr & 0xff, value); return; + case 0x1000 ... 0x1fff: + s->vram[addr - 0x100000] = value&0xff; + return; }; if ((addr &~0xff) == s->nand_phys && s->nand_enable) @@ -465,7 +582,7 @@ static void tc6393xb_writel(void *opaque, target_phys_addr_t addr, uint32_t valu tc6393xb_writeb(opaque, addr + 3, value >> 24); } -struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq) +struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq, DisplayState *ds) { int iomemtype; struct tc6393xb_s *s; @@ -493,6 +610,19 @@ struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq) tc6393xb_writefn, s); cpu_register_physical_memory(s->target_base, 0x200000, iomemtype); + if (ds) { + s->ds = ds; + s->vram = qemu_mallocz(0x100000); + s->scr_width = 480; + s->scr_height = 640; + s->console = graphic_console_init(ds, + tc6393xb_update_display, + NULL, /* invalidate */ + NULL, /* screen_dump */ + NULL, /* text_update */ + s); + } + return s; } /* vim:set shiftwidth=4 ts=4 et: */ diff --git a/hw/tc6393xb_template.h b/hw/tc6393xb_template.h new file mode 100644 index 0000000..1e0dcac --- /dev/null +++ b/hw/tc6393xb_template.h @@ -0,0 +1,52 @@ +/* + * Toshiba TC6393XB I/O Controller. + * Found in Sharp Zaurus SL-6000 (tosa) or some + * Toshiba e-Series PDAs. + * + * FB support code. Based on G364 fb emulator + * + * Copyright (c) 2007 Hervé Poussineau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +static void glue(tc6393xb_draw_graphic, BITS)(struct tc6393xb_s *s) +{ + int i, j; + int w_display; + uint16_t *data_buffer; + uint8_t *data_display, *dd; + + data_buffer = (uint16_t*)s->vram; + w_display = s->scr_width * PIXEL_WIDTH / 8; + data_display = s->ds->data; + for(i = 0; i < s->scr_height; i++) { + dd = data_display; + for (j = 0; j < s->scr_width; j++, dd += PIXEL_WIDTH / 8, data_buffer++) { + uint16_t color = *data_buffer; + *((glue(glue(uint, PIXEL_WIDTH), _t) *)dd) = glue(rgb_to_pixel, BITS)( + ((color & 0xf800) * 0x108) >> 11, + ((color & 0x7e0) * 0x41) >> 9, + ((color & 0x1f) * 0x21) >> 2 + ); + } + data_display += s->ds->linesize; + } +} + +#undef PIXEL_WIDTH +#undef BITS + diff --git a/hw/tosa.c b/hw/tosa.c index 711060c..cbb0cb2 100644 --- a/hw/tosa.c +++ b/hw/tosa.c @@ -204,7 +204,9 @@ static void tosa_init(ram_addr_t ram_size, int vga_ram_size, cpu_register_physical_memory(0, TOSA_ROM, qemu_ram_alloc(TOSA_ROM) | IO_MEM_ROM); - tc6393xb_init(0x10000000, pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_TC6393XB_INT]); + tc6393xb_init(0x10000000, + pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_TC6393XB_INT], + ds); scp0 = scoop_init(cpu, 0, 0x08800000); scp1 = scoop_init(cpu, 1, 0x14800040); -- 1.5.6.5