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