File Index
Files and directories
Sign in
FILE

dc_fused_io.c

File preview with syntax highlighting.

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