diff options
Diffstat (limited to 'meta-steppeeagle/recipes-kernel/linux/linux-yocto/0000-yocto-amd-drm-radeon-backport-support-from-kernel-version-3.12.10.patch')
-rw-r--r-- | meta-steppeeagle/recipes-kernel/linux/linux-yocto/0000-yocto-amd-drm-radeon-backport-support-from-kernel-version-3.12.10.patch | 780 |
1 files changed, 780 insertions, 0 deletions
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0000-yocto-amd-drm-radeon-backport-support-from-kernel-version-3.12.10.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0000-yocto-amd-drm-radeon-backport-support-from-kernel-version-3.12.10.patch new file mode 100644 index 00000000..8540cbf0 --- /dev/null +++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0000-yocto-amd-drm-radeon-backport-support-from-kernel-version-3.12.10.patch @@ -0,0 +1,780 @@ +This single patch is a backport from kernel version 3.12.10 to kernel version +3.12. This lays the ground for the next set of patches which had been created +on top of 3.12.10. + +Signed-off-by: Arindam Nath <arindam.nath@amd.com> +diff -Naur a/drivers/acpi/bus.c b/drivers/acpi/bus.c +--- a/drivers/acpi/bus.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/acpi/bus.c 2014-04-03 02:38:06.049166833 +0530 +@@ -156,6 +156,16 @@ + } + EXPORT_SYMBOL(acpi_bus_get_private_data); + ++void acpi_bus_no_hotplug(acpi_handle handle) ++{ ++ struct acpi_device *adev = NULL; ++ ++ acpi_bus_get_device(handle, &adev); ++ if (adev) ++ adev->flags.no_hotplug = true; ++} ++EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug); ++ + static void acpi_print_osc_error(acpi_handle handle, + struct acpi_osc_context *context, char *error) + { +diff -Naur a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c +--- a/drivers/gpu/drm/radeon/atombios_crtc.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c 2014-04-03 01:45:50.161111970 +0530 +@@ -1180,23 +1180,18 @@ + fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1); + + if (rdev->family >= CHIP_BONAIRE) { +- u32 num_pipe_configs = rdev->config.cik.max_tile_pipes; +- u32 num_rb = rdev->config.cik.max_backends_per_se; +- if (num_pipe_configs > 8) +- num_pipe_configs = 8; +- if (num_pipe_configs == 8) +- fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P8_32x32_16x16); +- else if (num_pipe_configs == 4) { +- if (num_rb == 4) +- fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_16x16); +- else if (num_rb < 4) +- fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_8x16); +- } else if (num_pipe_configs == 2) +- fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P2); ++ /* Read the pipe config from the 2D TILED SCANOUT mode. ++ * It should be the same for the other modes too, but not all ++ * modes set the pipe config field. */ ++ u32 pipe_config = (rdev->config.cik.tile_mode_array[10] >> 6) & 0x1f; ++ ++ fb_format |= CIK_GRPH_PIPE_CONFIG(pipe_config); + } else if ((rdev->family == CHIP_TAHITI) || + (rdev->family == CHIP_PITCAIRN)) + fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16); +- else if (rdev->family == CHIP_VERDE) ++ else if ((rdev->family == CHIP_VERDE) || ++ (rdev->family == CHIP_OLAND) || ++ (rdev->family == CHIP_HAINAN)) /* for completeness. HAINAN has no display hw */ + fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16); + + switch (radeon_crtc->crtc_id) { +@@ -1753,7 +1748,7 @@ + if (pll != ATOM_PPLL_INVALID) + return pll; + } +- } else { ++ } else if (!ASIC_IS_DCE41(rdev)) { /* Don't share PLLs on DCE4.1 chips */ + /* use the same PPLL for all monitors with the same clock */ + pll = radeon_get_shared_nondp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) +diff -Naur a/drivers/gpu/drm/radeon/atombios_i2c.c b/drivers/gpu/drm/radeon/atombios_i2c.c +--- a/drivers/gpu/drm/radeon/atombios_i2c.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/atombios_i2c.c 2014-04-03 01:45:50.161111970 +0530 +@@ -44,7 +44,7 @@ + PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args; + int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction); + unsigned char *base; +- u16 out; ++ u16 out = cpu_to_le16(0); + + memset(&args, 0, sizeof(args)); + +@@ -55,9 +55,14 @@ + DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num); + return -EINVAL; + } +- args.ucRegIndex = buf[0]; +- if (num > 1) +- memcpy(&out, &buf[1], num - 1); ++ if (buf == NULL) ++ args.ucRegIndex = 0; ++ else ++ args.ucRegIndex = buf[0]; ++ if (num) ++ num--; ++ if (num) ++ memcpy(&out, &buf[1], num); + args.lpI2CDataOut = cpu_to_le16(out); + } else { + if (num > ATOM_MAX_HW_I2C_READ) { +@@ -94,14 +99,14 @@ + struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap); + struct i2c_msg *p; + int i, remaining, current_count, buffer_offset, max_bytes, ret; +- u8 buf = 0, flags; ++ u8 flags; + + /* check for bus probe */ + p = &msgs[0]; + if ((num == 1) && (p->len == 0)) { + ret = radeon_process_i2c_ch(i2c, + p->addr, HW_I2C_WRITE, +- &buf, 1); ++ NULL, 0); + if (ret) + return ret; + else +diff -Naur a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c +--- a/drivers/gpu/drm/radeon/cik.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/cik.c 2014-04-03 01:45:50.165111971 +0530 +@@ -2608,7 +2608,7 @@ + * Returns the disabled RB bitmask. + */ + static u32 cik_get_rb_disabled(struct radeon_device *rdev, +- u32 max_rb_num, u32 se_num, ++ u32 max_rb_num_per_se, + u32 sh_per_se) + { + u32 data, mask; +@@ -2622,7 +2622,7 @@ + + data >>= BACKEND_DISABLE_SHIFT; + +- mask = cik_create_bitmask(max_rb_num / se_num / sh_per_se); ++ mask = cik_create_bitmask(max_rb_num_per_se / sh_per_se); + + return data & mask; + } +@@ -2639,7 +2639,7 @@ + */ + static void cik_setup_rb(struct radeon_device *rdev, + u32 se_num, u32 sh_per_se, +- u32 max_rb_num) ++ u32 max_rb_num_per_se) + { + int i, j; + u32 data, mask; +@@ -2649,19 +2649,21 @@ + for (i = 0; i < se_num; i++) { + for (j = 0; j < sh_per_se; j++) { + cik_select_se_sh(rdev, i, j); +- data = cik_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se); ++ data = cik_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se); + disabled_rbs |= data << ((i * sh_per_se + j) * CIK_RB_BITMAP_WIDTH_PER_SH); + } + } + cik_select_se_sh(rdev, 0xffffffff, 0xffffffff); + + mask = 1; +- for (i = 0; i < max_rb_num; i++) { ++ for (i = 0; i < max_rb_num_per_se * se_num; i++) { + if (!(disabled_rbs & mask)) + enabled_rbs |= mask; + mask <<= 1; + } + ++ rdev->config.cik.backend_enable_mask = enabled_rbs; ++ + for (i = 0; i < se_num; i++) { + cik_select_se_sh(rdev, i, 0xffffffff); + data = 0; +diff -Naur a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c +--- a/drivers/gpu/drm/radeon/cik_sdma.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/cik_sdma.c 2014-04-03 01:45:50.169111972 +0530 +@@ -468,7 +468,7 @@ + radeon_ring_write(ring, 0); /* src/dst endian swap */ + radeon_ring_write(ring, src_offset & 0xffffffff); + radeon_ring_write(ring, upper_32_bits(src_offset) & 0xffffffff); +- radeon_ring_write(ring, dst_offset & 0xfffffffc); ++ radeon_ring_write(ring, dst_offset & 0xffffffff); + radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xffffffff); + src_offset += cur_size_in_bytes; + dst_offset += cur_size_in_bytes; +diff -Naur a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c +--- a/drivers/gpu/drm/radeon/dce6_afmt.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/dce6_afmt.c 2014-04-03 01:45:50.169111972 +0530 +@@ -132,7 +132,7 @@ + } + + sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb); +- if (sad_count < 0) { ++ if (sad_count <= 0) { + DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); + return; + } +@@ -193,7 +193,7 @@ + } + + sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); +- if (sad_count < 0) { ++ if (sad_count <= 0) { + DRM_ERROR("Couldn't read SADs: %d\n", sad_count); + return; + } +diff -Naur a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c +--- a/drivers/gpu/drm/radeon/evergreen_hdmi.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c 2014-04-03 01:45:50.169111972 +0530 +@@ -81,7 +81,7 @@ + } + + sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb); +- if (sad_count < 0) { ++ if (sad_count <= 0) { + DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count); + return; + } +@@ -134,7 +134,7 @@ + } + + sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); +- if (sad_count < 0) { ++ if (sad_count <= 0) { + DRM_ERROR("Couldn't read SADs: %d\n", sad_count); + return; + } +diff -Naur a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c +--- a/drivers/gpu/drm/radeon/ni.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/ni.c 2014-04-03 01:45:50.169111972 +0530 +@@ -900,6 +900,10 @@ + (rdev->pdev->device == 0x999C)) { + rdev->config.cayman.max_simds_per_se = 6; + rdev->config.cayman.max_backends_per_se = 2; ++ rdev->config.cayman.max_hw_contexts = 8; ++ rdev->config.cayman.sx_max_export_size = 256; ++ rdev->config.cayman.sx_max_export_pos_size = 64; ++ rdev->config.cayman.sx_max_export_smx_size = 192; + } else if ((rdev->pdev->device == 0x9903) || + (rdev->pdev->device == 0x9904) || + (rdev->pdev->device == 0x990A) || +@@ -910,6 +914,10 @@ + (rdev->pdev->device == 0x999D)) { + rdev->config.cayman.max_simds_per_se = 4; + rdev->config.cayman.max_backends_per_se = 2; ++ rdev->config.cayman.max_hw_contexts = 8; ++ rdev->config.cayman.sx_max_export_size = 256; ++ rdev->config.cayman.sx_max_export_pos_size = 64; ++ rdev->config.cayman.sx_max_export_smx_size = 192; + } else if ((rdev->pdev->device == 0x9919) || + (rdev->pdev->device == 0x9990) || + (rdev->pdev->device == 0x9991) || +@@ -920,9 +928,17 @@ + (rdev->pdev->device == 0x99A0)) { + rdev->config.cayman.max_simds_per_se = 3; + rdev->config.cayman.max_backends_per_se = 1; ++ rdev->config.cayman.max_hw_contexts = 4; ++ rdev->config.cayman.sx_max_export_size = 128; ++ rdev->config.cayman.sx_max_export_pos_size = 32; ++ rdev->config.cayman.sx_max_export_smx_size = 96; + } else { + rdev->config.cayman.max_simds_per_se = 2; + rdev->config.cayman.max_backends_per_se = 1; ++ rdev->config.cayman.max_hw_contexts = 4; ++ rdev->config.cayman.sx_max_export_size = 128; ++ rdev->config.cayman.sx_max_export_pos_size = 32; ++ rdev->config.cayman.sx_max_export_smx_size = 96; + } + rdev->config.cayman.max_texture_channel_caches = 2; + rdev->config.cayman.max_gprs = 256; +@@ -930,10 +946,6 @@ + rdev->config.cayman.max_gs_threads = 32; + rdev->config.cayman.max_stack_entries = 512; + rdev->config.cayman.sx_num_of_sets = 8; +- rdev->config.cayman.sx_max_export_size = 256; +- rdev->config.cayman.sx_max_export_pos_size = 64; +- rdev->config.cayman.sx_max_export_smx_size = 192; +- rdev->config.cayman.max_hw_contexts = 8; + rdev->config.cayman.sq_num_cf_insts = 2; + + rdev->config.cayman.sc_prim_fifo_size = 0x40; +diff -Naur a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c +--- a/drivers/gpu/drm/radeon/r600_hdmi.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/r600_hdmi.c 2014-04-03 01:45:50.169111972 +0530 +@@ -24,6 +24,7 @@ + * Authors: Christian König + */ + #include <linux/hdmi.h> ++#include <linux/gcd.h> + #include <drm/drmP.h> + #include <drm/radeon_drm.h> + #include "radeon.h" +@@ -57,35 +58,57 @@ + static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { + /* 32kHz 44.1kHz 48kHz */ + /* Clock N CTS N CTS N CTS */ +- { 25175, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ ++ { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */ + { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ + { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ + { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ + { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ + { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ +- { 74176, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ ++ { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */ + { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ +- { 148352, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ ++ { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */ + { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ +- { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */ + }; + ++ + /* +- * calculate CTS value if it's not found in the table ++ * calculate CTS and N values if they are not found in the table + */ +-static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq) ++static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq) + { +- u64 n; +- u32 d; ++ int n, cts; ++ unsigned long div, mul; + +- if (*CTS == 0) { +- n = (u64)clock * (u64)N * 1000ULL; +- d = 128 * freq; +- do_div(n, d); +- *CTS = n; +- } +- DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n", +- N, *CTS, freq); ++ /* Safe, but overly large values */ ++ n = 128 * freq; ++ cts = clock * 1000; ++ ++ /* Smallest valid fraction */ ++ div = gcd(n, cts); ++ ++ n /= div; ++ cts /= div; ++ ++ /* ++ * The optimal N is 128*freq/1000. Calculate the closest larger ++ * value that doesn't truncate any bits. ++ */ ++ mul = ((128*freq/1000) + (n-1))/n; ++ ++ n *= mul; ++ cts *= mul; ++ ++ /* Check that we are in spec (not always possible) */ ++ if (n < (128*freq/1500)) ++ printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n"); ++ if (n > (128*freq/300)) ++ printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n"); ++ ++ *N = n; ++ *CTS = cts; ++ ++ DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n", ++ *N, *CTS, freq); + } + + struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock) +@@ -93,15 +116,16 @@ + struct radeon_hdmi_acr res; + u8 i; + +- for (i = 0; r600_hdmi_predefined_acr[i].clock != clock && +- r600_hdmi_predefined_acr[i].clock != 0; i++) +- ; +- res = r600_hdmi_predefined_acr[i]; +- +- /* In case some CTS are missing */ +- r600_hdmi_calc_cts(clock, &res.cts_32khz, res.n_32khz, 32000); +- r600_hdmi_calc_cts(clock, &res.cts_44_1khz, res.n_44_1khz, 44100); +- r600_hdmi_calc_cts(clock, &res.cts_48khz, res.n_48khz, 48000); ++ /* Precalculated values for common clocks */ ++ for (i = 0; i < ARRAY_SIZE(r600_hdmi_predefined_acr); i++) { ++ if (r600_hdmi_predefined_acr[i].clock == clock) ++ return r600_hdmi_predefined_acr[i]; ++ } ++ ++ /* And odd clocks get manually calculated */ ++ r600_hdmi_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000); ++ r600_hdmi_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100); ++ r600_hdmi_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000); + + return res; + } +@@ -280,9 +304,9 @@ + WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo); + WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ + } +- } else if (ASIC_IS_DCE3(rdev)) { ++ } else { + /* according to the reg specs, this should DCE3.2 only, but in +- * practice it seems to cover DCE3.0/3.1 as well. ++ * practice it seems to cover DCE2.0/3.0/3.1 as well. + */ + if (dig->dig_encoder == 0) { + WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100); +@@ -293,10 +317,6 @@ + WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100); + WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */ + } +- } else { +- /* according to the reg specs, this should be DCE2.0 and DCE3.0/3.1 */ +- WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) | +- AUDIO_DTO_MODULE(clock / 10)); + } + } + +diff -Naur a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c +--- a/drivers/gpu/drm/radeon/radeon_asic.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/radeon_asic.c 2014-04-03 01:45:50.173111972 +0530 +@@ -2019,6 +2019,8 @@ + .bandwidth_update = &dce8_bandwidth_update, + .get_vblank_counter = &evergreen_get_vblank_counter, + .wait_for_vblank = &dce4_wait_for_vblank, ++ .set_backlight_level = &atombios_set_backlight_level, ++ .get_backlight_level = &atombios_get_backlight_level, + .hdmi_enable = &evergreen_hdmi_enable, + .hdmi_setmode = &evergreen_hdmi_setmode, + }, +@@ -2119,6 +2121,8 @@ + .bandwidth_update = &dce8_bandwidth_update, + .get_vblank_counter = &evergreen_get_vblank_counter, + .wait_for_vblank = &dce4_wait_for_vblank, ++ .set_backlight_level = &atombios_set_backlight_level, ++ .get_backlight_level = &atombios_get_backlight_level, + .hdmi_enable = &evergreen_hdmi_enable, + .hdmi_setmode = &evergreen_hdmi_setmode, + }, +diff -Naur a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c +--- a/drivers/gpu/drm/radeon/radeon_atombios.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c 2014-04-03 01:45:50.173111972 +0530 +@@ -2918,7 +2918,7 @@ + mpll_param->dll_speed = args.ucDllSpeed; + mpll_param->bwcntl = args.ucBWCntl; + mpll_param->vco_mode = +- (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK) ? 1 : 0; ++ (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK); + mpll_param->yclk_sel = + (args.ucPllCntlFlag & MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0; + mpll_param->qdr = +diff -Naur a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c +--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c 2014-04-03 01:45:50.173111972 +0530 +@@ -34,6 +34,7 @@ + bool atpx_detected; + /* handle for device - and atpx */ + acpi_handle dhandle; ++ acpi_handle other_handle; + struct radeon_atpx atpx; + } radeon_atpx_priv; + +@@ -448,9 +449,10 @@ + return false; + + status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); +- if (ACPI_FAILURE(status)) ++ if (ACPI_FAILURE(status)) { ++ radeon_atpx_priv.other_handle = dhandle; + return false; +- ++ } + radeon_atpx_priv.dhandle = dhandle; + radeon_atpx_priv.atpx.handle = atpx_handle; + return true; +@@ -527,6 +529,16 @@ + printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", + acpi_method_name); + radeon_atpx_priv.atpx_detected = true; ++ /* ++ * On some systems hotplug events are generated for the device ++ * being switched off when ATPX is executed. They cause ACPI ++ * hotplug to trigger and attempt to remove the device from ++ * the system, which causes it to break down. Prevent that from ++ * happening by setting the no_hotplug flag for the involved ++ * ACPI device objects. ++ */ ++ acpi_bus_no_hotplug(radeon_atpx_priv.dhandle); ++ acpi_bus_no_hotplug(radeon_atpx_priv.other_handle); + return true; + } + return false; +diff -Naur a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c +--- a/drivers/gpu/drm/radeon/radeon_gart.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/radeon_gart.c 2014-04-03 01:45:50.173111972 +0530 +@@ -1156,6 +1156,8 @@ + return -ENOMEM; + + r = radeon_ib_get(rdev, ridx, &ib, NULL, ndw * 4); ++ if (r) ++ return r; + ib.length_dw = 0; + + r = radeon_vm_update_pdes(rdev, vm, &ib, bo_va->soffset, bo_va->eoffset); +diff -Naur a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h +--- a/drivers/gpu/drm/radeon/radeon.h 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/radeon.h 2014-04-03 01:45:50.177111972 +0530 +@@ -1930,7 +1930,7 @@ + unsigned sc_earlyz_tile_fifo_size; + + unsigned num_tile_pipes; +- unsigned num_backends_per_se; ++ unsigned backend_enable_mask; + unsigned backend_disable_mask_per_asic; + unsigned backend_map; + unsigned num_texture_channel_caches; +@@ -1960,7 +1960,7 @@ + unsigned sc_earlyz_tile_fifo_size; + + unsigned num_tile_pipes; +- unsigned num_backends_per_se; ++ unsigned backend_enable_mask; + unsigned backend_disable_mask_per_asic; + unsigned backend_map; + unsigned num_texture_channel_caches; +diff -Naur a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c +--- a/drivers/gpu/drm/radeon/radeon_kms.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/radeon_kms.c 2014-04-03 01:45:50.177111972 +0530 +@@ -436,6 +436,15 @@ + case RADEON_INFO_SI_CP_DMA_COMPUTE: + *value = 1; + break; ++ case RADEON_INFO_SI_BACKEND_ENABLED_MASK: ++ if (rdev->family >= CHIP_BONAIRE) { ++ *value = rdev->config.cik.backend_enable_mask; ++ } else if (rdev->family >= CHIP_TAHITI) { ++ *value = rdev->config.si.backend_enable_mask; ++ } else { ++ DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n"); ++ } ++ break; + default: + DRM_DEBUG_KMS("Invalid request %d\n", info->request); + return -EINVAL; +diff -Naur a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c 2014-04-03 01:45:50.181111972 +0530 +@@ -422,6 +422,7 @@ + /* Pin framebuffer & get tilling informations */ + obj = radeon_fb->obj; + rbo = gem_to_radeon_bo(obj); ++retry: + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) + return r; +@@ -430,6 +431,33 @@ + &base); + if (unlikely(r != 0)) { + radeon_bo_unreserve(rbo); ++ ++ /* On old GPU like RN50 with little vram pining can fails because ++ * current fb is taking all space needed. So instead of unpining ++ * the old buffer after pining the new one, first unpin old one ++ * and then retry pining new one. ++ * ++ * As only master can set mode only master can pin and it is ++ * unlikely the master client will race with itself especialy ++ * on those old gpu with single crtc. ++ * ++ * We don't shutdown the display controller because new buffer ++ * will end up in same spot. ++ */ ++ if (!atomic && fb && fb != crtc->fb) { ++ struct radeon_bo *old_rbo; ++ unsigned long nsize, osize; ++ ++ old_rbo = gem_to_radeon_bo(to_radeon_framebuffer(fb)->obj); ++ osize = radeon_bo_size(old_rbo); ++ nsize = radeon_bo_size(rbo); ++ if (nsize <= osize && !radeon_bo_reserve(old_rbo, false)) { ++ radeon_bo_unpin(old_rbo); ++ radeon_bo_unreserve(old_rbo); ++ fb = NULL; ++ goto retry; ++ } ++ } + return -EINVAL; + } + radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); +diff -Naur a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c +--- a/drivers/gpu/drm/radeon/radeon_uvd.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/radeon_uvd.c 2014-04-03 01:45:50.181111972 +0530 +@@ -240,6 +240,8 @@ + if (handle != 0 && rdev->uvd.filp[i] == filp) { + struct radeon_fence *fence; + ++ radeon_uvd_note_usage(rdev); ++ + r = radeon_uvd_get_destroy_msg(rdev, + R600_RING_TYPE_UVD_INDEX, handle, &fence); + if (r) { +@@ -470,7 +472,7 @@ + return -EINVAL; + } + +- if ((start >> 28) != (end >> 28)) { ++ if ((start >> 28) != ((end - 1) >> 28)) { + DRM_ERROR("reloc %LX-%LX crossing 256MB boundary!\n", + start, end); + return -EINVAL; +@@ -620,7 +622,7 @@ + if (r) + goto err; + +- r = radeon_ib_get(rdev, ring, &ib, NULL, 16); ++ r = radeon_ib_get(rdev, ring, &ib, NULL, 64); + if (r) + goto err; + +diff -Naur a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c +--- a/drivers/gpu/drm/radeon/rs690.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/rs690.c 2014-04-03 01:45:50.181111972 +0530 +@@ -162,6 +162,16 @@ + base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); + base = G_000100_MC_FB_START(base) << 16; + rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); ++ /* Some boards seem to be configured for 128MB of sideport memory, ++ * but really only have 64MB. Just skip the sideport and use ++ * UMA memory. ++ */ ++ if (rdev->mc.igp_sideport_enabled && ++ (rdev->mc.real_vram_size == (384 * 1024 * 1024))) { ++ base += 128 * 1024 * 1024; ++ rdev->mc.real_vram_size -= 128 * 1024 * 1024; ++ rdev->mc.mc_vram_size = rdev->mc.real_vram_size; ++ } + + /* Use K8 direct mapping for fast fb access. */ + rdev->fastfb_working = false; +diff -Naur a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c +--- a/drivers/gpu/drm/radeon/rv770_dpm.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/rv770_dpm.c 2014-04-03 01:45:50.185111972 +0530 +@@ -2328,6 +2328,12 @@ + pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss, + ASIC_INTERNAL_MEMORY_SS, 0); + ++ /* disable ss, causes hangs on some cayman boards */ ++ if (rdev->family == CHIP_CAYMAN) { ++ pi->sclk_ss = false; ++ pi->mclk_ss = false; ++ } ++ + if (pi->sclk_ss || pi->mclk_ss) + pi->dynamic_ss = true; + else +diff -Naur a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c +--- a/drivers/gpu/drm/radeon/si.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/si.c 2014-04-03 01:45:50.189111972 +0530 +@@ -2816,7 +2816,7 @@ + } + + static u32 si_get_rb_disabled(struct radeon_device *rdev, +- u32 max_rb_num, u32 se_num, ++ u32 max_rb_num_per_se, + u32 sh_per_se) + { + u32 data, mask; +@@ -2830,14 +2830,14 @@ + + data >>= BACKEND_DISABLE_SHIFT; + +- mask = si_create_bitmask(max_rb_num / se_num / sh_per_se); ++ mask = si_create_bitmask(max_rb_num_per_se / sh_per_se); + + return data & mask; + } + + static void si_setup_rb(struct radeon_device *rdev, + u32 se_num, u32 sh_per_se, +- u32 max_rb_num) ++ u32 max_rb_num_per_se) + { + int i, j; + u32 data, mask; +@@ -2847,19 +2847,21 @@ + for (i = 0; i < se_num; i++) { + for (j = 0; j < sh_per_se; j++) { + si_select_se_sh(rdev, i, j); +- data = si_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se); ++ data = si_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se); + disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH); + } + } + si_select_se_sh(rdev, 0xffffffff, 0xffffffff); + + mask = 1; +- for (i = 0; i < max_rb_num; i++) { ++ for (i = 0; i < max_rb_num_per_se * se_num; i++) { + if (!(disabled_rbs & mask)) + enabled_rbs |= mask; + mask <<= 1; + } + ++ rdev->config.si.backend_enable_mask = enabled_rbs; ++ + for (i = 0; i < se_num; i++) { + si_select_se_sh(rdev, i, 0xffffffff); + data = 0; +@@ -3887,8 +3889,15 @@ + rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); + rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); + /* size in MB on si */ +- rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; +- rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; ++ tmp = RREG32(CONFIG_MEMSIZE); ++ /* some boards may have garbage in the upper 16 bits */ ++ if (tmp & 0xffff0000) { ++ DRM_INFO("Probable bad vram size: 0x%08x\n", tmp); ++ if (tmp & 0xffff) ++ tmp &= 0xffff; ++ } ++ rdev->mc.mc_vram_size = tmp * 1024ULL * 1024ULL; ++ rdev->mc.real_vram_size = rdev->mc.mc_vram_size; + rdev->mc.visible_vram_size = rdev->mc.aper_size; + si_vram_gtt_location(rdev, &rdev->mc); + radeon_update_bandwidth_info(rdev); +diff -Naur a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h +--- a/drivers/gpu/drm/radeon/sid.h 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/sid.h 2014-04-03 01:45:50.189111972 +0530 +@@ -478,7 +478,7 @@ + #define STATE3_MASK (0x1f << 15) + #define STATE3_SHIFT 15 + +-#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x2808 ++#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x28e8 + #define TRAIN_DONE_D0 (1 << 30) + #define TRAIN_DONE_D1 (1 << 31) + +diff -Naur a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c +--- a/drivers/gpu/drm/radeon/trinity_dpm.c 2013-11-04 05:11:51.000000000 +0530 ++++ b/drivers/gpu/drm/radeon/trinity_dpm.c 2014-04-03 01:45:50.193111972 +0530 +@@ -1873,9 +1873,9 @@ + pi->enable_sclk_ds = true; + pi->enable_gfx_power_gating = true; + pi->enable_gfx_clock_gating = true; +- pi->enable_mg_clock_gating = true; +- pi->enable_gfx_dynamic_mgpg = true; /* ??? */ +- pi->override_dynamic_mgpg = true; ++ pi->enable_mg_clock_gating = false; ++ pi->enable_gfx_dynamic_mgpg = false; ++ pi->override_dynamic_mgpg = false; + pi->enable_auto_thermal_throttling = true; + pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */ + pi->uvd_dpm = true; /* ??? */ +diff -Naur a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h +--- a/include/acpi/acpi_bus.h 2013-11-04 05:11:51.000000000 +0530 ++++ b/include/acpi/acpi_bus.h 2014-04-03 02:41:15.381170177 +0530 +@@ -168,6 +168,7 @@ + u32 ejectable:1; + u32 power_manageable:1; + u32 match_driver:1; ++ u32 no_hotplug:1; + u32 reserved:27; + }; + +@@ -356,6 +357,7 @@ + extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int); + void acpi_bus_private_data_handler(acpi_handle, void *); + int acpi_bus_get_private_data(acpi_handle, void **); ++void acpi_bus_no_hotplug(acpi_handle handle); + extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); + extern int register_acpi_notifier(struct notifier_block *); + extern int unregister_acpi_notifier(struct notifier_block *); +diff -Naur a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h +--- a/include/uapi/drm/radeon_drm.h 2013-11-04 05:11:51.000000000 +0530 ++++ b/include/uapi/drm/radeon_drm.h 2014-04-03 02:30:27.125158815 +0530 +@@ -981,6 +981,8 @@ + #define RADEON_INFO_SI_TILE_MODE_ARRAY 0x16 + /* query if CP DMA is supported on the compute ring */ + #define RADEON_INFO_SI_CP_DMA_COMPUTE 0x17 ++/* query the number of render backends */ ++#define RADEON_INFO_SI_BACKEND_ENABLED_MASK 0x19 + + + struct drm_radeon_info { |