From cbae2899df9975c7e6762fa12a48f8730bde7df2 Mon Sep 17 00:00:00 2001 From: robbederks Date: Wed, 14 Jul 2021 15:53:39 +0200 Subject: [PATCH] Tici: amplifier config (#21596) * amplifier config on boot * add to release * another spot * add debug when running separately * rename for clarity --- release/files_common | 1 + release/files_tici | 1 + selfdrive/hardware/base.py | 6 +- selfdrive/hardware/eon/hardware.py | 5 +- selfdrive/hardware/pc/hardware.py | 5 +- selfdrive/hardware/tici/amplifier.py | 100 +++++++++++++++++++++++++++ selfdrive/hardware/tici/hardware.py | 25 +++---- selfdrive/thermald/thermald.py | 1 + 8 files changed, 127 insertions(+), 17 deletions(-) create mode 100755 selfdrive/hardware/tici/amplifier.py diff --git a/release/files_common b/release/files_common index de0140ae5c..07b138de55 100644 --- a/release/files_common +++ b/release/files_common @@ -277,6 +277,7 @@ selfdrive/hardware/eon/hardware.h selfdrive/hardware/eon/hardware.py selfdrive/hardware/tici/__init__.py selfdrive/hardware/tici/hardware.py +selfdrive/hardware/tici/amplifier.py selfdrive/hardware/pc/__init__.py selfdrive/hardware/pc/hardware.py diff --git a/release/files_tici b/release/files_tici index d26b09e7f3..14fdf252e7 100644 --- a/release/files_tici +++ b/release/files_tici @@ -13,5 +13,6 @@ selfdrive/hardware/tici/hardware.py selfdrive/hardware/tici/pins.py selfdrive/hardware/tici/agnos.py selfdrive/hardware/tici/agnos.json +selfdrive/hardware/tici/amplifier.py selfdrive/timezoned.py diff --git a/selfdrive/hardware/base.py b/selfdrive/hardware/base.py index 6652ac57d5..64b7991dd8 100644 --- a/selfdrive/hardware/base.py +++ b/selfdrive/hardware/base.py @@ -111,7 +111,7 @@ class HardwareBase: pass @abstractmethod - def set_power_save(self, enabled): + def set_power_save(self, powersave_enabled): pass @abstractmethod @@ -121,3 +121,7 @@ class HardwareBase: @abstractmethod def get_modem_version(self): pass + + @abstractmethod + def initialize_hardware(self): + pass diff --git a/selfdrive/hardware/eon/hardware.py b/selfdrive/hardware/eon/hardware.py index 76de35a724..ccb1d22260 100644 --- a/selfdrive/hardware/eon/hardware.py +++ b/selfdrive/hardware/eon/hardware.py @@ -375,7 +375,7 @@ class Android(HardwareBase): with open("/sys/class/leds/lcd-backlight/brightness", "w") as f: f.write(str(int(percentage * 2.55))) - def set_power_save(self, enabled): + def set_power_save(self, powersave_enabled): pass def get_gpu_usage_percent(self): @@ -388,3 +388,6 @@ class Android(HardwareBase): def get_modem_version(self): return None + + def initialize_hardware(self): + pass diff --git a/selfdrive/hardware/pc/hardware.py b/selfdrive/hardware/pc/hardware.py index 0d3e4f168f..3a2c7dcaa5 100644 --- a/selfdrive/hardware/pc/hardware.py +++ b/selfdrive/hardware/pc/hardware.py @@ -83,7 +83,7 @@ class Pc(HardwareBase): def set_screen_brightness(self, percentage): pass - def set_power_save(self, enabled): + def set_power_save(self, powersave_enabled): pass def get_gpu_usage_percent(self): @@ -91,3 +91,6 @@ class Pc(HardwareBase): def get_modem_version(self): return None + + def initialize_hardware(self): + pass diff --git a/selfdrive/hardware/tici/amplifier.py b/selfdrive/hardware/tici/amplifier.py new file mode 100755 index 0000000000..b0c201c078 --- /dev/null +++ b/selfdrive/hardware/tici/amplifier.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +from smbus2 import SMBus +from collections import namedtuple + +# https://datasheets.maximintegrated.com/en/ds/MAX98089.pdf + +AmpConfig = namedtuple('AmpConfig', ['name', 'value', 'register', 'offset', 'mask']) +EQParams = namedtuple('EQParams', ['K', 'k1', 'k2', 'c1', 'c2']) + +def configs_from_eq_params(base, eq_params): + return [ + AmpConfig("K (high)", (eq_params.K >> 8), base, 0, 0xFF), + AmpConfig("K (low)", (eq_params.K & 0xFF), base + 1, 0, 0xFF), + AmpConfig("k1 (high)", (eq_params.k1 >> 8), base + 2, 0, 0xFF), + AmpConfig("k1 (low)", (eq_params.k1 & 0xFF), base + 3, 0, 0xFF), + AmpConfig("k2 (high)", (eq_params.k2 >> 8), base + 4, 0, 0xFF), + AmpConfig("k2 (low)", (eq_params.k2 & 0xFF), base + 5, 0, 0xFF), + AmpConfig("c1 (high)", (eq_params.c1 >> 8), base + 6, 0, 0xFF), + AmpConfig("c1 (low)", (eq_params.c1 & 0xFF), base + 7, 0, 0xFF), + AmpConfig("c2 (high)", (eq_params.c2 >> 8), base + 8, 0, 0xFF), + AmpConfig("c2 (low)", (eq_params.c2 & 0xFF), base + 9, 0, 0xFF), + ] + +BASE_CONFIG = [ + AmpConfig("MCLK prescaler", 0b01, 0x10, 4, 0b00110000), + AmpConfig("PM: enable speakers", 0b11, 0x4D, 4, 0b00110000), + AmpConfig("PM: enable DACs", 0b11, 0x4D, 0, 0b00000011), + AmpConfig("Right speaker output from right DAC", 0b1, 0x2C, 0, 0b11111111), + AmpConfig("Right Speaker Mixer Gain", 0b00, 0x2D, 2, 0b00001100), + AmpConfig("Enable PLL1", 0b1, 0x12, 7, 0b10000000), + AmpConfig("Enable PLL2", 0b1, 0x1A, 7, 0b10000000), + AmpConfig("DAI1: I2S mode", 0b00100, 0x14, 2, 0b01111100), + AmpConfig("DAI2: I2S mode", 0b00100, 0x1C, 2, 0b01111100), + AmpConfig("Right speaker output volume", 0x1F, 0x3E, 0, 0b00011111), + AmpConfig("DAI1 Passband filtering: music mode", 0b1, 0x18, 7, 0b10000000), + AmpConfig("DAI1 voice mode gain (DV1G)", 0b00, 0x2F, 4, 0b00110000), + AmpConfig("DAI1 attenuation (DV1)", 0x0, 0x2F, 0, 0b00001111), + AmpConfig("DAI2 attenuation (DV2)", 0x0, 0x31, 0, 0b00001111), + AmpConfig("DAI2: DC blocking", 0b1, 0x20, 0, 0b00000001), + AmpConfig("DAI2: High sample rate", 0b0, 0x20, 3, 0b00001000), + AmpConfig("ALC enable", 0b0, 0x43, 7, 0b10000000), + AmpConfig("ALC/excursion limiter release time", 0b101, 0x43, 4, 0b01110000), + AmpConfig("DAI1 EQ enable", 0b0, 0x49, 0, 0b00000001), + AmpConfig("DAI2 EQ enable", 0b1, 0x49, 1, 0b00000010), + AmpConfig("DAI2 EQ clip detection disabled", 0b0, 0x32, 4, 0b00010000), + AmpConfig("DAI2 EQ attenuation", 0x5, 0x32, 0, 0b00001111), + AmpConfig("Excursion limiter upper corner freq", 0b100, 0x41, 4, 0b01110000), + AmpConfig("Excursion limiter lower corner freq", 0b00, 0x41, 0, 0b00000011), + AmpConfig("Excursion limiter threshold", 0b000, 0x42, 0, 0b00001111), + AmpConfig("Distortion limit (THDCLP)", 0x6, 0x46, 4, 0b11110000), + AmpConfig("Distortion limiter release time constant", 0b0, 0x46, 0, 0b00000001), + AmpConfig("Right DAC input mixer: DAI1 left", 0b0, 0x22, 3, 0b00001000), + AmpConfig("Right DAC input mixer: DAI1 right", 0b0, 0x22, 2, 0b00000100), + AmpConfig("Right DAC input mixer: DAI2 left", 0b1, 0x22, 1, 0b00000010), + AmpConfig("Right DAC input mixer: DAI2 right", 0b0, 0x22, 0, 0b00000001), + AmpConfig("DAI1 audio port selector", 0b10, 0x16, 6, 0b11000000), + AmpConfig("DAI2 audio port selector", 0b01, 0x1E, 6, 0b11000000), + AmpConfig("Enable left digital microphone", 0b1, 0x48, 5, 0b00100000), + AmpConfig("Enable right digital microphone", 0b1, 0x48, 4, 0b00010000), +] + +BASE_CONFIG += configs_from_eq_params(0x84, EQParams(0x65C4, 0xC07C, 0x3D66, 0x07D9, 0x120F)) +BASE_CONFIG += configs_from_eq_params(0x8E, EQParams(0x1009, 0xC6BF, 0x2952, 0x1C97, 0x30DF)) +BASE_CONFIG += configs_from_eq_params(0x98, EQParams(0x2822, 0xC1C7, 0x3B50, 0x0EF8, 0x180A)) +BASE_CONFIG += configs_from_eq_params(0xA2, EQParams(0x1009, 0xC5C2, 0x271F, 0x1A87, 0x32A6)) +BASE_CONFIG += configs_from_eq_params(0xAC, EQParams(0x2000, 0xCA1E, 0x4000, 0x2287, 0x0000)) + +class Amplifier: + AMP_I2C_BUS = 0 + AMP_ADDRESS = 0x10 + + def __init__(self, debug=False): + self.debug = debug + + def set_config(self, config): + with SMBus(self.AMP_I2C_BUS) as bus: + if self.debug: + print(f"Setting \"{config.name}\" to {config.value}:") + + old_value = bus.read_byte_data(self.AMP_ADDRESS, config.register, force=True) + new_value = (old_value & (~config.mask)) | ((config.value << config.offset) & config.mask) + bus.write_byte_data(self.AMP_ADDRESS, config.register, new_value, force=True) + + if self.debug: + print(f" Changed {hex(config.register)}: {hex(old_value)} -> {hex(new_value)}") + + def set_global_shutdown(self, amp_disabled): + self.set_config(AmpConfig("Global shutdown", 0b0 if amp_disabled else 0b1, 0x51, 7, 0b10000000)) + + def initialize_configuration(self): + for config in BASE_CONFIG: + self.set_config(config) + + # Re-init amp + self.set_global_shutdown(amp_disabled=True) + self.set_global_shutdown(amp_disabled=False) + + +if __name__ == "__main__": + Amplifier(debug=True).initialize_configuration() diff --git a/selfdrive/hardware/tici/hardware.py b/selfdrive/hardware/tici/hardware.py index f1be8ab360..0fc7bc23a2 100644 --- a/selfdrive/hardware/tici/hardware.py +++ b/selfdrive/hardware/tici/hardware.py @@ -3,10 +3,10 @@ from functools import cached_property from enum import IntEnum import subprocess from pathlib import Path -from smbus2 import SMBus from cereal import log from selfdrive.hardware.base import HardwareBase, ThermalConfig +from selfdrive.hardware.tici.amplifier import Amplifier NM = 'org.freedesktop.NetworkManager' NM_CON_ACT = NM + '.Connection.Active' @@ -43,16 +43,6 @@ NetworkStrength = log.DeviceState.NetworkStrength MM_MODEM_ACCESS_TECHNOLOGY_UMTS = 1 << 5 MM_MODEM_ACCESS_TECHNOLOGY_LTE = 1 << 14 -AMP_I2C_BUS = 0 -AMP_ADDRESS = 0x10 - -def write_amplifier_reg(reg, val, offset, mask): - with SMBus(AMP_I2C_BUS) as bus: - v = bus.read_byte_data(AMP_ADDRESS, reg, force=True) - v = (v & (~mask)) | ((val << offset) & mask) - bus.write_byte_data(AMP_ADDRESS, reg, v, force=True) - - class Tici(HardwareBase): @cached_property def bus(self): @@ -67,6 +57,10 @@ class Tici(HardwareBase): def mm(self): return self.bus.get_object(MM, '/org/freedesktop/ModemManager1') + @cached_property + def amplifier(self): + return Amplifier() + def get_os_version(self): with open("/VERSION") as f: return f.read().strip() @@ -268,14 +262,14 @@ class Tici(HardwareBase): except Exception: pass - def set_power_save(self, enabled): + def set_power_save(self, powersave_enabled): # amplifier, 100mW at idle - write_amplifier_reg(0x51, 0b0 if enabled else 0b1, 7, 0b10000000) + self.amplifier.set_global_shutdown(amp_disabled=powersave_enabled) # offline big cluster, leave core 4 online for boardd for i in range(5, 8): # TODO: fix permissions with udev - val = "0" if enabled else "1" + val = "0" if powersave_enabled else "1" os.system(f"sudo su -c 'echo {val} > /sys/devices/system/cpu/cpu{i}/online'") def get_gpu_usage_percent(self): @@ -284,3 +278,6 @@ class Tici(HardwareBase): return 100.0 * int(used) / int(total) except Exception: return 0 + + def initialize_hardware(self): + self.amplifier.initialize_configuration() diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index 8092585e22..9256d0345a 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -171,6 +171,7 @@ def thermald_thread(): power_monitor = PowerMonitoring() no_panda_cnt = 0 + HARDWARE.initialize_hardware() thermal_config = HARDWARE.get_thermal_config() if params.get_bool("IsOnroad"):