m1n1.fw.dcp.iboot: Add iBoot DCP interface client

Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
Hector Martin 2022-01-16 19:38:13 +09:00
parent 17e0dfceab
commit d2535159a5

View file

@ -0,0 +1,217 @@
# SPDX-License-Identifier: MIT
from construct import *
from ...utils import *
from ..asc import StandardASC
from ..afk.epic import *
EOTF = "EOTF" / Enum(Int32ul,
GAMMA_SDR = 1,
GAMMA_HDR = 2,
)
Encoding = "Encoding" / Enum(Int32ul,
RGB = 1,
YCBCR_444 = 3,
YCBCR_422 = 4,
YCBCR_420 = 5,
)
Colorimetry = "Colorimetry" / Enum(Int32ul,
BT601_709 = 1,
BT2020 = 2,
DCIP3 = 3,
)
SurfaceFormat = "SurfaceFormat" / Enum(Int32ul,
BGRA = 1,
BGRA2 = 2,
RGBA = 3,
w18p = 4,
BGRA3 = 5,
_444v = 6,
_422v = 7,
_420v = 8,
w30r = 9,
w40a = 10,
)
Transform = "Transform" / Enum(Int8ul,
NONE = 0,
XFLIP = 1,
YFLIP = 2,
ROT_90 = 3,
ROT_180 = 4,
ROT_270 = 5,
)
AddrFormat = "AddrFormat" / Enum(Int32ul,
PLANAR = 1,
TILED = 2,
AGX = 3
)
TimingMode = Struct(
"valid" / Bool(Int32ul),
"width" / Int32ul,
"height" / Int32ul,
"fps_frac" / Int16ul,
"fps_int" / Int16ul,
Padding(8),
)
TimingModeList = Struct(
"count" / Int32ul,
"list" / GreedyRange(TimingMode),
)
ColorMode = Struct(
"valid" / Bool(Int32ul),
"colorimetry" / Colorimetry,
"eotf" / EOTF,
"encoding" / Encoding,
"bpp" / Int32ul,
Padding(4),
)
ColorModeList = Struct(
"count" / Int32ul,
"list" / GreedyRange(ColorMode),
)
SwapInfo = Struct(
"unk1" / Int32ul,
"unk2" / Int32ul,
"unk3" / Int32ul,
"swap_id" / Int32ul,
"unk5" / Int32ul,
)
PlaneInfo = Struct(
"width" / Int32ul,
"height" / Int32ul,
"base" / Hex(Int32ul),
"offset" / Hex(Int32ul),
"stride" / Hex(Int32ul),
"size" / Hex(Int32ul),
"tile_size" / Int16ul,
"tile_w" / Int8ul,
"tile_h" / Int8ul,
"unk1" / UnkBytes(0xd),
"unk2" / Hex(Int8ul),
"unk3" / UnkBytes(0x26),
)
IBootPlaneInfo = Struct(
"unk1" / Default(Int32ul, 0),
"addr" / Default(Int64ul, 0),
"tile_size" / Default(Int32ul, 0),
"stride" / Default(Int32ul, 0),
"unk5" / Default(Int32ul, 0),
"unk6" / Default(Int32ul, 0),
"unk7" / Default(Int32ul, 0),
"unk8" / Default(Int32ul, 0),
"addr_format" / Default(AddrFormat, AddrFormat.PLANAR),
"unk9" / Default(Int32ul, 0),
)
IBootLayerInfo = Struct(
"planes" / Array(3, IBootPlaneInfo),
"unk" / Default(Int32ul, 0),
"plane_cnt" / Int32ul,
"width" / Int32ul,
"height" / Int32ul,
"surface_fmt" / SurfaceFormat,
"colorspace" / Int32ul,
"eotf" / EOTF,
"transform" / Transform,
Padding(3)
)
SwapSetLayer = Struct(
"unk" / Default(Int32ul, 0),
"layer_id" / Int32ul,
"layer_info" / IBootLayerInfo,
"src_w" / Int32ul,
"src_h" / Int32ul,
"src_x" / Int32ul,
"src_y" / Int32ul,
"dst_w" / Int32ul,
"dst_h" / Int32ul,
"dst_x" / Int32ul,
"dst_x" / Int32ul,
"unk2" / Default(Int32ul, 0),
)
class DCPIBootService(EPICService):
NAME = "disp0-service"
SHORT = "disp0"
def send_cmd(self, op, data=b'', replen=None):
msg = struct.pack("<IIII", op, 16 + len(data), 0, 0) + data
if replen is not None:
replen += 8
resp = super().send_cmd(0xc0, msg, replen)
if not resp:
return
rcmd, rlen = struct.unpack("<II", resp[:8])
return resp[8:rlen]
def setPower(self, power):
self.send_cmd(2, b"\x01" if power else b"\x00")
def getModeCount(self):
buf = self.send_cmd(3, b"", 12)
hpd, timing_cnt, color_cnt = struct.unpack("<III", buf)
return bool(hpd), timing_cnt, color_cnt
def getTimingModes(self):
return TimingModeList.parse(self.send_cmd(4, replen=4096)).list
def getColorModes(self):
return ColorModeList.parse(self.send_cmd(5, replen=4096)).list
def setMode(self, timing_mode, color_mode):
data = TimingMode.build(timing_mode) + ColorMode.build(color_mode)
self.send_cmd(6, data)
def swapBegin(self):
return SwapInfo.parse(self.send_cmd(15, replen=128))
def swapSetLayer(self, layer_id, info, src_rect, dst_rect):
data = Container()
data.layer_id = layer_id
data.layer_info = info
data.src_w, data.src_h, data.src_x, data.src_y = src_rect
data.dst_w, data.dst_h, data.dst_x, data.dst_y = dst_rect
return self.send_cmd(16, SwapSetLayer.build(data), replen=128)
def swapSetTimestamp(self):
pass
# 17
def swapEnd(self):
return self.send_cmd(18, b"\x00" * 12, replen=128)
#def swapWait(self, swap_id):
#buf = struct.pack("<IIII", 1, swap_id, 0, swap_id)
#return self.send_cmd(19, buf, replen=128)
class DCPIBootEndpoint(EPICEndpoint):
SHORT = "iboot"
SERVICES = [
DCPIBootService,
]
class DCPIBootClient(StandardASC):
DVA_OFFSET = 0xf00000000
ENDPOINTS = {
0x23: DCPIBootEndpoint,
}
def __init__(self, u, asc_base, dart=None, disp_dart=None):
super().__init__(u, asc_base, dart)
self.disp_dart = disp_dart