summaryrefslogtreecommitdiff
path: root/tests/kms-test-brxalloc.py
blob: c80d2e33c84685d088451f6868d7099d67adb8c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/python3
# SPDX-License-Identifier: GPL-2.0-or-later
# SPDX-FileCopyrightText: 2018-2019 Renesas Electronics Corporation

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 M3-N. 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 not in ['r8a7795', 'r8a77965']:
            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(f'Planes differ for CRTCs {outputs[0].crtc.id} and {outputs[1].crtc.id}')
            return

        self.logger.log(f'Found {len(planes)} planes for CRTCs {outputs[0].crtc.id} '
                        f'and {outputs[1].crtc.id}')

        # Get one connector for each CRTC
        for connector in self.output_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(f'No connected connectors for CRTCs {outputs[0].crtc.id} '
                      f'and {outputs[1].crtc.id}')
            return

        self.start(f'Moving {len(planes)} planes from {outputs[0].connector.fullname} '
                   f'to {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(f'atomic mode set on {output.connector.fullname} failed with {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(f'Adding plane {plane.id} to {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(f'atomic plane set failed with {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(f'Moving plane {plane.id} to {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(f'atomic plane disable failed with {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(f'atomic plane set failed with {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()