aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu
diff options
context:
space:
mode:
authorRoman Kapl <rka@sysgo.com>2017-10-30 06:56:13 -0400
committerAlex Deucher <alexander.deucher@amd.com>2017-10-31 18:24:59 -0400
commit4f626a4ac8f57ddabf06d03870adab91e463217f (patch)
tree96f38adcabc68d8934f4235ebe7bf77f6db400c3 /drivers/gpu/drm/amd/amdgpu
parentbbb4d8d9ee81714b98c25df39a1ed90fa075e90a (diff)
drm/radeon: fix atombios on big endian
The function for byteswapping the data send to/from atombios was buggy for num_bytes not divisible by four. The function must be aware of the fact that after byte-swapping the u32 units, valid bytes might end up after the num_bytes boundary. This patch was tested on kernel 3.12 and allowed us to sucesfully use DisplayPort on and Radeon SI card. Namely it fixed the link training and EDID readout. The function is patched both in radeon and amd drivers, since the functions and the fixes are identical. Signed-off-by: Roman Kapl <rka@sysgo.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c38
1 files changed, 18 insertions, 20 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
index f66d33e4baca..f450b69323fa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -1766,34 +1766,32 @@ bool amdgpu_atombios_scratch_need_asic_init(struct amdgpu_device *adev)
1766 return true; 1766 return true;
1767} 1767}
1768 1768
1769/* Atom needs data in little endian format 1769/* Atom needs data in little endian format so swap as appropriate when copying
1770 * so swap as appropriate when copying data to 1770 * data to or from atom. Note that atom operates on dw units.
1771 * or from atom. Note that atom operates on 1771 *
1772 * dw units. 1772 * Use to_le=true when sending data to atom and provide at least
1773 * ALIGN(num_bytes,4) bytes in the dst buffer.
1774 *
1775 * Use to_le=false when receiving data from atom and provide ALIGN(num_bytes,4)
1776 * byes in the src buffer.
1773 */ 1777 */
1774void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le) 1778void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le)
1775{ 1779{
1776#ifdef __BIG_ENDIAN 1780#ifdef __BIG_ENDIAN
1777 u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */ 1781 u32 src_tmp[5], dst_tmp[5];
1778 u32 *dst32, *src32;
1779 int i; 1782 int i;
1783 u8 align_num_bytes = ALIGN(num_bytes, 4);
1780 1784
1781 memcpy(src_tmp, src, num_bytes);
1782 src32 = (u32 *)src_tmp;
1783 dst32 = (u32 *)dst_tmp;
1784 if (to_le) { 1785 if (to_le) {
1785 for (i = 0; i < ((num_bytes + 3) / 4); i++) 1786 memcpy(src_tmp, src, num_bytes);
1786 dst32[i] = cpu_to_le32(src32[i]); 1787 for (i = 0; i < align_num_bytes / 4; i++)
1787 memcpy(dst, dst_tmp, num_bytes); 1788 dst_tmp[i] = cpu_to_le32(src_tmp[i]);
1789 memcpy(dst, dst_tmp, align_num_bytes);
1788 } else { 1790 } else {
1789 u8 dws = num_bytes & ~3; 1791 memcpy(src_tmp, src, align_num_bytes);
1790 for (i = 0; i < ((num_bytes + 3) / 4); i++) 1792 for (i = 0; i < align_num_bytes / 4; i++)
1791 dst32[i] = le32_to_cpu(src32[i]); 1793 dst_tmp[i] = le32_to_cpu(src_tmp[i]);
1792 memcpy(dst, dst_tmp, dws); 1794 memcpy(dst, dst_tmp, num_bytes);
1793 if (num_bytes % 4) {
1794 for (i = 0; i < (num_bytes % 4); i++)
1795 dst[dws+i] = dst_tmp[dws+i];
1796 }
1797 } 1795 }
1798#else 1796#else
1799 memcpy(dst, src, num_bytes); 1797 memcpy(dst, src, num_bytes);