1#!/usr/bin/env python3 2# 3# Copyright (c) 2019 Intel Corporation 4# 5# SPDX-License-Identifier: Apache-2.0 6import time 7import logging 8from ctypes import c_uint16, addressof 9 10from lib.driver import DiagDriver, Register 11import lib.registers as regs_def 12import lib.platforms as plat_def 13 14 15class Device: 16 17 def __init__(self): 18 self.__opened = False 19 20 self.drv = DiagDriver() 21 self.dev_info = None 22 23 self.hda_bar_mmap = None 24 self.dsp_bar_mmap = None 25 26 self.hda_gctl = None 27 self.hda_gcap = None 28 self.hda_ppctl = None 29 self.hda_spibe = None 30 31 self.dsp_ctl_sts = None 32 self.dsp_hipci = None 33 self.dsp_hipcie = None 34 self.dsp_hipct = None 35 36 self.fw_status = None 37 self.fw_err_code = None 38 39 self.ipc_len = None 40 self.ipc_cmd = None 41 42 self.allocated = [] 43 44 def close(self): 45 if not self.__opened: 46 logging.warning("Audio device not opened!!!") 47 return 48 self.__opened = False 49 50 def open_device(self): 51 logging.debug(">>> Device.open_device()") 52 53 # Open device to get HDA BAR and DSP BAR 54 self.dev_info = self.drv.open_device() 55 56 # HDA MMAP 57 self.hda_bar_mmap = self.drv.mmap(self.dev_info.hda_bar.base_p, 58 self.dev_info.hda_bar.size) 59 self.dev_info.hda_bar.base_v = addressof(self.hda_bar_mmap) 60 # DSP MMAP 61 self.dsp_bar_mmap = self.drv.mmap(self.dev_info.dsp_bar.base_p, 62 self.dev_info.dsp_bar.size) 63 self.dev_info.dsp_bar.base_v = addressof(self.dsp_bar_mmap) 64 logging.debug(self.dev_info) 65 66 # Registers from HDA 67 self.hda_gctl = Register(self.hda_bar_mmap, 68 regs_def.HDA_GR_GCTL) 69 self.hda_gcap = Register(self.hda_bar_mmap, 70 regs_def.HDA_GR_GCAP, c_uint16) 71 self.hda_ppctl = Register(self.hda_bar_mmap, 72 regs_def.HDA_PPC_PPCTL) 73 self.hda_spibe = Register(self.hda_bar_mmap, 74 regs_def.HDA_SPBF_SPBFCTL) 75 # Registers from DSP 76 self.dsp_ctl_sts = Register(self.dsp_bar_mmap, 77 regs_def.ADSP_GR_ADSPCS) 78 self.dsp_hipci = Register(self.dsp_bar_mmap, 79 regs_def.ADSP_IPC_HIPCI) 80 self.dsp_hipcie = Register(self.dsp_bar_mmap, 81 regs_def.ADSP_IPC_HIPCIE) 82 self.dsp_hipct = Register(self.dsp_bar_mmap, 83 regs_def.ADSP_IPC_HIPCT) 84 self.fw_status = Register(self.dsp_bar_mmap, 85 plat_def.FW_STATUS) 86 self.fw_err_code = Register(self.dsp_bar_mmap, 87 plat_def.FW_ERR_CODE) 88 self.ipc_len = Register(self.dsp_bar_mmap, 89 plat_def.FW_MBOX_UPLINK + plat_def.IPC_GLOBAL_LEN) 90 self.ipc_cmd = Register(self.dsp_bar_mmap, 91 plat_def.FW_MBOX_UPLINK + plat_def.IPC_GLOBAL_CMD) 92 93 self.__opened = True 94 logging.debug("<<< Device.open_device()") 95 96 def alloc_memory(self, size): 97 logging.debug(">>> Device.alloc_memory()") 98 buf = self.drv.alloc_mem(size) 99 if buf.dma_addr_p == 0: 100 raise RuntimeError("Could not allocate the memory") 101 self.allocated.append(buf) 102 logging.debug("<<< Device.alloc_memory()") 103 return buf 104 105 def free_memory(self, mem): 106 logging.debug(">>> Device.free_memory()") 107 if mem in self.allocated: 108 ret = self.drv.free_mem(mem) 109 if ret != 0: 110 logging.error("Failed to free memory") 111 self.allocated.remove(mem) 112 else: 113 logging.warning("Cannot find the memory from list") 114 logging.debug("<<< Device.free_memory()") 115 116 def power_cycle(self): 117 logging.debug("Controller power down") 118 self.hda_gctl.value = 0 119 while self.hda_gctl.value != 0: 120 time.sleep(0.1) 121 logging.debug(" HDA_GCTL=%s" % self.hda_gctl) 122 123 logging.debug("Controller power up") 124 self.hda_gctl.value = 1 125 while self.hda_gctl.value != 1: 126 time.sleep(0.1) 127 logging.debug(" HDA_GCTL=%s" % self.hda_gctl) 128 129 def enable_proc_pipe_ctl(self): 130 logging.debug("Enable processing pipe control") 131 iss = ((self.hda_gcap.value & regs_def.HDA_GR_GCAP_ISS) 132 >> regs_def.HDA_GR_GCAP_ISS_OFFSET) 133 oss = ((self.hda_gcap.value & regs_def.HDA_GR_GCAP_OSS) 134 >> regs_def.HDA_GR_GCAP_OSS_OFFSET) 135 136 iss_mask = int("1" * iss, 2) 137 oss_mask = int("1" * oss, 2) 138 139 dma_mask = iss_mask + (oss_mask << iss) 140 141 # Enable processing pipe 142 self.hda_ppctl.value = self.hda_ppctl.value | 0x40000000 | dma_mask 143 logging.debug(" HDA_PPCTL=%s" % self.hda_ppctl) 144 145 def get_ipc_message(self): 146 logging.info("Read IPC message from DSP") 147 logging.info("IPC LEN: %s" % self.ipc_len) 148 logging.info("IPC CMD: %s" % self.ipc_cmd) 149 150 def core_reset_enter(self, core_mask): 151 # Set Reset Bit for cores 152 logging.debug("Enter core reset(mask=0x%08X)" % core_mask) 153 154 reset = core_mask << regs_def.ADSP_GR_ADSPCS_CRST_OFFSET 155 self._update_bits(self.dsp_ctl_sts, reset, reset) 156 157 # Check core entered reset 158 reg = self.dsp_ctl_sts.value 159 if (reg & reset) != reset: 160 raise RuntimeError("Reset enter failed: DSP_CTL_STS=%s core_maks=0x%08X" 161 % (self.dsp_ctl_sts, core_mask)) 162 logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) 163 164 def core_reset_leave(self, core_mask): 165 # Set Reset Bit for cores 166 logging.debug("Leave core reset(mask=0x%08X)" % core_mask) 167 168 leave = core_mask << regs_def.ADSP_GR_ADSPCS_CRST_OFFSET 169 self._update_bits(self.dsp_ctl_sts, leave, 0) 170 171 # Check core entered reset 172 reg = self.dsp_ctl_sts.value 173 if (reg & leave) != 0: 174 raise RuntimeError("Reset leave failed: DSP_CTL_STS=%s core_maks=0x%08X" 175 % (self.dsp_ctl_sts, core_mask)) 176 logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) 177 178 def core_stall_reset(self, core_mask): 179 logging.debug("Stall core(mask=0x%08X)" % core_mask) 180 stall = core_mask << regs_def.ADSP_GR_ADSPCS_CSTALL_OFFSET 181 self._update_bits(self.dsp_ctl_sts, stall, stall) 182 logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) 183 self.core_reset_enter(core_mask) 184 185 def core_run(self, core_mask): 186 self.core_reset_leave(core_mask) 187 188 logging.debug("Run/Unstall core(mask=0x%08X)" % core_mask) 189 run = core_mask << regs_def.ADSP_GR_ADSPCS_CSTALL_OFFSET 190 self._update_bits(self.dsp_ctl_sts, run, 0) 191 logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) 192 193 def core_power_down(self, core_mask): 194 logging.debug("Power down core(mask=0x%08X)" % core_mask) 195 mask = core_mask << regs_def.ADSP_GR_ADSPCS_SPA_OFFSET 196 self._update_bits(self.dsp_ctl_sts, mask, 0) 197 198 cnt = 0 199 while cnt < 10: 200 cpa = self.dsp_ctl_sts.value & regs_def.ADSP_GR_ADSPCS_CPA 201 mask = (core_mask & 0) << regs_def.ADSP_GR_ADSPCS_CPA_OFFSET 202 if cpa == mask: 203 logging.debug("Confirmed match value: 0x%04X" % cpa) 204 break 205 time.sleep(0.01) 206 cnt += 1 207 208 if cnt == 10: 209 logging.error(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) 210 raise RuntimeError("Failed to power down the core") 211 logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) 212 213 def core_power_up(self, core_mask): 214 logging.debug("Power Up core(mask=0x%08X)" % core_mask) 215 mask = core_mask << regs_def.ADSP_GR_ADSPCS_SPA_OFFSET 216 self._update_bits(self.dsp_ctl_sts, mask, mask) 217 218 cnt = 0 219 while cnt < 10: 220 cpa = self.dsp_ctl_sts.value & regs_def.ADSP_GR_ADSPCS_CPA 221 mask = core_mask << regs_def.ADSP_GR_ADSPCS_CPA_OFFSET 222 223 if cpa == mask: 224 logging.debug("Confirmed match value: 0x%04X" % cpa) 225 break 226 time.sleep(0.01) 227 cnt += 1 228 229 if cnt == 10: 230 logging.error(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) 231 raise RuntimeError("Failed to power up the core") 232 233 logging.debug(" DSP_CTL_STS=%s" % self.dsp_ctl_sts) 234 235 @staticmethod 236 def _update_bits(reg, mask, value): 237 238 old_val = reg.value 239 new_val = (old_val & ~mask) | (value & mask) 240 241 if old_val == new_val: 242 return False 243 244 reg.value = new_val 245 return True 246