LCOV - code coverage report
Current view: top level - drivers/gpu/drm/tests - drm_dp_mst_helper_test.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 55 64 85.9 %
Date: 2023-07-19 18:55:55 Functions: 7 8 87.5 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  * Test cases for the DRM DP MST helpers
       4             :  *
       5             :  * Copyright (c) 2022 MaĆ­ra Canal <mairacanal@riseup.net>
       6             :  */
       7             : 
       8             : #include <kunit/test.h>
       9             : 
      10             : #include <drm/display/drm_dp_mst_helper.h>
      11             : #include <drm/drm_print.h>
      12             : 
      13             : #include "../display/drm_dp_mst_topology_internal.h"
      14             : 
      15             : struct drm_dp_mst_calc_pbn_mode_test {
      16             :         const int clock;
      17             :         const int bpp;
      18             :         const bool dsc;
      19             :         const int expected;
      20             : };
      21             : 
      22             : static const struct drm_dp_mst_calc_pbn_mode_test drm_dp_mst_calc_pbn_mode_cases[] = {
      23             :         {
      24             :                 .clock = 154000,
      25             :                 .bpp = 30,
      26             :                 .dsc = false,
      27             :                 .expected = 689
      28             :         },
      29             :         {
      30             :                 .clock = 234000,
      31             :                 .bpp = 30,
      32             :                 .dsc = false,
      33             :                 .expected = 1047
      34             :         },
      35             :         {
      36             :                 .clock = 297000,
      37             :                 .bpp = 24,
      38             :                 .dsc = false,
      39             :                 .expected = 1063
      40             :         },
      41             :         {
      42             :                 .clock = 332880,
      43             :                 .bpp = 24,
      44             :                 .dsc = true,
      45             :                 .expected = 50
      46             :         },
      47             :         {
      48             :                 .clock = 324540,
      49             :                 .bpp = 24,
      50             :                 .dsc = true,
      51             :                 .expected = 49
      52             :         },
      53             : };
      54             : 
      55           5 : static void drm_test_dp_mst_calc_pbn_mode(struct kunit *test)
      56             : {
      57           5 :         const struct drm_dp_mst_calc_pbn_mode_test *params = test->param_value;
      58             : 
      59           5 :         KUNIT_EXPECT_EQ(test, drm_dp_calc_pbn_mode(params->clock, params->bpp, params->dsc),
      60             :                         params->expected);
      61           5 : }
      62             : 
      63           5 : static void dp_mst_calc_pbn_mode_desc(const struct drm_dp_mst_calc_pbn_mode_test *t, char *desc)
      64             : {
      65           5 :         sprintf(desc, "Clock %d BPP %d DSC %s", t->clock, t->bpp, t->dsc ? "enabled" : "disabled");
      66           5 : }
      67             : 
      68           6 : KUNIT_ARRAY_PARAM(drm_dp_mst_calc_pbn_mode, drm_dp_mst_calc_pbn_mode_cases,
      69             :                   dp_mst_calc_pbn_mode_desc);
      70             : 
      71             : static u8 data[] = { 0xff, 0x00, 0xdd };
      72             : 
      73             : struct drm_dp_mst_sideband_msg_req_test {
      74             :         const char *desc;
      75             :         const struct drm_dp_sideband_msg_req_body in;
      76             : };
      77             : 
      78             : static const struct drm_dp_mst_sideband_msg_req_test drm_dp_mst_sideband_msg_req_cases[] = {
      79             :         {
      80             :                 .desc = "DP_ENUM_PATH_RESOURCES with port number",
      81             :                 .in = {
      82             :                         .req_type = DP_ENUM_PATH_RESOURCES,
      83             :                         .u.port_num.port_number = 5,
      84             :                 },
      85             :         },
      86             :         {
      87             :                 .desc = "DP_POWER_UP_PHY with port number",
      88             :                 .in = {
      89             :                         .req_type = DP_POWER_UP_PHY,
      90             :                         .u.port_num.port_number = 5,
      91             :                 },
      92             :         },
      93             :         {
      94             :                 .desc = "DP_POWER_DOWN_PHY with port number",
      95             :                 .in = {
      96             :                         .req_type = DP_POWER_DOWN_PHY,
      97             :                         .u.port_num.port_number = 5,
      98             :                 },
      99             :         },
     100             :         {
     101             :                 .desc = "DP_ALLOCATE_PAYLOAD with SDP stream sinks",
     102             :                 .in = {
     103             :                         .req_type = DP_ALLOCATE_PAYLOAD,
     104             :                         .u.allocate_payload.number_sdp_streams = 3,
     105             :                         .u.allocate_payload.sdp_stream_sink = { 1, 2, 3 },
     106             :                 },
     107             :         },
     108             :         {
     109             :                 .desc = "DP_ALLOCATE_PAYLOAD with port number",
     110             :                 .in = {
     111             :                         .req_type = DP_ALLOCATE_PAYLOAD,
     112             :                         .u.allocate_payload.port_number = 0xf,
     113             :                 },
     114             :         },
     115             :         {
     116             :                 .desc = "DP_ALLOCATE_PAYLOAD with VCPI",
     117             :                 .in = {
     118             :                         .req_type = DP_ALLOCATE_PAYLOAD,
     119             :                         .u.allocate_payload.vcpi = 0x7f,
     120             :                 },
     121             :         },
     122             :         {
     123             :                 .desc = "DP_ALLOCATE_PAYLOAD with PBN",
     124             :                 .in = {
     125             :                         .req_type = DP_ALLOCATE_PAYLOAD,
     126             :                         .u.allocate_payload.pbn = U16_MAX,
     127             :                 },
     128             :         },
     129             :         {
     130             :                 .desc = "DP_QUERY_PAYLOAD with port number",
     131             :                 .in = {
     132             :                         .req_type = DP_QUERY_PAYLOAD,
     133             :                         .u.query_payload.port_number = 0xf,
     134             :                 },
     135             :         },
     136             :         {
     137             :                 .desc = "DP_QUERY_PAYLOAD with VCPI",
     138             :                 .in = {
     139             :                         .req_type = DP_QUERY_PAYLOAD,
     140             :                         .u.query_payload.vcpi = 0x7f,
     141             :                 },
     142             :         },
     143             :         {
     144             :                 .desc = "DP_REMOTE_DPCD_READ with port number",
     145             :                 .in = {
     146             :                         .req_type = DP_REMOTE_DPCD_READ,
     147             :                         .u.dpcd_read.port_number = 0xf,
     148             :                 },
     149             :         },
     150             :         {
     151             :                 .desc = "DP_REMOTE_DPCD_READ with DPCD address",
     152             :                 .in = {
     153             :                         .req_type = DP_REMOTE_DPCD_READ,
     154             :                         .u.dpcd_read.dpcd_address = 0xfedcb,
     155             :                 },
     156             :         },
     157             :         {
     158             :                 .desc = "DP_REMOTE_DPCD_READ with max number of bytes",
     159             :                 .in = {
     160             :                         .req_type = DP_REMOTE_DPCD_READ,
     161             :                         .u.dpcd_read.num_bytes = U8_MAX,
     162             :                 },
     163             :         },
     164             :         {
     165             :                 .desc = "DP_REMOTE_DPCD_WRITE with port number",
     166             :                 .in = {
     167             :                         .req_type = DP_REMOTE_DPCD_WRITE,
     168             :                         .u.dpcd_write.port_number = 0xf,
     169             :                 },
     170             :         },
     171             :         {
     172             :                 .desc = "DP_REMOTE_DPCD_WRITE with DPCD address",
     173             :                 .in = {
     174             :                         .req_type = DP_REMOTE_DPCD_WRITE,
     175             :                         .u.dpcd_write.dpcd_address = 0xfedcb,
     176             :                 },
     177             :         },
     178             :         {
     179             :                 .desc = "DP_REMOTE_DPCD_WRITE with data array",
     180             :                 .in = {
     181             :                         .req_type = DP_REMOTE_DPCD_WRITE,
     182             :                         .u.dpcd_write.num_bytes = ARRAY_SIZE(data),
     183             :                         .u.dpcd_write.bytes = data,
     184             :                 },
     185             :         },
     186             :         {
     187             :                 .desc = "DP_REMOTE_I2C_READ with port number",
     188             :                 .in = {
     189             :                         .req_type = DP_REMOTE_I2C_READ,
     190             :                         .u.i2c_read.port_number = 0xf,
     191             :                 },
     192             :         },
     193             :         {
     194             :                 .desc = "DP_REMOTE_I2C_READ with I2C device ID",
     195             :                 .in = {
     196             :                         .req_type = DP_REMOTE_I2C_READ,
     197             :                         .u.i2c_read.read_i2c_device_id = 0x7f,
     198             :                 },
     199             :         },
     200             :         {
     201             :                 .desc = "DP_REMOTE_I2C_READ with transactions array",
     202             :                 .in = {
     203             :                         .req_type = DP_REMOTE_I2C_READ,
     204             :                         .u.i2c_read.num_transactions = 3,
     205             :                         .u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3,
     206             :                         .u.i2c_read.transactions = {
     207             :                                 { .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7f,
     208             :                                   .i2c_transaction_delay = 0xf, },
     209             :                                 { .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7e,
     210             :                                   .i2c_transaction_delay = 0xe, },
     211             :                                 { .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7d,
     212             :                                   .i2c_transaction_delay = 0xd, },
     213             :                         },
     214             :                 },
     215             :         },
     216             :         {
     217             :                 .desc = "DP_REMOTE_I2C_WRITE with port number",
     218             :                 .in = {
     219             :                         .req_type = DP_REMOTE_I2C_WRITE,
     220             :                         .u.i2c_write.port_number = 0xf,
     221             :                 },
     222             :         },
     223             :         {
     224             :                 .desc = "DP_REMOTE_I2C_WRITE with I2C device ID",
     225             :                 .in = {
     226             :                         .req_type = DP_REMOTE_I2C_WRITE,
     227             :                         .u.i2c_write.write_i2c_device_id = 0x7f,
     228             :                 },
     229             :         },
     230             :         {
     231             :                 .desc = "DP_REMOTE_I2C_WRITE with data array",
     232             :                 .in = {
     233             :                         .req_type = DP_REMOTE_I2C_WRITE,
     234             :                         .u.i2c_write.num_bytes = ARRAY_SIZE(data),
     235             :                         .u.i2c_write.bytes = data,
     236             :                 },
     237             :         },
     238             :         {
     239             :                 .desc = "DP_QUERY_STREAM_ENC_STATUS with stream ID",
     240             :                 .in = {
     241             :                         .req_type = DP_QUERY_STREAM_ENC_STATUS,
     242             :                         .u.enc_status.stream_id = 1,
     243             :                 },
     244             :         },
     245             :         {
     246             :                 .desc = "DP_QUERY_STREAM_ENC_STATUS with client ID",
     247             :                 .in = {
     248             :                         .req_type = DP_QUERY_STREAM_ENC_STATUS,
     249             :                         .u.enc_status.client_id = { 0x4f, 0x7f, 0xb4, 0x00, 0x8c, 0x0d, 0x67 },
     250             :                 },
     251             :         },
     252             :         {
     253             :                 .desc = "DP_QUERY_STREAM_ENC_STATUS with stream event",
     254             :                 .in = {
     255             :                         .req_type = DP_QUERY_STREAM_ENC_STATUS,
     256             :                         .u.enc_status.stream_event = 3,
     257             :                 },
     258             :         },
     259             :         {
     260             :                 .desc = "DP_QUERY_STREAM_ENC_STATUS with valid stream event",
     261             :                 .in = {
     262             :                         .req_type = DP_QUERY_STREAM_ENC_STATUS,
     263             :                         .u.enc_status.valid_stream_event = 0,
     264             :                 },
     265             :         },
     266             :         {
     267             :                 .desc = "DP_QUERY_STREAM_ENC_STATUS with stream behavior",
     268             :                 .in = {
     269             :                         .req_type = DP_QUERY_STREAM_ENC_STATUS,
     270             :                         .u.enc_status.stream_behavior = 3,
     271             :                 },
     272             :         },
     273             :         {
     274             :                 .desc = "DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior",
     275             :                 .in = {
     276             :                         .req_type = DP_QUERY_STREAM_ENC_STATUS,
     277             :                         .u.enc_status.valid_stream_behavior = 1,
     278             :                 }
     279             :         },
     280             : };
     281             : 
     282             : static bool
     283          27 : sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
     284             :                        const struct drm_dp_sideband_msg_req_body *out)
     285             : {
     286             :         const struct drm_dp_remote_i2c_read_tx *txin, *txout;
     287             :         int i;
     288             : 
     289          27 :         if (in->req_type != out->req_type)
     290             :                 return false;
     291             : 
     292          27 :         switch (in->req_type) {
     293             :         /*
     294             :          * Compare struct members manually for request types which can't be
     295             :          * compared simply using memcmp(). This is because said request types
     296             :          * contain pointers to other allocated structs
     297             :          */
     298             :         case DP_REMOTE_I2C_READ:
     299             : #define IN in->u.i2c_read
     300             : #define OUT out->u.i2c_read
     301           3 :                 if (IN.num_bytes_read != OUT.num_bytes_read ||
     302           3 :                     IN.num_transactions != OUT.num_transactions ||
     303           3 :                     IN.port_number != OUT.port_number ||
     304           3 :                     IN.read_i2c_device_id != OUT.read_i2c_device_id)
     305             :                         return false;
     306             : 
     307           3 :                 for (i = 0; i < IN.num_transactions; i++) {
     308           3 :                         txin = &IN.transactions[i];
     309           3 :                         txout = &OUT.transactions[i];
     310             : 
     311           6 :                         if (txin->i2c_dev_id != txout->i2c_dev_id ||
     312           6 :                             txin->no_stop_bit != txout->no_stop_bit ||
     313           6 :                             txin->num_bytes != txout->num_bytes ||
     314           3 :                             txin->i2c_transaction_delay !=
     315           3 :                             txout->i2c_transaction_delay)
     316             :                                 return false;
     317             : 
     318           3 :                         if (memcmp(txin->bytes, txout->bytes,
     319             :                                    txin->num_bytes) != 0)
     320             :                                 return false;
     321             :                 }
     322             :                 break;
     323             : #undef IN
     324             : #undef OUT
     325             : 
     326             :         case DP_REMOTE_DPCD_WRITE:
     327             : #define IN in->u.dpcd_write
     328             : #define OUT out->u.dpcd_write
     329           6 :                 if (IN.dpcd_address != OUT.dpcd_address ||
     330           6 :                     IN.num_bytes != OUT.num_bytes ||
     331           3 :                     IN.port_number != OUT.port_number)
     332             :                         return false;
     333             : 
     334           3 :                 return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
     335             : #undef IN
     336             : #undef OUT
     337             : 
     338             :         case DP_REMOTE_I2C_WRITE:
     339             : #define IN in->u.i2c_write
     340             : #define OUT out->u.i2c_write
     341           3 :                 if (IN.port_number != OUT.port_number ||
     342           3 :                     IN.write_i2c_device_id != OUT.write_i2c_device_id ||
     343             :                     IN.num_bytes != OUT.num_bytes)
     344             :                         return false;
     345             : 
     346           3 :                 return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
     347             : #undef IN
     348             : #undef OUT
     349             : 
     350             :         default:
     351          18 :                 return memcmp(in, out, sizeof(*in)) == 0;
     352             :         }
     353             : 
     354             :         return true;
     355             : }
     356             : 
     357           0 : static void drm_test_dp_mst_msg_printf(struct drm_printer *p, struct va_format *vaf)
     358             : {
     359           0 :         struct kunit *test = p->arg;
     360             : 
     361           0 :         kunit_err(test, "%pV", vaf);
     362           0 : }
     363             : 
     364          27 : static void drm_test_dp_mst_sideband_msg_req_decode(struct kunit *test)
     365             : {
     366          27 :         const struct drm_dp_mst_sideband_msg_req_test *params = test->param_value;
     367          27 :         const struct drm_dp_sideband_msg_req_body *in = &params->in;
     368             :         struct drm_dp_sideband_msg_req_body *out;
     369             :         struct drm_dp_sideband_msg_tx *txmsg;
     370          27 :         struct drm_printer p = {
     371             :                 .printfn = drm_test_dp_mst_msg_printf,
     372             :                 .arg = test
     373             :         };
     374             :         int i;
     375             : 
     376          27 :         out = kunit_kzalloc(test, sizeof(*out), GFP_KERNEL);
     377          27 :         KUNIT_ASSERT_NOT_NULL(test, out);
     378             : 
     379          27 :         txmsg = kunit_kzalloc(test, sizeof(*txmsg), GFP_KERNEL);
     380          27 :         KUNIT_ASSERT_NOT_NULL(test, txmsg);
     381             : 
     382          27 :         drm_dp_encode_sideband_req(in, txmsg);
     383          27 :         KUNIT_EXPECT_GE_MSG(test, drm_dp_decode_sideband_req(txmsg, out), 0,
     384             :                             "Failed to decode sideband request");
     385             : 
     386          27 :         if (!sideband_msg_req_equal(in, out)) {
     387           0 :                 KUNIT_FAIL(test, "Encode/decode failed");
     388           0 :                 kunit_err(test, "Expected:");
     389           0 :                 drm_dp_dump_sideband_msg_req_body(in, 1, &p);
     390           0 :                 kunit_err(test, "Got:");
     391           0 :                 drm_dp_dump_sideband_msg_req_body(out, 1, &p);
     392             :         }
     393             : 
     394          27 :         switch (in->req_type) {
     395             :         case DP_REMOTE_DPCD_WRITE:
     396           3 :                 kfree(out->u.dpcd_write.bytes);
     397           3 :                 break;
     398             :         case DP_REMOTE_I2C_READ:
     399           3 :                 for (i = 0; i < out->u.i2c_read.num_transactions; i++)
     400           3 :                         kfree(out->u.i2c_read.transactions[i].bytes);
     401             :                 break;
     402             :         case DP_REMOTE_I2C_WRITE:
     403           3 :                 kfree(out->u.i2c_write.bytes);
     404           3 :                 break;
     405             :         }
     406          27 : }
     407             : 
     408             : static void
     409          27 : drm_dp_mst_sideband_msg_req_desc(const struct drm_dp_mst_sideband_msg_req_test *t, char *desc)
     410             : {
     411          27 :         strcpy(desc, t->desc);
     412          27 : }
     413             : 
     414          28 : KUNIT_ARRAY_PARAM(drm_dp_mst_sideband_msg_req, drm_dp_mst_sideband_msg_req_cases,
     415             :                   drm_dp_mst_sideband_msg_req_desc);
     416             : 
     417             : static struct kunit_case drm_dp_mst_helper_tests[] = {
     418             :         KUNIT_CASE_PARAM(drm_test_dp_mst_calc_pbn_mode, drm_dp_mst_calc_pbn_mode_gen_params),
     419             :         KUNIT_CASE_PARAM(drm_test_dp_mst_sideband_msg_req_decode,
     420             :                          drm_dp_mst_sideband_msg_req_gen_params),
     421             :         { }
     422             : };
     423             : 
     424             : static struct kunit_suite drm_dp_mst_helper_test_suite = {
     425             :         .name = "drm_dp_mst_helper",
     426             :         .test_cases = drm_dp_mst_helper_tests,
     427             : };
     428             : 
     429             : kunit_test_suite(drm_dp_mst_helper_test_suite);
     430             : 
     431             : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.14