Commit 66450b1596fddd03204b54cc4f9fb99fb928c857
1 parent
7fc42b4b
Implement OMAP PWL (backlight) module.
Fix GPIO clock name and output level change notifications. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3512 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
120 additions
and
4 deletions
hw/omap.c
... | ... | @@ -22,6 +22,18 @@ |
22 | 22 | #include "arm_pic.h" |
23 | 23 | |
24 | 24 | /* Should signal the TCMI */ |
25 | +uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) | |
26 | +{ | |
27 | + OMAP_8B_REG(addr); | |
28 | + return 0; | |
29 | +} | |
30 | + | |
31 | +void omap_badwidth_write8(void *opaque, target_phys_addr_t addr, | |
32 | + uint32_t value) | |
33 | +{ | |
34 | + OMAP_8B_REG(addr); | |
35 | +} | |
36 | + | |
25 | 37 | uint32_t omap_badwidth_read16(void *opaque, target_phys_addr_t addr) |
26 | 38 | { |
27 | 39 | OMAP_16B_REG(addr); |
... | ... | @@ -3140,9 +3152,8 @@ static void omap_gpio_write(void *opaque, target_phys_addr_t addr, |
3140 | 3152 | return; |
3141 | 3153 | |
3142 | 3154 | case 0x04: /* DATA_OUTPUT */ |
3143 | - diff = s->outputs ^ (value & ~s->dir); | |
3155 | + diff = (s->outputs ^ value) & ~s->dir; | |
3144 | 3156 | s->outputs = value; |
3145 | - value &= ~s->dir; | |
3146 | 3157 | while ((ln = ffs(diff))) { |
3147 | 3158 | ln --; |
3148 | 3159 | if (s->handler[ln]) |
... | ... | @@ -3369,7 +3380,7 @@ static CPUWriteMemoryFunc *omap_uwire_writefn[] = { |
3369 | 3380 | |
3370 | 3381 | void omap_uwire_reset(struct omap_uwire_s *s) |
3371 | 3382 | { |
3372 | - s->control= 0; | |
3383 | + s->control = 0; | |
3373 | 3384 | s->setup[0] = 0; |
3374 | 3385 | s->setup[1] = 0; |
3375 | 3386 | s->setup[2] = 0; |
... | ... | @@ -3407,6 +3418,97 @@ void omap_uwire_attach(struct omap_uwire_s *s, |
3407 | 3418 | s->chip[chipselect] = slave; |
3408 | 3419 | } |
3409 | 3420 | |
3421 | +/* Pseudonoise Pulse-Width Light Modulator */ | |
3422 | +void omap_pwl_update(struct omap_mpu_state_s *s) | |
3423 | +{ | |
3424 | + int output = (s->pwl.clk && s->pwl.enable) ? s->pwl.level : 0; | |
3425 | + | |
3426 | + if (output != s->pwl.output) { | |
3427 | + s->pwl.output = output; | |
3428 | + printf("%s: Backlight now at %i/256\n", __FUNCTION__, output); | |
3429 | + } | |
3430 | +} | |
3431 | + | |
3432 | +static uint32_t omap_pwl_read(void *opaque, target_phys_addr_t addr) | |
3433 | +{ | |
3434 | + struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; | |
3435 | + int offset = addr - s->pwl.base; | |
3436 | + | |
3437 | + switch (offset) { | |
3438 | + case 0x00: /* PWL_LEVEL */ | |
3439 | + return s->pwl.level; | |
3440 | + case 0x04: /* PWL_CTRL */ | |
3441 | + return s->pwl.enable; | |
3442 | + } | |
3443 | + OMAP_BAD_REG(addr); | |
3444 | + return 0; | |
3445 | +} | |
3446 | + | |
3447 | +static void omap_pwl_write(void *opaque, target_phys_addr_t addr, | |
3448 | + uint32_t value) | |
3449 | +{ | |
3450 | + struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; | |
3451 | + int offset = addr - s->pwl.base; | |
3452 | + | |
3453 | + switch (offset) { | |
3454 | + case 0x00: /* PWL_LEVEL */ | |
3455 | + s->pwl.level = value; | |
3456 | + omap_pwl_update(s); | |
3457 | + break; | |
3458 | + case 0x04: /* PWL_CTRL */ | |
3459 | + s->pwl.enable = value & 1; | |
3460 | + omap_pwl_update(s); | |
3461 | + break; | |
3462 | + default: | |
3463 | + OMAP_BAD_REG(addr); | |
3464 | + return; | |
3465 | + } | |
3466 | +} | |
3467 | + | |
3468 | +static CPUReadMemoryFunc *omap_pwl_readfn[] = { | |
3469 | + omap_badwidth_read8, | |
3470 | + omap_badwidth_read8, | |
3471 | + omap_pwl_read, | |
3472 | +}; | |
3473 | + | |
3474 | +static CPUWriteMemoryFunc *omap_pwl_writefn[] = { | |
3475 | + omap_badwidth_write8, | |
3476 | + omap_badwidth_write8, | |
3477 | + omap_pwl_write, | |
3478 | +}; | |
3479 | + | |
3480 | +void omap_pwl_reset(struct omap_mpu_state_s *s) | |
3481 | +{ | |
3482 | + s->pwl.output = 0; | |
3483 | + s->pwl.level = 0; | |
3484 | + s->pwl.enable = 0; | |
3485 | + s->pwl.clk = 1; | |
3486 | + omap_pwl_update(s); | |
3487 | +} | |
3488 | + | |
3489 | +static void omap_pwl_clk_update(void *opaque, int line, int on) | |
3490 | +{ | |
3491 | + struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque; | |
3492 | + | |
3493 | + s->pwl.clk = on; | |
3494 | + omap_pwl_update(s); | |
3495 | +} | |
3496 | + | |
3497 | +static void omap_pwl_init(target_phys_addr_t base, struct omap_mpu_state_s *s, | |
3498 | + omap_clk clk) | |
3499 | +{ | |
3500 | + int iomemtype; | |
3501 | + | |
3502 | + s->pwl.base = base; | |
3503 | + omap_pwl_reset(s); | |
3504 | + | |
3505 | + iomemtype = cpu_register_io_memory(0, omap_pwl_readfn, | |
3506 | + omap_pwl_writefn, s); | |
3507 | + cpu_register_physical_memory(s->pwl.base, 0x800, iomemtype); | |
3508 | + | |
3509 | + omap_clk_adduser(clk, qemu_allocate_irqs(omap_pwl_clk_update, s, 1)[0]); | |
3510 | +} | |
3511 | + | |
3410 | 3512 | /* General chip reset */ |
3411 | 3513 | static void omap_mpu_reset(void *opaque) |
3412 | 3514 | { |
... | ... | @@ -3437,6 +3539,7 @@ static void omap_mpu_reset(void *opaque) |
3437 | 3539 | omap_mpuio_reset(mpu->mpuio); |
3438 | 3540 | omap_gpio_reset(mpu->gpio); |
3439 | 3541 | omap_uwire_reset(mpu->microwire); |
3542 | + omap_pwl_reset(mpu); | |
3440 | 3543 | cpu_reset(mpu->env); |
3441 | 3544 | } |
3442 | 3545 | |
... | ... | @@ -3553,11 +3656,13 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, |
3553 | 3656 | s->wakeup, omap_findclk(s, "clk32-kHz")); |
3554 | 3657 | |
3555 | 3658 | s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1], |
3556 | - omap_findclk(s, "mpuper_ck")); | |
3659 | + omap_findclk(s, "arm_gpio_ck")); | |
3557 | 3660 | |
3558 | 3661 | s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX], |
3559 | 3662 | s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck")); |
3560 | 3663 | |
3664 | + omap_pwl_init(0xfffb5800, s, omap_findclk(s, "clk32-kHz")); | |
3665 | + | |
3561 | 3666 | qemu_register_reset(omap_mpu_reset, s); |
3562 | 3667 | |
3563 | 3668 | return s; | ... | ... |
hw/omap.h
... | ... | @@ -534,6 +534,14 @@ struct omap_mpu_state_s { |
534 | 534 | |
535 | 535 | struct omap_uwire_s *microwire; |
536 | 536 | |
537 | + struct { | |
538 | + target_phys_addr_t base; | |
539 | + uint8_t output; | |
540 | + uint8_t level; | |
541 | + uint8_t enable; | |
542 | + int clk; | |
543 | + } pwl; | |
544 | + | |
537 | 545 | /* MPU private TIPB peripherals */ |
538 | 546 | struct omap_intr_handler_s *ih[2]; |
539 | 547 | |
... | ... | @@ -615,6 +623,9 @@ void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, |
615 | 623 | # define OMAP_RO_REG(paddr) \ |
616 | 624 | printf("%s: Read-only register " OMAP_FMT_plx "\n", \ |
617 | 625 | __FUNCTION__, paddr) |
626 | +# define OMAP_8B_REG(paddr) \ | |
627 | + printf("%s: 8-bit register " OMAP_FMT_plx "\n", \ | |
628 | + __FUNCTION__, paddr) | |
618 | 629 | # define OMAP_16B_REG(paddr) \ |
619 | 630 | printf("%s: 16-bit register " OMAP_FMT_plx "\n", \ |
620 | 631 | __FUNCTION__, paddr) | ... | ... |