summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_rm_emulation.c171
1 files changed, 167 insertions, 4 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index d43333f..48e91dd 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -2197,11 +2197,19 @@ static void gsp_rm_handle_display_get_ip_version(struct gsp_emu_context *ctx,
* displayMask=1|DDC=1, SPECIFIC_OR_GET_INFO (0x73028b) SOR /
* SOR_SINGLE_TMDS_A (TMDS avoids the whole DP-AUX lib), SPECIFIC_
* GET_CONNECTOR_DATA (0x730250) one HDMI_A entry, DFP_GET_INFO (0x731140)
- * TMDS flags. Still a headless setup: no connect state or EDID is claimed
- * (those are modeset-time queries).
+ * TMDS flags.
+ *
+ * r1617: the connector was still reported disconnected. NVKMS
+ * nvRmGetConnectedDpys() polls SYSTEM_GET_CONNECT_STATE (0x730108) and a zero
+ * displayMask makes it see no displays; the driver then sets the NoScanout
+ * NULL mode and the NVKMS deferred display close bumps the shared nvClip
+ * modeNum past the GL client's mode-switch test (which requires bit0 clear).
+ * Report display 0 connected, its type as DFP (0x730240) and a 600 MHz pclk
+ * limit (0x73028a); the SOR caps seed already gives 600 MHz TMDS. The EDID
+ * itself is served by gsp_rm_handle_display_get_edid() (0x730245).
*/
static void gsp_rm_handle_display_heads(struct gsp_emu_context *ctx, u32 cmd,
- u32 req_size,
+ u32 req_size, const u8 *req_params,
u32 *out_status, u8 *out_params,
u32 *out_params_size)
{
@@ -2234,6 +2242,39 @@ static void gsp_rm_handle_display_heads(struct gsp_emu_context *ctx, u32 cmd,
memcpy(out_params + 8, &one, 4);
}
break;
+ case 0x730108: /* SYSTEM_GET_CONNECT_STATE: {subDev, flags,
+ * displayMask, retryTimeMs} - report the requested
+ * display 0 connected (NVKMS polls this ~126x while
+ * opening the display; zero made it set NoScanout). */
+ if (sz >= 16) {
+ u32 mask = 0;
+
+ if (req_params)
+ memcpy(&mask, req_params + 8, 4);
+ mask &= 1;
+ if (!mask)
+ mask = 1;
+ memcpy(out_params + 8, &mask, 4);
+ }
+ break;
+ case 0x730240: /* SPECIFIC_GET_TYPE: {subDev, displayId,
+ * displayType} - display 0 is our static DFP. */
+ if (sz >= 12) {
+ v = 2; /* NV0073_CTRL_SPECIFIC_DISPLAY_TYPE_DFP */
+ memcpy(out_params + 8, &v, 4);
+ }
+ break;
+ case 0x73028a: /* SPECIFIC_GET_PCLK_LIMIT: {subDev, displayId,
+ * pclkLimit, orPclkLimit, vbPclkLimit} in kHz. The
+ * TMDS SOR caps (600 MHz) are the real limit; a sane
+ * RM value also keeps non-TMDS validation working. */
+ if (sz >= 20) {
+ v = 600000;
+ memcpy(out_params + 8, &v, 4);
+ memcpy(out_params + 12, &v, 4);
+ memcpy(out_params + 16, &v, 4);
+ }
+ break;
case 0x73028b: /* SPECIFIC_OR_GET_INFO: {subDev, displayId, index,
* type, protocol, ditherType, ditherAlgo, location,
* rootPortId, dcbIndex, vbiosAddress, bIsLitByVbios,
@@ -2261,6 +2302,24 @@ static void gsp_rm_handle_display_heads(struct gsp_emu_context *ctx, u32 cmd,
/* data[0].location = 0 */
}
break;
+ case 0x73010b: /* SYSTEM_GET_HEAD_ROUTING_MAP: {subDev,
+ * displayMask, oldDisplayMask, oldHeadRoutingMap,
+ * headRoutingMap} - the generic zero reply dropped
+ * displayMask (0), so the boot display init's head-
+ * routing step saw no display. Keep display 0 routed
+ * to head 0 (headRoutingMap=0). */
+ if (sz >= 20) {
+ u32 mask = 0;
+
+ if (req_params)
+ memcpy(&mask, req_params + 4, 4);
+ mask &= 1;
+ if (!mask)
+ mask = 1;
+ memcpy(out_params + 4, &mask, 4);
+ /* headRoutingMap stays 0: display 0 -> head 0 */
+ }
+ break;
case 0x731140: /* DFP_GET_INFO: {subDev, displayId, flags,
* UHBRSupportedByDfp} - flags signal bits = TMDS(0) */
break; /* zeros are the TMDS signal value */
@@ -2273,6 +2332,66 @@ static void gsp_rm_handle_display_heads(struct gsp_emu_context *ctx, u32 cmd,
}
/*
+ * NV0073_CTRL_CMD_SPECIFIC_GET_EDID_V2 (0x730245)
+ *
+ * nvidia-modeset's ReadEdidFromResman() reads the display EDID through this
+ * control, not through the I2C_TRANSACTION (0x402c0105) path. A zero or
+ * invalid reply leaves the DFP with no modes, so the driver falls back to
+ * the NoScanout NULL mode and the NVKMS deferred close bumps the shared
+ * nvClip modeNum. Serve a 128-byte EDID 1.3 base block with a 1920x1080@60
+ * detailed timing plus the 640x480/800x600/1024x768 established timings
+ * (checksum valid, no extension block).
+ *
+ * Params (NV0073_CTRL_SPECIFIC_GET_EDID_V2_PARAMS): subDeviceInstance@0,
+ * displayId@4, bufferSize@8, flags@12, edidBuffer@16[2048]. Echo the whole
+ * request and patch bufferSize + edidBuffer (the request is zero-initialized
+ * by the caller; the reply must stay the same serialized length).
+ */
+static void gsp_rm_handle_display_get_edid(struct gsp_emu_context *ctx,
+ u32 req_size,
+ const u8 *req_params,
+ u32 *out_status,
+ u8 *out_params,
+ u32 *out_params_size)
+{
+ static const u8 edid[128] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x3a, 0xc4, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x22, 0x01, 0x03, 0x80, 0x33, 0x1d, 0x78,
+ 0x0a, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26,
+ 0x0f, 0x50, 0x54, 0x21, 0x08, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a,
+ 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+ 0x45, 0x00, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1a,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
+ 0x4b, 0x1e, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ };
+ u32 buffer_size = sizeof(edid);
+ u32 display_id = 0;
+
+ if (!req_params || req_size < 16) {
+ *out_params_size = 0;
+ *out_status = 0x1; /* NV_ERR_INVALID_ARGUMENT */
+ return;
+ }
+ memcpy(out_params, req_params, req_size);
+ memcpy(out_params + 8, &buffer_size, 4);
+ memcpy(out_params + 16, edid, sizeof(edid));
+ memcpy(&display_id, out_params + 4, 4);
+ *out_params_size = req_size;
+ *out_status = 0;
+ nv_vgpu_info(ctx->vgpu,
+ "vgsp-rm: GET_EDID_V2 displayId=%u -> %u-byte EDID (1920x1080@60)",
+ display_id, buffer_size);
+}
+
+/*
* CE_GET_FAULT_METHOD_BUFFER_SIZE (0x20802a08)
*
* kchangrpInit allocates one fault method buffer per runqueue of this
@@ -3283,7 +3402,7 @@ static void gsp_rm_handle_rm_alloc(struct gsp_emu_context *ctx,
* classified yet (rate-limited). %phN is capped at 64 bytes per print,
* so chunk it. */
if (gsp_sema_dbg && gsp_rm_alloc_interesting(class_id) &&
- rm->alloc_param_dumps < 60) {
+ rm->alloc_param_dumps < 500) {
u32 shown = min(params_size, (u32)384);
u32 off;
@@ -4264,14 +4383,58 @@ static void gsp_rm_handle_rm_control(struct gsp_emu_context *ctx,
case 0x730287: /* NV0073_CTRL_CMD_SPECIFIC_GET_ALL_HEAD_MASK */
case 0x7302ad: /* NV0073_CTRL_CMD_SPECIFIC_GET_VALID_HEAD_WINDOW_ASSIGNMENT */
case 0x730107: /* NV0073_CTRL_CMD_SYSTEM_GET_SUPPORTED */
+ case 0x730108: /* NV0073_CTRL_CMD_SYSTEM_GET_CONNECT_STATE */
+ case 0x730240: /* NV0073_CTRL_CMD_SPECIFIC_GET_TYPE */
+ case 0x73028a: /* NV0073_CTRL_CMD_SPECIFIC_GET_PCLK_LIMIT */
case 0x73028b: /* NV0073_CTRL_CMD_SPECIFIC_OR_GET_INFO */
case 0x730250: /* NV0073_CTRL_CMD_SPECIFIC_GET_CONNECTOR_DATA */
+ case 0x73010b: /* NV0073_CTRL_CMD_SYSTEM_GET_HEAD_ROUTING_MAP */
case 0x731140: /* NV0073_CTRL_CMD_DFP_GET_INFO */
gsp_rm_handle_display_heads(ctx, req.cmd, req.paramsSize,
+ req_data + GSP_RM_CTRL_HDR_SIZE,
&out_status,
reply + GSP_RM_CTRL_HDR_SIZE, &out_params_size);
break;
+ case 0x730245: /* NV0073_CTRL_CMD_SPECIFIC_GET_EDID_V2 */
+ gsp_rm_handle_display_get_edid(ctx, req.paramsSize,
+ req_data + GSP_RM_CTRL_HDR_SIZE,
+ &out_status,
+ reply + GSP_RM_CTRL_HDR_SIZE, &out_params_size);
+ break;
+
+ case 0xc3720101: { /* NVC372_CTRL_CMD_IS_MODE_POSSIBLE (IMP) */
+ /*
+ * nvidia-modeset's GPU IMP check: 2048-byte params
+ * (NVC372_CTRL_IS_MODE_POSSIBLE_PARAMS) with the mode inputs
+ * and the bIsPossible answer at byte offset 1904 (NvBool is
+ * one byte). The caller memsets the struct before filling
+ * the inputs, so echoing the request and flipping
+ * bIsPossible is coherent. The generic zero reply answered
+ * "not possible", which made every EDID mode fail with
+ * "GPU extended capability check failed" before any mode set.
+ */
+ u8 *rp = reply + GSP_RM_CTRL_HDR_SIZE;
+ const u8 *pp = req_data + GSP_RM_CTRL_HDR_SIZE;
+
+ if (req.paramsSize >= 1905 &&
+ req.paramsSize <= GSPRM_MAX_SINGLE_ELEM_DATA) {
+ memcpy(rp, pp, req.paramsSize);
+ rp[1904] = 1; /* bIsPossible */
+ out_params_size = req.paramsSize;
+ } else {
+ out_params_size = 0;
+ }
+ if (gsp_sema_dbg)
+ nv_vgpu_info(ctx->vgpu,
+ "vgsp-rm: IS_MODE_POSSIBLE in=%u -> possible (heads=%u windows=%u)",
+ req.paramsSize,
+ req.paramsSize > 5 ? pp[4] : 0,
+ req.paramsSize > 5 ? pp[5] : 0);
+ out_status = 0;
+ break;
+ }
+
case TU104_CTRL_CE_GET_FAULT_METHOD_BUFFER_SIZE:
gsp_rm_handle_ce_get_fault_method_buffer_size(ctx, sequence,
&out_status,