Merge tag 'drm-fixes-2018-11-23' of git://anongit.freedesktop.org/drm/drm
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 23 Nov 2018 18:03:08 +0000 (10:03 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 23 Nov 2018 18:03:08 +0000 (10:03 -0800)
Pull drm fixes from Dave Airlie:
 "Regular drm fixes:

  amdgpu:
   - Vega20 fixes
   - firmware loading fix
   - panel display fix
   - override fix

  i915:
   - Sandybridge lockup fix
   - fastboot DSI panel fix
   - GPU hang on Broxton
   - GPU reloc fixes on pineview/bearlake

  ast:
   - screen blurring fix
   - cursor appearance fix

  udmabuf:
   - mmap fix

  vc4:
   - NULL deref fix
   - async cursor update fix

  All seems pretty normal at this stage"

* tag 'drm-fixes-2018-11-23' of git://anongit.freedesktop.org/drm/drm:
  drm/ast: fixed cursor may disappear sometimes
  drm/ast: change resolution may cause screen blurred
  drm/i915: Add rotation readout for plane initial config
  drm/i915: Force a LUT update in intel_initial_commit()
  drm/fb-helper: Blacklist writeback when adding connectors to fbdev
  drm/i915: Write GPU relocs harder with gen3
  drm/amdgpu: Enable HDP memory light sleep
  drm/i915: Prevent machine hang from Broxton's vtd w/a and error capture
  drm/amd/pp: handle negative values when reading OD
  drm/amdgpu: Add missing firmware entry for HAINAN
  drm/amd/powerplay: disable Vega20 DS related features
  drm/amdgpu: Fix oops when pp_funcs->switch_power_profile is unset
  drm/i915: Disable LP3 watermarks on all SNB machines
  drm/ast: Remove existing framebuffers before loading driver
  udmabuf: set read/write flag when exporting
  drm/amd/display: Support amdgpu "max bpc" connector property (v2)
  drm/amdgpu: Add amdgpu "max bpc" connector property (v2)
  drm/vc4: Set ->legacy_cursor_update to false when doing non-async updates
  drm/vc4: Fix NULL pointer dereference in the async update path

24 files changed:
drivers/dma-buf/udmabuf.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/ast/ast_drv.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_gpu_error.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/vc4/vc4_kms.c
drivers/gpu/drm/vc4/vc4_plane.c

index 5b44ef226904f9be2530b992c3d06ed338dca53c..fc359ca4503d127fda5f9f631f95d98c4a1d671a 100644 (file)
@@ -184,6 +184,7 @@ static long udmabuf_create(const struct udmabuf_create_list *head,
        exp_info.ops  = &udmabuf_ops;
        exp_info.size = ubuf->pagecount << PAGE_SHIFT;
        exp_info.priv = ubuf;
+       exp_info.flags = O_RDWR;
 
        buf = dma_buf_export(&exp_info);
        if (IS_ERR(buf)) {
index c31a8849e9f87705ed3abac2ac23bfcbc7303d85..1580ec60b89f753ce2e12018b2a07eb936802d2e 100644 (file)
@@ -501,8 +501,11 @@ void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
 
-       amdgpu_dpm_switch_power_profile(adev,
-                                       PP_SMC_POWER_PROFILE_COMPUTE, !idle);
+       if (adev->powerplay.pp_funcs &&
+           adev->powerplay.pp_funcs->switch_power_profile)
+               amdgpu_dpm_switch_power_profile(adev,
+                                               PP_SMC_POWER_PROFILE_COMPUTE,
+                                               !idle);
 }
 
 bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid)
index 6748cd7fc129b0e7b83966da865f674c676c04e1..686a26de50f91e816471548bf3c1a0fc3f86db86 100644 (file)
@@ -626,6 +626,13 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev)
                                         "dither",
                                         amdgpu_dither_enum_list, sz);
 
+       if (amdgpu_device_has_dc_support(adev)) {
+               adev->mode_info.max_bpc_property =
+                       drm_property_create_range(adev->ddev, 0, "max bpc", 8, 16);
+               if (!adev->mode_info.max_bpc_property)
+                       return -ENOMEM;
+       }
+
        return 0;
 }
 
index b9e9e8b02fb756a0d7291c605353d59cd228826e..d1b4d9b6aae0d1743f77dc2373d0c9159d03f937 100644 (file)
@@ -339,6 +339,8 @@ struct amdgpu_mode_info {
        struct drm_property *audio_property;
        /* FMT dithering */
        struct drm_property *dither_property;
+       /* maximum number of bits per channel for monitor color */
+       struct drm_property *max_bpc_property;
        /* hardcoded DFP edid from BIOS */
        struct edid *bios_hardcoded_edid;
        int bios_hardcoded_edid_size;
index e1c2b4e9c7b23a10ac3b1b2b5375d2bf84eae9c2..73ad02aea2b2e802f0dbce340d70877bdc3b6ca1 100644 (file)
@@ -46,6 +46,7 @@ MODULE_FIRMWARE("amdgpu/tahiti_mc.bin");
 MODULE_FIRMWARE("amdgpu/pitcairn_mc.bin");
 MODULE_FIRMWARE("amdgpu/verde_mc.bin");
 MODULE_FIRMWARE("amdgpu/oland_mc.bin");
+MODULE_FIRMWARE("amdgpu/hainan_mc.bin");
 MODULE_FIRMWARE("amdgpu/si58_mc.bin");
 
 #define MC_SEQ_MISC0__MT__MASK   0xf0000000
index bf5e6a413dee6e9b5de53f62ad7547ecb5e5b23e..4cc0dcb1a1875bfc559affd1f55e268a25e6282e 100644 (file)
 #define mmMP0_MISC_LIGHT_SLEEP_CTRL                                                             0x01ba
 #define mmMP0_MISC_LIGHT_SLEEP_CTRL_BASE_IDX                                                    0
 
+/* for Vega20 register name change */
+#define mmHDP_MEM_POWER_CTRL   0x00d4
+#define HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK 0x00000001L
+#define HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK   0x00000002L
+#define HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK  0x00010000L
+#define HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK            0x00020000L
+#define mmHDP_MEM_POWER_CTRL_BASE_IDX  0
 /*
  * Indirect registers accessor
  */
@@ -870,15 +877,33 @@ static void soc15_update_hdp_light_sleep(struct amdgpu_device *adev, bool enable
 {
        uint32_t def, data;
 
-       def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS));
+       if (adev->asic_type == CHIP_VEGA20) {
+               def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_CTRL));
 
-       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
-               data |= HDP_MEM_POWER_LS__LS_ENABLE_MASK;
-       else
-               data &= ~HDP_MEM_POWER_LS__LS_ENABLE_MASK;
+               if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
+                       data |= HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK |
+                               HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK |
+                               HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK |
+                               HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK;
+               else
+                       data &= ~(HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK |
+                               HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK |
+                               HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK |
+                               HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK);
 
-       if (def != data)
-               WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS), data);
+               if (def != data)
+                       WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_CTRL), data);
+       } else {
+               def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS));
+
+               if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
+                       data |= HDP_MEM_POWER_LS__LS_ENABLE_MASK;
+               else
+                       data &= ~HDP_MEM_POWER_LS__LS_ENABLE_MASK;
+
+               if (def != data)
+                       WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS), data);
+       }
 }
 
 static void soc15_update_drm_clock_gating(struct amdgpu_device *adev, bool enable)
index c1262f62cd9f21400c68a6040000d31e4a9a9716..ca925200fe09240ae4f96a2ef7f633726b4cf883 100644 (file)
@@ -2358,8 +2358,15 @@ static void update_stream_scaling_settings(const struct drm_display_mode *mode,
 static enum dc_color_depth
 convert_color_depth_from_display_info(const struct drm_connector *connector)
 {
+       struct dm_connector_state *dm_conn_state =
+               to_dm_connector_state(connector->state);
        uint32_t bpc = connector->display_info.bpc;
 
+       /* TODO: Remove this when there's support for max_bpc in drm */
+       if (dm_conn_state && bpc > dm_conn_state->max_bpc)
+               /* Round down to nearest even number. */
+               bpc = dm_conn_state->max_bpc - (dm_conn_state->max_bpc & 1);
+
        switch (bpc) {
        case 0:
                /*
@@ -2943,6 +2950,9 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector,
        } else if (property == adev->mode_info.underscan_property) {
                dm_new_state->underscan_enable = val;
                ret = 0;
+       } else if (property == adev->mode_info.max_bpc_property) {
+               dm_new_state->max_bpc = val;
+               ret = 0;
        }
 
        return ret;
@@ -2985,6 +2995,9 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector,
        } else if (property == adev->mode_info.underscan_property) {
                *val = dm_state->underscan_enable;
                ret = 0;
+       } else if (property == adev->mode_info.max_bpc_property) {
+               *val = dm_state->max_bpc;
+               ret = 0;
        }
        return ret;
 }
@@ -3795,6 +3808,9 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        drm_object_attach_property(&aconnector->base.base,
                                adev->mode_info.underscan_vborder_property,
                                0);
+       drm_object_attach_property(&aconnector->base.base,
+                               adev->mode_info.max_bpc_property,
+                               0);
 
 }
 
index 924a38a1fc446019a0aac035b018b952e3be9923..6e069d777ab22d0e733bb7bc1c62d3d3370cc265 100644 (file)
@@ -204,6 +204,7 @@ struct dm_connector_state {
        enum amdgpu_rmx_type scaling;
        uint8_t underscan_vborder;
        uint8_t underscan_hborder;
+       uint8_t max_bpc;
        bool underscan_enable;
        bool freesync_enable;
        bool freesync_capable;
index ed35ec0341e671ab8f5cee4d89d2417283147bf3..88f6b35ea6fee9cb7bdf40df0eeef3b3d71ee233 100644 (file)
@@ -4525,12 +4525,12 @@ static int smu7_get_sclk_od(struct pp_hwmgr *hwmgr)
        struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
        struct smu7_single_dpm_table *golden_sclk_table =
                        &(data->golden_dpm_table.sclk_table);
-       int value;
+       int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
+       int golden_value = golden_sclk_table->dpm_levels
+                       [golden_sclk_table->count - 1].value;
 
-       value = (sclk_table->dpm_levels[sclk_table->count - 1].value -
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) *
-                       100 /
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
@@ -4567,12 +4567,12 @@ static int smu7_get_mclk_od(struct pp_hwmgr *hwmgr)
        struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
        struct smu7_single_dpm_table *golden_mclk_table =
                        &(data->golden_dpm_table.mclk_table);
-       int value;
+        int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
+       int golden_value = golden_mclk_table->dpm_levels
+                       [golden_mclk_table->count - 1].value;
 
-       value = (mclk_table->dpm_levels[mclk_table->count - 1].value -
-                       golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) *
-                       100 /
-                       golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
index 8c4db86bb4b770b345575564ad335d48e2681835..e2bc6e0c229f96dde7baf50d2f2189efce4c2c2e 100644 (file)
@@ -4522,15 +4522,13 @@ static int vega10_get_sclk_od(struct pp_hwmgr *hwmgr)
        struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
        struct vega10_single_dpm_table *golden_sclk_table =
                        &(data->golden_dpm_table.gfx_table);
-       int value;
-
-       value = (sclk_table->dpm_levels[sclk_table->count - 1].value -
-                       golden_sclk_table->dpm_levels
-                       [golden_sclk_table->count - 1].value) *
-                       100 /
-                       golden_sclk_table->dpm_levels
+       int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
+       int golden_value = golden_sclk_table->dpm_levels
                        [golden_sclk_table->count - 1].value;
 
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
+
        return value;
 }
 
@@ -4575,16 +4573,13 @@ static int vega10_get_mclk_od(struct pp_hwmgr *hwmgr)
        struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
        struct vega10_single_dpm_table *golden_mclk_table =
                        &(data->golden_dpm_table.mem_table);
-       int value;
-
-       value = (mclk_table->dpm_levels
-                       [mclk_table->count - 1].value -
-                       golden_mclk_table->dpm_levels
-                       [golden_mclk_table->count - 1].value) *
-                       100 /
-                       golden_mclk_table->dpm_levels
+       int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
+       int golden_value = golden_mclk_table->dpm_levels
                        [golden_mclk_table->count - 1].value;
 
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
+
        return value;
 }
 
index 74bc37308dc09cb8303cd42146c7d88af3a27c58..54364444ecd121dd611c30148f4e292a8ee18e1a 100644 (file)
@@ -2243,12 +2243,12 @@ static int vega12_get_sclk_od(struct pp_hwmgr *hwmgr)
        struct vega12_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
        struct vega12_single_dpm_table *golden_sclk_table =
                        &(data->golden_dpm_table.gfx_table);
-       int value;
+       int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
+       int golden_value = golden_sclk_table->dpm_levels
+                       [golden_sclk_table->count - 1].value;
 
-       value = (sclk_table->dpm_levels[sclk_table->count - 1].value -
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) *
-                       100 /
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
@@ -2264,16 +2264,13 @@ static int vega12_get_mclk_od(struct pp_hwmgr *hwmgr)
        struct vega12_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
        struct vega12_single_dpm_table *golden_mclk_table =
                        &(data->golden_dpm_table.mem_table);
-       int value;
-
-       value = (mclk_table->dpm_levels
-                       [mclk_table->count - 1].value -
-                       golden_mclk_table->dpm_levels
-                       [golden_mclk_table->count - 1].value) *
-                       100 /
-                       golden_mclk_table->dpm_levels
+       int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
+       int golden_value = golden_mclk_table->dpm_levels
                        [golden_mclk_table->count - 1].value;
 
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
+
        return value;
 }
 
index 99861f32b1f95aedfb5c64d39814baca329662c2..b4eadd47f3a44a22b95ccd12effd99924a493e24 100644 (file)
@@ -75,7 +75,17 @@ static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)
        data->phy_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
        data->phy_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
 
-       data->registry_data.disallowed_features = 0x0;
+       /*
+        * Disable the following features for now:
+        *   GFXCLK DS
+        *   SOCLK DS
+        *   LCLK DS
+        *   DCEFCLK DS
+        *   FCLK DS
+        *   MP1CLK DS
+        *   MP0CLK DS
+        */
+       data->registry_data.disallowed_features = 0xE0041C00;
        data->registry_data.od_state_in_dc_support = 0;
        data->registry_data.thermal_support = 1;
        data->registry_data.skip_baco_hardware = 0;
@@ -1313,12 +1323,13 @@ static int vega20_get_sclk_od(
                        &(data->dpm_table.gfx_table);
        struct vega20_single_dpm_table *golden_sclk_table =
                        &(data->golden_dpm_table.gfx_table);
-       int value;
+       int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
+       int golden_value = golden_sclk_table->dpm_levels
+                       [golden_sclk_table->count - 1].value;
 
        /* od percentage */
-       value = DIV_ROUND_UP((sclk_table->dpm_levels[sclk_table->count - 1].value -
-               golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) * 100,
-               golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value);
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
@@ -1358,12 +1369,13 @@ static int vega20_get_mclk_od(
                        &(data->dpm_table.mem_table);
        struct vega20_single_dpm_table *golden_mclk_table =
                        &(data->golden_dpm_table.mem_table);
-       int value;
+       int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
+       int golden_value = golden_mclk_table->dpm_levels
+                       [golden_mclk_table->count - 1].value;
 
        /* od percentage */
-       value = DIV_ROUND_UP((mclk_table->dpm_levels[mclk_table->count - 1].value -
-               golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) * 100,
-               golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value);
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
index 69dab82a37714853b5dfdb74dbe479f7d6c10fb1..bf589c53b908d66789679df6f4098c883150fa87 100644 (file)
@@ -60,8 +60,29 @@ static const struct pci_device_id pciidlist[] = {
 
 MODULE_DEVICE_TABLE(pci, pciidlist);
 
+static void ast_kick_out_firmware_fb(struct pci_dev *pdev)
+{
+       struct apertures_struct *ap;
+       bool primary = false;
+
+       ap = alloc_apertures(1);
+       if (!ap)
+               return;
+
+       ap->ranges[0].base = pci_resource_start(pdev, 0);
+       ap->ranges[0].size = pci_resource_len(pdev, 0);
+
+#ifdef CONFIG_X86
+       primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
+#endif
+       drm_fb_helper_remove_conflicting_framebuffers(ap, "astdrmfb", primary);
+       kfree(ap);
+}
+
 static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+       ast_kick_out_firmware_fb(pdev);
+
        return drm_get_pci_dev(pdev, ent, &driver);
 }
 
index 5e77d456d9bb9434040107a69536815a270c7865..7c6ac3cadb6b7fabcfe9a309d5fc201db6b75bf7 100644 (file)
@@ -568,6 +568,7 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,
        }
        ast_bo_unreserve(bo);
 
+       ast_set_offset_reg(crtc);
        ast_set_start_address_crt1(crtc, (u32)gpu_addr);
 
        return 0;
@@ -1254,7 +1255,7 @@ static int ast_cursor_move(struct drm_crtc *crtc,
        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, ((y >> 8) & 0x07));
 
        /* dummy write to fire HWC */
-       ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xCB, 0xFF, 0x00);
+       ast_show_cursor(crtc);
 
        return 0;
 }
index a502f3e519fdb668c685f392d518361e1e0a1ef2..dd852a25d37540fdf9ee6254f08a68b98df3e9a5 100644 (file)
@@ -219,6 +219,9 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
        mutex_lock(&fb_helper->lock);
        drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
+               if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+                       continue;
+
                ret = __drm_fb_helper_add_one_connector(fb_helper, connector);
                if (ret)
                        goto fail;
index 1aaccbe7e1debd0c11440ac9acae9c15b07880d5..d4fac09095f862aed3131243957059de2df4f6b0 100644 (file)
@@ -1268,7 +1268,7 @@ relocate_entry(struct i915_vma *vma,
                else if (gen >= 4)
                        len = 4;
                else
-                       len = 3;
+                       len = 6;
 
                batch = reloc_gpu(eb, vma, len);
                if (IS_ERR(batch))
@@ -1309,6 +1309,11 @@ relocate_entry(struct i915_vma *vma,
                        *batch++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL;
                        *batch++ = addr;
                        *batch++ = target_offset;
+
+                       /* And again for good measure (blb/pnv) */
+                       *batch++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL;
+                       *batch++ = addr;
+                       *batch++ = target_offset;
                }
 
                goto out;
index 47c302543799007bee421d85039be8b016aed6e7..07999fe09ad231a037bc73379b5fc27aaf484b94 100644 (file)
@@ -3413,6 +3413,11 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
                ggtt->vm.insert_page    = bxt_vtd_ggtt_insert_page__BKL;
                if (ggtt->vm.clear_range != nop_clear_range)
                        ggtt->vm.clear_range = bxt_vtd_ggtt_clear_range__BKL;
+
+               /* Prevent recursively calling stop_machine() and deadlocks. */
+               dev_info(dev_priv->drm.dev,
+                        "Disabling error capture for VT-d workaround\n");
+               i915_disable_error_state(dev_priv, -ENODEV);
        }
 
        ggtt->invalidate = gen6_ggtt_invalidate;
index 8762d17b66591e2afc8fc9647bef2784145f2c19..3eb33e000d6f00f3ae4b3fdbc8f37f38e97b4d83 100644 (file)
@@ -648,6 +648,9 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
                return 0;
        }
 
+       if (IS_ERR(error))
+               return PTR_ERR(error);
+
        if (*error->error_msg)
                err_printf(m, "%s\n", error->error_msg);
        err_printf(m, "Kernel: " UTS_RELEASE "\n");
@@ -1859,6 +1862,7 @@ void i915_capture_error_state(struct drm_i915_private *i915,
        error = i915_capture_gpu_state(i915);
        if (!error) {
                DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
+               i915_disable_error_state(i915, -ENOMEM);
                return;
        }
 
@@ -1914,5 +1918,14 @@ void i915_reset_error_state(struct drm_i915_private *i915)
        i915->gpu_error.first_error = NULL;
        spin_unlock_irq(&i915->gpu_error.lock);
 
-       i915_gpu_state_put(error);
+       if (!IS_ERR(error))
+               i915_gpu_state_put(error);
+}
+
+void i915_disable_error_state(struct drm_i915_private *i915, int err)
+{
+       spin_lock_irq(&i915->gpu_error.lock);
+       if (!i915->gpu_error.first_error)
+               i915->gpu_error.first_error = ERR_PTR(err);
+       spin_unlock_irq(&i915->gpu_error.lock);
 }
index 8710fb18ed746cface7e9a7b2d6d6ac7cd06b2b4..3ec89a504de52331ade6a9452a844527d84ec515 100644 (file)
@@ -343,6 +343,7 @@ static inline void i915_gpu_state_put(struct i915_gpu_state *gpu)
 
 struct i915_gpu_state *i915_first_error_state(struct drm_i915_private *i915);
 void i915_reset_error_state(struct drm_i915_private *i915);
+void i915_disable_error_state(struct drm_i915_private *i915, int err);
 
 #else
 
@@ -355,13 +356,18 @@ static inline void i915_capture_error_state(struct drm_i915_private *dev_priv,
 static inline struct i915_gpu_state *
 i915_first_error_state(struct drm_i915_private *i915)
 {
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 
 static inline void i915_reset_error_state(struct drm_i915_private *i915)
 {
 }
 
+static inline void i915_disable_error_state(struct drm_i915_private *i915,
+                                           int err)
+{
+}
+
 #endif /* IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) */
 
 #endif /* _I915_GPU_ERROR_H_ */
index a54843fdeb2f04a353c30af6e86e131c203b2868..c9878dd1f7cd04dd3a6a7b8877d8f5d95eafc620 100644 (file)
@@ -2890,6 +2890,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
        return;
 
 valid_fb:
+       intel_state->base.rotation = plane_config->rotation;
        intel_fill_fb_ggtt_view(&intel_state->view, fb,
                                intel_state->base.rotation);
        intel_state->color_plane[0].stride =
@@ -7882,8 +7883,15 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
                        plane_config->tiling = I915_TILING_X;
                        fb->modifier = I915_FORMAT_MOD_X_TILED;
                }
+
+               if (val & DISPPLANE_ROTATE_180)
+                       plane_config->rotation = DRM_MODE_ROTATE_180;
        }
 
+       if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B &&
+           val & DISPPLANE_MIRROR)
+               plane_config->rotation |= DRM_MODE_REFLECT_X;
+
        pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
        fourcc = i9xx_format_to_fourcc(pixel_format);
        fb->format = drm_format_info(fourcc);
@@ -8952,6 +8960,29 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
                goto error;
        }
 
+       /*
+        * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
+        * while i915 HW rotation is clockwise, thats why this swapping.
+        */
+       switch (val & PLANE_CTL_ROTATE_MASK) {
+       case PLANE_CTL_ROTATE_0:
+               plane_config->rotation = DRM_MODE_ROTATE_0;
+               break;
+       case PLANE_CTL_ROTATE_90:
+               plane_config->rotation = DRM_MODE_ROTATE_270;
+               break;
+       case PLANE_CTL_ROTATE_180:
+               plane_config->rotation = DRM_MODE_ROTATE_180;
+               break;
+       case PLANE_CTL_ROTATE_270:
+               plane_config->rotation = DRM_MODE_ROTATE_90;
+               break;
+       }
+
+       if (INTEL_GEN(dev_priv) >= 10 &&
+           val & PLANE_CTL_FLIP_HORIZONTAL)
+               plane_config->rotation |= DRM_MODE_REFLECT_X;
+
        base = I915_READ(PLANE_SURF(pipe, plane_id)) & 0xfffff000;
        plane_config->base = base;
 
@@ -15267,6 +15298,14 @@ retry:
                        ret = drm_atomic_add_affected_planes(state, crtc);
                        if (ret)
                                goto out;
+
+                       /*
+                        * FIXME hack to force a LUT update to avoid the
+                        * plane update forcing the pipe gamma on without
+                        * having a proper LUT loaded. Remove once we
+                        * have readout for pipe gamma enable.
+                        */
+                       crtc_state->color_mgmt_changed = true;
                }
        }
 
index 8b298e5f012dac121385df61fa72d6a653a21354..db6fa1d0cbdae3efea1e3ddb1c3ce43bf5f8a10e 100644 (file)
@@ -547,6 +547,7 @@ struct intel_initial_plane_config {
        unsigned int tiling;
        int size;
        u32 base;
+       u8 rotation;
 };
 
 #define SKL_MIN_SRC_W 8
index 245f0022bcfd00c730f020b24326bfba90de4ea2..3fe358db12768f23a2fcf7fe971821c4cac3f1b9 100644 (file)
@@ -2493,6 +2493,9 @@ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate,
        uint32_t method1, method2;
        int cpp;
 
+       if (mem_value == 0)
+               return U32_MAX;
+
        if (!intel_wm_plane_visible(cstate, pstate))
                return 0;
 
@@ -2522,6 +2525,9 @@ static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate,
        uint32_t method1, method2;
        int cpp;
 
+       if (mem_value == 0)
+               return U32_MAX;
+
        if (!intel_wm_plane_visible(cstate, pstate))
                return 0;
 
@@ -2545,6 +2551,9 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate,
 {
        int cpp;
 
+       if (mem_value == 0)
+               return U32_MAX;
+
        if (!intel_wm_plane_visible(cstate, pstate))
                return 0;
 
@@ -3008,6 +3017,34 @@ static void snb_wm_latency_quirk(struct drm_i915_private *dev_priv)
        intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);
 }
 
+static void snb_wm_lp3_irq_quirk(struct drm_i915_private *dev_priv)
+{
+       /*
+        * On some SNB machines (Thinkpad X220 Tablet at least)
+        * LP3 usage can cause vblank interrupts to be lost.
+        * The DEIIR bit will go high but it looks like the CPU
+        * never gets interrupted.
+        *
+        * It's not clear whether other interrupt source could
+        * be affected or if this is somehow limited to vblank
+        * interrupts only. To play it safe we disable LP3
+        * watermarks entirely.
+        */
+       if (dev_priv->wm.pri_latency[3] == 0 &&
+           dev_priv->wm.spr_latency[3] == 0 &&
+           dev_priv->wm.cur_latency[3] == 0)
+               return;
+
+       dev_priv->wm.pri_latency[3] = 0;
+       dev_priv->wm.spr_latency[3] = 0;
+       dev_priv->wm.cur_latency[3] = 0;
+
+       DRM_DEBUG_KMS("LP3 watermarks disabled due to potential for lost interrupts\n");
+       intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency);
+       intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency);
+       intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);
+}
+
 static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)
 {
        intel_read_wm_latency(dev_priv, dev_priv->wm.pri_latency);
@@ -3024,8 +3061,10 @@ static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)
        intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency);
        intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);
 
-       if (IS_GEN6(dev_priv))
+       if (IS_GEN6(dev_priv)) {
                snb_wm_latency_quirk(dev_priv);
+               snb_wm_lp3_irq_quirk(dev_priv);
+       }
 }
 
 static void skl_setup_wm_latency(struct drm_i915_private *dev_priv)
index 127468785f7484495df89a00989c17388548f9c5..1f94b9affe4bbafddede75306c3109b1368bc172 100644 (file)
@@ -214,6 +214,12 @@ static int vc4_atomic_commit(struct drm_device *dev,
                return 0;
        }
 
+       /* We know for sure we don't want an async update here. Set
+        * state->legacy_cursor_update to false to prevent
+        * drm_atomic_helper_setup_commit() from auto-completing
+        * commit->flip_done.
+        */
+       state->legacy_cursor_update = false;
        ret = drm_atomic_helper_setup_commit(state, nonblock);
        if (ret)
                return ret;
index 9dc3fcbd290bef915cea9d12472b79b3dd36db4a..c6635f23918a8c1ec07531fc6aeffede5e6e528f 100644 (file)
@@ -807,7 +807,7 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb)
 static void vc4_plane_atomic_async_update(struct drm_plane *plane,
                                          struct drm_plane_state *state)
 {
-       struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state);
+       struct vc4_plane_state *vc4_state, *new_vc4_state;
 
        if (plane->state->fb != state->fb) {
                vc4_plane_async_set_fb(plane, state->fb);
@@ -828,7 +828,18 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane,
        plane->state->src_y = state->src_y;
 
        /* Update the display list based on the new crtc_x/y. */
-       vc4_plane_atomic_check(plane, plane->state);
+       vc4_plane_atomic_check(plane, state);
+
+       new_vc4_state = to_vc4_plane_state(state);
+       vc4_state = to_vc4_plane_state(plane->state);
+
+       /* Update the current vc4_state pos0, pos2 and ptr0 dlist entries. */
+       vc4_state->dlist[vc4_state->pos0_offset] =
+               new_vc4_state->dlist[vc4_state->pos0_offset];
+       vc4_state->dlist[vc4_state->pos2_offset] =
+               new_vc4_state->dlist[vc4_state->pos2_offset];
+       vc4_state->dlist[vc4_state->ptr0_offset] =
+               new_vc4_state->dlist[vc4_state->ptr0_offset];
 
        /* Note that we can't just call vc4_plane_write_dlist()
         * because that would smash the context data that the HVS is