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