Merge tag 'drm-intel-next-2019-03-20' of git://anongit.freedesktop.org/drm/drm-intel...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / i915 / i915_drv.c
index 9df65d386d11b40349df879fec224f0990a40b62..9e380cd317dcd0faf2a7bdfa9ed78316db208969 100644 (file)
@@ -188,6 +188,11 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id)
                DRM_DEBUG_KMS("Found Cannon Lake LP PCH (CNP-LP)\n");
                WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv));
                return PCH_CNP;
                DRM_DEBUG_KMS("Found Cannon Lake LP PCH (CNP-LP)\n");
                WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv));
                return PCH_CNP;
+       case INTEL_PCH_CMP_DEVICE_ID_TYPE:
+               DRM_DEBUG_KMS("Found Comet Lake PCH (CMP)\n");
+               WARN_ON(!IS_COFFEELAKE(dev_priv));
+               /* CometPoint is CNP Compatible */
+               return PCH_CNP;
        case INTEL_PCH_ICP_DEVICE_ID_TYPE:
                DRM_DEBUG_KMS("Found Ice Lake PCH\n");
                WARN_ON(!IS_ICELAKE(dev_priv));
        case INTEL_PCH_ICP_DEVICE_ID_TYPE:
                DRM_DEBUG_KMS("Found Ice Lake PCH\n");
                WARN_ON(!IS_ICELAKE(dev_priv));
@@ -219,20 +224,20 @@ intel_virt_detect_pch(const struct drm_i915_private *dev_priv)
         * make an educated guess as to which PCH is really there.
         */
 
         * make an educated guess as to which PCH is really there.
         */
 
-       if (IS_GEN(dev_priv, 5))
-               id = INTEL_PCH_IBX_DEVICE_ID_TYPE;
-       else if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
-               id = INTEL_PCH_CPT_DEVICE_ID_TYPE;
+       if (IS_ICELAKE(dev_priv))
+               id = INTEL_PCH_ICP_DEVICE_ID_TYPE;
+       else if (IS_CANNONLAKE(dev_priv) || IS_COFFEELAKE(dev_priv))
+               id = INTEL_PCH_CNP_DEVICE_ID_TYPE;
+       else if (IS_KABYLAKE(dev_priv) || IS_SKYLAKE(dev_priv))
+               id = INTEL_PCH_SPT_DEVICE_ID_TYPE;
        else if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv))
                id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE;
        else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                id = INTEL_PCH_LPT_DEVICE_ID_TYPE;
        else if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv))
                id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE;
        else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                id = INTEL_PCH_LPT_DEVICE_ID_TYPE;
-       else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
-               id = INTEL_PCH_SPT_DEVICE_ID_TYPE;
-       else if (IS_COFFEELAKE(dev_priv) || IS_CANNONLAKE(dev_priv))
-               id = INTEL_PCH_CNP_DEVICE_ID_TYPE;
-       else if (IS_ICELAKE(dev_priv))
-               id = INTEL_PCH_ICP_DEVICE_ID_TYPE;
+       else if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
+               id = INTEL_PCH_CPT_DEVICE_ID_TYPE;
+       else if (IS_GEN(dev_priv, 5))
+               id = INTEL_PCH_IBX_DEVICE_ID_TYPE;
 
        if (id)
                DRM_DEBUG_KMS("Assuming PCH ID %04x\n", id);
 
        if (id)
                DRM_DEBUG_KMS("Assuming PCH ID %04x\n", id);
@@ -330,16 +335,16 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data,
                value = dev_priv->overlay ? 1 : 0;
                break;
        case I915_PARAM_HAS_BSD:
                value = dev_priv->overlay ? 1 : 0;
                break;
        case I915_PARAM_HAS_BSD:
-               value = !!dev_priv->engine[VCS];
+               value = !!dev_priv->engine[VCS0];
                break;
        case I915_PARAM_HAS_BLT:
                break;
        case I915_PARAM_HAS_BLT:
-               value = !!dev_priv->engine[BCS];
+               value = !!dev_priv->engine[BCS0];
                break;
        case I915_PARAM_HAS_VEBOX:
                break;
        case I915_PARAM_HAS_VEBOX:
-               value = !!dev_priv->engine[VECS];
+               value = !!dev_priv->engine[VECS0];
                break;
        case I915_PARAM_HAS_BSD2:
                break;
        case I915_PARAM_HAS_BSD2:
-               value = !!dev_priv->engine[VCS2];
+               value = !!dev_priv->engine[VCS1];
                break;
        case I915_PARAM_HAS_LLC:
                value = HAS_LLC(dev_priv);
                break;
        case I915_PARAM_HAS_LLC:
                value = HAS_LLC(dev_priv);
@@ -348,10 +353,10 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data,
                value = HAS_WT(dev_priv);
                break;
        case I915_PARAM_HAS_ALIASING_PPGTT:
                value = HAS_WT(dev_priv);
                break;
        case I915_PARAM_HAS_ALIASING_PPGTT:
-               value = min_t(int, INTEL_PPGTT(dev_priv), I915_GEM_PPGTT_FULL);
+               value = INTEL_PPGTT(dev_priv);
                break;
        case I915_PARAM_HAS_SEMAPHORES:
                break;
        case I915_PARAM_HAS_SEMAPHORES:
-               value = 0;
+               value = !!(dev_priv->caps.scheduler & I915_SCHEDULER_CAP_SEMAPHORES);
                break;
        case I915_PARAM_HAS_SECURE_BATCHES:
                value = capable(CAP_SYS_ADMIN);
                break;
        case I915_PARAM_HAS_SECURE_BATCHES:
                value = capable(CAP_SYS_ADMIN);
@@ -714,8 +719,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
        return 0;
 
 cleanup_gem:
        return 0;
 
 cleanup_gem:
-       if (i915_gem_suspend(dev_priv))
-               DRM_ERROR("failed to idle hardware; continuing to unload!\n");
+       i915_gem_suspend(dev_priv);
        i915_gem_fini(dev_priv);
 cleanup_modeset:
        intel_modeset_cleanup(dev);
        i915_gem_fini(dev_priv);
 cleanup_modeset:
        intel_modeset_cleanup(dev);
@@ -873,6 +877,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv)
        mutex_init(&dev_priv->av_mutex);
        mutex_init(&dev_priv->wm.wm_mutex);
        mutex_init(&dev_priv->pps_mutex);
        mutex_init(&dev_priv->av_mutex);
        mutex_init(&dev_priv->wm.wm_mutex);
        mutex_init(&dev_priv->pps_mutex);
+       mutex_init(&dev_priv->hdcp_comp_mutex);
 
        i915_memcpy_init_early(dev_priv);
        intel_runtime_pm_init_early(dev_priv);
 
        i915_memcpy_init_early(dev_priv);
        intel_runtime_pm_init_early(dev_priv);
@@ -1034,110 +1039,180 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv)
        intel_gvt_sanitize_options(dev_priv);
 }
 
        intel_gvt_sanitize_options(dev_priv);
 }
 
-static enum dram_rank skl_get_dimm_rank(u8 size, u32 rank)
+#define DRAM_TYPE_STR(type) [INTEL_DRAM_ ## type] = #type
+
+static const char *intel_dram_type_str(enum intel_dram_type type)
 {
 {
-       if (size == 0)
-               return I915_DRAM_RANK_INVALID;
-       if (rank == SKL_DRAM_RANK_SINGLE)
-               return I915_DRAM_RANK_SINGLE;
-       else if (rank == SKL_DRAM_RANK_DUAL)
-               return I915_DRAM_RANK_DUAL;
+       static const char * const str[] = {
+               DRAM_TYPE_STR(UNKNOWN),
+               DRAM_TYPE_STR(DDR3),
+               DRAM_TYPE_STR(DDR4),
+               DRAM_TYPE_STR(LPDDR3),
+               DRAM_TYPE_STR(LPDDR4),
+       };
 
 
-       return I915_DRAM_RANK_INVALID;
+       if (type >= ARRAY_SIZE(str))
+               type = INTEL_DRAM_UNKNOWN;
+
+       return str[type];
 }
 
 }
 
-static bool
-skl_is_16gb_dimm(enum dram_rank rank, u8 size, u8 width)
+#undef DRAM_TYPE_STR
+
+static int intel_dimm_num_devices(const struct dram_dimm_info *dimm)
 {
 {
-       if (rank == I915_DRAM_RANK_SINGLE && width == 8 && size == 16)
-               return true;
-       else if (rank == I915_DRAM_RANK_DUAL && width == 8 && size == 32)
-               return true;
-       else if (rank == SKL_DRAM_RANK_SINGLE && width == 16 && size == 8)
-               return true;
-       else if (rank == SKL_DRAM_RANK_DUAL && width == 16 && size == 16)
-               return true;
+       return dimm->ranks * 64 / (dimm->width ?: 1);
+}
 
 
-       return false;
+/* Returns total GB for the whole DIMM */
+static int skl_get_dimm_size(u16 val)
+{
+       return val & SKL_DRAM_SIZE_MASK;
 }
 
 }
 
-static int
-skl_dram_get_channel_info(struct dram_channel_info *ch, u32 val)
+static int skl_get_dimm_width(u16 val)
 {
 {
-       u32 tmp_l, tmp_s;
-       u32 s_val = val >> SKL_DRAM_S_SHIFT;
+       if (skl_get_dimm_size(val) == 0)
+               return 0;
 
 
-       if (!val)
-               return -EINVAL;
+       switch (val & SKL_DRAM_WIDTH_MASK) {
+       case SKL_DRAM_WIDTH_X8:
+       case SKL_DRAM_WIDTH_X16:
+       case SKL_DRAM_WIDTH_X32:
+               val = (val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT;
+               return 8 << val;
+       default:
+               MISSING_CASE(val);
+               return 0;
+       }
+}
+
+static int skl_get_dimm_ranks(u16 val)
+{
+       if (skl_get_dimm_size(val) == 0)
+               return 0;
+
+       val = (val & SKL_DRAM_RANK_MASK) >> SKL_DRAM_RANK_SHIFT;
+
+       return val + 1;
+}
 
 
-       tmp_l = val & SKL_DRAM_SIZE_MASK;
-       tmp_s = s_val & SKL_DRAM_SIZE_MASK;
+/* Returns total GB for the whole DIMM */
+static int cnl_get_dimm_size(u16 val)
+{
+       return (val & CNL_DRAM_SIZE_MASK) / 2;
+}
+
+static int cnl_get_dimm_width(u16 val)
+{
+       if (cnl_get_dimm_size(val) == 0)
+               return 0;
 
 
-       if (tmp_l == 0 && tmp_s == 0)
+       switch (val & CNL_DRAM_WIDTH_MASK) {
+       case CNL_DRAM_WIDTH_X8:
+       case CNL_DRAM_WIDTH_X16:
+       case CNL_DRAM_WIDTH_X32:
+               val = (val & CNL_DRAM_WIDTH_MASK) >> CNL_DRAM_WIDTH_SHIFT;
+               return 8 << val;
+       default:
+               MISSING_CASE(val);
+               return 0;
+       }
+}
+
+static int cnl_get_dimm_ranks(u16 val)
+{
+       if (cnl_get_dimm_size(val) == 0)
+               return 0;
+
+       val = (val & CNL_DRAM_RANK_MASK) >> CNL_DRAM_RANK_SHIFT;
+
+       return val + 1;
+}
+
+static bool
+skl_is_16gb_dimm(const struct dram_dimm_info *dimm)
+{
+       /* Convert total GB to Gb per DRAM device */
+       return 8 * dimm->size / (intel_dimm_num_devices(dimm) ?: 1) == 16;
+}
+
+static void
+skl_dram_get_dimm_info(struct drm_i915_private *dev_priv,
+                      struct dram_dimm_info *dimm,
+                      int channel, char dimm_name, u16 val)
+{
+       if (INTEL_GEN(dev_priv) >= 10) {
+               dimm->size = cnl_get_dimm_size(val);
+               dimm->width = cnl_get_dimm_width(val);
+               dimm->ranks = cnl_get_dimm_ranks(val);
+       } else {
+               dimm->size = skl_get_dimm_size(val);
+               dimm->width = skl_get_dimm_width(val);
+               dimm->ranks = skl_get_dimm_ranks(val);
+       }
+
+       DRM_DEBUG_KMS("CH%u DIMM %c size: %u GB, width: X%u, ranks: %u, 16Gb DIMMs: %s\n",
+                     channel, dimm_name, dimm->size, dimm->width, dimm->ranks,
+                     yesno(skl_is_16gb_dimm(dimm)));
+}
+
+static int
+skl_dram_get_channel_info(struct drm_i915_private *dev_priv,
+                         struct dram_channel_info *ch,
+                         int channel, u32 val)
+{
+       skl_dram_get_dimm_info(dev_priv, &ch->dimm_l,
+                              channel, 'L', val & 0xffff);
+       skl_dram_get_dimm_info(dev_priv, &ch->dimm_s,
+                              channel, 'S', val >> 16);
+
+       if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) {
+               DRM_DEBUG_KMS("CH%u not populated\n", channel);
                return -EINVAL;
                return -EINVAL;
+       }
 
 
-       ch->l_info.size = tmp_l;
-       ch->s_info.size = tmp_s;
-
-       tmp_l = (val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT;
-       tmp_s = (s_val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT;
-       ch->l_info.width = (1 << tmp_l) * 8;
-       ch->s_info.width = (1 << tmp_s) * 8;
-
-       tmp_l = val & SKL_DRAM_RANK_MASK;
-       tmp_s = s_val & SKL_DRAM_RANK_MASK;
-       ch->l_info.rank = skl_get_dimm_rank(ch->l_info.size, tmp_l);
-       ch->s_info.rank = skl_get_dimm_rank(ch->s_info.size, tmp_s);
-
-       if (ch->l_info.rank == I915_DRAM_RANK_DUAL ||
-           ch->s_info.rank == I915_DRAM_RANK_DUAL)
-               ch->rank = I915_DRAM_RANK_DUAL;
-       else if (ch->l_info.rank == I915_DRAM_RANK_SINGLE &&
-                ch->s_info.rank == I915_DRAM_RANK_SINGLE)
-               ch->rank = I915_DRAM_RANK_DUAL;
+       if (ch->dimm_l.ranks == 2 || ch->dimm_s.ranks == 2)
+               ch->ranks = 2;
+       else if (ch->dimm_l.ranks == 1 && ch->dimm_s.ranks == 1)
+               ch->ranks = 2;
        else
        else
-               ch->rank = I915_DRAM_RANK_SINGLE;
+               ch->ranks = 1;
 
 
-       ch->is_16gb_dimm = skl_is_16gb_dimm(ch->l_info.rank, ch->l_info.size,
-                                           ch->l_info.width) ||
-                          skl_is_16gb_dimm(ch->s_info.rank, ch->s_info.size,
-                                           ch->s_info.width);
+       ch->is_16gb_dimm =
+               skl_is_16gb_dimm(&ch->dimm_l) ||
+               skl_is_16gb_dimm(&ch->dimm_s);
 
 
-       DRM_DEBUG_KMS("(size:width:rank) L(%dGB:X%d:%s) S(%dGB:X%d:%s)\n",
-                     ch->l_info.size, ch->l_info.width,
-                     ch->l_info.rank ? "dual" : "single",
-                     ch->s_info.size, ch->s_info.width,
-                     ch->s_info.rank ? "dual" : "single");
+       DRM_DEBUG_KMS("CH%u ranks: %u, 16Gb DIMMs: %s\n",
+                     channel, ch->ranks, yesno(ch->is_16gb_dimm));
 
        return 0;
 }
 
 static bool
 
        return 0;
 }
 
 static bool
-intel_is_dram_symmetric(u32 val_ch0, u32 val_ch1,
-                       struct dram_channel_info *ch0)
+intel_is_dram_symmetric(const struct dram_channel_info *ch0,
+                       const struct dram_channel_info *ch1)
 {
 {
-       return (val_ch0 == val_ch1 &&
-               (ch0->s_info.size == 0 ||
-                (ch0->l_info.size == ch0->s_info.size &&
-                 ch0->l_info.width == ch0->s_info.width &&
-                 ch0->l_info.rank == ch0->s_info.rank)));
+       return !memcmp(ch0, ch1, sizeof(*ch0)) &&
+               (ch0->dimm_s.size == 0 ||
+                !memcmp(&ch0->dimm_l, &ch0->dimm_s, sizeof(ch0->dimm_l)));
 }
 
 static int
 skl_dram_get_channels_info(struct drm_i915_private *dev_priv)
 {
        struct dram_info *dram_info = &dev_priv->dram_info;
 }
 
 static int
 skl_dram_get_channels_info(struct drm_i915_private *dev_priv)
 {
        struct dram_info *dram_info = &dev_priv->dram_info;
-       struct dram_channel_info ch0, ch1;
-       u32 val_ch0, val_ch1;
+       struct dram_channel_info ch0 = {}, ch1 = {};
+       u32 val;
        int ret;
 
        int ret;
 
-       val_ch0 = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN);
-       ret = skl_dram_get_channel_info(&ch0, val_ch0);
+       val = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN);
+       ret = skl_dram_get_channel_info(dev_priv, &ch0, 0, val);
        if (ret == 0)
                dram_info->num_channels++;
 
        if (ret == 0)
                dram_info->num_channels++;
 
-       val_ch1 = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN);
-       ret = skl_dram_get_channel_info(&ch1, val_ch1);
+       val = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN);
+       ret = skl_dram_get_channel_info(dev_priv, &ch1, 1, val);
        if (ret == 0)
                dram_info->num_channels++;
 
        if (ret == 0)
                dram_info->num_channels++;
 
@@ -1151,28 +1226,47 @@ skl_dram_get_channels_info(struct drm_i915_private *dev_priv)
         * will be same as if single rank memory, so consider single rank
         * memory.
         */
         * will be same as if single rank memory, so consider single rank
         * memory.
         */
-       if (ch0.rank == I915_DRAM_RANK_SINGLE ||
-           ch1.rank == I915_DRAM_RANK_SINGLE)
-               dram_info->rank = I915_DRAM_RANK_SINGLE;
+       if (ch0.ranks == 1 || ch1.ranks == 1)
+               dram_info->ranks = 1;
        else
        else
-               dram_info->rank = max(ch0.rank, ch1.rank);
+               dram_info->ranks = max(ch0.ranks, ch1.ranks);
 
 
-       if (dram_info->rank == I915_DRAM_RANK_INVALID) {
+       if (dram_info->ranks == 0) {
                DRM_INFO("couldn't get memory rank information\n");
                return -EINVAL;
        }
 
        dram_info->is_16gb_dimm = ch0.is_16gb_dimm || ch1.is_16gb_dimm;
 
                DRM_INFO("couldn't get memory rank information\n");
                return -EINVAL;
        }
 
        dram_info->is_16gb_dimm = ch0.is_16gb_dimm || ch1.is_16gb_dimm;
 
-       dev_priv->dram_info.symmetric_memory = intel_is_dram_symmetric(val_ch0,
-                                                                      val_ch1,
-                                                                      &ch0);
+       dram_info->symmetric_memory = intel_is_dram_symmetric(&ch0, &ch1);
 
 
-       DRM_DEBUG_KMS("memory configuration is %sSymmetric memory\n",
-                     dev_priv->dram_info.symmetric_memory ? "" : "not ");
+       DRM_DEBUG_KMS("Memory configuration is symmetric? %s\n",
+                     yesno(dram_info->symmetric_memory));
        return 0;
 }
 
        return 0;
 }
 
+static enum intel_dram_type
+skl_get_dram_type(struct drm_i915_private *dev_priv)
+{
+       u32 val;
+
+       val = I915_READ(SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN);
+
+       switch (val & SKL_DRAM_DDR_TYPE_MASK) {
+       case SKL_DRAM_DDR_TYPE_DDR3:
+               return INTEL_DRAM_DDR3;
+       case SKL_DRAM_DDR_TYPE_DDR4:
+               return INTEL_DRAM_DDR4;
+       case SKL_DRAM_DDR_TYPE_LPDDR3:
+               return INTEL_DRAM_LPDDR3;
+       case SKL_DRAM_DDR_TYPE_LPDDR4:
+               return INTEL_DRAM_LPDDR4;
+       default:
+               MISSING_CASE(val);
+               return INTEL_DRAM_UNKNOWN;
+       }
+}
+
 static int
 skl_get_dram_info(struct drm_i915_private *dev_priv)
 {
 static int
 skl_get_dram_info(struct drm_i915_private *dev_priv)
 {
@@ -1180,6 +1274,9 @@ skl_get_dram_info(struct drm_i915_private *dev_priv)
        u32 mem_freq_khz, val;
        int ret;
 
        u32 mem_freq_khz, val;
        int ret;
 
+       dram_info->type = skl_get_dram_type(dev_priv);
+       DRM_DEBUG_KMS("DRAM type: %s\n", intel_dram_type_str(dram_info->type));
+
        ret = skl_dram_get_channels_info(dev_priv);
        if (ret)
                return ret;
        ret = skl_dram_get_channels_info(dev_priv);
        if (ret)
                return ret;
@@ -1200,6 +1297,85 @@ skl_get_dram_info(struct drm_i915_private *dev_priv)
        return 0;
 }
 
        return 0;
 }
 
+/* Returns Gb per DRAM device */
+static int bxt_get_dimm_size(u32 val)
+{
+       switch (val & BXT_DRAM_SIZE_MASK) {
+       case BXT_DRAM_SIZE_4GBIT:
+               return 4;
+       case BXT_DRAM_SIZE_6GBIT:
+               return 6;
+       case BXT_DRAM_SIZE_8GBIT:
+               return 8;
+       case BXT_DRAM_SIZE_12GBIT:
+               return 12;
+       case BXT_DRAM_SIZE_16GBIT:
+               return 16;
+       default:
+               MISSING_CASE(val);
+               return 0;
+       }
+}
+
+static int bxt_get_dimm_width(u32 val)
+{
+       if (!bxt_get_dimm_size(val))
+               return 0;
+
+       val = (val & BXT_DRAM_WIDTH_MASK) >> BXT_DRAM_WIDTH_SHIFT;
+
+       return 8 << val;
+}
+
+static int bxt_get_dimm_ranks(u32 val)
+{
+       if (!bxt_get_dimm_size(val))
+               return 0;
+
+       switch (val & BXT_DRAM_RANK_MASK) {
+       case BXT_DRAM_RANK_SINGLE:
+               return 1;
+       case BXT_DRAM_RANK_DUAL:
+               return 2;
+       default:
+               MISSING_CASE(val);
+               return 0;
+       }
+}
+
+static enum intel_dram_type bxt_get_dimm_type(u32 val)
+{
+       if (!bxt_get_dimm_size(val))
+               return INTEL_DRAM_UNKNOWN;
+
+       switch (val & BXT_DRAM_TYPE_MASK) {
+       case BXT_DRAM_TYPE_DDR3:
+               return INTEL_DRAM_DDR3;
+       case BXT_DRAM_TYPE_LPDDR3:
+               return INTEL_DRAM_LPDDR3;
+       case BXT_DRAM_TYPE_DDR4:
+               return INTEL_DRAM_DDR4;
+       case BXT_DRAM_TYPE_LPDDR4:
+               return INTEL_DRAM_LPDDR4;
+       default:
+               MISSING_CASE(val);
+               return INTEL_DRAM_UNKNOWN;
+       }
+}
+
+static void bxt_get_dimm_info(struct dram_dimm_info *dimm,
+                             u32 val)
+{
+       dimm->width = bxt_get_dimm_width(val);
+       dimm->ranks = bxt_get_dimm_ranks(val);
+
+       /*
+        * Size in register is Gb per DRAM device. Convert to total
+        * GB to match the way we report this for non-LP platforms.
+        */
+       dimm->size = bxt_get_dimm_size(val) * intel_dimm_num_devices(dimm) / 8;
+}
+
 static int
 bxt_get_dram_info(struct drm_i915_private *dev_priv)
 {
 static int
 bxt_get_dram_info(struct drm_i915_private *dev_priv)
 {
@@ -1228,57 +1404,44 @@ bxt_get_dram_info(struct drm_i915_private *dev_priv)
         * Now read each DUNIT8/9/10/11 to check the rank of each dimms.
         */
        for (i = BXT_D_CR_DRP0_DUNIT_START; i <= BXT_D_CR_DRP0_DUNIT_END; i++) {
         * Now read each DUNIT8/9/10/11 to check the rank of each dimms.
         */
        for (i = BXT_D_CR_DRP0_DUNIT_START; i <= BXT_D_CR_DRP0_DUNIT_END; i++) {
-               u8 size, width;
-               enum dram_rank rank;
-               u32 tmp;
+               struct dram_dimm_info dimm;
+               enum intel_dram_type type;
 
                val = I915_READ(BXT_D_CR_DRP0_DUNIT(i));
                if (val == 0xFFFFFFFF)
                        continue;
 
                dram_info->num_channels++;
 
                val = I915_READ(BXT_D_CR_DRP0_DUNIT(i));
                if (val == 0xFFFFFFFF)
                        continue;
 
                dram_info->num_channels++;
-               tmp = val & BXT_DRAM_RANK_MASK;
-
-               if (tmp == BXT_DRAM_RANK_SINGLE)
-                       rank = I915_DRAM_RANK_SINGLE;
-               else if (tmp == BXT_DRAM_RANK_DUAL)
-                       rank = I915_DRAM_RANK_DUAL;
-               else
-                       rank = I915_DRAM_RANK_INVALID;
-
-               tmp = val & BXT_DRAM_SIZE_MASK;
-               if (tmp == BXT_DRAM_SIZE_4GB)
-                       size = 4;
-               else if (tmp == BXT_DRAM_SIZE_6GB)
-                       size = 6;
-               else if (tmp == BXT_DRAM_SIZE_8GB)
-                       size = 8;
-               else if (tmp == BXT_DRAM_SIZE_12GB)
-                       size = 12;
-               else if (tmp == BXT_DRAM_SIZE_16GB)
-                       size = 16;
-               else
-                       size = 0;
-
-               tmp = (val & BXT_DRAM_WIDTH_MASK) >> BXT_DRAM_WIDTH_SHIFT;
-               width = (1 << tmp) * 8;
-               DRM_DEBUG_KMS("dram size:%dGB width:X%d rank:%s\n", size,
-                             width, rank == I915_DRAM_RANK_SINGLE ? "single" :
-                             rank == I915_DRAM_RANK_DUAL ? "dual" : "unknown");
+
+               bxt_get_dimm_info(&dimm, val);
+               type = bxt_get_dimm_type(val);
+
+               WARN_ON(type != INTEL_DRAM_UNKNOWN &&
+                       dram_info->type != INTEL_DRAM_UNKNOWN &&
+                       dram_info->type != type);
+
+               DRM_DEBUG_KMS("CH%u DIMM size: %u GB, width: X%u, ranks: %u, type: %s\n",
+                             i - BXT_D_CR_DRP0_DUNIT_START,
+                             dimm.size, dimm.width, dimm.ranks,
+                             intel_dram_type_str(type));
 
                /*
                 * If any of the channel is single rank channel,
                 * worst case output will be same as if single rank
                 * memory, so consider single rank memory.
                 */
 
                /*
                 * If any of the channel is single rank channel,
                 * worst case output will be same as if single rank
                 * memory, so consider single rank memory.
                 */
-               if (dram_info->rank == I915_DRAM_RANK_INVALID)
-                       dram_info->rank = rank;
-               else if (rank == I915_DRAM_RANK_SINGLE)
-                       dram_info->rank = I915_DRAM_RANK_SINGLE;
+               if (dram_info->ranks == 0)
+                       dram_info->ranks = dimm.ranks;
+               else if (dimm.ranks == 1)
+                       dram_info->ranks = 1;
+
+               if (type != INTEL_DRAM_UNKNOWN)
+                       dram_info->type = type;
        }
 
        }
 
-       if (dram_info->rank == I915_DRAM_RANK_INVALID) {
-               DRM_INFO("couldn't get memory rank information\n");
+       if (dram_info->type == INTEL_DRAM_UNKNOWN ||
+           dram_info->ranks == 0) {
+               DRM_INFO("couldn't get memory information\n");
                return -EINVAL;
        }
 
                return -EINVAL;
        }
 
@@ -1290,14 +1453,8 @@ static void
 intel_get_dram_info(struct drm_i915_private *dev_priv)
 {
        struct dram_info *dram_info = &dev_priv->dram_info;
 intel_get_dram_info(struct drm_i915_private *dev_priv)
 {
        struct dram_info *dram_info = &dev_priv->dram_info;
-       char bandwidth_str[32];
        int ret;
 
        int ret;
 
-       dram_info->valid = false;
-       dram_info->rank = I915_DRAM_RANK_INVALID;
-       dram_info->bandwidth_kbps = 0;
-       dram_info->num_channels = 0;
-
        /*
         * Assume 16Gb DIMMs are present until proven otherwise.
         * This is only used for the level 0 watermark latency
        /*
         * Assume 16Gb DIMMs are present until proven otherwise.
         * This is only used for the level 0 watermark latency
@@ -1305,28 +1462,22 @@ intel_get_dram_info(struct drm_i915_private *dev_priv)
         */
        dram_info->is_16gb_dimm = !IS_GEN9_LP(dev_priv);
 
         */
        dram_info->is_16gb_dimm = !IS_GEN9_LP(dev_priv);
 
-       if (INTEL_GEN(dev_priv) < 9 || IS_GEMINILAKE(dev_priv))
+       if (INTEL_GEN(dev_priv) < 9)
                return;
 
                return;
 
-       /* Need to calculate bandwidth only for Gen9 */
-       if (IS_BROXTON(dev_priv))
+       if (IS_GEN9_LP(dev_priv))
                ret = bxt_get_dram_info(dev_priv);
                ret = bxt_get_dram_info(dev_priv);
-       else if (IS_GEN(dev_priv, 9))
-               ret = skl_get_dram_info(dev_priv);
        else
        else
-               ret = skl_dram_get_channels_info(dev_priv);
+               ret = skl_get_dram_info(dev_priv);
        if (ret)
                return;
 
        if (ret)
                return;
 
-       if (dram_info->bandwidth_kbps)
-               sprintf(bandwidth_str, "%d KBps", dram_info->bandwidth_kbps);
-       else
-               sprintf(bandwidth_str, "unknown");
-       DRM_DEBUG_KMS("DRAM bandwidth:%s, total-channels: %u\n",
-                     bandwidth_str, dram_info->num_channels);
-       DRM_DEBUG_KMS("DRAM rank: %s rank 16GB-dimm:%s\n",
-                     (dram_info->rank == I915_DRAM_RANK_DUAL) ?
-                     "dual" : "single", yesno(dram_info->is_16gb_dimm));
+       DRM_DEBUG_KMS("DRAM bandwidth: %u kBps, channels: %u\n",
+                     dram_info->bandwidth_kbps,
+                     dram_info->num_channels);
+
+       DRM_DEBUG_KMS("DRAM ranks: %u, 16Gb DIMMs: %s\n",
+                     dram_info->ranks, yesno(dram_info->is_16gb_dimm));
 }
 
 /**
 }
 
 /**
@@ -1348,7 +1499,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
 
        if (HAS_PPGTT(dev_priv)) {
                if (intel_vgpu_active(dev_priv) &&
 
        if (HAS_PPGTT(dev_priv)) {
                if (intel_vgpu_active(dev_priv) &&
-                   !intel_vgpu_has_full_48bit_ppgtt(dev_priv)) {
+                   !intel_vgpu_has_full_ppgtt(dev_priv)) {
                        i915_report_error(dev_priv,
                                          "incompatible vGPU found, support for isolated ppGTT required\n");
                        return -ENXIO;
                        i915_report_error(dev_priv,
                                          "incompatible vGPU found, support for isolated ppGTT required\n");
                        return -ENXIO;
@@ -1753,8 +1904,7 @@ void i915_driver_unload(struct drm_device *dev)
        /* Flush any external code that still may be under the RCU lock */
        synchronize_rcu();
 
        /* Flush any external code that still may be under the RCU lock */
        synchronize_rcu();
 
-       if (i915_gem_suspend(dev_priv))
-               DRM_ERROR("failed to idle hardware; continuing to unload!\n");
+       i915_gem_suspend(dev_priv);
 
        drm_atomic_helper_shutdown(dev);
 
 
        drm_atomic_helper_shutdown(dev);
 
@@ -1862,7 +2012,6 @@ static bool suspend_to_idle(struct drm_i915_private *dev_priv)
 static int i915_drm_prepare(struct drm_device *dev)
 {
        struct drm_i915_private *i915 = to_i915(dev);
 static int i915_drm_prepare(struct drm_device *dev)
 {
        struct drm_i915_private *i915 = to_i915(dev);
-       int err;
 
        /*
         * NB intel_display_suspend() may issue new requests after we've
 
        /*
         * NB intel_display_suspend() may issue new requests after we've
@@ -1870,12 +2019,9 @@ static int i915_drm_prepare(struct drm_device *dev)
         * split out that work and pull it forward so that after point,
         * the GPU is not woken again.
         */
         * split out that work and pull it forward so that after point,
         * the GPU is not woken again.
         */
-       err = i915_gem_suspend(i915);
-       if (err)
-               dev_err(&i915->drm.pdev->dev,
-                       "GEM idle failed, suspend/resume might fail\n");
+       i915_gem_suspend(i915);
 
 
-       return err;
+       return 0;
 }
 
 static int i915_drm_suspend(struct drm_device *dev)
 }
 
 static int i915_drm_suspend(struct drm_device *dev)