Revision a984a69e hw/spitz.c
b/hw/spitz.c | ||
---|---|---|
13 | 13 |
#include "sysemu.h" |
14 | 14 |
#include "pcmcia.h" |
15 | 15 |
#include "i2c.h" |
16 |
#include "ssi.h" |
|
16 | 17 |
#include "flash.h" |
17 | 18 |
#include "qemu-timer.h" |
18 | 19 |
#include "devices.h" |
... | ... | |
525 | 526 |
#define LCDTG_PICTRL 0x06 |
526 | 527 |
#define LCDTG_POLCTRL 0x07 |
527 | 528 |
|
528 |
static int bl_intensity, bl_power; |
|
529 |
typedef struct { |
|
530 |
SSISlave ssidev; |
|
531 |
int bl_intensity; |
|
532 |
int bl_power; |
|
533 |
} SpitzLCDTG; |
|
529 | 534 |
|
530 |
static void spitz_bl_update(PXA2xxState *s)
|
|
535 |
static void spitz_bl_update(SpitzLCDTG *s)
|
|
531 | 536 |
{ |
532 |
if (bl_power && bl_intensity)
|
|
533 |
zaurus_printf("LCD Backlight now at %i/63\n", bl_intensity); |
|
537 |
if (s->bl_power && s->bl_intensity)
|
|
538 |
zaurus_printf("LCD Backlight now at %i/63\n", s->bl_intensity);
|
|
534 | 539 |
else |
535 | 540 |
zaurus_printf("LCD Backlight now off\n"); |
536 | 541 |
} |
537 | 542 |
|
543 |
/* FIXME: Implement GPIO properly and remove this hack. */ |
|
544 |
static SpitzLCDTG *spitz_lcdtg; |
|
545 |
|
|
538 | 546 |
static inline void spitz_bl_bit5(void *opaque, int line, int level) |
539 | 547 |
{ |
540 |
int prev = bl_intensity; |
|
548 |
SpitzLCDTG *s = spitz_lcdtg; |
|
549 |
int prev = s->bl_intensity; |
|
541 | 550 |
|
542 | 551 |
if (level) |
543 |
bl_intensity &= ~0x20; |
|
552 |
s->bl_intensity &= ~0x20;
|
|
544 | 553 |
else |
545 |
bl_intensity |= 0x20; |
|
554 |
s->bl_intensity |= 0x20;
|
|
546 | 555 |
|
547 |
if (bl_power && prev != bl_intensity)
|
|
548 |
spitz_bl_update((PXA2xxState *) opaque);
|
|
556 |
if (s->bl_power && prev != s->bl_intensity)
|
|
557 |
spitz_bl_update(s);
|
|
549 | 558 |
} |
550 | 559 |
|
551 | 560 |
static inline void spitz_bl_power(void *opaque, int line, int level) |
552 | 561 |
{ |
553 |
bl_power = !!level; |
|
554 |
spitz_bl_update((PXA2xxState *) opaque); |
|
562 |
SpitzLCDTG *s = spitz_lcdtg; |
|
563 |
s->bl_power = !!level; |
|
564 |
spitz_bl_update(s); |
|
555 | 565 |
} |
556 | 566 |
|
557 |
static void spitz_lcdtg_dac_put(void *opaque, uint8_t cmd)
|
|
567 |
static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value)
|
|
558 | 568 |
{ |
559 |
int addr, value; |
|
560 |
addr = cmd >> 5; |
|
561 |
value = cmd & 0x1f; |
|
569 |
SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev); |
|
570 |
int addr; |
|
571 |
addr = value >> 5; |
|
572 |
value &= 0x1f; |
|
562 | 573 |
|
563 | 574 |
switch (addr) { |
564 | 575 |
case LCDTG_RESCTL: |
... | ... | |
569 | 580 |
break; |
570 | 581 |
|
571 | 582 |
case LCDTG_DUTYCTRL: |
572 |
bl_intensity &= ~0x1f; |
|
573 |
bl_intensity |= value; |
|
574 |
if (bl_power) |
|
575 |
spitz_bl_update((PXA2xxState *) opaque);
|
|
583 |
s->bl_intensity &= ~0x1f;
|
|
584 |
s->bl_intensity |= value;
|
|
585 |
if (s->bl_power)
|
|
586 |
spitz_bl_update(s);
|
|
576 | 587 |
break; |
577 | 588 |
|
578 | 589 |
case LCDTG_POWERREG0: |
579 | 590 |
/* Set common voltage to M62332FP */ |
580 | 591 |
break; |
581 | 592 |
} |
593 |
return 0; |
|
594 |
} |
|
595 |
|
|
596 |
static void spitz_lcdtg_save(QEMUFile *f, void *opaque) |
|
597 |
{ |
|
598 |
SpitzLCDTG *s = (SpitzLCDTG *)opaque; |
|
599 |
qemu_put_be32(f, s->bl_intensity); |
|
600 |
qemu_put_be32(f, s->bl_power); |
|
601 |
} |
|
602 |
|
|
603 |
static int spitz_lcdtg_load(QEMUFile *f, void *opaque, int version_id) |
|
604 |
{ |
|
605 |
SpitzLCDTG *s = (SpitzLCDTG *)opaque; |
|
606 |
s->bl_intensity = qemu_get_be32(f); |
|
607 |
s->bl_power = qemu_get_be32(f); |
|
608 |
return 0; |
|
609 |
} |
|
610 |
|
|
611 |
static void spitz_lcdtg_init(SSISlave *dev) |
|
612 |
{ |
|
613 |
SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev); |
|
614 |
|
|
615 |
spitz_lcdtg = s; |
|
616 |
s->bl_power = 0; |
|
617 |
s->bl_intensity = 0x20; |
|
618 |
|
|
619 |
register_savevm("spitz-lcdtg", -1, 1, |
|
620 |
spitz_lcdtg_save, spitz_lcdtg_load, s); |
|
582 | 621 |
} |
583 | 622 |
|
584 | 623 |
/* SSP devices */ |
... | ... | |
590 | 629 |
#define SPITZ_GPIO_MAX1111_CS 20 |
591 | 630 |
#define SPITZ_GPIO_TP_INT 11 |
592 | 631 |
|
593 |
static int lcd_en, ads_en, max_en; |
|
594 |
static MAX111xState *max1111; |
|
595 |
static ADS7846State *ads7846; |
|
632 |
static DeviceState *max1111; |
|
596 | 633 |
|
597 | 634 |
/* "Demux" the signal based on current chipselect */ |
598 |
static uint32_t corgi_ssp_read(void *opaque) |
|
599 |
{ |
|
600 |
if (lcd_en) |
|
601 |
return 0; |
|
602 |
if (ads_en) |
|
603 |
return ads7846_read(ads7846); |
|
604 |
if (max_en) |
|
605 |
return max111x_read(max1111); |
|
606 |
return 0; |
|
607 |
} |
|
635 |
typedef struct { |
|
636 |
SSISlave ssidev; |
|
637 |
SSIBus *bus[3]; |
|
638 |
int enable[3]; |
|
639 |
} CorgiSSPState; |
|
608 | 640 |
|
609 |
static void corgi_ssp_write(void *opaque, uint32_t value)
|
|
641 |
static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value)
|
|
610 | 642 |
{ |
611 |
if (lcd_en) |
|
612 |
spitz_lcdtg_dac_put(opaque, value); |
|
613 |
if (ads_en) |
|
614 |
ads7846_write(ads7846, value); |
|
615 |
if (max_en) |
|
616 |
max111x_write(max1111, value); |
|
643 |
CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev); |
|
644 |
int i; |
|
645 |
|
|
646 |
for (i = 0; i < 3; i++) { |
|
647 |
if (s->enable[i]) { |
|
648 |
return ssi_transfer(s->bus[i], value); |
|
649 |
} |
|
650 |
} |
|
651 |
return 0; |
|
617 | 652 |
} |
618 | 653 |
|
619 | 654 |
static void corgi_ssp_gpio_cs(void *opaque, int line, int level) |
620 | 655 |
{ |
621 |
switch (line) { |
|
622 |
case 0: |
|
623 |
lcd_en = !level; |
|
624 |
break; |
|
625 |
case 1: |
|
626 |
ads_en = !level; |
|
627 |
break; |
|
628 |
case 2: |
|
629 |
max_en = !level; |
|
630 |
break; |
|
631 |
} |
|
656 |
CorgiSSPState *s = (CorgiSSPState *)opaque; |
|
657 |
assert(line >= 0 && line < 3); |
|
658 |
s->enable[line] = !level; |
|
632 | 659 |
} |
633 | 660 |
|
634 | 661 |
#define MAX1111_BATT_VOLT 1 |
... | ... | |
652 | 679 |
|
653 | 680 |
static void spitz_ssp_save(QEMUFile *f, void *opaque) |
654 | 681 |
{ |
655 |
qemu_put_be32(f, lcd_en); |
|
656 |
qemu_put_be32(f, ads_en); |
|
657 |
qemu_put_be32(f, max_en); |
|
658 |
qemu_put_be32(f, bl_intensity); |
|
659 |
qemu_put_be32(f, bl_power); |
|
682 |
CorgiSSPState *s = (CorgiSSPState *)opaque; |
|
683 |
int i; |
|
684 |
|
|
685 |
for (i = 0; i < 3; i++) { |
|
686 |
qemu_put_be32(f, s->enable[i]); |
|
687 |
} |
|
660 | 688 |
} |
661 | 689 |
|
662 | 690 |
static int spitz_ssp_load(QEMUFile *f, void *opaque, int version_id) |
663 | 691 |
{ |
664 |
lcd_en = qemu_get_be32(f); |
|
665 |
ads_en = qemu_get_be32(f); |
|
666 |
max_en = qemu_get_be32(f); |
|
667 |
bl_intensity = qemu_get_be32(f); |
|
668 |
bl_power = qemu_get_be32(f); |
|
692 |
CorgiSSPState *s = (CorgiSSPState *)opaque; |
|
693 |
int i; |
|
669 | 694 |
|
695 |
if (version_id != 1) { |
|
696 |
return -EINVAL; |
|
697 |
} |
|
698 |
for (i = 0; i < 3; i++) { |
|
699 |
s->enable[i] = qemu_get_be32(f); |
|
700 |
} |
|
670 | 701 |
return 0; |
671 | 702 |
} |
672 | 703 |
|
704 |
static void corgi_ssp_init(SSISlave *dev) |
|
705 |
{ |
|
706 |
CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev); |
|
707 |
|
|
708 |
qdev_init_gpio_in(&dev->qdev, corgi_ssp_gpio_cs, 3); |
|
709 |
s->bus[0] = ssi_create_bus(); |
|
710 |
qdev_attach_child_bus(&dev->qdev, "ssi0", s->bus[0]); |
|
711 |
s->bus[1] = ssi_create_bus(); |
|
712 |
qdev_attach_child_bus(&dev->qdev, "ssi1", s->bus[1]); |
|
713 |
s->bus[2] = ssi_create_bus(); |
|
714 |
qdev_attach_child_bus(&dev->qdev, "ssi2", s->bus[2]); |
|
715 |
|
|
716 |
register_savevm("spitz_ssp", -1, 1, spitz_ssp_save, spitz_ssp_load, s); |
|
717 |
} |
|
718 |
|
|
673 | 719 |
static void spitz_ssp_attach(PXA2xxState *cpu) |
674 | 720 |
{ |
675 |
qemu_irq *chipselects; |
|
721 |
DeviceState *mux; |
|
722 |
DeviceState *dev; |
|
723 |
void *bus; |
|
724 |
|
|
725 |
mux = ssi_create_slave(cpu->ssp[CORGI_SSP_PORT - 1], "corgi-ssp"); |
|
676 | 726 |
|
677 |
lcd_en = ads_en = max_en = 0; |
|
727 |
bus = qdev_get_child_bus(mux, "ssi0"); |
|
728 |
dev = ssi_create_slave(bus, "spitz-lcdtg"); |
|
678 | 729 |
|
679 |
ads7846 = ads7846_init(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_TP_INT]); |
|
730 |
bus = qdev_get_child_bus(mux, "ssi1"); |
|
731 |
dev = ssi_create_slave(bus, "ads7846"); |
|
732 |
qdev_connect_gpio_out(dev, 0, |
|
733 |
pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_TP_INT]); |
|
680 | 734 |
|
681 |
max1111 = max1111_init(0); |
|
735 |
bus = qdev_get_child_bus(mux, "ssi2"); |
|
736 |
max1111 = ssi_create_slave(bus, "max1111"); |
|
682 | 737 |
max111x_set_input(max1111, MAX1111_BATT_VOLT, SPITZ_BATTERY_VOLT); |
683 | 738 |
max111x_set_input(max1111, MAX1111_BATT_TEMP, 0); |
684 | 739 |
max111x_set_input(max1111, MAX1111_ACIN_VOLT, SPITZ_CHARGEON_ACIN); |
685 | 740 |
|
686 |
pxa2xx_ssp_attach(cpu->ssp[CORGI_SSP_PORT - 1], corgi_ssp_read, |
|
687 |
corgi_ssp_write, cpu); |
|
688 |
|
|
689 |
chipselects = qemu_allocate_irqs(corgi_ssp_gpio_cs, cpu, 3); |
|
690 |
pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_LCDCON_CS, chipselects[0]); |
|
691 |
pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_ADS7846_CS, chipselects[1]); |
|
692 |
pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_MAX1111_CS, chipselects[2]); |
|
693 |
|
|
694 |
bl_intensity = 0x20; |
|
695 |
bl_power = 0; |
|
696 |
|
|
697 |
register_savevm("spitz_ssp", 0, 0, spitz_ssp_save, spitz_ssp_load, cpu); |
|
741 |
pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_LCDCON_CS, |
|
742 |
qdev_get_gpio_in(mux, 0)); |
|
743 |
pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_ADS7846_CS, |
|
744 |
qdev_get_gpio_in(mux, 1)); |
|
745 |
pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_MAX1111_CS, |
|
746 |
qdev_get_gpio_in(mux, 2)); |
|
698 | 747 |
} |
699 | 748 |
|
700 | 749 |
/* CF Microdrive */ |
... | ... | |
1018 | 1067 |
.desc = "Terrier PDA (PXA270)", |
1019 | 1068 |
.init = terrier_init, |
1020 | 1069 |
}; |
1070 |
|
|
1071 |
static SSISlaveInfo corgi_ssp_info = { |
|
1072 |
.init = corgi_ssp_init, |
|
1073 |
.transfer = corgi_ssp_transfer |
|
1074 |
}; |
|
1075 |
|
|
1076 |
static SSISlaveInfo spitz_lcdtg_info = { |
|
1077 |
.init = spitz_lcdtg_init, |
|
1078 |
.transfer = spitz_lcdtg_transfer |
|
1079 |
}; |
|
1080 |
|
|
1081 |
static void spitz_register_devices(void) |
|
1082 |
{ |
|
1083 |
ssi_register_slave("corgi-ssp", sizeof(CorgiSSPState), &corgi_ssp_info); |
|
1084 |
ssi_register_slave("spitz-lcdtg", sizeof(SpitzLCDTG), &spitz_lcdtg_info); |
|
1085 |
} |
|
1086 |
|
|
1087 |
device_init(spitz_register_devices) |
Also available in: Unified diff