mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
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: Leo (Sunpeng) Li <sunpeng.li@amd.com> Reviewed-by: Harry Wentland <Harry.Wentland@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
11fffe45b7
commit
086247a4b2
|
|
@ -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);
|
||||||
#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 @@
|
||||||
#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)
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
if (!gamma)
|
if (!gamma)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
gamma->num_entries = MAX_COLOR_LUT_ENTRIES;
|
gamma->num_entries = lut_size;
|
||||||
|
if (gamma->num_entries == MAX_COLOR_LEGACY_LUT_ENTRIES)
|
||||||
gamma->type = GAMMA_RGB_256;
|
gamma->type = GAMMA_RGB_256;
|
||||||
|
else if (gamma->num_entries == MAX_COLOR_LUT_ENTRIES)
|
||||||
/* Truncate, and store in dc_gamma for output tf calculation */
|
gamma->type = GAMMA_CS_TFM_1D;
|
||||||
for (i = 0; i < gamma->num_entries; i++) {
|
else {
|
||||||
r = drm_color_lut_extract(lut[i].red, 16);
|
/* Invalid lut size */
|
||||||
g = drm_color_lut_extract(lut[i].green, 16);
|
dc_gamma_release(&gamma);
|
||||||
b = drm_color_lut_extract(lut[i].blue, 16);
|
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user