diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2014-02-10 00:02:57 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2014-02-10 00:02:57 +0000 |
commit | b8601c2d33f64ea9399dad8c4059119a4c845c2c (patch) | |
tree | bc73f13c19e539c1a0933cfbf9bb1bbead6a7386 /sys/dev/pci/drm | |
parent | 70f9ff5a6d25598932cb4e9d34c61e493bfcc5fa (diff) |
drm/radeon: fix endian issues with DP handling (v3)
From Alex Deucher
65a57d9cbf80a90856ba53e6cee8bfd69f0fc90a in ubuntu 3.8
34be8c9af7b8728465963740fc11136ae90dfc36 in mainline linux
Diffstat (limited to 'sys/dev/pci/drm')
-rw-r--r-- | sys/dev/pci/drm/radeon/atombios_dp.c | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/sys/dev/pci/drm/radeon/atombios_dp.c b/sys/dev/pci/drm/radeon/atombios_dp.c index f7542343c81..50e01eb0f96 100644 --- a/sys/dev/pci/drm/radeon/atombios_dp.c +++ b/sys/dev/pci/drm/radeon/atombios_dp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atombios_dp.c,v 1.1 2013/08/12 04:11:53 jsg Exp $ */ +/* $OpenBSD: atombios_dp.c,v 1.2 2014/02/10 00:02:56 jsg Exp $ */ /* * Copyright 2007-8 Advanced Micro Devices, Inc. * Copyright 2008 Red Hat Inc. @@ -47,6 +47,41 @@ static char *pre_emph_names[] = { #endif /***** 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 { PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; @@ -68,10 +103,10 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, 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.lpDataOut = 16 + 4; + args.v1.lpAuxRequest = cpu_to_le16((u16)(0 + 4)); + args.v1.lpDataOut = cpu_to_le16((u16)(16 + 4)); args.v1.ucDataOutLen = 0; args.v1.ucChannelID = chan->rec.i2c_id; args.v1.ucDelay = delay / 10; @@ -105,7 +140,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, recv_bytes = recv_size; if (recv && recv_size) - memcpy(recv, base + 16, recv_bytes); + radeon_copy_swap(recv, base + 16, recv_bytes, false); return recv_bytes; } |