Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1/*
  2 * SPDX-License-Identifier: MIT
  3 *
  4 * Copyright © 2019 Intel Corporation
  5 */
  6
  7#include "i915_drv.h"
  8#include "intel_lrc_reg.h"
  9#include "intel_sseu.h"
 10
 11unsigned int
 12intel_sseu_subslice_total(const struct sseu_dev_info *sseu)
 13{
 14	unsigned int i, total = 0;
 15
 16	for (i = 0; i < ARRAY_SIZE(sseu->subslice_mask); i++)
 17		total += hweight8(sseu->subslice_mask[i]);
 18
 19	return total;
 20}
 21
 22unsigned int
 23intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice)
 24{
 25	return hweight8(sseu->subslice_mask[slice]);
 26}
 27
 28u32 intel_sseu_make_rpcs(struct drm_i915_private *i915,
 29			 const struct intel_sseu *req_sseu)
 30{
 31	const struct sseu_dev_info *sseu = &RUNTIME_INFO(i915)->sseu;
 32	bool subslice_pg = sseu->has_subslice_pg;
 33	struct intel_sseu ctx_sseu;
 34	u8 slices, subslices;
 35	u32 rpcs = 0;
 36
 37	/*
 38	 * No explicit RPCS request is needed to ensure full
 39	 * slice/subslice/EU enablement prior to Gen9.
 40	 */
 41	if (INTEL_GEN(i915) < 9)
 42		return 0;
 43
 44	/*
 45	 * If i915/perf is active, we want a stable powergating configuration
 46	 * on the system.
 47	 *
 48	 * We could choose full enablement, but on ICL we know there are use
 49	 * cases which disable slices for functional, apart for performance
 50	 * reasons. So in this case we select a known stable subset.
 51	 */
 52	if (!i915->perf.exclusive_stream) {
 53		ctx_sseu = *req_sseu;
 54	} else {
 55		ctx_sseu = intel_sseu_from_device_info(sseu);
 56
 57		if (IS_GEN(i915, 11)) {
 58			/*
 59			 * We only need subslice count so it doesn't matter
 60			 * which ones we select - just turn off low bits in the
 61			 * amount of half of all available subslices per slice.
 62			 */
 63			ctx_sseu.subslice_mask =
 64				~(~0 << (hweight8(ctx_sseu.subslice_mask) / 2));
 65			ctx_sseu.slice_mask = 0x1;
 66		}
 67	}
 68
 69	slices = hweight8(ctx_sseu.slice_mask);
 70	subslices = hweight8(ctx_sseu.subslice_mask);
 71
 72	/*
 73	 * Since the SScount bitfield in GEN8_R_PWR_CLK_STATE is only three bits
 74	 * wide and Icelake has up to eight subslices, specfial programming is
 75	 * needed in order to correctly enable all subslices.
 76	 *
 77	 * According to documentation software must consider the configuration
 78	 * as 2x4x8 and hardware will translate this to 1x8x8.
 79	 *
 80	 * Furthemore, even though SScount is three bits, maximum documented
 81	 * value for it is four. From this some rules/restrictions follow:
 82	 *
 83	 * 1.
 84	 * If enabled subslice count is greater than four, two whole slices must
 85	 * be enabled instead.
 86	 *
 87	 * 2.
 88	 * When more than one slice is enabled, hardware ignores the subslice
 89	 * count altogether.
 90	 *
 91	 * From these restrictions it follows that it is not possible to enable
 92	 * a count of subslices between the SScount maximum of four restriction,
 93	 * and the maximum available number on a particular SKU. Either all
 94	 * subslices are enabled, or a count between one and four on the first
 95	 * slice.
 96	 */
 97	if (IS_GEN(i915, 11) &&
 98	    slices == 1 &&
 99	    subslices > min_t(u8, 4, hweight8(sseu->subslice_mask[0]) / 2)) {
100		GEM_BUG_ON(subslices & 1);
101
102		subslice_pg = false;
103		slices *= 2;
104	}
105
106	/*
107	 * Starting in Gen9, render power gating can leave
108	 * slice/subslice/EU in a partially enabled state. We
109	 * must make an explicit request through RPCS for full
110	 * enablement.
111	 */
112	if (sseu->has_slice_pg) {
113		u32 mask, val = slices;
114
115		if (INTEL_GEN(i915) >= 11) {
116			mask = GEN11_RPCS_S_CNT_MASK;
117			val <<= GEN11_RPCS_S_CNT_SHIFT;
118		} else {
119			mask = GEN8_RPCS_S_CNT_MASK;
120			val <<= GEN8_RPCS_S_CNT_SHIFT;
121		}
122
123		GEM_BUG_ON(val & ~mask);
124		val &= mask;
125
126		rpcs |= GEN8_RPCS_ENABLE | GEN8_RPCS_S_CNT_ENABLE | val;
127	}
128
129	if (subslice_pg) {
130		u32 val = subslices;
131
132		val <<= GEN8_RPCS_SS_CNT_SHIFT;
133
134		GEM_BUG_ON(val & ~GEN8_RPCS_SS_CNT_MASK);
135		val &= GEN8_RPCS_SS_CNT_MASK;
136
137		rpcs |= GEN8_RPCS_ENABLE | GEN8_RPCS_SS_CNT_ENABLE | val;
138	}
139
140	if (sseu->has_eu_pg) {
141		u32 val;
142
143		val = ctx_sseu.min_eus_per_subslice << GEN8_RPCS_EU_MIN_SHIFT;
144		GEM_BUG_ON(val & ~GEN8_RPCS_EU_MIN_MASK);
145		val &= GEN8_RPCS_EU_MIN_MASK;
146
147		rpcs |= val;
148
149		val = ctx_sseu.max_eus_per_subslice << GEN8_RPCS_EU_MAX_SHIFT;
150		GEM_BUG_ON(val & ~GEN8_RPCS_EU_MAX_MASK);
151		val &= GEN8_RPCS_EU_MAX_MASK;
152
153		rpcs |= val;
154
155		rpcs |= GEN8_RPCS_ENABLE;
156	}
157
158	return rpcs;
159}