drm/i915/chv: Determine CHV slice/subslice/EU info
authorJeff McGee <jeff.mcgee@intel.com>
Fri, 27 Feb 2015 20:12:28 +0000 (12:12 -0800)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 17 Mar 2015 21:30:05 +0000 (22:30 +0100)
Total EU was already being detected on CHV, so we just add the
additional info parameters. The detection method is changed to
be more robust in the case of subslice fusing - we don't want
to trust the EU fuse bits corresponding to subslices which are
fused-off.

v2: Fixed subslice disable bitmasks and removed unnecessary ?
    operation (Ville)

Signed-off-by: Jeff McGee <jeff.mcgee@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_reg.h

index 3b64c526b6b9f25a44c324f4537b72a19daa21b4..8e914303b831c065293cdf8ffdddbda0307ae4ea 100644 (file)
@@ -611,14 +611,42 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
 
        /* Initialize slice/subslice/EU info */
        if (IS_CHERRYVIEW(dev)) {
-               u32 fuse, mask_eu;
+               u32 fuse, eu_dis;
 
                fuse = I915_READ(CHV_FUSE_GT);
-               mask_eu = fuse & (CHV_FGT_EU_DIS_SS0_R0_MASK |
-                                 CHV_FGT_EU_DIS_SS0_R1_MASK |
-                                 CHV_FGT_EU_DIS_SS1_R0_MASK |
-                                 CHV_FGT_EU_DIS_SS1_R1_MASK);
-               info->eu_total = 16 - hweight32(mask_eu);
+
+               info->slice_total = 1;
+
+               if (!(fuse & CHV_FGT_DISABLE_SS0)) {
+                       info->subslice_per_slice++;
+                       eu_dis = fuse & (CHV_FGT_EU_DIS_SS0_R0_MASK |
+                                        CHV_FGT_EU_DIS_SS0_R1_MASK);
+                       info->eu_total += 8 - hweight32(eu_dis);
+               }
+
+               if (!(fuse & CHV_FGT_DISABLE_SS1)) {
+                       info->subslice_per_slice++;
+                       eu_dis = fuse & (CHV_FGT_EU_DIS_SS1_R0_MASK |
+                                       CHV_FGT_EU_DIS_SS1_R1_MASK);
+                       info->eu_total += 8 - hweight32(eu_dis);
+               }
+
+               info->subslice_total = info->subslice_per_slice;
+               /*
+                * CHV expected to always have a uniform distribution of EU
+                * across subslices.
+               */
+               info->eu_per_subslice = info->subslice_total ?
+                                       info->eu_total / info->subslice_total :
+                                       0;
+               /*
+                * CHV supports subslice power gating on devices with more than
+                * one subslice, and supports EU power gating on devices with
+                * more than one EU pair per subslice.
+               */
+               info->has_slice_pg = 0;
+               info->has_subslice_pg = (info->subslice_total > 1);
+               info->has_eu_pg = (info->eu_per_subslice > 2);
        } else if (IS_SKYLAKE(dev)) {
                const int s_max = 3, ss_max = 4, eu_max = 8;
                int s, ss;
index bf35b6c87ce885ce61f42b0f280951f655ee3f27..f680f4d5e31fa258195f67b0d7abeac2163bc8d4 100644 (file)
@@ -1522,6 +1522,8 @@ enum skl_disp_power_wells {
 
 /* Fuse readout registers for GT */
 #define CHV_FUSE_GT                    (VLV_DISPLAY_BASE + 0x2168)
+#define   CHV_FGT_DISABLE_SS0          (1 << 10)
+#define   CHV_FGT_DISABLE_SS1          (1 << 11)
 #define   CHV_FGT_EU_DIS_SS0_R0_SHIFT  16
 #define   CHV_FGT_EU_DIS_SS0_R0_MASK   (0xf << CHV_FGT_EU_DIS_SS0_R0_SHIFT)
 #define   CHV_FGT_EU_DIS_SS0_R1_SHIFT  20