Skip to content

Commit c457d9c

Browse files
committed
drm/i915: Make sure we have enough memory bandwidth on ICL
ICL has so many planes that it can easily exceed the maximum effective memory bandwidth of the system. We must therefore check that we don't exceed that limit. The algorithm is very magic number heavy and lacks sufficient explanation for now. We also have no sane way to query the memory clock and timings, so we must rely on a combination of raw readout from the memory controller and hardcoded assumptions. The memory controller values obviously change as the system jumps between the different SAGV points, so we try to stabilize it first by disabling SAGV for the duration of the readout. The utilized bandwidth is tracked via a device wide atomic private object. That is actually not robust because we can't afford to enforce strict global ordering between the pipes. Thus I think I'll need to change this to simply chop up the available bandwidth between all the active pipes. Each pipe can then do whatever it wants as long as it doesn't exceed its budget. That scheme will also require that we assume that any number of planes could be active at any time. TODO: make it robust and deal with all the open questions v2: Sleep longer after disabling SAGV v3: Poll for the dclk to get raised (seen it take 250ms!) If the system has 2133MT/s memory then we pointlessly wait one full second :( v4: Use the new pcode interface to get the qgv points rather that using hardcoded numbers v5: Move the pcode stuff into intel_bw.c (Matt) s/intel_sagv_info/intel_qgv_info/ Do the NV12/P010 as per spec for now (Matt) s/IS_ICELAKE/IS_GEN11/ v6: Ignore bandwidth limits if the pcode query fails Signed-off-by: Ville Syrjälä <[email protected]> Reviewed-by: Matt Roper <[email protected]> Acked-by: Clint Taylor <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent d284d51 commit c457d9c

File tree

10 files changed

+552
-1
lines changed

10 files changed

+552
-1
lines changed

drivers/gpu/drm/i915/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ i915-y += intel_audio.o \
138138
intel_atomic.o \
139139
intel_atomic_plane.o \
140140
intel_bios.o \
141+
intel_bw.o \
141142
intel_cdclk.o \
142143
intel_color.o \
143144
intel_combo_phy.o \

drivers/gpu/drm/i915/i915_drv.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#include "i915_vgpu.h"
6161
#include "intel_acpi.h"
6262
#include "intel_audio.h"
63+
#include "intel_bw.h"
6364
#include "intel_cdclk.h"
6465
#include "intel_csr.h"
6566
#include "intel_dp.h"
@@ -1657,6 +1658,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
16571658
*/
16581659
intel_get_dram_info(dev_priv);
16591660

1661+
intel_bw_init_hw(dev_priv);
16601662

16611663
return 0;
16621664

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include <drm/drm_cache.h>
5555
#include <drm/drm_util.h>
5656
#include <drm/drm_dsc.h>
57+
#include <drm/drm_atomic.h>
5758
#include <drm/drm_connector.h>
5859
#include <drm/i915_mei_hdcp_interface.h>
5960

@@ -1841,6 +1842,13 @@ struct drm_i915_private {
18411842
} type;
18421843
} dram_info;
18431844

1845+
struct intel_bw_info {
1846+
int num_planes;
1847+
int deratedbw[3];
1848+
} max_bw[6];
1849+
1850+
struct drm_private_obj bw_obj;
1851+
18441852
struct i915_runtime_pm runtime_pm;
18451853

18461854
struct {

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8780,6 +8780,9 @@ enum {
87808780
#define GEN6_PCODE_WRITE_MIN_FREQ_TABLE 0x8
87818781
#define GEN6_PCODE_READ_MIN_FREQ_TABLE 0x9
87828782
#define GEN6_READ_OC_PARAMS 0xc
8783+
#define ICL_PCODE_MEM_SUBSYSYSTEM_INFO 0xd
8784+
#define ICL_PCODE_MEM_SS_READ_GLOBAL_INFO (0x0 << 8)
8785+
#define ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point) (((point) << 16) | (0x1 << 8))
87838786
#define GEN6_PCODE_READ_D_COMP 0x10
87848787
#define GEN6_PCODE_WRITE_D_COMP 0x11
87858788
#define HSW_PCODE_DE_WRITE_FREQ_REQ 0x17

drivers/gpu/drm/i915/intel_atomic_plane.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,29 @@ intel_plane_destroy_state(struct drm_plane *plane,
114114
drm_atomic_helper_plane_destroy_state(plane, state);
115115
}
116116

117+
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
118+
const struct intel_plane_state *plane_state)
119+
{
120+
const struct drm_framebuffer *fb = plane_state->base.fb;
121+
unsigned int cpp;
122+
123+
if (!plane_state->base.visible)
124+
return 0;
125+
126+
cpp = fb->format->cpp[0];
127+
128+
/*
129+
* Based on HSD#:1408715493
130+
* NV12 cpp == 4, P010 cpp == 8
131+
*
132+
* FIXME what is the logic behind this?
133+
*/
134+
if (fb->format->is_yuv && fb->format->num_planes > 1)
135+
cpp *= 4;
136+
137+
return cpp * crtc_state->pixel_rate;
138+
}
139+
117140
int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
118141
struct intel_crtc_state *new_crtc_state,
119142
const struct intel_plane_state *old_plane_state,
@@ -125,6 +148,7 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
125148
new_crtc_state->active_planes &= ~BIT(plane->id);
126149
new_crtc_state->nv12_planes &= ~BIT(plane->id);
127150
new_crtc_state->c8_planes &= ~BIT(plane->id);
151+
new_crtc_state->data_rate[plane->id] = 0;
128152
new_plane_state->base.visible = false;
129153

130154
if (!new_plane_state->base.crtc && !old_plane_state->base.crtc)
@@ -149,6 +173,9 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
149173
if (new_plane_state->base.visible || old_plane_state->base.visible)
150174
new_crtc_state->update_planes |= BIT(plane->id);
151175

176+
new_crtc_state->data_rate[plane->id] =
177+
intel_plane_data_rate(new_crtc_state, new_plane_state);
178+
152179
return intel_plane_atomic_calc_changes(old_crtc_state,
153180
&new_crtc_state->base,
154181
old_plane_state,

drivers/gpu/drm/i915/intel_atomic_plane.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ struct intel_plane_state;
1515

1616
extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
1717

18+
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
19+
const struct intel_plane_state *plane_state);
1820
void intel_update_plane(struct intel_plane *plane,
1921
const struct intel_crtc_state *crtc_state,
2022
const struct intel_plane_state *plane_state);

0 commit comments

Comments
 (0)