]>
Commit | Line | Data |
---|---|---|
2e3322ac GKH |
1 | From 34be8c9af7b8728465963740fc11136ae90dfc36 Mon Sep 17 00:00:00 2001 |
2 | From: Alex Deucher <alexander.deucher@amd.com> | |
3 | Date: Thu, 18 Jul 2013 11:13:53 -0400 | |
4 | Subject: drm/radeon: fix endian issues with DP handling (v3) | |
5 | ||
6 | From: Alex Deucher <alexander.deucher@amd.com> | |
7 | ||
8 | commit 34be8c9af7b8728465963740fc11136ae90dfc36 upstream. | |
9 | ||
10 | The atom interpreter expects data in LE format, so | |
11 | swap the message buffer as apprioriate. | |
12 | ||
13 | v2: properly handle non-dw aligned byte counts. | |
14 | v3: properly handle remainder | |
15 | ||
16 | Signed-off-by: Alex Deucher <alexander.deucher@amd.com> | |
17 | Cc: Dong He <hedonghust@gmail.com> | |
18 | Signed-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 | } |