diff options
Diffstat (limited to 'firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c')
-rw-r--r-- | firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c index 8ebba3a8d5..ed7dab1572 100644 --- a/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c +++ b/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c | |||
@@ -104,8 +104,15 @@ | |||
104 | #define SYS_CTRL_EN_TS_THERM 0x06 | 104 | #define SYS_CTRL_EN_TS_THERM 0x06 |
105 | #define SYS_CTRL_FRESET 0x80 | 105 | #define SYS_CTRL_FRESET 0x80 |
106 | 106 | ||
107 | /* HDQ status codes */ | ||
108 | #define HDQ_STATUS_OK 0x00 | ||
109 | #define HDQ_STATUS_NOT_READY 0x01 | ||
110 | #define HDQ_STATUS_TIMEOUT 0x02 | ||
111 | |||
107 | /* protects spi avr commands from concurrent access */ | 112 | /* protects spi avr commands from concurrent access */ |
108 | static struct mutex avr_mtx; | 113 | static struct mutex avr_mtx; |
114 | /* serializes hdq read/write and status retrieval */ | ||
115 | static struct mutex hdq_mtx; | ||
109 | 116 | ||
110 | /* AVR thread events */ | 117 | /* AVR thread events */ |
111 | #define INPUT_INTERRUPT 1 | 118 | #define INPUT_INTERRUPT 1 |
@@ -498,6 +505,7 @@ void avr_hid_init(void) | |||
498 | IO_SERIAL1_MODE = 0x6DB; | 505 | IO_SERIAL1_MODE = 0x6DB; |
499 | 506 | ||
500 | mutex_init(&avr_mtx); | 507 | mutex_init(&avr_mtx); |
508 | mutex_init(&hdq_mtx); | ||
501 | } | 509 | } |
502 | 510 | ||
503 | int _battery_level(void) | 511 | int _battery_level(void) |
@@ -510,6 +518,17 @@ int _battery_level(void) | |||
510 | return avr_battery_level & BATTERY_LEVEL_PERCENTAGE_MASK; | 518 | return avr_battery_level & BATTERY_LEVEL_PERCENTAGE_MASK; |
511 | } | 519 | } |
512 | 520 | ||
521 | int _battery_voltage(void) | ||
522 | { | ||
523 | return avr_hid_hdq_read_short(HDQ_REG_VOLT); | ||
524 | } | ||
525 | |||
526 | int _battery_time(void) | ||
527 | { | ||
528 | /* HDQ_REG_TTE reads as 65535 when charging */ | ||
529 | return avr_hid_hdq_read_short(HDQ_REG_TTE); | ||
530 | } | ||
531 | |||
513 | unsigned int power_input_status(void) | 532 | unsigned int power_input_status(void) |
514 | { | 533 | { |
515 | if (avr_battery_status & BATTERY_STATUS_CHARGER_CONNECTED) | 534 | if (avr_battery_status & BATTERY_STATUS_CHARGER_CONNECTED) |
@@ -524,6 +543,70 @@ bool charging_state(void) | |||
524 | return (avr_battery_status & BATTERY_STATUS_CHARGING) != 0; | 543 | return (avr_battery_status & BATTERY_STATUS_CHARGING) != 0; |
525 | } | 544 | } |
526 | 545 | ||
546 | static int avr_hid_hdq_read_byte_internal(uint8_t address) | ||
547 | { | ||
548 | uint8_t result[2]; | ||
549 | |||
550 | if (!avr_execute_command(CMD_HDQ_READ, &address, sizeof(address))) | ||
551 | { | ||
552 | return -1; | ||
553 | } | ||
554 | |||
555 | do | ||
556 | { | ||
557 | mdelay(10); | ||
558 | if (!avr_execute_command(CMD_HDQ_STATUS, result, sizeof(result))) | ||
559 | { | ||
560 | return -1; | ||
561 | } | ||
562 | } | ||
563 | while (result[0] == HDQ_STATUS_NOT_READY); | ||
564 | |||
565 | if (result[0] != HDQ_STATUS_OK) | ||
566 | { | ||
567 | logf("HDQ read %d status %d", address, result[0]); | ||
568 | return -1; | ||
569 | } | ||
570 | |||
571 | return result[1]; | ||
572 | } | ||
573 | |||
574 | int avr_hid_hdq_read_byte(uint8_t address) | ||
575 | { | ||
576 | int retry; | ||
577 | int value = -1; | ||
578 | for (retry = 0; (retry < 3) && (value < 0); retry++) | ||
579 | { | ||
580 | mutex_lock(&hdq_mtx); | ||
581 | value = avr_hid_hdq_read_byte_internal(address); | ||
582 | mutex_unlock(&hdq_mtx); | ||
583 | } | ||
584 | return value; | ||
585 | } | ||
586 | |||
587 | int avr_hid_hdq_read_short(uint8_t address) | ||
588 | { | ||
589 | int old_hi = -1, old_lo = -1, hi = -2, lo = -2; | ||
590 | /* Keep reading until we read the same value twice. | ||
591 | * There's no atomic 16-bit value retrieval, so keep reading | ||
592 | * until we read the same value twice. HDQ registers update | ||
593 | * no more than once per 2.56 seconds so usually there will | ||
594 | * be 4 reads and sometimes 6 reads. | ||
595 | */ | ||
596 | while ((old_hi != hi) || (old_lo != lo)) | ||
597 | { | ||
598 | old_hi = hi; | ||
599 | old_lo = lo; | ||
600 | hi = avr_hid_hdq_read_byte(address + 1); | ||
601 | lo = avr_hid_hdq_read_byte(address); | ||
602 | } | ||
603 | if ((hi < 0) || (lo < 0)) | ||
604 | { | ||
605 | return -1; | ||
606 | } | ||
607 | return (hi << 8) | lo; | ||
608 | } | ||
609 | |||
527 | static void avr_hid_enable_wheel(void) | 610 | static void avr_hid_enable_wheel(void) |
528 | { | 611 | { |
529 | uint8_t enable = 0x01; | 612 | uint8_t enable = 0x01; |