Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

erosqnative: hw4 support

Support hw4 units with AXP2101 PMU

Bootloader successfully compiles and loads onto device.
The LCD appears to be identical to hw3 units.
Scroll wheel and buttons work
Audio output works, including volume.
HP/LO detect works
Rockbox build is generic
GPIO gating logic seems to be working as intended now.

- Added new GPIO definitions - some significant overlaps with pins
from previous hardware revisions...
- Added some GPIO definitions for older players we didn't know about
- Add register definitions for AXP2101 from datasheet
(these are very different from AXP192!)
- Add AXP2101 regulator definitions, need to support multiple step
sizes per regulator.
- Verify AXP2101 voltage set multi-range logic
- Verify AXP2101 voltage get multi-range logic
- Make AXP2101 its own driver
- AXP2101 driver should be "minimally viable", though I think
there is some extra functionality that could be implemented.
- Disabling the coulomb counter stuff - we could maybe make
the E-Gauge work for the same purpose, but it only appears to
be used on the debug screen at the moment so it doesn't seem
like it's worth the effort.
- Found new button GPIOs
- Found error in my GPIO setting logic, blue light works now!
- Set LDO/DCDC output voltages to OF's settings, as far as
I can tell.
- Determined we probably want TCS1421_CFG1:0 to be 0x00,
for UFP behavior
- Tested this rb build with both old and new bootloaders on hw1.5,
hw2, hw4 in as many configurations as I can think of, works across
the board.
- Bootloader can install itself on hw4, so nand chip isn't novel
- Uninstallation file can be made by patcher script, works on hw4
- Installation file can be made by patcher script, works on hw4
- Added HW4 to rbutil, manual

Change-Id: I5b75782273e81c2c6f2b9c79501c8b7cbf88391f

authored by

Dana Conrad and committed by
Solomon Peachy
253eb79d d7b57e33

+1403 -108
+3
firmware/SOURCES
··· 1976 1976 #ifdef HAVE_AXP_PMU 1977 1977 drivers/axp-pmu.c 1978 1978 #endif 1979 + #ifdef HAVE_AXP2101_ADDON 1980 + drivers/axp-2101.c 1981 + #endif 1979 1982 #ifdef HAVE_FT6x06 1980 1983 drivers/ft6x06.c 1981 1984 #endif
+661
firmware/drivers/axp-2101.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2021 Aidan MacDonald 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + 22 + #include "axp-2101.h" 23 + #include "power.h" 24 + #include "system.h" 25 + #include "i2c-async.h" 26 + #include <string.h> 27 + 28 + /* Headers for the debug menu */ 29 + #ifndef BOOTLOADER 30 + # include "action.h" 31 + # include "list.h" 32 + # include <stdio.h> 33 + #endif 34 + 35 + struct axp_adc_info { 36 + uint8_t reg; 37 + uint8_t en_reg; 38 + uint8_t en_bit; 39 + int8_t num; 40 + int8_t den; 41 + }; 42 + 43 + struct axp_supply_info { 44 + uint8_t volt_reg; 45 + uint8_t volt_reg_mask; 46 + uint8_t en_reg; 47 + uint8_t en_bit; 48 + int min_mV; 49 + int max_mV; // if multiple steps, set to max of step 1 50 + int step_mV; 51 + int step2_min_mV; 52 + int step2_mV; 53 + int step2_max_mV; 54 + int step3_min_mV; 55 + int step3_mV; 56 + int step3_max_mV; 57 + }; 58 + 59 + static const struct axp_adc_info axp_adc_info[AXP2101_NUM_ADC_CHANNELS] = { 60 + // TODO: Datasheet ADC conversion table doesn't seem to make any sense... 61 + // 0x000 0x001 0x002 ... 0xFFF 62 + // 0mV 1mV 2mV ... 8.192V 63 + [AXP2101_ADC_VBAT_VOLTAGE] = {AXP2101_REG_ADC_VBAT_H, AXP2101_REG_ADCCHNENABLE, 1 << 0, 1, 1}, 64 + // 0mV 1mV 2mV ... 8.192V 65 + [AXP2101_ADC_VBUS_VOLTAGE] = {AXP2101_REG_ADC_VBUS_H, AXP2101_REG_ADCCHNENABLE, 1 << 2, 1, 1}, 66 + // 0mV 1mV 2mV ... 8.192V 67 + [AXP2101_ADC_VSYS_VOLTAGE] = {AXP2101_REG_ADC_VSYS_H, AXP2101_REG_ADCCHNENABLE, 1 << 3, 1, 1}, 68 + // 0mV 0.5mV 1mV ... 4.096V 69 + [AXP2101_ADC_TS_VOLTAGE] = {AXP2101_REG_ADC_TS_H, AXP2101_REG_ADCCHNENABLE, 1 << 1, 1, 1}, 70 + // 0mV 0.1mV 2mV ... 0.8192V 71 + [AXP2101_ADC_DIE_TEMPERATURE] = {AXP2101_REG_ADC_TDIE_H, AXP2101_REG_ADCCHNENABLE, 1 << 4, 1, 1}, 72 + }; 73 + 74 + static const struct axp_supply_info axp_supply_info[AXP2101_NUM_SUPPLIES] = { 75 + [AXP2101_SUPPLY_DCDC1] = { 76 + .volt_reg = 0x82, 77 + .volt_reg_mask = 0x1f, // N.B. max value 0b10011, values higher reserved 78 + .en_reg = 0x80, 79 + .en_bit = 0, 80 + .min_mV = 1500, 81 + .max_mV = 3400, 82 + .step_mV = 100, 83 + .step2_min_mV = 0, 84 + .step2_mV = 0, 85 + .step2_max_mV = 0, 86 + .step3_min_mV = 0, 87 + .step3_mV = 0, 88 + .step3_max_mV = 0, 89 + }, 90 + [AXP2101_SUPPLY_DCDC2] = { 91 + .volt_reg = 0x83, 92 + .volt_reg_mask = 0x7f, // N.B. max value 0b1010111, values higher reserved 93 + .en_reg = 0x80, 94 + .en_bit = 1, 95 + .min_mV = 500, 96 + .max_mV = 1200, 97 + .step_mV = 10, 98 + .step2_min_mV = 1220, 99 + .step2_mV = 20, 100 + .step2_max_mV = 1540, 101 + .step3_min_mV = 0, 102 + .step3_mV = 0, 103 + .step3_max_mV = 0, 104 + // N.B. 10mV/step from 0.5 - 1.2v (71 steps), 105 + // 20mV/step from 1.22 - 1.54v (17 steps) 106 + }, 107 + [AXP2101_SUPPLY_DCDC3] = { 108 + .volt_reg = 0x84, 109 + .volt_reg_mask = 0x7f, // N.B. max value 0b1101011, values higher reserved 110 + .en_reg = 0x80, 111 + .en_bit = 2, 112 + .min_mV = 500, 113 + .max_mV = 1200, 114 + .step_mV = 10, 115 + .step2_min_mV = 1220, 116 + .step2_mV = 20, 117 + .step2_max_mV = 1540, 118 + .step3_min_mV = 1600, 119 + .step3_mV = 100, 120 + .step3_max_mV = 3400, 121 + // N.B. 10mV/step from 0.5 - 1.2V (71 steps) 122 + // 20mV/step from 1.22 - 1.54V (17 steps) 123 + // 100mV/step from 1.6 - 3.4V (19 steps) 124 + }, 125 + [AXP2101_SUPPLY_DCDC4] = { 126 + .volt_reg = 0x85, 127 + .volt_reg_mask = 0x7f, // N.B. max value 0b1100110, values higher reserved 128 + .en_reg = 0x80, 129 + .en_bit = 3, 130 + .min_mV = 500, 131 + .max_mV = 1200, 132 + .step_mV = 10, 133 + .step2_min_mV = 1220, 134 + .step2_mV = 20, 135 + .step2_max_mV = 1840, 136 + .step3_min_mV = 0, 137 + .step3_mV = 0, 138 + .step3_max_mV = 0, 139 + // N.B. 10mV/step from 0.5 - 1.2V (71 steps) 140 + // 20mV/step from 1.22 - 1.84V (32 steps) 141 + }, 142 + [AXP2101_SUPPLY_DCDC5] = { 143 + .volt_reg = 0x86, 144 + .volt_reg_mask = 0x3f, // N.B. max value 0b10111, values higher reserved 145 + .en_reg = 0x80, 146 + .en_bit = 4, 147 + .min_mV = 1400, 148 + .max_mV = 3700, 149 + .step_mV = 100, 150 + .step2_min_mV = 0, 151 + .step2_mV = 0, 152 + .step2_max_mV = 0, 153 + .step3_min_mV = 0, 154 + .step3_mV = 0, 155 + .step3_max_mV = 0, 156 + }, 157 + [AXP2101_SUPPLY_ALDO1] = { 158 + .volt_reg = 0x92, 159 + .volt_reg_mask = 0x3f, // N.B. max value 0b1110, values higher reserved 160 + .en_reg = 0x90, 161 + .en_bit = 0, 162 + .min_mV = 500, 163 + .max_mV = 3500, 164 + .step_mV = 100, 165 + .step2_min_mV = 0, 166 + .step2_mV = 0, 167 + .step2_max_mV = 0, 168 + .step3_min_mV = 0, 169 + .step3_mV = 0, 170 + .step3_max_mV = 0, 171 + }, 172 + [AXP2101_SUPPLY_ALDO2] = { 173 + .volt_reg = 0x93, 174 + .volt_reg_mask = 0x3f, // N.B. max value 0b1110, values higher reserved 175 + .en_reg = 0x90, 176 + .en_bit = 1, 177 + .min_mV = 500, 178 + .max_mV = 3500, 179 + .step_mV = 100, 180 + .step2_min_mV = 0, 181 + .step2_mV = 0, 182 + .step2_max_mV = 0, 183 + .step3_min_mV = 0, 184 + .step3_mV = 0, 185 + .step3_max_mV = 0, 186 + }, 187 + [AXP2101_SUPPLY_ALDO3] = { 188 + .volt_reg = 0x94, 189 + .volt_reg_mask = 0x3f, // N.B. max value 0b1110, values higher reserved 190 + .en_reg = 0x90, 191 + .en_bit = 2, 192 + .min_mV = 500, 193 + .max_mV = 3500, 194 + .step_mV = 100, 195 + .step2_min_mV = 0, 196 + .step2_mV = 0, 197 + .step2_max_mV = 0, 198 + .step3_min_mV = 0, 199 + .step3_mV = 0, 200 + .step3_max_mV = 0, 201 + }, 202 + [AXP2101_SUPPLY_ALDO4] = { 203 + .volt_reg = 0x95, 204 + .volt_reg_mask = 0x3f, // N.B. max value 0b1110, values higher reserved 205 + .en_reg = 0x90, 206 + .en_bit = 3, 207 + .min_mV = 500, 208 + .max_mV = 3500, 209 + .step_mV = 100, 210 + .step2_min_mV = 0, 211 + .step2_mV = 0, 212 + .step2_max_mV = 0, 213 + .step3_min_mV = 0, 214 + .step3_mV = 0, 215 + .step3_max_mV = 0, 216 + }, 217 + [AXP2101_SUPPLY_BLDO1] = { 218 + .volt_reg = 0x96, 219 + .volt_reg_mask = 0x3f, // N.B. max value 0b11110, values higher reserved 220 + .en_reg = 0x90, 221 + .en_bit = 4, 222 + .min_mV = 500, 223 + .max_mV = 3500, 224 + .step_mV = 100, 225 + .step2_min_mV = 0, 226 + .step2_mV = 0, 227 + .step2_max_mV = 0, 228 + .step3_min_mV = 0, 229 + .step3_mV = 0, 230 + .step3_max_mV = 0, 231 + }, 232 + [AXP2101_SUPPLY_BLDO2] = { 233 + .volt_reg = 0x97, 234 + .volt_reg_mask = 0x3f, // N.B. max value 0b11110, values higher reserved 235 + .en_reg = 0x90, 236 + .en_bit = 5, 237 + .min_mV = 500, 238 + .max_mV = 3500, 239 + .step_mV = 100, 240 + .step2_min_mV = 0, 241 + .step2_mV = 0, 242 + .step2_max_mV = 0, 243 + .step3_min_mV = 0, 244 + .step3_mV = 0, 245 + .step3_max_mV = 0, 246 + }, 247 + [AXP2101_SUPPLY_DLDO1] = { 248 + .volt_reg = 0x99, 249 + .volt_reg_mask = 0x3f, // N.B. max value 0b11100, values higher reserved 250 + .en_reg = 0x90, 251 + .en_bit = 7, 252 + .min_mV = 500, 253 + .max_mV = 3400, 254 + .step_mV = 100, 255 + .step2_min_mV = 0, 256 + .step2_mV = 0, 257 + .step2_max_mV = 0, 258 + .step3_min_mV = 0, 259 + .step3_mV = 0, 260 + .step3_max_mV = 0, 261 + }, 262 + [AXP2101_SUPPLY_DLDO2] = { 263 + .volt_reg = 0x9a, 264 + .volt_reg_mask = 0x3f, // N.B. max value 0b11100, values higher reserved 265 + .en_reg = 0x91, 266 + .en_bit = 0, 267 + .min_mV = 500, 268 + .max_mV = 1400, 269 + .step_mV = 560, 270 + .step2_min_mV = 0, 271 + .step2_mV = 0, 272 + .step2_max_mV = 0, 273 + .step3_min_mV = 0, 274 + .step3_mV = 0, 275 + .step3_max_mV = 0, 276 + }, 277 + [AXP2101_SUPPLY_VCPUS] = { 278 + .volt_reg = 0x98, 279 + .volt_reg_mask = 0x3f, // N.B. max value 0b10011, values higher reserved 280 + .en_reg = 0x90, 281 + .en_bit = 6, 282 + .min_mV = 500, 283 + .max_mV = 1400, 284 + .step_mV = 50, 285 + .step2_min_mV = 0, 286 + .step2_mV = 0, 287 + .step2_max_mV = 0, 288 + .step3_min_mV = 0, 289 + .step3_mV = 0, 290 + .step3_max_mV = 0, 291 + }, 292 + // No voltage reg given - are these fixed? 293 + // [AXP_SUPPLY_RTCLDO1] = { 294 + // }, 295 + // [AXP_SUPPLY_RTCLDO2] = { 296 + // }, 297 + }; 298 + 299 + void axp2101_init(void) 300 + { 301 + } 302 + 303 + void axp2101_supply_set_voltage(int supply, int voltage) 304 + { 305 + const struct axp_supply_info* info = &axp_supply_info[supply]; 306 + if(info->volt_reg == 0 || info->volt_reg_mask == 0) 307 + return; 308 + 309 + if(voltage > 0 && info->step_mV != 0) { 310 + if(voltage < info->min_mV) 311 + return; 312 + 313 + int regval; 314 + 315 + // there's probably a more elegant way to do this... 316 + if(voltage > info->max_mV) { 317 + if(info->step2_max_mV == 0) { 318 + return; 319 + } else { 320 + if(voltage > info->step2_max_mV) { 321 + if(info->step3_max_mV == 0 || voltage > info->step3_max_mV) { 322 + return; 323 + } else { 324 + // step3 range 325 + regval = ((info->max_mV - info->min_mV) / info->step_mV)\ 326 + + ((info->step2_max_mV - info->step2_min_mV) / info->step2_mV)\ 327 + + ((voltage - info->step3_min_mV) / info->step3_mV) + 2; 328 + } 329 + } else { 330 + // step2 range 331 + regval = ((info->max_mV - info->min_mV) / info->step_mV)\ 332 + + ((voltage - info->step2_min_mV) / info->step2_mV) + 1; 333 + } 334 + } 335 + } else { 336 + // step1 range 337 + regval = (voltage - info->min_mV) / info->step_mV; 338 + } 339 + i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, info->volt_reg, 340 + info->volt_reg_mask, regval, NULL); 341 + } 342 + 343 + if(info->en_bit != 0xff) { 344 + i2c_reg_setbit1(AXP_PMU_BUS, AXP_PMU_ADDR, 345 + info->en_reg, info->en_bit, 346 + voltage > 0 ? 1 : 0, NULL); 347 + } 348 + } 349 + 350 + int axp2101_supply_get_voltage(int supply) 351 + { 352 + const struct axp_supply_info* info = &axp_supply_info[supply]; 353 + if(info->volt_reg == 0) 354 + return AXP2101_SUPPLY_NOT_PRESENT; 355 + 356 + if(info->en_reg != 0) { 357 + int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, info->en_reg); 358 + if(r < 0) 359 + return AXP2101_SUPPLY_DISABLED; 360 + if(r & (1 << info->en_bit) == 0) 361 + return AXP2101_SUPPLY_DISABLED; 362 + } 363 + 364 + /* Hack, avoid undefined shift below. Can be useful too... */ 365 + if(info->volt_reg_mask == 0) 366 + return info->min_mV; 367 + 368 + int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, info->volt_reg); 369 + if(r < 0) 370 + return 0; 371 + 372 + int val; 373 + r = r & info->volt_reg_mask; 374 + 375 + // there's probably a more elegant way to do this... 376 + if(r > ((info->max_mV - info->min_mV) / info->step_mV)) { 377 + r = r - ((info->max_mV - info->min_mV) / info->step_mV); 378 + 379 + if(r > ((info->step2_max_mV - info->step2_min_mV) / info->step2_mV + 1)) { 380 + r = r - ((info->step2_max_mV - info->step2_min_mV) / info->step2_mV); 381 + /* step 3 */ 382 + val = info->step3_min_mV + ((r-2) * info->step3_mV); 383 + 384 + } else { 385 + /* step 2 */ 386 + val = info->step2_min_mV + ((r-1) * info->step2_mV); 387 + 388 + } 389 + } else { 390 + /* step 1 */ 391 + val = info->min_mV + (r * info->step_mV); 392 + 393 + } 394 + 395 + return val; 396 + } 397 + 398 + /* TODO: can we trust the battery current direction? */ 399 + int axp2101_battery_status(void) 400 + { 401 + int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP2101_REG_PMU_STATUS2); 402 + if((r >> 5) & 0x03 == 0) { 403 + return AXP2101_BATT_FULL; 404 + } else if((r >> 5) & 0x03 == 01) { 405 + return AXP2101_BATT_CHARGING; 406 + } else { 407 + return AXP2101_BATT_DISCHARGING; 408 + } 409 + } 410 + 411 + int axp2101_input_status(void) 412 + { 413 + #ifdef HAVE_BATTERY_SWITCH 414 + int input_status = 0; 415 + #else 416 + int input_status = AXP2101_INPUT_BATTERY; 417 + #endif 418 + 419 + int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP2101_REG_PMU_STATUS1); 420 + if(r & 0x20) 421 + input_status |= AXP2101_INPUT_USB; 422 + #ifdef HAVE_BATTERY_SWITCH 423 + if(r & 0x80) 424 + input_status |= AXP2101_INPUT_BATTERY; 425 + #endif 426 + 427 + return input_status; 428 + } 429 + 430 + int axp2101_adc_read(int adc) 431 + { 432 + int value = axp2101_adc_read_raw(adc); 433 + if(value == INT_MIN) 434 + return INT_MIN; 435 + 436 + return axp2101_adc_conv_raw(adc, value); 437 + } 438 + 439 + int axp2101_adc_read_raw(int adc) 440 + { 441 + /* Read the ADC */ 442 + uint8_t buf[2]; 443 + uint8_t reg = axp_adc_info[adc].reg; 444 + int rc = i2c_reg_read(AXP_PMU_BUS, AXP_PMU_ADDR, reg, 2, &buf[0]); 445 + if(rc != I2C_STATUS_OK) 446 + return INT_MIN; 447 + 448 + /* Parse the value */ 449 + return ((buf[0] & 0x3f) << 8) | (buf[1] & 0xff); 450 + } 451 + 452 + int axp2101_adc_conv_raw(int adc, int value) 453 + { 454 + return axp_adc_info[adc].num * value / axp_adc_info[adc].den; 455 + } 456 + 457 + void axp2101_adc_set_enabled(int adc_bits) 458 + { 459 + uint8_t xfer[1]; 460 + xfer[0] = 0; 461 + 462 + /* Compute the new register values */ 463 + const struct axp_adc_info* info = axp_adc_info; 464 + for(int i = 0; i < AXP2101_NUM_ADC_CHANNELS; ++i) { 465 + if(!(adc_bits & (1 << i))) 466 + continue; 467 + 468 + xfer[0] |= info[i].en_bit; 469 + } 470 + 471 + /* Update the configuration */ 472 + i2c_reg_write(AXP_PMU_BUS, AXP_PMU_ADDR, AXP2101_REG_ADCCHNENABLE, 1, &xfer[0]); 473 + } 474 + 475 + // TODO: See if we can figure out "optimum" battery chemistry-type settings 476 + // like constant-current charging, charge curves... that stuff is all configurable 477 + // as far as I can tell! Probably important to at least figure out if the defaults 478 + // are clearly wrong or not! 479 + 480 + // TODO: what are DATA_BUFFER 0-3 for???? 481 + 482 + // there are many current settings: 483 + // Reg 16: Input current limit control 484 + // Reg 61: Precharge current limit 485 + // Reg 62: Constant current charge current limit 486 + // Reg 63: Charging termination current limit 487 + 488 + // there are also voltage settings for charging: 489 + // Reg 14: Linear Charger Vsys voltage dpm 490 + // Reg 15: Input Voltage limit control 491 + // Reg 64: CV charger charge voltage limit 492 + 493 + // There are also some timer stuff: 494 + // Reg 67: Charger timeout setting and control 495 + 496 + // constant current charge current limits 497 + static const int chargecurrent_tbl[] = { 498 + 0, 25, 50, 75, 100, 125, 150, 175, 200, 499 + 300, 400, 500, 600, 700, 800, 900, 1000, 500 + }; 501 + 502 + // constant current charge current limits 503 + void axp2101_set_charge_current(int current_mA) 504 + { 505 + /* find greatest charging current not exceeding requested current */ 506 + unsigned int index = 0; 507 + while(index < ARRAYLEN(chargecurrent_tbl)-1 && 508 + chargecurrent_tbl[index+1] <= current_mA) 509 + ++index; 510 + 511 + i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 512 + AXP2101_REG_ICC_SETTING, 0x0f, index, NULL); 513 + } 514 + 515 + int axp2101_get_charge_current(void) 516 + { 517 + int ret = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, 518 + AXP2101_REG_ICC_SETTING); 519 + if(ret < 0) 520 + ret = 0; 521 + 522 + return chargecurrent_tbl[ret & 0x0f]; 523 + } 524 + 525 + void axp2101_power_off(void) 526 + { 527 + /* Set the shutdown bit */ 528 + i2c_reg_setbit1(AXP_PMU_BUS, AXP_PMU_ADDR, 529 + AXP2101_REG_PMUCOMMCONFIG, 0, 1, NULL); 530 + } 531 + 532 + #ifndef BOOTLOADER 533 + enum { 534 + AXP_DEBUG_BATTERY_STATUS, 535 + AXP_DEBUG_INPUT_STATUS, 536 + AXP_DEBUG_CHARGE_CURRENT, 537 + AXP_DEBUG_FIRST_ADC, 538 + AXP_DEBUG_FIRST_SUPPLY = AXP_DEBUG_FIRST_ADC + AXP2101_NUM_ADC_CHANNELS, 539 + AXP_DEBUG_NUM_ENTRIES = AXP_DEBUG_FIRST_SUPPLY + AXP2101_NUM_SUPPLIES, 540 + }; 541 + 542 + static int axp2101_debug_menu_cb(int action, struct gui_synclist* lists) 543 + { 544 + (void)lists; 545 + 546 + if(action == ACTION_NONE) 547 + action = ACTION_REDRAW; 548 + 549 + return action; 550 + } 551 + 552 + static const char* axp2101_debug_menu_get_name(int item, void* data, 553 + char* buf, size_t buflen) 554 + { 555 + (void)data; 556 + 557 + static const char* const adc_names[] = { 558 + "V_bat", "V_bus", "V_sys", "V_ts", "V_die", 559 + }; 560 + 561 + static const char* const adc_units[] = { 562 + "mV", "mV", "mV", "mV", "C*100", 563 + }; 564 + 565 + static const char* const supply_names[] = { 566 + "DCDC1", "DCDC2", "DCDC3", "DCDC4", "DCDC5", 567 + "ALDO1", "ALDO2", "ALDO3", "ALDO4", "BLDO1", "BLDO2", "DLDO1", "DLDO2", 568 + "VCPUS", 569 + }; 570 + 571 + int adc = item - AXP_DEBUG_FIRST_ADC; 572 + if(item >= AXP_DEBUG_FIRST_ADC && adc < AXP2101_NUM_ADC_CHANNELS) { 573 + int raw_value = axp2101_adc_read_raw(adc); 574 + if(raw_value == INT_MIN) { 575 + snprintf(buf, buflen, "%s: [Disabled]", adc_names[adc]); 576 + return buf; 577 + } 578 + 579 + int value = axp2101_adc_conv_raw(adc, raw_value); 580 + snprintf(buf, buflen, "%s: %d %s", adc_names[adc], 581 + value, adc_units[adc]); 582 + 583 + return buf; 584 + } 585 + 586 + int supply = item - AXP_DEBUG_FIRST_SUPPLY; 587 + if(item >= AXP_DEBUG_FIRST_SUPPLY && supply < AXP2101_NUM_SUPPLIES) { 588 + int voltage = axp2101_supply_get_voltage(supply); 589 + if(voltage == AXP2101_SUPPLY_NOT_PRESENT) 590 + snprintf(buf, buflen, "%s: [Not Present]", supply_names[supply]); 591 + else if(voltage == AXP2101_SUPPLY_DISABLED) 592 + snprintf(buf, buflen, "%s: [Disabled]", supply_names[supply]); 593 + else 594 + snprintf(buf, buflen, "%s: %d mV", supply_names[supply], voltage); 595 + 596 + return buf; 597 + } 598 + 599 + switch(item) { 600 + case AXP_DEBUG_BATTERY_STATUS: { 601 + switch(axp2101_battery_status()) { 602 + case AXP2101_BATT_FULL: 603 + return "Battery: Full"; 604 + case AXP2101_BATT_CHARGING: 605 + return "Battery: Charging"; 606 + case AXP2101_BATT_DISCHARGING: 607 + return "Battery: Discharging"; 608 + default: 609 + return "Battery: Unknown"; 610 + } 611 + } break; 612 + 613 + case AXP_DEBUG_INPUT_STATUS: { 614 + int s = axp2101_input_status(); 615 + const char* ac = (s & AXP2101_INPUT_AC) ? " AC" : ""; 616 + const char* usb = (s & AXP2101_INPUT_USB) ? " USB" : ""; 617 + const char* batt = (s & AXP2101_INPUT_BATTERY) ? " Battery" : ""; 618 + snprintf(buf, buflen, "Inputs:%s%s%s", ac, usb, batt); 619 + return buf; 620 + } break; 621 + 622 + case AXP_DEBUG_CHARGE_CURRENT: { 623 + int current = axp2101_get_charge_current(); 624 + snprintf(buf, buflen, "Max charge current: %d mA", current); 625 + return buf; 626 + } break; 627 + 628 + default: 629 + return "---"; 630 + } 631 + } 632 + 633 + bool axp2101_debug_menu(void) 634 + { 635 + struct simplelist_info info; 636 + simplelist_info_init(&info, "AXP debug", AXP_DEBUG_NUM_ENTRIES, NULL); 637 + info.action_callback = axp2101_debug_menu_cb; 638 + info.get_name = axp2101_debug_menu_get_name; 639 + return simplelist_show_list(&info); 640 + } 641 + #endif /* !BOOTLOADER */ 642 + 643 + /* This is basically the only valid implementation, so define it here */ 644 + unsigned int axp2101_power_input_status(void) 645 + { 646 + unsigned int state = 0; 647 + int input_status = axp2101_input_status(); 648 + 649 + if(input_status & AXP2101_INPUT_AC) 650 + state |= POWER_INPUT_MAIN_CHARGER; 651 + 652 + if(input_status & AXP2101_INPUT_USB) 653 + state |= POWER_INPUT_USB_CHARGER; 654 + 655 + #ifdef HAVE_BATTERY_SWITCH 656 + if(input_status & AXP2101_INPUT_BATTERY) 657 + state |= POWER_INPUT_BATTERY; 658 + #endif 659 + 660 + return state; 661 + }
+43 -12
firmware/drivers/axp-pmu.c
··· 25 25 #include "i2c-async.h" 26 26 #include <string.h> 27 27 28 + #if defined(HAVE_AXP2101_ADDON) 29 + # include "axp-2101.h" 30 + # include "devicedata.h" 31 + #endif 32 + 28 33 /* Headers for the debug menu */ 29 34 #ifndef BOOTLOADER 30 35 # include "action.h" ··· 521 526 522 527 bool axp_debug_menu(void) 523 528 { 524 - struct simplelist_info info; 525 - simplelist_info_init(&info, "AXP debug", AXP_DEBUG_NUM_ENTRIES, NULL); 526 - info.action_callback = axp_debug_menu_cb; 527 - info.get_name = axp_debug_menu_get_name; 528 - return simplelist_show_list(&info); 529 + #if defined(EROS_QN) 530 + int devicever; 531 + # if defined(BOOTLOADER) 532 + devicever = EROSQN_VER; 533 + # else 534 + devicever = device_data.lcd_version; 535 + # endif 536 + if (devicever >= 4) { 537 + return axp2101_debug_menu(); 538 + } else 539 + #endif 540 + { 541 + struct simplelist_info info; 542 + simplelist_info_init(&info, "AXP debug", AXP_DEBUG_NUM_ENTRIES, NULL); 543 + info.action_callback = axp_debug_menu_cb; 544 + info.get_name = axp_debug_menu_get_name; 545 + return simplelist_show_list(&info); 546 + } 529 547 } 530 548 #endif /* !BOOTLOADER */ 531 549 ··· 533 551 unsigned int power_input_status(void) 534 552 { 535 553 unsigned int state = 0; 536 - int input_status = axp_input_status(); 554 + #if defined(EROS_QN) 555 + int devicever; 556 + # if defined(BOOTLOADER) 557 + devicever = EROSQN_VER; 558 + # else 559 + devicever = device_data.lcd_version; 560 + # endif 561 + if (devicever >= 4) { 562 + return axp2101_power_input_status(); 563 + } else 564 + #endif 565 + { 566 + int input_status = axp_input_status(); 537 567 538 - if(input_status & AXP_INPUT_AC) 539 - state |= POWER_INPUT_MAIN_CHARGER; 568 + if(input_status & AXP_INPUT_AC) 569 + state |= POWER_INPUT_MAIN_CHARGER; 540 570 541 - if(input_status & AXP_INPUT_USB) 542 - state |= POWER_INPUT_USB_CHARGER; 571 + if(input_status & AXP_INPUT_USB) 572 + state |= POWER_INPUT_USB_CHARGER; 543 573 544 574 #ifdef HAVE_BATTERY_SWITCH 545 - if(input_status & AXP_INPUT_BATTERY) 546 - state |= POWER_INPUT_BATTERY; 575 + if(input_status & AXP_INPUT_BATTERY) 576 + state |= POWER_INPUT_BATTERY; 547 577 #endif 578 + } 548 579 549 580 return state; 550 581 }
+211
firmware/export/axp-2101.h
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2021 Aidan MacDonald 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + 22 + #ifndef __AXP_2101_H__ 23 + #define __AXP_2101_H__ 24 + 25 + #include "config.h" 26 + #include <stdbool.h> 27 + #include <stdint.h> 28 + 29 + /* ADC channels */ 30 + #define AXP2101_ADC_VBAT_VOLTAGE 0 31 + #define AXP2101_ADC_VBUS_VOLTAGE 1 32 + #define AXP2101_ADC_VSYS_VOLTAGE 2 33 + #define AXP2101_ADC_TS_VOLTAGE 3 34 + #define AXP2101_ADC_DIE_TEMPERATURE 4 35 + #define AXP2101_NUM_ADC_CHANNELS 5 36 + 37 + /* ADC sampling rates */ 38 + #define AXP2101_ADC_RATE_25HZ 0 39 + #define AXP2101_ADC_RATE_50HZ 1 40 + #define AXP2101_ADC_RATE_100HZ 2 41 + #define AXP2101_ADC_RATE_200HZ 3 42 + 43 + /* Return values of axp_battery_status() */ 44 + #define AXP2101_BATT_DISCHARGING 0 45 + #define AXP2101_BATT_CHARGING 1 46 + #define AXP2101_BATT_FULL 2 47 + 48 + /* Bits returned by axp_input_status() */ 49 + #define AXP2101_INPUT_AC (1 << 0) 50 + #define AXP2101_INPUT_USB (1 << 1) 51 + #define AXP2101_INPUT_BATTERY (1 << 2) 52 + #define AXP2101_INPUT_EXTERNAL (AXP_INPUT_AC|AXP_INPUT_USB) 53 + 54 + #define AXP2101_SUPPLY_DCDC1 0 55 + #define AXP2101_SUPPLY_DCDC2 1 56 + #define AXP2101_SUPPLY_DCDC3 2 57 + #define AXP2101_SUPPLY_DCDC4 3 58 + #define AXP2101_SUPPLY_DCDC5 4 59 + #define AXP2101_SUPPLY_ALDO1 5 60 + #define AXP2101_SUPPLY_ALDO2 6 61 + #define AXP2101_SUPPLY_ALDO3 7 62 + #define AXP2101_SUPPLY_ALDO4 8 63 + #define AXP2101_SUPPLY_BLDO1 9 64 + #define AXP2101_SUPPLY_BLDO2 10 65 + #define AXP2101_SUPPLY_DLDO1 11 66 + #define AXP2101_SUPPLY_DLDO2 12 67 + #define AXP2101_SUPPLY_VCPUS 13 68 + #define AXP2101_SUPPLY_RTCLDO1 14 69 + #define AXP2101_SUPPLY_RTCLDO2 15 70 + #define AXP2101_NUM_SUPPLIES 16 71 + 72 + /* Special values returned by axp_supply_get_voltage */ 73 + #define AXP2101_SUPPLY_NOT_PRESENT INT_MIN 74 + #define AXP2101_SUPPLY_DISABLED (-1) 75 + 76 + /* AXP2101 registers */ 77 + #define AXP2101_REG_PMU_STATUS1 0x00 78 + #define AXP2101_REG_PMU_STATUS2 0x01 79 + #define AXP2101_REG_DATA_BUFFER0 0x04 80 + #define AXP2101_REG_DATA_BUFFER1 0x05 81 + #define AXP2101_REG_DATA_BUFFER2 0x06 82 + #define AXP2101_REG_DATA_BUFFER3 0x07 83 + #define AXP2101_REG_PMUCOMMCONFIG 0x10 84 + #define AXP2101_REG_BATFET_CTRL 0x12 85 + #define AXP2101_REG_DIETEMPCTRL 0x13 86 + #define AXP2101_REG_MINSYSVOLTCTRL 0x14 87 + #define AXP2101_REG_INVOLTLIMITCTRL 0x15 88 + #define AXP2101_REG_INCURRLIMITCTRL 0x16 89 + #define AXP2101_REG_FUELGAUGERESET 0x17 90 + #define AXP2101_REG_PERIPHERALCTRL 0x18 91 + #define AXP2101_REG_WATCHDOGCTRL 0x19 92 + #define AXP2101_REG_LOWBATTWARN 0x1a 93 + #define AXP2101_REG_PWRONSTATUS 0x20 94 + #define AXP2101_REG_PWROFFSTATUS 0x21 95 + #define AXP2101_REG_PWROFFENABLE 0x22 96 + #define AXP2101_REG_PWROFF_DCDC_OVP_UVP 0x23 97 + #define AXP2101_REG_VSYSPWROFFTHRESH 0x24 98 + #define AXP2101_REG_PWROK_SETTING 0x25 99 + #define AXP2101_REG_SLEEPWAKE 0x26 100 + #define AXP2101_REG_LOGICTHRESH 0x27 101 + #define AXP2101_REG_FASTPWRON0 0x28 102 + #define AXP2101_REG_FASTPWRON1 0x29 103 + #define AXP2101_REG_FASTPWRON2 0x2a 104 + #define AXP2101_REG_FASTPWRON_CTRL 0x2b 105 + #define AXP2101_REG_ADCCHNENABLE 0x30 106 + #define AXP2101_REG_ADC_VBAT_H 0x34 107 + #define AXP2101_REG_ADC_VBAT_L 0x35 108 + #define AXP2101_REG_ADC_TS_H 0x36 109 + #define AXP2101_REG_ADC_TS_L 0x37 110 + #define AXP2101_REG_ADC_VBUS_H 0x38 111 + #define AXP2101_REG_ADC_VBUS_L 0x39 112 + #define AXP2101_REG_ADC_VSYS_H 0x3a 113 + #define AXP2101_REG_ADC_VSYS_L 0x3b 114 + #define AXP2101_REG_ADC_TDIE_H 0x3c 115 + #define AXP2101_REG_ADC_TDIE_L 0x3d 116 + #define AXP2101_REG_IRQEN0 0x40 117 + #define AXP2101_REG_IRQEN1 0x41 118 + #define AXP2101_REG_IRQEN2 0x42 119 + #define AXP2101_REG_IRQSTATUS0 0x48 120 + #define AXP2101_REG_IRQSTATUS1 0x49 121 + #define AXP2101_REG_IRQSTATUS2 0x4a 122 + #define AXP2101_REG_TSPINCTRL 0x50 123 + #define AXP2101_REG_TS_HYSL2H 0x52 124 + #define AXP2101_REG_TS_HYSH2L 0x53 125 + #define AXP2101_REG_VLTF_CHG 0x54 126 + #define AXP2101_REG_VHTF_CHG 0x55 127 + #define AXP2101_REG_VLTF_WORK 0x56 128 + #define AXP2101_REG_VHTF_WORK 0x57 129 + #define AXP2101_REG_JIETA_ENABLE 0x58 130 + #define AXP2101_REG_JIETA_SETTING0 0x59 131 + #define AXP2101_REG_JIETA_SETTING1 0x5a 132 + #define AXP2101_REG_JIETA_SETTING2 0x5b 133 + #define AXP2101_REG_IPRECHG_SETTING 0x61 134 + #define AXP2101_REG_ICC_SETTING 0x62 135 + #define AXP2101_REG_ITERM_SETTING 0x63 136 + #define AXP2101_REG_CV_SETTING 0x64 137 + #define AXP2101_REG_THERMREGTHRESH 0x65 138 + #define AXP2101_REG_CHARGETIMEOUT 0x67 139 + #define AXP2101_REG_BATTDETECTCTRL 0x68 140 + #define AXP2101_REG_CHGLED 0x69 141 + #define AXP2101_REG_BUTTONBAT 0x6a 142 + #define AXP2101_REG_DCDC_ONOFF 0x80 143 + #define AXP2101_REG_DCDC_FORCEPWM 0x81 144 + #define AXP2101_REG_DCDC0_VOLTAGE 0x82 145 + #define AXP2101_REG_DCDC1_VOLTAGE 0x83 146 + #define AXP2101_REG_DCDC2_VOLTAGE 0x84 147 + #define AXP2101_REG_DCDC3_VOLTAGE 0x85 148 + #define AXP2101_REG_DCDC4_VOLTAGE 0x86 149 + #define AXP2101_REG_LDO_ONOFF0 0x90 150 + #define AXP2101_REG_LDO_ONOFF1 0x91 151 + #define AXP2101_REG_LDO0_VOLTAGE 0x92 152 + #define AXP2101_REG_LDO1_VOLTAGE 0x93 153 + #define AXP2101_REG_LDO2_VOLTAGE 0x94 154 + #define AXP2101_REG_LDO3_VOLTAGE 0x94 155 + #define AXP2101_REG_LDO4_VOLTAGE 0x95 156 + #define AXP2101_REG_LDO5_VOLTAGE 0x96 157 + #define AXP2101_REG_LDO6_VOLTAGE 0x97 158 + #define AXP2101_REG_LDO7_VOLTAGE 0x98 159 + #define AXP2101_REG_LDO8_VOLTAGE 0x99 160 + #define AXP2101_REG_LDO9_VOLTAGE 0x9a 161 + #define AXP2101_REG_BATT_PARAMETER 0xa1 162 + #define AXP2101_REG_FUEL_GAUGE_CTRL 0xa2 163 + #define AXP2101_REG_BATT_PERCENTAGE 0xa4 164 + 165 + /* Must be called from power_init() to initialize the driver state */ 166 + extern void axp2101_init(void); 167 + 168 + /* - axp_supply_set_voltage(): set a supply voltage to the given value 169 + * in millivolts. Pass a voltage of AXP_SUPPLY_DISABLED to shut off 170 + * the supply. Any invalid supply or voltage will make the call a no-op. 171 + * 172 + * - axp_supply_get_voltage() returns a supply voltage in millivolts. 173 + * If the supply is powered off, returns AXP_SUPPLY_DISABLED. 174 + * If the chip does not have the supply, returns AXP_SUPPLY_NOT_PRESENT. 175 + */ 176 + extern void axp2101_supply_set_voltage(int supply, int voltage); 177 + extern int axp2101_supply_get_voltage(int supply); 178 + 179 + /* Basic battery and power supply status */ 180 + extern int axp2101_battery_status(void); 181 + extern int axp2101_input_status(void); 182 + 183 + /* ADC access -- ADCs which are not enabled will return INT_MIN if read. 184 + * The output of axp_adc_read() is normalized to appropriate units: 185 + * 186 + * - for voltages, the scale is millivolts 187 + * - for currents, the scale is milliamps 188 + * - for temperatures, the scale is tenths of a degree Celsius 189 + * - for power, the scale is microwatts 190 + * 191 + * See the comment in axp_adc_conv_raw() for raw value precision/scale. 192 + */ 193 + extern int axp2101_adc_read(int adc); 194 + extern int axp2101_adc_read_raw(int adc); 195 + extern int axp2101_adc_conv_raw(int adc, int value); 196 + extern void axp2101_adc_set_enabled(int adc_bits); 197 + extern int axp2101_adc_get_rate(void); 198 + 199 + /* Set/get maximum charging current in milliamps */ 200 + extern void axp2101_set_charge_current(int current_mA); 201 + extern int axp2101_get_charge_current(void); 202 + 203 + /* Set the shutdown bit */ 204 + extern void axp2101_power_off(void); 205 + 206 + /* Debug menu */ 207 + extern bool axp2101_debug_menu(void); 208 + 209 + extern unsigned int axp2101_power_input_status(void); 210 + 211 + #endif /* __AXP_2101_H__ */
+1
firmware/export/config/erosqnative.h
··· 100 100 #define HAVE_SW_POWEROFF 101 101 102 102 #ifndef SIMULATOR 103 + #define HAVE_AXP2101_ADDON 103 104 #define HAVE_AXP_PMU 192 104 105 #define HAVE_POWEROFF_WHILE_CHARGING 105 106 #endif
+88 -36
firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c
··· 31 31 #include "eros_qn_codec.h" 32 32 #include <string.h> 33 33 #include <stdbool.h> 34 + #include "devicedata.h" 34 35 35 36 #ifndef BOOTLOADER 36 37 # include "lcd.h" ··· 75 76 /* Value of headphone detect register */ 76 77 static uint8_t hp_detect_reg = 0x00; 77 78 static uint8_t hp_detect_reg_old = 0x00; 79 + #ifndef BOOTLOADER 78 80 static uint8_t hp_detect_debounce1 = 0x00; 81 + #endif 79 82 static uint8_t hp_detect_debounce2 = 0x00; 80 83 static uint8_t debounce_count = 0; 81 84 82 85 /* Interval to poll the register */ 83 86 #define HPD_POLL_TIME (HZ/4) 84 87 88 + #ifndef BOOTLOADER 85 89 static int hp_detect_tmo_cb(struct timeout* tmo) 86 90 { 87 91 if (hp_detect_debounce1 == hp_detect_debounce2){ ··· 100 104 return HPD_POLL_TIME; 101 105 } 102 106 103 - static void hp_detect_init(void) 107 + static void hp_detect_init(int version) 104 108 { 105 - static struct timeout tmo; 106 - static const uint8_t gpio_reg = AXP192_REG_GPIOSTATE1; 107 - static i2c_descriptor desc = { 108 - .slave_addr = AXP_PMU_ADDR, 109 - .bus_cond = I2C_START | I2C_STOP, 110 - .tran_mode = I2C_READ, 111 - .buffer[0] = (void*)&gpio_reg, 112 - .count[0] = 1, 113 - .buffer[1] = &hp_detect_debounce1, 114 - .count[1] = 1, 115 - .callback = NULL, 116 - .arg = 0, 117 - .next = NULL, 118 - }; 109 + if (version <= 3) { 110 + static struct timeout tmo; 111 + static const uint8_t gpio_reg = AXP192_REG_GPIOSTATE1; 112 + static i2c_descriptor desc = { 113 + .slave_addr = AXP_PMU_ADDR, 114 + .bus_cond = I2C_START | I2C_STOP, 115 + .tran_mode = I2C_READ, 116 + .buffer[0] = (void*)&gpio_reg, 117 + .count[0] = 1, 118 + .buffer[1] = &hp_detect_debounce1, 119 + .count[1] = 1, 120 + .callback = NULL, 121 + .arg = 0, 122 + .next = NULL, 123 + }; 119 124 120 - /* Headphone and LO detects are wired to AXP192 GPIOs 0 and 1, 121 - * set them to inputs. */ 122 - i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO0FUNCTION, 0x01); /* HP detect */ 123 - i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO1FUNCTION, 0x01); /* LO detect */ 125 + /* Headphone and LO detects are wired to AXP192 GPIOs 0 and 1, 126 + * set them to inputs. */ 127 + i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO0FUNCTION, 0x01); /* HP detect */ 128 + i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO1FUNCTION, 0x01); /* LO detect */ 129 + 130 + /* Get an initial reading before startup */ 131 + int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, gpio_reg); 132 + if(r >= 0) 133 + { 134 + hp_detect_reg = r; 135 + hp_detect_debounce1 = r; 136 + hp_detect_debounce2 = r; 137 + hp_detect_reg_old = hp_detect_reg; 138 + } 124 139 125 - /* Get an initial reading before startup */ 126 - int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, gpio_reg); 127 - if(r >= 0) 128 - { 129 - hp_detect_reg = r; 130 - hp_detect_debounce1 = r; 131 - hp_detect_debounce2 = r; 140 + /* Poll the register every second */ 141 + timeout_register(&tmo, &hp_detect_tmo_cb, HPD_POLL_TIME, (intptr_t)&desc); 142 + } else { 143 + uint32_t b = REG_GPIO_PIN(GPIO_B); 144 + 145 + // initialize headphone detect variables 146 + // HP_detect PB14 --> bit 4 147 + // LO_detect PB22 --> bit 5 148 + hp_detect_reg = ( (b>>10)&(0x10) | (b>>17)&(0x20) ); 149 + hp_detect_debounce1 = hp_detect_reg; 150 + hp_detect_debounce2 = hp_detect_reg; 132 151 hp_detect_reg_old = hp_detect_reg; 133 152 } 134 - 135 - /* Poll the register every second */ 136 - timeout_register(&tmo, &hp_detect_tmo_cb, HPD_POLL_TIME, (intptr_t)&desc); 137 153 } 154 + #endif 138 155 139 156 bool headphones_inserted(void) 140 157 { ··· 187 204 gpio_enable_irq(GPIO_BTN_SCROLL_B); 188 205 189 206 /* Set up headphone and line out detect polling */ 190 - hp_detect_init(); 207 + #ifndef BOOTLOADER 208 + hp_detect_init(device_data.lcd_version); 209 + #endif 191 210 } 192 211 193 212 /* wheel Quadrature line A interrupt */ ··· 238 257 if((a & (1 << 16)) == 0) r |= BUTTON_PLAY; 239 258 if((a & (1 << 17)) == 0) r |= BUTTON_VOL_UP; 240 259 if((a & (1 << 19)) == 0) r |= BUTTON_VOL_DOWN; 241 - 242 - if((b & (1 << 7)) == 0) r |= BUTTON_POWER; 243 - if((b & (1 << 28)) == 0) r |= BUTTON_MENU; 260 + #ifdef BOOTLOADER 261 + # if EROSQN_VER >= 4 262 + if((b & (1 << 31)) == 0) r |= BUTTON_POWER; 263 + if((a & (1 << 18)) == 0) r |= BUTTON_BACK; 264 + # else 265 + if((b & (1 << 7)) == 0) r |= BUTTON_POWER; 266 + if((d & (1 << 5)) == 0) r |= BUTTON_BACK; 267 + # endif 268 + #else 269 + if (device_data.lcd_version >= 4){ 270 + if((b & (1 << 31)) == 0) r |= BUTTON_POWER; 271 + if((a & (1 << 18)) == 0) r |= BUTTON_BACK; 272 + } else { 273 + if((b & (1 << 7)) == 0) r |= BUTTON_POWER; 274 + if((d & (1 << 5)) == 0) r |= BUTTON_BACK; 275 + } 276 + #endif 244 277 if((b & (1 << 28)) == 0) r |= BUTTON_MENU; 245 - 278 + 246 279 if((d & (1 << 4)) == 0) r |= BUTTON_PREV; 280 + if((c & (1 << 24)) == 0) r |= BUTTON_NEXT; 281 + 282 + #ifndef BOOTLOADER 283 + if (device_data.lcd_version >= 4){ 284 + // get new HP/LO detect states 285 + // HP_detect PB14 --> hp_detect bit 4 286 + // LO_detect PB22 --> hp_detect bit 5 287 + hp_detect_debounce1 = ( (b>>10)&(0x10) | (b>>17)&(0x20) ); 247 288 248 - if((d & (1 << 5)) == 0) r |= BUTTON_BACK; 249 - if((c & (1 << 24)) == 0) r |= BUTTON_NEXT; 289 + // enter them into the debounce process 290 + if (hp_detect_debounce1 == hp_detect_debounce2){ 291 + if (debounce_count >= 2){ 292 + debounce_count = 2; 293 + } else { 294 + debounce_count = debounce_count + 1; 295 + } 296 + } else { 297 + debounce_count = 0; 298 + hp_detect_debounce2 = hp_detect_debounce1; 299 + } 300 + } 301 + #endif 250 302 251 303 /* check encoder - from testing, each indent is 2 state changes or so */ 252 304 if (enc_position > 1)
+121 -18
firmware/target/mips/ingenic_x1000/erosqnative/gpio-target.h
··· 1 1 /* -------------------- NOTES ------------------- */ 2 2 3 - /* I don't think we have any devices on I2C1, the pins /may/ be reused. */ 4 - /* DEFINE_PINGROUP(I2C1, GPIO_C, 3 << 26, GPIOF_DEVICE(0)) */ 5 - 6 - /* OF has SD Card power listed as 0x2a - PB10, but it seems to work without. */ 7 - 8 - /* I think BT power reg is pin 0x53 - C19 */ 9 - 10 - /* USB_DETECT D3 chosen by trial-and-error. */ 11 - 12 3 /* I have a suspicion this isn't right for AXP_IRQ, 13 4 * and it's not used right now anyway. copied from m3k. */ 14 5 /* DEFINE_GPIO(AXP_IRQ, GPIO_PB(10), GPIOF_INPUT) */ 15 6 16 7 /* ---------------------------------------------- */ 17 8 9 + /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ 10 + /* ======================================================= */ 11 + /* DO NOT CHANGE THE ORDER OF THESE DEFINES */ 12 + /* WITHOUT CONSIDERING GPIO-X1000.C!! */ 13 + /* ======================================================= */ 14 + /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ 18 15 16 + /**************************/ 17 + /* PIN GROUPINGS */ 18 + /************************ */ 19 19 /* Name Port Pins Function */ 20 20 DEFINE_PINGROUP(LCD_DATA, GPIO_A, 0xffff << 0, GPIOF_DEVICE(1)) 21 21 DEFINE_PINGROUP(LCD_CONTROL, GPIO_B, 0x1a << 16, GPIOF_DEVICE(1)) ··· 26 26 DEFINE_PINGROUP(I2C2, GPIO_D, 3 << 0, GPIOF_DEVICE(1)) 27 27 28 28 /* Name Pin Function */ 29 + /*************************/ 30 + /* AUDIO STUFF */ 31 + /*************************/ 29 32 /* mute DAC: 0 - mute, 1 - play */ 30 33 /* Note: This seems to actually be power to the DAC in general, 31 34 * at least on the ES9018K2M devices. Was "DAC_XMIT". */ 32 35 DEFINE_GPIO(DAC_PWR, GPIO_PB(12), GPIOF_OUTPUT(0)) 33 36 37 + /* Headphone Amp power */ 38 + DEFINE_GPIO(HPAMP_POWER, GPIO_PB(6), GPIOF_OUTPUT(0)) 39 + 40 + /* DAC AVDD */ 41 + DEFINE_GPIO(DAC_ANALOG_PWR, GPIO_PB(9), GPIOF_OUTPUT(0)) 42 + 43 + /* SPDIF power? */ 44 + // gpio 53 --> port B, pin 21 45 + DEFINE_GPIO(SPDIF_PWR, GPIO_PB(21), GPIOF_OUTPUT(0)) 46 + 34 47 /* mute HP amp: 0 - mute, 1 - play */ 35 48 DEFINE_GPIO(HPAMP_SHDN, GPIO_PB(8), GPIOF_OUTPUT(0)) 36 49 ··· 43 56 */ 44 57 DEFINE_GPIO(STEREOSW_SEL, GPIO_PB(5), GPIOF_OUTPUT(0)) 45 58 46 - /* DAC AVDD */ 47 - DEFINE_GPIO(DAC_ANALOG_PWR, GPIO_PB(9), GPIOF_OUTPUT(0)) 48 - 49 - /* Headphone Amp power */ 50 - DEFINE_GPIO(HPAMP_POWER, GPIO_PB(6), GPIOF_OUTPUT(0)) 51 - 59 + /**************/ 60 + /* SD and USB */ 61 + /**************/ 52 62 /* SD card */ 63 + DEFINE_GPIO(MMC_PWR, GPIO_PB(10), GPIOF_OUTPUT(1)) 53 64 DEFINE_GPIO(MSC0_CD, GPIO_PB(11), GPIOF_INPUT) 54 65 55 66 /* USB */ 67 + /* USB_DETECT D3 chosen by trial-and-error. */ 56 68 DEFINE_GPIO(USB_DETECT, GPIO_PD(3), GPIOF_INPUT) 57 69 DEFINE_GPIO(USB_DRVVBUS, GPIO_PB(25), GPIOF_OUTPUT(0)) 58 70 71 + /* TCS1421_CFG (USB) CFG1 */ 72 + // set TCS1421_CFG0:1 to 00, Upstream Facing Port (tried others, they don't work) 73 + // GPIO 62 --> PORT B, PIN 30 74 + DEFINE_GPIO(TCS1421_CFG1, GPIO_PB(30), GPIOF_OUTPUT(0)) 75 + 76 + /* BL POWER */ 77 + // gpio 89 --> port c, pin 25 78 + // oh, this is probably backlight power, isn't it? 79 + DEFINE_GPIO(BL_PWR, GPIO_PC(25), GPIOF_OUTPUT(0)) 80 + 81 + /************/ 82 + /* LCD */ 83 + /************/ 59 84 /* LCD */ 60 - DEFINE_GPIO(LCD_PWR, GPIO_PB(14), GPIOF_OUTPUT(0)) 61 85 DEFINE_GPIO(LCD_RESET, GPIO_PB(13), GPIOF_OUTPUT(0)) 62 86 DEFINE_GPIO(LCD_CE, GPIO_PB(18), GPIOF_OUTPUT(1)) 63 87 DEFINE_GPIO(LCD_RD, GPIO_PB(16), GPIOF_OUTPUT(1)) 64 88 89 + /************/ 90 + /* BUTTONS */ 91 + /************/ 65 92 /* Buttons */ 66 93 DEFINE_GPIO(BTN_PLAY, GPIO_PA(16), GPIOF_INPUT) 67 94 DEFINE_GPIO(BTN_VOL_UP, GPIO_PA(17), GPIOF_INPUT) 68 95 DEFINE_GPIO(BTN_VOL_DOWN, GPIO_PA(19), GPIOF_INPUT) 69 - DEFINE_GPIO(BTN_POWER, GPIO_PB(7), GPIOF_INPUT) 70 96 DEFINE_GPIO(BTN_MENU, GPIO_PB(28), GPIOF_INPUT) 71 - DEFINE_GPIO(BTN_BACK, GPIO_PD(5), GPIOF_INPUT) 72 97 DEFINE_GPIO(BTN_PREV, GPIO_PD(4), GPIOF_INPUT) 73 98 DEFINE_GPIO(BTN_NEXT, GPIO_PC(24), GPIOF_INPUT) 74 99 DEFINE_GPIO(BTN_SCROLL_A, GPIO_PB(24), GPIOF_INPUT) 75 100 DEFINE_GPIO(BTN_SCROLL_B, GPIO_PB(23), GPIOF_INPUT) 101 + 102 + /**********************/ 103 + /* BLUETOOTH STUFF */ 104 + /**********************/ 105 + /* BT Power */ 106 + // GPIO 86 --> Port C, Pin 22 107 + DEFINE_GPIO(BT_PWR, GPIO_PC(22), GPIOF_OUTPUT(0)) 108 + 109 + 110 + 111 + 112 + /****************************** */ 113 + /* HW1/2/3-ONLY STUFF */ 114 + /****************************** */ 115 + DEFINE_GPIO(HW1_START, GPIO_PC(0), GPIOF_OUTPUT(0)) 116 + /************/ 117 + /* BUTTONS */ 118 + /************/ 119 + DEFINE_GPIO(BTN_BACK_HW1, GPIO_PD(5), GPIOF_INPUT) 120 + DEFINE_GPIO(BTN_POWER_HW1, GPIO_PB(7), GPIOF_INPUT) 121 + 122 + /**********************/ 123 + /* BLUETOOTH STUFF */ 124 + /**********************/ 125 + // GPIO 83 --> port C, pin 19 126 + DEFINE_GPIO(BT_REG_ON_HW1, GPIO_PC(19), GPIOF_OUTPUT(0)) 127 + 128 + /************/ 129 + /* LCD */ 130 + /************/ 131 + /* LCD */ 132 + DEFINE_GPIO(LCD_PWR_HW1, GPIO_PB(14), GPIOF_OUTPUT(0)) 133 + DEFINE_GPIO(HW1_END, GPIO_PC(0), GPIOF_OUTPUT(0)) 134 + 135 + 136 + 137 + 138 + /****************************** */ 139 + /* HW4-ONLY STUFF */ 140 + /****************************** */ 141 + DEFINE_GPIO(HW4_START, GPIO_PC(0), GPIOF_OUTPUT(0)) 142 + DEFINE_GPIO(BLUELIGHT_HW4, GPIO_PB(7), GPIOF_OUTPUT(1)) 143 + /************/ 144 + /* BUTTONS */ 145 + /************/ 146 + DEFINE_GPIO(BTN_BACK_HW4, GPIO_PA(18), GPIOF_INPUT) 147 + DEFINE_GPIO(BTN_POWER_HW4, GPIO_PB(31), GPIOF_INPUT) 148 + 149 + /**********************/ 150 + /* BLUETOOTH STUFF */ 151 + /**********************/ 152 + /* bt_wake_host */ 153 + // gpio 84 --> port C, pin 20 154 + DEFINE_GPIO(BT_WAKE_HOST, GPIO_PC(20), GPIOF_INPUT) 155 + 156 + /* host_wake_bt */ 157 + // gpio 83 --> port C, pin 19 158 + DEFINE_GPIO(HOST_WAKE_BT, GPIO_PC(19), GPIOF_OUTPUT(0)) 159 + 160 + /**************/ 161 + /* USB */ 162 + /**************/ 163 + /* USB_TCS1421_CFG0 */ 164 + // set TCS1421_CFG0:1 to 00, Upstream Facing Port (tried others, they don't work) 165 + // gpio 101 --> port D, pin 5 166 + DEFINE_GPIO(TCS1421_CFG0, GPIO_PD(5), GPIOF_OUTPUT(0)) 167 + 168 + /***************/ 169 + /* PLUG DETECT */ 170 + /***************/ 171 + /* HP_DETECT */ 172 + // gpio 46 --> port B, pin 14 173 + DEFINE_GPIO(HP_DETECT_HW4, GPIO_PB(14), GPIOF_INPUT) 174 + 175 + /* LO_DETECT */ 176 + // gpio 54 --> Port B, pin 22 177 + DEFINE_GPIO(LO_DETECT_HW4, GPIO_PB(22), GPIOF_INPUT) 178 + DEFINE_GPIO(HW4_END, GPIO_PC(0), GPIOF_OUTPUT(0))
+12 -3
firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c
··· 292 292 { 293 293 if(enable) { 294 294 /* power up the panel */ 295 - gpio_set_level(GPIO_LCD_PWR, 1); 295 + #ifdef BOOTLOADER 296 + # if EROSQN_VER <= 3 297 + gpio_set_level(GPIO_LCD_PWR_HW1, 1); 298 + # endif 299 + #else 300 + if (device_data.lcd_version <= 3) 301 + { 302 + gpio_set_level(GPIO_LCD_PWR_HW1, 1); 303 + } 304 + #endif 296 305 mdelay(20); 297 306 gpio_set_level(GPIO_LCD_RESET, 1); 298 307 mdelay(12); ··· 307 316 gpio_set_level(GPIO_LCD_CE, 0); 308 317 309 318 #ifdef BOOTLOADER 310 - # if EROSQN_VER == 3 319 + # if EROSQN_VER >= 3 311 320 lcd_exec_commands(&erosqnative_lcd_cmd_enable_v3[0]); 312 321 # else 313 322 lcd_exec_commands(&erosqnative_lcd_cmd_enable_v1[0]); 314 323 # endif 315 324 #else 316 - if (device_data.lcd_version == 3) 325 + if (device_data.lcd_version >= 3) 317 326 { 318 327 lcd_exec_commands(&erosqnative_lcd_cmd_enable_v3[0]); 319 328 }
+143 -28
firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c
··· 29 29 # include "usb_core.h" 30 30 #endif 31 31 #include "axp-pmu.h" 32 + #include "axp-2101.h" 32 33 #include "i2c-x1000.h" 34 + #include "devicedata.h" 33 35 34 36 const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = 35 37 { ··· 58 60 { 59 61 /* Initialize driver */ 60 62 i2c_x1000_set_freq(2, I2C_FREQ_400K); 61 - axp_init(); 62 63 63 - /* Set lowest sample rate */ 64 - axp_adc_set_rate(AXP_ADC_RATE_25HZ); 64 + int devicever; 65 + #if defined(BOOTLOADER) 66 + devicever = EROSQN_VER; 67 + #else 68 + devicever = device_data.lcd_version; 69 + #endif 70 + if (devicever >= 4){ 71 + uint8_t regread; 72 + axp2101_init(); 73 + /* Enable required ADCs */ 74 + axp2101_adc_set_enabled( 75 + (1 << AXP2101_ADC_VBAT_VOLTAGE) | 76 + (1 << AXP2101_ADC_VBUS_VOLTAGE) | 77 + (1 << AXP2101_ADC_VSYS_VOLTAGE) | 78 + (1 << AXP2101_ADC_VBUS_VOLTAGE) | 79 + (1 << AXP2101_ADC_TS_VOLTAGE) | 80 + (1 << AXP2101_ADC_DIE_TEMPERATURE)); 65 81 66 - /* Enable required ADCs */ 67 - axp_adc_set_enabled( 68 - (1 << ADC_BATTERY_VOLTAGE) | 69 - (1 << ADC_CHARGE_CURRENT) | 70 - (1 << ADC_DISCHARGE_CURRENT) | 71 - (1 << ADC_VBUS_VOLTAGE) | 72 - (1 << ADC_VBUS_CURRENT) | 73 - (1 << ADC_INTERNAL_TEMP) | 74 - (1 << ADC_APS_VOLTAGE)); 82 + i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 83 + AXP2101_REG_DCDC_ONOFF, 0, 0x1f, NULL); 84 + i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 85 + AXP2101_REG_LDO_ONOFF0, 0, 0xff, NULL); 86 + i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 87 + AXP2101_REG_LDO_ONOFF1, 0, 0x01, NULL); 75 88 76 - /* Turn on all power outputs */ 77 - i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 78 - AXP_REG_PWROUTPUTCTRL2, 0, 0x5f, NULL); 79 - i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 80 - AXP_REG_DCDCWORKINGMODE, 0, 0xc0, NULL); 89 + // set power button delay to 1s to match earlier devices 90 + regread = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, 91 + AXP2101_REG_LOGICTHRESH); 92 + if ((regread&0x03) != 0x02){ 93 + i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 94 + AXP2101_REG_LOGICTHRESH, 0x03, 0, NULL); 95 + i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 96 + AXP2101_REG_LOGICTHRESH, 0, 0x02, NULL); 97 + } 98 + 99 + // These match the OF as far as I can discern 100 + // TODO: These values are set in EFUSE apparently, could 101 + // do a "check then set if necessary"... 102 + // Also if we had a fresh device we could verify what 103 + // the OF sets. 104 + axp2101_supply_set_voltage(AXP2101_SUPPLY_DCDC1, 3300); 105 + axp2101_supply_set_voltage(AXP2101_SUPPLY_DCDC2, 1200); 106 + axp2101_supply_set_voltage(AXP2101_SUPPLY_DCDC3, 2800); 107 + axp2101_supply_set_voltage(AXP2101_SUPPLY_DCDC4, 1800); 108 + axp2101_supply_set_voltage(AXP2101_SUPPLY_DCDC5, 1400); 109 + 110 + axp2101_supply_set_voltage(AXP2101_SUPPLY_ALDO1, 2500); 111 + axp2101_supply_set_voltage(AXP2101_SUPPLY_ALDO2, 3300); 112 + axp2101_supply_set_voltage(AXP2101_SUPPLY_ALDO3, 3300); 113 + axp2101_supply_set_voltage(AXP2101_SUPPLY_ALDO4, 3300); 114 + 115 + axp2101_supply_set_voltage(AXP2101_SUPPLY_BLDO1, 3300); 116 + axp2101_supply_set_voltage(AXP2101_SUPPLY_BLDO2, 3300); 117 + 118 + axp2101_supply_set_voltage(AXP2101_SUPPLY_DLDO1, 2500); 119 + axp2101_supply_set_voltage(AXP2101_SUPPLY_DLDO2, 1250); 120 + 121 + axp2101_supply_set_voltage(AXP2101_SUPPLY_VCPUS, 500); 122 + 123 + /* Set the default charging current. This is the same as the 124 + * OF's setting, although it's not strictly within the USB spec. */ 125 + axp2101_set_charge_current(780); 126 + } else { 127 + axp_init(); 128 + /* Set lowest sample rate */ 129 + axp_adc_set_rate(AXP_ADC_RATE_25HZ); 130 + 131 + /* Enable required ADCs */ 132 + axp_adc_set_enabled( 133 + (1 << ADC_BATTERY_VOLTAGE) | 134 + (1 << ADC_CHARGE_CURRENT) | 135 + (1 << ADC_DISCHARGE_CURRENT) | 136 + (1 << ADC_VBUS_VOLTAGE) | 137 + (1 << ADC_VBUS_CURRENT) | 138 + (1 << ADC_INTERNAL_TEMP) | 139 + (1 << ADC_APS_VOLTAGE)); 140 + 141 + /* TODO: Set Output Voltages! */ 142 + i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 143 + AXP_REG_PWROUTPUTCTRL2, 0, 0x5f, NULL); 144 + i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR, 145 + AXP_REG_DCDCWORKINGMODE, 0, 0xc0, NULL); 81 146 82 - /* Set the default charging current. This is the same as the 83 - * OF's setting, although it's not strictly within the USB spec. */ 84 - axp_set_charge_current(780); 147 + /* Set the default charging current. This is the same as the 148 + * OF's setting, although it's not strictly within the USB spec. */ 149 + axp_set_charge_current(780); 150 + } 85 151 86 152 #ifdef BOOTLOADER 87 153 /* Delay to give power outputs time to stabilize. ··· 95 161 #ifdef HAVE_USB_CHARGING_ENABLE 96 162 void usb_charging_maxcurrent_change(int maxcurrent) 97 163 { 98 - axp_set_charge_current(maxcurrent); 164 + int devicever; 165 + #if defined(BOOTLOADER) 166 + devicever = EROSQN_VER; 167 + #else 168 + devicever = device_data.lcd_version; 169 + #endif 170 + if (devicever >= 4){ 171 + axp2101_set_charge_current(maxcurrent); 172 + } else { 173 + axp_set_charge_current(maxcurrent); 174 + } 175 + 99 176 } 100 177 #endif 101 178 ··· 105 182 106 183 void power_off(void) 107 184 { 108 - axp_power_off(); 185 + int devicever; 186 + #if defined(BOOTLOADER) 187 + devicever = EROSQN_VER; 188 + #else 189 + devicever = device_data.lcd_version; 190 + #endif 191 + if (devicever >= 4){ 192 + axp2101_power_off(); 193 + } else { 194 + axp_power_off(); 195 + } 109 196 while(1); 110 197 } 111 198 112 199 bool charging_state(void) 113 200 { 114 - return axp_battery_status() == AXP_BATT_CHARGING; 201 + int devicever; 202 + #if defined(BOOTLOADER) 203 + devicever = EROSQN_VER; 204 + #else 205 + devicever = device_data.lcd_version; 206 + #endif 207 + if (devicever >= 4){ 208 + return axp2101_battery_status() == AXP2101_BATT_CHARGING; 209 + } else { 210 + return axp_battery_status() == AXP_BATT_CHARGING; 211 + } 115 212 } 116 213 117 214 int _battery_voltage(void) 118 215 { 119 - return axp_adc_read(ADC_BATTERY_VOLTAGE); 216 + int devicever; 217 + #if defined(BOOTLOADER) 218 + devicever = EROSQN_VER; 219 + #else 220 + devicever = device_data.lcd_version; 221 + #endif 222 + if (devicever >= 4){ 223 + return axp2101_adc_read(AXP2101_ADC_VBAT_VOLTAGE); 224 + } else { 225 + return axp_adc_read(ADC_BATTERY_VOLTAGE); 226 + } 120 227 } 121 228 122 229 #if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE 123 230 int _battery_current(void) 124 231 { 125 - if(charging_state()) 126 - return axp_adc_read(ADC_CHARGE_CURRENT); 127 - else 128 - return axp_adc_read(ADC_DISCHARGE_CURRENT); 232 + int devicever; 233 + #if defined(BOOTLOADER) 234 + devicever = EROSQN_VER; 235 + #else 236 + devicever = device_data.lcd_version; 237 + #endif 238 + if (devicever <= 3){ 239 + if(charging_state()) 240 + return axp_adc_read(ADC_CHARGE_CURRENT); 241 + else 242 + return axp_adc_read(ADC_DISCHARGE_CURRENT); 243 + } 129 244 } 130 245 #endif
+32
firmware/target/mips/ingenic_x1000/gpio-x1000.c
··· 20 20 ****************************************************************************/ 21 21 22 22 #include "gpio-x1000.h" 23 + #if defined(EROS_QN) 24 + # include "devicedata.h" 25 + #endif 23 26 24 27 static const struct gpio_setting gpio_settings[PIN_COUNT] INITDATA_ATTR = { 25 28 #define DEFINE_GPIO(_name, _gpio, _func) \ ··· 59 62 60 63 void gpio_init(void) 61 64 { 65 + #if defined(EROS_QN) 66 + int devicever; 67 + # if defined(BOOTLOADER) 68 + devicever = EROSQN_VER; 69 + # else 70 + devicever = device_data.lcd_version; 71 + # endif 72 + #endif 62 73 /* Apply all initial GPIO settings */ 63 74 for(int i = 0; i < PINGROUP_COUNT; ++i) { 64 75 const struct pingroup_setting* d = &pingroup_settings[i]; ··· 68 79 69 80 for(int i = 0; i < PIN_COUNT; ++i) { 70 81 const struct gpio_setting* d = &gpio_settings[i]; 82 + 83 + #ifdef EROS_QN 84 + // eros_qn only 85 + // There surely has to be a nicer way to do this... 86 + // Note: PIN_ indicates position in the list, 87 + // GPIO_ indicates actual port/pin number 88 + // (so if you want to go based on order of the list, use the PIN_ designator!) 89 + if((d->gpio != GPIO_NONE) &&\ 90 + ((i < PIN_HW1_START) ||\ 91 + (devicever <= 3 &&\ 92 + (i > PIN_HW1_START && i < PIN_HW1_END))\ 93 + ||\ 94 + (devicever >= 4 &&\ 95 + (i > PIN_HW4_START && i < PIN_HW4_END)))) 96 + 97 + // if((d->gpio != GPIO_NONE) && (d->gpio != GPIO_BTN_POWER_HW1)) 98 + #else 99 + // non-eros_qn devices 71 100 if(d->gpio != GPIO_NONE) 101 + #endif 102 + { 72 103 gpioz_configure(GPION_PORT(d->gpio), GPION_MASK(d->gpio), d->func); 104 + } 73 105 } 74 106 75 107 /* Any GPIO pins left in an IRQ trigger state need to be switched off,
+6 -1
manual/getting_started/hibyos_nativeinstall.tex
··· 40 40 \item Hifiwalker H2 V1.7 - V1.8 41 41 \item Surfans F20 V3.0 - V3.3 42 42 \end{itemize} 43 - 44 43 These players use \fname{erosqnative-hw3-erosq.upt} as the update file. 44 + \item[hw4 players] 45 + \begin{itemize} 46 + \item Hifiwalker H2 V1.9 47 + \item Surfans F20 V3.4 48 + \end{itemize} 49 + These players use \fname{erosqnative-hw4-erosq_2024.upt} as the update file. 45 50 \end{description} 46 51 47 52 Download the \fname{.upt} file for these players from \download{bootloader/aigo/native/}.
+15
manual/rockbox_interface/main.tex
··· 38 38 39 39 Throughout this manual, the buttons on the \dap{} are labelled according to the 40 40 picture above. 41 + 42 + \opt{erosqnative}{ 43 + \note{The \dap{} has two outputs: Headphone output on the left and Line output on the right. 44 + Due to the circuitry which does detection, it is recommended to only use headphones plugged 45 + into the Headphone output and devices which take Line input into the Line output. If devices 46 + which take a Line input are plugged into the Headphone output, it is likely that the \dap{} 47 + will not detect the plug and no sound will result. 48 + 49 + In the other direction, headphones plugged into the Line output may damage the headphones (and 50 + your ears!) due to the extremely loud volume. 51 + 52 + Note that the volume of the Line output is set by the \setting{Volume Limit} if it needs to 53 + be reduced.} 54 + } 55 + 41 56 \opt{touchscreen}{ 42 57 The areas of the touchscreen in the 3$\times$3 grid mode are in turn referred as follows: 43 58 \begin{table}
+32 -3
tools/configure
··· 1678 1678 ==FiiO== ==xDuoo== ==AIGO== 1679 1679 244) M3K Linux 241) X3 245) Eros Q / K 1680 1680 246) M3K baremetal 242) X3II 247) Eros Q / K native 1681 - 243) X20 248) Eros Q / K native v3 1682 - ==Shanling== (GC9A01 LCD Controller) 1683 - 260) Q1 1681 + 243) X20 (hw1/hw2 bl, all hw rb) 1682 + ==Shanling== 248) Eros Q / K native 1683 + 260) Q1 (hw3 bl only) 1684 + 249) Eros Q / K native 1685 + (hw4 bl only) 1684 1686 EOF 1685 1687 1686 1688 buildfor=`input`; ··· 4134 4136 # player version, for bootloader usage 4135 4137 # version 3 4136 4138 extradefines="$extradefines -DEROSQN_VER=3" 4139 + ;; 4140 + 4141 + 249|erosqnative_v4) 4142 + target_id=118 4143 + modelname="erosqnative_v4" 4144 + target="EROS_QN" 4145 + memory=32 4146 + mipsr2elcc 4147 + appextra="recorder:gui" 4148 + plugins="yes" 4149 + tool="$rootdir/tools/scramble -add=erosqnative " 4150 + boottool="$rootdir/tools/mkspl-x1000 -type=nand -ppb=2 -bpp=2 " 4151 + output="rockbox.erosq" 4152 + bootoutput="bootloader.erosq" 4153 + sysfontbl="16-Terminus" 4154 + # toolset is the tools within the tools directory that we build for 4155 + # this particular target. 4156 + toolset="$x1000tools" 4157 + bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" 4158 + bmp2rb_native="$rootdir/tools/bmp2rb -f 4" 4159 + # architecture, manufacturer and model for the target-tree build 4160 + t_cpu="mips" 4161 + t_manufacturer="ingenic_x1000" 4162 + t_model="erosqnative" 4163 + # player version, for bootloader usage 4164 + # version 4 4165 + extradefines="$extradefines -DEROSQN_VER=4" 4137 4166 ;; 4138 4167 4139 4168 250|ihifi770c)
+35 -7
utils/rbutilqt/rbutil.ini
··· 80 80 platform137=aigoerosq.hifiwalkerh2.v13 81 81 platform138=aigoerosq.surfansf20 82 82 ; default erosqnative should be most recent hardware revision 83 - platform139=erosqnative.hw3 84 - platform140=erosqnative.hw3.hifiwalkerh2 85 - platform141=erosqnative.hw3.surfansf20 86 - platform142=erosqnative.hw1hw2 87 - platform143=erosqnative.hw1hw2.hifiwalkerh2 88 - platform144=erosqnative.hw1hw2.hifiwalkerh2.v13 89 - platform145=erosqnative.hw1hw2.surfansf20 83 + platform139=erosqnative.hw4.hifiwalkerh2 84 + platform140=erosqnative.hw4.surfansf20 85 + platform141=erosqnative.hw3 86 + platform142=erosqnative.hw3.hifiwalkerh2 87 + platform143=erosqnative.hw3.surfansf20 88 + platform144=erosqnative.hw1hw2 89 + platform145=erosqnative.hw1hw2.hifiwalkerh2 90 + platform146=erosqnative.hw1hw2.hifiwalkerh2.v13 91 + platform147=erosqnative.hw1hw2.surfansf20 90 92 91 93 ; devices sections 92 94 ; ··· 873 875 playerpic=aigoerosq 874 876 encoder=rbspeex 875 877 status=disabled 878 + 879 + [erosqnative.hw4.hifiwalkerh2] 880 + name="HIFI WALKER H2 V1.9" 881 + bootloadermethod=file 882 + bootloadername=/aigo/native/erosqnative-hw4-erosq_2024.upt 883 + bootloaderfile=/update.upt 884 + manualname=erosqnative 885 + themename=aigoerosq 886 + brand=HIFI WALKER 887 + usbid=0xc5020023 ; shared across EROS Q / K series 888 + usberror= 889 + playerpic=aigoerosq 890 + encoder=rbspeex 891 + 892 + [erosqnative.hw4.surfansf20] 893 + name="Surfans F20 V3.4" 894 + bootloadermethod=file 895 + bootloadername=/aigo/native/erosqnative-hw4-erosq_2024.upt 896 + bootloaderfile=/update.upt 897 + manualname=erosqnative 898 + themename=aigoerosq 899 + brand=Surfans 900 + usbid=0xc5020023 ; shared across EROS Q / K series 901 + usberror= 902 + playerpic=aigoerosq 903 + encoder=rbspeex 876 904 877 905 [erosqnative.hw3] 878 906 name="AIGO Eros Q V2.1"