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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
// SPDX-License-Identifier: MIT
//
// Copyright 2025 Advanced Micro Devices, Inc.
#include "dc_fused_io.h"
#include "dm_helpers.h"
#include "gpio.h"
static bool op_i2c_convert(
union dmub_rb_cmd *cmd,
const struct mod_hdcp_atomic_op_i2c *op,
enum dmub_cmd_fused_request_type type,
uint32_t ddc_line,
bool over_aux
)
{
struct dmub_cmd_fused_request *req = &cmd->fused_io.request;
struct dmub_cmd_fused_request_location_i2c *loc = &req->u.i2c;
if (!op || op->size > sizeof(req->buffer))
return false;
req->type = type;
loc->is_aux = false;
loc->ddc_line = ddc_line;
loc->over_aux = over_aux;
loc->address = op->address;
loc->offset = op->offset;
loc->length = op->size;
memcpy(req->buffer, op->data, op->size);
return true;
}
static bool op_aux_convert(
union dmub_rb_cmd *cmd,
const struct mod_hdcp_atomic_op_aux *op,
enum dmub_cmd_fused_request_type type,
uint32_t ddc_line
)
{
struct dmub_cmd_fused_request *req = &cmd->fused_io.request;
struct dmub_cmd_fused_request_location_aux *loc = &req->u.aux;
if (!op || op->size > sizeof(req->buffer))
return false;
req->type = type;
loc->is_aux = true;
loc->ddc_line = ddc_line;
loc->address = op->address;
loc->length = op->size;
memcpy(req->buffer, op->data, op->size);
return true;
}
static bool atomic_write_poll_read(
struct dc_link *link,
union dmub_rb_cmd commands[3],
uint32_t poll_timeout_us,
uint8_t poll_mask_msb
)
{
const uint8_t count = 3;
const uint32_t timeout_per_request_us = 10000;
const uint32_t timeout_per_aux_transaction_us = 10000;
uint64_t timeout_us = 0;
commands[1].fused_io.request.poll_mask_msb = poll_mask_msb;
commands[1].fused_io.request.timeout_us = poll_timeout_us;
for (uint8_t i = 0; i < count; i++) {
struct dmub_rb_cmd_fused_io *io = &commands[i].fused_io;
io->header.type = DMUB_CMD__FUSED_IO;
io->header.sub_type = DMUB_CMD__FUSED_IO_EXECUTE;
io->header.multi_cmd_pending = i != count - 1;
io->header.payload_bytes = sizeof(commands[i].fused_io) - sizeof(io->header);
timeout_us += timeout_per_request_us + io->request.timeout_us;
if (!io->request.timeout_us && io->request.u.aux.is_aux)
timeout_us += timeout_per_aux_transaction_us * (io->request.u.aux.length / 16);
}
if (!dm_helpers_execute_fused_io(link->ctx, link, commands, count, timeout_us))
return false;
return commands[0].fused_io.request.status == FUSED_REQUEST_STATUS_SUCCESS;
}
bool dm_atomic_write_poll_read_i2c(
struct dc_link *link,
const struct mod_hdcp_atomic_op_i2c *write,
const struct mod_hdcp_atomic_op_i2c *poll,
struct mod_hdcp_atomic_op_i2c *read,
uint32_t poll_timeout_us,
uint8_t poll_mask_msb
)
{
if (!link)
return false;
const bool over_aux = false;
const uint32_t ddc_line = link->ddc->ddc_pin->pin_data->en;
union dmub_rb_cmd commands[3] = { 0 };
const bool converted = op_i2c_convert(&commands[0], write, FUSED_REQUEST_WRITE, ddc_line, over_aux)
&& op_i2c_convert(&commands[1], poll, FUSED_REQUEST_POLL, ddc_line, over_aux)
&& op_i2c_convert(&commands[2], read, FUSED_REQUEST_READ, ddc_line, over_aux);
if (!converted)
return false;
const bool result = atomic_write_poll_read(link, commands, poll_timeout_us, poll_mask_msb);
memcpy(read->data, commands[0].fused_io.request.buffer, read->size);
return result;
}
bool dm_atomic_write_poll_read_aux(
struct dc_link *link,
const struct mod_hdcp_atomic_op_aux *write,
const struct mod_hdcp_atomic_op_aux *poll,
struct mod_hdcp_atomic_op_aux *read,
uint32_t poll_timeout_us,
uint8_t poll_mask_msb
)
{
if (!link)
return false;
const uint32_t ddc_line = link->ddc->ddc_pin->pin_data->en;
union dmub_rb_cmd commands[3] = { 0 };
const bool converted = op_aux_convert(&commands[0], write, FUSED_REQUEST_WRITE, ddc_line)
&& op_aux_convert(&commands[1], poll, FUSED_REQUEST_POLL, ddc_line)
&& op_aux_convert(&commands[2], read, FUSED_REQUEST_READ, ddc_line);
if (!converted)
return false;
const bool result = atomic_write_poll_read(link, commands, poll_timeout_us, poll_mask_msb);
memcpy(read->data, commands[0].fused_io.request.buffer, read->size);
return result;
}
|