#!/usr/bin/env python3 # # Copyright (c) 2019 Intel Corporation # # SPDX-License-Identifier: Apache-2.0 import time import logging from ctypes import c_uint16, addressof from lib.driver import DiagDriver, Register import lib.registers as regs_def import lib.platforms as plat_def class Device: def __init__(self): self.__opened = False self.drv = DiagDriver() self.dev_info = None self.hda_bar_mmap = None self.dsp_bar_mmap = None self.hda_gctl = None self.hda_gcap = None self.hda_ppctl = None self.hda_spibe = None self.dsp_ctl_sts = None self.dsp_hipci = None self.dsp_hipcie = None self.dsp_hipct = None self.fw_status = None self.fw_err_code = None self.ipc_len = None self.ipc_cmd = None self.allocated = [] def close(self): if not self.__opened: logging.warning("Audio device not opened!!!") return self.__opened = False def open_device(self): logging.debug(">>> Device.open_device()") # Open device to get HDA BAR and DSP BAR self.dev_info = self.drv.open_device() # HDA MMAP self.hda_bar_mmap = self.drv.mmap(self.dev_info.hda_bar.base_p, self.dev_info.hda_bar.size) self.dev_info.hda_bar.base_v = addressof(self.hda_bar_mmap) # DSP MMAP self.dsp_bar_mmap = self.drv.mmap(self.dev_info.dsp_bar.base_p, self.dev_info.dsp_bar.size) self.dev_info.dsp_bar.base_v = addressof(self.dsp_bar_mmap) logging.debug(self.dev_info) # Registers from HDA self.hda_gctl = Register(self.hda_bar_mmap, regs_def.HDA_GR_GCTL) self.hda_gcap = Register(self.hda_bar_mmap, regs_def.HDA_GR_GCAP, c_uint16) self.hda_ppctl = Register(self.hda_bar_mmap, regs_def.HDA_PPC_PPCTL) self.hda_spibe = Register(self.hda_bar_mmap, regs_def.HDA_SPBF_SPBFCTL) # Registers from DSP self.dsp_ctl_sts = Register(self.dsp_bar_mmap, regs_def.ADSP_GR_ADSPCS) self.dsp_hipci = Register(self.dsp_bar_mmap, regs_def.ADSP_IPC_HIPCI) self.dsp_hipcie = Register(self.dsp_bar_mmap, regs_def.ADSP_IPC_HIPCIE) self.dsp_hipct = Register(self.dsp_bar_mmap, regs_def.ADSP_IPC_HIPCT) self.fw_status = Register(self.dsp_bar_mmap, plat_def.FW_STATUS) self.fw_err_code = Register(self.dsp_bar_mmap, plat_def.FW_ERR_CODE) self.ipc_len = Register(self.dsp_bar_mmap, plat_def.FW_MBOX_UPLINK + plat_def.IPC_GLOBAL_LEN) self.ipc_cmd = Register(self.dsp_bar_mmap, plat_def.FW_MBOX_UPLINK + plat_def.IPC_GLOBAL_CMD) self.__opened = True logging.debug("<<< Device.open_device()") def alloc_memory(self, size): logging.debug(">>> Device.alloc_memory()") buf = self.drv.alloc_mem(size) if buf.dma_addr_p == 0: raise RuntimeError("Could not allocate the memory") self.allocated.append(buf) logging.debug("<<< Device.alloc_memory()") return buf def free_memory(self, mem): logging.debug(">>> Device.free_memory()") if mem in self.allocated: ret = self.drv.free_mem(mem) if ret != 0: logging.error("Failed to free memory") self.allocated.remove(mem) else: logging.warning("Cannot find the memory from list") logging.debug("<<< Device.free_memory()") def power_cycle(self): logging.debug("Controller power down") self.hda_gctl.value = 0 while self.hda_gctl.value != 0: time.sleep(0.1) logging.debug(" HDA_GCTL=%s" % self.hda_gctl) logging.debug("Controller power up") self.hda_gctl.value = 1 while self.hda_gctl.value != 1: time.sleep(0.1) logging.debug(" HDA_GCTL=%s" % self.hda_gctl) def enable_proc_pipe_ctl(self): logging.debug("Enable processing pipe control") iss = ((self.hda_gcap.value & regs_def.HDA_GR_GCAP_ISS) >> regs_def.HDA_GR_GCAP_ISS_OFFSET) oss = ((self.hda_gcap.value & regs_def.HDA_GR_GCAP_OSS) >> regs_def.HDA_GR_GCAP_OSS_OFFSET) iss_mask = int("1" * iss, 2) oss_mask = int("1" * oss, 2) dma_mask = iss_mask + (oss_mask << iss) # Enable processing pipe self.hda_ppctl.value = self.hda_ppctl.value | 0x40000000 | dma_mask logging.debug(" HDA_PPCTL=%s" % self.hda_ppctl) def get_ipc_message(self): logging.info("Read IPC message from DSP") logging.info("IPC LEN: %s" % self.ipc_len) logging.info("IPC CMD: %s" % self.ipc_cmd) def core_reset_enter(self, core_mask): # Set Reset Bit for cores logging.debug("Enter core reset(mask=0x%08X)" % core_mask) reset = core_mask << regs_def.ADSP_GR_ADSPCS_CRST_OFFSET self._update_bits(self.dsp_ctl_sts, reset, reset) # Check core entered reset reg = self.dsp_ctl_sts.value if (reg & reset) != reset: raise RuntimeError("Reset enter failed: DSP_CTL_STS=%s core_maks=0x%08X" % (self.dsp_ctl_sts, core_mask)) logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) def core_reset_leave(self, core_mask): # Set Reset Bit for cores logging.debug("Leave core reset(mask=0x%08X)" % core_mask) leave = core_mask << regs_def.ADSP_GR_ADSPCS_CRST_OFFSET self._update_bits(self.dsp_ctl_sts, leave, 0) # Check core entered reset reg = self.dsp_ctl_sts.value if (reg & leave) != 0: raise RuntimeError("Reset leave failed: DSP_CTL_STS=%s core_maks=0x%08X" % (self.dsp_ctl_sts, core_mask)) logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) def core_stall_reset(self, core_mask): logging.debug("Stall core(mask=0x%08X)" % core_mask) stall = core_mask << regs_def.ADSP_GR_ADSPCS_CSTALL_OFFSET self._update_bits(self.dsp_ctl_sts, stall, stall) logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) self.core_reset_enter(core_mask) def core_run(self, core_mask): self.core_reset_leave(core_mask) logging.debug("Run/Unstall core(mask=0x%08X)" % core_mask) run = core_mask << regs_def.ADSP_GR_ADSPCS_CSTALL_OFFSET self._update_bits(self.dsp_ctl_sts, run, 0) logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) def core_power_down(self, core_mask): logging.debug("Power down core(mask=0x%08X)" % core_mask) mask = core_mask << regs_def.ADSP_GR_ADSPCS_SPA_OFFSET self._update_bits(self.dsp_ctl_sts, mask, 0) cnt = 0 while cnt < 10: cpa = self.dsp_ctl_sts.value & regs_def.ADSP_GR_ADSPCS_CPA mask = (core_mask & 0) << regs_def.ADSP_GR_ADSPCS_CPA_OFFSET if cpa == mask: logging.debug("Confirmed match value: 0x%04X" % cpa) break time.sleep(0.01) cnt += 1 if cnt == 10: logging.error(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) raise RuntimeError("Failed to power down the core") logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) def core_power_up(self, core_mask): logging.debug("Power Up core(mask=0x%08X)" % core_mask) mask = core_mask << regs_def.ADSP_GR_ADSPCS_SPA_OFFSET self._update_bits(self.dsp_ctl_sts, mask, mask) cnt = 0 while cnt < 10: cpa = self.dsp_ctl_sts.value & regs_def.ADSP_GR_ADSPCS_CPA mask = core_mask << regs_def.ADSP_GR_ADSPCS_CPA_OFFSET if cpa == mask: logging.debug("Confirmed match value: 0x%04X" % cpa) break time.sleep(0.01) cnt += 1 if cnt == 10: logging.error(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) raise RuntimeError("Failed to power up the core") logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) @staticmethod def _update_bits(reg, mask, value): old_val = reg.value new_val = (old_val & ~mask) | (value & mask) if old_val == new_val: return False reg.value = new_val return True