From: "Leo (Sunpeng) Li" <sunpeng.li@xxxxxxx> Push staged values on the driver-private CRTC, to kernel DRM when it's initialized. This is to flush out any previous state that hardware was in, and set them to their default values. Signed-off-by: Leo (Sunpeng) Li <sunpeng.li at amd.com> --- src/drmmode_display.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 0ffc6ad..85de01e 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -824,6 +824,133 @@ err_allocs: return 0; } +/** + * Query DRM for the property ID - as recognized by DRM - for the specified + * color management property, on the specified CRTC. + * + * @crtc: The CRTC to query DRM properties on. + * @prop_id: Color management property enum. + * + * Return the DRM property ID, if the property exists. 0 otherwise. + */ +static uint32_t get_drm_cm_prop_id(xf86CrtcPtr crtc, + enum drmmode_cm_prop prop_id) +{ + AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmModeObjectPropertiesPtr drm_props; + int i; + + drm_props = drmModeObjectGetProperties(pAMDGPUEnt->fd, + drmmode_crtc->mode_crtc->crtc_id, + DRM_MODE_OBJECT_CRTC); + if (!drm_props) + goto err_allocs; + + for (i = 0; i < drm_props->count_props; i++) { + drmModePropertyPtr drm_prop; + + drm_prop = drmModeGetProperty(pAMDGPUEnt->fd, + drm_props->props[i]); + if (!drm_prop) + goto err_allocs; + + if (get_cm_enum_from_str(drm_prop->name) == prop_id){ + drmModeFreeProperty(drm_prop); + return drm_props->props[i]; + } + + drmModeFreeProperty(drm_prop); + } + +err_allocs: + drmModeFreeObjectProperties(drm_props); + return 0; +} + +/** + * Push staged color management properties on the CRTC to DRM. + * + * @crtc: The CRTC containing staged properties + * @cm_prop_index: The color property to push + * + * Return 0 on success, X-defined error codes on failure. + */ +static int drmmode_crtc_push_cm_prop(xf86CrtcPtr crtc, + enum drmmode_cm_prop cm_prop_index) +{ + AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + size_t expected_bytes = 0; + uint32_t created_blob_id = 0; + void *blob_data = NULL; + uint32_t drm_prop_id; + Bool free_blob_data = FALSE; + int ret; + + drm_prop_id = get_drm_cm_prop_id(crtc, cm_prop_index); + /* It's possible that kernel driver does not support color management. + */ + if (!drm_prop_id) + return BadName; + + if (cm_prop_index == CM_GAMMA_LUT) { + /* Calculate the expected size of value in bytes */ + expected_bytes = sizeof(struct drm_color_lut) * + drmmode_crtc->gamma_lut_size; + blob_data = drmmode_crtc->degamma_lut; + } else if (cm_prop_index == CM_DEGAMMA_LUT) { + expected_bytes = sizeof(struct drm_color_lut) * + drmmode_crtc->degamma_lut_size; + blob_data = drmmode_crtc->degamma_lut; + } else if (cm_prop_index == CM_CTM) { + expected_bytes = sizeof(struct drm_color_ctm); + blob_data = drmmode_crtc->ctm; + } else + return BadName; + + + if (blob_data) { + ret = drmModeCreatePropertyBlob(pAMDGPUEnt->fd, + blob_data, expected_bytes, + &created_blob_id); + if (ret) { + xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, + "Creating DRM blob failed with errno %d\n", + ret); + if (free_blob_data) + free(blob_data); + return BadRequest; + } + } + + ret = drmModeObjectSetProperty(pAMDGPUEnt->fd, + drmmode_crtc->mode_crtc->crtc_id, + DRM_MODE_OBJECT_CRTC, + drm_prop_id, + (uint64_t)created_blob_id); + + /* If successful, kernel will have a reference already. Safe to destroy + * the blob either way. + */ + if (blob_data) + drmModeDestroyPropertyBlob(pAMDGPUEnt->fd, created_blob_id); + + if (ret) { + xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, + "Setting DRM property blob failed with errno %d\n", + ret); + if (free_blob_data) + free(blob_data); + return BadRequest; + } + + if (free_blob_data) + free(blob_data); + + return Success; +} + static void drmmode_crtc_gamma_do_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green, uint16_t *blue, int size) @@ -1433,6 +1560,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res drmmode_crtc_private_ptr drmmode_crtc; AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); AMDGPUInfoPtr info = AMDGPUPTR(pScrn); + int i; crtc = xf86CrtcCreate(pScrn, &info->drmmode_crtc_funcs); if (crtc == NULL) @@ -1458,6 +1586,14 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res drmmode_crtc->ctm->matrix[0] = drmmode_crtc->ctm->matrix[4] = drmmode_crtc->ctm->matrix[8] = (uint64_t)1 << 32; + /* Push properties to initialize them */ + for (i = 0; i < CM_NUM_PROPS; i++) { + if (i == CM_DEGAMMA_LUT_SIZE || i == CM_GAMMA_LUT_SIZE) + continue; + if (drmmode_crtc_push_cm_prop(crtc, i)) + return 0; + } + /* Mark num'th crtc as in use on this device. */ pAMDGPUEnt->assigned_crtcs |= (1 << num); xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, -- 2.7.4