@@ -9410,7 +9410,12 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
*/
if (dm_new_crtc_state->base.color_mgmt_changed ||
drm_atomic_crtc_needs_modeset(new_crtc_state)) {
- ret = amdgpu_dm_update_crtc_color_mgmt(dm_new_crtc_state);
+ if (!dm_state) {
+ ret = dm_atomic_get_state(state, &dm_state);
+ if (ret)
+ goto fail;
+ }
+ ret = amdgpu_dm_update_crtc_color_mgmt(dm_new_crtc_state, dm_state->context);
if (ret)
goto fail;
}
@@ -875,7 +875,8 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
void amdgpu_dm_init_color_mod(void);
int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state);
-int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc);
+int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc,
+ struct dc_state *ctx);
int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
struct dc_plane_state *dc_plane_state);
@@ -364,6 +364,49 @@ static int __set_input_tf(struct dc_transfer_func *func,
return res ? 0 : -ENOMEM;
}
+/* amdgpu_dm_atomic_shaper_lut3d - set DRM CRTC shaper LUT and 3D LUT to DC
+ * interface
+ * @dc: Display Core control structure
+ * @ctx: new DC state information
+ * @stream: DC stream state to set shaper LUT and 3D LUT
+ * @drm_shaper_lut: DRM CRTC (user) shaper LUT
+ * @drm_shaper_size: size of shaper LUT
+ * @drm_lut3d: DRM CRTC (user) 3D LUT
+ * @drm_lut3d_size: size of 3D LUT
+ *
+ * Returns:
+ * 0 on success.
+ */
+static int amdgpu_dm_atomic_shaper_lut3d(struct dc *dc,
+ struct dc_state *ctx,
+ struct dc_stream_state *stream,
+ const struct drm_color_lut *drm_shaper_lut,
+ uint32_t drm_shaper_size,
+ const struct drm_color_lut *drm_lut3d,
+ uint32_t drm_lut3d_size)
+{
+ struct dc_3dlut *lut3d_func;
+ struct dc_transfer_func *func_shaper;
+ bool acquire = drm_shaper_size || drm_lut3d_size;
+
+ lut3d_func = (struct dc_3dlut *)stream->lut3d_func;
+ func_shaper = (struct dc_transfer_func *)stream->func_shaper;
+
+ ASSERT((lut3d_func && func_shaper) || (!lut3d_func && !func_shaper));
+ if ((acquire && !lut3d_func && !func_shaper) ||
+ (!acquire && lut3d_func && func_shaper))
+ {
+ if (!dc_acquire_release_mpc_3dlut_for_ctx(dc, acquire, ctx, stream,
+ &lut3d_func, &func_shaper))
+ return DC_ERROR_UNEXPECTED;
+ }
+
+ stream->func_shaper = func_shaper;
+ stream->lut3d_func = lut3d_func;
+
+ return 0;
+}
+
/**
* amdgpu_dm_verify_lut_sizes - verifies if DRM luts match the hw supported sizes
* @crtc_state: the DRM CRTC state
@@ -403,6 +446,7 @@ int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state)
/**
* amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream.
* @crtc: amdgpu_dm crtc state
+ * @ctx: new DC state information
*
* With no plane level color management properties we're free to use any
* of the HW blocks as long as the CRTC CTM always comes before the
@@ -422,7 +466,8 @@ int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state)
* Returns:
* 0 on success. Error code if setup fails.
*/
-int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc)
+int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc,
+ struct dc_state *ctx)
{
struct dc_stream_state *stream = crtc->stream;
struct amdgpu_device *adev = drm_to_adev(crtc->base.state->dev);
@@ -481,6 +526,14 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc)
if (r)
return r;
} else {
+ r = amdgpu_dm_atomic_shaper_lut3d(adev->dm.dc, ctx, stream,
+ NULL, 0, NULL, 0);
+ if (r)
+ return r;
+ /* Note: OGAM is disabled if 3D LUT is successfully programmed.
+ * See params and set_output_gamma in
+ * dcn30_set_output_transfer_func()
+ */
regamma_size = has_regamma ? regamma_size : 0;
r = amdgpu_dm_set_atomic_regamma(stream, regamma_lut,
regamma_size, has_rom);
@@ -1258,6 +1258,30 @@ static struct display_stream_compressor *dcn301_dsc_create(
return &dsc->base;
}
+static enum dc_status
+dcn301_remove_stream_from_ctx(struct dc *dc,
+ struct dc_state *new_ctx,
+ struct dc_stream_state *dc_stream)
+{
+ struct dc_3dlut *lut3d_func;
+ struct dc_transfer_func *func_shaper;
+
+ lut3d_func = (struct dc_3dlut *)dc_stream->lut3d_func;
+ func_shaper = (struct dc_transfer_func *)dc_stream->func_shaper;
+
+ ASSERT((lut3d_func && func_shaper) || (!lut3d_func && !func_shaper));
+ if (lut3d_func && func_shaper)
+ {
+ if (!dc_acquire_release_mpc_3dlut_for_ctx(dc, false, new_ctx, dc_stream,
+ &lut3d_func, &func_shaper))
+ return DC_ERROR_UNEXPECTED;
+ }
+
+ dc_stream->lut3d_func = lut3d_func;
+ dc_stream->func_shaper = func_shaper;
+
+ return dcn20_remove_stream_from_ctx(dc, new_ctx, dc_stream);
+}
static void dcn301_destroy_resource_pool(struct resource_pool **pool)
{
@@ -1406,7 +1430,7 @@ static struct resource_funcs dcn301_res_pool_funcs = {
.acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
.add_stream_to_ctx = dcn30_add_stream_to_ctx,
.add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
- .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
+ .remove_stream_from_ctx = dcn301_remove_stream_from_ctx,
.populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context,
.set_mcif_arb_params = dcn30_set_mcif_arb_params,
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,