Commit f258fee6 authored by David Francis's avatar David Francis Committed by Alex Deucher
Browse files

drm/amd/display: Add debugfs dpcd interface



[Why]
We need arbitrary read/write over DP AUX DPCD
for debugging

[How]
Three debugfs entries

Set the target address by writing to
"aux_dpcd_address"
(The first four bytes written are used)

Set the transaction size in bytes by writing to
"aux_dpcd_size"
(The first four bytes written are used)

Start a transaction by reading/writing
"aux_dpcd_data"

Do note: there is no concerrency protection at all
Accessing these entries in quick succession can lead
to strange behaviour

Signed-off-by: default avatarDavid Francis <David.Francis@amd.com>
Reviewed-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c7ba3653
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -4395,6 +4395,8 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
		DRM_ERROR("Failed to create debugfs for connector");
		goto out_free;
	}
	aconnector->debugfs_dpcd_address = 0;
	aconnector->debugfs_dpcd_size = 0;
#endif

	if (connector_type == DRM_MODE_CONNECTOR_DisplayPort
+4 −0
Original line number Diff line number Diff line
@@ -238,6 +238,10 @@ struct amdgpu_dm_connector {
	struct mutex hpd_lock;

	bool fake_enable;
#ifdef CONFIG_DEBUG_FS
	uint32_t debugfs_dpcd_address;
	uint32_t debugfs_dpcd_size;
#endif
};

#define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base)
+106 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include "amdgpu.h"
#include "amdgpu_dm.h"
#include "amdgpu_dm_debugfs.h"
#include "dm_helpers.h"

/* function description
 * get/ set DP configuration: lane_count, link_rate, spread_spectrum
@@ -731,6 +732,88 @@ static ssize_t dp_sdp_message_debugfs_write(struct file *f, const char __user *b

DEFINE_SHOW_ATTRIBUTE(vrr_range);

static ssize_t dp_dpcd_address_write(struct file *f, const char __user *buf,
				 size_t size, loff_t *pos)
{
	int r;
	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;

	if (size < sizeof(connector->debugfs_dpcd_address))
		return 0;

	r = copy_from_user(&connector->debugfs_dpcd_address,
			buf, sizeof(connector->debugfs_dpcd_address));

	return size - r;
}

static ssize_t dp_dpcd_size_write(struct file *f, const char __user *buf,
				 size_t size, loff_t *pos)
{
	int r;
	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;

	if (size < sizeof(connector->debugfs_dpcd_size))
		return 0;

	r = copy_from_user(&connector->debugfs_dpcd_size,
			buf, sizeof(connector->debugfs_dpcd_size));

	if (connector->debugfs_dpcd_size > 256)
		connector->debugfs_dpcd_size = 0;

	return size - r;
}

static ssize_t dp_dpcd_data_write(struct file *f, const char __user *buf,
				 size_t size, loff_t *pos)
{
	int r;
	char *data;
	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
	struct dc_link *link = connector->dc_link;
	uint32_t write_size = connector->debugfs_dpcd_size;

	if (size < write_size)
		return 0;

	data = kzalloc(write_size, GFP_KERNEL);
	if (!data)
		return 0;

	r = copy_from_user(data, buf, write_size);

	dm_helpers_dp_write_dpcd(link->ctx, link,
			connector->debugfs_dpcd_address, data, write_size - r);
	kfree(data);
	return write_size - r;
}

static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf,
				 size_t size, loff_t *pos)
{
	int r;
	char *data;
	struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
	struct dc_link *link = connector->dc_link;
	uint32_t read_size = connector->debugfs_dpcd_size;

	if (size < read_size)
		return 0;

	data = kzalloc(read_size, GFP_KERNEL);
	if (!data)
		return 0;

	dm_helpers_dp_read_dpcd(link->ctx, link,
			connector->debugfs_dpcd_address, data, read_size);

	r = copy_to_user(buf, data, read_size);

	kfree(data);
	return read_size - r;
}

static const struct file_operations dp_link_settings_debugfs_fops = {
	.owner = THIS_MODULE,
	.read = dp_link_settings_read,
@@ -757,6 +840,25 @@ static const struct file_operations sdp_message_fops = {
	.llseek = default_llseek
};

static const struct file_operations dp_dpcd_address_debugfs_fops = {
	.owner = THIS_MODULE,
	.write = dp_dpcd_address_write,
	.llseek = default_llseek
};

static const struct file_operations dp_dpcd_size_debugfs_fops = {
	.owner = THIS_MODULE,
	.write = dp_dpcd_size_write,
	.llseek = default_llseek
};

static const struct file_operations dp_dpcd_data_debugfs_fops = {
	.owner = THIS_MODULE,
	.read = dp_dpcd_data_read,
	.write = dp_dpcd_data_write,
	.llseek = default_llseek
};

static const struct {
	char *name;
	const struct file_operations *fops;
@@ -765,7 +867,10 @@ static const struct {
		{"phy_settings", &dp_phy_settings_debugfs_fop},
		{"test_pattern", &dp_phy_test_pattern_fops},
		{"vrr_range", &vrr_range_fops},
		{"sdp_message", &sdp_message_fops}
		{"sdp_message", &sdp_message_fops},
		{"aux_dpcd_address", &dp_dpcd_address_debugfs_fops},
		{"aux_dpcd_size", &dp_dpcd_size_debugfs_fops},
		{"aux_dpcd_data", &dp_dpcd_data_debugfs_fops}
};

int connector_debugfs_init(struct amdgpu_dm_connector *connector)