Skip to content

Commit ca2450d

Browse files
committed
panel: Add basic support for parsing DTBs from newer SoCs
Newer SoCs use a qcom,mdss-dsi-display-timings subnode, which allows defining multiple possible display modes (resolution, refresh rate, ...) for one panel. The generator does not attemt to support this fully (yet!), for now we just adjust the parsing a bit and pick the first timing.
1 parent 80feba9 commit ca2450d

File tree

2 files changed

+48
-11
lines changed

2 files changed

+48
-11
lines changed

fdt2.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ def subnodes(self, parent):
2121
yield offset
2222
offset = self.next_subnode(offset, [FDT_ERR_NOTFOUND])
2323

24+
def subnode_or_none(self, parentoffset, name):
25+
offset = self.subnode_offset(parentoffset, name, [FDT_ERR_NOTFOUND])
26+
if offset == -FDT_ERR_NOTFOUND:
27+
return None
28+
return offset
29+
2430
def getprop_or_none(self, nodeoffset, prop_name):
2531
prop = self.getprop(nodeoffset, prop_name, [FDT_ERR_NOTFOUND])
2632
if prop == -FDT_ERR_NOTFOUND:

panel.py

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,13 @@ def __init__(self, prefix: str, size: str) -> None:
107107
self.prefix = prefix
108108
self.size = size
109109

110-
def __init__(self, fdt: Fdt2, node: int, t: Type) -> None:
110+
def __init__(self, fdt: Fdt2, panel_node: int, mode_node: int, t: Type) -> None:
111111
self.type = type
112-
self.px = fdt.getprop(node, f'qcom,mdss-dsi-panel-{t.size}').as_int32()
113-
self.fp = fdt.getprop(node, f'qcom,mdss-dsi-{t.prefix}-front-porch').as_int32()
114-
self.bp = fdt.getprop(node, f'qcom,mdss-dsi-{t.prefix}-back-porch').as_int32()
115-
self.pw = fdt.getprop(node, f'qcom,mdss-dsi-{t.prefix}-pulse-width').as_int32()
116-
self.size = fdt.getprop_int32(node, f'qcom,mdss-pan-physical-{t.size}-dimension')
112+
self.px = fdt.getprop(mode_node, f'qcom,mdss-dsi-panel-{t.size}').as_int32()
113+
self.fp = fdt.getprop(mode_node, f'qcom,mdss-dsi-{t.prefix}-front-porch').as_int32()
114+
self.bp = fdt.getprop(mode_node, f'qcom,mdss-dsi-{t.prefix}-back-porch').as_int32()
115+
self.pw = fdt.getprop(mode_node, f'qcom,mdss-dsi-{t.prefix}-pulse-width').as_int32()
116+
self.size = fdt.getprop_int32(panel_node, f'qcom,mdss-pan-physical-{t.size}-dimension')
117117

118118

119119
@dataclass
@@ -184,6 +184,22 @@ def _remove_before(text: str, sub: str) -> str:
184184
return text[i + 1:] if i >= 0 else text
185185

186186

187+
def _find_mode_node(fdt: Fdt2, node: int) -> int:
188+
timings_node = fdt.subnode_or_none(node, "qcom,mdss-dsi-display-timings")
189+
if timings_node is None:
190+
return node
191+
192+
mode_node = None
193+
for timing in fdt.subnodes(timings_node):
194+
if mode_node:
195+
print("WARNING: Multiple display timings are not supported yet, using first!")
196+
break
197+
mode_node = timing
198+
199+
assert mode_node, "No display timings found"
200+
return mode_node
201+
202+
187203
class Panel:
188204
def __init__(self, name: str, fdt: Fdt2, node: int) -> None:
189205
self.name = name
@@ -192,9 +208,14 @@ def __init__(self, name: str, fdt: Fdt2, node: int) -> None:
192208
self.short_id = _replace_all(self.id, '_panel', '_video', '_vid', '_cmd',
193209
'_hd', '_qhd', '_720p', '_1080p',
194210
'_wvga', '_fwvga', '_qvga', '_xga', '_wxga')
195-
self.h = Dimension(fdt, node, Dimension.Type.HORIZONTAL)
196-
self.v = Dimension(fdt, node, Dimension.Type.VERTICAL)
197-
self.framerate = fdt.getprop(node, 'qcom,mdss-dsi-panel-framerate').as_int32()
211+
212+
# Newer SoCs can use panels in different modes (resolution, refresh rate etc).
213+
# We don't support this properly yet but many panels just have a single mode
214+
# ("timing") defined, so let's try to support this here.
215+
mode_node = _find_mode_node(fdt, node)
216+
self.h = Dimension(fdt, node, mode_node, Dimension.Type.HORIZONTAL)
217+
self.v = Dimension(fdt, node, mode_node, Dimension.Type.VERTICAL)
218+
self.framerate = fdt.getprop(mode_node, 'qcom,mdss-dsi-panel-framerate').as_int32()
198219
self.bpp = fdt.getprop(node, 'qcom,mdss-dsi-bpp').as_int32()
199220
self.mode = Mode(fdt.getprop(node, 'qcom,mdss-dsi-panel-type').as_str())
200221
self.traffic_mode = TrafficMode.parse(fdt.getprop(node, 'qcom,mdss-dsi-traffic-mode'))
@@ -227,8 +248,8 @@ def __init__(self, name: str, fdt: Fdt2, node: int) -> None:
227248
self.reset_seq = None
228249

229250
self.cmds = {
230-
'on': CommandSequence(fdt, node, 'on'),
231-
'off': CommandSequence(fdt, node, 'off')
251+
'on': CommandSequence(fdt, mode_node, 'on'),
252+
'off': CommandSequence(fdt, mode_node, 'off')
232253
}
233254

234255
# If all commands are sent in LPM, add flag globally
@@ -259,3 +280,13 @@ def find(fdt: Fdt2) -> Iterator[Panel]:
259280
panel = Panel.parse(fdt, sub)
260281
if panel:
261282
yield panel
283+
284+
# Newer device trees do not necessarily have panels below MDP,
285+
# search for qcom,dsi-display node instead
286+
for display in fdt.find_by_compatible('qcom,dsi-display'):
287+
# Actual display node is pointed to by qcom,dsi-panel
288+
phandle = fdt.getprop(display, 'qcom,dsi-panel').as_uint32()
289+
offset = fdt.node_offset_by_phandle(phandle)
290+
panel = Panel.parse(fdt, offset)
291+
if panel:
292+
yield panel

0 commit comments

Comments
 (0)