from warnings import warn from UniTAP.libs.lib_tsi import * from UniTAP.dev.ports.modules.link.dp.link_status_common import DpLinkTrainingResult from UniTAP.libs.lib_tsi.tsi_io import PortIO from UniTAP.utils.function_wrapper import * from .link_tx_status import LinkDisplayPortStatusSource from .link_tx_config import LinkDisplayPortConfig from .link_tx_force_config import LinkDisplayPortForceConfig from .private_link_tx_types import * from UniTAP.dev.ports.modules.dpcd import DPCDRegisters from .link_tx_types import DPLinkPattern, DPOutLinkMode from .dp_cable_info import DpCableInfo, CableCapabilitiesEnum class LinkDisplayPortTx: """ Class `LinkDisplayPortTx` contains information about DP link. - Read link status `status`. - Configure and read link configuration `config`. - Get maximum stream count `max_stream_count`. - Do link training `link_training`. - Get last result of link training `last_lt_result`. - Read and write scrambler seed value `scrambler_seed`. - Set `set_override_voltage` and get `get_override_voltage` override voltage. - Set `set_override_pre_emp` and get `get_override_pre_emp` override pre-emphasis. - Set and get override FFE presets `override_ffe_presets`. - Set and get link pattern `link_pattern` 'set_link_pattern'. - Set and get force link config `LinkDisplayPortForceConfig`. """ def __init__(self, port_io: PortIO, dpcd: DPCDRegisters, hw_caps: DPTXHWCaps): self.__io = port_io self.__HW_CAPS = hw_caps self.__status = LinkDisplayPortStatusSource(self.__io, self.__HW_CAPS, dpcd) self.__config = LinkDisplayPortConfig(self.__io, self.__HW_CAPS) self.__force_config = LinkDisplayPortForceConfig(self.__io, self.__HW_CAPS) self.__cable_info = DpCableInfo(port_io, TSI_DPTX_CABLE_ATTRIBUTES_R) @property def status(self) -> LinkDisplayPortStatusSource: """ Returns object of class `LinkDisplayPortStatusSource` for working with link status. Returns: object of `LinkDisplayPortStatusSource` type """ return self.__status @property def config(self) -> LinkDisplayPortConfig: """ Returns object of class `LinkDisplayPortConfig` for working with link configuration. Returns: object of `LinkDisplayPortConfig` type """ return self.__config @property def force_config(self) -> LinkDisplayPortForceConfig: """ Returns object of class `LinkDisplayPortForceConfig` for working with link configuration. Returns: object of `LinkDisplayPortForceConfig` type """ return self.__force_config @property def max_stream_count(self): """ Returns maximum supported stream count. Returns: object of int type """ return self.__HW_CAPS.mst_stream_count def start_link_training(self) -> bool: """ Make link training. Returns 'True' state if link training was success, 'False' - if not. Returns: object of bool type """ def is_link_training_success(link: LinkDisplayPortTx): return link.last_lt_result() == DpLinkTrainingResult.LTR_SUCCESS self.__io.set(TSI_W_DPTX_COMMAND, 1, c_uint32) return function_scheduler(is_link_training_success, self, interval=0.1, timeout=5) def last_lt_result(self) -> DpLinkTrainingResult: """ Returns last result of link training. Returns: object of `DpLinkTrainingResult` type """ _, value = self.__io.get(TSI_DPTX_LT_RESULT_R, c_uint) return DpLinkTrainingResult(value) @property def scrambler_seed(self) -> int: """ Returns scrambler seed value. Returns: object of `int` type """ if not self.__HW_CAPS.scrambler_seed: warnings.warn("Scrambler Seed is not supported.") return 0 return self.__io.get(TSI_DPTX_SCR_SEED, c_uint32)[1] @scrambler_seed.setter def scrambler_seed(self, value: int = 0): """ Write new value to scrambler seed Args: value (int) - new scrambler seed value """ if not self.__HW_CAPS.scrambler_seed: warnings.warn("Scrambler Seed is not supported.") return if self.config._read_lt_features().auto_seed is not None and not self.config._read_lt_features().auto_seed: self.__io.set(TSI_DPTX_SCR_SEED, value, c_uint32) else: warnings.warn("AutoSeed has already enabled. Transferred value will not be written") def get_override_voltage(self, stream_index: int) -> int: """ Returns override voltage of selected stream. Args: stream_index (int) - number of selected stream Returns: object of `int` type """ return (self.__get_override_voltage() >> stream_index) & 0x3 def set_override_voltage(self, stream_index: int, value: int): """ Returns override voltage of selected stream. Args: stream_index (int) - number of selected stream value (int) - new override voltage value """ if stream_index < self.status.mst_stream_count: raise ValueError(f"Selected stream {stream_index} is not available. " f"Available stream number: {self.status.mst_stream_count}") if not (0 <= value <= 3): raise ValueError(f"Incorrect input value {value}. Available range: 0-{self.status.lane_count}") old_value = self.__get_override_voltage() old_value &= ~(3 << (stream_index * 8)) old_value |= (value << (stream_index * 8)) self.__io.set(TSI_DPTX_OVERRIDE_VOLTAGE_SWING, old_value, c_uint32) def get_override_pre_emp(self, stream_index: int) -> int: """ Returns override pre-emphasis of selected stream. Args: stream_index (int) - number of selected stream Returns: object of `int` type """ return (self.__get_override_pre_emp() >> stream_index) & 0x3 def set_override_pre_emp(self, stream_index: int, value: int): """ Returns override pre-emphasis of selected stream. Args: stream_index (int) - number of selected stream value (int) - new override pre-emphasis value """ if stream_index < self.status.mst_stream_count: raise ValueError(f"Selected stream {stream_index} is not available. " f"Available stream number: {self.status.mst_stream_count}") if not (0 <= value <= 3): raise ValueError(f"Incorrect input value {value}. Available range: 0-{self.status.lane_count}") old_value = self.__get_override_pre_emp() old_value &= ~(3 << (stream_index * 8)) old_value |= (value << (stream_index * 8)) self.__io.set(TSI_DPTX_OVERRIDE_PRE_EMPHASIS, old_value, c_uint32) @property def override_ffe_presets(self) -> list: """ Returns override FFE presets values. Returns: object of `list` type """ if not self.__HW_CAPS.dp2_custom_rates: warnings.warn("FFE presets does not support.") return [] return self.__io.get(TSI_DP2TX_OUT_FFE, c_uint8, 4)[1] @override_ffe_presets.setter def override_ffe_presets(self, value: List[int]): """ Returns override FFE presets. Args: value list[int] - new values for override FFE presets. """ if not self.__HW_CAPS.dp2_custom_rates: warnings.warn("FFE presets does not support.") return new_value = value[0] | (value[0] << 8) | (value[0] << 16) | (value[0] << 32) self.__io.set(TSI_DP2TX_OUT_FFE, new_value) def __get_override_voltage(self) -> int: return self.__io.get(TSI_DPTX_OVERRIDE_VOLTAGE_SWING, c_uint32)[1] def __get_override_pre_emp(self) -> int: return self.__io.get(TSI_DPTX_OVERRIDE_PRE_EMPHASIS, c_uint32)[1] @property def link_pattern(self) -> DPLinkPattern: """ Returns current DP link pattern `DPLinkPattern`. Returns: object of `DPLinkPattern` type """ return DPLinkPattern(self.__io.get(TSI_DPTX_OUTPUT_PATTERN, c_uint32)[1]) def set_link_pattern(self, pattern: DPLinkPattern, additional_param: int = 1): """ Write DP link pattern value `DPLinkPattern`. Args: pattern (DPLinkPattern) - new pattern value. additional_param (int) """ if not self.__HW_CAPS.dp2_custom_rates and pattern not in [e.value for e in DPLinkPattern]: raise ValueError(f"Current pattern {pattern.name} is not supported") self.__io.set(TSI_DPTX_OUTPUT_PATTERN, pattern.value, c_uint32) if pattern == DPLinkPattern.LinkSquarePattern: self.__io.set(TSI_DPTX_SQUARE_PATTERN_NUMBER, additional_param, c_uint32) def set_force_link_mode(self, link_mode: DPOutLinkMode): self.__io.set(TSI_DPTX_OUT_LINK_MODE, link_mode.value, c_uint32) def get_force_link_mode(self) -> DPOutLinkMode: return DPOutLinkMode(self.__io.get(TSI_DPTX_OUT_LINK_MODE, c_uint32)[1]) def cable_rx_type(self) -> CableCapabilitiesEnum: """ Get cable type from the RX side. Returns: object of `CableCapabilitiesEnum` type """ return self.__cable_info.get_another_port_cable_type() def cable_tx_type(self) -> CableCapabilitiesEnum: """ Get cable type from the TX side. Returns: object of `CableCapabilitiesEnum` type """ warn("TX cable information is no longer available on the TX port.", DeprecationWarning,2) return CableCapabilitiesEnum.Unknown