Commit 82cf435b authored by Lionel Landwerlin's avatar Lionel Landwerlin Committed by Matt Roper

drm/i915: Implement color management on bdw/skl/bxt/kbl

Patch based on a previous series by Shashank Sharma.

v2: Do not read GAMMA_MODE register to figure what mode we're in

v3: Program PREC_PAL_GC_MAX to clamp pixel values > 1.0

    Add documentation on how the Broadcast RGB property is affected by CTM

v4: Update contributors

v5: Refactor degamma/gamma LUTs load into a single function

v6: Fix missing intel_crtc variable (bisect issue)

v7: Fix & simplify limited range matrix multiplication (Matt Roper's
    comment)
Signed-off-by: default avatarShashank Sharma <shashank.sharma@intel.com>
Signed-off-by: default avatarKumar, Kiran S <kiran.s.kumar@intel.com>
Signed-off-by: default avatarKausal Malladi <kausalmalladi@gmail.com>
Signed-off-by: default avatarLionel Landwerlin <lionel.g.landwerlin@intel.com>
Acknowledged-by: default avatarMatt Roper <matthew.d.roper@intel.com>
Signed-off-by: default avatarMatt Roper <matthew.d.roper@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1458125837-2576-4-git-send-email-lionel.g.landwerlin@intel.com
parent 05dc698c
......@@ -2153,7 +2153,11 @@ void intel_crt_init(struct drm_device *dev)
<td valign="top" >ENUM</td>
<td valign="top" >{ "Automatic", "Full", "Limited 16:235" }</td>
<td valign="top" >Connector</td>
<td valign="top" >TBD</td>
<td valign="top" >When this property is set to Limited 16:235
and CTM is set, the hardware will be programmed with the
result of the multiplication of CTM by the limited range
matrix to ensure the pixels normaly in the range 0..1.0 are
remapped to the range 16/255..235/255.</td>
</tr>
<tr>
<td valign="top" >“audio”</td>
......
......@@ -66,6 +66,9 @@ static struct drm_driver driver;
#define IVB_CURSOR_OFFSETS \
.cursor_offsets = { CURSOR_A_OFFSET, IVB_CURSOR_B_OFFSET, IVB_CURSOR_C_OFFSET }
#define BDW_COLORS \
.color = { .degamma_lut_size = 512, .gamma_lut_size = 512 }
static const struct intel_device_info intel_i830_info = {
.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
.has_overlay = 1, .overlay_needs_physical = 1,
......@@ -288,24 +291,28 @@ static const struct intel_device_info intel_haswell_m_info = {
.is_mobile = 1,
};
#define BDW_FEATURES \
HSW_FEATURES, \
BDW_COLORS
static const struct intel_device_info intel_broadwell_d_info = {
HSW_FEATURES,
BDW_FEATURES,
.gen = 8,
};
static const struct intel_device_info intel_broadwell_m_info = {
HSW_FEATURES,
BDW_FEATURES,
.gen = 8, .is_mobile = 1,
};
static const struct intel_device_info intel_broadwell_gt3d_info = {
HSW_FEATURES,
BDW_FEATURES,
.gen = 8,
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
};
static const struct intel_device_info intel_broadwell_gt3m_info = {
HSW_FEATURES,
BDW_FEATURES,
.gen = 8, .is_mobile = 1,
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
};
......@@ -321,13 +328,13 @@ static const struct intel_device_info intel_cherryview_info = {
};
static const struct intel_device_info intel_skylake_info = {
HSW_FEATURES,
BDW_FEATURES,
.is_skylake = 1,
.gen = 9,
};
static const struct intel_device_info intel_skylake_gt3_info = {
HSW_FEATURES,
BDW_FEATURES,
.is_skylake = 1,
.gen = 9,
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
......@@ -345,17 +352,18 @@ static const struct intel_device_info intel_broxton_info = {
.has_fbc = 1,
GEN_DEFAULT_PIPEOFFSETS,
IVB_CURSOR_OFFSETS,
BDW_COLORS,
};
static const struct intel_device_info intel_kabylake_info = {
HSW_FEATURES,
BDW_FEATURES,
.is_preliminary = 1,
.is_kabylake = 1,
.gen = 9,
};
static const struct intel_device_info intel_kabylake_gt3_info = {
HSW_FEATURES,
BDW_FEATURES,
.is_preliminary = 1,
.is_kabylake = 1,
.gen = 9,
......
......@@ -630,6 +630,7 @@ struct drm_i915_display_funcs {
/* display clock increase/decrease */
/* pll clock increase/decrease */
void (*load_csc_matrix)(struct drm_crtc *crtc);
void (*load_luts)(struct drm_crtc *crtc);
};
......@@ -781,6 +782,11 @@ struct intel_device_info {
u8 has_slice_pg:1;
u8 has_subslice_pg:1;
u8 has_eu_pg:1;
struct color_luts {
u16 degamma_lut_size;
u16 gamma_lut_size;
} color;
};
#undef DEFINE_FLAG
......
......@@ -7663,6 +7663,28 @@ enum skl_disp_power_wells {
#define PIPE_CSC_POSTOFF_ME(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME)
#define PIPE_CSC_POSTOFF_LO(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO)
/* pipe degamma/gamma LUTs on IVB+ */
#define _PAL_PREC_INDEX_A 0x4A400
#define _PAL_PREC_INDEX_B 0x4AC00
#define _PAL_PREC_INDEX_C 0x4B400
#define PAL_PREC_10_12_BIT (0 << 31)
#define PAL_PREC_SPLIT_MODE (1 << 31)
#define PAL_PREC_AUTO_INCREMENT (1 << 15)
#define _PAL_PREC_DATA_A 0x4A404
#define _PAL_PREC_DATA_B 0x4AC04
#define _PAL_PREC_DATA_C 0x4B404
#define _PAL_PREC_GC_MAX_A 0x4A410
#define _PAL_PREC_GC_MAX_B 0x4AC10
#define _PAL_PREC_GC_MAX_C 0x4B410
#define _PAL_PREC_EXT_GC_MAX_A 0x4A420
#define _PAL_PREC_EXT_GC_MAX_B 0x4AC20
#define _PAL_PREC_EXT_GC_MAX_C 0x4B420
#define PREC_PAL_INDEX(pipe) _MMIO_PIPE(pipe, _PAL_PREC_INDEX_A, _PAL_PREC_INDEX_B)
#define PREC_PAL_DATA(pipe) _MMIO_PIPE(pipe, _PAL_PREC_DATA_A, _PAL_PREC_DATA_B)
#define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4)
#define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4)
/* MIPI DSI registers */
#define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c) /* ports A and C only */
......
This diff is collapsed.
......@@ -11911,6 +11911,12 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
return ret;
}
if (crtc_state->color_mgmt_changed) {
ret = intel_color_check(crtc, crtc_state);
if (ret)
return ret;
}
ret = 0;
if (dev_priv->display.compute_pipe_wm) {
ret = dev_priv->display.compute_pipe_wm(pipe_config);
......@@ -11953,7 +11959,6 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
static const struct drm_crtc_helper_funcs intel_helper_funcs = {
.mode_set_base_atomic = intel_pipe_set_base_atomic,
.load_lut = intel_color_load_luts,
.atomic_begin = intel_begin_crtc_commit,
.atomic_flush = intel_finish_crtc_commit,
.atomic_check = intel_crtc_atomic_check,
......@@ -13576,6 +13581,18 @@ static int intel_atomic_commit(struct drm_device *dev,
dev_priv->display.crtc_enable(crtc);
}
if (!modeset &&
crtc->state->active &&
crtc->state->color_mgmt_changed) {
/*
* Only update color management when not doing
* a modeset as this will be done by
* crtc_enable already.
*/
intel_color_set_csc(crtc);
intel_color_load_luts(crtc);
}
if (!modeset)
intel_pre_plane_update(to_intel_crtc_state(old_crtc_state));
......@@ -13686,8 +13703,9 @@ void intel_crtc_restore_mode(struct drm_crtc *crtc)
#undef for_each_intel_crtc_masked
static const struct drm_crtc_funcs intel_crtc_funcs = {
.gamma_set = intel_color_legacy_gamma_set,
.gamma_set = drm_atomic_helper_legacy_gamma_set,
.set_config = drm_atomic_helper_set_config,
.set_property = drm_atomic_helper_crtc_set_property,
.destroy = intel_crtc_destroy,
.page_flip = intel_crtc_page_flip,
.atomic_duplicate_state = intel_crtc_duplicate_state,
......
......@@ -1668,9 +1668,8 @@ extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
/* intel_color.c */
void intel_color_init(struct drm_crtc *crtc);
int intel_color_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
void intel_color_set_csc(struct drm_crtc *crtc);
void intel_color_load_luts(struct drm_crtc *crtc);
void intel_color_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t start, uint32_t size);
#endif /* __INTEL_DRV_H__ */
......@@ -379,6 +379,7 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
struct drm_connector *connector;
struct drm_encoder *encoder;
struct drm_fb_helper_crtc *new_crtc;
struct intel_crtc *intel_crtc;
fb_conn = fb_helper->connector_info[i];
connector = fb_conn->connector;
......@@ -420,6 +421,13 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
num_connectors_enabled++;
intel_crtc = to_intel_crtc(connector->state->crtc);
for (j = 0; j < 256; j++) {
intel_crtc->lut_r[j] = j;
intel_crtc->lut_g[j] = j;
intel_crtc->lut_b[j] = j;
}
new_crtc = intel_fb_helper_crtc(fb_helper, connector->state->crtc);
/*
......
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