[PATCH v4 11/12] drm/bridge: tc358768: Fix tc358768_ns_to_cnt()
The tc358768_ns_to_cnt() is, most likely, supposed to do a div-round-up operation, but it misses subtracting one from the dividend. Fix this by just using DIV_ROUND_UP(). Fixes: ff1ca6397b1d ("drm/bridge: Add tc358768 driver") Reviewed-by: Peter Ujfalusi Tested-by: Maxim Schwalm # Asus TF700T Tested-by: Marcel Ziswiler Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/bridge/tc358768.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index 9ce8d120b50c..f41bf56b7d6b 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -630,7 +630,7 @@ static int tc358768_setup_pll(struct tc358768_priv *priv, static u32 tc358768_ns_to_cnt(u32 ns, u32 period_ps) { - return (ns * 1000 + period_ps) / period_ps; + return DIV_ROUND_UP(ns * 1000, period_ps); } static u32 tc358768_ps_to_ns(u32 ps) -- 2.34.1
[PATCH v4 07/12] drm/bridge: tc358768: Print logical values, not raw register values
The driver debug prints DSI related timings as raw register values in hex. It is much more useful to see the "logical" value of the timing, not the register value. Change the prints to print the values separately, in case a single register contains multiple values, and use %u to have it in a more human consumable form. Reviewed-by: Peter Ujfalusi Tested-by: Maxim Schwalm # Asus TF700T Tested-by: Marcel Ziswiler Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/bridge/tc358768.c | 21 - 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index b98c517c4726..88060f961064 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -739,57 +739,59 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) /* LP11 > 100us for D-PHY Rx Init */ val = tc358768_ns_to_cnt(100 * 1000, dsibclk_nsk) - 1; - dev_dbg(priv->dev, "LINEINITCNT: 0x%x\n", val); + dev_dbg(priv->dev, "LINEINITCNT: %u\n", val); tc358768_write(priv, TC358768_LINEINITCNT, val); /* LPTimeCnt > 50ns */ val = tc358768_ns_to_cnt(50, dsibclk_nsk) - 1; lptxcnt = val; - dev_dbg(priv->dev, "LPTXTIMECNT: 0x%x\n", val); + dev_dbg(priv->dev, "LPTXTIMECNT: %u\n", val); tc358768_write(priv, TC358768_LPTXTIMECNT, val); /* 38ns < TCLK_PREPARE < 95ns */ val = tc358768_ns_to_cnt(65, dsibclk_nsk) - 1; + dev_dbg(priv->dev, "TCLK_PREPARECNT %u\n", val); /* TCLK_PREPARE + TCLK_ZERO > 300ns */ val2 = tc358768_ns_to_cnt(300 - tc358768_to_ns(2 * ui_nsk), dsibclk_nsk) - 2; + dev_dbg(priv->dev, "TCLK_ZEROCNT %u\n", val2); val |= val2 << 8; - dev_dbg(priv->dev, "TCLK_HEADERCNT: 0x%x\n", val); tc358768_write(priv, TC358768_TCLK_HEADERCNT, val); /* TCLK_TRAIL > 60ns AND TEOT <= 105 ns + 12*UI */ raw_val = tc358768_ns_to_cnt(60 + tc358768_to_ns(2 * ui_nsk), dsibclk_nsk) - 5; val = clamp(raw_val, 0, 127); - dev_dbg(priv->dev, "TCLK_TRAILCNT: 0x%x\n", val); + dev_dbg(priv->dev, "TCLK_TRAILCNT: %u\n", val); tc358768_write(priv, TC358768_TCLK_TRAILCNT, val); /* 40ns + 4*UI < THS_PREPARE < 85ns + 6*UI */ val = 50 + tc358768_to_ns(4 * ui_nsk); val = tc358768_ns_to_cnt(val, dsibclk_nsk) - 1; + dev_dbg(priv->dev, "THS_PREPARECNT %u\n", val); /* THS_PREPARE + THS_ZERO > 145ns + 10*UI */ raw_val = tc358768_ns_to_cnt(145 - tc358768_to_ns(3 * ui_nsk), dsibclk_nsk) - 10; val2 = clamp(raw_val, 0, 127); + dev_dbg(priv->dev, "THS_ZEROCNT %u\n", val2); val |= val2 << 8; - dev_dbg(priv->dev, "THS_HEADERCNT: 0x%x\n", val); tc358768_write(priv, TC358768_THS_HEADERCNT, val); /* TWAKEUP > 1ms in lptxcnt steps */ val = tc358768_ns_to_cnt(102, dsibclk_nsk); val = val / (lptxcnt + 1) - 1; - dev_dbg(priv->dev, "TWAKEUP: 0x%x\n", val); + dev_dbg(priv->dev, "TWAKEUP: %u\n", val); tc358768_write(priv, TC358768_TWAKEUP, val); /* TCLK_POSTCNT > 60ns + 52*UI */ val = tc358768_ns_to_cnt(60 + tc358768_to_ns(52 * ui_nsk), dsibclk_nsk) - 3; - dev_dbg(priv->dev, "TCLK_POSTCNT: 0x%x\n", val); + dev_dbg(priv->dev, "TCLK_POSTCNT: %u\n", val); tc358768_write(priv, TC358768_TCLK_POSTCNT, val); /* max(60ns + 4*UI, 8*UI) < THS_TRAILCNT < 105ns + 12*UI */ raw_val = tc358768_ns_to_cnt(60 + tc358768_to_ns(18 * ui_nsk), dsibclk_nsk) - 4; val = clamp(raw_val, 0, 15); - dev_dbg(priv->dev, "THS_TRAILCNT: 0x%x\n", val); + dev_dbg(priv->dev, "THS_TRAILCNT: %u\n", val); tc358768_write(priv, TC358768_THS_TRAILCNT, val); val = BIT(0); @@ -803,10 +805,11 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) /* TXTAGOCNT[26:16] RXTASURECNT[10:0] */ val = tc358768_to_ns((lptxcnt + 1) * dsibclk_nsk * 4); val = tc358768_ns_to_cnt(val, dsibclk_nsk) / 4 - 1; + dev_dbg(priv->dev, "TXTAGOCNT: %u\n", val); val2 = tc358768_ns_to_cnt(tc358768_to_ns((lptxcnt + 1) * dsibclk_nsk), dsibclk_nsk) - 2; + dev_dbg(priv->dev, "RXTASURECNT: %u\n", val2); val = val << 16 | val2; - dev_dbg(priv->dev, "BTACNTRL1: 0x%x\n", val); tc358768_write(priv, TC358768_BTACNTRL1, val); /* START[0] */ -- 2.34.1
[PATCH v4 09/12] drm/bridge: tc358768: Rename dsibclk to hsbyteclk
The Toshiba documentation talks about HSByteClk when referring to the DSI HS byte clock, whereas the driver uses 'dsibclk' name. Also, in a few places the driver calculates the byte clock from the DSI clock, even if the byte clock is already available in a variable. To align the driver with the documentation, change the 'dsibclk' variable to 'hsbyteclk'. This also make it easier to visually separate 'dsibclk' and 'dsiclk' variables. Reviewed-by: Peter Ujfalusi Tested-by: Maxim Schwalm # Asus TF700T Tested-by: Marcel Ziswiler Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/bridge/tc358768.c | 48 +++ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index 6297d28250e9..0f117d673b14 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -604,7 +604,7 @@ static int tc358768_setup_pll(struct tc358768_priv *priv, dev_dbg(priv->dev, "PLL: refclk %lu, fbd %u, prd %u, frs %u\n", clk_get_rate(priv->refclk), fbd, prd, frs); - dev_dbg(priv->dev, "PLL: pll_clk: %u, DSIClk %u, DSIByteClk %u\n", + dev_dbg(priv->dev, "PLL: pll_clk: %u, DSIClk %u, HSByteClk %u\n", priv->dsiclk * 2, priv->dsiclk, priv->dsiclk / 4); dev_dbg(priv->dev, "PLL: pclk %u (panel: %u)\n", tc358768_pll_to_pclk(priv, priv->dsiclk * 2), @@ -646,8 +646,8 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) u32 val, val2, lptxcnt, hact, data_type; s32 raw_val; const struct drm_display_mode *mode; - u32 dsibclk_nsk, dsiclk_nsk, ui_nsk; - u32 dsiclk, dsibclk, video_start; + u32 hsbyteclk_nsk, dsiclk_nsk, ui_nsk; + u32 dsiclk, hsbyteclk, video_start; const u32 internal_delay = 40; int ret, i; struct videomode vm; @@ -678,7 +678,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) drm_display_mode_to_videomode(mode, &vm); dsiclk = priv->dsiclk; - dsibclk = dsiclk / 4; + hsbyteclk = dsiclk / 4; /* Data Format Control Register */ val = BIT(2) | BIT(1) | BIT(0); /* rdswap_en | dsitx_en | txdt_en */ @@ -730,67 +730,67 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) tc358768_write(priv, TC358768_D0W_CNTRL + i * 4, 0x); /* DSI Timings */ - dsibclk_nsk = (u32)div_u64((u64)10 * TC358768_PRECISION, - dsibclk); + hsbyteclk_nsk = (u32)div_u64((u64)10 * TC358768_PRECISION, + hsbyteclk); dsiclk_nsk = (u32)div_u64((u64)10 * TC358768_PRECISION, dsiclk); ui_nsk = dsiclk_nsk / 2; dev_dbg(dev, "dsiclk_nsk: %u\n", dsiclk_nsk); dev_dbg(dev, "ui_nsk: %u\n", ui_nsk); - dev_dbg(dev, "dsibclk_nsk: %u\n", dsibclk_nsk); + dev_dbg(dev, "hsbyteclk_nsk: %u\n", hsbyteclk_nsk); /* LP11 > 100us for D-PHY Rx Init */ - val = tc358768_ns_to_cnt(100 * 1000, dsibclk_nsk) - 1; + val = tc358768_ns_to_cnt(100 * 1000, hsbyteclk_nsk) - 1; dev_dbg(dev, "LINEINITCNT: %u\n", val); tc358768_write(priv, TC358768_LINEINITCNT, val); /* LPTimeCnt > 50ns */ - val = tc358768_ns_to_cnt(50, dsibclk_nsk) - 1; + val = tc358768_ns_to_cnt(50, hsbyteclk_nsk) - 1; lptxcnt = val; dev_dbg(dev, "LPTXTIMECNT: %u\n", val); tc358768_write(priv, TC358768_LPTXTIMECNT, val); /* 38ns < TCLK_PREPARE < 95ns */ - val = tc358768_ns_to_cnt(65, dsibclk_nsk) - 1; + val = tc358768_ns_to_cnt(65, hsbyteclk_nsk) - 1; dev_dbg(dev, "TCLK_PREPARECNT %u\n", val); /* TCLK_PREPARE + TCLK_ZERO > 300ns */ val2 = tc358768_ns_to_cnt(300 - tc358768_to_ns(2 * ui_nsk), - dsibclk_nsk) - 2; + hsbyteclk_nsk) - 2; dev_dbg(dev, "TCLK_ZEROCNT %u\n", val2); val |= val2 << 8; tc358768_write(priv, TC358768_TCLK_HEADERCNT, val); /* TCLK_TRAIL > 60ns AND TEOT <= 105 ns + 12*UI */ - raw_val = tc358768_ns_to_cnt(60 + tc358768_to_ns(2 * ui_nsk), dsibclk_nsk) - 5; + raw_val = tc358768_ns_to_cnt(60 + tc358768_to_ns(2 * ui_nsk), hsbyteclk_nsk) - 5; val = clamp(raw_val, 0, 127); dev_dbg(dev, "TCLK_TRAILCNT: %u\n", val); tc358768_write(priv, TC358768_TCLK_TRAILCNT, val); /* 40ns + 4*UI < THS_PREPARE < 85ns + 6*UI */ val = 50 + tc358768_to_ns(4 * ui_nsk); - val = tc358768_ns_to_cnt(val, dsibclk_nsk) - 1; + val = tc358768_ns_to_cnt(val, hsbyteclk_nsk) - 1; dev_dbg(dev, "THS_PREPARECNT %u\n", val); /* THS_PREPARE + THS_ZERO > 145ns + 10*UI */ - raw_val = tc358768_ns_to_cnt(145 - tc358768_to_ns(3 * ui_nsk), dsibclk_nsk) - 10; + raw_val = tc358768_ns_to_cnt(145 - tc35876
[PATCH v4 10/12] drm/bridge: tc358768: Clean up clock period code
The driver defines TC358768_PRECISION as 1000, and uses "nsk" to refer to clock periods. The original author does not remember where all this came from. Effectively the driver is using picoseconds as the unit for clock periods, yet referring to them by "nsk". Clean this up by just saying the periods are in picoseconds. Reviewed-by: Peter Ujfalusi Tested-by: Maxim Schwalm # Asus TF700T Tested-by: Marcel Ziswiler Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/bridge/tc358768.c | 60 +++ 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index 0f117d673b14..9ce8d120b50c 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -627,15 +628,14 @@ static int tc358768_setup_pll(struct tc358768_priv *priv, return tc358768_clear_error(priv); } -#define TC358768_PRECISION 1000 -static u32 tc358768_ns_to_cnt(u32 ns, u32 period_nsk) +static u32 tc358768_ns_to_cnt(u32 ns, u32 period_ps) { - return (ns * TC358768_PRECISION + period_nsk) / period_nsk; + return (ns * 1000 + period_ps) / period_ps; } -static u32 tc358768_to_ns(u32 nsk) +static u32 tc358768_ps_to_ns(u32 ps) { - return (nsk / TC358768_PRECISION); + return ps / 1000; } static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) @@ -646,7 +646,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) u32 val, val2, lptxcnt, hact, data_type; s32 raw_val; const struct drm_display_mode *mode; - u32 hsbyteclk_nsk, dsiclk_nsk, ui_nsk; + u32 hsbyteclk_ps, dsiclk_ps, ui_ps; u32 dsiclk, hsbyteclk, video_start; const u32 internal_delay = 40; int ret, i; @@ -730,67 +730,65 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) tc358768_write(priv, TC358768_D0W_CNTRL + i * 4, 0x); /* DSI Timings */ - hsbyteclk_nsk = (u32)div_u64((u64)10 * TC358768_PRECISION, - hsbyteclk); - dsiclk_nsk = (u32)div_u64((u64)10 * TC358768_PRECISION, dsiclk); - ui_nsk = dsiclk_nsk / 2; - dev_dbg(dev, "dsiclk_nsk: %u\n", dsiclk_nsk); - dev_dbg(dev, "ui_nsk: %u\n", ui_nsk); - dev_dbg(dev, "hsbyteclk_nsk: %u\n", hsbyteclk_nsk); + hsbyteclk_ps = (u32)div_u64(PICO, hsbyteclk); + dsiclk_ps = (u32)div_u64(PICO, dsiclk); + ui_ps = dsiclk_ps / 2; + dev_dbg(dev, "dsiclk: %u ps, ui %u ps, hsbyteclk %u ps\n", dsiclk_ps, + ui_ps, hsbyteclk_ps); /* LP11 > 100us for D-PHY Rx Init */ - val = tc358768_ns_to_cnt(100 * 1000, hsbyteclk_nsk) - 1; + val = tc358768_ns_to_cnt(100 * 1000, hsbyteclk_ps) - 1; dev_dbg(dev, "LINEINITCNT: %u\n", val); tc358768_write(priv, TC358768_LINEINITCNT, val); /* LPTimeCnt > 50ns */ - val = tc358768_ns_to_cnt(50, hsbyteclk_nsk) - 1; + val = tc358768_ns_to_cnt(50, hsbyteclk_ps) - 1; lptxcnt = val; dev_dbg(dev, "LPTXTIMECNT: %u\n", val); tc358768_write(priv, TC358768_LPTXTIMECNT, val); /* 38ns < TCLK_PREPARE < 95ns */ - val = tc358768_ns_to_cnt(65, hsbyteclk_nsk) - 1; + val = tc358768_ns_to_cnt(65, hsbyteclk_ps) - 1; dev_dbg(dev, "TCLK_PREPARECNT %u\n", val); /* TCLK_PREPARE + TCLK_ZERO > 300ns */ - val2 = tc358768_ns_to_cnt(300 - tc358768_to_ns(2 * ui_nsk), - hsbyteclk_nsk) - 2; + val2 = tc358768_ns_to_cnt(300 - tc358768_ps_to_ns(2 * ui_ps), + hsbyteclk_ps) - 2; dev_dbg(dev, "TCLK_ZEROCNT %u\n", val2); val |= val2 << 8; tc358768_write(priv, TC358768_TCLK_HEADERCNT, val); /* TCLK_TRAIL > 60ns AND TEOT <= 105 ns + 12*UI */ - raw_val = tc358768_ns_to_cnt(60 + tc358768_to_ns(2 * ui_nsk), hsbyteclk_nsk) - 5; + raw_val = tc358768_ns_to_cnt(60 + tc358768_ps_to_ns(2 * ui_ps), hsbyteclk_ps) - 5; val = clamp(raw_val, 0, 127); dev_dbg(dev, "TCLK_TRAILCNT: %u\n", val); tc358768_write(priv, TC358768_TCLK_TRAILCNT, val); /* 40ns + 4*UI < THS_PREPARE < 85ns + 6*UI */ - val = 50 + tc358768_to_ns(4 * ui_nsk); - val = tc358768_ns_to_cnt(val, hsbyteclk_nsk) - 1; + val = 50 + tc358768_ps_to_ns(4 * ui_ps); + val = tc358768_ns_to_cnt(val, hsbyteclk_ps) - 1; dev_dbg(dev, "THS_PREPARECNT %u\n", val); /* THS_PREPARE + THS_ZERO > 145ns + 10*UI */ - raw_val = tc358768_ns_to_cnt(145 - tc358768_to_ns(3 * ui_nsk), hsbyteclk_nsk) - 10; + raw_val = tc358768_ns_to_cnt(145 - tc358768_ps_to_ns(3 * ui_ps), hsbyteclk_ps) - 10; val2 = clamp(raw_val, 0, 127); dev_dbg(dev, "THS_ZEROCNT %u\n", val2); val |= val2 << 8; tc358768_writ
[PATCH v4 12/12] drm/bridge: tc358768: Attempt to fix DSI horizontal timings
The DSI horizontal timing calculations done by the driver seem to often lead to underflows or overflows, depending on the videomode. There are two main things the current driver doesn't seem to get right: DSI HSW and HFP, and VSDly. However, even following Toshiba's documentation it seems we don't always get a working display. This patch attempts to fix the horizontal timings for DSI event mode, and on a system with a DSI->HDMI encoder, a lot of standard HDMI modes now seem to work. The work relies on Toshiba's documentation, but also quite a bit on empirical testing. This also adds timing related debug prints to make it easier to improve on this later. The DSI pulse mode has only been tested with a fixed-resolution panel, which limits the testing of different modes on DSI pulse mode. However, as the VSDly calculation also affects pulse mode, so this might cause a regression. Reviewed-by: Peter Ujfalusi Tested-by: Marcel Ziswiler Tested-by: Maxim Schwalm # Asus TF700T Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/bridge/tc358768.c | 211 +- 1 file changed, 183 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index f41bf56b7d6b..e5ecf1a79e82 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -157,6 +158,7 @@ struct tc358768_priv { u32 frs;/* PLL Freqency range for HSCK (post divider) */ u32 dsiclk; /* pll_clk / 2 */ + u32 pclk; /* incoming pclk rate */ }; static inline struct tc358768_priv *dsi_host_to_tc358768(struct mipi_dsi_host @@ -380,6 +382,7 @@ static int tc358768_calc_pll(struct tc358768_priv *priv, priv->prd = best_prd; priv->frs = frs; priv->dsiclk = best_pll / 2; + priv->pclk = mode->clock * 1000; return 0; } @@ -638,6 +641,28 @@ static u32 tc358768_ps_to_ns(u32 ps) return ps / 1000; } +static u32 tc358768_dpi_to_ns(u32 val, u32 pclk) +{ + return (u32)div_u64((u64)val * NANO, pclk); +} + +/* Convert value in DPI pixel clock units to DSI byte count */ +static u32 tc358768_dpi_to_dsi_bytes(struct tc358768_priv *priv, u32 val) +{ + u64 m = (u64)val * priv->dsiclk / 4 * priv->dsi_lanes; + u64 n = priv->pclk; + + return (u32)div_u64(m + n - 1, n); +} + +static u32 tc358768_dsi_bytes_to_ns(struct tc358768_priv *priv, u32 val) +{ + u64 m = (u64)val * NANO; + u64 n = priv->dsiclk / 4 * priv->dsi_lanes; + + return (u32)div_u64(m, n); +} + static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) { struct tc358768_priv *priv = bridge_to_tc358768(bridge); @@ -647,11 +672,19 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) s32 raw_val; const struct drm_display_mode *mode; u32 hsbyteclk_ps, dsiclk_ps, ui_ps; - u32 dsiclk, hsbyteclk, video_start; - const u32 internal_delay = 40; + u32 dsiclk, hsbyteclk; int ret, i; struct videomode vm; struct device *dev = priv->dev; + /* In pixelclock units */ + u32 dpi_htot, dpi_data_start; + /* In byte units */ + u32 dsi_dpi_htot, dsi_dpi_data_start; + u32 dsi_hsw, dsi_hbp, dsi_hact, dsi_hfp; + const u32 dsi_hss = 4; /* HSS is a short packet (4 bytes) */ + /* In hsbyteclk units */ + u32 dsi_vsdly; + const u32 internal_dly = 40; if (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) { dev_warn_once(dev, "Non-continuous mode unimplemented, falling back to continuous\n"); @@ -686,27 +719,23 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) case MIPI_DSI_FMT_RGB888: val |= (0x3 << 4); hact = vm.hactive * 3; - video_start = (vm.hsync_len + vm.hback_porch) * 3; data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; break; case MIPI_DSI_FMT_RGB666: val |= (0x4 << 4); hact = vm.hactive * 3; - video_start = (vm.hsync_len + vm.hback_porch) * 3; data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; break; case MIPI_DSI_FMT_RGB666_PACKED: val |= (0x4 << 4) | BIT(3); hact = vm.hactive * 18 / 8; - video_start = (vm.hsync_len + vm.hback_porch) * 18 / 8; data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; break; case MIPI_DSI_FMT_RGB565: val |= (0x5 << 4); hact = vm.hactive * 2; - video_start = (vm.hsync_len + vm.hback_porch) * 2; data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; break; default: @@ -716,9 +745,150 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
[PATCH v4 06/12] drm/bridge: tc358768: Use struct videomode
The TC358768 documentation uses HFP, HBP, etc. values to deal with the video mode, while the driver currently uses the DRM display mode (htotal, hsync_start, etc). Change the driver to convert the DRM display mode to struct videomode, which then allows us to use the same units the documentation uses. This makes it much easier to work on the code when using the TC358768 documentation as a reference. Reviewed-by: Peter Ujfalusi Tested-by: Maxim Schwalm # Asus TF700T Tested-by: Marcel Ziswiler Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/bridge/tc358768.c | 45 +-- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index a465674f1e2e..b98c517c4726 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -650,6 +650,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) u32 dsiclk, dsibclk, video_start; const u32 internal_delay = 40; int ret, i; + struct videomode vm; if (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) { dev_warn_once(priv->dev, "Non-continuous mode unimplemented, falling back to continuous\n"); @@ -673,6 +674,8 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) return; } + drm_display_mode_to_videomode(mode, &vm); + dsiclk = priv->dsiclk; dsibclk = dsiclk / 4; @@ -681,28 +684,28 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) switch (dsi_dev->format) { case MIPI_DSI_FMT_RGB888: val |= (0x3 << 4); - hact = mode->hdisplay * 3; - video_start = (mode->htotal - mode->hsync_start) * 3; + hact = vm.hactive * 3; + video_start = (vm.hsync_len + vm.hback_porch) * 3; data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; break; case MIPI_DSI_FMT_RGB666: val |= (0x4 << 4); - hact = mode->hdisplay * 3; - video_start = (mode->htotal - mode->hsync_start) * 3; + hact = vm.hactive * 3; + video_start = (vm.hsync_len + vm.hback_porch) * 3; data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; break; case MIPI_DSI_FMT_RGB666_PACKED: val |= (0x4 << 4) | BIT(3); - hact = mode->hdisplay * 18 / 8; - video_start = (mode->htotal - mode->hsync_start) * 18 / 8; + hact = vm.hactive * 18 / 8; + video_start = (vm.hsync_len + vm.hback_porch) * 18 / 8; data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; break; case MIPI_DSI_FMT_RGB565: val |= (0x5 << 4); - hact = mode->hdisplay * 2; - video_start = (mode->htotal - mode->hsync_start) * 2; + hact = vm.hactive * 2; + video_start = (vm.hsync_len + vm.hback_porch) * 2; data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; break; default: @@ -814,43 +817,43 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) tc358768_write(priv, TC358768_DSI_EVENT, 0); /* vact */ - tc358768_write(priv, TC358768_DSI_VACT, mode->vdisplay); + tc358768_write(priv, TC358768_DSI_VACT, vm.vactive); /* vsw */ - tc358768_write(priv, TC358768_DSI_VSW, - mode->vsync_end - mode->vsync_start); + tc358768_write(priv, TC358768_DSI_VSW, vm.vsync_len); + /* vbp */ - tc358768_write(priv, TC358768_DSI_VBPR, - mode->vtotal - mode->vsync_end); + tc358768_write(priv, TC358768_DSI_VBPR, vm.vback_porch); /* hsw * byteclk * ndl / pclk */ - val = (u32)div_u64((mode->hsync_end - mode->hsync_start) * + val = (u32)div_u64(vm.hsync_len * ((u64)priv->dsiclk / 4) * priv->dsi_lanes, - mode->clock * 1000); + vm.pixelclock); tc358768_write(priv, TC358768_DSI_HSW, val); /* hbp * byteclk * ndl / pclk */ - val = (u32)div_u64((mode->htotal - mode->hsync_end) * + val = (u32)div_u64(vm.hback_porch * ((u64)priv->dsiclk / 4) * priv->dsi_lanes, - mode->clock * 1000); + vm.pixelclock); tc358768_write(priv, TC358768_DSI_HBPR, val); } else { /* Set event mode */ tc358768_write(priv, TC358768_DSI_EVENT, 1); /* vact */ - tc358768_write(priv, TC358768_DSI_VACT, mode->vdisplay); +
[PATCH v4 03/12] drm/bridge: tc358768: Default to positive h/v syncs
As the TC358768 is a DPI to DSI bridge, the DSI side does not need to define h/v sync polarities. This means that sometimes we have a mode without defined sync polarities, which does not work on the DPI side. Add a mode_fixup hook to default to positive sync polarities. Reviewed-by: Peter Ujfalusi Tested-by: Maxim Schwalm # Asus TF700T Tested-by: Marcel Ziswiler Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/bridge/tc358768.c | 18 ++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index bc97a837955b..963ac550509b 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -963,9 +963,27 @@ tc358768_atomic_get_input_bus_fmts(struct drm_bridge *bridge, return input_fmts; } +static bool tc358768_mode_fixup(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + /* Default to positive sync */ + + if (!(adjusted_mode->flags & + (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC))) + adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; + + if (!(adjusted_mode->flags & + (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))) + adjusted_mode->flags |= DRM_MODE_FLAG_PVSYNC; + + return true; +} + static const struct drm_bridge_funcs tc358768_bridge_funcs = { .attach = tc358768_bridge_attach, .mode_valid = tc358768_bridge_mode_valid, + .mode_fixup = tc358768_mode_fixup, .pre_enable = tc358768_bridge_pre_enable, .enable = tc358768_bridge_enable, .disable = tc358768_bridge_disable, -- 2.34.1
[PATCH v4 08/12] drm/bridge: tc358768: Use dev for dbg prints, not priv->dev
Simplify the code by capturing the priv->dev value to dev variable, and use it. Reviewed-by: Peter Ujfalusi Tested-by: Maxim Schwalm # Asus TF700T Tested-by: Marcel Ziswiler Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/bridge/tc358768.c | 41 --- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index 88060f961064..6297d28250e9 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -651,9 +651,10 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) const u32 internal_delay = 40; int ret, i; struct videomode vm; + struct device *dev = priv->dev; if (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) { - dev_warn_once(priv->dev, "Non-continuous mode unimplemented, falling back to continuous\n"); + dev_warn_once(dev, "Non-continuous mode unimplemented, falling back to continuous\n"); mode_flags &= ~MIPI_DSI_CLOCK_NON_CONTINUOUS; } @@ -661,7 +662,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) ret = tc358768_sw_reset(priv); if (ret) { - dev_err(priv->dev, "Software reset failed: %d\n", ret); + dev_err(dev, "Software reset failed: %d\n", ret); tc358768_hw_disable(priv); return; } @@ -669,7 +670,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) mode = &bridge->encoder->crtc->state->adjusted_mode; ret = tc358768_setup_pll(priv, mode); if (ret) { - dev_err(priv->dev, "PLL setup failed: %d\n", ret); + dev_err(dev, "PLL setup failed: %d\n", ret); tc358768_hw_disable(priv); return; } @@ -709,7 +710,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; break; default: - dev_err(priv->dev, "Invalid data format (%u)\n", + dev_err(dev, "Invalid data format (%u)\n", dsi_dev->format); tc358768_hw_disable(priv); return; @@ -733,65 +734,65 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) dsibclk); dsiclk_nsk = (u32)div_u64((u64)10 * TC358768_PRECISION, dsiclk); ui_nsk = dsiclk_nsk / 2; - dev_dbg(priv->dev, "dsiclk_nsk: %u\n", dsiclk_nsk); - dev_dbg(priv->dev, "ui_nsk: %u\n", ui_nsk); - dev_dbg(priv->dev, "dsibclk_nsk: %u\n", dsibclk_nsk); + dev_dbg(dev, "dsiclk_nsk: %u\n", dsiclk_nsk); + dev_dbg(dev, "ui_nsk: %u\n", ui_nsk); + dev_dbg(dev, "dsibclk_nsk: %u\n", dsibclk_nsk); /* LP11 > 100us for D-PHY Rx Init */ val = tc358768_ns_to_cnt(100 * 1000, dsibclk_nsk) - 1; - dev_dbg(priv->dev, "LINEINITCNT: %u\n", val); + dev_dbg(dev, "LINEINITCNT: %u\n", val); tc358768_write(priv, TC358768_LINEINITCNT, val); /* LPTimeCnt > 50ns */ val = tc358768_ns_to_cnt(50, dsibclk_nsk) - 1; lptxcnt = val; - dev_dbg(priv->dev, "LPTXTIMECNT: %u\n", val); + dev_dbg(dev, "LPTXTIMECNT: %u\n", val); tc358768_write(priv, TC358768_LPTXTIMECNT, val); /* 38ns < TCLK_PREPARE < 95ns */ val = tc358768_ns_to_cnt(65, dsibclk_nsk) - 1; - dev_dbg(priv->dev, "TCLK_PREPARECNT %u\n", val); + dev_dbg(dev, "TCLK_PREPARECNT %u\n", val); /* TCLK_PREPARE + TCLK_ZERO > 300ns */ val2 = tc358768_ns_to_cnt(300 - tc358768_to_ns(2 * ui_nsk), dsibclk_nsk) - 2; - dev_dbg(priv->dev, "TCLK_ZEROCNT %u\n", val2); + dev_dbg(dev, "TCLK_ZEROCNT %u\n", val2); val |= val2 << 8; tc358768_write(priv, TC358768_TCLK_HEADERCNT, val); /* TCLK_TRAIL > 60ns AND TEOT <= 105 ns + 12*UI */ raw_val = tc358768_ns_to_cnt(60 + tc358768_to_ns(2 * ui_nsk), dsibclk_nsk) - 5; val = clamp(raw_val, 0, 127); - dev_dbg(priv->dev, "TCLK_TRAILCNT: %u\n", val); + dev_dbg(dev, "TCLK_TRAILCNT: %u\n", val); tc358768_write(priv, TC358768_TCLK_TRAILCNT, val); /* 40ns + 4*UI < THS_PREPARE < 85ns + 6*UI */ val = 50 + tc358768_to_ns(4 * ui_nsk); val = tc358768_ns_to_cnt(val, dsibclk_nsk) - 1; - dev_dbg(priv->dev, "THS_PREPARECNT %u\n", val); + dev_dbg(dev, "THS_PREPARECNT %u\n", val); /* THS_PREPARE + THS_ZERO > 145ns + 10*UI */ raw_val = tc358768_ns_to_cnt(145 - tc358768_to_ns(3 * ui_nsk), dsibclk_nsk) - 10; val2 = clamp(raw_val, 0, 127); - dev_dbg(priv->dev, "THS_ZEROCNT %u\n", val2); + dev_dbg(dev, "THS_ZEROCNT %u\n", val2); val |= val2 << 8; tc358768_write(priv, TC358768_THS_HEADERCNT, val); /* TWAKE
[PATCH v4 04/12] drm/bridge: tc358768: Fix bit updates
The driver has a few places where it does: if (thing_is_enabled_in_config) update_thing_bit_in_hw() This means that if the thing is _not_ enabled, the bit never gets cleared. This affects the h/vsyncs and continuous DSI clock bits. Fix the driver to always update the bit. Fixes: ff1ca6397b1d ("drm/bridge: Add tc358768 driver") Reviewed-by: Peter Ujfalusi Tested-by: Maxim Schwalm # Asus TF700T Tested-by: Marcel Ziswiler Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/bridge/tc358768.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index 963ac550509b..2af23f1e 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -794,8 +794,8 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) val |= BIT(i + 1); tc358768_write(priv, TC358768_HSTXVREGEN, val); - if (!(mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) - tc358768_write(priv, TC358768_TXOPTIONCNTRL, 0x1); + tc358768_write(priv, TC358768_TXOPTIONCNTRL, + (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) ? 0 : BIT(0)); /* TXTAGOCNT[26:16] RXTASURECNT[10:0] */ val = tc358768_to_ns((lptxcnt + 1) * dsibclk_nsk * 4); @@ -861,11 +861,12 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) tc358768_write(priv, TC358768_DSI_HACT, hact); /* VSYNC polarity */ - if (!(mode->flags & DRM_MODE_FLAG_NVSYNC)) - tc358768_update_bits(priv, TC358768_CONFCTL, BIT(5), BIT(5)); + tc358768_update_bits(priv, TC358768_CONFCTL, BIT(5), +(mode->flags & DRM_MODE_FLAG_PVSYNC) ? BIT(5) : 0); + /* HSYNC polarity */ - if (mode->flags & DRM_MODE_FLAG_PHSYNC) - tc358768_update_bits(priv, TC358768_PP_MISC, BIT(0), BIT(0)); + tc358768_update_bits(priv, TC358768_PP_MISC, BIT(0), +(mode->flags & DRM_MODE_FLAG_PHSYNC) ? BIT(0) : 0); /* Start DSI Tx */ tc358768_write(priv, TC358768_DSI_START, 0x1); -- 2.34.1
[PATCH v4 01/12] drm/tegra: rgb: Parameterize V- and H-sync polarities
From: Thierry Reding The polarities of the V- and H-sync signals are encoded as flags in the display mode, so use the existing information to setup the signals for the RGB interface. Signed-off-by: Thierry Reding Cc: Thierry Reding [tomi.valkei...@ideasonboard.com: default to positive sync] Reviewed-by: Peter Ujfalusi Tested-by: Maxim Schwalm # Asus TF700T Tested-by: Marcel Ziswiler Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/tegra/rgb.c | 16 +--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index 79566c9ea8ff..fc66bbd913b2 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -99,6 +99,7 @@ static void tegra_rgb_encoder_disable(struct drm_encoder *encoder) static void tegra_rgb_encoder_enable(struct drm_encoder *encoder) { + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct tegra_output *output = encoder_to_output(encoder); struct tegra_rgb *rgb = to_rgb(output); u32 value; @@ -108,10 +109,19 @@ static void tegra_rgb_encoder_enable(struct drm_encoder *encoder) value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL; tegra_dc_writel(rgb->dc, value, DC_DISP_DATA_ENABLE_OPTIONS); - /* XXX: parameterize? */ + /* configure H- and V-sync signal polarities */ value = tegra_dc_readl(rgb->dc, DC_COM_PIN_OUTPUT_POLARITY(1)); - value &= ~LVS_OUTPUT_POLARITY_LOW; - value &= ~LHS_OUTPUT_POLARITY_LOW; + + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + value |= LHS_OUTPUT_POLARITY_LOW; + else + value &= ~LHS_OUTPUT_POLARITY_LOW; + + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + value |= LVS_OUTPUT_POLARITY_LOW; + else + value &= ~LVS_OUTPUT_POLARITY_LOW; + tegra_dc_writel(rgb->dc, value, DC_COM_PIN_OUTPUT_POLARITY(1)); /* XXX: parameterize? */ -- 2.34.1
[PATCH v4 05/12] drm/bridge: tc358768: Cleanup PLL calculations
As is quite common, some of TC358768's PLL register fields are to be programmed with (value - 1). Specifically, the FBD and PRD, multiplier and divider, are such fields. However, what the driver currently does is that it considers that the formula used for PLL rate calculation is: RefClk * [(FBD + 1)/ (PRD + 1)] * [1 / (2^FRS)] where FBD and PRD are values directly from the registers, while a more sensible way to look at it is: RefClk * FBD / PRD * (1 / (2^FRS)) and when the FBD and PRD values are written to the registers, they will be subtracted by one. Change the driver accordingly, as it simplifies the PLL code. Reviewed-by: Peter Ujfalusi Tested-by: Maxim Schwalm # Asus TF700T Tested-by: Marcel Ziswiler Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/bridge/tc358768.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index 2af23f1e..a465674f1e2e 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -316,7 +316,7 @@ static int tc358768_calc_pll(struct tc358768_priv *priv, target_pll = tc358768_pclk_to_pll(priv, mode->clock * 1000); - /* pll_clk = RefClk * [(FBD + 1)/ (PRD + 1)] * [1 / (2^FRS)] */ + /* pll_clk = RefClk * FBD / PRD * (1 / (2^FRS)) */ for (i = 0; i < ARRAY_SIZE(frs_limits); i++) if (target_pll >= frs_limits[i]) @@ -336,19 +336,19 @@ static int tc358768_calc_pll(struct tc358768_priv *priv, best_prd = 0; best_fbd = 0; - for (prd = 0; prd < 16; ++prd) { - u32 divisor = (prd + 1) * (1 << frs); + for (prd = 1; prd <= 16; ++prd) { + u32 divisor = prd * (1 << frs); u32 fbd; - for (fbd = 0; fbd < 512; ++fbd) { + for (fbd = 1; fbd <= 512; ++fbd) { u32 pll, diff, pll_in; - pll = (u32)div_u64((u64)refclk * (fbd + 1), divisor); + pll = (u32)div_u64((u64)refclk * fbd, divisor); if (pll >= max_pll || pll < min_pll) continue; - pll_in = (u32)div_u64((u64)refclk, prd + 1); + pll_in = (u32)div_u64((u64)refclk, prd); if (pll_in < 400) continue; @@ -611,7 +611,7 @@ static int tc358768_setup_pll(struct tc358768_priv *priv, mode->clock * 1000); /* PRD[15:12] FBD[8:0] */ - tc358768_write(priv, TC358768_PLLCTL0, (prd << 12) | fbd); + tc358768_write(priv, TC358768_PLLCTL0, ((prd - 1) << 12) | (fbd - 1)); /* FRS[11:10] LBWS[9:8] CKEN[4] RESETB[1] EN[0] */ tc358768_write(priv, TC358768_PLLCTL1, -- 2.34.1
[PATCH v4 02/12] drm/bridge: tc358768: Fix use of uninitialized variable
smatch reports: drivers/gpu/drm/bridge/tc358768.c:223 tc358768_update_bits() error: uninitialized symbol 'orig'. Fix this by bailing out from tc358768_update_bits() if the tc358768_read() produces an error. Fixes: ff1ca6397b1d ("drm/bridge: Add tc358768 driver") Reviewed-by: Peter Ujfalusi Tested-by: Maxim Schwalm # Asus TF700T Tested-by: Marcel Ziswiler Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/bridge/tc358768.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c index 819a4b6ec2a0..bc97a837955b 100644 --- a/drivers/gpu/drm/bridge/tc358768.c +++ b/drivers/gpu/drm/bridge/tc358768.c @@ -216,6 +216,10 @@ static void tc358768_update_bits(struct tc358768_priv *priv, u32 reg, u32 mask, u32 tmp, orig; tc358768_read(priv, reg, &orig); + + if (priv->error) + return; + tmp = orig & ~mask; tmp |= val & mask; if (tmp != orig) -- 2.34.1
[PATCH v4 00/12] drm/bridge: tc358768: Fixes and timings improvements
This series contains various fixes and cleanups for TC358768. The target of this work is to get TC358768 working on Toradex's AM62 based board, which has the following display pipeline: AM62 DPI -> TC358768 -> LT8912B -> HDMI connector The main thing the series does is to improve the DSI HSW, HFP and VSDly calculations. Tomi Signed-off-by: Tomi Valkeinen --- Changes in v4: - Add Tested-by tags - Fix a typo in a comment - Link to v3: https://lore.kernel.org/r/20230822-tc358768-v3-0-c82405dac...@ideasonboard.com Changes in v3: - Add Peter's reviewed-bys - Move "Default to positive h/v syncs" earlier in the series to avoid regression in the middle of the series - Link to v2: https://lore.kernel.org/r/20230816-tc358768-v2-0-242b9d5f7...@ideasonboard.com Changes in v2: - Add "drm/tegra: rgb: Parameterize V- and H-sync polarities" so that Tegra can configure the polarities correctly. - Add "drm/bridge: tc358768: Default to positive h/v syncs" as we don't (necessarily) have the polarities set in the mode. - Drop "drm/bridge: tc358768: Add DRM_BRIDGE_ATTACH_NO_CONNECTOR support" as it's not needed for DRM_BRIDGE_ATTACH_NO_CONNECTOR support. - Link to v1: https://lore.kernel.org/r/20230804-tc358768-v1-0-1afd44b78...@ideasonboard.com --- Thierry Reding (1): drm/tegra: rgb: Parameterize V- and H-sync polarities Tomi Valkeinen (11): drm/bridge: tc358768: Fix use of uninitialized variable drm/bridge: tc358768: Default to positive h/v syncs drm/bridge: tc358768: Fix bit updates drm/bridge: tc358768: Cleanup PLL calculations drm/bridge: tc358768: Use struct videomode drm/bridge: tc358768: Print logical values, not raw register values drm/bridge: tc358768: Use dev for dbg prints, not priv->dev drm/bridge: tc358768: Rename dsibclk to hsbyteclk drm/bridge: tc358768: Clean up clock period code drm/bridge: tc358768: Fix tc358768_ns_to_cnt() drm/bridge: tc358768: Attempt to fix DSI horizontal timings drivers/gpu/drm/bridge/tc358768.c | 381 -- drivers/gpu/drm/tegra/rgb.c | 16 +- 2 files changed, 295 insertions(+), 102 deletions(-) --- base-commit: f45acf7acf75921c0409d452f0165f51a19a74fd change-id: 20230804-tc358768-1b6949ef2e3d Best regards, -- Tomi Valkeinen
Re: [Intel-gfx] [PATCH v5] drm/i915: Avoid circular locking dependency when flush delayed work on gt reset
On Mon, Aug 28, 2023 at 04:01:38PM -0700, John Harrison wrote: > On 8/23/2023 10:37, John Harrison wrote: > > On 8/23/2023 09:00, Daniel Vetter wrote: > > > On Tue, Aug 22, 2023 at 11:53:24AM -0700, John Harrison wrote: > > > > On 8/11/2023 11:20, Zhanjun Dong wrote: > > > > > This attempts to avoid circular locking dependency between > > > > > flush delayed > > > > > work and intel_gt_reset. > > > > > When intel_gt_reset was called, task will hold a lock. > > > > > To cacel delayed work here, the _sync version will also > > > > > acquire a lock, > > > > > which might trigger the possible cirular locking dependency warning. > > > > > When intel_gt_reset called, reset_in_progress flag will be > > > > > set, add code > > > > > to check the flag, call async verion if reset is in progress. > > > > > > > > > > Signed-off-by: Zhanjun Dong > > > > > Cc: John Harrison > > > > > Cc: Andi Shyti > > > > > Cc: Daniel Vetter > > > > > --- > > > > > drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 11 ++- > > > > > 1 file changed, 10 insertions(+), 1 deletion(-) > > > > > > > > > > diff --git > > > > > a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > > > > > b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > > > > > index a0e3ef1c65d2..600388c849f7 100644 > > > > > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > > > > > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > > > > > @@ -1359,7 +1359,16 @@ static void > > > > > guc_enable_busyness_worker(struct intel_guc *guc) > > > > > static void guc_cancel_busyness_worker(struct intel_guc *guc) > > > > > { > > > > > - cancel_delayed_work_sync(&guc->timestamp.work); > > > > > + /* > > > > > + * When intel_gt_reset was called, task will hold a lock. > > > > > + * To cacel delayed work here, the _sync version will > > > > > also acquire a lock, which might > > > > > + * trigger the possible cirular locking dependency warning. > > > > > + * Check the reset_in_progress flag, call async verion > > > > > if reset is in progress. > > > > > + */ > > > > This needs to explain in much more detail what is going on and > > > > why it is not > > > > a problem. E.g.: > > > > > > > > The busyness worker needs to be cancelled. In general that means > > > > using the synchronous cancel version to ensure that an in-progress > > > > worker will not keep executing beyond whatever is happening that > > > > needs the cancel. E.g. suspend, driver unload, etc. However, in the > > > > case of a reset, the synchronous version is not required and can > > > > trigger a false deadlock detection warning. > > > > > > > > The business worker takes the reset mutex to protect against resets > > > > interfering with it. However, it does a trylock and bails > > > > out if the > > > > reset lock is already acquired. Thus there is no actual deadlock or > > > > other concern with the worker running concurrently with a reset. So > > > > an asynchronous cancel is safe in the case of a reset rather than a > > > > driver unload or suspend type operation. On the other hand, if the > > > > cancel_sync version is used when a reset is in progress then the > > > > mutex deadlock detection sees the mutex being acquired through > > > > multiple paths and complains. > > > > > > > > So just don't bother. That keeps the detection code happy and is > > > > safe because of the trylock code described above. > > > So why do we even need to cancel anything if it doesn't do anything > > > while > > > the reset is in progress? > > It still needs to be cancelled. The worker only aborts if it is actively > > executing concurrently with the reset. It might not start to execute > > until after the reset has completed. And there is presumably a reason > > why the cancel is being called, a reason not necessarily related to > > resets at all. Leaving the worker to run arbitrarily after the driver is > > expecting it to be stopped will lead to much worse things than a fake > > lockdep splat, e.g. a use after free pointer deref. > > > > John. > @Daniel Vetter - ping? Is this explanation sufficient? Are you okay with > this change now? Sorry for the late reply, I'm constantly behind on mails :-/ Ping me on irc next time around if I don't reply, that's quicker. "presumably" isn't good enough for locking design. Either you know, and can prove it all, or you shouldn't touch the code and its locking design before you've figured this out. Again, either this is a deadlock, race condition, or the cancel isn't necessary. And this argument works in full generality. All this patch does it replace the dealock with one of the other two, and that's not good enough if you don't even know which one it is. - if you need the cancel, you have a race condition - if you don't have a race condition, you don't need the cancel - currently you have the deadlock "presumably" and "maybe" aint enoug for locking design
Re: [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
Am 05.09.23 um 16:28 schrieb Sui Jingfeng: Hi, On 2023/9/5 21:28, Christian König wrote: 2) Typically, those non-86 machines don't have a good UEFI firmware support, which doesn't support select primary GPU as firmware stage. Even on x86, there are old UEFI firmwares which already made undesired decision for you. 3) This series is attempt to solve the remain problems at the driver level, while another series[1] of me is target to solve the majority of the problems at device level. Tested (limited) on x86 with four video card mounted, Intel UHD Graphics 630 is the default boot VGA, successfully override by ast2400 with ast.modeset=10 append at the kernel cmd line. The value 10 is incredibly arbitrary, and multiplied as a magic number all over the place. +1 This is the exact reason why I made this series as RFC, because this is a open-ended problem. The choices of 3,4,5,6,7,8 and 9 are as arbitrary as the number of '10'. '1' and '2' is definitely not suitable, because the seat has already been taken. Well you are completely missing the point. *DON'T* abuse the modeset module parameters for this! If you use 10 or any other value doesn't matter. Regards, Christian. Take the drm/nouveau as an example: ``` MODULE_PARM_DESC(modeset, "enable driver (default: auto, " "0 = disabled, 1 = enabled, 2 = headless)"); int nouveau_modeset = -1; module_param_named(modeset, nouveau_modeset, int, 0400); ``` '1' is for enable the drm driver, some driver even override the 'nomodeset' parameter. '2' is not suitable, because nouveau use it as headless GPU (render-only or compute class GPU?) '3' is also not likely the best, the concerns is that what if a specific drm driver want to expand the usage in the future? The reason I pick up the digit '10' is that 1) The modeset parameter is unlikely to get expanded up to 10 usages. Other drm drivers only use the '-1', '0' and 1, choose '2' will conflict with drm/nouveau. By pick the digit '10', it leave some space(room) to various device driver authors. It also helps to keep the usage consistent across various drivers. 2) An int taken up 4 byte, I don't want to waste even a single byte, While in the process of defencing my patch, I have to say draft another kernel command line would cause the wasting of precious RAM storage. An int can have 2^31 usage, why we can't improve the utilization rate? 3) Please consider the fact that the modeset is the most common and attractive parameter No name is better than the 'modeset', as other name is not easy to remember. Again, this is for Linux user, thus it is not arbitrary. Despite simple and trivial, I think about it more than one week.
Re: [Nouveau] [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
Am 05.09.23 um 15:30 schrieb suijingfeng: Hi, On 2023/9/5 18:45, Thomas Zimmermann wrote: Hi Am 04.09.23 um 21:57 schrieb Sui Jingfeng: From: Sui Jingfeng On a machine with multiple GPUs, a Linux user has no control over which one is primary at boot time. This series tries to solve above mentioned If anything, the primary graphics adapter is the one initialized by the firmware. I think our boot-up graphics also make this assumption implicitly. Yes, but by the time of DRM drivers get loaded successfully,the boot-up graphics already finished. This is an incorrect assumption. drm_aperture_remove_conflicting_pci_framebuffers() and co don't kill the framebuffer, they just remove the current framebuffer driver to avoid further updates. So what happens (at least for amdgpu) is that we take over the framebuffer, including both mode and it's contents, and provide a new framebuffer interface until DRM masters like X or Wayland take over. Firmware framebuffer device already get killed by the drm_aperture_remove_conflicting_pci_framebuffers() function (or its siblings). So, this series is definitely not to interact with the firmware framebuffer (or more intelligent framebuffer drivers). It is for user space program, such as X server and Wayland compositor. Its for Linux user or drm drivers testers, which allow them to direct graphic display server using right hardware of interested as primary video card. Also, I believe that X server and Wayland compositor are the best test examples. If a specific DRM driver can't work with X server as a primary, then there probably have something wrong. But what's the use case for overriding this setting? On a specific machine with multiple GPUs mounted, only the primary graphics get POST-ed (initialized) by the firmware. Therefore, the DRM drivers for the rest video cards, have to choose to work without the prerequisite setups done by firmware, This is called as POST. Well, you don't seem to understand the background here. This is perfectly normal behavior. Secondary cards are posted after loading the appropriate DRM driver. At least for amdgpu this is done by calling the appropriate functions in the BIOS. One of the use cases of this series is to test if a specific DRM driver could works properly, even though there is no prerequisite works have been done by firmware at all. And it seems that the results is not satisfying in all cases. drm/ast is the first drm drivers which refused to work if not being POST-ed by the firmware. As far as I know this is expected as well. AST is a relatively simple driver and when it's not the primary one during boot the assumption is that it isn't used at all. Regards, Christian. Before apply this series, I was unable make drm/ast as the primary video card easily. On a multiple video card configuration, the monitor connected with the AST2400 not light up. While confusing, a naive programmer may suspect the PRIME is not working. After applied this series and passing ast.modeset=10 on the kernel cmd line, I found that the monitor connected with my ast2400 video card still black, It doesn't display and doesn't show image to me. While in the process of study drm/ast, I know that drm/ast driver has the POST code shipped. See the ast_post_gpu() function, then, I was wondering why this function doesn't works. After a short-time (hasty) debugging, I found that the the ast_post_gpu() function didn't get run. Because it have something to do with the ast->config_mode. Without thinking too much, I hardcoded the ast->config_mode as ast_use_p2a to force the ast_post_gpu() function get run. ``` --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -132,6 +132,8 @@ static int ast_device_config_init(struct ast_device *ast) } } + ast->config_mode = ast_use_p2a; + switch (ast->config_mode) { case ast_use_defaults: drm_info(dev, "Using default configuration\n"); ``` Then, the monitor light up, it display the Ubuntu greeter to me. Therefore, my patch is helpful, at lease for the Linux drm driver tester and developer. It allow programmers to test the specific part of the specific drive without changing a line of the source code and without the need of sudo authority. It helps to improve efficiency of the testing and patch verification. I know the PrimaryGPU option of Xorg conf, but this approach will remember the setup have been made, you need modify it with root authority each time you want to switch the primary. But on rapid developing and/or testing multiple video drivers, with only one computer hardware resource available. What we really want probably is a one-shoot command as this series provide. So, this is the first use case. This probably also help to test full modeset, PRIME and reverse PRIME on multiple video card machine. Best regards Thomas
Re: [RFT PATCH 13/15] drm/imx/ipuv3: Call drm_atomic_helper_shutdown() at shutdown/unbind time
Hi, On Di, 2023-09-05 at 13:29 -0700, Doug Anderson wrote: > Hi, > > On Mon, Sep 4, 2023 at 1:30 AM Philipp Zabel wrote: > > > > On Fr, 2023-09-01 at 16:41 -0700, Douglas Anderson wrote: > > > Based on grepping through the source code this driver appears to be > > > missing a call to drm_atomic_helper_shutdown() at system shutdown time > > > and at driver unbind time. Among other things, this means that if a > > > panel is in use that it won't be cleanly powered off at system > > > shutdown time. > > > > > > The fact that we should call drm_atomic_helper_shutdown() in the case > > > of OS shutdown/restart and at driver remove (or unbind) time comes > > > straight out of the kernel doc "driver instance overview" in > > > drm_drv.c. > > > > > > A few notes about this fix: > > > - When adding drm_atomic_helper_shutdown() to the unbind path, I added > > > it after drm_kms_helper_poll_fini() since that's when other drivers > > > seemed to have it. > > > - Technically with a previous patch, ("drm/atomic-helper: > > > drm_atomic_helper_shutdown(NULL) should be a noop"), we don't > > > actually need to check to see if our "drm" pointer is NULL before > > > calling drm_atomic_helper_shutdown(). We'll leave the "if" test in, > > > though, so that this patch can land without any dependencies. It > > > could potentially be removed later. > > > - This patch also makes sure to set the drvdata to NULL in the case of > > > bind errors to make sure that shutdown can't access freed data. > > > > > > Suggested-by: Maxime Ripard > > > Signed-off-by: Douglas Anderson > > > > Thank you, > > Tested-by: Philipp Zabel > > Thanks! I notice that: > > ./scripts/get_maintainer.pl --scm -f drivers/gpu/drm/imx/ipuv3/imx-drm-core.c > > Doesn't say drm-misc but also when I look at the MAINTAINERS file and > find the section for "DRM DRIVERS FOR FREESCALE IMX" That should probably say "IMX5/6" nowadays. There are a lot more i.MX that do not use IPUv3 than those that do. > it doesn't explicitly list a different git tree. I used to send pull requests from git.pengutronix.de/git/pza/linux, same as for the reset controller framework. I might still have to do that for changes in drivers/gpu/ipu-v3 that need coordination between drm and v4l2, but usually pure drm/imx/ipuv3 changes are pushed to drm- misc. > I guess the "shawnguo" git tree listed by get_maintainer.pl is just > from regex matching? The "N: imx" pattern in "ARM/FREESCALE IMX / MXC ARM ARCHITECTURE", I think. > Would you expect this to go through drm-misc? If so, I'll probably > land it sooner rather than later. I can also post up a patch making it > obvious that "DRM DRIVERS FOR FREESCALE IMX" goes through drm-misc if > you don't object. Yes, both would be great. regards Philipp
Re: [PATCH v2 2/7] drm: ci: Force db410c to host mode
Hi Maxime, On 05/09/23 19:10, Maxime Ripard wrote: With, &usb { dr_mode = "host"; }; The target is <0x> and fdtoverlay fails to apply the dtbo. You do have /plugin/ and have compiled the base device tree with overlay support, right? After compiling base dtbs with overlay support (make DTC_FLAGS=-@ dtbs) it works. With, &{/soc@0/usb} { dr_mode = "host"; }; The target-path is "/soc@0/usb" (usb: usb@78d9000) Right, and that's not the path you want to modify. The path you want to modify is /soc@0/usb@78d9000. usb is the label, it's absolute, and you can't mix and match a path ("/soc@0/") and a label ("usb") Thanks for the clarification. Regards, Vignesh
Re: [Nouveau] [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
Hi, On 2023/9/5 23:05, Thomas Zimmermann wrote: You might have found a bug in the ast driver. Ast has means to detect if the device has been POSTed and maybe do that. If this doesn't work correctly, it needs a fix. That sounds fine. The bug is not a big deal, I'm just take it as an example and report it to you. But a real fix can be complex, because there are quite a lot of servers ship with ASpeed BMC hardware. Honestly I don't have the time fix it on formal way. I have already tons patches in pending and I will focus on solve VGAARB related problem. Because I want to test your patch occasionally. So this series is useful for myself at corner cases.
Re: [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
Hi, On 2023/9/5 22:52, Alex Williamson wrote: On Tue, 5 Sep 2023 03:57:15 +0800 Sui Jingfeng wrote: From: Sui Jingfeng On a machine with multiple GPUs, a Linux user has no control over which one is primary at boot time. This series tries to solve above mentioned problem by introduced the ->be_primary() function stub. The specific device drivers can provide an implementation to hook up with this stub by calling the vga_client_register() function. Once the driver bound the device successfully, VGAARB will call back to the device driver. To query if the device drivers want to be primary or not. Device drivers can just pass NULL if have no such needs. Please note that: 1) The ARM64, Loongarch, Mips servers have a lot PCIe slot, and I would like to mount at least three video cards. 2) Typically, those non-86 machines don't have a good UEFI firmware support, which doesn't support select primary GPU as firmware stage. Even on x86, there are old UEFI firmwares which already made undesired decision for you. 3) This series is attempt to solve the remain problems at the driver level, while another series[1] of me is target to solve the majority of the problems at device level. Tested (limited) on x86 with four video card mounted, Intel UHD Graphics 630 is the default boot VGA, successfully override by ast2400 with ast.modeset=10 append at the kernel cmd line. $ lspci | grep VGA 00:02.0 VGA compatible controller: Intel Corporation CoffeeLake-S GT2 [UHD Graphics 630] In all my previous experiments with VGA routing and IGD I found that IGD can't actually release VGA routing and Intel confirmed the hardware doesn't have the ability to do so. Which model of the IGD you are using? even for the IGD in Atom D2550, the legacy 128KB VGA memory range can be tuned to be mapped to IGD or to the DMI Interface. See the 1.7.3.2 section of the N2000 datasheet[1]. If a specific model of Intel has a bug in the VGA routing hardware logic unit, I would like to ignore it. Or switch to the UEFI firmware on such hardware. It is the hardware engineer's responsibility, I will not worry about it. Thanks for you tell this. [1] https://www.intel.com/content/dam/doc/datasheet/atom-d2000-n2000-vol-2-datasheet.pdf It will always be primary from a VGA routing perspective. Was this actually tested with non-UEFI? As you already said, the generous Intel already have confirmed that the hardware defect. So probably this is a good chance to switch to UEFI to solve the problem. Then, no testing for legacy is needed. I suspect it might only work in UEFI mode where we probably don't actually have a dependency on VGA routing. This is essentially why vfio requires UEFI ROMs when assigning GPUs to VMs, VGA routing is too broken to use on Intel systems with IGD. Thanks, Thanks for you tell me this. To be honest, I have only tested my patch on machines with UEFI firmware. Since UEFI because the main stream, but if this patch is really useful for majority machine, I'm satisfied. The results is not too bad. Thanks. Alex
Re: [Nouveau] [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
Hi, On 2023/9/5 23:05, Thomas Zimmermann wrote: However, on modern Linux systems the primary display does not really exist. 'Primary' is the device that is available via VGA, VESA or EFI. I may miss the point, what do you means by choose the word "modern"? Are you trying to tell me that X server is too old and Wayland is the modern display server? Our drivers don't use these interfaces, but the native registers. Yes and no? Yes for the machine with the UEFI firmware, but I not sure if this statement is true for the machine with the legacy firmware. As the display controller in the ASpeed BMC is VGA compatible. Therefore, in theory, it should works with the VGA console on the machine with another VGA compatible video card. So the ast_vga_set_decode() function provided in the 0007 patch probably useful on legacy firmware environment. To be honest, I have tested this on various machine with UEFI firmware. But I didn't realized that I should do the testing on legacy firmware environment before sending this patch. It seems that the testing effort needed are quite exhausting, since all my machines come with the UEFI firmware. So is it OK to leave the legacy part to someone else who interested in it? Probably Alex is more professional at legacy VGA routing stuff? :-)
Re: [PATCH] drm/vmwgfx: fix typo of sizeof argument
On Tue, 2023-09-05 at 18:02 +0800, Konstantin Meskhidze wrote: > Since size of 'header' pointer and '*header' structure is equal on 64-bit > machines issue probably didn't cause any wrong behavior. But anyway, > fixing typo is required. > > Fixes: 7a73ba7469cb ("drm/vmwgfx: Use TTM handles instead of SIDs as > user-space > surface handles.") > Co-developed-by: Ivanov Mikhail > Signed-off-by: Konstantin Meskhidze > --- > drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > index 98e0723ca6f5..cc3f301ca163 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c > @@ -1619,7 +1619,7 @@ static int vmw_cmd_tex_state(struct vmw_private > *dev_priv, > { > VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetTextureState); > SVGA3dTextureState *last_state = (SVGA3dTextureState *) > - ((unsigned long) header + header->size + sizeof(header)); > + ((unsigned long) header + header->size + sizeof(*header)); > SVGA3dTextureState *cur_state = (SVGA3dTextureState *) > ((unsigned long) header + sizeof(*cmd)); > struct vmw_resource *ctx; Hah, yea, that's an old one. Thanks! I can push it through the drm-misc tree. Reviewed-by: Zack Rusin z
Re: [Nouveau] [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
On 2023/9/5 23:05, Thomas Zimmermann wrote: Hi Am 05.09.23 um 15:30 schrieb suijingfeng: Hi, On 2023/9/5 18:45, Thomas Zimmermann wrote: Hi Am 04.09.23 um 21:57 schrieb Sui Jingfeng: From: Sui Jingfeng On a machine with multiple GPUs, a Linux user has no control over which one is primary at boot time. This series tries to solve above mentioned If anything, the primary graphics adapter is the one initialized by the firmware. I think our boot-up graphics also make this assumption implicitly. Yes, but by the time of DRM drivers get loaded successfully,the boot-up graphics already finished. Firmware framebuffer device already get killed by the drm_aperture_remove_conflicting_pci_framebuffers() function (or its siblings). So, this series is definitely not to interact with the firmware framebuffer Yes and no. The helpers you mention will attempt to remove the firmware framebuffer on the given PCI device. If you have multiple PCI devices, the other devices would not be affected. Yes and no. For the yes part: drm_aperture_remove_conflicting_pci_framebuffers() only kill the conflict one. But for a specific machine with the modern UEFI firmware, there should be only one firmware framebuffer driver. That shoudd be the EFIFB(UEFI GOP). I do have multiple PCI devices, but I don't understand when and why a system will have more than one firmware framebuffer. Even for the machines with the legacy BIOS, the fixed VGA aperture address range can only be owned by one firmware driver. It is just that we need to handle the routing, the ->set_decode() callback of vga_client_register() is used to do such work. Am I correct?
Re: [Nouveau] [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
Hi, On 2023/9/5 23:05, Thomas Zimmermann wrote: However, on modern Linux systems the primary display does not really exist. No, it do exist. X server need to know which one is the primary GPU. The '*' character at the of (4@0:0:0) PCI device is the Primary. The '*' denote primary, see the log below. (II) xfree86: Adding drm device (/dev/dri/card2) (II) xfree86: Adding drm device (/dev/dri/card0) (II) Platform probe for /sys/devices/pci:00/:00:1c.5/:003:00.0/:04:00.0/drm/card0 (II) xfree86: Adding drm device (/dev/dri/card3) (II) Platform probe for /sys/devices/pci:00/:00:1c.6/:005:00.0/drm/card3 (--) PCI: (0@0:2:0) 8086:3e91:8086:3e91 rev 0, Mem @ 0xdb00/16216, 0xa000/536870912, I/O @ 0xf000/64, BIOS @ 0x/131072 (--) PCI: (1@0:0:0) 1002:6771:1043:8636 rev 0, Mem @ 0xc000/2688435456, 0xdf22/131072, I/O @ 0xe000/256, BIOS @ 0x/131072 (--) PCI:*(4@0:0:0) 1a03:2000:1a03:2000 rev 48, Mem @ 0xde00/166777216, 0xdf02/131072, I/O @ 0xc000/128, BIOS @ 0x/131072 (--) PCI: (5@0:0:0) 10de:1288:174b:b324 rev 161, Mem @ 0xdc00/116777216, 0xd000/134217728, 0xd800/33554432, I/O @ 0xb000/128, BIOS @@0x/524288 The modesetting driver of X server will create framebuffer on the primary video adapter. If a 2D video adapter (like the aspeed BMC) is not the primary, then it probably will not be used. The only chance to be able to display something is to functional as a output slave. But the output slave technology need the PRIME support for cross driver buffer sharing. So, there do have some difference between the primary and non-primary video adapters. 'Primary' is the device that is available via VGA, VESA or EFI. Our drivers don't use these interfaces, but the native registers. As you said yourself, these firmware devices (VGA, VESA, EFI) are removed ASAP by the native drivers.
Re: [PATCH v3 1/8] drm/msm/dpu: populate SSPP scaler block version
On 2023-09-05 04:25:19, Dmitry Baryshkov wrote: > The function _dpu_hw_sspp_setup_scaler3() passes and > dpu_hw_setup_scaler3() uses scaler_blk.version to determine in which way > the scaler (QSEED3) block should be programmed. However up to now we > were not setting this field. Set it now, splitting the vig_sblk data > which has different version fields. > > Reported-by: Marijn Suijten > Fixes: 9b6f4fedaac2 ("drm/msm/dpu: Add SM6125 support") > Fixes: 27f0df03f3ff ("drm/msm/dpu: Add SM6375 support") > Fixes: 3186acba5cdc ("drm/msm/dpu: Add SM6350 support") > Fixes: efcd0107727c ("drm/msm/dpu: add support for SM8550") > Fixes: 4a352c2fc15a ("drm/msm/dpu: Introduce SC8280XP") > Fixes: 0e91bcbb0016 ("drm/msm/dpu: Add SM8350 to hw catalog") > Fixes: 100d7ef6995d ("drm/msm/dpu: add support for SM8450") > Fixes: 3581b7062cec ("drm/msm/disp/dpu1: add support for display on SM6115") > Fixes: dabfdd89eaa9 ("drm/msm/disp/dpu1: add inline rotation support for > sc7280") > Fixes: f3af2d6ee9ab ("drm/msm/dpu: Add SC8180x to hw catalog") > Fixes: 94391a14fc27 ("drm/msm/dpu1: Add MSM8998 to hw catalog") > Fixes: af776a3e1c30 ("drm/msm/dpu: add SM8250 to hw catalog") > Fixes: 386fced3f76f ("drm/msm/dpu: add SM8150 to hw catalog") > Fixes: b75ab05a3479 ("msm:disp:dpu1: add scaler support on SC7180 display") > Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support") > Signed-off-by: Dmitry Baryshkov So as it turns out this patch is basically [1] with review comments applied, though no mention whatsoever that .version isn't just a convenient way to represent the version but what the register read by _dpu_hw_sspp_get_scaler3_ver() contains? (That was the review: hardcode the constants instead of doing runtime register reads) With that, `_dpu_hw_sspp_get_scaler3_ver()` and `dpu_hw_sspp->get_scaler_ver` must now be completely unused? [1]: https://lore.kernel.org/linux-arm-msm/caa8ejpobxpsyeqzq3zgwsqg6fc7pzqumwr9ddpdmgoemts-...@mail.gmail.com/#t It seems patch 6 in this series also has a matching - r-b'd - patch in that series ;) - Marijn > --- > .../msm/disp/dpu1/catalog/dpu_5_0_sm8150.h| 8 +- > .../msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h | 8 +- > .../msm/disp/dpu1/catalog/dpu_8_1_sm8450.h| 8 +- > .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 95 ++- > 4 files changed, 85 insertions(+), 34 deletions(-) > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h > b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h > index 99acaf917e43..f0c3804f4258 100644 > --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h > +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h > @@ -77,7 +77,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { > .name = "sspp_0", .id = SSPP_VIG0, > .base = 0x4000, .len = 0x1f0, > .features = VIG_SDM845_MASK, > - .sblk = &sdm845_vig_sblk_0, > + .sblk = &sm8150_vig_sblk_0, > .xin_id = 0, > .type = SSPP_TYPE_VIG, > .clk_ctrl = DPU_CLK_CTRL_VIG0, > @@ -85,7 +85,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { > .name = "sspp_1", .id = SSPP_VIG1, > .base = 0x6000, .len = 0x1f0, > .features = VIG_SDM845_MASK, > - .sblk = &sdm845_vig_sblk_1, > + .sblk = &sm8150_vig_sblk_1, > .xin_id = 4, > .type = SSPP_TYPE_VIG, > .clk_ctrl = DPU_CLK_CTRL_VIG1, > @@ -93,7 +93,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { > .name = "sspp_2", .id = SSPP_VIG2, > .base = 0x8000, .len = 0x1f0, > .features = VIG_SDM845_MASK, > - .sblk = &sdm845_vig_sblk_2, > + .sblk = &sm8150_vig_sblk_2, > .xin_id = 8, > .type = SSPP_TYPE_VIG, > .clk_ctrl = DPU_CLK_CTRL_VIG2, > @@ -101,7 +101,7 @@ static const struct dpu_sspp_cfg sm8150_sspp[] = { > .name = "sspp_3", .id = SSPP_VIG3, > .base = 0xa000, .len = 0x1f0, > .features = VIG_SDM845_MASK, > - .sblk = &sdm845_vig_sblk_3, > + .sblk = &sm8150_vig_sblk_3, > .xin_id = 12, > .type = SSPP_TYPE_VIG, > .clk_ctrl = DPU_CLK_CTRL_VIG3, > diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h > b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h > index f3de21025ca7..3ec954722a8e 100644 > --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h > +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h > @@ -76,7 +76,7 @@ static const struct dpu_sspp_cfg sc8180x_sspp[] = { > .name = "sspp_0", .id = SSPP_VIG0, > .base = 0x4000, .len = 0x1f0, > .features = VIG_SDM845_MASK, > - .sblk = &sdm845_vig_sblk_0, > + .sblk = &sm8150_vig_sblk_0, > .xin_id = 0, > .type = SSPP_TY
Re: [PATCH v2 6/6] drm/drm-file: Allow size unit selection in drm_show_memory_stats
On Wed, Aug 30, 2023 at 8:51 AM Adrián Larumbe wrote: > > >> The current implementation will try to pick the highest available > >> unit. This is rather unflexible, and allowing drivers to display BO size > >> statistics through fdinfo in units of their choice might be desirable. > >> > >> The new argument to drm_show_memory_stats is to be interpreted as the > >> integer multiplier of a 10-power of 2, so 1 would give us size in Kib and 2 > >> in Mib. If we want drm-file functions to pick the highest unit, then 0 > >> should be passed. > >> > >> Signed-off-by: Adrián Larumbe > >> --- > >> drivers/gpu/drm/drm_file.c | 22 +- > >> drivers/gpu/drm/msm/msm_drv.c | 2 +- > >> drivers/gpu/drm/panfrost/panfrost_drv.c | 2 +- > >> include/drm/drm_file.h | 5 +++-- > >> 4 files changed, 18 insertions(+), 13 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c > >> index 762965e3d503..517e1fb8072a 100644 > >> --- a/drivers/gpu/drm/drm_file.c > >> +++ b/drivers/gpu/drm/drm_file.c > >> @@ -873,7 +873,7 @@ void drm_send_event(struct drm_device *dev, struct > >> drm_pending_event *e) > >> EXPORT_SYMBOL(drm_send_event); > >> > >> static void print_size(struct drm_printer *p, const char *stat, > >> - const char *region, u64 sz) > >> + const char *region, u64 sz, unsigned int unit) > >> { > >> const char *units[] = {"", " KiB", " MiB"}; > >> unsigned u; > >> @@ -881,6 +881,8 @@ static void print_size(struct drm_printer *p, const > >> char *stat, > >> for (u = 0; u < ARRAY_SIZE(units) - 1; u++) { > >> if (sz < SZ_1K) > >> break; > >> + if (unit > 0 && unit == u) > >> + break; > >> sz = div_u64(sz, SZ_1K); > >> } > >> > >> @@ -898,17 +900,18 @@ static void print_size(struct drm_printer *p, const > >> char *stat, > >> void drm_print_memory_stats(struct drm_printer *p, > >> const struct drm_memory_stats *stats, > >> enum drm_gem_object_status supported_status, > >> - const char *region) > >> + const char *region, > >> + unsigned int unit) > > > >I'm not really adverse to changing what units we use.. or perhaps > >changing the threshold to go to higher units to be 1x or 10x > >of the previous unit. But I'm less excited about having different > >drivers using different units. > > > >BR, > >-R > > Would it be alright if I left it set to the default unit, and allow changing > it > at runtime with a debugfs file? I suppose we could, but it does seem a bit like overkill. OTOH I think it would make sense to increase the threshold, ie. switch to MiB after 10MiB instead of 1MiB.. at that point the fractional component is less significant.. BR, -R > >> { > >> - print_size(p, "total", region, stats->private + stats->shared); > >> - print_size(p, "shared", region, stats->shared); > >> - print_size(p, "active", region, stats->active); > >> + print_size(p, "total", region, stats->private + stats->shared, > >> unit); > >> + print_size(p, "shared", region, stats->shared, unit); > >> + print_size(p, "active", region, stats->active, unit); > >> > >> if (supported_status & DRM_GEM_OBJECT_RESIDENT) > >> - print_size(p, "resident", region, stats->resident); > >> + print_size(p, "resident", region, stats->resident, unit); > >> > >> if (supported_status & DRM_GEM_OBJECT_PURGEABLE) > >> - print_size(p, "purgeable", region, stats->purgeable); > >> + print_size(p, "purgeable", region, stats->purgeable, unit); > >> } > >> EXPORT_SYMBOL(drm_print_memory_stats); > >> > >> @@ -916,11 +919,12 @@ EXPORT_SYMBOL(drm_print_memory_stats); > >> * drm_show_memory_stats - Helper to collect and show standard fdinfo > >> memory stats > >> * @p: the printer to print output to > >> * @file: the DRM file > >> + * @unit: multipliyer of power of two exponent of desired unit > >> * > >> * Helper to iterate over GEM objects with a handle allocated in the > >> specified > >> * file. > >> */ > >> -void drm_show_memory_stats(struct drm_printer *p, struct drm_file *file) > >> +void drm_show_memory_stats(struct drm_printer *p, struct drm_file *file, > >> unsigned int unit) > >> { > >> struct drm_gem_object *obj; > >> struct drm_memory_stats status = {}; > >> @@ -967,7 +971,7 @@ void drm_show_memory_stats(struct drm_printer *p, > >> struct drm_file *file) > >> } > >> spin_unlock(&file->table_lock); > >> > >> - drm_print_memory_stats(p, &status, supported_status, "memory"); > >> + drm_print_memory_stats(p, &status, supported_status, "memory", > >> unit); > >> } > >> EXPORT_SYMBOL(drm_show_
Re: [PATCH 7/7] drm/msm/dp: Remove dp_display_is_ds_bridge()
Quoting Dmitry Baryshkov (2023-09-03 15:40:49) > On 29/08/2023 21:47, Stephen Boyd wrote: > > This function is simply drm_dp_is_branch() so use that instead of > > open-coding it. > > > > Cc: Vinod Polimera > > Cc: Kuogee Hsieh > > Signed-off-by: Stephen Boyd > > --- > > drivers/gpu/drm/msm/dp/dp_display.c | 9 + > > 1 file changed, 1 insertion(+), 8 deletions(-) > > Reviewed-by: Dmitry Baryshkov Thanks. > > > > > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c > > b/drivers/gpu/drm/msm/dp/dp_display.c > > index 76f13954015b..96bbf6fec2f1 100644 > > --- a/drivers/gpu/drm/msm/dp/dp_display.c > > +++ b/drivers/gpu/drm/msm/dp/dp_display.c > > @@ -341,19 +341,12 @@ static const struct component_ops dp_display_comp_ops > > = { > > .unbind = dp_display_unbind, > > }; > > > > -static bool dp_display_is_ds_bridge(struct dp_panel *panel) > > -{ > > - return (panel->dpcd[DP_DOWNSTREAMPORT_PRESENT] & > > - DP_DWN_STRM_PORT_PRESENT); > > -} > > - > > static bool dp_display_is_sink_count_zero(struct dp_display_private *dp) > > Nit: you might as well inline this function Ok. I'll send a followup to this series with a patch for that. I found that with an Apple dongle it always prints out a message to the kernel log when I have HDMI disconnected that there isn't a sink connected, which is annoying. So at least two more patches are incoming.
[PATCH v3 2/2] drm/v3d: Expose the total GPU usage stats on sysfs
The previous patch exposed the accumulated amount of active time per client for each V3D queue. But this doesn't provide a global notion of the GPU usage. Therefore, provide the accumulated amount of active time for each V3D queue (BIN, RENDER, CSD, TFU and CACHE_CLEAN), considering all the jobs submitted to the queue, independent of the client. This data is exposed through the sysfs interface, so that if the interface is queried at two different points of time the usage percentage of each of the queues can be calculated. Co-developed-by: Jose Maria Casanova Crespo Signed-off-by: Jose Maria Casanova Crespo Signed-off-by: Maíra Canal --- drivers/gpu/drm/v3d/Makefile| 3 +- drivers/gpu/drm/v3d/v3d_drv.c | 9 + drivers/gpu/drm/v3d/v3d_drv.h | 8 drivers/gpu/drm/v3d/v3d_gem.c | 6 ++- drivers/gpu/drm/v3d/v3d_irq.c | 28 + drivers/gpu/drm/v3d/v3d_sched.c | 15 ++- drivers/gpu/drm/v3d/v3d_sysfs.c | 69 + 7 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/v3d/v3d_sysfs.c diff --git a/drivers/gpu/drm/v3d/Makefile b/drivers/gpu/drm/v3d/Makefile index e8b314137020..4b21b20e4998 100644 --- a/drivers/gpu/drm/v3d/Makefile +++ b/drivers/gpu/drm/v3d/Makefile @@ -11,7 +11,8 @@ v3d-y := \ v3d_mmu.o \ v3d_perfmon.o \ v3d_trace_points.o \ - v3d_sched.o + v3d_sched.o \ + v3d_sysfs.o v3d-$(CONFIG_DEBUG_FS) += v3d_debugfs.o diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c index 5003c9ef1914..c7d22952b3ae 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c @@ -315,8 +315,14 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) if (ret) goto irq_disable; + ret = v3d_sysfs_init(dev); + if (ret) + goto drm_unregister; + return 0; +drm_unregister: + drm_dev_unregister(drm); irq_disable: v3d_irq_disable(v3d); gem_destroy: @@ -330,6 +336,9 @@ static void v3d_platform_drm_remove(struct platform_device *pdev) { struct drm_device *drm = platform_get_drvdata(pdev); struct v3d_dev *v3d = to_v3d_dev(drm); + struct device *dev = &pdev->dev; + + v3d_sysfs_destroy(dev); drm_dev_unregister(drm); diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index 7f2897e5b2cb..adebcdde4ebd 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -38,6 +38,10 @@ struct v3d_queue_state { u64 fence_context; u64 emit_seqno; + + u64 start_ns; + u64 enabled_ns; + u64 jobs_sent; }; /* Performance monitor object. The perform lifetime is controlled by userspace @@ -441,3 +445,7 @@ int v3d_perfmon_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); + +/* v3d_sysfs.c */ +int v3d_sysfs_init(struct device *dev); +void v3d_sysfs_destroy(struct device *dev); diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 40ed0c7c3fad..da6376909e10 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -1014,8 +1014,12 @@ v3d_gem_init(struct drm_device *dev) u32 pt_size = 4096 * 1024; int ret, i; - for (i = 0; i < V3D_MAX_QUEUES; i++) + for (i = 0; i < V3D_MAX_QUEUES; i++) { v3d->queue[i].fence_context = dma_fence_context_alloc(1); + v3d->queue[i].start_ns = 0; + v3d->queue[i].enabled_ns = 0; + v3d->queue[i].jobs_sent = 0; + } spin_lock_init(&v3d->mm_lock); spin_lock_init(&v3d->job_lock); diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c index c724f65058f4..622111e613e3 100644 --- a/drivers/gpu/drm/v3d/v3d_irq.c +++ b/drivers/gpu/drm/v3d/v3d_irq.c @@ -102,10 +102,17 @@ v3d_irq(int irq, void *arg) struct v3d_fence *fence = to_v3d_fence(v3d->bin_job->base.irq_fence); struct v3d_file_priv *file = v3d->bin_job->base.file->driver_priv; + u64 runtime = local_clock() - file->start_ns[V3D_BIN]; file->enabled_ns[V3D_BIN] += local_clock() - file->start_ns[V3D_BIN]; file->jobs_sent[V3D_BIN]++; + v3d->queue[V3D_BIN].jobs_sent++; + file->start_ns[V3D_BIN] = 0; + v3d->queue[V3D_BIN].start_ns = 0; + + file->enabled_ns[V3D_BIN] += runtime; + v3d->queue[V3D_BIN].enabled_ns += runtime; trace_v3d_bcl_irq(&v3d->drm, fence->seqno); dma_fence_signal(&fence->base); @@ -116,10 +123,17 @@ v3d_irq(int irq, void *arg) struct v3d_fence *fence = to_v3d_fence(v3d->render
[PATCH v3 0/2] drm/v3d: Expose GPU usage stats
This patchset exposes GPU usages stats both globally and per-file descriptor. The first patch exposes the accumulated amount of active time per client through the fdinfo infrastructure. The amount of active time is exposed for each V3D queue. Moreover, it exposes the number of jobs submitted to each queue. The second patch exposes the accumulated amount of active time for each V3D queue, independent of the client. This data is exposed through the sysfs interface. With these patches, it is possible to calculate the GPU usage percentage per queue globally and per-file descriptor. * Example fdinfo output: $ cat /proc/1140/fdinfo/4 pos:0 flags: 0242 mnt_id: 24 ino:209 drm-driver: v3d drm-client-id: 44 drm-engine-bin: 1661076898 ns v3d-jobs-bin: 19576 jobs drm-engine-render: 31469427170 ns v3d-jobs-render:19575 jobs drm-engine-tfu: 5002964 ns v3d-jobs-tfu: 13 jobs drm-engine-csd: 188038329691 ns v3d-jobs-csd: 250393 jobs drm-engine-cache_clean: 27736024038 ns v3d-jobs-cache_clean: 250392 job * Example gputop output: DRM minor 128 PID bin render tfucsd cache_clean NAME 1140 |▎||██▋ || ||█▍ ||█▋ | computecloth 1158 |▍||▉ || || || | gears 1002 |▏||█▎|| || || | chromium-browse Best Regards, - Maíra --- v1 -> v2: https://lore.kernel.org/dri-devel/20230727142929.1275149-1-mca...@igalia.com/T/ * Use sysfs to expose global GPU stats (Tvrtko Ursulin) v2 -> v3: https://lore.kernel.org/dri-devel/20230807211849.49867-1-mca...@igalia.com/T/ * Document the expected behavior in case of a GPU reset (Melissa Wen) * Add a brief description about the sysfs outputs (Melissa Wen) * Instead of having multiple sysfs files, use only one sysfs file, called gpu_stats, with all the information (Chema Casanova) * Add the number of jobs submitted in the global GPU stats (Chema Casanova) * Now, the number of jobs submitted is only incremented if the job was completed Maíra Canal (2): drm/v3d: Implement show_fdinfo() callback for GPU usage stats drm/v3d: Expose the total GPU usage stats on sysfs drivers/gpu/drm/v3d/Makefile| 3 +- drivers/gpu/drm/v3d/v3d_drv.c | 45 - drivers/gpu/drm/v3d/v3d_drv.h | 31 +++ drivers/gpu/drm/v3d/v3d_gem.c | 7 +++- drivers/gpu/drm/v3d/v3d_irq.c | 49 +++ drivers/gpu/drm/v3d/v3d_sched.c | 33 drivers/gpu/drm/v3d/v3d_sysfs.c | 69 + 7 files changed, 234 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/v3d/v3d_sysfs.c -- 2.41.0
[PATCH v3 1/2] drm/v3d: Implement show_fdinfo() callback for GPU usage stats
This patch exposes the accumulated amount of active time per client through the fdinfo infrastructure. The amount of active time is exposed for each V3D queue: BIN, RENDER, CSD, TFU and CACHE_CLEAN. In order to calculate the amount of active time per client, a CPU clock is used through the function local_clock(). The point where the jobs has started is marked and is finally compared with the time that the job had finished. Moreover, the number of jobs submitted to each queue is also exposed on fdinfo through the identifier "v3d-jobs-". Co-developed-by: Jose Maria Casanova Crespo Signed-off-by: Jose Maria Casanova Crespo Signed-off-by: Maíra Canal --- drivers/gpu/drm/v3d/v3d_drv.c | 36 - drivers/gpu/drm/v3d/v3d_drv.h | 23 + drivers/gpu/drm/v3d/v3d_gem.c | 1 + drivers/gpu/drm/v3d/v3d_irq.c | 21 +++ drivers/gpu/drm/v3d/v3d_sched.c | 20 ++ 5 files changed, 100 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c index ffbbe9d527d3..5003c9ef1914 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -111,6 +112,10 @@ v3d_open(struct drm_device *dev, struct drm_file *file) v3d_priv->v3d = v3d; for (i = 0; i < V3D_MAX_QUEUES; i++) { + v3d_priv->enabled_ns[i] = 0; + v3d_priv->start_ns[i] = 0; + v3d_priv->jobs_sent[i] = 0; + sched = &v3d->queue[i].sched; drm_sched_entity_init(&v3d_priv->sched_entity[i], DRM_SCHED_PRIORITY_NORMAL, &sched, @@ -136,7 +141,35 @@ v3d_postclose(struct drm_device *dev, struct drm_file *file) kfree(v3d_priv); } -DEFINE_DRM_GEM_FOPS(v3d_drm_fops); +static void v3d_show_fdinfo(struct drm_printer *p, struct drm_file *file) +{ + struct v3d_file_priv *file_priv = file->driver_priv; + u64 timestamp = local_clock(); + enum v3d_queue queue; + + for (queue = 0; queue < V3D_MAX_QUEUES; queue++) { + /* Note that, in case of a GPU reset, the time spent during an +* attempt of executing the job is not computed in the runtime. +*/ + drm_printf(p, "drm-engine-%s: \t%llu ns\n", + v3d_queue_to_string(queue), + file_priv->start_ns[queue] ? file_priv->enabled_ns[queue] + + timestamp - file_priv->start_ns[queue] + : file_priv->enabled_ns[queue]); + + /* Note that we only count jobs that completed. Therefore, jobs +* that were resubmitted due to a GPU reset are not computed. +*/ + drm_printf(p, "v3d-jobs-%s: \t%llu jobs\n", + v3d_queue_to_string(queue), file_priv->jobs_sent[queue]); + } +} + +static const struct file_operations v3d_drm_fops = { + .owner = THIS_MODULE, + DRM_GEM_FOPS, + .show_fdinfo = drm_show_fdinfo, +}; /* DRM_AUTH is required on SUBMIT_CL for now, while we don't have GMP * protection between clients. Note that render nodes would be @@ -176,6 +209,7 @@ static const struct drm_driver v3d_drm_driver = { .ioctls = v3d_drm_ioctls, .num_ioctls = ARRAY_SIZE(v3d_drm_ioctls), .fops = &v3d_drm_fops, + .show_fdinfo = v3d_show_fdinfo, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index 7f664a4b2a75..7f2897e5b2cb 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -21,6 +21,18 @@ struct reset_control; #define V3D_MAX_QUEUES (V3D_CACHE_CLEAN + 1) +static inline char *v3d_queue_to_string(enum v3d_queue queue) +{ + switch (queue) { + case V3D_BIN: return "bin"; + case V3D_RENDER: return "render"; + case V3D_TFU: return "tfu"; + case V3D_CSD: return "csd"; + case V3D_CACHE_CLEAN: return "cache_clean"; + } + return "UNKNOWN"; +} + struct v3d_queue_state { struct drm_gpu_scheduler sched; @@ -167,6 +179,12 @@ struct v3d_file_priv { } perfmon; struct drm_sched_entity sched_entity[V3D_MAX_QUEUES]; + + u64 start_ns[V3D_MAX_QUEUES]; + + u64 enabled_ns[V3D_MAX_QUEUES]; + + u64 jobs_sent[V3D_MAX_QUEUES]; }; struct v3d_bo { @@ -238,6 +256,11 @@ struct v3d_job { */ struct v3d_perfmon *perfmon; + /* File descriptor of the process that submitted the job that could be used +* for collecting stats by process of GPU usage. +*/ + struct drm_file *file; + /* Callback for the freeing of the job on refcount going to 0. */ void (*free)(struct kref *ref); }; diff
[PATCH v2 2/2] drm/tests: Add new format conversion tests to better cover drm_fb_blit()
To fully cover drm_fb_blit(), add format conversion tests that are only supported through drm_fb_blit(). Signed-off-by: Arthur Grillo --- drivers/gpu/drm/tests/drm_format_helper_test.c | 142 + 1 file changed, 142 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index b888f7334510..889287245b1e 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -81,6 +81,16 @@ struct fb_swab_result { const u32 expected[TEST_BUF_SIZE]; }; +struct convert_to_xbgr_result { + unsigned int dst_pitch; + const u32 expected[TEST_BUF_SIZE]; +}; + +struct convert_to_abgr_result { + unsigned int dst_pitch; + const u32 expected[TEST_BUF_SIZE]; +}; + struct convert_xrgb_case { const char *name; unsigned int pitch; @@ -98,6 +108,8 @@ struct convert_xrgb_case { struct convert_to_argb2101010_result argb2101010_result; struct convert_to_mono_result mono_result; struct fb_swab_result swab_result; + struct convert_to_xbgr_result xbgr_result; + struct convert_to_abgr_result abgr_result; }; static struct convert_xrgb_case convert_xrgb_cases[] = { @@ -155,6 +167,14 @@ static struct convert_xrgb_case convert_xrgb_cases[] = { .dst_pitch = TEST_USE_DEFAULT_PITCH, .expected = { 0xFF01 }, }, + .xbgr_result = { + .dst_pitch = TEST_USE_DEFAULT_PITCH, + .expected = { 0x01FF }, + }, + .abgr_result = { + .dst_pitch = TEST_USE_DEFAULT_PITCH, + .expected = { 0xFFFF }, + }, }, { .name = "single_pixel_clip_rectangle", @@ -213,6 +233,14 @@ static struct convert_xrgb_case convert_xrgb_cases[] = { .dst_pitch = TEST_USE_DEFAULT_PITCH, .expected = { 0xFF10 }, }, + .xbgr_result = { + .dst_pitch = TEST_USE_DEFAULT_PITCH, + .expected = { 0x10FF }, + }, + .abgr_result = { + .dst_pitch = TEST_USE_DEFAULT_PITCH, + .expected = { 0xFFFF }, + }, }, { /* Well known colors: White, black, red, green, blue, magenta, @@ -343,6 +371,24 @@ static struct convert_xrgb_case convert_xrgb_cases[] = { 0x0077, 0x0088, }, }, + .xbgr_result = { + .dst_pitch = TEST_USE_DEFAULT_PITCH, + .expected = { + 0x11FF, 0x2200, + 0x33FF, 0x4400FF00, + 0x55FF, 0x66FF00FF, + 0x7700, 0x8800, + }, + }, + .abgr_result = { + .dst_pitch = TEST_USE_DEFAULT_PITCH, + .expected = { + 0x, 0xFF00, + 0xFFFF, 0xFF00FF00, + 0x, 0x00FF, + 0xFF00, 0xFF00, + }, + }, }, { /* Randomly picked colors. Full buffer within the clip area. */ @@ -458,6 +504,22 @@ static struct convert_xrgb_case convert_xrgb_cases[] = { 0x0303A8C2, 0x73F06CD2, 0x9C440EA3, 0x, 0x, }, }, + .xbgr_result = { + .dst_pitch = 20, + .expected = { + 0xA19C440E, 0xB1054D11, 0xC103F3A8, 0x, 0x, + 0xD173F06C, 0xA29C440E, 0xB2054D11, 0x, 0x, + 0xC20303A8, 0xD273F06C, 0xA39C440E, 0x, 0x, + }, + }, + .abgr_result = { + .dst_pitch = 20, + .expected = { + 0xFF9C440E, 0xFF054D11, 0xFF03F3A8, 0x, 0x, + 0xFF73F06C, 0xFF9C440E, 0xFF054D11, 0x, 0x, + 0xFF0303A8, 0xFF73F06C, 0xFF9C440E, 0x, 0x, + }, + }, }, }; @@ -1082,6 +1144,84 @@ static void drm_test_fb_swab(struct kunit *test) KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } +st
[PATCH v2 1/2] drm/tests: Add calls to drm_fb_blit() on supported format conversion tests
Add a call to drm_fb_blit() on existing format conversion tests that has support. Signed-off-by: Arthur Grillo --- drivers/gpu/drm/tests/drm_format_helper_test.c | 142 + 1 file changed, 142 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 79bc9d4bbd71..b888f7334510 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -643,6 +643,18 @@ static void drm_test_fb_xrgb_to_rgb565(struct kunit *test) drm_fb_xrgb_to_rgb565(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip, true); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); KUNIT_EXPECT_MEMEQ(test, buf, result->expected_swab, dst_size); + + buf = dst.vaddr; + memset(buf, 0, TEST_BUF_SIZE); + + int blit_result = 0; + + blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGB565, &src, &fb, ¶ms->clip); + + buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); + + KUNIT_EXPECT_FALSE(test, blit_result); + KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } static void drm_test_fb_xrgb_to_xrgb1555(struct kunit *test) @@ -677,6 +689,18 @@ static void drm_test_fb_xrgb_to_xrgb1555(struct kunit *test) drm_fb_xrgb_to_xrgb1555(&dst, dst_pitch, &src, &fb, ¶ms->clip); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); + + buf = dst.vaddr; /* restore original value of buf */ + memset(buf, 0, TEST_BUF_SIZE); + + int blit_result = 0; + + blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB1555, &src, &fb, ¶ms->clip); + + buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); + + KUNIT_EXPECT_FALSE(test, blit_result); + KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } static void drm_test_fb_xrgb_to_argb1555(struct kunit *test) @@ -711,6 +735,18 @@ static void drm_test_fb_xrgb_to_argb1555(struct kunit *test) drm_fb_xrgb_to_argb1555(&dst, dst_pitch, &src, &fb, ¶ms->clip); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); + + buf = dst.vaddr; /* restore original value of buf */ + memset(buf, 0, TEST_BUF_SIZE); + + int blit_result = 0; + + blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB1555, &src, &fb, ¶ms->clip); + + buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); + + KUNIT_EXPECT_FALSE(test, blit_result); + KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } static void drm_test_fb_xrgb_to_rgba5551(struct kunit *test) @@ -745,6 +781,18 @@ static void drm_test_fb_xrgb_to_rgba5551(struct kunit *test) drm_fb_xrgb_to_rgba5551(&dst, dst_pitch, &src, &fb, ¶ms->clip); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); + + buf = dst.vaddr; /* restore original value of buf */ + memset(buf, 0, TEST_BUF_SIZE); + + int blit_result = 0; + + blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGBA5551, &src, &fb, ¶ms->clip); + + buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); + + KUNIT_EXPECT_FALSE(test, blit_result); + KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } static void drm_test_fb_xrgb_to_rgb888(struct kunit *test) @@ -782,6 +830,16 @@ static void drm_test_fb_xrgb_to_rgb888(struct kunit *test) drm_fb_xrgb_to_rgb888(&dst, dst_pitch, &src, &fb, ¶ms->clip); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); + + buf = dst.vaddr; /* restore original value of buf */ + memset(buf, 0, TEST_BUF_SIZE); + + int blit_result = 0; + + blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGB888, &src, &fb, ¶ms->clip); + + KUNIT_EXPECT_FALSE(test, blit_result); + KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } static void drm_test_fb_xrgb_to_argb(struct kunit *test) @@ -816,6 +874,18 @@ static void drm_test_fb_xrgb_to_argb(struct kunit *test) drm_fb_xrgb_to_argb(&dst, dst_pitch, &src, &fb, ¶ms->clip); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); + + buf = dst.vaddr; /* restore original value of buf */ + memset(buf, 0, TEST_BUF_SIZE); + + int blit_result = 0; + + blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB, &src, &fb, ¶ms->c
[PATCH v2 0/2] Add KUnit tests for drm_fb_blit()
This patchset tests the drm_fb_blit() function. As this function can be used with already tested formats, the first patch adds calls to drm_fb_blit() on the tests of supported formats. Some supported formats were not yet covered by the existing tests because they are only supported by drm_fb_blit(). The second patch adds those format conversion tests. Signed-off-by: Arthur Grillo --- Changes in v2: - Split the patch into two (Maíra Canal) - Link to v1: https://lore.kernel.org/r/20230901-final-gsoc-v1-1-e310c7685...@riseup.net --- Arthur Grillo (2): drm/tests: Add calls to drm_fb_blit() on supported format conversion tests drm/tests: Add new format conversion tests to better cover drm_fb_blit() drivers/gpu/drm/tests/drm_format_helper_test.c | 284 + 1 file changed, 284 insertions(+) --- base-commit: f45acf7acf75921c0409d452f0165f51a19a74fd change-id: 20230901-final-gsoc-395a84443c8f Best regards, -- Arthur Grillo
Re: [RFT PATCH 1/6] drm/atomic-helper: drm_atomic_helper_shutdown(NULL) should be a noop
Hi, On Mon, Sep 4, 2023 at 12:55 AM Maxime Ripard wrote: > > On Fri, 1 Sep 2023 16:39:52 -0700, Douglas Anderson wrote: > > As with other places in the Linux kernel--kfree(NULL) being the most > > famous example--it's convenient to treat being passed a NULL argument > > as a noop in cleanup functions. Let's make > > drm_atomic_helper_shutdown() work like this. > > > > > > [ ... ] > > Acked-by: Maxime Ripard Thanks! If there are no objections, I'd tend to land this patch sometime early next week just to get it out of the queue, even if other patches in the series are still being discussed / need spinning. If anyone objects to that idea, please shout. -Doug
Re: [RFT PATCH 15/15] drm/renesas/shmobile: Call drm_helper_force_disable_all() at shutdown/remove time
Hi, On Mon, Sep 4, 2023 at 12:28 AM Geert Uytterhoeven wrote: > > Hi Douglas, > > On Sat, Sep 2, 2023 at 1:42 AM Douglas Anderson wrote: > > Based on grepping through the source code, this driver appears to be > > missing a call to drm_atomic_helper_shutdown(), or in this case the > > non-atomic equivalent drm_helper_force_disable_all(), at system > > shutdown time and at driver remove time. This is important because > > drm_helper_force_disable_all() will cause panels to get disabled > > cleanly which may be important for their power sequencing. Future > > changes will remove any custom powering off in individual panel > > drivers so the DRM drivers need to start getting this right. > > > > The fact that we should call drm_atomic_helper_shutdown(), or in this > > case the non-atomic equivalent drm_helper_force_disable_all(), in the > > case of OS shutdown/restart comes straight out of the kernel doc > > "driver instance overview" in drm_drv.c. > > > > Suggested-by: Maxime Ripard > > Signed-off-by: Douglas Anderson > > Thanks for your patch! > > > --- a/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c > > +++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c > > @@ -179,12 +180,20 @@ static int shmob_drm_remove(struct platform_device > > *pdev) > > > > drm_dev_unregister(ddev); > > drm_kms_helper_poll_fini(ddev); > > + drm_helper_force_disable_all(ddev); > > After "[PATCH v3 36/41] drm: renesas: shmobile: Atomic conversion part > 1"[1], this function will already call drm_atomic_helper_shutdown()... > > > free_irq(sdev->irq, ddev); > > drm_dev_put(ddev); > > > > return 0; > > } > > > > +static void shmob_drm_shutdown(struct platform_device *pdev) > > +{ > > + struct shmob_drm_device *sdev = platform_get_drvdata(pdev); > > + > > + drm_helper_force_disable_all(sdev->ddev); > > ... and this should be replaced by a call to drm_atomic_helper_shutdown(). > > [1] > https://lore.kernel.org/dri-devel/fd7a6702490bd431f314d6591551bb39e77e3304.1692178020.git.geert+rene...@glider.be Ah, thanks! I will put this patch on hold and check back in a few weeks to see how things are looking. If you wanted to fold it into your series I certainly wouldn't object to it, but if not that's fine too. ;-) -Doug
Re: [RFC PATCH 3/3] drm/virtio: drm_gem_plane_helper_prepare_fb for obj synchronization
Hi Dmitry, On 8/31/2023 3:51 PM, Dmitry Osipenko wrote: On 8/24/23 20:58, Kim, Dongwon wrote: ... You can do fence-wait in the guest userspace/Mesa after blitting/drawing to the udmabuf. There is already synchronization between QEMU and virtio-gpu driver on the guest. Upon resource flush, virtio-gpu waits for the response for the message from the QEMU and QEMU sends out the response once rendering is done. The problem we are seeing is not that the rendering part is reusing the buffer before it's displayed by the QEMU. Problem we are facing is more like some frame is often not finished when "resource-flush" is issued. So unless there is a way for QEMU to wait for this fence (guest drm), I think we should have some synchronization point in the guest side. I saw other DRM drivers, omap, tegra, vc4 and so on are doing the similar so I guess this is a generic solution for such cases. But I do understand your concern as the primary use case of virtio-gpu driver is for virgl. So this extra wait would cost some performance drop. But I have a couple of points here as well. 1. Wouldn't this extra wait caused by drm_gem_plane_helper_prepare_fb be minimal as the actual rendering is done in the host? 2. Can we just make this helper called only if virgl is not used as 3D driver? The problem you described above shouldn't be resolved by your patch. You need to wait for FB to be released by the host's display and not to before GPU finished rendering on guest. I.e. you're swapping display buffers and your dGPU starts rendering to the buffer that is in active use by host's display, correct? I don't believe the guest will start rendering on the same FB while host is consuming it because the virtio-gpu driver on the guest won't release the FB for the next frame before it gets the virtio resp for the resource flush command and the host (QEMU) will hold the response until the rendering is finished. And having this helper clearly fixes the issue we encountered (some old frame is sometimes shown..). But you might be right. The way I understood the original problem might not be 100% correct as it's based on my assumption on how things were fixed with addition of the helper. Then can you help me to approach to the real problem? If it's really fixed by the helper, then what would the original issue be? Maybe you need to do glFinish() on host after swapping buffers? But that will block host for a long time. I can try glFinish everytime after it draws a frame on the host. But.. If that is the issue, then wouldn't I expect some skipped frames, not old frames? For now I don't have solution. Virglrender today supports native contexts. The method you're using for GPU priming was proven to be slow in comparison to multi-gpu native contexts. There is ongoing work for supporting fence passing from guest to host [1] that allows to do fence-syncing on host. You'll find links to the WIP virtio-intel native context in [1] as well. You won't find GPU priming support using native context in [1], patches hasn't been published yet. [1] https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/1138 Note that in general it's not acceptable to upstream patches that serve downstream only. Yours display sync issue is irrelevant to the upstream stack unless you're going to upstream all the VMM and guest userspace patches, and in such case you should always publish all the patches and provide links. So, you need to check the performance impact and publish all the patches to the relevant upstream projects. QEMU has all patches regarding this (blob scanout support) but guest Mesa patch for KMSRO is still outstanding. https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9592 I understand this specific patch would need more discussion/justification but what about other two, are you generally ok with those in the same series? The first patch should be dropped. The second one could be useful, Yes, the first one will be gone. I will upload a revised version of the second one only with proper explanation. you'll need to provide step-by-step instruction for how to reproduce the multi-display issue, please write it in the cover-letter for the next patch version. Thanks. Always appreciate your feedback!!
Re: [RFT PATCH 2/6] drm: Call drm_atomic_helper_shutdown() at shutdown time for misc drivers
Dne sobota, 02. september 2023 ob 01:39:53 CEST je Douglas Anderson napisal(a): > Based on grepping through the source code these drivers appear to be > missing a call to drm_atomic_helper_shutdown() at system shutdown > time. Among other things, this means that if a panel is in use that it > won't be cleanly powered off at system shutdown time. > > The fact that we should call drm_atomic_helper_shutdown() in the case > of OS shutdown/restart comes straight out of the kernel doc "driver > instance overview" in drm_drv.c. > > All of the drivers in this patch were fairly straightforward to fix > since they already had a call to drm_atomic_helper_shutdown() at > remove/unbind time but were just lacking one at system shutdown. The > only hitch is that some of these drivers use the component model to > register/unregister their DRM devices. The shutdown callback is part > of the original device. The typical solution here, based on how other > DRM drivers do this, is to keep track of whether the device is bound > based on drvdata. In most cases the drvdata is the drm_device, so we > can just make sure it is NULL when the device is not bound. In some > drivers, this required minor code changes. To make things simpler, > drm_atomic_helper_shutdown() has been modified to consider a NULL > drm_device as a noop in the patch ("drm/atomic-helper: > drm_atomic_helper_shutdown(NULL) should be a noop"). > > Suggested-by: Maxime Ripard > Signed-off-by: Douglas Anderson > --- > This commit is only compile-time tested. > > Note that checkpatch yells that "drivers/gpu/drm/tiny/cirrus.c" is > marked as 'obsolete', but it seems silly not to include the fix if > it's already been written. If someone wants me to take that out, > though, I can. > > drivers/gpu/drm/arm/display/komeda/komeda_drv.c | 9 + > drivers/gpu/drm/arm/display/komeda/komeda_kms.c | 7 +++ > drivers/gpu/drm/arm/display/komeda/komeda_kms.h | 1 + > drivers/gpu/drm/arm/hdlcd_drv.c | 6 ++ > drivers/gpu/drm/arm/malidp_drv.c| 6 ++ > drivers/gpu/drm/ast/ast_drv.c | 6 ++ > drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c| 6 ++ > drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | 8 > drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 6 ++ > drivers/gpu/drm/hyperv/hyperv_drm_drv.c | 6 ++ > drivers/gpu/drm/logicvc/logicvc_drm.c | 9 + > drivers/gpu/drm/loongson/lsdc_drv.c | 6 ++ > drivers/gpu/drm/mcde/mcde_drv.c | 9 + > drivers/gpu/drm/omapdrm/omap_drv.c | 8 > drivers/gpu/drm/qxl/qxl_drv.c | 7 +++ > drivers/gpu/drm/sti/sti_drv.c | 7 +++ > drivers/gpu/drm/sun4i/sun4i_drv.c | 6 ++ For sun4i: Tested-by: Jernej Skrabec Reviewed-by: Jernej Skrabec Best regards, Jernej > drivers/gpu/drm/tiny/bochs.c| 6 ++ > drivers/gpu/drm/tiny/cirrus.c | 6 ++ > 19 files changed, 125 insertions(+)
Re: [PATCH 2/2] drm/panel: Add AUO G156HAN04.0 LVDS display support
Hi Elmar, Just had a few minor comments: Looking at past panel-simple changes, I think the prefix here should be "drm/panel: simple:" On 8/28/2023 2:49 AM, Elmar Albert wrote: From: Elmar Albert G156HAN04.0 is a Color Active Matrix Liquid Crystal Display composed of a TFT LCD panel, a driver circuit, and LED backlight system. The screen format is intended to supportthe 16:9 FHD, 1920(H) x 1080(V) screen nit: "support the" and 16.7M colors (RGB 8-bits ) with LED backlight driving circuit. All input signals are LVDS interface compatible. G156HAN04.0 is designed for a display unit of notebook style personal computer and industrial machine. Signed-off-by: Elmar Albert --- Cc: Conor Dooley Cc: Daniel Vetter Cc: David Airlie Cc: devicet...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: Krzysztof Kozlowski Cc: Neil Armstrong Cc: Rob Herring Cc: Sam Ravnborg Cc: Thierry Reding --- drivers/gpu/drm/panel/panel-simple.c | 36 1 file changed, 36 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 52572fde9705..4fe6dafcabf6 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1050,6 +1050,39 @@ static const struct panel_desc auo_g133han01 = { .connector_type = DRM_MODE_CONNECTOR_LVDS, }; +static const struct display_timing auo_g156han04_timings = { + .pixelclock = { 13700, 14100, 14600 }, + + .hactive = { 1920, 1920, 1920 }, + .hfront_porch = { 60, 60, 60 }, + .hback_porch = { 90, 92, 111 }, + .hsync_len ={ 32, 32, 32 }, + + .vactive = { 1080, 1080, 1080 }, + .vfront_porch = { 12, 12, 12 }, + .vback_porch = { 24, 36, 56 }, + .vsync_len ={ 8, 8, 8 }, +}; + +static const struct panel_desc auo_g156han04 = { + .timings = &auo_g156han04_timings, + .num_timings = 1, + .bpc = 8, + .size = { + .width = 344, + .height = 194, + }, + .delay = { + .prepare = 50, /* T2 */ + .enable = 200, /* T3 */ + .disable = 110, /* T10 */ + .unprepare = 1000, /* T13 */ The inclusion of the comments seems unnecessary. Thanks, Jessica Zhang + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct drm_display_mode auo_g156xtn01_mode = { .clock = 76000, .hdisplay = 1366, @@ -4118,6 +4151,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "auo,g133han01", .data = &auo_g133han01, + }, { + .compatible = "auo,g156han04", + .data = &auo_g156han04, }, { .compatible = "auo,g156xtn01", .data = &auo_g156xtn01, -- 2.34.1
Re: [RFT PATCH 13/15] drm/imx/ipuv3: Call drm_atomic_helper_shutdown() at shutdown/unbind time
Hi, On Mon, Sep 4, 2023 at 1:30 AM Philipp Zabel wrote: > > On Fr, 2023-09-01 at 16:41 -0700, Douglas Anderson wrote: > > Based on grepping through the source code this driver appears to be > > missing a call to drm_atomic_helper_shutdown() at system shutdown time > > and at driver unbind time. Among other things, this means that if a > > panel is in use that it won't be cleanly powered off at system > > shutdown time. > > > > The fact that we should call drm_atomic_helper_shutdown() in the case > > of OS shutdown/restart and at driver remove (or unbind) time comes > > straight out of the kernel doc "driver instance overview" in > > drm_drv.c. > > > > A few notes about this fix: > > - When adding drm_atomic_helper_shutdown() to the unbind path, I added > > it after drm_kms_helper_poll_fini() since that's when other drivers > > seemed to have it. > > - Technically with a previous patch, ("drm/atomic-helper: > > drm_atomic_helper_shutdown(NULL) should be a noop"), we don't > > actually need to check to see if our "drm" pointer is NULL before > > calling drm_atomic_helper_shutdown(). We'll leave the "if" test in, > > though, so that this patch can land without any dependencies. It > > could potentially be removed later. > > - This patch also makes sure to set the drvdata to NULL in the case of > > bind errors to make sure that shutdown can't access freed data. > > > > Suggested-by: Maxime Ripard > > Signed-off-by: Douglas Anderson > > Thank you, > Tested-by: Philipp Zabel Thanks! I notice that: ./scripts/get_maintainer.pl --scm -f drivers/gpu/drm/imx/ipuv3/imx-drm-core.c Doesn't say drm-misc but also when I look at the MAINTAINERS file and find the section for "DRM DRIVERS FOR FREESCALE IMX" it doesn't explicitly list a different git tree. I guess the "shawnguo" git tree listed by get_maintainer.pl is just from regex matching? Would you expect this to go through drm-misc? If so, I'll probably land it sooner rather than later. I can also post up a patch making it obvious that "DRM DRIVERS FOR FREESCALE IMX" goes through drm-misc if you don't object. Thanks! -Doug
Re: [PATCH v3 2/5] dt-bindings: display: tegra: nvidia,tegra20-dc: Add parallel RGB output port node
Hi Rob, On 21.08.23 18:14, Rob Herring wrote: > On Mon, Aug 07, 2023 at 05:35:12PM +0300, Svyatoslav Ryhel wrote: >> From: Maxim Schwalm >> >> Either this node, which is optional, or the nvidia,panel property can be >> present. >> >> Signed-off-by: Maxim Schwalm >> Signed-off-by: Svyatoslav Ryhel >> --- >> .../display/tegra/nvidia,tegra20-dc.yaml | 31 +++ >> 1 file changed, 31 insertions(+) >> >> diff --git >> a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-dc.yaml >> b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-dc.yaml >> index 69be95afd562..102304703062 100644 >> --- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-dc.yaml >> +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-dc.yaml >> @@ -127,6 +127,37 @@ allOf: >>$ref: /schemas/types.yaml#/definitions/phandle >>description: phandle of a display panel >> >> +port: >> + $ref: /schemas/graph.yaml#/$defs/port-base >> + description: Parallel RGB output port >> + >> + properties: >> +endpoint: >> + $ref: /schemas/media/video-interfaces.yaml# > > Just to make sure, what properties are you using from this? Usually > we'll list them though not a hard requirement. If none, then you just > need to ref graph.yaml#/properties/port instead and can drop the rest. currently, just bus-width is used in devicetrees, but I don't think that it is needed at the moment. So perhaps the property can be dropped. >> + unevaluatedProperties: false >> + >> + unevaluatedProperties: false > > In the indented cases, it's easier to read if this is before > properties/patternProperties. > >> + >> + anyOf: >> +- if: >> +not: >> + properties: >> +nvidia,panel: false >> + then: >> +not: >> + properties: >> +port: true >> +- if: >> +not: >> + properties: >> +port: false >> + then: >> +not: >> + properties: >> +nvidia,panel: true > > I would prefer to drop this and mark "nvidia,panel" as deprecated. > Eventually I plan to add a mode to the tools to warn on using deprecated > properties. Having both could be perfectly fine too. You have the > "nvidia,panel" for compatibility with an old OS version and 'port' to > work with newer users. The reason for adding this was that just one of them can be utilized at the same time. Having both could potentially break the display output. I think that all the other nvidia,* properties could marked as deprecated as well because they don't seem to be doing much since commit d9f980ebcd01 ("drm/tegra: output: rgb: Wrap directly-connected panel into DRM bridge"). >> + >> + additionalProperties: false > > Move this up too. > Best regards, Maxim
Re: [RFT PATCH 03/15] drm/ingenic: Call drm_atomic_helper_shutdown() at shutdown time
Paul, On Mon, Sep 4, 2023 at 2:15 AM Paul Cercueil wrote: > > Hi Douglas, > > Le vendredi 01 septembre 2023 à 16:41 -0700, Douglas Anderson a écrit : > > Based on grepping through the source code this driver appears to be > > missing a call to drm_atomic_helper_shutdown() at system shutdown > > time. Among other things, this means that if a panel is in use that > > it > > won't be cleanly powered off at system shutdown time. > > > > The fact that we should call drm_atomic_helper_shutdown() in the case > > of OS shutdown/restart comes straight out of the kernel doc "driver > > instance overview" in drm_drv.c. > > > > Since this driver uses the component model and shutdown happens at > > the > > base driver, we communicate whether we have to call > > drm_atomic_helper_shutdown() by seeing if drvdata is non-NULL. > > > > Suggested-by: Maxime Ripard > > Signed-off-by: Douglas Anderson > > LGTM. > Acked-by: Paul Cercueil Thanks for the Ack! Would you expect this patch to land through "drm-misc", or do you expect it to go through some other tree? Running: ./scripts/get_maintainer.pl --scm -f drivers/gpu/drm/ingenic/ingenic-drm-drv.c ...does not show that this driver normally goes through drm-misc, but it also doesn't show that it goes through any other tree so maybe it's just an artifact of the way it's tagged in the MAINTAINERS file? If it's fine for this to go through drm-misc, I'll probably land it (with your Ack and Maxime's Review) sooner rather than later just to make this patch series less unwieldy. > > --- > > This commit is only compile-time tested. > > > > NOTE: this patch touches a lot more than other similar patches since > > the bind() function is long and we want to make sure that we unset > > the > > drvdata if bind() fails. > > > > While making this patch, I noticed that the bind() function of this > > driver is using "devm" and thus assumes it doesn't need to do much > > explicit error handling. That's actually a bug. As per kernel docs > > [1] > > "the lifetime of the aggregate driver does not align with any of the > > underlying struct device instances. Therefore devm cannot be used and > > all resources acquired or allocated in this callback must be > > explicitly released in the unbind callback". Fixing that is outside > > the scope of this commit. > > > > [1] https://docs.kernel.org/driver-api/component.html > > > > Noted, thanks. FWIW, I think that at least a few other DRM drivers handle this by doing some of their resource allocation / acquiring in the probe() function and then only doing things in the bind() that absolutely need to be in the bind. ;-) -Doug
Re: [PATCH v2] Documentation/gpu: VM_BIND locking document
On Wed, Aug 16, 2023 at 11:15:47AM +0200, Thomas Hellström wrote: > Add the first version of the VM_BIND locking document which is > intended to be part of the xe driver upstreaming agreement. > > The document describes and discuss the locking used during exec- > functions, evicton and for userptr gpu-vmas. Intention is to be using the > same nomenclature as the drm-vm-bind-async.rst. > > v2: > - s/gvm/gpu_vm/g (Rodrigo Vivi) > - Clarify the userptr seqlock with a pointer to mm/mmu_notifier.c > (Rodrigo Vivi) > - Adjust commit message accordingly. > - Add SPDX license header. > > Cc: Rodrigo Vivi > Signed-off-by: Thomas Hellström > --- > Documentation/gpu/drm-vm-bind-locking.rst | 351 ++ > 1 file changed, 351 insertions(+) > create mode 100644 Documentation/gpu/drm-vm-bind-locking.rst > > diff --git a/Documentation/gpu/drm-vm-bind-locking.rst > b/Documentation/gpu/drm-vm-bind-locking.rst > new file mode 100644 > index ..b813961a9ec2 > --- /dev/null > +++ b/Documentation/gpu/drm-vm-bind-locking.rst > @@ -0,0 +1,351 @@ > +.. SPDX-License-Identifier: (GPL-2.0+ OR MIT) > + > +=== > +VM_BIND locking > +=== > + > +This document attempts to describe what's needed to get VM_BIND locking > right, > +including the userptr mmu_notifier locking and it will also discuss some > +optimizations to get rid of the looping through of all userptr mappings and > +external / shared object mappings that is needed in the simplest > +implementation. It will also discuss some implications for faulting gpu_vms. > + > +Nomenclature > + > + > +* ``Context``: GPU execution context. > +* ``gpu_vm``: Abstraction of a virtual GPU address space with > + meta-data. Typically one per client (DRM file-private), or one per > + context. > +* ``gpu_vma``: Abstraction of a GPU address range within a gpu_vm with The same nomenclature was used within the VM_BIND async document as well. I wonder if it would make sense to align the naming with the GPUVA manager, such that ('drm_gpuva_manager' -> 'drm_gpuvm'). This would also result into better function names, such as drm_gpuvm_resv_lock() or drm_gpuvm_prepare_objects() and potentially way better naming for the VM_BO abstraction 'drm_gpuvm_bo'. However, I'd like to keep 'drm_gpuva' rather than 'drm_gpu_vma', but I think this is close enough anyway. > + associated meta-data. The backing storage of a gpu_vma can either be > + a gem buffer object or anonymous pages mapped also into the CPU > + address space for the process. > +* ``userptr gpu_vma or just userptr``: A gpu_vma, the backing store of > + which is anonymous pages as described above. > +* ``revalidating``: Revalidating a gpu_vma means making the latest version > + of the backing store resident and making sure the gpu_vma's > + page-table entries point to that backing store. > +* ``dma_fence``: A struct dma_fence that is similar to a struct completion > + and which tracks GPU activity. When the GPU activity is finished, > + the dma_fence signals. > +* ``dma_resv``: A struct dma_resv (AKA reservation object) that is used > + to track GPU activity in the form of multiple dma_fences on a > + gpu_vm or a gem buffer object. The dma_resv contains an array / list > + of dma_fences and a lock that needs to be held when adding > + additional dma_fences to the dma_resv. The lock is of a type that > + allows deadlock-safe locking of multiple dma_resvs in arbitrary order. > +* ``exec function``: An exec function is a function that revalidates all > + affected gpu_vmas, submits a GPU command batch and registers the > + dma_fence representing the GPU command's activity with all affected > + dma_resvs. For completeness, although not covered by this document, > + it's worth mentioning that an exec function may also be the > + revalidation worker that is used by some drivers in compute / > + long-running mode. > +* ``local object``: A GEM object which is local to a gpu_vm. Shared gem > + objects also share the gpu_vm's dma_resv. > +* ``shared object``: AKA external object: A GEM object which may be shared > + by multiple gpu_vms and whose backing storage may be shared with > + other drivers. > + > + > +Introducing the locks > += > + > +One of the benefits of VM_BIND is that local GEM objects share the gpu_vm's > +dma_resv object and hence the dma_resv lock. So even with a huge > +number of local GEM objects, only one lock is needed to make the exec > +sequence atomic. > + > +The following locks and locking orders are used: > + > +* The ``gpu_vm->lock`` (optionally an rwsem). Protects how the gpu_vm is > + partitioned into gpu_vmas, protects the gpu_vm's list of external objects, > + and can also with some simplification protect the gpu_vm's list of > + userptr gpu_vmas. With the CPU mm analogy this would correspond to the > + mmap_lock. > +* The ``userptr_seqlock``. This lock is taken in read mode for each > + userptr gpu_vma on t
[PATCH] drm/i915/mtl: Drop force_probe requirement
Meteorlake has been very usable for a while now, all of uapi changes related to fundamental platform usage have been finalized and all required firmware blobs are available. Recent CI results have also been healthy, so we're ready to drop the force_probe requirement and enable the platform by default. Cc: Rodrigo Vivi Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Cc: Jani Nikula Signed-off-by: Radhakrishna Sripada --- drivers/gpu/drm/i915/i915_pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index df7c261410f7..fe748906c06f 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -836,7 +836,6 @@ static const struct intel_device_info mtl_info = { .has_pxp = 1, .memory_regions = REGION_SMEM | REGION_STOLEN_LMEM, .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(CCS0), - .require_force_probe = 1, MTL_CACHELEVEL, }; -- 2.34.1
Re: [PATCH] drm/amd/display: prevent potential division by zero errors
On 2023-09-05 14:53, Hamza Mahfooz wrote: There are two places in apply_below_the_range() where it's possible for a divide by zero error to occur. So, to fix this make sure the divisor is non-zero before attempting the computation in both cases. Cc: sta...@vger.kernel.org Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2637 Fixes: a463b263032f ("drm/amd/display: Fix frames_to_insert math") Fixes: ded6119e825a ("drm/amd/display: Reinstate LFC optimization") Signed-off-by: Hamza Mahfooz --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index dbd60811f95d..ef3a67409021 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -338,7 +338,9 @@ static void apply_below_the_range(struct core_freesync *core_freesync, * - Delta for CEIL: delta_from_mid_point_in_us_1 * - Delta for FLOOR: delta_from_mid_point_in_us_2 */ - if ((last_render_time_in_us / mid_point_frames_ceil) < in_out_vrr->min_duration_in_us) { + if (mid_point_frames_ceil && + (last_render_time_in_us / mid_point_frames_ceil) < + in_out_vrr->min_duration_in_us) { /* Check for out of range. * If using CEIL produces a value that is out of range, * then we are forced to use FLOOR. @@ -385,8 +387,9 @@ static void apply_below_the_range(struct core_freesync *core_freesync, /* Either we've calculated the number of frames to insert, * or we need to insert min duration frames */ - if (last_render_time_in_us / frames_to_insert < - in_out_vrr->min_duration_in_us){ + if (frames_to_insert && + (last_render_time_in_us / frames_to_insert) < + in_out_vrr->min_duration_in_us){ frames_to_insert -= (frames_to_insert > 1) ? 1 : 0; } Reviewed-by: Aurabindo Pillai -- Thanks & Regards, Jay
Re: [RFC PATCH 00/10] drm/panel: Remove most store/double-check of prepared/enabled state
Hi, On Thu, Aug 10, 2023 at 1:23 AM Linus Walleij wrote: > > On Fri, Aug 4, 2023 at 11:07 PM Douglas Anderson > wrote: > > > As talked about in commit d2aacaf07395 ("drm/panel: Check for already > > prepared/enabled in drm_panel"), we want to remove needless code from > > panel drivers that was storing and double-checking the > > prepared/enabled state. Even if someone was relying on the > > double-check before, that double-check is now in the core and not > > needed in individual drivers. > > > > This series attempts to do just that. While the original grep, AKA: > > git grep 'if.*>prepared' -- drivers/gpu/drm/panel > > git grep 'if.*>enabled' -- drivers/gpu/drm/panel > > ...still produces a few hits after my series, they are _mostly_ all > > gone. The ones that are left are less trivial to fix. > > > > One of the main reasons that many panels probably needed to store and > > double-check their prepared/enabled appears to have been to handle > > shutdown and/or remove. Panels drivers often wanted to force the power > > off for panels in these cases and this was a good reason for the > > double-check. As part of this series a new helper is added that uses > > the state tracking that the drm_panel core is doing so each individual > > panel driver doesn't need to do it. > > > > This series changes a lot of drivers and obviously the author can't > > test on all of them. The changes here are also not completely trivial > > in all cases. Please double-check your drivers carefully to make sure > > something wasn't missed. After looking at over 40 drivers I'll admit > > that my eyes glazed over a little. > > > > I've attempted to organize these patches like to group together panels > > that needed similar handling. Panels that had code that didn't seem to > > match anyone else got their own patch. I made judgement calls on what > > I considered "similar". > > > > As noted in individual patches, there are some cases here where I > > expect behavior to change a little bit. I'm hoping these changes are > > for the better and don't cause any problems. Fingers crossed. > > > > I have at least confirmed that "allmodconfig" for arm64 doesn't fall > > on its face with this series. I haven't done a ton of other testing. > > The series: > Reviewed-by: Linus Walleij > > Please send out a non-RFC version, this is clearly the right thing to > do. As per the long discussion in response to patch #4, I think there are still open questions about the later patches in this series. However, I could land patches #1 - #3 if there are no concerns. Would anyone object if I just landed them straight from this series with Linus's review, or would I need to repost just patches #1 - #3 without the "RFC" tag? Thanks! -Doug
Re: [RFC PATCH 04/10] drm/panel_helper: Introduce drm_panel_helper
Hi, On Tue, Sep 5, 2023 at 9:45 AM Doug Anderson wrote: > > As per our discussion, in V2 we will make drm_panel_remove() actually > unprepare / disable a panel if it was left enabled. This would > essentially fold in the drm_panel_helper_shutdown() from my RFC patch. > This would make tdo_tl070wsh30_panel_remove() behave the same as it > did before. Ugh, though I may have to think about this more when I get > to implementation since I don't think there's a guarantee of the > ordering of shutdown calls between the DRM driver and the panel. > Anyway, something to discuss later. Ugh, ignore the above paragraph. I managed to confuse myself and was thinking about shutdown but talking about remove. Sigh. :( Instead, pretend the above paragraph said: As per our discussion, in V2 we will make drm_panel_remove() actually unprepare / disable a panel (and print a warning) if it was left enabled. This would essentially fold in the drm_panel_helper_shutdown() from my RFC patch (but add a warning). This would make tdo_tl070wsh30_panel_remove() behave the same as it did before with the addition of a warning if someone tries to remove a currently powered panel. -Doug
[PATCH] drm/amd/display: prevent potential division by zero errors
There are two places in apply_below_the_range() where it's possible for a divide by zero error to occur. So, to fix this make sure the divisor is non-zero before attempting the computation in both cases. Cc: sta...@vger.kernel.org Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2637 Fixes: a463b263032f ("drm/amd/display: Fix frames_to_insert math") Fixes: ded6119e825a ("drm/amd/display: Reinstate LFC optimization") Signed-off-by: Hamza Mahfooz --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index dbd60811f95d..ef3a67409021 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -338,7 +338,9 @@ static void apply_below_the_range(struct core_freesync *core_freesync, * - Delta for CEIL: delta_from_mid_point_in_us_1 * - Delta for FLOOR: delta_from_mid_point_in_us_2 */ - if ((last_render_time_in_us / mid_point_frames_ceil) < in_out_vrr->min_duration_in_us) { + if (mid_point_frames_ceil && + (last_render_time_in_us / mid_point_frames_ceil) < + in_out_vrr->min_duration_in_us) { /* Check for out of range. * If using CEIL produces a value that is out of range, * then we are forced to use FLOOR. @@ -385,8 +387,9 @@ static void apply_below_the_range(struct core_freesync *core_freesync, /* Either we've calculated the number of frames to insert, * or we need to insert min duration frames */ - if (last_render_time_in_us / frames_to_insert < - in_out_vrr->min_duration_in_us){ + if (frames_to_insert && + (last_render_time_in_us / frames_to_insert) < + in_out_vrr->min_duration_in_us){ frames_to_insert -= (frames_to_insert > 1) ? 1 : 0; } -- 2.41.0
[PATCH v3 6/8] drm/drm_file: Add DRM obj's RSS reporting function for fdinfo
Some BO's might be mapped onto physical memory chunkwise and on demand, like Panfrost's tiler heap. In this case, even though the drm_gem_shmem_object page array might already be allocated, only a very small fraction of the BO is currently backed by system memory, but drm_show_memory_stats will then proceed to add its entire virtual size to the file's total resident size regardless. This led to very unrealistic RSS sizes being reckoned for Panfrost, where said tiler heap buffer is initially allocated with a virtual size of 128 MiB, but only a small part of it will eventually be backed by system memory after successive GPU page faults. Provide a new DRM object generic function that would allow drivers to return a more accurate RSS size for their BOs. Signed-off-by: Adrián Larumbe Reviewed-by: Boris Brezillon --- drivers/gpu/drm/drm_file.c | 5 - include/drm/drm_gem.h | 9 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index 883d83bc0e3d..762965e3d503 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -944,7 +944,10 @@ void drm_show_memory_stats(struct drm_printer *p, struct drm_file *file) } if (s & DRM_GEM_OBJECT_RESIDENT) { - status.resident += obj->size; + if (obj->funcs && obj->funcs->rss) + status.resident += obj->funcs->rss(obj); + else + status.resident += obj->size; } else { /* If already purged or not yet backed by pages, don't * count it as purgeable: diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index bc9f6aa2f3fe..16364487fde9 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@ -208,6 +208,15 @@ struct drm_gem_object_funcs { */ enum drm_gem_object_status (*status)(struct drm_gem_object *obj); + /** +* @rss: +* +* Return resident size of the object in physical memory. +* +* Called by drm_show_memory_stats(). +*/ + size_t (*rss)(struct drm_gem_object *obj); + /** * @vm_ops: * -- 2.42.0
[PATCH v3 8/8] drm/drm-file: Show finer-grained BO sizes in drm_show_memory_stats
The current implementation will try to pick the highest available size display unit as soon as the BO size exceeds that of the previous multiplier. By selecting a higher threshold, we could show more accurate size numbers. Signed-off-by: Adrián Larumbe --- drivers/gpu/drm/drm_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index 762965e3d503..0b5fbd493e05 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -879,7 +879,7 @@ static void print_size(struct drm_printer *p, const char *stat, unsigned u; for (u = 0; u < ARRAY_SIZE(units) - 1; u++) { - if (sz < SZ_1K) + if (sz < (SZ_1K * 1)) break; sz = div_u64(sz, SZ_1K); } -- 2.42.0
[PATCH v3 7/8] drm/panfrost: Implement generic DRM object RSS reporting function
BO's RSS is updated every time new pages are allocated on demand and mapped for the object at GPU page fault's IRQ handler, but only for heap buffers. The reason this is unnecessary for non-heap buffers is that they are mapped onto the GPU's VA space and backed by physical memory in their entirety at BO creation time. This calculation is unnecessary for imported PRIME objects, since heap buffers cannot be exported by our driver, and the actual BO RSS size is the one reported in its attached dmabuf structure. Signed-off-by: Adrián Larumbe --- drivers/gpu/drm/panfrost/panfrost_gem.c | 14 ++ drivers/gpu/drm/panfrost/panfrost_gem.h | 5 + drivers/gpu/drm/panfrost/panfrost_mmu.c | 12 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c index 7d8f83d20539..cb92c0ed7615 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -208,6 +208,19 @@ static enum drm_gem_object_status panfrost_gem_status(struct drm_gem_object *obj return res; } +static size_t panfrost_gem_rss(struct drm_gem_object *obj) +{ + struct panfrost_gem_object *bo = to_panfrost_bo(obj); + + if (bo->is_heap) + return bo->heap_rss_size; + else if (bo->base.pages) { + WARN_ON(bo->heap_rss_size); + return bo->base.base.size; + } else + return 0; +} + static const struct drm_gem_object_funcs panfrost_gem_funcs = { .free = panfrost_gem_free_object, .open = panfrost_gem_open, @@ -220,6 +233,7 @@ static const struct drm_gem_object_funcs panfrost_gem_funcs = { .vunmap = drm_gem_shmem_object_vunmap, .mmap = drm_gem_shmem_object_mmap, .status = panfrost_gem_status, + .rss = panfrost_gem_rss, .vm_ops = &drm_gem_shmem_vm_ops, }; diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.h b/drivers/gpu/drm/panfrost/panfrost_gem.h index ad2877eeeccd..13c0a8149c3a 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.h +++ b/drivers/gpu/drm/panfrost/panfrost_gem.h @@ -36,6 +36,11 @@ struct panfrost_gem_object { */ atomic_t gpu_usecount; + /* +* Object chunk size currently mapped onto physical memory +*/ + size_t heap_rss_size; + bool noexec :1; bool is_heap:1; }; diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index d54d4e7b2195..67c206124781 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -285,17 +285,19 @@ static void panfrost_mmu_flush_range(struct panfrost_device *pfdev, pm_runtime_put_autosuspend(pfdev->dev); } -static int mmu_map_sg(struct panfrost_device *pfdev, struct panfrost_mmu *mmu, +static size_t mmu_map_sg(struct panfrost_device *pfdev, struct panfrost_mmu *mmu, u64 iova, int prot, struct sg_table *sgt) { unsigned int count; struct scatterlist *sgl; struct io_pgtable_ops *ops = mmu->pgtbl_ops; u64 start_iova = iova; + size_t total = 0; for_each_sgtable_dma_sg(sgt, sgl, count) { unsigned long paddr = sg_dma_address(sgl); size_t len = sg_dma_len(sgl); + total += len; dev_dbg(pfdev->dev, "map: as=%d, iova=%llx, paddr=%lx, len=%zx", mmu->as, iova, paddr, len); @@ -315,7 +317,7 @@ static int mmu_map_sg(struct panfrost_device *pfdev, struct panfrost_mmu *mmu, panfrost_mmu_flush_range(pfdev, mmu, start_iova, iova - start_iova); - return 0; + return total; } int panfrost_mmu_map(struct panfrost_gem_mapping *mapping) @@ -447,6 +449,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, pgoff_t page_offset; struct sg_table *sgt; struct page **pages; + size_t mapped_size; bomapping = addr_to_mapping(pfdev, as, addr); if (!bomapping) @@ -518,10 +521,11 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, if (ret) goto err_map; - mmu_map_sg(pfdev, bomapping->mmu, addr, - IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt); + mapped_size = mmu_map_sg(pfdev, bomapping->mmu, addr, +IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt); bomapping->active = true; + bo->heap_rss_size += mapped_size; dev_dbg(pfdev->dev, "mapped page fault @ AS%d %llx", as, addr); -- 2.42.0
[PATCH v3 3/8] drm/panfrost: Enable debugfs toggling of cycle counter register
Allow user space to decide whether the cycle counting register should be enabled. The main goal is letting tools like nvtop or IGT's gputop access this information in debug builds to obtain engine utilisation numbers. Signed-off-by: Adrián Larumbe --- drivers/gpu/drm/panfrost/Makefile | 2 + drivers/gpu/drm/panfrost/panfrost_debugfs.c | 51 + drivers/gpu/drm/panfrost/panfrost_debugfs.h | 13 ++ drivers/gpu/drm/panfrost/panfrost_drv.c | 5 ++ 4 files changed, 71 insertions(+) create mode 100644 drivers/gpu/drm/panfrost/panfrost_debugfs.c create mode 100644 drivers/gpu/drm/panfrost/panfrost_debugfs.h diff --git a/drivers/gpu/drm/panfrost/Makefile b/drivers/gpu/drm/panfrost/Makefile index 7da2b3f02ed9..2c01c1e7523e 100644 --- a/drivers/gpu/drm/panfrost/Makefile +++ b/drivers/gpu/drm/panfrost/Makefile @@ -12,4 +12,6 @@ panfrost-y := \ panfrost_perfcnt.o \ panfrost_dump.o +panfrost-$(CONFIG_DEBUG_FS) += panfrost_debugfs.o + obj-$(CONFIG_DRM_PANFROST) += panfrost.o diff --git a/drivers/gpu/drm/panfrost/panfrost_debugfs.c b/drivers/gpu/drm/panfrost/panfrost_debugfs.c new file mode 100644 index ..48d5ddfcb1c6 --- /dev/null +++ b/drivers/gpu/drm/panfrost/panfrost_debugfs.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright 2023 Collabora ltd. */ + +#include +#include +#include +#include + +#include "panfrost_device.h" +#include "panfrost_gpu.h" +#include "panfrost_debugfs.h" + +static int +profile_get(void *data, u64 *val) +{ + struct drm_device *dev = data; + struct panfrost_device *pfdev = dev->dev_private; + + *val = atomic_read(&pfdev->profile_mode); + + return 0; +} + +static int +profile_set(void *data, u64 val) +{ + struct drm_device *dev = data; + struct panfrost_device *pfdev = dev->dev_private; + + if (atomic_read(&pfdev->profile_mode) == val) + return 0; + + if (val == false) + panfrost_cycle_counter_stop(pfdev); + else + atomic_set(&pfdev->profile_mode, 1); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(profile_fops, +profile_get, profile_set, +"%llu\n"); + +void panfrost_debugfs_init(struct drm_minor *minor) +{ + struct drm_device *dev = minor->dev; + + debugfs_create_file("profile", 0600, minor->debugfs_root, + dev, &profile_fops); +} diff --git a/drivers/gpu/drm/panfrost/panfrost_debugfs.h b/drivers/gpu/drm/panfrost/panfrost_debugfs.h new file mode 100644 index ..db1c158bcf2f --- /dev/null +++ b/drivers/gpu/drm/panfrost/panfrost_debugfs.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2023 Collabora ltd. + */ + +#ifndef PANFROST_DEBUGFS_H +#define PANFROST_DEBUGFS_H + +#ifdef CONFIG_DEBUG_FS +void panfrost_debugfs_init(struct drm_minor *minor); +#endif + +#endif /* PANFROST_DEBUGFS_H */ diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index a2ab99698ca8..2dfd9f79a31b 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -20,6 +20,7 @@ #include "panfrost_job.h" #include "panfrost_gpu.h" #include "panfrost_perfcnt.h" +#include "panfrost_debugfs.h" static bool unstable_ioctls; module_param_unsafe(unstable_ioctls, bool, 0600); @@ -546,6 +547,10 @@ static const struct drm_driver panfrost_drm_driver = { .gem_create_object = panfrost_gem_create_object, .gem_prime_import_sg_table = panfrost_gem_prime_import_sg_table, + +#ifdef CONFIG_DEBUG_FS + .debugfs_init = panfrost_debugfs_init, +#endif }; static int panfrost_probe(struct platform_device *pdev) -- 2.42.0
[PATCH v3 5/8] drm/panfrost: Add fdinfo support for memory stats
A new DRM GEM object function is added so that drm_show_memory_stats can provide more accurate memory usage numbers. Ideally, in panfrost_gem_status, the BO's purgeable flag would be checked after locking the driver's shrinker mutex, but drm_show_memory_stats takes over the drm file's object handle database spinlock, so there's potential for a race condition here. Signed-off-by: Adrián Larumbe --- drivers/gpu/drm/panfrost/panfrost_drv.c | 1 + drivers/gpu/drm/panfrost/panfrost_gem.c | 14 ++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index 94787f4aee27..3de7e821ef23 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -574,6 +574,7 @@ static void panfrost_show_fdinfo(struct drm_printer *p, struct drm_file *file) panfrost_gpu_show_fdinfo(pfdev, file->driver_priv, p); + drm_show_memory_stats(p, file); } static const struct file_operations panfrost_drm_driver_fops = { diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c index 3c812fbd126f..7d8f83d20539 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -195,6 +195,19 @@ static int panfrost_gem_pin(struct drm_gem_object *obj) return drm_gem_shmem_pin(&bo->base); } +static enum drm_gem_object_status panfrost_gem_status(struct drm_gem_object *obj) +{ + struct panfrost_gem_object *bo = to_panfrost_bo(obj); + enum drm_gem_object_status res = 0; + + res |= (bo->base.madv == PANFROST_MADV_DONTNEED) ? + DRM_GEM_OBJECT_PURGEABLE : 0; + + res |= (bo->base.pages) ? DRM_GEM_OBJECT_RESIDENT : 0; + + return res; +} + static const struct drm_gem_object_funcs panfrost_gem_funcs = { .free = panfrost_gem_free_object, .open = panfrost_gem_open, @@ -206,6 +219,7 @@ static const struct drm_gem_object_funcs panfrost_gem_funcs = { .vmap = drm_gem_shmem_object_vmap, .vunmap = drm_gem_shmem_object_vunmap, .mmap = drm_gem_shmem_object_mmap, + .status = panfrost_gem_status, .vm_ops = &drm_gem_shmem_vm_ops, }; -- 2.42.0
[PATCH v3 2/8] drm/panfrost: Enable cycle counter register upon job submission
In a future development, we will want to keep track of the number of GPU cycles spent on a given job. That means we should enable it only when the GPU has work to do, and switch it off whenever it is idle to avoid power waste. To avoid race conditions during enablement/disabling, a reference counting mechanism was introduced, and a job flag that tells us whether a given job increased the refcount. This is necessary, because a future development will let user space toggle cycle counting through a debugfs file, and a given job might have been in flight by the time cycle counting was disabled. Toggling of GPU cycle counting has to be done through a module parameter. Signed-off-by: Adrián Larumbe --- drivers/gpu/drm/panfrost/panfrost_device.c | 5 +++ drivers/gpu/drm/panfrost/panfrost_device.h | 6 +++ drivers/gpu/drm/panfrost/panfrost_gpu.c| 43 ++ drivers/gpu/drm/panfrost/panfrost_gpu.h| 6 +++ drivers/gpu/drm/panfrost/panfrost_job.c| 10 + drivers/gpu/drm/panfrost/panfrost_job.h| 1 + 6 files changed, 71 insertions(+) diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c index fa1a086a862b..1ea2ac3804f0 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.c +++ b/drivers/gpu/drm/panfrost/panfrost_device.c @@ -18,6 +18,9 @@ #include "panfrost_mmu.h" #include "panfrost_perfcnt.h" +static bool profile; +module_param(profile, bool, 0600); + static int panfrost_reset_init(struct panfrost_device *pfdev) { pfdev->rstc = devm_reset_control_array_get_optional_exclusive(pfdev->dev); @@ -207,6 +210,8 @@ int panfrost_device_init(struct panfrost_device *pfdev) spin_lock_init(&pfdev->as_lock); + atomic_set(&pfdev->profile_mode, profile); + err = panfrost_clk_init(pfdev); if (err) { dev_err(pfdev->dev, "clk init failed %d\n", err); diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h index b0126b9fbadc..5c09c9f3ae08 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.h +++ b/drivers/gpu/drm/panfrost/panfrost_device.h @@ -107,6 +107,7 @@ struct panfrost_device { struct list_head scheduled_jobs; struct panfrost_perfcnt *perfcnt; + atomic_t profile_mode; struct mutex sched_lock; @@ -121,6 +122,11 @@ struct panfrost_device { struct shrinker shrinker; struct panfrost_devfreq pfdevfreq; + + struct { + atomic_t use_count; + spinlock_t lock; + } cycle_counter; }; struct panfrost_mmu { diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index 2faa344d89ee..fddbc72bf093 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -73,6 +73,8 @@ int panfrost_gpu_soft_reset(struct panfrost_device *pfdev) gpu_write(pfdev, GPU_INT_CLEAR, GPU_IRQ_MASK_ALL); gpu_write(pfdev, GPU_INT_MASK, GPU_IRQ_MASK_ALL); + atomic_set(&pfdev->cycle_counter.use_count, 0); + return 0; } @@ -321,6 +323,46 @@ static void panfrost_gpu_init_features(struct panfrost_device *pfdev) pfdev->features.shader_present, pfdev->features.l2_present); } +void panfrost_cycle_counter_get(struct panfrost_device *pfdev) +{ + if (atomic_inc_not_zero(&pfdev->cycle_counter.use_count)) + return; + + spin_lock(&pfdev->cycle_counter.lock); + if (atomic_inc_return(&pfdev->cycle_counter.use_count) == 1) + gpu_write(pfdev, GPU_CMD, GPU_CMD_CYCLE_COUNT_START); + spin_unlock(&pfdev->cycle_counter.lock); +} + +void panfrost_cycle_counter_put(struct panfrost_device *pfdev) +{ + if (atomic_add_unless(&pfdev->cycle_counter.use_count, -1, 1)) + return; + + spin_lock(&pfdev->cycle_counter.lock); + if (atomic_dec_return(&pfdev->cycle_counter.use_count) == 0) + gpu_write(pfdev, GPU_CMD, GPU_CMD_CYCLE_COUNT_STOP); + spin_unlock(&pfdev->cycle_counter.lock); +} + +void panfrost_cycle_counter_stop(struct panfrost_device *pfdev) +{ + atomic_set(&pfdev->profile_mode, 0); + gpu_write(pfdev, GPU_CMD, GPU_CMD_CYCLE_COUNT_STOP); +} + +unsigned long long panfrost_cycle_counter_read(struct panfrost_device *pfdev) +{ + u32 hi, lo; + + do { + hi = gpu_read(pfdev, GPU_CYCLE_COUNT_HI); + lo = gpu_read(pfdev, GPU_CYCLE_COUNT_LO); + } while (hi != gpu_read(pfdev, GPU_CYCLE_COUNT_HI)); + + return ((u64)hi << 32) | lo; +} + void panfrost_gpu_power_on(struct panfrost_device *pfdev) { int ret; @@ -367,6 +409,7 @@ void panfrost_gpu_power_on(struct panfrost_device *pfdev) void panfrost_gpu_power_off(struct panfrost_device *pfdev) { + panfrost_cycle_counter_stop(pfdev); gpu_write(pfdev, TILER_PWROFF_LO, 0); gpu_write(pfdev, SHADER_PWROFF_LO, 0); gpu_write(pfdev, L
[PATCH v3 4/8] drm/panfrost: Add fdinfo support GPU load metrics
The drm-stats fdinfo tags made available to user space are drm-engine, drm-cycles, drm-max-freq and drm-curfreq, one per job slot. This deviates from standard practice in other DRM drivers, where a single set of key:value pairs is provided for the whole render engine. However, Panfrost has separate queues for fragment and vertex/tiler jobs, so a decision was made to calculate bus cycles and workload times separately. Maximum operating frequency is calculated at devfreq initialisation time. Current frequency is made available to user space because nvtop uses it when performing engine usage calculations. It is important to bear in mind that both GPU cycle and kernel time numbers provided are at best rough estimations, and always reported in excess from the actual figure because of two reasons: - Excess time because of the delay between the end of a job processing, the subsequent job IRQ and the actual time of the sample. - Time spent in the engine queue waiting for the GPU to pick up the next job. Signed-off-by: Adrián Larumbe --- drivers/gpu/drm/panfrost/panfrost_devfreq.c | 8 +++ drivers/gpu/drm/panfrost/panfrost_devfreq.h | 3 ++ drivers/gpu/drm/panfrost/panfrost_device.h | 13 + drivers/gpu/drm/panfrost/panfrost_drv.c | 59 - drivers/gpu/drm/panfrost/panfrost_job.c | 27 ++ drivers/gpu/drm/panfrost/panfrost_job.h | 4 ++ 6 files changed, 113 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c index 58dfb15a8757..28caffc689e2 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c @@ -58,6 +58,7 @@ static int panfrost_devfreq_get_dev_status(struct device *dev, spin_lock_irqsave(&pfdevfreq->lock, irqflags); panfrost_devfreq_update_utilization(pfdevfreq); + pfdevfreq->current_frequency = status->current_frequency; status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time, pfdevfreq->idle_time)); @@ -117,6 +118,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) struct devfreq *devfreq; struct thermal_cooling_device *cooling; struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + unsigned long freq = ULONG_MAX; if (pfdev->comp->num_supplies > 1) { /* @@ -172,6 +174,12 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) return ret; } + /* Find the fastest defined rate */ + opp = dev_pm_opp_find_freq_floor(dev, &freq); + if (IS_ERR(opp)) + return PTR_ERR(opp); + pfdevfreq->fast_rate = freq; + dev_pm_opp_put(opp); /* diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h index 1514c1f9d91c..48dbe185f206 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h @@ -19,6 +19,9 @@ struct panfrost_devfreq { struct devfreq_simple_ondemand_data gov_data; bool opp_of_table_added; + unsigned long current_frequency; + unsigned long fast_rate; + ktime_t busy_time; ktime_t idle_time; ktime_t time_last_update; diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h index 5c09c9f3ae08..7ad3973b1a3a 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.h +++ b/drivers/gpu/drm/panfrost/panfrost_device.h @@ -24,6 +24,7 @@ struct panfrost_perfcnt; #define NUM_JOB_SLOTS 3 #define MAX_PM_DOMAINS 5 +#define MAX_SLOT_NAME_LEN 25 struct panfrost_features { u16 id; @@ -141,12 +142,24 @@ struct panfrost_mmu { struct list_head list; }; +struct drm_info_gpu { + unsigned long maxfreq; + + struct engine_info { + unsigned long long elapsed_ns; + unsigned long long cycles; + char name[MAX_SLOT_NAME_LEN]; + } engines[NUM_JOB_SLOTS]; +}; + struct panfrost_file_priv { struct panfrost_device *pfdev; struct drm_sched_entity sched_entity[NUM_JOB_SLOTS]; struct panfrost_mmu *mmu; + + struct drm_info_gpu fdinfo; }; static inline struct panfrost_device *to_panfrost_device(struct drm_device *ddev) diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index 2dfd9f79a31b..94787f4aee27 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -268,6 +268,7 @@ static int panfrost_ioctl_submit(struct drm_device *dev, void *data, job->requirements = args->requirements; job->flush_id = panfrost_gpu_get_latest_flush_id(pfdev); job->mmu = file_priv->mmu; + job->priv = file_priv; slot = panfrost_job_get_slot(job); @@ -484,6 +485,14 @@ panfrost_open(struct drm_device *dev, struc
[PATCH v3 0/8] Add fdinfo support to Panfrost
This patch series adds fdinfo support to the Panfrost DRM driver. It will display a series of key:value pairs under /proc/pid/fdinfo/fd for render processes that open the Panfrost DRM file. The pairs contain basic drm gpu engine and memory region information that can either be cat by a privileged user or accessed with IGT's gputop utility. Changelog: v1: https://lore.kernel.org/lkml/bb52b872-e41b-3894-285e-b52cfc849...@arm.com/T/ v2: https://lore.kernel.org/lkml/20230901084457.5bc1a...@collabora.com/T/ - Changed the way gpu cycles and engine time are calculated, using GPU registers and taking into account potential resets. - Split render engine values into fragment and vertex/tiler ones. - Added more fine-grained calculation of RSS size for BO's. - Implemente selection of drm-memory region size units - Removed locking of shrinker's mutex in GEM obj status function v3: - Changed fdinfo engine names to something more descriptive - Mentioned GPU cycle counts aren't an exact measure - Handled the case when job->priv might be NULL - Handled 32 bit overflow of cycle register - Kept fdinfo drm memory stats size unit display within 10k times the previous multiplier for more accurate BO size numbers - Removed special handling of Prime imported BO RSS - Use rss_size only for heap objects - Use bo->base.madv instead of specific purgeable flag - Fixed kernel test robot warnings Adrián Larumbe (8): drm/panfrost: Add cycle count GPU register definitions drm/panfrost: Enable cycle counter register upon job submission drm/panfrost: Enable debugfs toggling of cycle counter register drm/panfrost: Add fdinfo support GPU load metrics drm/panfrost: Add fdinfo support for memory stats drm/drm_file: Add DRM obj's RSS reporting function for fdinfo drm/panfrost: Implement generic DRM object RSS reporting function drm/drm-file: Show finer-grained BO sizes in drm_show_memory_stats drivers/gpu/drm/drm_file.c | 7 ++- drivers/gpu/drm/panfrost/Makefile | 2 + drivers/gpu/drm/panfrost/panfrost_debugfs.c | 51 drivers/gpu/drm/panfrost/panfrost_debugfs.h | 13 + drivers/gpu/drm/panfrost/panfrost_devfreq.c | 8 +++ drivers/gpu/drm/panfrost/panfrost_devfreq.h | 3 + drivers/gpu/drm/panfrost/panfrost_device.c | 5 ++ drivers/gpu/drm/panfrost/panfrost_device.h | 19 ++ drivers/gpu/drm/panfrost/panfrost_drv.c | 65 - drivers/gpu/drm/panfrost/panfrost_gem.c | 28 + drivers/gpu/drm/panfrost/panfrost_gem.h | 5 ++ drivers/gpu/drm/panfrost/panfrost_gpu.c | 43 ++ drivers/gpu/drm/panfrost/panfrost_gpu.h | 6 ++ drivers/gpu/drm/panfrost/panfrost_job.c | 37 drivers/gpu/drm/panfrost/panfrost_job.h | 5 ++ drivers/gpu/drm/panfrost/panfrost_mmu.c | 12 ++-- drivers/gpu/drm/panfrost/panfrost_regs.h| 5 ++ include/drm/drm_gem.h | 9 +++ 18 files changed, 316 insertions(+), 7 deletions(-) create mode 100644 drivers/gpu/drm/panfrost/panfrost_debugfs.c create mode 100644 drivers/gpu/drm/panfrost/panfrost_debugfs.h base-commit: f45acf7acf75921c0409d452f0165f51a19a74fd -- 2.42.0
[PATCH v3 1/8] drm/panfrost: Add cycle count GPU register definitions
These GPU registers will be used when programming the cycle counter, which we need for providing accurate fdinfo drm-cycles values to user space. Signed-off-by: Adrián Larumbe Reviewed-by: Boris Brezillon Reviewed-by: Steven Price --- drivers/gpu/drm/panfrost/panfrost_regs.h | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h index 919f44ac853d..55ec807550b3 100644 --- a/drivers/gpu/drm/panfrost/panfrost_regs.h +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h @@ -46,6 +46,8 @@ #define GPU_CMD_SOFT_RESET 0x01 #define GPU_CMD_PERFCNT_CLEAR0x03 #define GPU_CMD_PERFCNT_SAMPLE 0x04 +#define GPU_CMD_CYCLE_COUNT_START0x05 +#define GPU_CMD_CYCLE_COUNT_STOP 0x06 #define GPU_CMD_CLEAN_CACHES 0x07 #define GPU_CMD_CLEAN_INV_CACHES 0x08 #define GPU_STATUS 0x34 @@ -73,6 +75,9 @@ #define GPU_PRFCNT_TILER_EN0x74 #define GPU_PRFCNT_MMU_L2_EN 0x7c +#define GPU_CYCLE_COUNT_LO 0x90 +#define GPU_CYCLE_COUNT_HI 0x94 + #define GPU_THREAD_MAX_THREADS 0x0A0 /* (RO) Maximum number of threads per core */ #define GPU_THREAD_MAX_WORKGROUP_SIZE 0x0A4 /* (RO) Maximum workgroup size */ #define GPU_THREAD_MAX_BARRIER_SIZE0x0A8 /* (RO) Maximum threads waiting at a barrier */ -- 2.42.0
[drm-misc:drm-misc-next 3/3] drivers/gpu/drm/tegra/dsi.c:259:43: error: passing argument 3 of 'drm_debugfs_remove_files' from incompatible pointer type
tree: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next head: f45acf7acf75921c0409d452f0165f51a19a74fd commit: 8e455145d8f163aefa6b9cc29478e0a9f82276e6 [3/3] drm/debugfs: rework drm_debugfs_create_files implementation v2 config: openrisc-randconfig-r015-20230906 (https://download.01.org/0day-ci/archive/20230906/202309060212.6xvtsnab-...@intel.com/config) compiler: or1k-linux-gcc (GCC) 13.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230906/202309060212.6xvtsnab-...@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot | Closes: https://lore.kernel.org/oe-kbuild-all/202309060212.6xvtsnab-...@intel.com/ All errors (new ones prefixed by >>): drivers/gpu/drm/tegra/dsi.c: In function 'tegra_dsi_early_unregister': >> drivers/gpu/drm/tegra/dsi.c:259:43: error: passing argument 3 of >> 'drm_debugfs_remove_files' from incompatible pointer type >> [-Werror=incompatible-pointer-types] 259 | connector->debugfs_entry, | ~^~~ | | | struct dentry * In file included from drivers/gpu/drm/tegra/dsi.c:21: include/drm/drm_debugfs.h:163:73: note: expected 'struct drm_minor *' but argument is of type 'struct dentry *' 163 |int count, struct drm_minor *minor) | ~~^ >> drivers/gpu/drm/tegra/dsi.c:258:9: error: too many arguments to function >> 'drm_debugfs_remove_files' 258 | drm_debugfs_remove_files(dsi->debugfs_files, count, | ^~~~ include/drm/drm_debugfs.h:162:19: note: declared here 162 | static inline int drm_debugfs_remove_files(const struct drm_info_list *files, | ^~~~ cc1: some warnings being treated as errors -- drivers/gpu/drm/tegra/dc.c: In function 'tegra_dc_early_unregister': >> drivers/gpu/drm/tegra/dc.c:1757:60: error: passing argument 3 of >> 'drm_debugfs_remove_files' from incompatible pointer type >> [-Werror=incompatible-pointer-types] 1757 | drm_debugfs_remove_files(dc->debugfs_files, count, root, minor); |^~~~ || |struct dentry * In file included from drivers/gpu/drm/tegra/dc.c:27: include/drm/drm_debugfs.h:163:73: note: expected 'struct drm_minor *' but argument is of type 'struct dentry *' 163 |int count, struct drm_minor *minor) | ~~^ >> drivers/gpu/drm/tegra/dc.c:1757:9: error: too many arguments to function >> 'drm_debugfs_remove_files' 1757 | drm_debugfs_remove_files(dc->debugfs_files, count, root, minor); | ^~~~ include/drm/drm_debugfs.h:162:19: note: declared here 162 | static inline int drm_debugfs_remove_files(const struct drm_info_list *files, | ^~~~ cc1: some warnings being treated as errors -- drivers/gpu/drm/tegra/hdmi.c: In function 'tegra_hdmi_early_unregister': >> drivers/gpu/drm/tegra/hdmi.c:1120:43: error: passing argument 3 of >> 'drm_debugfs_remove_files' from incompatible pointer type >> [-Werror=incompatible-pointer-types] 1120 | connector->debugfs_entry, minor); | ~^~~ | | | struct dentry * In file included from drivers/gpu/drm/tegra/hdmi.c:26: include/drm/drm_debugfs.h:163:73: note: expected 'struct drm_minor *' but argument is of type 'struct dentry *' 163 |int count, struct drm_minor *minor) | ~~^ >> drivers/gpu/drm/tegra/hdmi.c:1119:9: error: too many arguments to function >> 'drm_debugfs_remove_files' 1119 | drm_debugfs_remove_files(hdmi->debugfs_files, count, | ^~~~ include/drm/drm_debugfs.h:162:19: note: declared here 162 | static inline int drm_debugfs_remove_files(const struct drm_info_list *files, | ^~~~ cc1: some warnings being treated as errors -- drivers/gpu/drm/tegra/sor.c: In function 'tegra_sor_early_unregister': >> drivers
[PATCH 6/6] drm/msm/dpu: Add MSM8996 support
From: Konrad Dybcio Add support for MSM8996, which - fun fact - was the SoC that this driver (or rather SDE, its downstream origin) was meant for and first tested on. It has some hardware that differs from the modern SoCs, so not a lot of current structs could have been reused. It's also seemingly the only SoC supported by DPU that uses RGB pipes. Note, by default this platform is still handled by the MDP5 driver unless the `msm.prefer_mdp5=false' parameter is provided. Signed-off-by: Konrad Dybcio Signed-off-by: Konrad Dybcio [DB: rebased on top of sblk changes, add dpu_rgb_sblk] Signed-off-by: Dmitry Baryshkov --- .../msm/disp/dpu1/catalog/dpu_1_7_msm8996.h | 353 ++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 95 + .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h| 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 1 + drivers/gpu/drm/msm/msm_drv.c | 1 + 5 files changed, 451 insertions(+) create mode 100644 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h new file mode 100644 index ..43e952fcce9b --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h @@ -0,0 +1,353 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023, Linaro Limited + * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved. + */ + +#ifndef _DPU_1_7_MSM8996_H +#define _DPU_1_7_MSM8996_H + +static const struct dpu_caps msm8996_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0x7, + .has_src_split = true, + .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .max_hdeci_exp = MAX_HORZ_DECIMATION, + .max_vdeci_exp = MAX_VERT_DECIMATION, +}; + +static const struct dpu_mdp_cfg msm8996_mdp[] = { + { + .name = "top_0", + .base = 0x0, .len = 0x454, + .features = BIT(DPU_MDP_VSYNC_SEL), + .clk_ctrls = { + [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, + [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, + [DPU_CLK_CTRL_VIG2] = { .reg_off = 0x2bc, .bit_off = 0 }, + [DPU_CLK_CTRL_VIG3] = { .reg_off = 0x2c4, .bit_off = 0 }, + [DPU_CLK_CTRL_RGB0] = { .reg_off = 0x2ac, .bit_off = 4 }, + [DPU_CLK_CTRL_RGB1] = { .reg_off = 0x2b4, .bit_off = 4 }, + [DPU_CLK_CTRL_RGB2] = { .reg_off = 0x2bc, .bit_off = 4 }, + [DPU_CLK_CTRL_RGB3] = { .reg_off = 0x2c4, .bit_off = 4 }, + [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, + [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, + [DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 }, + [DPU_CLK_CTRL_CURSOR1] = { .reg_off = 0x3b0, .bit_off = 16 }, + }, + }, +}; + +static const struct dpu_ctl_cfg msm8996_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x1000, .len = 0x64, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, { + .name = "ctl_1", .id = CTL_1, + .base = 0x1200, .len = 0x64, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, { + .name = "ctl_2", .id = CTL_2, + .base = 0x1400, .len = 0x64, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, { + .name = "ctl_3", .id = CTL_3, + .base = 0x1600, .len = 0x64, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, { + .name = "ctl_4", .id = CTL_4, + .base = 0x1800, .len = 0x64, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, +}; + +static const struct dpu_sspp_cfg msm8996_sspp[] = { + { + .name = "sspp_0", .id = SSPP_VIG0, + .base = 0x4000, .len = 0x150, + .features = VIG_MSM8996_MASK, + .sblk = &dpu_vig_sblk_qseed2, + .xin_id = 0, + .type = SSPP_TYPE_VIG, + .clk_ctrl = DPU_CLK_CTRL_VIG0, + }, { + .name = "sspp_1", .id = SSPP_VIG1, + .base = 0x6000, .len = 0x150, + .features = VIG_MSM8996_MASK, + .sblk = &dpu_vig_sblk_qseed2, + .xin_id = 4, + .type = SSPP_TYPE_VIG, + .clk_ctrl = DPU_CLK_CTRL_VIG1, + }, { + .name = "sspp_2", .id = SSPP_VIG2, + .base = 0x8000, .len = 0x150, +
[PATCH 1/6] drm/msm/mdss: fix highest-bank-bit for msm8998
According to the vendor DT files, msm8998 has highest-bank-bit equal to 2. Update the data accordingly. Fixes: 6f410b246209 ("drm/msm/mdss: populate missing data") Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/msm_mdss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index 2e87dd6cb17b..348c66b14683 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -511,7 +511,7 @@ static int mdss_remove(struct platform_device *pdev) static const struct msm_mdss_data msm8998_data = { .ubwc_enc_version = UBWC_1_0, .ubwc_dec_version = UBWC_1_0, - .highest_bank_bit = 1, + .highest_bank_bit = 2, }; static const struct msm_mdss_data qcm2290_data = { -- 2.39.2
[PATCH 5/6] drm/msm/dpu: add support for SDM660 and SDM630 platforms
Bring in hardware support for the SDM660 and SDM630 platforms, which belong to the same DPU generation as MSM8998. Note, by default these platforms are still handled by the MDP5 driver unless the `msm.prefer_mdp5=false' parameter is provided. Co-developed-by: Konrad Dybcio Signed-off-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov --- .../msm/disp/dpu1/catalog/dpu_3_2_sdm660.h| 291 ++ .../msm/disp/dpu1/catalog/dpu_3_3_sdm630.h| 225 ++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 2 + .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h| 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 + drivers/gpu/drm/msm/msm_drv.c | 2 + 6 files changed, 524 insertions(+) create mode 100644 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h new file mode 100644 index ..bd38fb753849 --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2023. Linaro Inc. All rights reserved. + */ + +#ifndef _DPU_3_2_SDM660_H +#define _DPU_3_2_SDM660_H + +static const struct dpu_caps sdm660_dpu_caps = { + .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .max_mixer_blendstages = 0x7, + .has_src_split = true, + .has_dim_layer = true, + .has_idle_pc = true, + .has_3d_merge = true, + .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, + .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE, + .max_hdeci_exp = MAX_HORZ_DECIMATION, + .max_vdeci_exp = MAX_VERT_DECIMATION, +}; + +static const struct dpu_mdp_cfg sdm660_mdp = { + .name = "top_0", + .base = 0x0, .len = 0x458, + .features = BIT(DPU_MDP_VSYNC_SEL), + .clk_ctrls = { + [DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0 }, + [DPU_CLK_CTRL_VIG1] = { .reg_off = 0x2b4, .bit_off = 0 }, + [DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8 }, + [DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8 }, + [DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2c4, .bit_off = 8 }, + [DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x3a8, .bit_off = 16 }, + }, +}; + +static const struct dpu_ctl_cfg sdm660_ctl[] = { + { + .name = "ctl_0", .id = CTL_0, + .base = 0x1000, .len = 0x94, + .features = BIT(DPU_CTL_SPLIT_DISPLAY), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9), + }, { + .name = "ctl_1", .id = CTL_1, + .base = 0x1200, .len = 0x94, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10), + }, { + .name = "ctl_2", .id = CTL_2, + .base = 0x1400, .len = 0x94, + .features = BIT(DPU_CTL_SPLIT_DISPLAY), + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11), + }, { + .name = "ctl_3", .id = CTL_3, + .base = 0x1600, .len = 0x94, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12), + }, { + .name = "ctl_4", .id = CTL_4, + .base = 0x1800, .len = 0x94, + .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13), + }, +}; + +static const struct dpu_sspp_cfg sdm660_sspp[] = { + { + .name = "sspp_0", .id = SSPP_VIG0, + .base = 0x4000, .len = 0x1ac, + .features = VIG_MSM8998_MASK, + .sblk = &dpu_vig_sblk_1_2, + .xin_id = 0, + .type = SSPP_TYPE_VIG, + .clk_ctrl = DPU_CLK_CTRL_VIG0, + }, { + .name = "sspp_1", .id = SSPP_VIG1, + .base = 0x6000, .len = 0x1ac, + .features = VIG_MSM8998_MASK, + .sblk = &dpu_vig_sblk_1_2, + .xin_id = 4, + .type = SSPP_TYPE_VIG, + .clk_ctrl = DPU_CLK_CTRL_VIG1, + }, { + .name = "sspp_8", .id = SSPP_DMA0, + .base = 0x24000, .len = 0x1ac, + .features = DMA_MSM8998_MASK, + .sblk = &dpu_dma_sblk, + .xin_id = 1, + .type = SSPP_TYPE_DMA, + .clk_ctrl = DPU_CLK_CTRL_DMA0, + }, { + .name = "sspp_9", .id = SSPP_DMA1, + .base = 0x26000, .len = 0x1ac, + .features = DMA_MSM8998_MASK, + .sblk = &dpu_dma_sblk, + .xin_id = 5, + .type = SSPP_TYPE_DMA, + .clk_ctrl = DPU_CLK_CTRL_DMA1, + }, { + .name = "sspp_10", .id = SSPP_DMA2, + .base = 0x28000, .len = 0x1ac, + .features = DMA_CURSOR_MSM8998_MASK, + .sblk = &dpu_dma_sblk, + .
[PATCH 4/6] drm/msm: add a kernel param to select between MDP5 and DPU drivers
For some of the platforms (e.g. SDM660, SDM630, MSM8996, etc.) it is possible to support this platform via the DPU driver (e.g. to provide support for DP, multirect, etc). Add a modparam to be able to switch between these two drivers. All platforms supported by both drivers are by default handled by the MDP5 driver. To let them be handled by the DPU driver pass the `msm.prefer_mdp5=false` kernel param. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 3 +++ drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 3 +++ drivers/gpu/drm/msm/msm_drv.c| 31 drivers/gpu/drm/msm/msm_drv.h| 1 + 4 files changed, 38 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index a9ba67e24e11..f3cb8c2ada5e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1351,6 +1351,9 @@ static int dpu_kms_init(struct drm_device *ddev) static int dpu_dev_probe(struct platform_device *pdev) { + if (!msm_disp_drv_should_bind(&pdev->dev, true)) + return -ENODEV; + return msm_drv_probe(&pdev->dev, dpu_kms_init); } diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 92bf9d949d09..3828725683a7 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -935,6 +935,9 @@ static int mdp5_dev_probe(struct platform_device *pdev) DBG(""); + if (!msm_disp_drv_should_bind(&pdev->dev, false)) + return -ENODEV; + ret = mdp5_setup_interconnect(pdev); if (ret) return ret; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 4bd028fa7500..1b8ec55704ba 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1184,6 +1184,37 @@ static int add_components_mdp(struct device *master_dev, return 0; } +#if !IS_REACHABLE(CONFIG_DRM_MSM_MDP5) || !IS_REACHABLE(CONFIG_DRM_MSM_DPU) +bool msm_disp_drv_should_bind(struct device *dev, bool mdp5_driver) +{ + /* If just a single driver is enabled, use it no matter what */ + return true; +} +#else + +static bool prefer_mdp5 = true; +MODULE_PARM_DESC(prefer_mdp5, "Select whether MDP5 or DPU driver should be preferred"); +module_param(prefer_mdp5, bool, 0444); + +/* list all platforms supported by both mdp5 and dpu drivers */ +static const char *const msm_mdp5_dpu_migration[] = { + NULL, +}; + +bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver) +{ + /* If it is not an MDP5 device, do not try MDP5 driver */ + if (!of_device_is_compatible(dev->of_node, "qcom,mdp5")) + return dpu_driver; + + /* If it is not in the migration list, use MDP5 */ + if (!of_device_compatible_match(dev->of_node, msm_mdp5_dpu_migration)) + return !dpu_driver; + + return prefer_mdp5 ? !dpu_driver : dpu_driver; +} +#endif + /* * We don't know what's the best binding to link the gpu with the drm device. * Fow now, we just hunt for all the possible gpus that we support, and add them diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index fdcbb02fa396..05370a03fb44 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -571,5 +571,6 @@ int msm_drv_probe(struct device *dev, int (*kms_init)(struct drm_device *dev)); void msm_drv_shutdown(struct platform_device *pdev); +bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver); #endif /* __MSM_DRV_H__ */ -- 2.39.2
[PATCH 2/6] drm/msm/mdss: generate MDSS data for MDP5 platforms
Older (mdp5) platforms do not use per-SoC compatible strings. Instead they use a single compat entry 'qcom,mdss'. To facilitate migrating these platforms to the DPU driver provide a way to generate the MDSS / UBWC data at runtime, when the DPU driver asks for it. It is not possible to generate this data structure at the probe time, since some platforms might not have MDP_CLK enabled, which makes reading HW_REV register return 0. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/msm_mdss.c | 37 ++ 1 file changed, 37 insertions(+) diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index 348c66b14683..fb6ee93b5abc 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -222,6 +222,36 @@ static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss) } } +static struct msm_mdss_data *msm_mdss_generate_mdp5_mdss_data(struct msm_mdss *mdss) +{ + struct msm_mdss_data *data; + u32 hw_rev; + + data = devm_kzalloc(mdss->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return NULL; + + hw_rev = readl_relaxed(mdss->mmio + HW_REV) >> 16; + + if (hw_rev == 0x1007 || /* msm8996 */ + hw_rev == 0x100e || /* msm8937 */ + hw_rev == 0x1010 || /* msm8953 */ + hw_rev == 0x3000 || /* msm8998 */ + hw_rev == 0x3002 || /* sdm660 */ + hw_rev == 0x3003) { /* sdm630 */ + data->ubwc_dec_version = UBWC_1_0; + data->ubwc_enc_version = UBWC_1_0; + } + + if (hw_rev == 0x1007 || /* msm8996 */ + hw_rev == 0x3000) /* msm8998 */ + data->highest_bank_bit = 2; + else + data->highest_bank_bit = 1; + + return data; +} + const struct msm_mdss_data *msm_mdss_get_mdss_data(struct device *dev) { struct msm_mdss *mdss; @@ -231,6 +261,13 @@ const struct msm_mdss_data *msm_mdss_get_mdss_data(struct device *dev) mdss = dev_get_drvdata(dev); + /* +* We could not do it at the probe time, since hw revision register was +* not readable. Fill data structure now for the MDP5 platforms. +*/ + if (!mdss->mdss_data && mdss->is_mdp5) + mdss->mdss_data = msm_mdss_generate_mdp5_mdss_data(mdss); + return mdss->mdss_data; } -- 2.39.2
[PATCH 3/6] drm/msm/dpu: support binding to the mdp5 devices
Existing MDP5 devices have slightly different bindings. The main register region is called `mdp_phys' instead of `mdp'. Also vbif register regions are a part of the parent, MDSS device. Add support for handling this binding differences. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 88 - drivers/gpu/drm/msm/msm_drv.h | 3 + drivers/gpu/drm/msm/msm_io_utils.c | 18 + 3 files changed, 91 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index aa6ba2cf4b84..a9ba67e24e11 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1054,37 +1054,53 @@ unsigned long dpu_kms_get_clk_rate(struct dpu_kms *dpu_kms, char *clock_name) #defineDPU_PERF_DEFAULT_MAX_CORE_CLK_RATE 41250 -static int dpu_kms_hw_init(struct msm_kms *kms) +static int dpu_kms_mmap_mdp5(struct dpu_kms *dpu_kms) { - struct dpu_kms *dpu_kms; - struct drm_device *dev; - int i, rc = -EINVAL; - unsigned long max_core_clk_rate; - u32 core_rev; + struct platform_device *mdss_dev; + int rc; - if (!kms) { - DPU_ERROR("invalid kms\n"); + mdss_dev = to_platform_device(dpu_kms->pdev->dev.parent); + + dpu_kms->mmio = msm_ioremap(dpu_kms->pdev, "mdp_phys"); + if (IS_ERR(dpu_kms->mmio)) { + rc = PTR_ERR(dpu_kms->mmio); + DPU_ERROR("mdp register memory map failed: %d\n", rc); + dpu_kms->mmio = NULL; return rc; } + DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio); - dpu_kms = to_dpu_kms(kms); - dev = dpu_kms->dev; + dpu_kms->vbif[VBIF_RT] = msm_ioremap_mdss(mdss_dev, + dpu_kms->pdev, + "vbif_phys"); + if (IS_ERR(dpu_kms->vbif[VBIF_RT])) { + rc = PTR_ERR(dpu_kms->vbif[VBIF_RT]); + DPU_ERROR("vbif register memory map failed: %d\n", rc); + dpu_kms->vbif[VBIF_RT] = NULL; + return rc; + } - dev->mode_config.cursor_width = 512; - dev->mode_config.cursor_height = 512; + dpu_kms->vbif[VBIF_NRT] = msm_ioremap_mdss(mdss_dev, + dpu_kms->pdev, + "vbif_nrt_phys"); + if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) { + dpu_kms->vbif[VBIF_NRT] = NULL; + DPU_DEBUG("VBIF NRT is not defined"); + } - rc = dpu_kms_global_obj_init(dpu_kms); - if (rc) - return rc; + return 0; +} - atomic_set(&dpu_kms->bandwidth_ref, 0); +static int dpu_kms_mmap_dpu(struct dpu_kms *dpu_kms) +{ + int rc; dpu_kms->mmio = msm_ioremap(dpu_kms->pdev, "mdp"); if (IS_ERR(dpu_kms->mmio)) { rc = PTR_ERR(dpu_kms->mmio); DPU_ERROR("mdp register memory map failed: %d\n", rc); dpu_kms->mmio = NULL; - goto error; + return rc; } DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio); @@ -1093,14 +1109,50 @@ static int dpu_kms_hw_init(struct msm_kms *kms) rc = PTR_ERR(dpu_kms->vbif[VBIF_RT]); DPU_ERROR("vbif register memory map failed: %d\n", rc); dpu_kms->vbif[VBIF_RT] = NULL; - goto error; + return rc; } + dpu_kms->vbif[VBIF_NRT] = msm_ioremap_quiet(dpu_kms->pdev, "vbif_nrt"); if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) { dpu_kms->vbif[VBIF_NRT] = NULL; DPU_DEBUG("VBIF NRT is not defined"); } + return 0; +} + +static int dpu_kms_hw_init(struct msm_kms *kms) +{ + struct dpu_kms *dpu_kms; + struct drm_device *dev; + int i, rc = -EINVAL; + unsigned long max_core_clk_rate; + u32 core_rev; + + if (!kms) { + DPU_ERROR("invalid kms\n"); + return rc; + } + + dpu_kms = to_dpu_kms(kms); + dev = dpu_kms->dev; + + dev->mode_config.cursor_width = 512; + dev->mode_config.cursor_height = 512; + + rc = dpu_kms_global_obj_init(dpu_kms); + if (rc) + return rc; + + atomic_set(&dpu_kms->bandwidth_ref, 0); + + if (of_device_is_compatible(dpu_kms->pdev->dev.of_node, "qcom,mdp5")) + rc = dpu_kms_mmap_mdp5(dpu_kms); + else + rc = dpu_kms_mmap_dpu(dpu_kms); + if (rc) + return rc; + dpu_kms_parse_data_bus_icc_path(dpu_kms); rc = pm_runtime_resume_and_get(&dpu_kms->pdev->dev); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 02fd6c7d0bb7..fdcbb02fa396 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/driver
[PATCH 0/6] drm/msm: provide migration path from MDP5 to DPU driver
Over the last several years the DPU driver has been actively developed, while the MDP5 is mostly in the maintenance mode. This results in some features being available only in the DPU driver. For example, bandwidth scaling, writeback support, properly supported bonded DSI aka dual DSI support. All the pre-SDM845 platforms were originally supported by the MDP5 driver only. However it is possible and easy to support some of the older SoCs in the DPU driver. For example in the v5.18 it got support for MSM8998. This can not be considered as a proper migration, since there msm8998.dtsi didn't describe the display hardware beforehand. Instead new bindings were added, making MSM8998 just another display hardware to be supported by the DPU driver. This series provides a way to gradually migrate support for several existing and well-supported SoCs from the MDP5 to the DPU driver without changing the DT. From the user experience point of view this is facilitated by the `msm.prefer_mdp5' kernel param. If the parameter is set to `true' (current default), all `shared' platforms will be handled by the MDP5 driver. If the switch is flipped to `false' (or if the MDP5 driver is disabled), these platforms will be handled by the DPU driver. Handling this by the modparam (rather than solely by kernel config) allows one to easly switch between the drivers, simplifying testing. This series implements support for two DPU 3.n platforms, SDM660 and SDM630, and a classical MDP5 1.7 (MSM8996) SoC. It should be easy to implement similar support for MSM8937 aka SDM430, MSM8917 aka SDM425, MSM8953 aka SDM625 / SDM632 / SDM450 and QCS405. They were left out beacuse of the lack of the hardware on my side. Then it should be relatively easy to also add support for MSM8992, MSM8994, MSM8956 and MSM8976. The major missing piece is the SharedMemoryPool, SMP. In theory after additional testing we can drop most of migration code and some parts of MDP5 driver. The proposed boundary is to move all platforms supporting cursor planes to the DPU driver, while limiting MDP5 to support only the older platforms which implement cursor as a part of the LM hardware block (MSM8974, APQ8084, MSM8x26, MSM8x16 and MSM8x39). Dependencies: [1] [1] https://patchwork.freedesktop.org/series/119804/ Dmitry Baryshkov (5): drm/msm/mdss: fix highest-bank-bit for msm8998 drm/msm/mdss: generate MDSS data for MDP5 platforms drm/msm/dpu: support binding to the mdp5 devices drm/msm: add a kernel param to select between MDP5 and DPU drivers drm/msm/dpu: add support for SDM660 and SDM630 platforms Konrad Dybcio (1): drm/msm/dpu: Add MSM8996 support .../msm/disp/dpu1/catalog/dpu_1_7_msm8996.h | 353 ++ .../msm/disp/dpu1/catalog/dpu_3_2_sdm660.h| 291 +++ .../msm/disp/dpu1/catalog/dpu_3_3_sdm630.h| 225 +++ .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 97 + .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h| 3 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 94 - drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 3 + drivers/gpu/drm/msm/msm_drv.c | 34 ++ drivers/gpu/drm/msm/msm_drv.h | 4 + drivers/gpu/drm/msm/msm_io_utils.c| 18 + drivers/gpu/drm/msm/msm_mdss.c| 39 +- 11 files changed, 1142 insertions(+), 19 deletions(-) create mode 100644 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_1_7_msm8996.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_2_sdm660.h create mode 100644 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_3_sdm630.h -- 2.39.2
Re: [PATCH -next 5/5] drm/amd/display: clean up one inconsistent indenting
Applied the series. Thanks! Alex On Thu, Aug 31, 2023 at 9:29 PM Yang Li wrote: > > drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn35/dcn35_fpu.c:260 > dcn35_update_bw_bounding_box_fpu() warn: inconsistent indenting > > Signed-off-by: Yang Li > --- > drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c > b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c > index 525ca0ed9ea9..46eb2d0592f3 100644 > --- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c > +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c > @@ -348,8 +348,8 @@ void dcn35_update_bw_bounding_box_fpu(struct dc *dc, > dc->debug.dram_clock_change_latency_ns / 1000.0; > } > /*temp till dml2 fully work without dml1*/ > - dml_init_instance(&dc->dml, &dcn3_5_soc, &dcn3_5_ip, > - DML_PROJECT_DCN31); > + dml_init_instance(&dc->dml, &dcn3_5_soc, &dcn3_5_ip, > + DML_PROJECT_DCN31); > } > > static bool is_dual_plane(enum surface_pixel_format format) > -- > 2.20.1.7.g153144c >
Re: [PATCH -next 4/4] drm/amd/display: Remove duplicated include in dcn35_clk_mgr.c
Applied. Thanks! On Thu, Aug 31, 2023 at 8:52 PM Yang Li wrote: > > ./drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c: > dcn35_clk_mgr.h is included more than once. > > Signed-off-by: Yang Li > --- > drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 1 - > 1 file changed, 1 deletion(-) > > diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c > b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c > index 3b2463c03694..9314e75195cd 100644 > --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c > +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c > @@ -46,7 +46,6 @@ > /* TODO: remove this include once we ported over remaining clk mgr > functions*/ > #include "dcn30/dcn30_clk_mgr.h" > #include "dcn31/dcn31_clk_mgr.h" > -#include "dcn35_clk_mgr.h" > > #include "dc_dmub_srv.h" > #include "link.h" > -- > 2.20.1.7.g153144c >
Re: [PATCH -next 3/4] drm/amd/display: Remove duplicated include in dcn35_hwseq.c
Applied. Thanks! On Thu, Aug 31, 2023 at 8:52 PM Yang Li wrote: > > ./drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.c: clk_mgr.h is included > more than once. > > Signed-off-by: Yang Li > --- > drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.c | 1 - > 1 file changed, 1 deletion(-) > > diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.c > b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.c > index cacb557a3014..666e2809d9dc 100644 > --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.c > +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.c > @@ -31,7 +31,6 @@ > #include "clk_mgr.h" > #include "reg_helper.h" > #include "abm.h" > -#include "clk_mgr.h" > #include "hubp.h" > #include "dchubbub.h" > #include "timing_generator.h" > -- > 2.20.1.7.g153144c >
Re: [PATCH -next 2/4] drm/amd/display: Remove duplicated include in dcn35_optc.c
Applied. Thanks! On Thu, Aug 31, 2023 at 8:52 PM Yang Li wrote: > > ./drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c: dcn35_optc.h is included > more than once. > > Signed-off-by: Yang Li > --- > drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c | 1 - > 1 file changed, 1 deletion(-) > > diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c > b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c > index d64be1a5071c..2bea1e475096 100644 > --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c > +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c > @@ -23,7 +23,6 @@ > */ > > #include "dcn35_optc.h" > -#include "dcn35_optc.h" > > #include "dcn30/dcn30_optc.h" > #include "dcn31/dcn31_optc.h" > -- > 2.20.1.7.g153144c >
Re: [PATCH -next 1/4] drm/amd/display: Remove duplicated include in dcn35_resource.c
Applied. Thanks! On Thu, Aug 31, 2023 at 8:52 PM Yang Li wrote: > > ./drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c: > dcn31/dcn31_dio_link_encoder.h is included more than once. > > Signed-off-by: Yang Li > --- > drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c | 1 - > 1 file changed, 1 deletion(-) > > diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c > b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c > index 0386b8fb270d..7f059fc2fc75 100644 > --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c > +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c > @@ -61,7 +61,6 @@ > #include "dcn32/dcn32_hpo_dp_link_encoder.h" > #include "link.h" > #include "dcn31/dcn31_apg.h" > -#include "dcn31/dcn31_dio_link_encoder.h" > #include "dcn32/dcn32_dio_link_encoder.h" > #include "dcn31/dcn31_vpg.h" > #include "dcn31/dcn31_afmt.h" > -- > 2.20.1.7.g153144c >
Re: [RFC,drm-misc-next v4 3/9] drm/radeon: Implement .be_primary() callback
Hi, On 2023/9/5 13:50, Christian König wrote: Am 04.09.23 um 21:57 schrieb Sui Jingfeng: From: Sui Jingfeng On a machine with multiple GPUs, a Linux user has no control over which one is primary at boot time. Question is why is that useful? Should we give users the ability to control that? I don't see an use case for this. On a specific machine with multiple GPUs mounted, only the primary graphics get POST-ed (initialized) by the firmware. Therefore the DRM drivers for the rest video cards have to work without the prerequisite setups done by firmware, This is called as POST. One of the use cases is to test if a specific DRM driver would works properly, under the circumstance of not being POST-ed, The ast drm driver is the first one which refused to work if not being POST-ed by the firmware. Before apply this series, I was unable make drm/ast as the primary video card easily. The problem is that on a multiple video card configuration, the monitor connected with my AST2400 card not light up. While confusing, a naive programmer may suspect the PRIME is not working. After applied this series and passing ast.modeset=10 on the kernel cmd line, I found that the monitor connected with my ast2400 video card still black, It doesn't display and It doesn't show image to me. While in the process of study drm/ast, I know that drm/ast driver has the POST code shipped, See the ast_post_gpu() function. Then, I was wondering why this function doesn't works. After a short-time (hasty) debugging, I found that the ast_post_gpu() function didn't get run. Because it have something to do with the ast->config_mode. Without thinking too much, I hardcoded the ast->config_mode as ast_use_p2a, the key point is to force the ast_post_gpu() function to run. ``` --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -132,6 +132,8 @@ static int ast_device_config_init(struct ast_device *ast) } } + ast->config_mode = ast_use_p2a; + switch (ast->config_mode) { case ast_use_defaults: drm_info(dev, "Using default configuration\n"); ``` Then, the monitor light up, it display the Ubuntu greeter to me. Therefore my patch is useful, at least for the Linux drm driver tester and developer. It allow programmers to test the specific part of a specific driver without changing a line of the source code and without the need of sudo authority. It improves the efficiency of the testing and patch verification. I know the PrimaryGPU option of Xorg conf, but this approach will remember the setup have been made, you need modify it with root authority each time you want to switch the primary. But on the process of rapid developing and/or testing for multiple video drivers, with only one computer hardware resource available. What we really want is a one-shot command, as provided by this series. So, this is the first use case. The second use case is that sometime the firmware is not reliable. While there are thousands of ARM64, PowerPC and Mips servers machine, Most of them don't have a good UEFI firmware support. I haven't test the drm/amdgpu and drm/radeon at my ARM64 server yet. Because this ARM64 server always use the platform(BMC) integrated display controller as primary. The UEFI firmware of it does not provide options menu to tune. So, for the first time, the discrete card because useless, despite more powerful. I will take time to carry on the testing, so I will be able to tell more in the future. Even on X86, when select the PEG as primary on the UEFI BIOS menu. There is no way to tell the bios which one of my three discrete video be the primary. Not to mention some old UEFI firmware, which doesn't provide a setting at all. While the benefit of my approach is the flexibility. Yes the i915, amdgpu and radeon are good quality, but there may have programmers want to try nouveau. The third use case is that VGAARB is also not reliable, It will select a wrong device as primary. Especially on Arm64, Loongarch and mips arch etc. And the X server will use this wrong device as primary and completely crash there. Either because of lacking a driver or the driver has a bug which can not bear the graphic environment up. VGAARB is firmware dependent. My patch provide a temporary method to rescue. The forth is probably the PRIME and reverse PRIME development and developing driver for new video cards.
Re: [PATCH] drm/amdgpu: clean up some inconsistent indenting
Applied and dropped the printk. Alex On Fri, Sep 1, 2023 at 3:40 AM Christian König wrote: > > Am 01.09.23 um 09:02 schrieb Jiapeng Chong: > > No functional modification involved. > > > > drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c:34 nbio_v7_11_get_rev_id() warn: > > inconsistent indenting. > > > We should probably not have a printk here in the first place. > > Christian. > > > > > Reported-by: Abaci Robot > > Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=6316 > > Signed-off-by: Jiapeng Chong > > --- > > drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c | 5 ++--- > > 1 file changed, 2 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c > > b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c > > index 7c08e5f95e97..76e21357dd4d 100644 > > --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c > > +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c > > @@ -31,10 +31,9 @@ > > static u32 nbio_v7_11_get_rev_id(struct amdgpu_device *adev) > > { > > u32 tmp; > > - printk("%s, getid\n",__func__); > > - > > - tmp = RREG32_SOC15(NBIO, 0, > > regRCC_STRAP1_RCC_DEV0_EPF0_STRAP0); > > > > + printk("%s, getid\n", __func__); > > + tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP1_RCC_DEV0_EPF0_STRAP0); > > tmp &= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0_MASK; > > tmp >>= > > RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0__SHIFT; > > >
[PATCH] drm/amd/display: Remove unwanted drm edid references
[WHY] edid_override and drm_edid_override_connector_update, according to drm documentation, should not be referred outside drm_edid. [HOW] Remove and replace them accordingly. Signed-off-by: Alex Hung --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 ++- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1bb1a394f55f..f6a255773242 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6372,15 +6372,12 @@ amdgpu_dm_connector_late_register(struct drm_connector *connector) static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct dc_link *dc_link = aconnector->dc_link; struct dc_sink *dc_em_sink = aconnector->dc_em_sink; struct edid *edid; - if (!connector->edid_override) - return; - - drm_edid_override_connector_update(&aconnector->base); - edid = aconnector->base.edid_blob_ptr->data; + edid = drm_get_edid(connector, &amdgpu_connector->ddc_bus->aux.ddc); aconnector->edid = edid; /* Update emulated (virtual) sink's EDID */ @@ -6421,22 +6418,6 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector) }; struct edid *edid; - if (!aconnector->base.edid_blob_ptr) { - /* if connector->edid_override valid, pass -* it to edid_override to edid_blob_ptr -*/ - - drm_edid_override_connector_update(&aconnector->base); - - if (!aconnector->base.edid_blob_ptr) { - DRM_ERROR("No EDID firmware found on connector: %s ,forcing to OFF!\n", - aconnector->base.name); - - aconnector->base.force = DRM_FORCE_OFF; - return; - } - } - edid = (struct edid *) aconnector->base.edid_blob_ptr->data; aconnector->edid = edid; -- 2.42.0
Re: [RFC PATCH 04/10] drm/panel_helper: Introduce drm_panel_helper
Hi, On Mon, Sep 4, 2023 at 8:33 AM Maxime Ripard wrote: > > > I don't understand the benefit of switching to refcounting, though. We > > don't ever expect the "prepare" or "enable" function to be called more > > than once and all we're guarding against is a double-unprepare and a > > double-enable. Switching this to refcounting would make the reader > > think that there was a legitimate case for things to be prepared or > > enabled twice. As far as I know, there isn't. > > Sure, eventually we'll want to remove it. > > I even said it as such here: > https://lore.kernel.org/dri-devel/wwzbd7dt5qyimshnd7sbgkf5gxk7tq5dxtrerz76uw5p6s7tzt@cbiezkfeuqqn/ > > However, we have a number of panels following various anti-patterns > where disable and unprepare would be called multiple times. A boolean > would just ignore the second, refcounting would warn over it, and that's > what we want. Can you provide a concrete example of a case where refcounting would give a better error? I'm still having a hard time understanding why you are saying that refcounting is better and something concrete would help me. Can you point at a driver you have in mind that follows an anti-pattern where refcount would be better? I'll try to be more concrete too and maybe you can point out where I'm confused. As far as I understand the only difference between the boolean and the refcount would be if someone _enabled_ or _prepared_ more than once, right? That would cause a refcount to increment to 2 but the boolean would stay at "true". I'm not aware of anyone calling enable or prepare more than once, but maybe you are? ...or maybe there's some other difference that I'm not aware of? Said another way... With a boolean and _not_ having more than one enable: 1. enable() => set "enabled" to true and enable panel. 2. disable() => set "enabled" to false and disable panel. 3. disable() => WARN, leave "enabled" as false. 4. disable() => WARN, leave "enabled" as false With a refcount and _not_ having more than one enable: 1. enable() => refcount becomes 1 and enable panel 2. disable() => refcount becomes 0 and disable panel 3. disable() => WARN, refcount stays 0 4. disable() => WARN, refcount stays 0 So with only one enable the behavior is the same. With a boolean and more than one enable: 1. enable() => set "enabled" to true and enable panel. 2. enable() => WARN, leave "enabled" as true 3. disable() => set "enabled" to false and disable panel. 4. disable() => WARN, leave "enabled" as false. 5. disable() => WARN, leave "enabled" as false With a refcount and more than one enable: 1. enable() => refcount becomes 1 and enable panel 2. enable() => refcount becomes 2 3. disable() => refcount becomes 1 4. disable() => refcount becomes 0 and disable panel 5. disable() => WARN, refcount stays 0 In the case that there is more than one enable, I think the "boolean" is better. Specifically: a) It doesn't change behavior from today. Perhaps you can show me a counterexample, but lacking that I'd assert that everyone today is expecting things to work like the "boolean" case. If we change to a refcount I think it could break someone. Even if nobody is relying on things working like the "boolean" case today, I would assert that I don't think anyone is expecting things to work like the "refcount" case. b) With a boolean we WARN at more appropriate times. Sure we could add a warning when the refcount becomes 2, but at that point why aren't we just using a boolean? c) The "boolean" case is already implemented today so no patches need to be sent for it. > > In any case, I don't think there's any need to switch this to > > refcounting as part of this effort. Someone could, in theory, do it as > > a separate patch series. > > I'm sorry, but I'll insist on getting a solution that will warn panels > that call drm_atomic_helper_shutdown or drm_panel_disable/unprepare by > hand. It doesn't have to be refcounting though if you have a better idea > in mind. As per above, I think this already happens with the boolean? Won't you see an error message like this: dev_warn(panel->dev, "Skipping unprepare of already unprepared panel\n"); ...from drm_panel_unprepare() > > > > The above solves the problem with panels wanting to power sequence > > > > themselves at remove() time, but not at shutdown() time. Thus we'd > > > > still have a dependency on having all drivers use > > > > drm_atomic_helper_shutdown() so that work becomes a dependency. > > > > > > Does it? I think it can be done in parallel? > > > > I don't think it can be in parallel. While it makes sense for panels > > to call drm_panel_remove() at remove time, it doesn't make sense for > > them to call it at shutdown time. That means that the trick of having > > the panel get powered off in drm_panel_remove() won't help for > > shutdown. For shutdown, which IMO is the more important case, we need > > to wait until all drm drivers call drm_atomic_helper_shutdown() > > properly. > > Right, my point was more
Re: [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
On Wed, 6 Sep 2023 00:21:09 +0800 suijingfeng wrote: > Hi, > > On 2023/9/5 22:52, Alex Williamson wrote: > > On Tue, 5 Sep 2023 03:57:15 +0800 > > Sui Jingfeng wrote: > > > >> From: Sui Jingfeng > >> > >> On a machine with multiple GPUs, a Linux user has no control over which > >> one is primary at boot time. This series tries to solve above mentioned > >> problem by introduced the ->be_primary() function stub. The specific > >> device drivers can provide an implementation to hook up with this stub by > >> calling the vga_client_register() function. > >> > >> Once the driver bound the device successfully, VGAARB will call back to > >> the device driver. To query if the device drivers want to be primary or > >> not. Device drivers can just pass NULL if have no such needs. > >> > >> Please note that: > >> > >> 1) The ARM64, Loongarch, Mips servers have a lot PCIe slot, and I would > >> like to mount at least three video cards. > >> > >> 2) Typically, those non-86 machines don't have a good UEFI firmware > >> support, which doesn't support select primary GPU as firmware stage. > >> Even on x86, there are old UEFI firmwares which already made undesired > >> decision for you. > >> > >> 3) This series is attempt to solve the remain problems at the driver level, > >> while another series[1] of me is target to solve the majority of the > >> problems at device level. > >> > >> Tested (limited) on x86 with four video card mounted, Intel UHD Graphics > >> 630 is the default boot VGA, successfully override by ast2400 with > >> ast.modeset=10 append at the kernel cmd line. > >> > >> $ lspci | grep VGA > >> > >> 00:02.0 VGA compatible controller: Intel Corporation CoffeeLake-S GT2 > >> [UHD Graphics 630] > > In all my previous experiments with VGA routing and IGD I found that > > IGD can't actually release VGA routing and Intel confirmed the hardware > > doesn't have the ability to do so. It will always be primary from a > > VGA routing perspective. Was this actually tested with non-UEFI? > > Yes, I have tested on my aspire e471 notebook (i5 5200U), > because that notebook using legacy firmware (also have UEFI, double firmware). > But this machine have difficult in install ubuntu under UEFI firmware in the > past. > So I keep it using the legacy firmware. > > It have two video card, IGD and nvidia video card(GFORCE 840M). > nvidia call its video card as 3D controller (pci->class = 0x030200) > > I have tested this patch and another patch mention at [1] together. > I can tell you that the firmware framebuffer of this notebook using vesafb, > not efifb. > And the framebuffer size (lfb.size) is very small. This is very strange, > but I don't have enough time to look in details. But still works. > > I'm using and tesing my patch whenever and wherever possible. So you're testing VGA routing using a non-VGA 3D controller through the VESA address space? How does that test anything about VGA routing? > > I suspect it might only work in UEFI mode where we probably don't > > actually have a dependency on VGA routing. This is essentially why > > vfio requires UEFI ROMs when assigning GPUs to VMs, VGA routing is too > > broken to use on Intel systems with IGD. Thanks, > > > What you tell me here is the side effect come with the VGA-compatible, > but I'm focus on the arbitration itself. I think there no need to keep > the VGA routing hardware features nowadays except that hardware vendor > want keep the backward compatibility and/or comply the PCI VGA compatible > spec. "VGA arbitration" is the mediation of VGA routing between devices, so I'm confused how you can be focused on the arbitration without the routing itself. Thanks, Alex
Re: [PATCH v5 09/17] drm/imagination: Implement power management
Hi Paul, On Wed, 2023-08-16 at 12:56 +0200, Paul Cercueil wrote: > Hi Sarah, > > Le mercredi 16 août 2023 à 09:25 +0100, Sarah Walker a écrit : > > Add power management to the driver, using runtime pm. The power off > > sequence depends on firmware commands which are not implemented in > > this > > patch. > > > > Changes since v4: > > - Suspend runtime PM before unplugging device on rmmod > > > > Changes since v3: > > - Don't power device when calling pvr_device_gpu_fini() > > - Documentation for pvr_dev->lost has been improved > > - pvr_power_init() renamed to pvr_watchdog_init() > > - Use drm_dev_{enter,exit} > > > > Changes since v2: > > - Use runtime PM > > - Implement watchdog > > > > Signed-off-by: Sarah Walker > > --- > > drivers/gpu/drm/imagination/Makefile | 1 + > > drivers/gpu/drm/imagination/pvr_device.c | 23 +- > > drivers/gpu/drm/imagination/pvr_device.h | 22 ++ > > drivers/gpu/drm/imagination/pvr_drv.c| 20 +- > > drivers/gpu/drm/imagination/pvr_power.c | 271 > > +++ > > drivers/gpu/drm/imagination/pvr_power.h | 39 > > 6 files changed, 373 insertions(+), 3 deletions(-) > > create mode 100644 drivers/gpu/drm/imagination/pvr_power.c > > create mode 100644 drivers/gpu/drm/imagination/pvr_power.h > > > > diff --git a/drivers/gpu/drm/imagination/Makefile > > b/drivers/gpu/drm/imagination/Makefile > > index 8fcabc1bea36..235e2d329e29 100644 > > --- a/drivers/gpu/drm/imagination/Makefile > > +++ b/drivers/gpu/drm/imagination/Makefile > > @@ -10,6 +10,7 @@ powervr-y := \ > > pvr_fw.o \ > > pvr_gem.o \ > > pvr_mmu.o \ > > + pvr_power.o \ > > pvr_vm.o > > > > obj-$(CONFIG_DRM_POWERVR) += powervr.o > > diff --git a/drivers/gpu/drm/imagination/pvr_device.c > > b/drivers/gpu/drm/imagination/pvr_device.c > > index ef8f7a2ff1a9..5dbd05f21238 100644 > > --- a/drivers/gpu/drm/imagination/pvr_device.c > > +++ b/drivers/gpu/drm/imagination/pvr_device.c > > @@ -5,6 +5,7 @@ > > #include "pvr_device_info.h" > > > > #include "pvr_fw.h" > > +#include "pvr_power.h" > > #include "pvr_rogue_cr_defs.h" > > #include "pvr_vm.h" > > > > @@ -357,6 +358,8 @@ pvr_device_gpu_fini(struct pvr_device *pvr_dev) > > int > > pvr_device_init(struct pvr_device *pvr_dev) > > { > > + struct drm_device *drm_dev = from_pvr_device(pvr_dev); > > + struct device *dev = drm_dev->dev; > > int err; > > > > /* Enable and initialize clocks required for the device to > > operate. */ > > @@ -364,13 +367,29 @@ pvr_device_init(struct pvr_device *pvr_dev) > > if (err) > > return err; > > > > + /* Explicitly power the GPU so we can access control > > registers before the FW is booted. */ > > + err = pm_runtime_resume_and_get(dev); > > + if (err) > > + return err; > > + > > /* Map the control registers into memory. */ > > err = pvr_device_reg_init(pvr_dev); > > if (err) > > - return err; > > + goto err_pm_runtime_put; > > > > /* Perform GPU-specific initialization steps. */ > > - return pvr_device_gpu_init(pvr_dev); > > + err = pvr_device_gpu_init(pvr_dev); > > + if (err) > > + goto err_pm_runtime_put; > > + > > + pm_runtime_put(dev); > > + > > + return 0; > > + > > +err_pm_runtime_put: > > + pm_runtime_put_sync_suspend(dev); > > + > > + return err; > > } > > > > /** > > diff --git a/drivers/gpu/drm/imagination/pvr_device.h > > b/drivers/gpu/drm/imagination/pvr_device.h > > index 990363e433d7..6d58ecfbc838 100644 > > --- a/drivers/gpu/drm/imagination/pvr_device.h > > +++ b/drivers/gpu/drm/imagination/pvr_device.h > > @@ -135,6 +135,28 @@ struct pvr_device { > > > > /** @fw_dev: Firmware related data. */ > > struct pvr_fw_device fw_dev; > > + > > + struct { > > + /** @work: Work item for watchdog callback. */ > > + struct delayed_work work; > > + > > + /** @old_kccb_cmds_executed: KCCB command execution > > count at last watchdog poll. */ > > + u32 old_kccb_cmds_executed; > > + > > + /** @kccb_stall_count: Number of watchdog polls KCCB > > has been stalled for. */ > > + u32 kccb_stall_count; > > + } watchdog; > > + > > + /** > > +* @lost: %true if the device has been lost. > > +* > > +* This variable is set if the device has become > > irretrievably unavailable, e.g. if the > > +* firmware processor has stopped responding and can not be > > revived via a hard reset. > > +*/ > > + bool lost; > > + > > + /** @sched_wq: Workqueue for schedulers. */ > > + struct workqueue_struct *sched_wq; > > }; > > > > /** > > diff --git a/drivers/gpu/drm/imagination/pvr_drv.c > > b/drivers/gpu/drm/imagination/pvr_drv.c > > index 0d51177b506c..0331dc549116 100644 > > --- a/drivers/
Re: [PATCH v5 02/17] dt-bindings: gpu: Add Imagination Technologies PowerVR GPU
Hi Linus, Thank you for your feedback (comments below). On Fri, 2023-08-18 at 11:36 +0200, Linus Walleij wrote: > Hi Sarah, > > thanks for your patch! > > Patches adding device tree bindings need to be CC:ed to > devicet...@vger.kernel.org > and the DT binding maintainers, I have added it for now. Thank you - it looks like something went wrong when the patch was sent. > > On Wed, Aug 16, 2023 at 10:26 AM Sarah Walker wrote: > > > Add the device tree binding documentation for the Series AXE GPU used in > > TI AM62 SoCs. > > > > Co-developed-by: Frank Binns > > Signed-off-by: Frank Binns > > Signed-off-by: Sarah Walker > (...) > > +properties: > > + compatible: > > +items: > > + - enum: > > + - ti,am62-gpu > > + - const: img,powervr-seriesaxe > > Should there not at least be a dash there? > > img,powervr-series-axe? > > It is spelled in two words in the commit message, > Series AXE not SeriesAXE? We've now changed the string to address your earlier feedback (see below). > > Moreover, if this pertains to the AXE-1-16 and AXE-2-16 it is kind of a > wildcard > and we usually don't do that, I would use the exact version instead, > such as: > const: img,powervr-axe-1-16 > any reason not to do this? The exact GPU model/revision is fully discoverable via a register. We saw the same is also true for Mali Bifrost, where they have a single string covering multiple models [1], so we took the same approach. We'll add a comment in v6 along the lines of the one in the Mali Bifrost bindings. > > I asked about the relationship between these strings and the product > designations earlier I think :/ Sorry about that, I honestly thought we'd addressed that bit of feedback by changing the compatibility string, but clearly we hadn't :( Thank you for catching this. We've now changed the string to "img,img-axe" to align with the marketing name, along with updating the commit message and various other places to refer to PowerVR and IMG GPUs (the DRM driver supporting both). Thanks Frank [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml?h=v6.5#n29
Re: [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
Hi, On 2023/9/5 22:52, Alex Williamson wrote: On Tue, 5 Sep 2023 03:57:15 +0800 Sui Jingfeng wrote: From: Sui Jingfeng On a machine with multiple GPUs, a Linux user has no control over which one is primary at boot time. This series tries to solve above mentioned problem by introduced the ->be_primary() function stub. The specific device drivers can provide an implementation to hook up with this stub by calling the vga_client_register() function. Once the driver bound the device successfully, VGAARB will call back to the device driver. To query if the device drivers want to be primary or not. Device drivers can just pass NULL if have no such needs. Please note that: 1) The ARM64, Loongarch, Mips servers have a lot PCIe slot, and I would like to mount at least three video cards. 2) Typically, those non-86 machines don't have a good UEFI firmware support, which doesn't support select primary GPU as firmware stage. Even on x86, there are old UEFI firmwares which already made undesired decision for you. 3) This series is attempt to solve the remain problems at the driver level, while another series[1] of me is target to solve the majority of the problems at device level. Tested (limited) on x86 with four video card mounted, Intel UHD Graphics 630 is the default boot VGA, successfully override by ast2400 with ast.modeset=10 append at the kernel cmd line. $ lspci | grep VGA 00:02.0 VGA compatible controller: Intel Corporation CoffeeLake-S GT2 [UHD Graphics 630] In all my previous experiments with VGA routing and IGD I found that IGD can't actually release VGA routing and Intel confirmed the hardware doesn't have the ability to do so. It will always be primary from a VGA routing perspective. Was this actually tested with non-UEFI? Yes, I have tested on my aspire e471 notebook (i5 5200U), because that notebook using legacy firmware (also have UEFI, double firmware). But this machine have difficult in install ubuntu under UEFI firmware in the past. So I keep it using the legacy firmware. It have two video card, IGD and nvidia video card(GFORCE 840M). nvidia call its video card as 3D controller (pci->class = 0x030200) I have tested this patch and another patch mention at [1] together. I can tell you that the firmware framebuffer of this notebook using vesafb, not efifb. And the framebuffer size (lfb.size) is very small. This is very strange, but I don't have enough time to look in details. But still works. I'm using and tesing my patch whenever and wherever possible. I suspect it might only work in UEFI mode where we probably don't actually have a dependency on VGA routing. This is essentially why vfio requires UEFI ROMs when assigning GPUs to VMs, VGA routing is too broken to use on Intel systems with IGD. Thanks, What you tell me here is the side effect come with the VGA-compatible, but I'm focus on the arbitration itself. I think there no need to keep the VGA routing hardware features nowadays except that hardware vendor want keep the backward compatibility and/or comply the PCI VGA compatible spec. Alex
Re: [Nouveau] [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
On 2023/9/5 18:49, Thomas Zimmermann wrote: Hi Am 04.09.23 um 21:57 schrieb Sui Jingfeng: From: Sui Jingfeng On a machine with multiple GPUs, a Linux user has no control over which one is primary at boot time. This series tries to solve above mentioned problem by introduced the ->be_primary() function stub. The specific device drivers can provide an implementation to hook up with this stub by calling the vga_client_register() function. Once the driver bound the device successfully, VGAARB will call back to the device driver. To query if the device drivers want to be primary or not. Device drivers can just pass NULL if have no such needs. Please note that: 1) The ARM64, Loongarch, Mips servers have a lot PCIe slot, and I would like to mount at least three video cards. 2) Typically, those non-86 machines don't have a good UEFI firmware support, which doesn't support select primary GPU as firmware stage. Even on x86, there are old UEFI firmwares which already made undesired decision for you. 3) This series is attempt to solve the remain problems at the driver level, while another series[1] of me is target to solve the majority of the problems at device level. Tested (limited) on x86 with four video card mounted, Intel UHD Graphics 630 is the default boot VGA, successfully override by ast2400 with ast.modeset=10 append at the kernel cmd line. FYI: per-driver modeset parameters are deprecated and not to be used. Please don't promote them. Well, please wait, I want to explain. drm/nouveau already promote it a little bit. Despite no code of conduct or specification guiding how the modules parameters should be. Noticed that there already have a lot of DRM drivers support the modeset parameters, for the modeset parameter, authors of various device driver try to make the usage not conflict with others. I believe that this is good thing for Linux users. It is probably the responsibility of the drm core maintainers to force various drm drivers to reach a minimal consensus. Probably it pains to do so and doesn't pay off. But reach a minimal consensus do benefit to Linux users. You can use modprobe.blacklist or initcall_blacklist on the kernel command line. There are some cases where the modprobe.blacklist doesn't works, I have come cross several time during the past. Because the device selected by the VGAARB is device-level thing, it is not the driver's problem. Sometimes when VGAARB has a bug, it will select a wrong device as primary. And the X server will use this wrong device as primary and completely crash there, due to lack a driver. Take my old S3 Graphics as an example: $ lspci | grep VGA 00:06.1 VGA compatible controller: Loongson Technology LLC DC (Display Controller) (rev 01) 03:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] 07:00.0 VGA compatible controller: S3 Graphics Ltd. Device 9070 (rev 01) 08:00.0 VGA compatible controller: S3 Graphics Ltd. Device 9070 (rev 01) Before apply this patch: [0.361748] pci :00:06.1: vgaarb: setting as boot VGA device [0.361753] pci :00:06.1: vgaarb: VGA device added: decodes=io+mem,owns=io+mem,locks=none [0.361765] pci :03:00.0: vgaarb: VGA device added: decodes=io+mem,owns=none,locks=none [0.361773] pci :07:00.0: vgaarb: VGA device added: decodes=io+mem,owns=none,locks=none [0.361779] pci :08:00.0: vgaarb: VGA device added: decodes=io+mem,owns=none,locks=none [0.361781] vgaarb: loaded [0.367838] pci :00:06.1: Overriding boot device as 1002:6778 [0.367841] pci :00:06.1: Overriding boot device as 5333:9070 [0.367843] pci :00:06.1: Overriding boot device as 5333:9070 For known reason, one of my system select the S3 Graphics as primary GPU. But this S3 Graphics not even have a decent drm upstream driver yet. Under such a case, I begin to believe that only the device who has a driver deserve the primary. Under such a condition, I want to reboot and enter the graphic environment with other working video cards. Either platform integrated and discrete GPU. This don't means I should compromise by un-mount the S3 graphics card from the motherboard, this also don't means that I should update my BIOS setting. As sometimes, the BIOS is more worse. With this series applied, all I need to do is to reboot the computer and pass a command line. By force override another video card (who has a decent driver support) as primary, I'm able to do the debugging under graphic environment. I would like to examine what's wrong with the vgaarb on a specific platform under X server graphic environment. Probably try compile a driver for this card and see it works, simply reboot without the need to change anything. It is so efficient. So this is probably the second usage of my patch. It hand the right of control back to the graphic developer.
Re: [RFC PATCH 0/5] drm/amd/display: improve DTN color state log
On 09/05, Melissa Wen wrote: > Hi, > > I'm updating the color state part of DTN log to match DCN3.0 HW better. > Currently, the DTN log considers the DCN10 color pipeline, which is > useless for DCN3.0 because of all the differences in color caps between > DCN versions. In addition to new color blocks and caps, some semantic > differences made the DCN10 output not fit DCN30. > > In this RFC, the first patch adds new color state elements to DPP and > implements the reading of registers according to HW blocks. Similarly to > MPC, the second patch also creates a DCN3-specific function to read the > MPC state and add the MPC color state logging to it. With DPP and MPC > color-register reading, I detach DCN10 color state logging from the HW > log and create a `.log_color_state` hook for logging color state > according to HW color blocks with DCN30 as the first use case. Finally, > the last patch adds DPP and MPC color caps output to facilitate > understanding of the color state log. > > This version works well with the driver-specific color properties[1] and > steamdeck/gamescope[2] together, where we can see color state changing > from default values. For comparison, here is the before and after of DPP and MPC section in the DTN log on Steam Deck + driver-specific color properties: Without this series: === DPP:IGAM format IGAM modeDGAM modeRGAM mode GAMUT mode C11 C12 C13 C14 C21 C22 C23 C24 C31 C32 C33 C34 [ 0]:0h BypassFixed Bypass Bypass0h h h h h h [ 3]:0h BypassFixed Bypass Bypass0h h h h h h MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE [ 0]: 0h 0h 3h 3 20 0 0 [ 3]: 0h 3h fh 2 20 0 0 With this series (Steamdeck/Gamescope): == DPP: DGAM ROM DGAM ROM type DGAM LUT SHAPER mode 3DLUT mode 3DLUT bit depth 3DLUT size RGAM mode GAMUT mode C11 C12 C13 C14 C21 C22 C23 C24 C31 C32 C33 C34 [ 0]:1 sRGBBypassRAM B RAM A 12-bit17x17x17 Bypass 0 h h h h h h [ 3]:1 sRGBBypassRAM B RAM A 12-bit17x17x17 Bypass 0 h h h h h h DPP Color Caps: input_lut_shared:0 icsc:1 dgam_ram:0 dgam_rom: srgb:1,bt2020:1,gamma2_2:1,pq:1,hlg:1 post_csc:1 gamcor:1 dgam_rom_for_yuv:0 3d_lut:1 blnd_lut:1 oscs:0 MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE SHAPER mode 3DLUT_mode 3DLUT bit-depth 3DLUT size OGAM mode OGAM LUT GAMUT mode C11 C12 C33 C34 [ 0]: 0h 0h 3h 3 20 0 0 Bypass Bypass 12-bit17x17x17 Bypass A 0 h h [ 3]: 0h 3h fh 2 20 0 0 Bypass Bypass 12-bit17x17x17 Bypass A 0 h h MPC Color Caps: gamut_remap:1, 3dlut:2, ogam_ram:1, ocsc:1 With this series (Steamdeck/KDE): DPP: DGAM ROM DGAM ROM type DGAM LUT SHAPER mode 3DLUT mode 3DLUT bit depth 3DLUT size RGAM mode GAMUT mode C11 C12 C13 C14 C21 C22 C23 C24 C31 C32 C33 C34 [ 0]:0 sRGBBypass Bypass Bypass 12-bit 9x9x9 Bypass 0 h h h h h h [ 3]:0 sRGBBypass Bypass Bypass 12-bit 9x9x9 Bypass 0 h h h h h h DPP Color Caps: input_lut_shared:0 icsc:1 dgam_ram:0 dgam_rom: srgb:1,bt2020:1,gamma2_2:1,pq:1,hlg:1 post_csc:1 gamcor:1 dgam_rom_for_yuv:0 3d_lut:1 blnd_lut:1 oscs:0 MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE SHAPER mode 3DLUT_mode 3DLUT bit-depth 3DLUT size OGAM mode OGAM LUT GAMUT mode C11 C12 C33 C34 [ 0]: 0h 0h 3h 3 20 0 0 Bypass Bypass 12-bit17x17x17RAM A 1 2000h 2000h [ 3]: 0h 3h fh 2 20 0 0 Bypass Bypass 12-bit17x17x17 Bypass A 0 h h MPC Color Caps: gamut_remap:1, 3dlut:2, ogam_ram:1, ocsc:1 > > Before extending it to other DCN families, I have some doubts. Does this > approach of the `.log_color_state` hook make sense for you? Is there any > conflict between logging color state by HW version and DTN log usage? Is > there a template/style f
Re: [Nouveau] [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
Hi Am 05.09.23 um 15:30 schrieb suijingfeng: Hi, On 2023/9/5 18:45, Thomas Zimmermann wrote: Hi Am 04.09.23 um 21:57 schrieb Sui Jingfeng: From: Sui Jingfeng On a machine with multiple GPUs, a Linux user has no control over which one is primary at boot time. This series tries to solve above mentioned If anything, the primary graphics adapter is the one initialized by the firmware. I think our boot-up graphics also make this assumption implicitly. Yes, but by the time of DRM drivers get loaded successfully,the boot-up graphics already finished. Firmware framebuffer device already get killed by the drm_aperture_remove_conflicting_pci_framebuffers() function (or its siblings). So, this series is definitely not to interact with the firmware framebuffer Yes and no. The helpers you mention will attempt to remove the firmware framebuffer on the given PCI device. If you have multiple PCI devices, the other devices would not be affected. This also means that probing a non-primary card will not affect the firmware framebuffer on the primary card. You can have all these drivers co-exist next to each other. If you link a full DRM driver into the kernel image, it might even be loaded before the firmware-framebuffer's driver. We had some funny bugs from these interactions. (or more intelligent framebuffer drivers). It is for user space program, such as X server and Wayland compositor. Its for Linux user or drm drivers testers, which allow them to direct graphic display server using right hardware of interested as primary video card. Also, I believe that X server and Wayland compositor are the best test examples. If a specific DRM driver can't work with X server as a primary, then there probably have something wrong. If you want to run a userspace compositor or X11 on a certain device, you best configure this in the program's config files. But not on the kernel command line. The whole concept of a 'primary' display is bogus IMHO. It only exists because old VGA and BIOS (and their equivalents on non-PC systems) were unable to use more than one graphics device. Hence, as you write below, only the first device got POSTed by the BIOS. If you had an additional card, the device driver needed to perform the POSTing. However, on modern Linux systems the primary display does not really exist. 'Primary' is the device that is available via VGA, VESA or EFI. Our drivers don't use these interfaces, but the native registers. As you said yourself, these firmware devices (VGA, VESA, EFI) are removed ASAP by the native drivers. But what's the use case for overriding this setting? On a specific machine with multiple GPUs mounted, only the primary graphics get POST-ed (initialized) by the firmware. Therefore, the DRM drivers for the rest video cards, have to choose to work without the prerequisite setups done by firmware, This is called as POST. One of the use cases of this series is to test if a specific DRM driver could works properly, even though there is no prerequisite works have been done by firmware at all. And it seems that the results is not satisfying in all cases. drm/ast is the first drm drivers which refused to work if not being POST-ed by the firmware. You might have found a bug in the ast driver. Ast has means to detect if the device has been POSTed and maybe do that. If this doesn't work correctly, it needs a fix. As Christian mentioned, if anything, you might add an option to specify the default card to vgaarb (e.g., as PCI slot). But userspace should avoid the idea of a primary card IMHO. Best regards Thomas Before apply this series, I was unable make drm/ast as the primary video card easily. On a multiple video card configuration, the monitor connected with the AST2400 not light up. While confusing, a naive programmer may suspect the PRIME is not working. After applied this series and passing ast.modeset=10 on the kernel cmd line, I found that the monitor connected with my ast2400 video card still black, It doesn't display and doesn't show image to me. While in the process of study drm/ast, I know that drm/ast driver has the POST code shipped. See the ast_post_gpu() function, then, I was wondering why this function doesn't works. After a short-time (hasty) debugging, I found that the the ast_post_gpu() function didn't get run. Because it have something to do with the ast->config_mode. Without thinking too much, I hardcoded the ast->config_mode as ast_use_p2a to force the ast_post_gpu() function get run. ``` --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -132,6 +132,8 @@ static int ast_device_config_init(struct ast_device *ast) } } + ast->config_mode = ast_use_p2a; + switch (ast->config_mode) { case ast_use_defaults: drm_info(dev, "Using default configuration\n"); ``` Then, the monitor light up, it display the Ubuntu gr
Re: [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
On Tue, 5 Sep 2023 03:57:15 +0800 Sui Jingfeng wrote: > From: Sui Jingfeng > > On a machine with multiple GPUs, a Linux user has no control over which > one is primary at boot time. This series tries to solve above mentioned > problem by introduced the ->be_primary() function stub. The specific > device drivers can provide an implementation to hook up with this stub by > calling the vga_client_register() function. > > Once the driver bound the device successfully, VGAARB will call back to > the device driver. To query if the device drivers want to be primary or > not. Device drivers can just pass NULL if have no such needs. > > Please note that: > > 1) The ARM64, Loongarch, Mips servers have a lot PCIe slot, and I would >like to mount at least three video cards. > > 2) Typically, those non-86 machines don't have a good UEFI firmware >support, which doesn't support select primary GPU as firmware stage. >Even on x86, there are old UEFI firmwares which already made undesired >decision for you. > > 3) This series is attempt to solve the remain problems at the driver level, >while another series[1] of me is target to solve the majority of the >problems at device level. > > Tested (limited) on x86 with four video card mounted, Intel UHD Graphics > 630 is the default boot VGA, successfully override by ast2400 with > ast.modeset=10 append at the kernel cmd line. > > $ lspci | grep VGA > > 00:02.0 VGA compatible controller: Intel Corporation CoffeeLake-S GT2 [UHD > Graphics 630] In all my previous experiments with VGA routing and IGD I found that IGD can't actually release VGA routing and Intel confirmed the hardware doesn't have the ability to do so. It will always be primary from a VGA routing perspective. Was this actually tested with non-UEFI? I suspect it might only work in UEFI mode where we probably don't actually have a dependency on VGA routing. This is essentially why vfio requires UEFI ROMs when assigning GPUs to VMs, VGA routing is too broken to use on Intel systems with IGD. Thanks, Alex > 01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] > Caicos XTX [Radeon HD 8490 / R5 235X OEM] > 04:00.0 VGA compatible controller: ASPEED Technology, Inc. ASPEED Graphics > Family (rev 30) > 05:00.0 VGA compatible controller: NVIDIA Corporation GK208B [GeForce GT > 720] (rev a1) > > $ sudo dmesg | grep vgaarb > > pci :00:02.0: vgaarb: setting as boot VGA device > pci :00:02.0: vgaarb: VGA device added: > decodes=io+mem,owns=io+mem,locks=none > pci :01:00.0: vgaarb: VGA device added: > decodes=io+mem,owns=none,locks=none > pci :04:00.0: vgaarb: VGA device added: > decodes=io+mem,owns=none,locks=none > pci :05:00.0: vgaarb: VGA device added: > decodes=io+mem,owns=none,locks=none > vgaarb: loaded > ast :04:00.0: vgaarb: Override as primary by driver > i915 :00:02.0: vgaarb: changed VGA decodes: > olddecodes=io+mem,decodes=none:owns=io+mem > radeon :01:00.0: vgaarb: changed VGA decodes: > olddecodes=io+mem,decodes=none:owns=none > ast :04:00.0: vgaarb: changed VGA decodes: > olddecodes=io+mem,decodes=none:owns=none > > v2: > * Add a simple implemment for drm/i915 and drm/ast > * Pick up all tags (Mario) > v3: > * Fix a mistake for drm/i915 implement > * Fix patch can not be applied problem because of merge conflect. > v4: > * Focus on solve the real problem. > > v1,v2 at https://patchwork.freedesktop.org/series/120059/ >v3 at https://patchwork.freedesktop.org/series/120562/ > > [1] https://patchwork.freedesktop.org/series/122845/ > > Sui Jingfeng (9): > PCI/VGA: Allowing the user to select the primary video adapter at boot > time > drm/nouveau: Implement .be_primary() callback > drm/radeon: Implement .be_primary() callback > drm/amdgpu: Implement .be_primary() callback > drm/i915: Implement .be_primary() callback > drm/loongson: Implement .be_primary() callback > drm/ast: Register as a VGA client by calling vga_client_register() > drm/hibmc: Register as a VGA client by calling vga_client_register() > drm/gma500: Register as a VGA client by calling vga_client_register() > > drivers/gpu/drm/amd/amdgpu/amdgpu_device.c| 11 +++- > drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 13 - > drivers/gpu/drm/ast/ast_drv.c | 31 ++ > drivers/gpu/drm/gma500/psb_drv.c | 57 ++- > .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 15 + > drivers/gpu/drm/i915/display/intel_vga.c | 15 - > drivers/gpu/drm/loongson/loongson_module.c| 2 +- > drivers/gpu/drm/loongson/loongson_module.h| 1 + > drivers/gpu/drm/loongson/lsdc_drv.c | 10 +++- > drivers/gpu/drm/nouveau/nouveau_vga.c | 11 +++- > drivers/gpu/drm/radeon/radeon_device.c| 10 +++- > drivers/pci/vgaarb.c | 43 -- > drivers/vfio/pci/vfio_pci_core.c
Re: [RFC][PATCH 0/2] drm/panic: Add a drm panic handler
On 04/09/2023 16:29, Thomas Zimmermann wrote: Hi Jocelyn, thanks for moving this effort forward. It's much appreciated. I looked through the patches and tried the patchset on my test machine. Thanks for taking the time to review and test it. Am 09.08.23 um 21:17 schrieb Jocelyn Falempe: This introduces a new drm panic handler, which displays a message when a panic occurs. So when fbcon is disabled, you can still see a kernel panic. This is one of the missing feature, when disabling VT/fbcon in the kernel: https://www.reddit.com/r/linux/comments/10eccv9/config_vtn_in_2023/ Fbcon can be replaced by a userspace kms console, but the panic screen must be done in the kernel. This is a proof of concept, and works only with simpledrm, using the drm_client API. This implementation with the drm client API, allocates new framebuffers, and looks a bit too complex to run in a panic handler. Maybe we should add an API to "steal" the current framebuffer instead, because in a panic handler user-space is already stopped. Yes, that was also my first thought. I'd use an extra callback in struct drm_driver, like this: struct drm_driver { int (*get_scanout_buffer)(/* return HW scanout */) } The scanout buffer would be described by kernel virtual address address, resolution, color format and scanline pitch. And that's what the panic handler uses. Thanks, I will try this solution. It shouldn't be too hard for simpledrm. Any driver implementing this interface would support the panic handler. If there's a concurrent display update, we'd have to synchronize. Normally in the panic handler, the kernel is already single-threaded, so there won't be another task doing things in parallel. (But the GPU might still be busy doing other stuff, if we're in the middle of a game). I think this drm_panic should be a "best effort", we can't guarantee the user will see the panic screen in all panic situations. To test it, make sure you're using the simpledrm driver, and trigger a panic: echo c > /proc/sysrq-trigger The penguin was cute. :) This only works if the display is already running. I had to start Gnome to set a display mode. Then let the panic handler take over the output. oh, I didn't expect this limitation. I will try to test that too. It might also get fixed by using the get_scanout_buffer() above. But with simpledrm, we could even display a message without an output, as the framebuffer is always there. There is one thing I don't know how to do, is to unregister the drm_panic when the graphic driver is unloaded. drm_client_register() says it will automatically unregister on driver unload. But then I don't know how to remove it from my linked list, and free the drm_client_dev struct. Unregistering wouldn't be necessary with this proposed get_scanout_buffer. In the case of a panic, just remain silent if there's no driver that provides such a callback. Is there a way to loop over all drm_devices ? otherwise drm_panic may still call get_scanout_buffer() on a freed device, which would be problematic. This is a first draft, so let me know what do you think about it. One thing that will need serious work is the raw output. The current blitting for XRGB is really just a quick-and-dirty hack. I think we should try to reuse fbdev's blitting code, if possible. The fbdev core, helpers and console come with all the features we need. We really only need to make them work without the struct fb_info, which is a full fbdev device. I'm a bit reluctant to re-use the fbdev code, for a few reasons: * I want drm_panic to work if CONFIG_FB and CONFIG_DRM_FBDEV_EMULATION are not set. * drm_panic only needs two things, to clear the framebuffer, and then draw white pixels where needed. As the frame is static, and the amount of white pixels is low, that should be good enough. So copy_area() or image_blit() are not that useful. * For this particular use-case, performances are not a priority, it doesn't matter if it takes 10us or 100ms to draw the panic screen, as it will stay the same until the user reboots. * Some aggressive optimizations might cause issues in a panic handler, like if you use workqueue/tasklet. On the other hand, writing the code for all supported formats is a bit tedious. drm_log [1] did it in ~300 lines, which should keep code duplication low. In struct fb_ops, there are callbacks for modifying the framebuffer. [1] They are used by fbcon foir drawing. But they operate on fb_info. For a while I've been thinking about using something like a drawable to provide some abstractions: struct drawable { /* store buffer parameters here */ ... struct drawable_funcs *funcs; }; struct drawable_funcs { /* have function pointers similar to struct fb_ops */ fill_rect() copy_area() image_blit() }; We cannot rewrite all the existing fbdev drivers. To make this work with fbdev, we'd need adapter code that conver
Re: [PATCH 0/4] drm/bridge: lt8912b: Init & remove related fixes
On Fri, 04 Aug 2023 13:48:09 +0300, Tomi Valkeinen wrote: > Fix various issues in lt8912b driver. > > Tomi > > Fixed the mentioned commit message typos, and an incorrect has for a "Fixes" tag. Applied, thanks! [1/4] drm/bridge: lt8912b: Fix bridge_detach https://cgit.freedesktop.org/drm/drm-misc/commit/?id=941882a0e96d [2/4] drm/bridge: lt8912b: Fix crash on bridge detach https://cgit.freedesktop.org/drm/drm-misc/commit/?id=44283993144a [3/4] drm/bridge: lt8912b: Manually disable HPD only if it was enabled https://cgit.freedesktop.org/drm/drm-misc/commit/?id=6985c5efc405 [4/4] drm/bridge: lt8912b: Add missing drm_bridge_attach call https://cgit.freedesktop.org/drm/drm-misc/commit/?id=f45acf7acf75 Rob
Re: [PATCH v2] drm: bridge: it66121: Fix invalid connector dereference
On Fri, 1 Sep 2023 15:01:23 +0530, Jai Luthra wrote: > Fix the NULL pointer dereference when no monitor is connected, and the > sound card is opened from userspace. > > Instead return an empty buffer (of zeroes) as the EDID information to > the sound framework if there is no connector attached. > > > [...] Applied, thanks! [1/1] drm: bridge: it66121: Fix invalid connector dereference https://cgit.freedesktop.org/drm/drm-misc/commit/?id=d0375f6858c4 Rob
Re: [PATCH 3/3] drm/drm_exec: Work around a WW mutex lockdep oddity
Hi, Christian On 9/5/23 15:14, Christian König wrote: Am 05.09.23 um 10:58 schrieb Thomas Hellström: If *any* object of a certain WW mutex class is locked, lockdep will consider *all* mutexes of that class as locked. Also the lock allocation tracking code will apparently register only the address of the first mutex locked in a sequence. This has the odd consequence that if that first mutex is unlocked and its memory then freed, the lock alloc tracking code will assume that memory is freed with a held lock in there. For now, work around that for drm_exec by releasing the first grabbed object lock last. Related lock alloc tracking warning: [ 322.660067] = [ 322.660070] WARNING: held lock freed! [ 322.660074] 6.5.0-rc7+ #155 Tainted: G U N [ 322.660078] - [ 322.660081] kunit_try_catch/4981 is freeing memory 888112adc000-888112adc3ff, with a lock still held there! [ 322.660089] 888112adc1a0 (reservation_ww_class_mutex){+.+.}-{3:3}, at: drm_exec_lock_obj+0x11a/0x600 [drm_exec] [ 322.660104] 2 locks held by kunit_try_catch/4981: [ 322.660108] #0: c9000343fe18 (reservation_ww_class_acquire){+.+.}-{0:0}, at: test_early_put+0x22f/0x490 [drm_exec_test] [ 322.660123] #1: 888112adc1a0 (reservation_ww_class_mutex){+.+.}-{3:3}, at: drm_exec_lock_obj+0x11a/0x600 [drm_exec] [ 322.660135] stack backtrace: [ 322.660139] CPU: 7 PID: 4981 Comm: kunit_try_catch Tainted: G U N 6.5.0-rc7+ #155 [ 322.660146] Hardware name: ASUS System Product Name/PRIME B560M-A AC, BIOS 0403 01/26/2021 [ 322.660152] Call Trace: [ 322.660155] [ 322.660158] dump_stack_lvl+0x57/0x90 [ 322.660164] debug_check_no_locks_freed+0x20b/0x2b0 [ 322.660172] slab_free_freelist_hook+0xa1/0x160 [ 322.660179] ? drm_exec_unlock_all+0x168/0x2a0 [drm_exec] [ 322.660186] __kmem_cache_free+0xb2/0x290 [ 322.660192] drm_exec_unlock_all+0x168/0x2a0 [drm_exec] [ 322.660200] drm_exec_fini+0xf/0x1c0 [drm_exec] [ 322.660206] test_early_put+0x289/0x490 [drm_exec_test] [ 322.660215] ? __pfx_test_early_put+0x10/0x10 [drm_exec_test] [ 322.660222] ? __kasan_check_byte+0xf/0x40 [ 322.660227] ? __ksize+0x63/0x140 [ 322.660233] ? drmm_add_final_kfree+0x3e/0xa0 [drm] [ 322.660289] ? _raw_spin_unlock_irqrestore+0x30/0x60 [ 322.660294] ? lockdep_hardirqs_on+0x7d/0x100 [ 322.660301] ? __pfx_kunit_try_run_case+0x10/0x10 [kunit] [ 322.660310] ? __pfx_kunit_generic_run_threadfn_adapter+0x10/0x10 [kunit] [ 322.660319] kunit_generic_run_threadfn_adapter+0x4a/0x90 [kunit] [ 322.660328] kthread+0x2e7/0x3c0 [ 322.660334] ? __pfx_kthread+0x10/0x10 [ 322.660339] ret_from_fork+0x2d/0x70 [ 322.660345] ? __pfx_kthread+0x10/0x10 [ 322.660349] ret_from_fork_asm+0x1b/0x30 [ 322.660358] [ 322.660818] ok 8 test_early_put Cc: Christian König Cc: Boris Brezillon Cc: Danilo Krummrich Cc: dri-devel@lists.freedesktop.org Signed-off-by: Thomas Hellström --- drivers/gpu/drm/drm_exec.c | 2 +- include/drm/drm_exec.h | 35 +++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_exec.c b/drivers/gpu/drm/drm_exec.c index ff69cf0fb42a..5d2809de4517 100644 --- a/drivers/gpu/drm/drm_exec.c +++ b/drivers/gpu/drm/drm_exec.c @@ -56,7 +56,7 @@ static void drm_exec_unlock_all(struct drm_exec *exec) struct drm_gem_object *obj; unsigned long index; - drm_exec_for_each_locked_object(exec, index, obj) { + drm_exec_for_each_locked_object_reverse(exec, index, obj) { Well that's a really good catch, just one more additional thought below. dma_resv_unlock(obj->resv); drm_gem_object_put(obj); } diff --git a/include/drm/drm_exec.h b/include/drm/drm_exec.h index e0462361adf9..55764cf7c374 100644 --- a/include/drm/drm_exec.h +++ b/include/drm/drm_exec.h @@ -51,6 +51,20 @@ struct drm_exec { struct drm_gem_object *prelocked; }; +/** + * drm_exec_obj() - Return the object for a give drm_exec index + * @exec: Pointer to the drm_exec context + * @index: The index. + * + * Return: Pointer to the locked object corresponding to @index if + * index is within the number of locked objects. NULL otherwise. + */ +static inline struct drm_gem_object * +drm_exec_obj(struct drm_exec *exec, unsigned long index) +{ + return index < exec->num_objects ? exec->objects[index] : NULL; +} + /** * drm_exec_for_each_locked_object - iterate over all the locked objects * @exec: drm_exec object @@ -59,10 +73,23 @@ struct drm_exec { * * Iterate over all the locked GEM objects inside the drm_exec object. */ -#define drm_exec_for_each_locked_object(exec, index, obj) \ - for (index = 0, obj = (exec)->objects[0]; \ - index < (exec)->num_objects; \ - ++index, obj = (exec)->objects[index]) +#define drm_exec_for_each_locked_object(exec, index, obj) \ + for ((index
Re: [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
Hi, On 2023/9/5 21:28, Christian König wrote: 2) Typically, those non-86 machines don't have a good UEFI firmware support, which doesn't support select primary GPU as firmware stage. Even on x86, there are old UEFI firmwares which already made undesired decision for you. 3) This series is attempt to solve the remain problems at the driver level, while another series[1] of me is target to solve the majority of the problems at device level. Tested (limited) on x86 with four video card mounted, Intel UHD Graphics 630 is the default boot VGA, successfully override by ast2400 with ast.modeset=10 append at the kernel cmd line. The value 10 is incredibly arbitrary, and multiplied as a magic number all over the place. +1 This is the exact reason why I made this series as RFC, because this is a open-ended problem. The choices of 3,4,5,6,7,8 and 9 are as arbitrary as the number of '10'. '1' and '2' is definitely not suitable, because the seat has already been taken. Take the drm/nouveau as an example: ``` MODULE_PARM_DESC(modeset, "enable driver (default: auto, " "0 = disabled, 1 = enabled, 2 = headless)"); int nouveau_modeset = -1; module_param_named(modeset, nouveau_modeset, int, 0400); ``` '1' is for enable the drm driver, some driver even override the 'nomodeset' parameter. '2' is not suitable, because nouveau use it as headless GPU (render-only or compute class GPU?) '3' is also not likely the best, the concerns is that what if a specific drm driver want to expand the usage in the future? The reason I pick up the digit '10' is that 1) The modeset parameter is unlikely to get expanded up to 10 usages. Other drm drivers only use the '-1', '0' and 1, choose '2' will conflict with drm/nouveau. By pick the digit '10', it leave some space(room) to various device driver authors. It also helps to keep the usage consistent across various drivers. 2) An int taken up 4 byte, I don't want to waste even a single byte, While in the process of defencing my patch, I have to say draft another kernel command line would cause the wasting of precious RAM storage. An int can have 2^31 usage, why we can't improve the utilization rate? 3) Please consider the fact that the modeset is the most common and attractive parameter No name is better than the 'modeset', as other name is not easy to remember. Again, this is for Linux user, thus it is not arbitrary. Despite simple and trivial, I think about it more than one week.
[RFC PATCH 5/5] drm/amd/display: add DPP and MPC color caps to DTN log
Add color caps information for DPP and MPC block to show HW color caps. Signed-off-by: Melissa Wen --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 23 +++ .../drm/amd/display/dc/dcn30/dcn30_hwseq.c| 23 +++ 2 files changed, 46 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index b2f3f1f85f4f..6caac6cb8873 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -329,6 +329,24 @@ dcn10_log_color_state(struct dc *dc, DTN_INFO("\n"); } DTN_INFO("\n"); + DTN_INFO("DPP Color Caps: input_lut_shared:%d icsc:%d" +" dgam_ram:%d dgam_rom: srgb:%d,bt2020:%d,gamma2_2:%d,pq:%d,hlg:%d" +" post_csc:%d gamcor:%d dgam_rom_for_yuv:%d 3d_lut:%d" +" blnd_lut:%d oscs:%d\n\n", +dc->caps.color.dpp.input_lut_shared, +dc->caps.color.dpp.icsc, +dc->caps.color.dpp.dgam_ram, +dc->caps.color.dpp.dgam_rom_caps.srgb, +dc->caps.color.dpp.dgam_rom_caps.bt2020, +dc->caps.color.dpp.dgam_rom_caps.gamma2_2, +dc->caps.color.dpp.dgam_rom_caps.pq, +dc->caps.color.dpp.dgam_rom_caps.hlg, +dc->caps.color.dpp.post_csc, +dc->caps.color.dpp.gamma_corr, +dc->caps.color.dpp.dgam_rom_for_yuv, +dc->caps.color.dpp.hw_3d_lut, +dc->caps.color.dpp.ogam_ram, +dc->caps.color.dpp.ocsc); DTN_INFO("MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE\n"); for (i = 0; i < pool->pipe_count; i++) { @@ -342,6 +360,11 @@ dcn10_log_color_state(struct dc *dc, s.idle); } DTN_INFO("\n"); + DTN_INFO("MPC Color Caps: gamut_remap:%d, 3dlut:%d, ogam_ram:%d, ocsc:%d\n\n", +dc->caps.color.mpc.gamut_remap, +dc->caps.color.mpc.num_3dluts, +dc->caps.color.mpc.ogam_ram, +dc->caps.color.mpc.ocsc); } void dcn10_log_hw_state(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index e1a2a68c1d45..dfccf0d3f0d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -125,6 +125,24 @@ dcn30_log_color_state(struct dc *dc, DTN_INFO("\n"); } DTN_INFO("\n"); + DTN_INFO("DPP Color Caps: input_lut_shared:%d icsc:%d" +" dgam_ram:%d dgam_rom: srgb:%d,bt2020:%d,gamma2_2:%d,pq:%d,hlg:%d" +" post_csc:%d gamcor:%d dgam_rom_for_yuv:%d 3d_lut:%d" +" blnd_lut:%d oscs:%d\n\n", +dc->caps.color.dpp.input_lut_shared, +dc->caps.color.dpp.icsc, +dc->caps.color.dpp.dgam_ram, +dc->caps.color.dpp.dgam_rom_caps.srgb, +dc->caps.color.dpp.dgam_rom_caps.bt2020, +dc->caps.color.dpp.dgam_rom_caps.gamma2_2, +dc->caps.color.dpp.dgam_rom_caps.pq, +dc->caps.color.dpp.dgam_rom_caps.hlg, +dc->caps.color.dpp.post_csc, +dc->caps.color.dpp.gamma_corr, +dc->caps.color.dpp.dgam_rom_for_yuv, +dc->caps.color.dpp.hw_3d_lut, +dc->caps.color.dpp.ogam_ram, +dc->caps.color.dpp.ocsc); DTN_INFO("MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE" " SHAPER mode 3DLUT_mode 3DLUT bit-depth 3DLUT size OGAM mode OGAM LUT" @@ -156,6 +174,11 @@ dcn30_log_color_state(struct dc *dc, s.gamut_remap_c11_c12, s.gamut_remap_c33_c34); } DTN_INFO("\n"); + DTN_INFO("MPC Color Caps: gamut_remap:%d, 3dlut:%d, ogam_ram:%d, ocsc:%d\n\n", +dc->caps.color.mpc.gamut_remap, +dc->caps.color.mpc.num_3dluts, +dc->caps.color.mpc.ogam_ram, +dc->caps.color.mpc.ocsc); } bool dcn30_set_blend_lut( -- 2.40.1
[RFC PATCH 4/5] drm/amd/display: hook DCN30 color state logging to DTN log
Color caps changed between HW versions which caused DCN10 color state sections on DTN log no longer fit DCN3.0 versions. Create a DCN3.0-specific color state logging and hook it to drivers of DCN3.0 family. Signed-off-by: Melissa Wen --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 5 +- .../drm/amd/display/dc/dcn30/dcn30_hwseq.c| 89 +++ .../drm/amd/display/dc/dcn30/dcn30_hwseq.h| 3 + .../gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 1 + .../drm/amd/display/dc/dcn301/dcn301_init.c | 1 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 + 6 files changed, 100 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d82e49045fbc..b2f3f1f85f4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -357,7 +357,10 @@ void dcn10_log_hw_state(struct dc *dc, dcn10_log_hubp_states(dc, log_ctx); - dcn10_log_color_state(dc, log_ctx); + if (dc->hwss.log_color_state) + dc->hwss.log_color_state(dc, log_ctx); + else + dcn10_log_color_state(dc, log_ctx); DTN_INFO("OTG: v_bs v_be v_ss v_se vpol vmax vmin vmax_sel vmin_sel h_bs h_be h_ss h_se hpol htot vtot underflow blank_en\n"); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index 255713ec29bb..e1a2a68c1d45 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -69,6 +69,95 @@ #define FN(reg_name, field_name) \ hws->shifts->field_name, hws->masks->field_name +void +dcn30_log_color_state(struct dc *dc, + struct dc_log_buffer_ctx *log_ctx) +{ + struct dc_context *dc_ctx = dc->ctx; + struct resource_pool *pool = dc->res_pool; + int i; + + DTN_INFO("DPP: DGAM ROM DGAM ROM type DGAM LUT SHAPER mode" +" 3DLUT mode 3DLUT bit depth 3DLUT size RGAM mode" +" GAMUT mode " +"C11 C12 C13 C14 C21 C22 C23 C24 C31 C32 C33 C34\n"); + + for (i = 0; i < pool->pipe_count; i++) { + struct dpp *dpp = pool->dpps[i]; + struct dcn_dpp_state s = {-1}; + + dpp->funcs->dpp_read_state(dpp, &s); + + if (!s.is_enabled) + continue; + + DTN_INFO("[%2d]: %7x %13s %8s %11s %10s %15s %10s %9s" +" %10x %08xh %08xh %08xh %08xh %08xh %08xh", + dpp->inst, + s.pre_dgam_mode, + (s.pre_dgam_select == 0) ? "sRGB" : +((s.pre_dgam_select == 1) ? "Gamma 2.2" : +((s.pre_dgam_select == 2) ? "Gamma 2.4" : +((s.pre_dgam_select == 3) ? "Gamma 2.6" : +((s.pre_dgam_select == 4) ? "BT.709" : +((s.pre_dgam_select == 5) ? "PQ" : +((s.pre_dgam_select == 6) ? "HLG" : +"Unknown")), + (s.gamcor_lut_mode == 0) ? "Bypass" : +((s.gamcor_lut_mode == 2) ? "RAM" : +"Unknown"), + (s.shaper_lut_mode == 1) ? "RAM A" : +((s.shaper_lut_mode == 2) ? "RAM B" : +"Bypass"), + (s.lut3d_mode == 1) ? "RAM A" : +((s.lut3d_mode == 2) ? "RAM B" : + "Bypass"), + (s.lut3d_bit_depth <= 0) ? "12-bit" : "10-bit", + (s.lut3d_size == 0) ? "17x17x17" : "9x9x9", + (s.rgam_lut_mode == 0) ? "Bypass" : +((s.rgam_lut_mode == 1) ? "RAM A" : +((s.rgam_lut_mode == 2) ? "RAM B" : + "Unknown")), + s.gamut_remap_mode, + s.gamut_remap_c11_c12, s.gamut_remap_c13_c14, + s.gamut_remap_c21_c22, s.gamut_remap_c23_c24, + s.gamut_remap_c31_c32, s.gamut_remap_c33_c34); + DTN_INFO("\n"); + } + DTN_INFO("\n"); + + DTN_INFO("MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE" +" SHAPER mode 3DLUT_mode 3DLUT bit-depth 3DLUT size OGAM mode OGAM LUT" +" GAMUT mode C11 C12 C33 C34\n"); + + for (i = 0; i < pool->pipe_count; i++) { + struct mpcc_state s = {0}; + + pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s); + if (s.opp_id != 0xf) +
[RFC PATCH 3/5] drm/amd/display: create DCN3-specific log for MPC state
Logging DCN3 MPC state was following DCN1 implementation that doesn't consider new DCN3 MPC color blocks. Create new elements according to DCN3 MPC color caps and a new DCN3-specific function for reading MPC data. Signed-off-by: Melissa Wen --- .../gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c | 55 ++- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 13 + 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c index d1500b223858..d164fbf89212 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c @@ -1382,8 +1382,61 @@ static void mpc3_set_mpc_mem_lp_mode(struct mpc *mpc) } } +static void mpc3_read_mpcc_state( + struct mpc *mpc, + int mpcc_inst, + struct mpcc_state *s) +{ + struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); + uint32_t rmu_status = 0xf; + + REG_GET(MPCC_OPP_ID[mpcc_inst], MPCC_OPP_ID, &s->opp_id); + REG_GET(MPCC_TOP_SEL[mpcc_inst], MPCC_TOP_SEL, &s->dpp_id); + REG_GET(MPCC_BOT_SEL[mpcc_inst], MPCC_BOT_SEL, &s->bot_mpcc_id); + REG_GET_4(MPCC_CONTROL[mpcc_inst], MPCC_MODE, &s->mode, + MPCC_ALPHA_BLND_MODE, &s->alpha_mode, + MPCC_ALPHA_MULTIPLIED_MODE, &s->pre_multiplied_alpha, + MPCC_BLND_ACTIVE_OVERLAP_ONLY, &s->overlap_only); + REG_GET_2(MPCC_STATUS[mpcc_inst], MPCC_IDLE, &s->idle, + MPCC_BUSY, &s->busy); + + /* Color blocks state */ + REG_GET(MPC_RMU_CONTROL, MPC_RMU0_MUX_STATUS, &rmu_status); + if (rmu_status == mpcc_inst) { + REG_GET(SHAPER_CONTROL[0], + MPC_RMU_SHAPER_LUT_MODE_CURRENT, &s->shaper_lut_mode); + REG_GET(RMU_3DLUT_MODE[0], + MPC_RMU_3DLUT_MODE_CURRENT, &s->lut3d_mode); + REG_GET(RMU_3DLUT_READ_WRITE_CONTROL[0], + MPC_RMU_3DLUT_30BIT_EN, &s->lut3d_bit_depth); + REG_GET(RMU_3DLUT_MODE[0], + MPC_RMU_3DLUT_SIZE, &s->lut3d_size); + } else { + REG_GET(SHAPER_CONTROL[1], + MPC_RMU_SHAPER_LUT_MODE_CURRENT, &s->shaper_lut_mode); + REG_GET(RMU_3DLUT_MODE[1], + MPC_RMU_3DLUT_MODE_CURRENT, &s->lut3d_mode); + REG_GET(RMU_3DLUT_READ_WRITE_CONTROL[1], + MPC_RMU_3DLUT_30BIT_EN, &s->lut3d_bit_depth); + REG_GET(RMU_3DLUT_MODE[1], + MPC_RMU_3DLUT_SIZE, &s->lut3d_size); + } + REG_GET_2(MPCC_OGAM_CONTROL[mpcc_inst], + MPCC_OGAM_MODE_CURRENT, &s->rgam_mode, + MPCC_OGAM_SELECT_CURRENT, &s->rgam_lut); + REG_GET(MPCC_GAMUT_REMAP_MODE[mpcc_inst], + MPCC_GAMUT_REMAP_MODE_CURRENT, &s->gamut_remap_mode); + if (s->gamut_remap_mode == 1) { + s->gamut_remap_c11_c12 = REG_READ(MPC_GAMUT_REMAP_C11_C12_A[mpcc_inst]); + s->gamut_remap_c33_c34 = REG_READ(MPC_GAMUT_REMAP_C33_C34_A[mpcc_inst]); + } else if (s->gamut_remap_mode == 2) { + s->gamut_remap_c11_c12 = REG_READ(MPC_GAMUT_REMAP_C11_C12_B[mpcc_inst]); + s->gamut_remap_c33_c34 = REG_READ(MPC_GAMUT_REMAP_C33_C34_B[mpcc_inst]); + } +} + static const struct mpc_funcs dcn30_mpc_funcs = { - .read_mpcc_state = mpc1_read_mpcc_state, + .read_mpcc_state = mpc3_read_mpcc_state, .insert_plane = mpc1_insert_plane, .remove_mpcc = mpc1_remove_mpcc, .mpc_init = mpc1_mpc_init, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 8d86159d9de0..e60b3503605b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -193,6 +193,19 @@ struct mpcc_state { uint32_t overlap_only; uint32_t idle; uint32_t busy; + uint32_t shaper_lut_mode; + uint32_t lut3d_mode; + uint32_t lut3d_bit_depth; + uint32_t lut3d_size; + uint32_t rgam_mode; + uint32_t rgam_lut; + uint32_t gamut_remap_mode; + uint32_t gamut_remap_c11_c12; + uint32_t gamut_remap_c13_c14; + uint32_t gamut_remap_c21_c22; + uint32_t gamut_remap_c23_c24; + uint32_t gamut_remap_c31_c32; + uint32_t gamut_remap_c33_c34; }; /** -- 2.40.1
[RFC PATCH 2/5] drm/amd/display: fill up DCN3 DPP color state
DCN3 DPP color state was uncollected and some state elements from DCN1 doesn't fit DCN3. Create new elements according to DCN3 color caps and fill them up for DTN log output. Signed-off-by: Melissa Wen --- .../gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c | 28 +-- drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 8 ++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c index 50dc83404644..a91d72f44bbd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c @@ -46,9 +46,31 @@ void dpp30_read_state(struct dpp *dpp_base, struct dcn_dpp_state *s) struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); REG_GET(DPP_CONTROL, - DPP_CLOCK_ENABLE, &s->is_enabled); - - // TODO: Implement for DCN3 + DPP_CLOCK_ENABLE, &s->is_enabled); + REG_GET_2(PRE_DEGAM, + PRE_DEGAM_MODE, &s->pre_dgam_mode, + PRE_DEGAM_SELECT, &s->pre_dgam_select); + REG_GET(CM_SHAPER_CONTROL, + CM_SHAPER_LUT_MODE, &s->shaper_lut_mode); + REG_GET(CM_3DLUT_MODE, + CM_3DLUT_MODE_CURRENT, &s->lut3d_mode); + REG_GET(CM_3DLUT_READ_WRITE_CONTROL, + CM_3DLUT_30BIT_EN, &s->lut3d_bit_depth); + REG_GET(CM_3DLUT_MODE, + CM_3DLUT_SIZE, &s->lut3d_size); + // BGAM has no ROM, and definition is different, can't reuse same dump +REG_GET(CM_BLNDGAM_CONTROL, + CM_BLNDGAM_LUT_MODE, &s->rgam_lut_mode); + REG_GET(CM_GAMUT_REMAP_CONTROL, + CM_GAMUT_REMAP_MODE, &s->gamut_remap_mode); + if (s->gamut_remap_mode) { + s->gamut_remap_c11_c12 = REG_READ(CM_GAMUT_REMAP_C11_C12); + s->gamut_remap_c13_c14 = REG_READ(CM_GAMUT_REMAP_C13_C14); + s->gamut_remap_c21_c22 = REG_READ(CM_GAMUT_REMAP_C21_C22); + s->gamut_remap_c23_c24 = REG_READ(CM_GAMUT_REMAP_C23_C24); + s->gamut_remap_c31_c32 = REG_READ(CM_GAMUT_REMAP_C31_C32); + s->gamut_remap_c33_c34 = REG_READ(CM_GAMUT_REMAP_C33_C34); + } } /*program post scaler scs block in dpp CM*/ void dpp3_program_post_csc( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h index f4aa76e02518..7e69d9e28f5b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -148,6 +148,14 @@ struct dcn_dpp_state { uint32_t gamut_remap_c23_c24; uint32_t gamut_remap_c31_c32; uint32_t gamut_remap_c33_c34; + uint32_t shaper_lut_mode; + uint32_t lut3d_mode; + uint32_t lut3d_bit_depth; + uint32_t lut3d_size; + uint32_t blnd_lut_mode; + uint32_t pre_dgam_mode; + uint32_t pre_dgam_select; + uint32_t gamcor_lut_mode; }; struct CM_bias_params { -- 2.40.1
[RFC PATCH 1/5] drm/amd/display: detach color state from hw state logging
Prepare to hook color state logging according to DCN version. Signed-off-by: Melissa Wen --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 27 +-- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 9834b75f1837..d82e49045fbc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -278,19 +278,14 @@ static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx) DTN_INFO("\n"); } -void dcn10_log_hw_state(struct dc *dc, - struct dc_log_buffer_ctx *log_ctx) +static void +dcn10_log_color_state(struct dc *dc, + struct dc_log_buffer_ctx *log_ctx) { struct dc_context *dc_ctx = dc->ctx; struct resource_pool *pool = dc->res_pool; int i; - DTN_INFO_BEGIN(); - - dcn10_log_hubbub_state(dc, log_ctx); - - dcn10_log_hubp_states(dc, log_ctx); - DTN_INFO("DPP:IGAM format IGAM modeDGAM modeRGAM mode" " GAMUT mode C11 C12 C13 C14 C21 C22 C23 C24 " "C31 C32 C33 C34\n"); @@ -347,6 +342,22 @@ void dcn10_log_hw_state(struct dc *dc, s.idle); } DTN_INFO("\n"); +} + +void dcn10_log_hw_state(struct dc *dc, + struct dc_log_buffer_ctx *log_ctx) +{ + struct dc_context *dc_ctx = dc->ctx; + struct resource_pool *pool = dc->res_pool; + int i; + + DTN_INFO_BEGIN(); + + dcn10_log_hubbub_state(dc, log_ctx); + + dcn10_log_hubp_states(dc, log_ctx); + + dcn10_log_color_state(dc, log_ctx); DTN_INFO("OTG: v_bs v_be v_ss v_se vpol vmax vmin vmax_sel vmin_sel h_bs h_be h_ss h_se hpol htot vtot underflow blank_en\n"); -- 2.40.1
[RFC PATCH 0/5] drm/amd/display: improve DTN color state log
Hi, I'm updating the color state part of DTN log to match DCN3.0 HW better. Currently, the DTN log considers the DCN10 color pipeline, which is useless for DCN3.0 because of all the differences in color caps between DCN versions. In addition to new color blocks and caps, some semantic differences made the DCN10 output not fit DCN30. In this RFC, the first patch adds new color state elements to DPP and implements the reading of registers according to HW blocks. Similarly to MPC, the second patch also creates a DCN3-specific function to read the MPC state and add the MPC color state logging to it. With DPP and MPC color-register reading, I detach DCN10 color state logging from the HW log and create a `.log_color_state` hook for logging color state according to HW color blocks with DCN30 as the first use case. Finally, the last patch adds DPP and MPC color caps output to facilitate understanding of the color state log. This version works well with the driver-specific color properties[1] and steamdeck/gamescope[2] together, where we can see color state changing from default values. Before extending it to other DCN families, I have some doubts. Does this approach of the `.log_color_state` hook make sense for you? Is there any conflict between logging color state by HW version and DTN log usage? Is there a template/style for DTN log output that I should follow? Let me know your thoughts. Thanks, Melissa [1] https://lore.kernel.org/amd-gfx/20230810160314.48225-1-m...@igalia.com/ [2] https://github.com/ValveSoftware/gamescope Melissa Wen (5): drm/amd/display: detach color state from hw state logging drm/amd/display: fill up DCN3 DPP color state drm/amd/display: create DCN3-specific log for MPC state drm/amd/display: hook DCN30 color state logging to DTN log drm/amd/display: add DPP and MPC color caps to DTN log .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 53 +++-- .../gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c | 28 - .../drm/amd/display/dc/dcn30/dcn30_hwseq.c| 112 ++ .../drm/amd/display/dc/dcn30/dcn30_hwseq.h| 3 + .../gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 1 + .../gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c | 55 - .../drm/amd/display/dc/dcn301/dcn301_init.c | 1 + drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 8 ++ drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 13 ++ .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 + 10 files changed, 264 insertions(+), 12 deletions(-) -- 2.40.1
Re: [RFT PATCH 01/15] drm/armada: Call drm_atomic_helper_shutdown() at shutdown time
Hi, On Sun, Sep 3, 2023 at 8:53 AM Russell King (Oracle) wrote: > > On Fri, Sep 01, 2023 at 04:41:12PM -0700, Douglas Anderson wrote: > > Based on grepping through the source code this driver appears to be > > missing a call to drm_atomic_helper_shutdown() at system shutdown > > time. Among other things, this means that if a panel is in use that it > > won't be cleanly powered off at system shutdown time. > > > > The fact that we should call drm_atomic_helper_shutdown() in the case > > of OS shutdown/restart comes straight out of the kernel doc "driver > > instance overview" in drm_drv.c. > > > > This driver was fairly easy to update. The drm_device is stored in the > > drvdata so we just have to make sure the drvdata is NULL whenever the > > device is not bound. > > ... and there I think you have a misunderstanding of the driver model. > Please have a look at device_unbind_cleanup() which will be called if > probe fails, or when the device is removed (in other words, when it is > not bound to a driver.) ...and there I think you didn't read this patch closely enough and perhaps that you have a misunderstanding of the component model. Please have a look at the difference between armada_drm_unbind() and armada_drm_remove() and also check which of those two functions is being modified by my patch. Were this patch adding a call to "dev_set_drvdata(dev, NULL)" in armada_drm_remove() then your NAK would be justified. However, I am not aware of anything in the component unbind path nor in the failure case of component bind that would NULL the drvdata. Kindly look at the patch a second time with this in mind. -Doug
Re: [PATCH v3 0/2] Match data improvements for it66121 driver
On Fri, 18 Aug 2023 20:18:15 +0100, Biju Das wrote: > This patch series aims to add match data improvements for it66121 driver. > > v2->v3: > * Removed fixes tag from patch#1 as nothing broken. > * Added Rb tag from Andy. > v1->v2: > * Split the patch into two. > * patch#1 extend match support for OF tables compared to legacy ID >lookup and fixes tag. > * patch#2 simplifies the probe() by using i2c_get_match_data. > * Dropped sentence for dropping local variable as it is integral part of >the patch. > > [...] Applied, thanks! [1/2] drm: bridge: it66121: Extend match support for OF tables https://cgit.freedesktop.org/drm/drm-misc/commit/?id=c11c1a50573e [2/2] drm: bridge: it66121: Simplify probe() https://cgit.freedesktop.org/drm/drm-misc/commit/?id=29ff3b7e23af Rob
[Bug 217872] New: RIP: 0010:amdgpu_vm_pde_update [amdgpu]
https://bugzilla.kernel.org/show_bug.cgi?id=217872 Bug ID: 217872 Summary: RIP: 0010:amdgpu_vm_pde_update [amdgpu] Product: Drivers Version: 2.5 Hardware: AMD OS: Linux Status: NEW Severity: high Priority: P3 Component: Video(DRI - non Intel) Assignee: drivers_video-...@kernel-bugs.osdl.org Reporter: jrch2...@gmail.com Regression: No [ 2164.137975] [ cut here ] [ 2164.137985] list_del corruption, 88d17d048738->next is LIST_POISON1 (dead0100) [ 2164.138004] WARNING: CPU: 8 PID: 10745 at lib/list_debug.c:55 __list_del_entry_valid+0x89/0xd0 [ 2164.138014] Modules linked in: xt_nat xt_tcpudp veth xt_conntrack nft_chain_nat xt_MASQUERADE nf_nat nf_conntrack_netlink nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 xt_addrtype nft_compat nf_tables nfnetlink br_netfilter bridge stp llc tun rfcomm cmac algif_hash algif_skcipher af_alg bnep snd_seq_dummy snd_hrtimer snd_seq overlay nct6775 nct6775_core hwmon_vid nls_iso8859_1 vfat fat intel_rapl_msr intel_rapl_common x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul joydev polyval_clmulni polyval_generic gf128mul ghash_clmulni_intel snd_hda_codec_realtek sha512_ssse3 iTCO_wdt ath3k aesni_intel btusb snd_hda_codec_generic crypto_simd intel_pmc_bxt cryptd iTCO_vendor_support btintel ledtrig_audio btbcm btrtl rapl snd_hda_codec_hdmi btmtk intel_cstate r8169 snd_hda_intel realtek snd_intel_dspcfg snd_intel_sdw_acpi mdio_devres bluetooth snd_usb_audio psmouse intel_uncore mxm_wmi snd_hda_codec snd_ump pcspkr i2c_i801 ecdh_generic snd_usbmidi_lib rfkill snd_rawmidi i2c_smbus [ 2164.138092] crc16 intel_pch_thermal snd_hda_core libphy lpc_ich snd_seq_device snd_hwdep ioatdma dca mousedev mac_hid dm_multipath snd_aloop snd_pcm snd_timer snd soundcore v4l2loopback_dc(OE) videodev mc fuse crypto_user dm_mod loop ip_tables x_tables usbhid serio_raw atkbd libps2 vivaldi_fmap nvme nvme_core xhci_pci xhci_pci_renesas nvme_common i8042 serio eeprom amdgpu drm_buddy drm_suballoc_helper video wmi drm_ttm_helper ttm i2c_algo_bit gpu_sched amdxcp drm_display_helper cec xfs libcrc32c crc32c_generic crc32c_intel [ 2164.138145] CPU: 8 PID: 10745 Comm: kworker/8:0H Tainted: G D W OE 6.5.1-1-cachyos-lto #1 165231ec090ac1fb173574db6e4d823c96776a31 [ 2164.138150] Hardware name: ATERMITER ZX-99EV3/ZX-99EV3, BIOS X99AT011 10/15/2020 [ 2164.138153] Workqueue: ttm ttm_bo_delayed_delete [ttm] [ 2164.138172] RIP: 0010:__list_del_entry_valid+0x89/0xd0 [ 2164.138177] Code: 31 c0 c3 cc cc cc cc cc 48 c7 c7 3f 3f 64 9b e8 fd 4d 9f ff 0f 0b 31 c0 c3 cc cc cc cc cc 48 c7 c7 5d 3c 6e 9b e8 e7 4d 9f ff <0f> 0b 31 c0 c3 cc cc cc cc cc 48 c7 c7 7a 80 65 9b e8 d1 4d 9f ff [ 2164.138180] RSP: :a1ebca067db8 EFLAGS: 00010246 [ 2164.138183] RAX: a2c219e743f99b00 RBX: 88d17d048720 RCX: 0027 [ 2164.138185] RDX: a1ebca067c98 RSI: 0002 RDI: 88d35fc21708 [ 2164.138188] RBP: R08: 1fff R09: 88d37ff7c680 [ 2164.138190] R10: 5ffd R11: 0004 R12: 88d17d048000 [ 2164.138192] R13: 88cc1130eed0 R14: 88d17d048738 R15: 88d176136000 [ 2164.138194] FS: () GS:88d35fc0() knlGS: [ 2164.138196] CS: 0010 DS: ES: CR0: 80050033 [ 2164.138199] CR2: 256100fce000 CR3: 000349ca8005 CR4: 001706e0 [ 2164.138202] Call Trace: [ 2164.138206] [ 2164.138210] ? __warn+0xcf/0x1c0 [ 2164.138216] ? __list_del_entry_valid+0x89/0xd0 [ 2164.138221] ? report_bug+0x15f/0x200 [ 2164.138228] ? handle_bug+0x42/0x70 [ 2164.138232] ? exc_invalid_op+0x1a/0x50 [ 2164.138235] ? asm_exc_invalid_op+0x1a/0x20 [ 2164.138243] ? __list_del_entry_valid+0x89/0xd0 [ 2164.138247] ? __list_del_entry_valid+0x89/0xd0 [ 2164.138251] amdgpu_vm_bo_relocated+0x35/0xf0 [amdgpu 2f75e5fa96b9ffccc7e67d417353e101c7ac828e] [ 2164.138816] amdgpu_vm_bo_invalidate+0xb7/0x160 [amdgpu 2f75e5fa96b9ffccc7e67d417353e101c7ac828e] [ 2164.139297] amdgpu_bo_move_notify+0x6b/0x120 [amdgpu 2f75e5fa96b9ffccc7e67d417353e101c7ac828e] [ 2164.139789] ttm_bo_delayed_delete+0x58/0xb0 [ttm b5edc8a71b12f4467124bbbdec9e03389e118e3e] [ 2164.139806] process_one_work+0x241/0x440 [ 2164.139812] worker_thread+0x291/0x5e0 [ 2164.139816] ? __pfx_worker_thread+0x10/0x10 [ 2164.139820] kthread+0x14a/0x170 [ 2164.139825] ? __pfx_kthread+0x10/0x10 [ 2164.139829] ret_from_fork+0x37/0x50 [ 2164.139834] ? __pfx_kthread+0x10/0x10 [ 2164.139838] ret_from_fork_asm+0x1b/0x30 [ 2164.139844] [ 2164.139846] ---[ end trace ]--- [ 2164.139922] BUG: kernel NULL pointer dereference, address: 0248 [ 2164.139927] #PF: supervisor read access in kernel mode [ 2164.139929] #PF: error_code(0x) - not-present page [ 2164.139931] PGD 0 P4D 0 [ 2164.139933] Oop
Re: [Intel-xe] [PATCH 2/3] drm/tests/drm_exec: Add a test for object freeing within drm_exec_fini()
Hi, Maxime On 9/5/23 15:16, Maxime Ripard wrote: On Tue, Sep 05, 2023 at 02:32:38PM +0200, Thomas Hellström wrote: Hi, On 9/5/23 14:05, Maxime Ripard wrote: Hi, On Tue, Sep 05, 2023 at 10:58:31AM +0200, Thomas Hellström wrote: Check that object freeing from within drm_exec_fini() works as expected and doesn't generate any warnings. Cc: Christian König Cc: dri-devel@lists.freedesktop.org Signed-off-by: Thomas Hellström --- drivers/gpu/drm/tests/drm_exec_test.c | 47 +++ 1 file changed, 47 insertions(+) diff --git a/drivers/gpu/drm/tests/drm_exec_test.c b/drivers/gpu/drm/tests/drm_exec_test.c index 563949d777dd..294c25f49cc7 100644 --- a/drivers/gpu/drm/tests/drm_exec_test.c +++ b/drivers/gpu/drm/tests/drm_exec_test.c @@ -170,6 +170,52 @@ static void test_prepare_array(struct kunit *test) drm_gem_private_object_fini(&gobj2); } +static const struct drm_gem_object_funcs put_funcs = { + .free = (void *)kfree, +}; + +/* + * Check that freeing objects from within drm_exec_fini() + * behaves as expected. + */ +static void test_early_put(struct kunit *test) +{ + struct drm_exec_priv *priv = test->priv; + struct drm_gem_object *gobj1; + struct drm_gem_object *gobj2; + struct drm_gem_object *array[2]; + struct drm_exec exec; + int ret; + + gobj1 = kzalloc(sizeof(*gobj1), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, gobj1); + if (!gobj1) + return; + + gobj2 = kzalloc(sizeof(*gobj2), GFP_KERNEL); + KUNIT_EXPECT_NOT_ERR_OR_NULL(test, gobj2); + if (!gobj2) { + kfree(gobj1); + return; + } + + gobj1->funcs = &put_funcs; + gobj2->funcs = &put_funcs; + array[0] = gobj1; + array[1] = gobj2; + drm_gem_private_object_init(priv->drm, gobj1, PAGE_SIZE); + drm_gem_private_object_init(priv->drm, gobj2, PAGE_SIZE); + + drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT); + drm_exec_until_all_locked(&exec) + ret = drm_exec_prepare_array(&exec, array, ARRAY_SIZE(array), +1); + KUNIT_EXPECT_EQ(test, ret, 0); + drm_gem_object_put(gobj1); + drm_gem_object_put(gobj2); + drm_exec_fini(&exec); It doesn't look like you actually check that "freeing objects from within drm_exec_fini() behaves as expected." What is the expectation here, and how is it checked? Hm. Good question, I've been manually checking dmesg for lockdep splats. Is there a way to automate that? I'm not familiar with the drm_exec API, but judging by the code I'd assume you want to check that gobj1 and gobj2 are actually freed using kfree? Actually not. What's important here is that the call to drm_exec_fini(), which puts the last references to gobj1 and gobj2 doesn't trigger any lockdep splats, like the one in the commit message of patch 3/3. So to make more sense, the test could perhaps be conditioned on CONFIG_DEBUG_LOCK_ALLOC. Still it would require manual checking of dmesg() after being run. /Thomas
Re: [PATCH v2 2/7] drm: ci: Force db410c to host mode
On Tue, Sep 05, 2023 at 07:06:43PM +0530, Vignesh Raman wrote: > Hi Maxime, > > On 05/09/23 17:27, Maxime Ripard wrote: > > On Tue, Sep 05, 2023 at 05:11:43PM +0530, Vignesh Raman wrote: > > > > > Also, that node actually has a label ("usb"), defined here: > > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/qcom/msm8916.dtsi#n2322 > > > > > > > > > > So you can end up with > > > > > > > > > > &usb { > > > > > dr_mode = "host"; > > > > > }; > > > > > > > > ... which is the simplest and thus more robust one. > > > > > > > > > > Should it be, > > > &{/soc@0/usb} { > > > dr_mode = "host"; > > > }; > > > > No. The &{/...} syntax refers to a path. &... refers to a label. They > > are not equivalent. > > Sorry I was not clear before. > > With, > &usb { > dr_mode = "host"; > }; > > The target is <0x> and fdtoverlay fails to apply the dtbo. You do have /plugin/ and have compiled the base device tree with overlay support, right? > With, > &{/soc@0/usb} { > dr_mode = "host"; > }; > > The target-path is "/soc@0/usb" (usb: usb@78d9000) Right, and that's not the path you want to modify. The path you want to modify is /soc@0/usb@78d9000. usb is the label, it's absolute, and you can't mix and match a path ("/soc@0/") and a label ("usb") Maxime signature.asc Description: PGP signature
Re: [PATCH v2 2/7] drm: ci: Force db410c to host mode
Hi Maxime, On 05/09/23 17:27, Maxime Ripard wrote: On Tue, Sep 05, 2023 at 05:11:43PM +0530, Vignesh Raman wrote: Also, that node actually has a label ("usb"), defined here: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/boot/dts/qcom/msm8916.dtsi#n2322 So you can end up with &usb { dr_mode = "host"; }; ... which is the simplest and thus more robust one. Should it be, &{/soc@0/usb} { dr_mode = "host"; }; No. The &{/...} syntax refers to a path. &... refers to a label. They are not equivalent. Sorry I was not clear before. With, &usb { dr_mode = "host"; }; The target is <0x> and fdtoverlay fails to apply the dtbo. With, &{/soc@0/usb} { dr_mode = "host"; }; The target-path is "/soc@0/usb" (usb: usb@78d9000) / { fragment@0 { target-path = "/soc@0/usb"; __overlay__ { dr_mode = "host"; }; }; }; So will use &{/...} syntax in this case. Regards, Vignesh
Re: [Nouveau] [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
Hi, On 2023/9/5 18:45, Thomas Zimmermann wrote: Hi Am 04.09.23 um 21:57 schrieb Sui Jingfeng: From: Sui Jingfeng On a machine with multiple GPUs, a Linux user has no control over which one is primary at boot time. This series tries to solve above mentioned If anything, the primary graphics adapter is the one initialized by the firmware. I think our boot-up graphics also make this assumption implicitly. Yes, but by the time of DRM drivers get loaded successfully,the boot-up graphics already finished. Firmware framebuffer device already get killed by the drm_aperture_remove_conflicting_pci_framebuffers() function (or its siblings). So, this series is definitely not to interact with the firmware framebuffer (or more intelligent framebuffer drivers). It is for user space program, such as X server and Wayland compositor. Its for Linux user or drm drivers testers, which allow them to direct graphic display server using right hardware of interested as primary video card. Also, I believe that X server and Wayland compositor are the best test examples. If a specific DRM driver can't work with X server as a primary, then there probably have something wrong. But what's the use case for overriding this setting? On a specific machine with multiple GPUs mounted, only the primary graphics get POST-ed (initialized) by the firmware. Therefore, the DRM drivers for the rest video cards, have to choose to work without the prerequisite setups done by firmware, This is called as POST. One of the use cases of this series is to test if a specific DRM driver could works properly, even though there is no prerequisite works have been done by firmware at all. And it seems that the results is not satisfying in all cases. drm/ast is the first drm drivers which refused to work if not being POST-ed by the firmware. Before apply this series, I was unable make drm/ast as the primary video card easily. On a multiple video card configuration, the monitor connected with the AST2400 not light up. While confusing, a naive programmer may suspect the PRIME is not working. After applied this series and passing ast.modeset=10 on the kernel cmd line, I found that the monitor connected with my ast2400 video card still black, It doesn't display and doesn't show image to me. While in the process of study drm/ast, I know that drm/ast driver has the POST code shipped. See the ast_post_gpu() function, then, I was wondering why this function doesn't works. After a short-time (hasty) debugging, I found that the the ast_post_gpu() function didn't get run. Because it have something to do with the ast->config_mode. Without thinking too much, I hardcoded the ast->config_mode as ast_use_p2a to force the ast_post_gpu() function get run. ``` --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -132,6 +132,8 @@ static int ast_device_config_init(struct ast_device *ast) } } + ast->config_mode = ast_use_p2a; + switch (ast->config_mode) { case ast_use_defaults: drm_info(dev, "Using default configuration\n"); ``` Then, the monitor light up, it display the Ubuntu greeter to me. Therefore, my patch is helpful, at lease for the Linux drm driver tester and developer. It allow programmers to test the specific part of the specific drive without changing a line of the source code and without the need of sudo authority. It helps to improve efficiency of the testing and patch verification. I know the PrimaryGPU option of Xorg conf, but this approach will remember the setup have been made, you need modify it with root authority each time you want to switch the primary. But on rapid developing and/or testing multiple video drivers, with only one computer hardware resource available. What we really want probably is a one-shoot command as this series provide. So, this is the first use case. This probably also help to test full modeset, PRIME and reverse PRIME on multiple video card machine. Best regards Thomas
Re: [RFC, drm-misc-next v4 0/9] PCI/VGA: Allowing the user to select the primary video adapter at boot time
Am 05.09.23 um 12:38 schrieb Jani Nikula: On Tue, 05 Sep 2023, Sui Jingfeng wrote: From: Sui Jingfeng On a machine with multiple GPUs, a Linux user has no control over which one is primary at boot time. This series tries to solve above mentioned problem by introduced the ->be_primary() function stub. The specific device drivers can provide an implementation to hook up with this stub by calling the vga_client_register() function. Once the driver bound the device successfully, VGAARB will call back to the device driver. To query if the device drivers want to be primary or not. Device drivers can just pass NULL if have no such needs. Please note that: 1) The ARM64, Loongarch, Mips servers have a lot PCIe slot, and I would like to mount at least three video cards. Well, you rarely find a board which can actually handle a single one :) 2) Typically, those non-86 machines don't have a good UEFI firmware support, which doesn't support select primary GPU as firmware stage. Even on x86, there are old UEFI firmwares which already made undesired decision for you. 3) This series is attempt to solve the remain problems at the driver level, while another series[1] of me is target to solve the majority of the problems at device level. Tested (limited) on x86 with four video card mounted, Intel UHD Graphics 630 is the default boot VGA, successfully override by ast2400 with ast.modeset=10 append at the kernel cmd line. The value 10 is incredibly arbitrary, and multiplied as a magic number all over the place. +1 $ lspci | grep VGA 00:02.0 VGA compatible controller: Intel Corporation CoffeeLake-S GT2 [UHD Graphics 630] 01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Caicos XTX [Radeon HD 8490 / R5 235X OEM] 04:00.0 VGA compatible controller: ASPEED Technology, Inc. ASPEED Graphics Family (rev 30) 05:00.0 VGA compatible controller: NVIDIA Corporation GK208B [GeForce GT 720] (rev a1) In this example, all of the GPUs are driven by different drivers. What good does a module parameter do if you have multiple GPUs of the same model, all driven by the same driver module? Completely agree. Question is what is the benefit for the end user to actually specify this? If you want the initial console on a different device than implement a kernel options for vgaarb and *not* the drivers. Regards, Christian. BR, Jani. $ sudo dmesg | grep vgaarb pci :00:02.0: vgaarb: setting as boot VGA device pci :00:02.0: vgaarb: VGA device added: decodes=io+mem,owns=io+mem,locks=none pci :01:00.0: vgaarb: VGA device added: decodes=io+mem,owns=none,locks=none pci :04:00.0: vgaarb: VGA device added: decodes=io+mem,owns=none,locks=none pci :05:00.0: vgaarb: VGA device added: decodes=io+mem,owns=none,locks=none vgaarb: loaded ast :04:00.0: vgaarb: Override as primary by driver i915 :00:02.0: vgaarb: changed VGA decodes: olddecodes=io+mem,decodes=none:owns=io+mem radeon :01:00.0: vgaarb: changed VGA decodes: olddecodes=io+mem,decodes=none:owns=none ast :04:00.0: vgaarb: changed VGA decodes: olddecodes=io+mem,decodes=none:owns=none v2: * Add a simple implemment for drm/i915 and drm/ast * Pick up all tags (Mario) v3: * Fix a mistake for drm/i915 implement * Fix patch can not be applied problem because of merge conflect. v4: * Focus on solve the real problem. v1,v2 at https://patchwork.freedesktop.org/series/120059/ v3 at https://patchwork.freedesktop.org/series/120562/ [1] https://patchwork.freedesktop.org/series/122845/ Sui Jingfeng (9): PCI/VGA: Allowing the user to select the primary video adapter at boot time drm/nouveau: Implement .be_primary() callback drm/radeon: Implement .be_primary() callback drm/amdgpu: Implement .be_primary() callback drm/i915: Implement .be_primary() callback drm/loongson: Implement .be_primary() callback drm/ast: Register as a VGA client by calling vga_client_register() drm/hibmc: Register as a VGA client by calling vga_client_register() drm/gma500: Register as a VGA client by calling vga_client_register() drivers/gpu/drm/amd/amdgpu/amdgpu_device.c| 11 +++- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 13 - drivers/gpu/drm/ast/ast_drv.c | 31 ++ drivers/gpu/drm/gma500/psb_drv.c | 57 ++- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 15 + drivers/gpu/drm/i915/display/intel_vga.c | 15 - drivers/gpu/drm/loongson/loongson_module.c| 2 +- drivers/gpu/drm/loongson/loongson_module.h| 1 + drivers/gpu/drm/loongson/lsdc_drv.c | 10 +++- drivers/gpu/drm/nouveau/nouveau_vga.c | 11 +++- drivers/gpu/drm/radeon/radeon_device.c| 10 +++- drivers/pci/vgaarb.c | 43 -- drivers/vfio/pci/vfio_pci_core.c | 2 +- include/linux/vga