#!/usr/bin/python3 import kmstest import pykms import time class Output(object): def __init__(self): self.crtc = None self.connector = None self.fb = None class BRxAllocTest(kmstest.KMSTest): """Test dynamic BRU and BRS allocation in the VSP.""" def main(self): # This test requires usage of two CRTCs connected to the same VSPDL # instance to test dynamic assignment of the BRU and BRS to pipelines. # This is only occurs on H3 ES2.0 (and M3N which we don't support yet). # Check the SoC model through sysfs as we can't detected it through the # DRM/KMS API. soc = open("/sys/devices/soc0/soc_id", "rb").read().strip().decode() if soc != "r8a7795": self.skip("VSPDL (BRU+BRS) not available") return outputs = [Output(), Output()] # Get the first and last CRTCs for crtc in self.card.crtcs: if outputs[0].crtc == None or crtc.id < outputs[0].crtc.id: outputs[0].crtc = crtc if outputs[1].crtc == None or crtc.id > outputs[1].crtc.id: outputs[1].crtc = crtc # Verify that the two CRTCs share the same planes planes = outputs[0].crtc.possible_planes if planes != outputs[1].crtc.possible_planes: self.skip("Planes differ for CRTCs %u and %u" % \ (outputs[0].crtc.id, outputs[1].crtc.id)) return self.logger.log("Found %u planes for CRTCs %u and %u" % \ (len(planes), outputs[0].crtc.id, outputs[1].crtc.id)) # Get one connector for each CRTC for connector in self.card.connectors: # Skip disconnected connectors if not connector.connected(): continue for crtc in connector.get_possible_crtcs(): if crtc == outputs[0].crtc: outputs[0].connector = connector if crtc == outputs[1].crtc: outputs[1].connector = connector if not outputs[0].connector or not outputs[1].connector: self.skip("No connected connectors for CRTCs %u and %u " % \ (outputs[0].crtc.id, outputs[1].crtc.id)) return self.start("Moving %u planes from %s to %s" % \ (len(planes), outputs[0].connector.fullname, outputs[1].connector.fullname)) # Set the initial mode for both outputs and wait 5s for the monitors to # wake up. for output in outputs: # Get the default mode and create a framebuffer mode = output.connector.get_default_mode() output.fb = pykms.DumbFramebuffer(self.card, mode.hdisplay, mode.vdisplay, "XR24") pykms.draw_test_pattern(output.fb) # Set the mode with no plane ret = self.atomic_crtc_mode_set(output.crtc, output.connector, mode, sync=True) if ret < 0: self.fail("atomic mode set on %s failed with %d" % \ (output.connector.fullname, ret)) return self.logger.log("Initial atomic mode set completed") time.sleep(5) # Add all planes offset = 0 output = outputs[0] for plane in planes: self.logger.log("Adding plane %u to %s" % (plane.id, output.connector.fullname)) source = kmstest.Rect(0, 0, output.fb.width, output.fb.height) destination = kmstest.Rect(offset, offset, output.fb.width, output.fb.height) ret = self.atomic_plane_set(plane, output.crtc, source, destination, output.fb, sync=True) if ret < 0: self.fail("atomic plane set failed with %d" % ret) return offset += 50 time.sleep(2) # Move all planes one by one offset = 0 output = outputs[1] for plane in planes: self.logger.log("Moving plane %u to %s" % (plane.id, output.connector.fullname)) # Switching CRTC directly is not supported by DRM, start by # disabling the plane. ret = self.atomic_plane_disable(plane) if ret < 0: self.fail("atomic plane disable failed with %d" % ret) return source = kmstest.Rect(0, 0, output.fb.width, output.fb.height) destination = kmstest.Rect(offset, offset, output.fb.width, output.fb.height) ret = self.atomic_plane_set(plane, output.crtc, source, destination, output.fb) if ret < 0: self.fail("atomic plane set failed with %d" % ret) return self.run(1) offset += 50 self.success() self.atomic_crtc_disable(outputs[0].crtc) self.atomic_crtc_disable(outputs[1].crtc) BRxAllocTest().execute()