def __init__(self, fdt: Fdt2, node: int, cmd: str) -> None: self.state = CommandSequence.State(fdt.getprop(node, f'qcom,mdss-dsi-{cmd}-command-state').as_str()) self.seq = [] prop = fdt.getprop_or_none(node, f'qcom,mdss-dsi-{cmd}-command') if prop is None: print(f'Warning: qcom,mdss-dsi-{cmd}-command does not exist') return # No commands itr = iter(prop) if cmd == 'on': # WHY SONY, WHY?????? Just put it in on-command... init = fdt.getprop_or_none(node, 'somc,mdss-dsi-init-command') if init: itr = itertools.chain(init, itr) for dtype in itr: last, vc, ack, wait = next(itr), next(itr), next(itr), next(itr) dlen = next(itr) << 8 | next(itr) payload = bytes(next(itr) for _ in range(0, dlen)) t = mipi.Transaction(dtype) # Very often there are too many arguments encoded in the command stream. # These are redundant, because they would be never sent anyway. max_dlen = t.max_args + 1 if 0 < max_dlen < dlen: payload = payload[:max_dlen] self.seq.append(Command(t, last, vc, ack, wait, payload))
def find(fdt: Fdt2) -> Iterator[Panel]: for mdp in fdt.find_by_compatible('qcom,mdss_mdp'): for sub in fdt.subnodes(mdp): panel = Panel.parse(fdt, sub) if panel: yield panel # Newer device trees do not necessarily have panels below MDP, # search for qcom,dsi-display node instead panel_phandles = set() for display in fdt.find_by_compatible('qcom,dsi-display'): # On even newer SoCs there is another node with qcom,dsi-display-list displays = fdt.getprop_or_none(display, 'qcom,dsi-display-list') if displays is None: panel_phandles.add( fdt.getprop(display, 'qcom,dsi-panel').as_uint32()) else: for display_phandle in displays.as_uint32_array(): display = fdt.node_offset_by_phandle(display_phandle) panel_phandles.add( fdt.getprop(display, 'qcom,dsi-panel').as_uint32()) for phandle in panel_phandles: offset = fdt.node_offset_by_phandle(phandle) panel = Panel.parse(fdt, offset) if panel: yield panel
def __init__(self, name: str, fdt: Fdt2, node: int) -> None: self.name = name self.id = _remove_before(_remove_prefixes(fdt.get_name(node), 'qcom,mdss_dsi_', 'ss_dsi_panel_', 'mot_').lower(), ',') print(f'Parsing: {self.id} ({name})') self.short_id = _replace_all(self.id, '_panel', '_video', '_vid', '_cmd', '_hd', '_qhd', '_720p', '_1080p', '_wvga', '_fwvga', '_qvga', '_xga', '_wxga') self.h = Dimension(fdt, node, Dimension.Type.HORIZONTAL) self.v = Dimension(fdt, node, Dimension.Type.VERTICAL) self.framerate = fdt.getprop(node, 'qcom,mdss-dsi-panel-framerate').as_int32() self.bpp = fdt.getprop(node, 'qcom,mdss-dsi-bpp').as_int32() self.mode = Mode(fdt.getprop(node, 'qcom,mdss-dsi-panel-type').as_str()) self.traffic_mode = TrafficMode.parse(fdt.getprop(node, 'qcom,mdss-dsi-traffic-mode')) backlight = fdt.getprop_or_none(node, 'qcom,mdss-dsi-bl-pmic-control-type') self.backlight = BacklightControl(backlight.as_str()) if backlight else None self.max_brightness = fdt.getprop_int32(node, 'qcom,mdss-dsi-bl-max-level', None) self.lanes = 0 while fdt.getprop_or_none(node, f'qcom,mdss-dsi-lane-{self.lanes}-state') is not None: self.lanes += 1 self.flags = self.mode.flags + self.traffic_mode.flags if fdt.getprop_int32(node, 'qcom,mdss-dsi-h-sync-pulse') != 0: self.flags.append('MIPI_DSI_MODE_VIDEO_HSE') if fdt.getprop_or_none(node, 'qcom,mdss-dsi-tx-eot-append') is None: self.flags.append('MIPI_DSI_MODE_EOT_PACKET') if fdt.getprop_or_none(node, 'qcom,mdss-dsi-force-clock-lane-hs') is None \ and fdt.getprop_or_none(node, 'qcom,mdss-dsi-force-clk-lane-hs') is None: self.flags.append('MIPI_DSI_CLOCK_NON_CONTINUOUS') reset_seq = fdt.getprop_or_none(node, 'qcom,mdss-dsi-reset-sequence') if reset_seq is not None: itr = iter(reset_seq.as_uint32_array()) self.reset_seq = list(zip(itr, itr)) else: self.reset_seq = None self.cmds = { 'on': CommandSequence(fdt, node, 'on'), 'off': CommandSequence(fdt, node, 'off') } # If all commands are sent in LPM, add flag globally if self.cmds['on'].state == CommandSequence.State.LP_MODE == self.cmds['off'].state: self.flags.append('MIPI_DSI_MODE_LPM') if self.bpp == 24: self.format = 'MIPI_DSI_FMT_RGB888' else: raise ValueError(f'Unsupported bpp: {self.bpp} (TODO)') # Sony </3 prop = fdt.getprop_or_none(node, 'somc,mdss-phy-size-mm') if prop: phy_size_mm = prop.as_uint32_array() self.h.size = phy_size_mm[0] self.v.size = phy_size_mm[1]
def parse(fdt: Fdt2, node: int) -> Panel: name = fdt.getprop_or_none(node, 'qcom,mdss-dsi-panel-name') return name and Panel(name.as_str(), fdt, node)
def __init__(self, name: str, fdt: Fdt2, node: int) -> None: self.name = name self.id = _remove_before( _remove_prefixes(fdt.get_name(node), 'qcom,mdss_dsi_', 'ss_dsi_panel_', 'mot_').lower(), ',') print(f'Parsing: {self.id} ({name})') self.short_id = _replace_all(self.id, '_panel', '_video', '_vid', '_cmd', '_hd', '_qhd', '_720p', '_1080p', '_wvga', '_fwvga', '_qvga', '_xga', '_wxga') # Newer SoCs can use panels in different modes (resolution, refresh rate etc). # We don't support this properly yet but many panels just have a single mode # ("timing") defined, so let's try to support this here. mode_node = _find_mode_node(fdt, node) self.h = Dimension(fdt, node, mode_node, Dimension.Type.HORIZONTAL) self.v = Dimension(fdt, node, mode_node, Dimension.Type.VERTICAL) self.framerate = fdt.getprop( mode_node, 'qcom,mdss-pan-dsi-frame-rate').as_int32() self.bpp = fdt.getprop(node, 'qcom,mdss-pan-bpp').as_int32() self.mode = Mode( 'dsi_cmd_mode') # FIXME, what do to with missing dsi_cmd_mode? self.traffic_mode = TrafficMode.parse( fdt.getprop(node, 'qcom,mdss-pan-dsi-traffic-mode')) backlight = fdt.getprop_or_none(node, 'qcom,mdss-dsi-bl-pmic-control-type') self.backlight = BacklightControl( backlight.as_str()) if backlight else None self.max_brightness = fdt.getprop_int32(node, 'qcom,mdss-dsi-bl-max-level', None) if self.backlight == BacklightControl.DCS and self.max_brightness is None: print( "WARNING: DCS backlight without maximum brightness, ignoring..." ) self.backlight = None self.lanes = 0 while fdt.getprop_or_none( node, f'qcom,mdss-dsi-lane-{self.lanes}-state') is not None: self.lanes += 1 self.lane_map = LaneMap.parse( fdt.getprop_or_none(node, 'qcom,mdss-dsi-lane-map')) self.flags = self.mode.flags + self.traffic_mode.flags if fdt.getprop_int32(node, 'qcom,mdss-dsi-h-sync-pulse') != 0: self.flags.append('MIPI_DSI_MODE_VIDEO_HSE') if fdt.getprop_or_none(node, 'qcom,mdss-dsi-tx-eot-append') is None: self.flags.append('MIPI_DSI_MODE_EOT_PACKET') if fdt.getprop_or_none(node, 'qcom,mdss-dsi-force-clock-lane-hs') is None \ and fdt.getprop_or_none(node, 'qcom,mdss-dsi-force-clk-lane-hs') is None: self.flags.append('MIPI_DSI_CLOCK_NON_CONTINUOUS') reset_seq = fdt.getprop_or_none(node, 'qcom,mdss-dsi-reset-sequence') if reset_seq is not None: itr = iter(reset_seq.as_uint32_array()) self.reset_seq = list(zip(itr, itr)) else: self.reset_seq = None self.cmds = { 'on': CommandSequence(fdt, mode_node, 'on'), 'off': CommandSequence(fdt, mode_node, 'off') } # If all commands are sent in LPM, add flag globally if self.cmds['on'].state == CommandSequence.State.LP_MODE == self.cmds[ 'off'].state: self.flags.append('MIPI_DSI_MODE_LPM') if self.bpp == 24: self.format = 'MIPI_DSI_FMT_RGB888' else: raise ValueError(f'Unsupported bpp: {self.bpp} (TODO)') # Sony </3 prop = fdt.getprop_or_none(node, 'somc,mdss-phy-size-mm') if prop: phy_size_mm = prop.as_uint32_array() self.h.size = phy_size_mm[0] self.v.size = phy_size_mm[1]
def __init__(self, name: str, fdt: Fdt2, node: int) -> None: self.name = name self.node_name = fdt.get_name(node) self.id = _remove_before(_remove_prefixes(self.node_name, 'qcom,mdss_dsi_', 'ss_dsi_panel_', 'mot_').lower(), ',') print(f'Parsing: {self.id} ({name})') self.short_id = _replace_all(self.id, '_panel', '_video', '_vid', '_cmd', '_hd', '_qhd', '_720p', '_1080p', '_wvga', '_fwvga', '_qvga', '_xga', '_wxga') # Newer SoCs can use panels in different modes (resolution, refresh rate etc). # We don't support this properly yet but many panels just have a single mode # ("timing") defined, so let's try to support this here. mode_node = _find_mode_node(fdt, node) self.h = Dimension(fdt, node, mode_node, Dimension.Type.HORIZONTAL) self.v = Dimension(fdt, node, mode_node, Dimension.Type.VERTICAL) self.framerate = fdt.getprop(mode_node, 'qcom,mdss-dsi-panel-framerate').as_int32() self.bpp = fdt.getprop(node, 'qcom,mdss-dsi-bpp').as_int32() self.mode = Mode(fdt.getprop(node, 'qcom,mdss-dsi-panel-type').as_str()) self.traffic_mode = TrafficMode.parse(fdt.getprop(node, 'qcom,mdss-dsi-traffic-mode')) backlight = fdt.getprop_or_none(node, 'qcom,mdss-dsi-bl-pmic-control-type') self.backlight = BacklightControl(backlight.as_str()) if backlight else None self.max_brightness = fdt.getprop_int32(node, 'qcom,mdss-dsi-bl-max-level', None) if self.backlight == BacklightControl.DCS and self.max_brightness is None: print("WARNING: DCS backlight without maximum brightness, ignoring...") self.backlight = None self.lanes = 0 while fdt.getprop_or_none(node, f'qcom,mdss-dsi-lane-{self.lanes}-state') is not None: self.lanes += 1 self.lane_map = LaneMap.parse(fdt.getprop_or_none(node, 'qcom,mdss-dsi-lane-map')) self.flags = self.mode.flags + self.traffic_mode.flags if fdt.getprop_int32(node, 'qcom,mdss-dsi-h-sync-pulse') != 0: self.flags.append('MIPI_DSI_MODE_VIDEO_HSE') if fdt.getprop_or_none(node, 'qcom,mdss-dsi-tx-eot-append') is None: self.flags.append('MIPI_DSI_MODE_NO_EOT_PACKET') if fdt.getprop_or_none(node, 'qcom,mdss-dsi-force-clock-lane-hs') is None \ and fdt.getprop_or_none(node, 'qcom,mdss-dsi-force-clk-lane-hs') is None \ and fdt.getprop_or_none(node, 'qcom,mdss-force-clk-lane-hs') is None: self.flags.append('MIPI_DSI_CLOCK_NON_CONTINUOUS') reset_seq = fdt.getprop_or_none(node, 'qcom,mdss-dsi-reset-sequence') if reset_seq is not None: itr = iter(reset_seq.as_uint32_array()) self.reset_seq = list(zip(itr, itr)) else: self.reset_seq = None self.cmds = { 'on': CommandSequence(fdt, mode_node, 'on'), 'off': CommandSequence(fdt, mode_node, 'off') } # If all commands are sent in LPM, add flag globally if self.cmds['on'].state == CommandSequence.State.LP_MODE == self.cmds['off'].state: self.flags.append('MIPI_DSI_MODE_LPM') if self.bpp == 24: self.format = 'MIPI_DSI_FMT_RGB888' else: raise ValueError(f'Unsupported bpp: {self.bpp} (TODO)') # Sony </3 prop = fdt.getprop_or_none(node, 'somc,mdss-phy-size-mm') if prop: phy_size_mm = prop.as_uint32_array() self.h.size = phy_size_mm[0] self.v.size = phy_size_mm[1] # Check DSI controller if LDO mode is needed self.ldo_mode = False dsi_ctrl = fdt.getprop_or_none(node, 'qcom,mdss-dsi-panel-controller') if dsi_ctrl is not None: dsi_ctrl = fdt.node_offset_by_phandle(dsi_ctrl.as_uint32()) self.ldo_mode = fdt.getprop_or_none(dsi_ctrl, 'qcom,regulator-ldo-mode') is not None # Timings are usually calculated by the driver except for downstream and LK p = fdt.getprop_or_none(node, 'qcom,mdss-dsi-panel-timings') self.timings = bytes(p) if p else bytes() self.tclk_post = fdt.getprop_int32(node, 'qcom,mdss-dsi-t-clk-post') self.tclk_pre = fdt.getprop_int32(node, 'qcom,mdss-dsi-t-clk-pre') # Additional weird values used by downstream and LK self.hsync_skew = fdt.getprop_int32(node, 'qcom,mdss-dsi-h-sync-skew') self.hfp_power_mode = fdt.getprop_or_none(node, 'qcom,mdss-dsi-hfp-power-mode') is not None self.hsa_power_mode = fdt.getprop_or_none(node, 'qcom,mdss-dsi-hsa-power-mode') is not None self.hbp_power_mode = fdt.getprop_or_none(node, 'qcom,mdss-dsi-hbp-power-mode') is not None self.bllp_power_mode = fdt.getprop_or_none(node, 'qcom,mdss-dsi-bllp-power-mode') is not None self.bllp_eof_power_mode = fdt.getprop_or_none(node, 'qcom,mdss-dsi-bllp-eof-power-mode') is not None self.lp11_init = fdt.getprop_or_none(node, 'qcom,mdss-dsi-lp11-init') is not None self.init_delay = fdt.getprop_int32(node, 'qcom,mdss-dsi-init-delay-us')