linux/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Test cases for for the DRM DP MST helpers
   4 */
   5
   6#define PREFIX_STR "[drm_dp_mst_helper]"
   7
   8#include <drm/drm_dp_mst_helper.h>
   9#include <drm/drm_print.h>
  10
  11#include "../drm_dp_mst_topology_internal.h"
  12#include "test-drm_modeset_common.h"
  13
  14int igt_dp_mst_calc_pbn_mode(void *ignored)
  15{
  16        int pbn, i;
  17        const struct {
  18                int rate;
  19                int bpp;
  20                int expected;
  21                bool dsc;
  22        } test_params[] = {
  23                { 154000, 30, 689, false },
  24                { 234000, 30, 1047, false },
  25                { 297000, 24, 1063, false },
  26                { 332880, 24, 50, true },
  27                { 324540, 24, 49, true },
  28        };
  29
  30        for (i = 0; i < ARRAY_SIZE(test_params); i++) {
  31                pbn = drm_dp_calc_pbn_mode(test_params[i].rate,
  32                                           test_params[i].bpp,
  33                                           test_params[i].dsc);
  34                FAIL(pbn != test_params[i].expected,
  35                     "Expected PBN %d for clock %d bpp %d, got %d\n",
  36                     test_params[i].expected, test_params[i].rate,
  37                     test_params[i].bpp, pbn);
  38        }
  39
  40        return 0;
  41}
  42
  43static bool
  44sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
  45                       const struct drm_dp_sideband_msg_req_body *out)
  46{
  47        const struct drm_dp_remote_i2c_read_tx *txin, *txout;
  48        int i;
  49
  50        if (in->req_type != out->req_type)
  51                return false;
  52
  53        switch (in->req_type) {
  54        /*
  55         * Compare struct members manually for request types which can't be
  56         * compared simply using memcmp(). This is because said request types
  57         * contain pointers to other allocated structs
  58         */
  59        case DP_REMOTE_I2C_READ:
  60#define IN in->u.i2c_read
  61#define OUT out->u.i2c_read
  62                if (IN.num_bytes_read != OUT.num_bytes_read ||
  63                    IN.num_transactions != OUT.num_transactions ||
  64                    IN.port_number != OUT.port_number ||
  65                    IN.read_i2c_device_id != OUT.read_i2c_device_id)
  66                        return false;
  67
  68                for (i = 0; i < IN.num_transactions; i++) {
  69                        txin = &IN.transactions[i];
  70                        txout = &OUT.transactions[i];
  71
  72                        if (txin->i2c_dev_id != txout->i2c_dev_id ||
  73                            txin->no_stop_bit != txout->no_stop_bit ||
  74                            txin->num_bytes != txout->num_bytes ||
  75                            txin->i2c_transaction_delay !=
  76                            txout->i2c_transaction_delay)
  77                                return false;
  78
  79                        if (memcmp(txin->bytes, txout->bytes,
  80                                   txin->num_bytes) != 0)
  81                                return false;
  82                }
  83                break;
  84#undef IN
  85#undef OUT
  86
  87        case DP_REMOTE_DPCD_WRITE:
  88#define IN in->u.dpcd_write
  89#define OUT out->u.dpcd_write
  90                if (IN.dpcd_address != OUT.dpcd_address ||
  91                    IN.num_bytes != OUT.num_bytes ||
  92                    IN.port_number != OUT.port_number)
  93                        return false;
  94
  95                return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
  96#undef IN
  97#undef OUT
  98
  99        case DP_REMOTE_I2C_WRITE:
 100#define IN in->u.i2c_write
 101#define OUT out->u.i2c_write
 102                if (IN.port_number != OUT.port_number ||
 103                    IN.write_i2c_device_id != OUT.write_i2c_device_id ||
 104                    IN.num_bytes != OUT.num_bytes)
 105                        return false;
 106
 107                return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
 108#undef IN
 109#undef OUT
 110
 111        default:
 112                return memcmp(in, out, sizeof(*in)) == 0;
 113        }
 114
 115        return true;
 116}
 117
 118static bool
 119sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in)
 120{
 121        struct drm_dp_sideband_msg_req_body out = {0};
 122        struct drm_printer p = drm_err_printer(PREFIX_STR);
 123        struct drm_dp_sideband_msg_tx txmsg;
 124        int i, ret;
 125
 126        drm_dp_encode_sideband_req(in, &txmsg);
 127        ret = drm_dp_decode_sideband_req(&txmsg, &out);
 128        if (ret < 0) {
 129                drm_printf(&p, "Failed to decode sideband request: %d\n",
 130                           ret);
 131                return false;
 132        }
 133
 134        if (!sideband_msg_req_equal(in, &out)) {
 135                drm_printf(&p, "Encode/decode failed, expected:\n");
 136                drm_dp_dump_sideband_msg_req_body(in, 1, &p);
 137                drm_printf(&p, "Got:\n");
 138                drm_dp_dump_sideband_msg_req_body(&out, 1, &p);
 139                return false;
 140        }
 141
 142        switch (in->req_type) {
 143        case DP_REMOTE_DPCD_WRITE:
 144                kfree(out.u.dpcd_write.bytes);
 145                break;
 146        case DP_REMOTE_I2C_READ:
 147                for (i = 0; i < out.u.i2c_read.num_transactions; i++)
 148                        kfree(out.u.i2c_read.transactions[i].bytes);
 149                break;
 150        case DP_REMOTE_I2C_WRITE:
 151                kfree(out.u.i2c_write.bytes);
 152                break;
 153        }
 154
 155        /* Clear everything but the req_type for the input */
 156        memset(&in->u, 0, sizeof(in->u));
 157
 158        return true;
 159}
 160
 161int igt_dp_mst_sideband_msg_req_decode(void *unused)
 162{
 163        struct drm_dp_sideband_msg_req_body in = { 0 };
 164        u8 data[] = { 0xff, 0x0, 0xdd };
 165        int i;
 166
 167#define DO_TEST() FAIL_ON(!sideband_msg_req_encode_decode(&in))
 168
 169        in.req_type = DP_ENUM_PATH_RESOURCES;
 170        in.u.port_num.port_number = 5;
 171        DO_TEST();
 172
 173        in.req_type = DP_POWER_UP_PHY;
 174        in.u.port_num.port_number = 5;
 175        DO_TEST();
 176
 177        in.req_type = DP_POWER_DOWN_PHY;
 178        in.u.port_num.port_number = 5;
 179        DO_TEST();
 180
 181        in.req_type = DP_ALLOCATE_PAYLOAD;
 182        in.u.allocate_payload.number_sdp_streams = 3;
 183        for (i = 0; i < in.u.allocate_payload.number_sdp_streams; i++)
 184                in.u.allocate_payload.sdp_stream_sink[i] = i + 1;
 185        DO_TEST();
 186        in.u.allocate_payload.port_number = 0xf;
 187        DO_TEST();
 188        in.u.allocate_payload.vcpi = 0x7f;
 189        DO_TEST();
 190        in.u.allocate_payload.pbn = U16_MAX;
 191        DO_TEST();
 192
 193        in.req_type = DP_QUERY_PAYLOAD;
 194        in.u.query_payload.port_number = 0xf;
 195        DO_TEST();
 196        in.u.query_payload.vcpi = 0x7f;
 197        DO_TEST();
 198
 199        in.req_type = DP_REMOTE_DPCD_READ;
 200        in.u.dpcd_read.port_number = 0xf;
 201        DO_TEST();
 202        in.u.dpcd_read.dpcd_address = 0xfedcb;
 203        DO_TEST();
 204        in.u.dpcd_read.num_bytes = U8_MAX;
 205        DO_TEST();
 206
 207        in.req_type = DP_REMOTE_DPCD_WRITE;
 208        in.u.dpcd_write.port_number = 0xf;
 209        DO_TEST();
 210        in.u.dpcd_write.dpcd_address = 0xfedcb;
 211        DO_TEST();
 212        in.u.dpcd_write.num_bytes = ARRAY_SIZE(data);
 213        in.u.dpcd_write.bytes = data;
 214        DO_TEST();
 215
 216        in.req_type = DP_REMOTE_I2C_READ;
 217        in.u.i2c_read.port_number = 0xf;
 218        DO_TEST();
 219        in.u.i2c_read.read_i2c_device_id = 0x7f;
 220        DO_TEST();
 221        in.u.i2c_read.num_transactions = 3;
 222        in.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3;
 223        for (i = 0; i < in.u.i2c_read.num_transactions; i++) {
 224                in.u.i2c_read.transactions[i].bytes = data;
 225                in.u.i2c_read.transactions[i].num_bytes = ARRAY_SIZE(data);
 226                in.u.i2c_read.transactions[i].i2c_dev_id = 0x7f & ~i;
 227                in.u.i2c_read.transactions[i].i2c_transaction_delay = 0xf & ~i;
 228        }
 229        DO_TEST();
 230
 231        in.req_type = DP_REMOTE_I2C_WRITE;
 232        in.u.i2c_write.port_number = 0xf;
 233        DO_TEST();
 234        in.u.i2c_write.write_i2c_device_id = 0x7f;
 235        DO_TEST();
 236        in.u.i2c_write.num_bytes = ARRAY_SIZE(data);
 237        in.u.i2c_write.bytes = data;
 238        DO_TEST();
 239
 240#undef DO_TEST
 241        return 0;
 242}
 243