1 // SPDX-License-Identifier: MIT 2 // 3 // Copyright 2025 Advanced Micro Devices, Inc. 4 5 #include "dc_fused_io.h" 6 7 #include "dm_helpers.h" 8 #include "gpio.h" 9 10 static bool op_i2c_convert( 11 union dmub_rb_cmd *cmd, 12 const struct mod_hdcp_atomic_op_i2c *op, 13 enum dmub_cmd_fused_request_type type, 14 uint32_t ddc_line 15 ) 16 { 17 struct dmub_cmd_fused_request *req = &cmd->fused_io.request; 18 struct dmub_cmd_fused_request_location_i2c *loc = &req->u.i2c; 19 20 if (!op || op->size > sizeof(req->buffer)) 21 return false; 22 23 req->type = type; 24 loc->is_aux = false; 25 loc->ddc_line = ddc_line; 26 loc->address = op->address; 27 loc->offset = op->offset; 28 loc->length = op->size; 29 memcpy(req->buffer, op->data, op->size); 30 31 return true; 32 } 33 34 static bool op_aux_convert( 35 union dmub_rb_cmd *cmd, 36 const struct mod_hdcp_atomic_op_aux *op, 37 enum dmub_cmd_fused_request_type type, 38 uint32_t ddc_line 39 ) 40 { 41 struct dmub_cmd_fused_request *req = &cmd->fused_io.request; 42 struct dmub_cmd_fused_request_location_aux *loc = &req->u.aux; 43 44 if (!op || op->size > sizeof(req->buffer)) 45 return false; 46 47 req->type = type; 48 loc->is_aux = true; 49 loc->ddc_line = ddc_line; 50 loc->address = op->address; 51 loc->length = op->size; 52 memcpy(req->buffer, op->data, op->size); 53 54 return true; 55 } 56 57 static bool atomic_write_poll_read( 58 struct dc_link *link, 59 union dmub_rb_cmd commands[3], 60 uint32_t poll_timeout_us, 61 uint8_t poll_mask_msb 62 ) 63 { 64 const uint8_t count = 3; 65 const uint32_t timeout_per_request_us = 10000; 66 const uint32_t timeout_per_aux_transaction_us = 10000; 67 uint64_t timeout_us = 0; 68 69 commands[1].fused_io.request.poll_mask_msb = poll_mask_msb; 70 commands[1].fused_io.request.timeout_us = poll_timeout_us; 71 72 for (uint8_t i = 0; i < count; i++) { 73 struct dmub_rb_cmd_fused_io *io = &commands[i].fused_io; 74 75 io->header.type = DMUB_CMD__FUSED_IO; 76 io->header.sub_type = DMUB_CMD__FUSED_IO_EXECUTE; 77 io->header.multi_cmd_pending = i != count - 1; 78 io->header.payload_bytes = sizeof(commands[i].fused_io) - sizeof(io->header); 79 80 timeout_us += timeout_per_request_us + io->request.timeout_us; 81 if (!io->request.timeout_us && io->request.u.aux.is_aux) 82 timeout_us += timeout_per_aux_transaction_us * (io->request.u.aux.length / 16); 83 } 84 85 if (!dm_helpers_execute_fused_io(link->ctx, link, commands, count, timeout_us)) 86 return false; 87 88 return commands[0].fused_io.request.status == FUSED_REQUEST_STATUS_SUCCESS; 89 } 90 91 bool dm_atomic_write_poll_read_i2c( 92 struct dc_link *link, 93 const struct mod_hdcp_atomic_op_i2c *write, 94 const struct mod_hdcp_atomic_op_i2c *poll, 95 struct mod_hdcp_atomic_op_i2c *read, 96 uint32_t poll_timeout_us, 97 uint8_t poll_mask_msb 98 ) 99 { 100 if (!link) 101 return false; 102 103 const uint32_t ddc_line = link->ddc->ddc_pin->pin_data->en; 104 union dmub_rb_cmd commands[3] = { 0 }; 105 const bool converted = op_i2c_convert(&commands[0], write, FUSED_REQUEST_WRITE, ddc_line) 106 && op_i2c_convert(&commands[1], poll, FUSED_REQUEST_POLL, ddc_line) 107 && op_i2c_convert(&commands[2], read, FUSED_REQUEST_READ, ddc_line); 108 109 if (!converted) 110 return false; 111 112 const bool result = atomic_write_poll_read(link, commands, poll_timeout_us, poll_mask_msb); 113 114 memcpy(read->data, commands[0].fused_io.request.buffer, read->size); 115 return result; 116 } 117 118 bool dm_atomic_write_poll_read_aux( 119 struct dc_link *link, 120 const struct mod_hdcp_atomic_op_aux *write, 121 const struct mod_hdcp_atomic_op_aux *poll, 122 struct mod_hdcp_atomic_op_aux *read, 123 uint32_t poll_timeout_us, 124 uint8_t poll_mask_msb 125 ) 126 { 127 if (!link) 128 return false; 129 130 const uint32_t ddc_line = link->ddc->ddc_pin->pin_data->en; 131 union dmub_rb_cmd commands[3] = { 0 }; 132 const bool converted = op_aux_convert(&commands[0], write, FUSED_REQUEST_WRITE, ddc_line) 133 && op_aux_convert(&commands[1], poll, FUSED_REQUEST_POLL, ddc_line) 134 && op_aux_convert(&commands[2], read, FUSED_REQUEST_READ, ddc_line); 135 136 if (!converted) 137 return false; 138 139 const bool result = atomic_write_poll_read(link, commands, poll_timeout_us, poll_mask_msb); 140 141 memcpy(read->data, commands[0].fused_io.request.buffer, read->size); 142 return result; 143 } 144 145