]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.4.56/drm-radeon-fix-endian-issues-with-dp-handling-v3.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.4.56 / drm-radeon-fix-endian-issues-with-dp-handling-v3.patch
CommitLineData
2e3322ac
GKH
1From 34be8c9af7b8728465963740fc11136ae90dfc36 Mon Sep 17 00:00:00 2001
2From: Alex Deucher <alexander.deucher@amd.com>
3Date: Thu, 18 Jul 2013 11:13:53 -0400
4Subject: drm/radeon: fix endian issues with DP handling (v3)
5
6From: Alex Deucher <alexander.deucher@amd.com>
7
8commit 34be8c9af7b8728465963740fc11136ae90dfc36 upstream.
9
10The atom interpreter expects data in LE format, so
11swap the message buffer as apprioriate.
12
13v2: properly handle non-dw aligned byte counts.
14v3: properly handle remainder
15
16Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
17Cc: Dong He <hedonghust@gmail.com>
18Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
19
20---
21 drivers/gpu/drm/radeon/atombios_dp.c | 43 +++++++++++++++++++++++++++++++----
22 1 file changed, 39 insertions(+), 4 deletions(-)
23
24--- a/drivers/gpu/drm/radeon/atombios_dp.c
25+++ b/drivers/gpu/drm/radeon/atombios_dp.c
26@@ -45,6 +45,41 @@ static char *pre_emph_names[] = {
27 };
28
29 /***** radeon AUX functions *****/
30+
31+/* Atom needs data in little endian format
32+ * so swap as appropriate when copying data to
33+ * or from atom. Note that atom operates on
34+ * dw units.
35+ */
36+static void radeon_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le)
37+{
38+#ifdef __BIG_ENDIAN
39+ u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */
40+ u32 *dst32, *src32;
41+ int i;
42+
43+ memcpy(src_tmp, src, num_bytes);
44+ src32 = (u32 *)src_tmp;
45+ dst32 = (u32 *)dst_tmp;
46+ if (to_le) {
47+ for (i = 0; i < ((num_bytes + 3) / 4); i++)
48+ dst32[i] = cpu_to_le32(src32[i]);
49+ memcpy(dst, dst_tmp, num_bytes);
50+ } else {
51+ u8 dws = num_bytes & ~3;
52+ for (i = 0; i < ((num_bytes + 3) / 4); i++)
53+ dst32[i] = le32_to_cpu(src32[i]);
54+ memcpy(dst, dst_tmp, dws);
55+ if (num_bytes % 4) {
56+ for (i = 0; i < (num_bytes % 4); i++)
57+ dst[dws+i] = dst_tmp[dws+i];
58+ }
59+ }
60+#else
61+ memcpy(dst, src, num_bytes);
62+#endif
63+}
64+
65 union aux_channel_transaction {
66 PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1;
67 PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2;
68@@ -66,10 +101,10 @@ static int radeon_process_aux_ch(struct
69
70 base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);
71
72- memcpy(base, send, send_bytes);
73+ radeon_copy_swap(base, send, send_bytes, true);
74
75- args.v1.lpAuxRequest = 0 + 4;
76- args.v1.lpDataOut = 16 + 4;
77+ args.v1.lpAuxRequest = cpu_to_le16((u16)(0 + 4));
78+ args.v1.lpDataOut = cpu_to_le16((u16)(16 + 4));
79 args.v1.ucDataOutLen = 0;
80 args.v1.ucChannelID = chan->rec.i2c_id;
81 args.v1.ucDelay = delay / 10;
82@@ -103,7 +138,7 @@ static int radeon_process_aux_ch(struct
83 recv_bytes = recv_size;
84
85 if (recv && recv_size)
86- memcpy(recv, base + 16, recv_bytes);
87+ radeon_copy_swap(recv, base + 16, recv_bytes, false);
88
89 return recv_bytes;
90 }