1.1.0版本
This commit is contained in:
279
UniTAP/dev/ports/modules/link/dp/link_tx.py
Normal file
279
UniTAP/dev/ports/modules/link/dp/link_tx.py
Normal file
@@ -0,0 +1,279 @@
|
||||
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
|
||||
Reference in New Issue
Block a user