Files
pqAutomationApp/UniTAP/dev/ports/modules/link/dp/link_tx.py

280 lines
9.8 KiB
Python
Raw Normal View History

2026-04-16 16:51:05 +08:00
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