Skip to contentSkip to conversation

scoop: GPRR reports the state of GPIO lines

PATCH In review Dmitry Baryshkov 2 participants 16 messages Nov 2, 2008 – Nov 4, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 scoop: GPRR reports the state of GPIO lines

---
 hw/zaurus.c |   16 +++++++---------
 1 files changed, 7 insertions(+), 9 deletions(-)
hw/zaurus.c +7 -9
index c475eaa..26e138d 100644
@@ -46,7 +46,6 @@ struct scoop_info_s {
     uint16_t irr;
     uint16_t imr;
     uint16_t isr;
-    uint16_t gprr;
 };
 
 #define SCOOP_MCR	0x00
@@ -99,9 +98,8 @@ static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
     case SCOOP_GPCR:
         return s->gpio_dir;
     case SCOOP_GPWR:
-        return s->gpio_level;
     case SCOOP_GPRR:
-        return s->gprr;
+        return s->gpio_level;
     default:
         zaurus_printf("Bad register offset " REG_FMT "\n", addr);
     }
@@ -144,12 +142,10 @@ static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
         scoop_gpio_handler_update(s);
         break;
     case SCOOP_GPWR:
+    case SCOOP_GPRR: // GPRR is probably R/O in real HW
         s->gpio_level = value & s->gpio_dir;
         scoop_gpio_handler_update(s);
         break;
-    case SCOOP_GPRR:
-        s->gprr = value;
-        break;
     default:
         zaurus_printf("Bad register offset " REG_FMT "\n", addr);
     }
@@ -194,6 +190,7 @@ void scoop_gpio_out_set(struct scoop_info_s *s, int line,
 static void scoop_save(QEMUFile *f, void *opaque)
 {
     struct scoop_info_s *s = (struct scoop_info_s *) opaque;
+    uint16_t dummy = 0;
     qemu_put_be16s(f, &s->status);
     qemu_put_be16s(f, &s->power);
     qemu_put_be32s(f, &s->gpio_level);
@@ -205,11 +202,11 @@ static void scoop_save(QEMUFile *f, void *opaque)
     qemu_put_be16s(f, &s->irr);
     qemu_put_be16s(f, &s->imr);
     qemu_put_be16s(f, &s->isr);
-    qemu_put_be16s(f, &s->gprr);
 }
 
 static int scoop_load(QEMUFile *f, void *opaque, int version_id)
 {
+    uint16_t dummy;
     struct scoop_info_s *s = (struct scoop_info_s *) opaque;
     qemu_get_be16s(f, &s->status);
     qemu_get_be16s(f, &s->power);
@@ -222,7 +219,8 @@ static int scoop_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_be16s(f, &s->irr);
     qemu_get_be16s(f, &s->imr);
     qemu_get_be16s(f, &s->isr);
-    qemu_get_be16s(f, &s->gprr);
+    if (version_id < 1)
+	    qemu_get_be16s(f, &dummy);
 
     return 0;
 }
@@ -243,7 +241,7 @@ struct scoop_info_s *scoop_init(struct pxa2xx_state_s *cpu,
     iomemtype = cpu_register_io_memory(0, scoop_readfn,
                     scoop_writefn, s);
     cpu_register_physical_memory(s->target_base, 0x1000, iomemtype);
-    register_savevm("scoop", instance, 0, scoop_save, scoop_load, s);
+    register_savevm("scoop", instance, 1, scoop_save, scoop_load, s);
 
     return s;
 }
Signature · 1 line
1.5.6.5
#1 lore raw

PATCH 1/1 tc6393xb: initial support for nand

---
 hw/tc6393xb.c |  244 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 221 insertions(+), 23 deletions(-)
hw/tc6393xb.c +221 -23
index 01ddb11..919a922 100644
@@ -10,6 +10,15 @@
 #include "hw.h"
 #include "pxa.h"
 #include "devices.h"
+#include "flash.h"
+
+#define	IRQ_TC6393_NAND		0
+#define	IRQ_TC6393_MMC		1
+#define	IRQ_TC6393_OHCI		2
+#define	IRQ_TC6393_SERIAL	3
+#define	IRQ_TC6393_FB		4
+
+#define	TC6393XB_NR_IRQS	8
 
 #define TC6393XB_GPIOS  16
 
@@ -40,8 +49,37 @@
 #define SCR_CONFIG	0xfc		/* b Configuration Control */
 #define SCR_DEBUG	0xff		/* b Debug		*/
 
+#define NAND_CFG_COMMAND    0x04    /* w Command        */
+#define NAND_CFG_BASE       0x10    /* l Control Base Address */
+#define NAND_CFG_INTP       0x3d    /* b Interrupt Pin  */
+#define NAND_CFG_INTE       0x48    /* b Int Enable     */
+#define NAND_CFG_EC         0x4a    /* b Event Control  */
+#define NAND_CFG_ICC        0x4c    /* b Internal Clock Control */
+#define NAND_CFG_ECCC       0x5b    /* b ECC Control    */
+#define NAND_CFG_NFTC       0x60    /* b NAND Flash Transaction Control */
+#define NAND_CFG_NFM        0x61    /* b NAND Flash Monitor */
+#define NAND_CFG_NFPSC      0x62    /* b NAND Flash Power Supply Control */
+#define NAND_CFG_NFDC       0x63    /* b NAND Flash Detect Control */
+
+#define NAND_DATA   0x00        /* l Data       */
+#define NAND_MODE   0x04        /* b Mode       */
+#define NAND_STATUS 0x05        /* b Status     */
+#define NAND_ISR    0x06        /* b Interrupt Status */
+#define NAND_IMR    0x07        /* b Interrupt Mask */
+
+#define NAND_MODE_WP        0x80
+#define NAND_MODE_CE        0x10
+#define NAND_MODE_ALE       0x02
+#define NAND_MODE_CLE       0x01
+#define NAND_MODE_ECC_MASK  0x60
+#define NAND_MODE_ECC_EN    0x20
+#define NAND_MODE_ECC_READ  0x40
+#define NAND_MODE_ECC_RST   0x60
+
 struct tc6393xb_s {
     target_phys_addr_t target_base;
+    qemu_irq irq;
+    qemu_irq *sub_irqs;
     struct {
         uint8_t ISR;
         uint8_t IMR;
@@ -71,6 +109,16 @@ struct tc6393xb_s {
     uint32_t prev_level;
     qemu_irq handler[TC6393XB_GPIOS];
     qemu_irq *gpio_in;
+
+    struct {
+        uint8_t mode;
+        uint8_t isr;
+        uint8_t imr;
+    } nand;
+    int nand_enable;
+    uint32_t nand_phys;
+    struct nand_flash_s *flash;
+    struct ecc_state_s ecc;
 };
 
 qemu_irq *tc6393xb_gpio_in_get(struct tc6393xb_s *s)
@@ -116,6 +164,17 @@ static void tc6393xb_gpio_handler_update(struct tc6393xb_s *s)
     s->prev_level = level;
 }
 
+static void tc6393xb_sub_irq(void *opaque, int line, int level) {
+    struct tc6393xb_s *s = opaque;
+    uint8_t isr = s->scr.ISR;
+    if (level)
+        isr |= 1 << line;
+    else
+        isr &= ~(1 << line);
+    s->scr.ISR = isr;
+    qemu_set_irq(s->irq, isr & s->scr.IMR);
+}
+
 #define SCR_REG_B(N)                            \
     case SCR_ ##N: return s->scr.N
 #define SCR_REG_W(N)                            \
@@ -131,10 +190,8 @@ static void tc6393xb_gpio_handler_update(struct tc6393xb_s *s)
     case SCR_ ##N(1): return s->scr.N[1];       \
     case SCR_ ##N(2): return s->scr.N[2]
 
-static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr)
+static uint32_t tc6393xb_scr_readb(struct tc6393xb_s *s, target_phys_addr_t addr)
 {
-    struct tc6393xb_s *s = opaque;
-    addr -= s->target_base;
     switch (addr) {
         case SCR_REVID:
             return 3;
@@ -171,7 +228,7 @@ static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr)
         SCR_REG_B(CONFIG);
         SCR_REG_B(DEBUG);
     }
-    fprintf(stderr, "tc6393xb: unhandled read at %08x\n", (uint32_t) addr);
+    fprintf(stderr, "tc6393xb_scr: unhandled read at %08x\n", (uint32_t) addr);
     return 0;
 }
 #undef SCR_REG_B
@@ -180,24 +237,22 @@ static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr)
 #undef SCR_REG_A
 
 #define SCR_REG_B(N)                                \
-    case SCR_ ##N: s->scr.N = value; break;
+    case SCR_ ##N: s->scr.N = value; return;
 #define SCR_REG_W(N)                                \
-    case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); break; \
-    case SCR_ ##N + 1: s->scr.N = (s->scr.N & 0xff) | (value << 8); break
+    case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); return; \
+    case SCR_ ##N + 1: s->scr.N = (s->scr.N & 0xff) | (value << 8); return
 #define SCR_REG_L(N)                                \
-    case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); break;   \
-    case SCR_ ##N + 1: s->scr.N = (s->scr.N & ~(0xff << 8)) | (value & (0xff << 8)); break;     \
-    case SCR_ ##N + 2: s->scr.N = (s->scr.N & ~(0xff << 16)) | (value & (0xff << 16)); break;   \
-    case SCR_ ##N + 3: s->scr.N = (s->scr.N & ~(0xff << 24)) | (value & (0xff << 24)); break;
+    case SCR_ ##N: s->scr.N = (s->scr.N & ~0xff) | (value & 0xff); return;   \
+    case SCR_ ##N + 1: s->scr.N = (s->scr.N & ~(0xff << 8)) | (value & (0xff << 8)); return;     \
+    case SCR_ ##N + 2: s->scr.N = (s->scr.N & ~(0xff << 16)) | (value & (0xff << 16)); return;   \
+    case SCR_ ##N + 3: s->scr.N = (s->scr.N & ~(0xff << 24)) | (value & (0xff << 24)); return;
 #define SCR_REG_A(N)                                \
-    case SCR_ ##N(0): s->scr.N[0] = value; break;   \
-    case SCR_ ##N(1): s->scr.N[1] = value; break;   \
-    case SCR_ ##N(2): s->scr.N[2] = value; break
+    case SCR_ ##N(0): s->scr.N[0] = value; return;   \
+    case SCR_ ##N(1): s->scr.N[1] = value; return;   \
+    case SCR_ ##N(2): s->scr.N[2] = value; return
 
-static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void tc6393xb_scr_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, uint32_t value)
 {
-    struct tc6393xb_s *s = opaque;
-    addr -= s->target_base;
     switch (addr) {
         SCR_REG_B(ISR);
         SCR_REG_B(IMR);
@@ -212,13 +267,13 @@ static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t valu
         case SCR_GPO_DSR(2):
             s->gpio_level = (s->gpio_level & ~(0xff << ((addr - SCR_GPO_DSR(0))*8))) | ((value & 0xff) << ((addr - SCR_GPO_DSR(0))*8));
             tc6393xb_gpio_handler_update(s);
-            break;
+            return;
         case SCR_GPO_DOECR(0):
         case SCR_GPO_DOECR(1):
         case SCR_GPO_DOECR(2):
             s->gpio_dir = (s->gpio_dir & ~(0xff << ((addr - SCR_GPO_DOECR(0))*8))) | ((value & 0xff) << ((addr - SCR_GPO_DOECR(0))*8));
             tc6393xb_gpio_handler_update(s);
-            break;
+            return;
         SCR_REG_A(GP_IARCR);
         SCR_REG_A(GP_IARLCR);
         SCR_REG_A(GPI_BCR);
@@ -233,17 +288,155 @@ static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t valu
         SCR_REG_W(MCR);
         SCR_REG_B(CONFIG);
         SCR_REG_B(DEBUG);
-        default:
-            fprintf(stderr, "tc6393xb: unhandled write at %08x: %02x\n",
-					(uint32_t) addr, value & 0xff);
-            break;
     }
+    fprintf(stderr, "tc6393xb_scr: unhandled write at %08x: %02x\n",
+					(uint32_t) addr, value & 0xff);
 }
 #undef SCR_REG_B
 #undef SCR_REG_W
 #undef SCR_REG_L
 #undef SCR_REG_A
 
+static void tc6393xb_nand_irq(struct tc6393xb_s *s) {
+    qemu_set_irq(s->sub_irqs[IRQ_TC6393_NAND],
+            (s->nand.imr & 0x80) && (s->nand.imr & s->nand.isr));
+}
+
+static uint32_t tc6393xb_nand_cfg_readb(struct tc6393xb_s *s, target_phys_addr_t addr) {
+    switch (addr) {
+        case NAND_CFG_COMMAND:
+            return s->nand_enable ? 2 : 0;
+        case NAND_CFG_BASE:
+        case NAND_CFG_BASE + 1:
+        case NAND_CFG_BASE + 2:
+        case NAND_CFG_BASE + 3:
+            return s->nand_phys >> (addr - NAND_CFG_BASE);
+    }
+    fprintf(stderr, "tc6393xb_nand_cfg: unhandled read at %08x\n", (uint32_t) addr);
+    return 0;
+}
+static void tc6393xb_nand_cfg_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, uint32_t value) {
+    switch (addr) {
+        case NAND_CFG_COMMAND:
+            s->nand_enable = (value & 0x2);
+            return;
+        case NAND_CFG_BASE:
+        case NAND_CFG_BASE + 1:
+        case NAND_CFG_BASE + 2:
+        case NAND_CFG_BASE + 3:
+            s->nand_phys &= ~(0xff << ((addr - NAND_CFG_BASE) * 8));
+            s->nand_phys |= (value & 0xff) << ((addr - NAND_CFG_BASE) * 8);
+            return;
+    }
+    fprintf(stderr, "tc6393xb_nand_cfg: unhandled write at %08x: %02x\n",
+					(uint32_t) addr, value & 0xff);
+}
+
+static uint32_t tc6393xb_nand_readb(struct tc6393xb_s *s, target_phys_addr_t addr) {
+    switch (addr) {
+        case NAND_DATA + 0:
+        case NAND_DATA + 1:
+        case NAND_DATA + 2:
+        case NAND_DATA + 3:
+            return nand_getio(s->flash);
+        case NAND_MODE:
+            return s->nand.mode;
+        case NAND_STATUS:
+            return 0x14;
+        case NAND_ISR:
+            return s->nand.isr;
+        case NAND_IMR:
+            return s->nand.imr;
+    }
+    fprintf(stderr, "tc6393xb_nand: unhandled read at %08x\n", (uint32_t) addr);
+    return 0;
+}
+static void tc6393xb_nand_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, uint32_t value) {
+//    fprintf(stderr, "tc6393xb_nand: write at %08x: %02x\n",
+//					(uint32_t) addr, value & 0xff);
+    switch (addr) {
+        case NAND_DATA + 0:
+        case NAND_DATA + 1:
+        case NAND_DATA + 2:
+        case NAND_DATA + 3:
+            nand_setio(s->flash, value);
+            s->nand.isr &= 1;
+            tc6393xb_nand_irq(s);
+            return;
+        case NAND_MODE:
+            s->nand.mode = value;
+            nand_setpins(s->flash,
+                    value & NAND_MODE_CLE,
+                    value & NAND_MODE_ALE,
+                    !(value & NAND_MODE_CE),
+                    value & NAND_MODE_WP,
+                    0); // FIXME: gnd
+            switch (value & NAND_MODE_ECC_MASK) {
+                case NAND_MODE_ECC_RST:
+                    ecc_reset(&s->ecc);
+                    break;
+                case NAND_MODE_ECC_READ:
+                    // FIXME
+                    break;
+                case NAND_MODE_ECC_EN:
+                    ecc_reset(&s->ecc);
+            }
+            return;
+        case NAND_ISR:
+            s->nand.isr = value;
+            tc6393xb_nand_irq(s);
+            return;
+        case NAND_IMR:
+            s->nand.imr = value;
+            tc6393xb_nand_irq(s);
+            return;
+    }
+    fprintf(stderr, "tc6393xb_nand: unhandled write at %08x: %02x\n",
+					(uint32_t) addr, value & 0xff);
+}
+
+static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr) {
+    struct tc6393xb_s *s = opaque;
+    addr -= s->target_base;
+
+    switch (addr >> 8) {
+        case 0:
+            return tc6393xb_scr_readb(s, addr & 0xff);
+        case 1:
+            return tc6393xb_nand_cfg_readb(s, addr & 0xff);
+    };
+
+    if ((addr &~0xff) == s->nand_phys && s->nand_enable) {
+//        return tc6393xb_nand_readb(s, addr & 0xff);
+        uint8_t d = tc6393xb_nand_readb(s, addr & 0xff);
+//        fprintf(stderr, "tc6393xb_nand: read at %08x: %02hhx\n", (uint32_t) addr, d);
+        return d;
+    }
+
+//    fprintf(stderr, "tc6393xb: unhandled read at %08x\n", (uint32_t) addr);
+    return 0;
+}
+
+static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) {
+    struct tc6393xb_s *s = opaque;
+    addr -= s->target_base;
+
+    switch (addr >> 8) {
+        case 0:
+            tc6393xb_scr_writeb(s, addr & 0xff, value);
+            return;
+        case 1:
+            tc6393xb_nand_cfg_writeb(s, addr & 0xff, value);
+            return;
+    };
+
+    if ((addr &~0xff) == s->nand_phys && s->nand_enable)
+        tc6393xb_nand_writeb(s, addr & 0xff, value);
+    else
+        fprintf(stderr, "tc6393xb: unhandled write at %08x: %02x\n",
+					(uint32_t) addr, value & 0xff);
+}
+
 static uint32_t tc6393xb_readw(void *opaque, target_phys_addr_t addr)
 {
     return (tc6393xb_readb(opaque, addr) & 0xff) |
@@ -289,8 +482,13 @@ struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq)
 
     s = (struct tc6393xb_s *) qemu_mallocz(sizeof(struct tc6393xb_s));
     s->target_base = base;
+    s->irq = irq;
     s->gpio_in = qemu_allocate_irqs(tc6393xb_gpio_set, s, TC6393XB_GPIOS);
 
+    s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS);
+
+    s->flash = nand_init(NAND_MFR_TOSHIBA, 0x76);
+
     iomemtype = cpu_register_io_memory(0, tc6393xb_readfn,
                     tc6393xb_writefn, s);
     cpu_register_physical_memory(s->target_base, 0x200000, iomemtype);
Signature · 1 line
1.5.6.5
#2 lore raw

PATCH 1/1 tosa: support leds

Tosa: add support for leds.

---
 hw/tosa.c |   35 ++++++++++++++++++++++++++++++++++-
 1 files changed, 34 insertions(+), 1 deletions(-)
hw/tosa.c +34 -1
index 75df52e..e629044 100644
@@ -27,11 +27,17 @@
 #define TOSA_GPIO_CF_CD			(13)
 #define TOSA_GPIO_JC_CF_IRQ		(36)	/* CF slot1 Ready */
 
-#define TOSA_SCOOP_GPIO_BASE	0
+#define TOSA_SCOOP_GPIO_BASE	1
 #define TOSA_GPIO_IR_POWERDWN	(TOSA_SCOOP_GPIO_BASE + 2)
 #define TOSA_GPIO_SD_WP			(TOSA_SCOOP_GPIO_BASE + 3)
 #define TOSA_GPIO_PWR_ON		(TOSA_SCOOP_GPIO_BASE + 4)
 
+#define TOSA_SCOOP_JC_GPIO_BASE		1
+#define TOSA_GPIO_BT_LED		(TOSA_SCOOP_JC_GPIO_BASE + 0)
+#define TOSA_GPIO_NOTE_LED		(TOSA_SCOOP_JC_GPIO_BASE + 1)
+#define TOSA_GPIO_CHRG_ERR_LED		(TOSA_SCOOP_JC_GPIO_BASE + 2)
+#define TOSA_GPIO_WLAN_LED		(TOSA_SCOOP_JC_GPIO_BASE + 7)
+
 static void tosa_microdrive_attach(struct pxa2xx_state_s *cpu)
 {
     struct pcmcia_card_s *md;
@@ -48,10 +54,33 @@ static void tosa_microdrive_attach(struct pxa2xx_state_s *cpu)
     }
 }
 
+static void tosa_out_switch(void *opaque, int line, int level)
+{
+    switch (line) {
+        case 0:
+            fprintf(stderr, "blue LED %s.\n", level ? "on" : "off");
+            break;
+        case 1:
+            fprintf(stderr, "green LED %s.\n", level ? "on" : "off");
+            break;
+        case 2:
+            fprintf(stderr, "amber LED %s.\n", level ? "on" : "off");
+            break;
+        case 3:
+            fprintf(stderr, "wlan LED %s.\n", level ? "on" : "off");
+            break;
+        default:
+            fprintf(stderr, "Uhandled out event: %d = %d\n", line, level);
+            break;
+    }
+}
+
+
 static void tosa_gpio_setup(struct pxa2xx_state_s *cpu,
                 struct scoop_info_s *scp0,
                 struct scoop_info_s *scp1)
 {
+    qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4);
     /* MMC/SD host */
     pxa2xx_mmci_handlers(cpu->mmc,
                     scoop_gpio_in_get(scp0)[TOSA_GPIO_SD_WP],
@@ -69,6 +98,10 @@ static void tosa_gpio_setup(struct pxa2xx_state_s *cpu,
                         pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_JC_CF_IRQ],
                         NULL);
 
+    scoop_gpio_out_set(scp1, TOSA_GPIO_BT_LED, outsignals[0]);
+    scoop_gpio_out_set(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]);
+    scoop_gpio_out_set(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]);
+    scoop_gpio_out_set(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
 }
 
 static struct arm_boot_info tosa_binfo = {
Signature · 1 line
1.5.6.5
#3 lore raw

PATCH 1/1 tosa: basic lcd support

---
 hw/tosa.c |   74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 74 insertions(+), 0 deletions(-)
hw/tosa.c +74 -0
index e629044..cb0e1da 100644
@@ -17,6 +17,7 @@
 #include "pcmcia.h"
 #include "block.h"
 #include "boards.h"
+#include "i2c.h"
 
 #define TOSA_RAM    0x04000000
 #define TOSA_ROM	0x00800000
@@ -38,6 +39,11 @@
 #define TOSA_GPIO_CHRG_ERR_LED		(TOSA_SCOOP_JC_GPIO_BASE + 2)
 #define TOSA_GPIO_WLAN_LED		(TOSA_SCOOP_JC_GPIO_BASE + 7)
 
+#define	DAC_BASE	0x4e
+#define DAC_CH1		0
+#define DAC_CH2		1
+
+
 static void tosa_microdrive_attach(struct pxa2xx_state_s *cpu)
 {
     struct pcmcia_card_s *md;
@@ -104,6 +110,72 @@ static void tosa_gpio_setup(struct pxa2xx_state_s *cpu,
     scoop_gpio_out_set(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
 }
 
+static uint32_t tosa_ssp_read(void *opaque) {
+    return 0;
+}
+
+static void tosa_ssp_write(void *opaque, uint32_t value)
+{
+    fprintf(stderr, "TG: %d %02x\n", value >> 5, value & 0x1f);
+}
+
+struct tosa_dac_i2c {
+    i2c_slave i2c;
+    int len;
+    char buf[3];
+};
+
+static int tosa_dac_send(i2c_slave *i2c, uint8_t data)
+{
+    struct tosa_dac_i2c *s = (struct tosa_dac_i2c *)i2c;
+    s->buf[s->len] = data;
+    if (s->len ++ > 2) {
+#ifdef VERBOSE
+        fprintf(stderr, "%s: message too long (%i bytes)\n", __FUNCTION__, s->len);
+#endif
+        return 1;
+    }
+
+    if (s->len == 2) {
+        fprintf(stderr, "dac: channel %d value 0x%02x\n",
+                s->buf[0], s->buf[1]);
+    }
+
+    return 0;
+}
+
+static void tosa_dac_event(i2c_slave *i2c, enum i2c_event event)
+{
+    struct tosa_dac_i2c *s = (struct tosa_dac_i2c *)i2c;
+    s->len = 0;
+    switch (event) {
+    case I2C_START_SEND:
+        break;
+    case I2C_FINISH:
+#ifdef VERBOSE
+        if (s->len < 2)
+            printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
+        if (s->len > 2)
+            printf("%s: message too long\n", __FUNCTION__);
+#endif
+        break;
+    default:
+        break;
+    }
+}
+
+static void tosa_tg_init(struct pxa2xx_state_s *cpu)
+{
+    struct i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+    struct i2c_slave *dac = i2c_slave_init(bus, 0, sizeof(struct tosa_dac_i2c));
+    dac->send = tosa_dac_send;
+    dac->event = tosa_dac_event;
+    i2c_set_slave_address(dac, DAC_BASE);
+    pxa2xx_ssp_attach(cpu->ssp[1], tosa_ssp_read,
+                    tosa_ssp_write, cpu);
+}
+
+
 static struct arm_boot_info tosa_binfo = {
     .loader_start = PXA2XX_SDRAM_BASE,
     .ram_size = 0x04000000,
@@ -140,6 +212,8 @@ static void tosa_init(ram_addr_t ram_size, int vga_ram_size,
 
     tosa_microdrive_attach(cpu);
 
+    tosa_tg_init(cpu);
+
     /* Setup initial (reset) machine state */
     cpu->env->regs[15] = tosa_binfo.loader_start;
 
Signature · 1 line
1.5.6.5
#4 lore raw

PATCH 1/1 tosa: provide correct IRQ to tc6393xb init

---
 hw/tosa.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
hw/tosa.c +2 -1
index cb0e1da..1c49509 100644
@@ -26,6 +26,7 @@
 #define TOSA_GPIO_ON_RESET		(19)
 #define TOSA_GPIO_CF_IRQ		(21)	/* CF slot0 Ready */
 #define TOSA_GPIO_CF_CD			(13)
+#define TOSA_GPIO_TC6393XB_INT  (15)
 #define TOSA_GPIO_JC_CF_IRQ		(36)	/* CF slot1 Ready */
 
 #define TOSA_SCOOP_GPIO_BASE	1
@@ -203,7 +204,7 @@ 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, NULL);
+    tc6393xb_init(0x10000000, pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_TC6393XB_INT]);
 
     scp0 = scoop_init(cpu, 0, 0x08800000);
     scp1 = scoop_init(cpu, 1, 0x14800040);
Signature · 1 line
1.5.6.5
#5 lore raw

PATCH 1/1 tosa: disable pxafb as it's not used on tosa.

---
 hw/tosa.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
hw/tosa.c +1 -1
index 1c49509..711060c 100644
@@ -199,7 +199,7 @@ static void tosa_init(ram_addr_t ram_size, int vga_ram_size,
     if (!cpu_model)
         cpu_model = "pxa255";
 
-    cpu = pxa255_init(tosa_binfo.ram_size, ds);
+    cpu = pxa255_init(tosa_binfo.ram_size, NULL);
 
     cpu_register_physical_memory(0, TOSA_ROM,
                     qemu_ram_alloc(TOSA_ROM) | IO_MEM_ROM);
Signature · 1 line
1.5.6.5
#6 lore raw

PATCH 1/1 tc6393xb: non-accelerated FB support

---
 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
hw/devices.h +1 -1
index 45fead9..e8fed68 100644
@@ -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);
hw/tc6393xb.c +131 -1

174 lines not on this page · raw message

hw/tc6393xb_template.h new file +52 -0

52 lines not on this page · raw message

hw/tosa.c +3 -1
index 711060c..cbb0cb2 100644
@@ -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);
Signature · 1 line
1.5.6.5
#7 lore raw

Re: [Qemu-devel] [PATCH] tc6393xb: non-accelerated FB support

2008/11/2 Dmitry Baryshkov <[email protected]>:

Quoted 102 lines
---
 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
hw/devices.h +1 -1
index 45fead9..e8fed68 100644
@@ -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);
hw/tc6393xb.c +58 -0
index 919a922..e3897ff 100644
@@ -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;
+

hw/tc6393xb.c static void tc6393xb_nand_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, · line 465

Quoted 10 lines
hw/tc6393xb.c +10 -0
+    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

This assumes in 24bit mode a pixel occupies only 3 bytes (which iirc is correct) and above PIXEL_WIDTH for 24 bits is set to 32.

Quoted 32 lines
hw/tc6393xb.c +32 -0
+
+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);

hw/tc6393xb.c static void tc6393xb_nand_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, · line 507

Quoted 10 lines
hw/tc6393xb.c +10 -0
+            break;
+        case GMODE_BLANK:
+        default:
+            tc6393xb_draw_blank(s, full_update);
+            break;
+    }
+#else
+            tc6393xb_draw_graphic(s);
+#endif
+}

Why's blank mode disabled?

Quoted 15 lines
hw/tc6393xb.c +4 -0
+
+
 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) {

hw/tc6393xb.c static void tc6393xb_writeb(void *opaque, target_phys_addr_t addr, uint32_t valu · line 548

Quoted 7 lines
hw/tc6393xb.c +3 -0
@@ -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;
    };

IIRC the page size is 0x400 on qemu-system-arm so you could register this region as RAM, this sould give a speed-up. The indentation is strange.

Quoted 71 lines
hw/tc6393xb.c +14 -1
    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: */
hw/tc6393xb_template.h new file +34 -0
new file mode 100644
index 0000000..1e0dcac
@@ -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;

hw/tc6393xb_template.h line 44

Quoted 10 lines
hw/tc6393xb_template.h new file +10 -0
+    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
+                           );

This assumes power of two PIXEL_WIDTH (which is power-of-two but possibly wrongly).
For the RGB565 host case you can possibly use memcpy.

Cheers

#8 lore raw

Re: [Qemu-devel] [PATCH] tc6393xb: non-accelerated FB support

Quoted 17 lines · andrzej zaborowski

2008/11/2 Dmitry Baryshkov <[email protected]>:

Quoted 16 lines
hw/tc6393xb.c +14 -0
+#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;
Quoted 8 lines

hw/tc6393xb.c static void tc6393xb_nand_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, · line 465

Quoted 5 lines
hw/tc6393xb.c +5 -0
+    }
+
+    dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height);
+}
+#endif

This assumes in 24bit mode a pixel occupies only 3 bytes (which iirc is correct) and above PIXEL_WIDTH for 24 bits is set to 32.

This is disabled as it's untested. And about 24bit mode... I'm really not sure. I thought that when used it has 24 bit color, but 32 bit alignment of colors. Otherwise it will be a nightmare to use.

Quoted 36 lines
Quoted 36 lines
hw/tc6393xb.c +36 -0
+
+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);
Quoted 8 lines

hw/tc6393xb.c static void tc6393xb_nand_writeb(struct tc6393xb_s *s, target_phys_addr_t addr, · line 507

Quoted 6 lines
hw/tc6393xb.c +6 -0
+            break;
+    }
+#else
+            tc6393xb_draw_graphic(s);
+#endif
+}

Why's blank mode disabled?

Not Yet Supported.

Quoted 4 lines

IIRC the page size is 0x400 on qemu-system-arm so you could register this region as RAM, this sould give a speed-up. The indentation is strange.

Hmm. Nice idea. I'll redo this patch anyway then.

Quoted 10 lines

hw/tc6393xb_template.h line 44

Quoted 9 lines
hw/tc6393xb_template.h new file +9 -0
+    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
+                           );
Quoted 3 lines

This assumes power of two PIXEL_WIDTH (which is power-of-two but possibly wrongly).
For the RGB565 host case you can possibly use memcpy.

See above about 24-bit mode.
Nice idea for 565 mode :)

Signature · 2 lines
With best wishes
Dmitry
#9 lore raw

Re: [Qemu-devel] [PATCH] tc6393xb: non-accelerated FB support

Quoted 95 lines · Dmitry Baryshkov
Quoted 17 lines · andrzej zaborowski

2008/11/2 Dmitry Baryshkov <[email protected]>:

Quoted 16 lines
(quoted diff) +14 -0
+#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;
Quoted 8 lines

Review

Quoted 5 lines
(quoted diff) +5 -0
+    }
+
+    dpy_update(s->ds, 0, 0, s->scr_width, s->scr_height);
+}
+#endif

This assumes in 24bit mode a pixel occupies only 3 bytes (which iirc is correct) and above PIXEL_WIDTH for 24 bits is set to 32.

This is disabled as it's untested. And about 24bit mode... I'm really not sure. I thought that when used it has 24 bit color, but 32 bit alignment of colors. Otherwise it will be a nightmare to use.

Quoted 36 lines
Quoted 36 lines
(quoted diff) +36 -0
+
+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);
Quoted 8 lines

Review

Quoted 6 lines
(quoted diff) +6 -0
+            break;
+    }
+#else
+            tc6393xb_draw_graphic(s);
+#endif
+}

Why's blank mode disabled?

Not Yet Supported.

Quoted 4 lines

IIRC the page size is 0x400 on qemu-system-arm so you could register this region as RAM, this sould give a speed-up. The indentation is strange.

Hmm. Nice idea. I'll redo this patch anyway then.

Quoted 10 lines
Quoted 9 lines
(quoted diff) +9 -0
+    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
+                           );
Quoted 6 lines
Quoted 3 lines

This assumes power of two PIXEL_WIDTH (which is power-of-two but possibly wrongly).
For the RGB565 host case you can possibly use memcpy.

See above about 24-bit mode.
Nice idea for 565 mode :)

As a second thought I've implemented blanking, implemented your suggestions. Please take a look at the following patch.

Quoted 1 line

From 57cd66fefc31ac18f1f896a8ca53441b01f0d345 Mon Sep 17 00:00:00 2001

From: Dmitry Baryshkov <[email protected]>
Date: Thu, 11 Sep 2008 04:39:15 +0400
Subject: [PATCH] tc6393xb: non-accelerated FB support

---
 hw/devices.h           |    4 +-
 hw/tc6393xb.c          |  120 +++++++++++++++++++++++++++++++++++++++++++++++-
 hw/tc6393xb_template.h |   72 +++++++++++++++++++++++++++++
 hw/tosa.c              |   17 +++++--
 4 files changed, 205 insertions(+), 8 deletions(-)
 create mode 100644 hw/tc6393xb_template.h
hw/devices.h +3 -1
index 45fead9..9572a63 100644
@@ -66,9 +66,11 @@ 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);
+#define TC6393XB_RAM	0x110000 /* amount of ram for Video and USB */
+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);
+qemu_irq tc6393xb_l3v_get(struct tc6393xb_s *s);
 
 #endif
hw/tc6393xb.c +118 -2

162 lines not on this page · raw message

hw/tc6393xb_template.h new file +72 -0

72 lines not on this page · raw message

hw/tosa.c +12 -5
index e66ab16..a54390f 100644
@@ -38,6 +38,7 @@
 #define TOSA_GPIO_BT_LED		(TOSA_SCOOP_JC_GPIO_BASE + 0)
 #define TOSA_GPIO_NOTE_LED		(TOSA_SCOOP_JC_GPIO_BASE + 1)
 #define TOSA_GPIO_CHRG_ERR_LED		(TOSA_SCOOP_JC_GPIO_BASE + 2)
+#define TOSA_GPIO_TC6393XB_L3V_ON	(TOSA_SCOOP_JC_GPIO_BASE + 5)
 #define TOSA_GPIO_WLAN_LED		(TOSA_SCOOP_JC_GPIO_BASE + 7)
 
 #define	DAC_BASE	0x4e
@@ -85,7 +86,8 @@ static void tosa_out_switch(void *opaque, int line, int level)
 
 static void tosa_gpio_setup(struct pxa2xx_state_s *cpu,
                 struct scoop_info_s *scp0,
-                struct scoop_info_s *scp1)
+                struct scoop_info_s *scp1,
+                struct tc6393xb_s *tmio)
 {
     qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4);
     /* MMC/SD host */
@@ -109,6 +111,8 @@ static void tosa_gpio_setup(struct pxa2xx_state_s *cpu,
     scoop_gpio_out_set(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]);
     scoop_gpio_out_set(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]);
     scoop_gpio_out_set(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
+
+    scoop_gpio_out_set(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio));
 }
 
 static uint32_t tosa_ssp_read(void *opaque) {
@@ -197,9 +201,10 @@ static void tosa_init(ram_addr_t ram_size, int vga_ram_size,
                 const char *initrd_filename, const char *cpu_model)
 {
     struct pxa2xx_state_s *cpu;
+    struct tc6393xb_s *tmio;
     struct scoop_info_s *scp0, *scp1;
 
-    if (ram_size < (TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE)) {
+    if (ram_size < (TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE + TC6393XB_RAM)) {
         fprintf(stderr, "This platform requires %i bytes of memory\n",
                 TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE);
         exit(1);
@@ -213,12 +218,14 @@ 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]);
+    tmio = 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);
 
-    tosa_gpio_setup(cpu, scp0, scp1);
+    tosa_gpio_setup(cpu, scp0, scp1, tmio);
 
     tosa_microdrive_attach(cpu);
 
@@ -239,5 +246,5 @@ QEMUMachine tosapda_machine = {
     .name = "tosa",
     .desc = "Tosa PDA (PXA255)",
     .init = tosa_init,
-    .ram_require = TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE + RAMSIZE_FIXED,
+    .ram_require = TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE + RAMSIZE_FIXED + TC6393XB_RAM,
 };
Signature · 6 lines
1.5.6.5


-- 
With best wishes
Dmitry
#10 lore raw

Re: [Qemu-devel] [PATCH] tc6393xb: non-accelerated FB support

2008/11/2 Dmitry Baryshkov <[email protected]>:
[...]

Quoted 2 lines

As a second thought I've implemented blanking, implemented your suggestions. Please take a look at the following patch.

Thanks, this looks better.

Quoted 237 lines

From 57cd66fefc31ac18f1f896a8ca53441b01f0d345 Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <[email protected]>
Date: Thu, 11 Sep 2008 04:39:15 +0400
Subject: [PATCH] tc6393xb: non-accelerated FB support

---
 hw/devices.h           |    4 +-
 hw/tc6393xb.c          |  120 +++++++++++++++++++++++++++++++++++++++++++++++-
 hw/tc6393xb_template.h |   72 +++++++++++++++++++++++++++++
 hw/tosa.c              |   17 +++++--
 4 files changed, 205 insertions(+), 8 deletions(-)
 create mode 100644 hw/tc6393xb_template.h
hw/devices.h +3 -1
index 45fead9..9572a63 100644
@@ -66,9 +66,11 @@ 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);
+#define TC6393XB_RAM   0x110000 /* amount of ram for Video and USB */
+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);
+qemu_irq tc6393xb_l3v_get(struct tc6393xb_s *s);
 
 #endif
hw/tc6393xb.c +118 -2
index 2c18984..8a3ff18 100644
@@ -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,14 @@ struct tc6393xb_s {
    uint32_t nand_phys;
    struct nand_flash_s *flash;
    struct ecc_state_s ecc;
+
+    DisplayState *ds;
+    QEMUConsole *console;
+    ram_addr_t vram_addr;
+    uint32_t scr_width, scr_height; /* in pixels */
+    qemu_irq l3v;
+    unsigned blank : 1,
+             blanked : 1;
 };
 
 qemu_irq *tc6393xb_gpio_in_get(struct tc6393xb_s *s)
@@ -164,6 +174,16 @@ static void tc6393xb_gpio_handler_update(struct tc6393xb_s *s)
    s->prev_level = level;
 }
 
+qemu_irq tc6393xb_l3v_get(struct tc6393xb_s *s) {
+    return s->l3v;
+}
+
+static void tc6393xb_l3v(void *opaque, int line, int level) {
+    struct tc6393xb_s *s = opaque;
+    s->blank = !level;
+    fprintf(stderr, "L3V: %d\n", level);
+}
+
 static void tc6393xb_sub_irq(void *opaque, int line, int level) {
    struct tc6393xb_s *s = opaque;
    uint8_t isr = s->scr.ISR;
@@ -395,6 +415,85 @@ static void tc6393xb_nand_writeb(struct tc6393xb_s *s, target_phys_addr_t addr,
                                       (uint32_t) addr, value & 0xff);
 }
 
+#define BITS 8
+#include "tc6393xb_template.h"
+#define BITS 15
+#include "tc6393xb_template.h"
+#define BITS 16
+#include "tc6393xb_template.h"
+#define BITS 24
+#include "tc6393xb_template.h"
+#define BITS 32
+#include "tc6393xb_template.h"
+
+static void tc6393xb_draw_graphic(struct tc6393xb_s *s, int full_update)
+{
+    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);
+}
+
+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);
+}
+
+static void tc6393xb_update_display(void *opaque)
+{
+    struct tc6393xb_s *s = opaque;
+    int full_update;
+
+    if (s->scr_width == 0 || s->scr_height == 0)
+        return;
+
+    full_update = 0;
+    if (s->blanked != s->blank) {
+        s->blanked = s->blank;
+        full_update = 1;
+    }
+    if (s->scr_width != s->ds->width || s->scr_height != s->ds->height) {
+        qemu_console_resize(s->console, s->scr_width, s->scr_height);
+        full_update = 1;
+    }
+    if (s->blanked)
+        tc6393xb_draw_blank(s, full_update);
+    else
+        tc6393xb_draw_graphic(s, full_update);
+}
+
+
 static uint32_t tc6393xb_readb(void *opaque, target_phys_addr_t addr) {
    struct tc6393xb_s *s = opaque;
    addr -= s->target_base;
@@ -465,7 +564,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;
@@ -485,13 +584,30 @@ struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq)
    s->irq = irq;
    s->gpio_in = qemu_allocate_irqs(tc6393xb_gpio_set, s, TC6393XB_GPIOS);
 
+    s->l3v = *qemu_allocate_irqs(tc6393xb_l3v, s, 1);
+    s->blanked = 1;
+
    s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS);
 
    s->flash = nand_init(NAND_MFR_TOSHIBA, 0x76);
 
    iomemtype = cpu_register_io_memory(0, tc6393xb_readfn,
                    tc6393xb_writefn, s);
-    cpu_register_physical_memory(s->target_base, 0x200000, iomemtype);
+    cpu_register_physical_memory(s->target_base, 0x10000, iomemtype);
+
+    if (ds) {
+        s->ds = ds;
+        s->vram_addr = qemu_ram_alloc(0x100000);
+        cpu_register_physical_memory(s->target_base + 0x100000, 0x100000, s->vram_addr);
+        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;
 }
hw/tc6393xb_template.h new file +27 -0
new file mode 100644
index 0000000..c9d4e03
@@ -0,0 +1,72 @@
+/*
+ * 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
+ */
+
+#if BITS == 8
+# define SET_PIXEL(addr, color)        *(uint8_t*)addr = color;

hw/tc6393xb_template.h line 37

Quoted 10 lines
hw/tc6393xb_template.h new file +10 -0
+#elif BITS == 15 || BITS == 16
+# define SET_PIXEL(addr, color)        *(uint16_t*)addr = color;
+#elif BITS == 24
+# define SET_PIXEL(addr, color)        \
+    addr[0] = color; addr[1] = (color) >> 8; addr[2] = (color) >> 16;
+#elif BITS == 32
+# define SET_PIXEL(addr, color)        *(uint32_t*)addr = color;
+#else
+# error unknown bit depth
+#endif

Hmm.. now when I look at this it triggers an alert because
*(uint16_t *) addr = color;
and
addr[0] = coor; addr[1] = (color) >> 8;
do different things on a bigendian host. But I can't tell offhand which one we want here...

pxa2xx_template.h and pl110_template.h might have the same problem.

Quoted 111 lines
hw/tc6393xb_template.h new file +35 -0
+
+
+static void glue(tc6393xb_draw_graphic, BITS)(struct tc6393xb_s *s)
+{
+    int i;
+    int w_display;
+    uint16_t *data_buffer;
+    uint8_t *data_display;
+
+    data_buffer = (uint16_t*)(phys_ram_base + s->vram_addr);
+    w_display = s->scr_width * BITS / 8;
+    data_display = s->ds->data;
+    for(i = 0; i < s->scr_height; i++) {
+#if (BITS == 16)
+       memcpy(data_display, data_buffer, s->scr_width * 2);
+       data_buffer += s->scr_width;
+        data_display += s->ds->linesize;
+#else
+       int j;
+        for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) {
+            uint16_t color = *data_buffer;
+           uint32_t dest_color = glue(rgb_to_pixel, BITS)(
+                           ((color & 0xf800) * 0x108) >> 11,
+                           ((color & 0x7e0) * 0x41) >> 9,
+                           ((color & 0x1f) * 0x21) >> 2
+                           );
+           SET_PIXEL(data_display, dest_color);
+        }
+#endif
+    }
+}
+
+#undef BITS
+#undef SET_PIXEL
+
hw/tosa.c +12 -6
index e66ab16..a54390f 100644
@@ -38,6 +38,7 @@
 #define TOSA_GPIO_BT_LED               (TOSA_SCOOP_JC_GPIO_BASE + 0)
 #define TOSA_GPIO_NOTE_LED             (TOSA_SCOOP_JC_GPIO_BASE + 1)
 #define TOSA_GPIO_CHRG_ERR_LED         (TOSA_SCOOP_JC_GPIO_BASE + 2)
+#define TOSA_GPIO_TC6393XB_L3V_ON      (TOSA_SCOOP_JC_GPIO_BASE + 5)
 #define TOSA_GPIO_WLAN_LED             (TOSA_SCOOP_JC_GPIO_BASE + 7)
 
 #define        DAC_BASE        0x4e
@@ -85,7 +86,8 @@ static void tosa_out_switch(void *opaque, int line, int level)
 
 static void tosa_gpio_setup(struct pxa2xx_state_s *cpu,
                struct scoop_info_s *scp0,
-                struct scoop_info_s *scp1)
+                struct scoop_info_s *scp1,
+                struct tc6393xb_s *tmio)
 {
    qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4);
    /* MMC/SD host */
@@ -109,6 +111,8 @@ static void tosa_gpio_setup(struct pxa2xx_state_s *cpu,
    scoop_gpio_out_set(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]);
    scoop_gpio_out_set(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]);
    scoop_gpio_out_set(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
+
+    scoop_gpio_out_set(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio));
 }
 
 static uint32_t tosa_ssp_read(void *opaque) {
@@ -197,9 +201,10 @@ static void tosa_init(ram_addr_t ram_size, int vga_ram_size,
                const char *initrd_filename, const char *cpu_model)
 {
    struct pxa2xx_state_s *cpu;
+    struct tc6393xb_s *tmio;
    struct scoop_info_s *scp0, *scp1;
 
-    if (ram_size < (TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE)) {
+    if (ram_size < (TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE + TC6393XB_RAM)) {
        fprintf(stderr, "This platform requires %i bytes of memory\n",
                TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE);
        exit(1);
@@ -213,12 +218,14 @@ 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]);
+    tmio = 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);
 
-    tosa_gpio_setup(cpu, scp0, scp1);
+    tosa_gpio_setup(cpu, scp0, scp1, tmio);
 
    tosa_microdrive_attach(cpu);
 
@@ -239,5 +246,5 @@ QEMUMachine tosapda_machine = {
    .name = "tosa",
    .desc = "Tosa PDA (PXA255)",
    .init = tosa_init,
-    .ram_require = TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE + RAMSIZE_FIXED,
+    .ram_require = TOSA_RAM + TOSA_ROM + PXA2XX_INTERNAL_SIZE + RAMSIZE_FIXED + TC6393XB_RAM,
 };
--

1.5.6.5

--
With best wishes
Dmitry

author
#11 lore raw

Re: [Qemu-devel] [PATCH] tc6393xb: non-accelerated FB support

2008/11/4 andrzej zaborowski <[email protected]>:

Quoted 6 lines

2008/11/2 Dmitry Baryshkov <[email protected]>:
[...]

Quoted 2 lines

As a second thought I've implemented blanking, implemented your suggestions. Please take a look at the following patch.

Thanks, this looks better.

Good!

Quoted 37 lines
Quoted 19 lines

From 57cd66fefc31ac18f1f896a8ca53441b01f0d345 Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <[email protected]>
Date: Thu, 11 Sep 2008 04:39:15 +0400
Subject: [PATCH] tc6393xb: non-accelerated FB support

---
 hw/devices.h           |    4 +-
 hw/tc6393xb.c          |  120 +++++++++++++++++++++++++++++++++++++++++++++++-
 hw/tc6393xb_template.h |   72 +++++++++++++++++++++++++++++
 hw/tosa.c              |   17 +++++--
 4 files changed, 205 insertions(+), 8 deletions(-)
 create mode 100644 hw/tc6393xb_template.h
hw/tc6393xb_template.h new file +3 -0
+
+#if BITS == 8
+# define SET_PIXEL(addr, color)        *(uint8_t*)addr = color;

hw/tc6393xb_template.h line 37

Quoted 10 lines
hw/tc6393xb_template.h new file +10 -0
+#elif BITS == 15 || BITS == 16
+# define SET_PIXEL(addr, color)        *(uint16_t*)addr = color;
+#elif BITS == 24
+# define SET_PIXEL(addr, color)        \
+    addr[0] = color; addr[1] = (color) >> 8; addr[2] = (color) >> 16;
+#elif BITS == 32
+# define SET_PIXEL(addr, color)        *(uint32_t*)addr = color;
+#else
+# error unknown bit depth
+#endif

Hmm.. now when I look at this it triggers an alert because
*(uint16_t *) addr = color;
and
addr[0] = coor; addr[1] = (color) >> 8;
do different things on a bigendian host. But I can't tell offhand which one we want here...

Quoted 3 lines

pxa2xx_template.h and pl110_template.h might have the same problem.

From a quick glance most other video emulators will suffer from this problem.

IMO we can merge this as is and later fix this if the problem really exists on BE hosts.

Signature · 2 lines
With best wishes
Dmitry
#12 lore raw

Re: [Qemu-devel] [PATCH] tosa: basic lcd support

In reply to Dmitry Baryshkov

2008/11/2 Dmitry Baryshkov <[email protected]>:

Quoted 83 lines
---
 hw/tosa.c |   74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 74 insertions(+), 0 deletions(-)
hw/tosa.c +56 -0
index e629044..cb0e1da 100644
@@ -17,6 +17,7 @@
 #include "pcmcia.h"
 #include "block.h"
 #include "boards.h"
+#include "i2c.h"
 
 #define TOSA_RAM    0x04000000
 #define TOSA_ROM       0x00800000
@@ -38,6 +39,11 @@
 #define TOSA_GPIO_CHRG_ERR_LED         (TOSA_SCOOP_JC_GPIO_BASE + 2)
 #define TOSA_GPIO_WLAN_LED             (TOSA_SCOOP_JC_GPIO_BASE + 7)
 
+#define        DAC_BASE        0x4e
+#define DAC_CH1                0
+#define DAC_CH2                1
+
+
 static void tosa_microdrive_attach(struct pxa2xx_state_s *cpu)
 {
    struct pcmcia_card_s *md;
@@ -104,6 +110,72 @@ static void tosa_gpio_setup(struct pxa2xx_state_s *cpu,
    scoop_gpio_out_set(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
 }
 
+static uint32_t tosa_ssp_read(void *opaque) {
+    return 0;
+}
+
+static void tosa_ssp_write(void *opaque, uint32_t value)
+{
+    fprintf(stderr, "TG: %d %02x\n", value >> 5, value & 0x1f);
+}
+
+struct tosa_dac_i2c {
+    i2c_slave i2c;
+    int len;
+    char buf[3];
+};
+
+static int tosa_dac_send(i2c_slave *i2c, uint8_t data)
+{
+    struct tosa_dac_i2c *s = (struct tosa_dac_i2c *)i2c;
+    s->buf[s->len] = data;
+    if (s->len ++ > 2) {
+#ifdef VERBOSE
+        fprintf(stderr, "%s: message too long (%i bytes)\n", __FUNCTION__, s->len);
+#endif
+        return 1;
+    }
+
+    if (s->len == 2) {
+        fprintf(stderr, "dac: channel %d value 0x%02x\n",
+                s->buf[0], s->buf[1]);
+    }
+
+    return 0;
+}
+
+static void tosa_dac_event(i2c_slave *i2c, enum i2c_event event)
+{
+    struct tosa_dac_i2c *s = (struct tosa_dac_i2c *)i2c;
+    s->len = 0;
+    switch (event) {
+    case I2C_START_SEND:
+        break;
+    case I2C_FINISH:
+#ifdef VERBOSE
+        if (s->len < 2)
+            printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
+        if (s->len > 2)
+            printf("%s: message too long\n", __FUNCTION__);
+#endif
+        break;
+    default:

hw/tosa.c static void tosa_gpio_setup(struct pxa2xx_state_s *cpu, · line 172

Quoted 10 lines
hw/tosa.c +10 -0
+        break;
+    }
+}
+
+static void tosa_tg_init(struct pxa2xx_state_s *cpu)
+{
+    struct i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+    struct i2c_slave *dac = i2c_slave_init(bus, 0, sizeof(struct tosa_dac_i2c));
+    dac->send = tosa_dac_send;
+    dac->event = tosa_dac_event;

You should set also .recv to not leave the kernel a possibility to crash qemu. Other than this, looks okay, but does this code help emulation in anyway? I suppose the kernel wants to see some i2c device present?

Cheers

#13 lore raw

Re: [Qemu-devel] [PATCH] tosa: basic lcd support

Quoted 12 lines · andrzej zaborowski

2008/11/2 Dmitry Baryshkov <[email protected]>:

Review

Quoted 6 lines
(quoted diff) +6 -0
+static void tosa_tg_init(struct pxa2xx_state_s *cpu)
+{
+    struct i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+    struct i2c_slave *dac = i2c_slave_init(bus, 0, sizeof(struct tosa_dac_i2c));
+    dac->send = tosa_dac_send;
+    dac->event = tosa_dac_event;

You should set also .recv to not leave the kernel a possibility to crash qemu. Other than this, looks okay, but does this code help emulation in anyway? I suppose the kernel wants to see some i2c device present?

The kernel expects to have the DAC in place. Otherwise I see barfs from it. So adding such simple i2c client is just a matter of preference. Anyway, please check this patch with .recv callback set:

Quoted 1 line

From 411faec51ff4a355eb5d02eecd5936bb0bcc0dc0 Mon Sep 17 00:00:00 2001

From: Dmitry Baryshkov <[email protected]>
Date: Sat, 13 Sep 2008 13:24:23 +0400
Subject: [PATCH] tosa: basic lcd support

---
 hw/tosa.c |   83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 83 insertions(+), 0 deletions(-)
hw/tosa.c +83 -0
index e629044..5cd3efb 100644
@@ -17,6 +17,7 @@
 #include "pcmcia.h"
 #include "block.h"
 #include "boards.h"
+#include "i2c.h"
 
 #define TOSA_RAM    0x04000000
 #define TOSA_ROM	0x00800000
@@ -38,6 +39,11 @@
 #define TOSA_GPIO_CHRG_ERR_LED		(TOSA_SCOOP_JC_GPIO_BASE + 2)
 #define TOSA_GPIO_WLAN_LED		(TOSA_SCOOP_JC_GPIO_BASE + 7)
 
+#define	DAC_BASE	0x4e
+#define DAC_CH1		0
+#define DAC_CH2		1
+
+
 static void tosa_microdrive_attach(struct pxa2xx_state_s *cpu)
 {
     struct pcmcia_card_s *md;
@@ -104,6 +110,81 @@ static void tosa_gpio_setup(struct pxa2xx_state_s *cpu,
     scoop_gpio_out_set(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
 }
 
+static uint32_t tosa_ssp_read(void *opaque) {
+    return 0;
+}
+
+static void tosa_ssp_write(void *opaque, uint32_t value)
+{
+    fprintf(stderr, "TG: %d %02x\n", value >> 5, value & 0x1f);
+}
+
+struct tosa_dac_i2c {
+    i2c_slave i2c;
+    int len;
+    char buf[3];
+};
+
+static int tosa_dac_send(i2c_slave *i2c, uint8_t data)
+{
+    struct tosa_dac_i2c *s = (struct tosa_dac_i2c *)i2c;
+    s->buf[s->len] = data;
+    if (s->len ++ > 2) {
+#ifdef VERBOSE
+        fprintf(stderr, "%s: message too long (%i bytes)\n", __FUNCTION__, s->len);
+#endif
+        return 1;
+    }
+
+    if (s->len == 2) {
+        fprintf(stderr, "dac: channel %d value 0x%02x\n",
+                s->buf[0], s->buf[1]);
+    }
+
+    return 0;
+}
+
+static void tosa_dac_event(i2c_slave *i2c, enum i2c_event event)
+{
+    struct tosa_dac_i2c *s = (struct tosa_dac_i2c *)i2c;
+    s->len = 0;
+    switch (event) {
+    case I2C_START_SEND:
+        break;
+    case I2C_START_RECV:
+        printf("%s: recv not supported!!!\n", __FUNCTION__);
+        break;
+    case I2C_FINISH:
+#ifdef VERBOSE
+        if (s->len < 2)
+            printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len);
+        if (s->len > 2)
+            printf("%s: message too long\n", __FUNCTION__);
+#endif
+        break;
+    default:
+        break;
+    }
+}
+
+int tosa_dac_recv(i2c_slave *s) {
+    printf("%s: recv not supported!!!\n", __FUNCTION__);
+    return -1;
+}
+
+static void tosa_tg_init(struct pxa2xx_state_s *cpu)
+{
+    struct i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+    struct i2c_slave *dac = i2c_slave_init(bus, 0, sizeof(struct tosa_dac_i2c));
+    dac->send = tosa_dac_send;
+    dac->event = tosa_dac_event;
+    dac->recv = tosa_dac_recv;
+    i2c_set_slave_address(dac, DAC_BASE);
+    pxa2xx_ssp_attach(cpu->ssp[1], tosa_ssp_read,
+                    tosa_ssp_write, cpu);
+}
+
+
 static struct arm_boot_info tosa_binfo = {
     .loader_start = PXA2XX_SDRAM_BASE,
     .ram_size = 0x04000000,
@@ -140,6 +221,8 @@ static void tosa_init(ram_addr_t ram_size, int vga_ram_size,
 
     tosa_microdrive_attach(cpu);
 
+    tosa_tg_init(cpu);
+
     /* Setup initial (reset) machine state */
     cpu->env->regs[15] = tosa_binfo.loader_start;
 
Signature · 5 lines
1.5.6.5

-- 
With best wishes
Dmitry
#14 lore raw

Re: [Qemu-devel] [PATCH] tosa: basic lcd support

2008/11/2 Dmitry Baryshkov <[email protected]>:

Quoted 14 lines · andrzej zaborowski
Quoted 12 lines

2008/11/2 Dmitry Baryshkov <[email protected]>:

hw/tosa.c static void tosa_gpio_setup(struct pxa2xx_state_s *cpu, · line 180

Quoted 6 lines
hw/tosa.c +6 -0
+static void tosa_tg_init(struct pxa2xx_state_s *cpu)
+{
+    struct i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
+    struct i2c_slave *dac = i2c_slave_init(bus, 0, sizeof(struct tosa_dac_i2c));
+    dac->send = tosa_dac_send;
+    dac->event = tosa_dac_event;

You should set also .recv to not leave the kernel a possibility to crash qemu. Other than this, looks okay, but does this code help emulation in anyway? I suppose the kernel wants to see some i2c device present?

Quoted 3 lines

The kernel expects to have the DAC in place. Otherwise I see barfs from it. So adding such simple i2c client is just a matter of preference. Anyway, please check this patch with .recv callback set:

Right, it expects a DAC. What I mean is that this implementation can equally well be a i2c framebuffer or a flux capacitor ;) But I assume you've tested that this already made the kernel happy.

Regards

#15 lore raw
In reply to Dmitry Baryshkov
Quoted 1 line · Dmitry Baryshkov

Oops... Please use this one instead.

Quoted 1 line

From 73733f4ccc3a8ee776a791f5cba6a4ba046e778c Mon Sep 17 00:00:00 2001

From: Dmitry Baryshkov <[email protected]>
Date: Sat, 31 May 2008 21:07:56 +0400
Subject: [PATCH] scoop: GPRR reports the state of GPIO lines

---
 hw/zaurus.c |   15 ++++++---------
 1 files changed, 6 insertions(+), 9 deletions(-)
hw/zaurus.c +6 -9
index c475eaa..a18453e 100644
@@ -46,7 +46,6 @@ struct scoop_info_s {
     uint16_t irr;
     uint16_t imr;
     uint16_t isr;
-    uint16_t gprr;
 };
 
 #define SCOOP_MCR	0x00
@@ -99,9 +98,8 @@ static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
     case SCOOP_GPCR:
         return s->gpio_dir;
     case SCOOP_GPWR:
-        return s->gpio_level;
     case SCOOP_GPRR:
-        return s->gprr;
+        return s->gpio_level;
     default:
         zaurus_printf("Bad register offset " REG_FMT "\n", addr);
     }
@@ -144,12 +142,10 @@ static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
         scoop_gpio_handler_update(s);
         break;
     case SCOOP_GPWR:
+    case SCOOP_GPRR: // GPRR is probably R/O in real HW
         s->gpio_level = value & s->gpio_dir;
         scoop_gpio_handler_update(s);
         break;
-    case SCOOP_GPRR:
-        s->gprr = value;
-        break;
     default:
         zaurus_printf("Bad register offset " REG_FMT "\n", addr);
     }
@@ -205,11 +201,11 @@ static void scoop_save(QEMUFile *f, void *opaque)
     qemu_put_be16s(f, &s->irr);
     qemu_put_be16s(f, &s->imr);
     qemu_put_be16s(f, &s->isr);
-    qemu_put_be16s(f, &s->gprr);
 }
 
 static int scoop_load(QEMUFile *f, void *opaque, int version_id)
 {
+    uint16_t dummy;
     struct scoop_info_s *s = (struct scoop_info_s *) opaque;
     qemu_get_be16s(f, &s->status);
     qemu_get_be16s(f, &s->power);
@@ -222,7 +218,8 @@ static int scoop_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_be16s(f, &s->irr);
     qemu_get_be16s(f, &s->imr);
     qemu_get_be16s(f, &s->isr);
-    qemu_get_be16s(f, &s->gprr);
+    if (version_id < 1)
+	    qemu_get_be16s(f, &dummy);
 
     return 0;
 }
@@ -243,7 +240,7 @@ struct scoop_info_s *scoop_init(struct pxa2xx_state_s *cpu,
     iomemtype = cpu_register_io_memory(0, scoop_readfn,
                     scoop_writefn, s);
     cpu_register_physical_memory(s->target_base, 0x1000, iomemtype);
-    register_savevm("scoop", instance, 0, scoop_save, scoop_load, s);
+    register_savevm("scoop", instance, 1, scoop_save, scoop_load, s);
 
     return s;
 }
Signature · 5 lines
1.5.6.5

-- 
With best wishes
Dmitry