summaryrefslogtreecommitdiff
path: root/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c')
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c83
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 */
108static struct mutex avr_mtx; 113static struct mutex avr_mtx;
114/* serializes hdq read/write and status retrieval */
115static 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
503int _battery_level(void) 511int _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
521int _battery_voltage(void)
522{
523 return avr_hid_hdq_read_short(HDQ_REG_VOLT);
524}
525
526int _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
513unsigned int power_input_status(void) 532unsigned 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
546static 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
574int 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
587int 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
527static void avr_hid_enable_wheel(void) 610static void avr_hid_enable_wheel(void)
528{ 611{
529 uint8_t enable = 0x01; 612 uint8_t enable = 0x01;