xref: /linux/drivers/gpu/drm/amd/display/dc/dc_fused_io.c (revision b08494a8f7416e5f09907318c5460ad6f6e2a548)
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