Commit 086247a4 authored by Leo (Sunpeng) Li's avatar Leo (Sunpeng) Li Committed by Alex Deucher

drm/amd/display: Use 4096 lut entries

Points in the DRM LUT are spaced linearly. Points in hardware are spaced
exponentially, with greater density towards 0. To maintain low-end
accuracy in hardware when sampling the DRM LUT, more points are needed.

However, X doesn't seem to play with legacy LUTs of such size.
Therefore, check for legacy lut when updating DC states, and update
accordingly.

v2: Use a macro for the maximum drm LUT value.

v3: Update commit to reflect that this does not map 1-1 to HW
Signed-off-by: default avatarLeo (Sunpeng) Li <sunpeng.li@amd.com>
Reviewed-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 11fffe45
...@@ -3197,7 +3197,7 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, ...@@ -3197,7 +3197,7 @@ static int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
dm->adev->mode_info.crtcs[crtc_index] = acrtc; dm->adev->mode_info.crtcs[crtc_index] = acrtc;
drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES, drm_crtc_enable_color_mgmt(&acrtc->base, MAX_COLOR_LUT_ENTRIES,
true, MAX_COLOR_LUT_ENTRIES); true, MAX_COLOR_LUT_ENTRIES);
drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LUT_ENTRIES); drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES);
return 0; return 0;
......
...@@ -268,7 +268,9 @@ void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc); ...@@ -268,7 +268,9 @@ void amdgpu_dm_crtc_handle_crc_irq(struct drm_crtc *crtc);
#define amdgpu_dm_crtc_handle_crc_irq(x) #define amdgpu_dm_crtc_handle_crc_irq(x)
#endif #endif
#define MAX_COLOR_LUT_ENTRIES 256 #define MAX_COLOR_LUT_ENTRIES 4096
/* Legacy gamm LUT users such as X doesn't like large LUT sizes */
#define MAX_COLOR_LEGACY_LUT_ENTRIES 256
void amdgpu_dm_init_color_mod(void); void amdgpu_dm_init_color_mod(void);
int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state, int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state,
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include "amdgpu_dm.h" #include "amdgpu_dm.h"
#include "modules/color/color_gamma.h" #include "modules/color/color_gamma.h"
#define MAX_DRM_LUT_VALUE 0xFFFF
/* /*
* Initialize the color module. * Initialize the color module.
* *
...@@ -47,19 +49,18 @@ void amdgpu_dm_init_color_mod(void) ...@@ -47,19 +49,18 @@ void amdgpu_dm_init_color_mod(void)
* f(a) = (0xFF00/MAX_COLOR_LUT_ENTRIES-1)a; for integer a in * f(a) = (0xFF00/MAX_COLOR_LUT_ENTRIES-1)a; for integer a in
* [0, MAX_COLOR_LUT_ENTRIES) * [0, MAX_COLOR_LUT_ENTRIES)
*/ */
static bool __is_lut_linear(struct drm_color_lut *lut) static bool __is_lut_linear(struct drm_color_lut *lut, uint32_t size)
{ {
int i; int i;
uint32_t max_os = 0xFF00;
uint32_t expected; uint32_t expected;
int delta; int delta;
for (i = 0; i < MAX_COLOR_LUT_ENTRIES; i++) { for (i = 0; i < size; i++) {
/* All color values should equal */ /* All color values should equal */
if ((lut[i].red != lut[i].green) || (lut[i].green != lut[i].blue)) if ((lut[i].red != lut[i].green) || (lut[i].green != lut[i].blue))
return false; return false;
expected = i * max_os / (MAX_COLOR_LUT_ENTRIES-1); expected = i * MAX_DRM_LUT_VALUE / (size-1);
/* Allow a +/-1 error. */ /* Allow a +/-1 error. */
delta = lut[i].red - expected; delta = lut[i].red - expected;
...@@ -69,6 +70,42 @@ static bool __is_lut_linear(struct drm_color_lut *lut) ...@@ -69,6 +70,42 @@ static bool __is_lut_linear(struct drm_color_lut *lut)
return true; return true;
} }
/**
* Convert the drm_color_lut to dc_gamma. The conversion depends on the size
* of the lut - whether or not it's legacy.
*/
static void __drm_lut_to_dc_gamma(struct drm_color_lut *lut,
struct dc_gamma *gamma,
bool is_legacy)
{
uint32_t r, g, b;
int i;
if (is_legacy) {
for (i = 0; i < MAX_COLOR_LEGACY_LUT_ENTRIES; i++) {
r = drm_color_lut_extract(lut[i].red, 16);
g = drm_color_lut_extract(lut[i].green, 16);
b = drm_color_lut_extract(lut[i].blue, 16);
gamma->entries.red[i] = dal_fixed31_32_from_int(r);
gamma->entries.green[i] = dal_fixed31_32_from_int(g);
gamma->entries.blue[i] = dal_fixed31_32_from_int(b);
}
return;
}
/* else */
for (i = 0; i < MAX_COLOR_LUT_ENTRIES; i++) {
r = drm_color_lut_extract(lut[i].red, 16);
g = drm_color_lut_extract(lut[i].green, 16);
b = drm_color_lut_extract(lut[i].blue, 16);
gamma->entries.red[i] = dal_fixed31_32_from_fraction(r, MAX_DRM_LUT_VALUE);
gamma->entries.green[i] = dal_fixed31_32_from_fraction(g, MAX_DRM_LUT_VALUE);
gamma->entries.blue[i] = dal_fixed31_32_from_fraction(b, MAX_DRM_LUT_VALUE);
}
}
/** /**
* amdgpu_dm_set_regamma_lut: Set regamma lut for the given CRTC. * amdgpu_dm_set_regamma_lut: Set regamma lut for the given CRTC.
* @crtc: amdgpu_dm crtc state * @crtc: amdgpu_dm crtc state
...@@ -85,11 +122,10 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc) ...@@ -85,11 +122,10 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc)
struct drm_property_blob *blob = crtc->base.gamma_lut; struct drm_property_blob *blob = crtc->base.gamma_lut;
struct dc_stream_state *stream = crtc->stream; struct dc_stream_state *stream = crtc->stream;
struct drm_color_lut *lut; struct drm_color_lut *lut;
uint32_t lut_size;
struct dc_gamma *gamma; struct dc_gamma *gamma;
enum dc_transfer_func_type old_type = stream->out_transfer_func->type; enum dc_transfer_func_type old_type = stream->out_transfer_func->type;
uint32_t r, g, b;
int i;
bool ret; bool ret;
if (!blob) { if (!blob) {
...@@ -100,8 +136,9 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc) ...@@ -100,8 +136,9 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc)
} }
lut = (struct drm_color_lut *)blob->data; lut = (struct drm_color_lut *)blob->data;
lut_size = blob->length / sizeof(struct drm_color_lut);
if (__is_lut_linear(lut)) { if (__is_lut_linear(lut, lut_size)) {
/* Set to bypass if lut is set to linear */ /* Set to bypass if lut is set to linear */
stream->out_transfer_func->type = TF_TYPE_BYPASS; stream->out_transfer_func->type = TF_TYPE_BYPASS;
stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; stream->out_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
...@@ -112,20 +149,20 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc) ...@@ -112,20 +149,20 @@ int amdgpu_dm_set_regamma_lut(struct dm_crtc_state *crtc)
if (!gamma) if (!gamma)
return -ENOMEM; return -ENOMEM;
gamma->num_entries = MAX_COLOR_LUT_ENTRIES; gamma->num_entries = lut_size;
gamma->type = GAMMA_RGB_256; if (gamma->num_entries == MAX_COLOR_LEGACY_LUT_ENTRIES)
gamma->type = GAMMA_RGB_256;
/* Truncate, and store in dc_gamma for output tf calculation */ else if (gamma->num_entries == MAX_COLOR_LUT_ENTRIES)
for (i = 0; i < gamma->num_entries; i++) { gamma->type = GAMMA_CS_TFM_1D;
r = drm_color_lut_extract(lut[i].red, 16); else {
g = drm_color_lut_extract(lut[i].green, 16); /* Invalid lut size */
b = drm_color_lut_extract(lut[i].blue, 16); dc_gamma_release(&gamma);
return -EINVAL;
gamma->entries.red[i] = dal_fixed31_32_from_int(r);
gamma->entries.green[i] = dal_fixed31_32_from_int(g);
gamma->entries.blue[i] = dal_fixed31_32_from_int(b);
} }
/* Convert drm_lut into dc_gamma */
__drm_lut_to_dc_gamma(lut, gamma, gamma->type == GAMMA_RGB_256);
/* Call color module to translate into something DC understands. Namely /* Call color module to translate into something DC understands. Namely
* a transfer function. * a transfer function.
*/ */
...@@ -212,7 +249,7 @@ int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state, ...@@ -212,7 +249,7 @@ int amdgpu_dm_set_degamma_lut(struct drm_crtc_state *crtc_state,
} }
lut = (struct drm_color_lut *)blob->data; lut = (struct drm_color_lut *)blob->data;
if (__is_lut_linear(lut)) { if (__is_lut_linear(lut, MAX_COLOR_LUT_ENTRIES)) {
dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS; dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS;
dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR;
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment