Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34be8c9a authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/radeon: fix endian issues with DP handling (v3)



The atom interpreter expects data in LE format, so
swap the message buffer as apprioriate.

v2: properly handle non-dw aligned byte counts.
v3: properly handle remainder

Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Cc: Dong He <hedonghust@gmail.com>
Cc: stable@vger.kernel.org
parent 3e3e53f8
Loading
Loading
Loading
Loading
+39 −4
Original line number Original line Diff line number Diff line
@@ -44,6 +44,41 @@ static char *pre_emph_names[] = {
};
};


/***** radeon AUX functions *****/
/***** radeon AUX functions *****/

/* Atom needs data in little endian format
 * so swap as appropriate when copying data to
 * or from atom. Note that atom operates on
 * dw units.
 */
static void radeon_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le)
{
#ifdef __BIG_ENDIAN
	u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */
	u32 *dst32, *src32;
	int i;

	memcpy(src_tmp, src, num_bytes);
	src32 = (u32 *)src_tmp;
	dst32 = (u32 *)dst_tmp;
	if (to_le) {
		for (i = 0; i < ((num_bytes + 3) / 4); i++)
			dst32[i] = cpu_to_le32(src32[i]);
		memcpy(dst, dst_tmp, num_bytes);
	} else {
		u8 dws = num_bytes & ~3;
		for (i = 0; i < ((num_bytes + 3) / 4); i++)
			dst32[i] = le32_to_cpu(src32[i]);
		memcpy(dst, dst_tmp, dws);
		if (num_bytes % 4) {
			for (i = 0; i < (num_bytes % 4); i++)
				dst[dws+i] = dst_tmp[dws+i];
		}
	}
#else
	memcpy(dst, src, num_bytes);
#endif
}

union aux_channel_transaction {
union aux_channel_transaction {
	PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1;
	PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1;
	PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2;
	PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2;
@@ -65,10 +100,10 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,


	base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);
	base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);


	memcpy(base, send, send_bytes);
	radeon_copy_swap(base, send, send_bytes, true);


	args.v1.lpAuxRequest = 0 + 4;
	args.v1.lpAuxRequest = cpu_to_le16((u16)(0 + 4));
	args.v1.lpDataOut = 16 + 4;
	args.v1.lpDataOut = cpu_to_le16((u16)(16 + 4));
	args.v1.ucDataOutLen = 0;
	args.v1.ucDataOutLen = 0;
	args.v1.ucChannelID = chan->rec.i2c_id;
	args.v1.ucChannelID = chan->rec.i2c_id;
	args.v1.ucDelay = delay / 10;
	args.v1.ucDelay = delay / 10;
@@ -102,7 +137,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
		recv_bytes = recv_size;
		recv_bytes = recv_size;


	if (recv && recv_size)
	if (recv && recv_size)
		memcpy(recv, base + 16, recv_bytes);
		radeon_copy_swap(recv, base + 16, recv_bytes, false);


	return recv_bytes;
	return recv_bytes;
}
}