Commit 41ab70e0 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'imx-drm-next-2021-05-12' of git://git.pengutronix.de/git/pza/linux into drm-next

drm/imx: fixes, dma-fence annotation, and color encoding/range plane properties

- Annotate dma-fence critical section in atomic_commit_tail
- Fix PRG modifiers after drmm resource conversion to regain tiled
  scanout capability
- Add 8 pixel alignment fix to support 1366x768 resolution
- Stop advertising YUV formats on planes that don't support them
- Add COLOR_ENCODING and COLOR_RANGE plane properties on planes
  that support them
- Remove unnecessarily exported symbols
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Philipp Zabel <p.zabel@pengutronix.de>
Link: https://patchwork.freedesktop.org/patch/msgid/858310d193e10fc17221418dee6172af367eb046.camel@pengutronix.de
parents 3a3ca726 fc1e985b
...@@ -81,6 +81,7 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -81,6 +81,7 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
struct drm_plane_state *old_plane_state, *new_plane_state; struct drm_plane_state *old_plane_state, *new_plane_state;
bool plane_disabling = false; bool plane_disabling = false;
int i; int i;
bool fence_cookie = dma_fence_begin_signalling();
drm_atomic_helper_commit_modeset_disables(dev, state); drm_atomic_helper_commit_modeset_disables(dev, state);
...@@ -111,6 +112,7 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -111,6 +112,7 @@ static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
} }
drm_atomic_helper_commit_hw_done(state); drm_atomic_helper_commit_hw_done(state);
dma_fence_end_signalling(fence_cookie);
} }
static const struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = { static const struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = {
...@@ -145,9 +147,26 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = { ...@@ -145,9 +147,26 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = {
/* none so far */ /* none so far */
}; };
static int imx_drm_dumb_create(struct drm_file *file_priv,
struct drm_device *drm,
struct drm_mode_create_dumb *args)
{
u32 width = args->width;
int ret;
args->width = ALIGN(width, 8);
ret = drm_gem_cma_dumb_create(file_priv, drm, args);
if (ret)
return ret;
args->width = width;
return ret;
}
static const struct drm_driver imx_drm_driver = { static const struct drm_driver imx_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
DRM_GEM_CMA_DRIVER_OPS, DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(imx_drm_dumb_create),
.ioctls = imx_drm_ioctls, .ioctls = imx_drm_ioctls,
.num_ioctls = ARRAY_SIZE(imx_drm_ioctls), .num_ioctls = ARRAY_SIZE(imx_drm_ioctls),
.fops = &imx_drm_driver_fops, .fops = &imx_drm_driver_fops,
......
...@@ -274,6 +274,11 @@ imx_ldb_encoder_atomic_mode_set(struct drm_encoder *encoder, ...@@ -274,6 +274,11 @@ imx_ldb_encoder_atomic_mode_set(struct drm_encoder *encoder,
"%s: mode exceeds 85 MHz pixel clock\n", __func__); "%s: mode exceeds 85 MHz pixel clock\n", __func__);
} }
if (!IS_ALIGNED(mode->hdisplay, 8)) {
dev_warn(ldb->dev,
"%s: hdisplay does not align to 8 byte\n", __func__);
}
if (dual) { if (dual) {
serial_clk = 3500UL * mode->clock; serial_clk = 3500UL * mode->clock;
imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk); imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk);
......
...@@ -305,10 +305,19 @@ static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc) ...@@ -305,10 +305,19 @@ static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc)
sig_cfg.vsync_pin = imx_crtc_state->di_vsync_pin; sig_cfg.vsync_pin = imx_crtc_state->di_vsync_pin;
drm_display_mode_to_videomode(mode, &sig_cfg.mode); drm_display_mode_to_videomode(mode, &sig_cfg.mode);
if (!IS_ALIGNED(sig_cfg.mode.hactive, 8)) {
unsigned int new_hactive = ALIGN(sig_cfg.mode.hactive, 8);
dev_warn(ipu_crtc->dev, "8-pixel align hactive %d -> %d\n",
sig_cfg.mode.hactive, new_hactive);
sig_cfg.mode.hfront_porch = new_hactive - sig_cfg.mode.hactive;
sig_cfg.mode.hactive = new_hactive;
}
ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di,
mode->flags & DRM_MODE_FLAG_INTERLACE, mode->flags & DRM_MODE_FLAG_INTERLACE,
imx_crtc_state->bus_format, mode->hdisplay); imx_crtc_state->bus_format, sig_cfg.mode.hactive);
ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg); ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg);
} }
......
...@@ -30,12 +30,17 @@ to_ipu_plane_state(struct drm_plane_state *p) ...@@ -30,12 +30,17 @@ to_ipu_plane_state(struct drm_plane_state *p)
return container_of(p, struct ipu_plane_state, base); return container_of(p, struct ipu_plane_state, base);
} }
static unsigned int ipu_src_rect_width(const struct drm_plane_state *state)
{
return ALIGN(drm_rect_width(&state->src) >> 16, 8);
}
static inline struct ipu_plane *to_ipu_plane(struct drm_plane *p) static inline struct ipu_plane *to_ipu_plane(struct drm_plane *p)
{ {
return container_of(p, struct ipu_plane, base); return container_of(p, struct ipu_plane, base);
} }
static const uint32_t ipu_plane_formats[] = { static const uint32_t ipu_plane_all_formats[] = {
DRM_FORMAT_ARGB1555, DRM_FORMAT_ARGB1555,
DRM_FORMAT_XRGB1555, DRM_FORMAT_XRGB1555,
DRM_FORMAT_ABGR1555, DRM_FORMAT_ABGR1555,
...@@ -72,6 +77,31 @@ static const uint32_t ipu_plane_formats[] = { ...@@ -72,6 +77,31 @@ static const uint32_t ipu_plane_formats[] = {
DRM_FORMAT_BGRX8888_A8, DRM_FORMAT_BGRX8888_A8,
}; };
static const uint32_t ipu_plane_rgb_formats[] = {
DRM_FORMAT_ARGB1555,
DRM_FORMAT_XRGB1555,
DRM_FORMAT_ABGR1555,
DRM_FORMAT_XBGR1555,
DRM_FORMAT_RGBA5551,
DRM_FORMAT_BGRA5551,
DRM_FORMAT_ARGB4444,
DRM_FORMAT_ARGB8888,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_RGBA8888,
DRM_FORMAT_RGBX8888,
DRM_FORMAT_BGRA8888,
DRM_FORMAT_BGRX8888,
DRM_FORMAT_RGB565,
DRM_FORMAT_RGB565_A8,
DRM_FORMAT_BGR565_A8,
DRM_FORMAT_RGB888_A8,
DRM_FORMAT_BGR888_A8,
DRM_FORMAT_RGBX8888_A8,
DRM_FORMAT_BGRX8888_A8,
};
static const uint64_t ipu_format_modifiers[] = { static const uint64_t ipu_format_modifiers[] = {
DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID DRM_FORMAT_MOD_INVALID
...@@ -264,7 +294,6 @@ void ipu_plane_disable_deferred(struct drm_plane *plane) ...@@ -264,7 +294,6 @@ void ipu_plane_disable_deferred(struct drm_plane *plane)
ipu_plane_disable(ipu_plane, false); ipu_plane_disable(ipu_plane, false);
} }
} }
EXPORT_SYMBOL_GPL(ipu_plane_disable_deferred);
static void ipu_plane_state_reset(struct drm_plane *plane) static void ipu_plane_state_reset(struct drm_plane *plane)
{ {
...@@ -284,6 +313,8 @@ static void ipu_plane_state_reset(struct drm_plane *plane) ...@@ -284,6 +313,8 @@ static void ipu_plane_state_reset(struct drm_plane *plane)
__drm_atomic_helper_plane_reset(plane, &ipu_state->base); __drm_atomic_helper_plane_reset(plane, &ipu_state->base);
ipu_state->base.zpos = zpos; ipu_state->base.zpos = zpos;
ipu_state->base.normalized_zpos = zpos; ipu_state->base.normalized_zpos = zpos;
ipu_state->base.color_encoding = DRM_COLOR_YCBCR_BT601;
ipu_state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
} }
} }
...@@ -320,10 +351,11 @@ static bool ipu_plane_format_mod_supported(struct drm_plane *plane, ...@@ -320,10 +351,11 @@ static bool ipu_plane_format_mod_supported(struct drm_plane *plane,
if (modifier == DRM_FORMAT_MOD_LINEAR) if (modifier == DRM_FORMAT_MOD_LINEAR)
return true; return true;
/* without a PRG there are no supported modifiers */ /*
if (!ipu_prg_present(ipu)) * Without a PRG the possible modifiers list only includes the linear
return false; * modifier, so we always take the early return from this function and
* only end up here if the PRG is present.
*/
return ipu_prg_format_supported(ipu, format, modifier); return ipu_prg_format_supported(ipu, format, modifier);
} }
...@@ -415,6 +447,12 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, ...@@ -415,6 +447,12 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
if (old_fb && fb->pitches[0] != old_fb->pitches[0]) if (old_fb && fb->pitches[0] != old_fb->pitches[0])
crtc_state->mode_changed = true; crtc_state->mode_changed = true;
if (ALIGN(fb->width, 8) * fb->format->cpp[0] >
fb->pitches[0] + fb->offsets[0]) {
dev_warn(dev, "pitch is not big enough for 8 pixels alignment");
return -EINVAL;
}
switch (fb->format->format) { switch (fb->format->format) {
case DRM_FORMAT_YUV420: case DRM_FORMAT_YUV420:
case DRM_FORMAT_YVU420: case DRM_FORMAT_YVU420:
...@@ -590,12 +628,31 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ...@@ -590,12 +628,31 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
if (ipu_state->use_pre) { if (ipu_state->use_pre) {
axi_id = ipu_chan_assign_axi_id(ipu_plane->dma); axi_id = ipu_chan_assign_axi_id(ipu_plane->dma);
ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id, ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id,
drm_rect_width(&new_state->src) >> 16, ipu_src_rect_width(new_state),
drm_rect_height(&new_state->src) >> 16, drm_rect_height(&new_state->src) >> 16,
fb->pitches[0], fb->format->format, fb->pitches[0], fb->format->format,
fb->modifier, &eba); fb->modifier, &eba);
} }
if (!old_state->fb ||
old_state->fb->format->format != fb->format->format ||
old_state->color_encoding != new_state->color_encoding ||
old_state->color_range != new_state->color_range) {
ics = ipu_drm_fourcc_to_colorspace(fb->format->format);
switch (ipu_plane->dp_flow) {
case IPU_DP_FLOW_SYNC_BG:
ipu_dp_setup_channel(ipu_plane->dp, new_state->color_encoding,
new_state->color_range, ics,
IPUV3_COLORSPACE_RGB);
break;
case IPU_DP_FLOW_SYNC_FG:
ipu_dp_setup_channel(ipu_plane->dp, new_state->color_encoding,
new_state->color_range, ics,
IPUV3_COLORSPACE_UNKNOWN);
break;
}
}
if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) { if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
/* nothing to do if PRE is used */ /* nothing to do if PRE is used */
if (ipu_state->use_pre) if (ipu_state->use_pre)
...@@ -615,17 +672,20 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ...@@ -615,17 +672,20 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
ics = ipu_drm_fourcc_to_colorspace(fb->format->format); ics = ipu_drm_fourcc_to_colorspace(fb->format->format);
switch (ipu_plane->dp_flow) { switch (ipu_plane->dp_flow) {
case IPU_DP_FLOW_SYNC_BG: case IPU_DP_FLOW_SYNC_BG:
ipu_dp_setup_channel(ipu_plane->dp, ics, IPUV3_COLORSPACE_RGB); ipu_dp_setup_channel(ipu_plane->dp, DRM_COLOR_YCBCR_BT601,
DRM_COLOR_YCBCR_LIMITED_RANGE, ics,
IPUV3_COLORSPACE_RGB);
break; break;
case IPU_DP_FLOW_SYNC_FG: case IPU_DP_FLOW_SYNC_FG:
ipu_dp_setup_channel(ipu_plane->dp, ics, ipu_dp_setup_channel(ipu_plane->dp, DRM_COLOR_YCBCR_BT601,
IPUV3_COLORSPACE_UNKNOWN); DRM_COLOR_YCBCR_LIMITED_RANGE, ics,
IPUV3_COLORSPACE_UNKNOWN);
break; break;
} }
ipu_dmfc_config_wait4eot(ipu_plane->dmfc, drm_rect_width(dst)); ipu_dmfc_config_wait4eot(ipu_plane->dmfc, drm_rect_width(dst));
width = drm_rect_width(&new_state->src) >> 16; width = ipu_src_rect_width(new_state);
height = drm_rect_height(&new_state->src) >> 16; height = drm_rect_height(&new_state->src) >> 16;
info = drm_format_info(fb->format->format); info = drm_format_info(fb->format->format);
ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0], ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0],
...@@ -690,7 +750,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ...@@ -690,7 +750,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
ipu_cpmem_zero(ipu_plane->alpha_ch); ipu_cpmem_zero(ipu_plane->alpha_ch);
ipu_cpmem_set_resolution(ipu_plane->alpha_ch, ipu_cpmem_set_resolution(ipu_plane->alpha_ch,
drm_rect_width(&new_state->src) >> 16, ipu_src_rect_width(new_state),
drm_rect_height(&new_state->src) >> 16); drm_rect_height(&new_state->src) >> 16);
ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8); ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8);
ipu_cpmem_set_high_priority(ipu_plane->alpha_ch); ipu_cpmem_set_high_priority(ipu_plane->alpha_ch);
...@@ -821,7 +881,6 @@ int ipu_planes_assign_pre(struct drm_device *dev, ...@@ -821,7 +881,6 @@ int ipu_planes_assign_pre(struct drm_device *dev,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(ipu_planes_assign_pre);
struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
int dma, int dp, unsigned int possible_crtcs, int dma, int dp, unsigned int possible_crtcs,
...@@ -830,16 +889,28 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, ...@@ -830,16 +889,28 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
struct ipu_plane *ipu_plane; struct ipu_plane *ipu_plane;
const uint64_t *modifiers = ipu_format_modifiers; const uint64_t *modifiers = ipu_format_modifiers;
unsigned int zpos = (type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1; unsigned int zpos = (type == DRM_PLANE_TYPE_PRIMARY) ? 0 : 1;
unsigned int format_count;
const uint32_t *formats;
int ret; int ret;
DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n", DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
dma, dp, possible_crtcs); dma, dp, possible_crtcs);
if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG) {
formats = ipu_plane_all_formats;
format_count = ARRAY_SIZE(ipu_plane_all_formats);
} else {
formats = ipu_plane_rgb_formats;
format_count = ARRAY_SIZE(ipu_plane_rgb_formats);
}
if (ipu_prg_present(ipu))
modifiers = pre_format_modifiers;
ipu_plane = drmm_universal_plane_alloc(dev, struct ipu_plane, base, ipu_plane = drmm_universal_plane_alloc(dev, struct ipu_plane, base,
possible_crtcs, &ipu_plane_funcs, possible_crtcs, &ipu_plane_funcs,
ipu_plane_formats, formats, format_count, modifiers,
ARRAY_SIZE(ipu_plane_formats), type, NULL);
modifiers, type, NULL);
if (IS_ERR(ipu_plane)) { if (IS_ERR(ipu_plane)) {
DRM_ERROR("failed to allocate and initialize %s plane\n", DRM_ERROR("failed to allocate and initialize %s plane\n",
zpos ? "overlay" : "primary"); zpos ? "overlay" : "primary");
...@@ -850,9 +921,6 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, ...@@ -850,9 +921,6 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
ipu_plane->dma = dma; ipu_plane->dma = dma;
ipu_plane->dp_flow = dp; ipu_plane->dp_flow = dp;
if (ipu_prg_present(ipu))
modifiers = pre_format_modifiers;
drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs); drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs);
if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG) if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG)
...@@ -864,6 +932,15 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, ...@@ -864,6 +932,15 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
ret = drm_plane_create_color_properties(&ipu_plane->base,
BIT(DRM_COLOR_YCBCR_BT601) |
BIT(DRM_COLOR_YCBCR_BT709),
BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
DRM_COLOR_YCBCR_BT601,
DRM_COLOR_YCBCR_LIMITED_RANGE);
if (ret)
return ERR_PTR(ret);
ret = ipu_plane_get_resources(dev, ipu_plane); ret = ipu_plane_get_resources(dev, ipu_plane);
if (ret) { if (ret) {
DRM_ERROR("failed to get %s plane resources: %pe\n", DRM_ERROR("failed to get %s plane resources: %pe\n",
......
...@@ -167,6 +167,11 @@ int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced, ...@@ -167,6 +167,11 @@ int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
dc->di = ipu_di_get_num(di); dc->di = ipu_di_get_num(di);
if (!IS_ALIGNED(width, 8)) {
dev_warn(priv->dev,
"%s: hactive does not align to 8 byte\n", __func__);
}
map = ipu_bus_format_to_map(bus_format); map = ipu_bus_format_to_map(bus_format);
/* /*
......
...@@ -506,6 +506,13 @@ int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode) ...@@ -506,6 +506,13 @@ int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode)
{ {
u32 diff; u32 diff;
if (!IS_ALIGNED(mode->hactive, 8) &&
mode->hfront_porch < ALIGN(mode->hactive, 8) - mode->hactive) {
dev_err(di->ipu->dev, "hactive %d is not aligned to 8 and front porch is too small to compensate\n",
mode->hactive);
return -EINVAL;
}
if (mode->vfront_porch >= 2) if (mode->vfront_porch >= 2)
return 0; return 0;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/err.h> #include <linux/err.h>
#include <drm/drm_color_mgmt.h>
#include <video/imx-ipu-v3.h> #include <video/imx-ipu-v3.h>
#include "ipu-prv.h" #include "ipu-prv.h"
...@@ -125,6 +126,8 @@ int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos) ...@@ -125,6 +126,8 @@ int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos); EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
static void ipu_dp_csc_init(struct ipu_flow *flow, static void ipu_dp_csc_init(struct ipu_flow *flow,
enum drm_color_encoding ycbcr_enc,
enum drm_color_range range,
enum ipu_color_space in, enum ipu_color_space in,
enum ipu_color_space out, enum ipu_color_space out,
u32 place) u32 place)
...@@ -148,7 +151,18 @@ static void ipu_dp_csc_init(struct ipu_flow *flow, ...@@ -148,7 +151,18 @@ static void ipu_dp_csc_init(struct ipu_flow *flow,
flow->base + DP_CSC_0); flow->base + DP_CSC_0);
writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30), writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
flow->base + DP_CSC_1); flow->base + DP_CSC_1);
} else if (ycbcr_enc == DRM_COLOR_YCBCR_BT709) {
/* Rec.709 limited range */
writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
writel(0x0e5 | (0x095 << 16), flow->base + DP_CSC_A_1);
writel(0x3e5 | (0x3bc << 16), flow->base + DP_CSC_A_2);
writel(0x095 | (0x10e << 16), flow->base + DP_CSC_A_3);
writel(0x000 | (0x3e10 << 16) | (1 << 30),
flow->base + DP_CSC_0);
writel(0x09a | (1 << 14) | (0x3dbe << 16) | (1 << 30),
flow->base + DP_CSC_1);
} else { } else {
/* BT.601 limited range */
writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0); writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1); writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2); writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
...@@ -165,6 +179,8 @@ static void ipu_dp_csc_init(struct ipu_flow *flow, ...@@ -165,6 +179,8 @@ static void ipu_dp_csc_init(struct ipu_flow *flow,
} }
int ipu_dp_setup_channel(struct ipu_dp *dp, int ipu_dp_setup_channel(struct ipu_dp *dp,
enum drm_color_encoding ycbcr_enc,
enum drm_color_range range,
enum ipu_color_space in, enum ipu_color_space in,
enum ipu_color_space out) enum ipu_color_space out)
{ {
...@@ -183,7 +199,8 @@ int ipu_dp_setup_channel(struct ipu_dp *dp, ...@@ -183,7 +199,8 @@ int ipu_dp_setup_channel(struct ipu_dp *dp,
* foreground and background are of same colorspace, put * foreground and background are of same colorspace, put
* colorspace converter after combining unit. * colorspace converter after combining unit.
*/ */
ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs, ipu_dp_csc_init(flow, ycbcr_enc, range,
flow->foreground.in_cs, flow->out_cs,
DP_COM_CONF_CSC_DEF_BOTH); DP_COM_CONF_CSC_DEF_BOTH);
} else { } else {
if (flow->foreground.in_cs == IPUV3_COLORSPACE_UNKNOWN || if (flow->foreground.in_cs == IPUV3_COLORSPACE_UNKNOWN ||
...@@ -192,10 +209,12 @@ int ipu_dp_setup_channel(struct ipu_dp *dp, ...@@ -192,10 +209,12 @@ int ipu_dp_setup_channel(struct ipu_dp *dp,
* foreground identical to output, apply color * foreground identical to output, apply color
* conversion on background * conversion on background
*/ */
ipu_dp_csc_init(flow, flow->background.in_cs, ipu_dp_csc_init(flow, ycbcr_enc, range,
flow->background.in_cs,
flow->out_cs, DP_COM_CONF_CSC_DEF_BG); flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
else else
ipu_dp_csc_init(flow, flow->foreground.in_cs, ipu_dp_csc_init(flow, ycbcr_enc, range,
flow->foreground.in_cs,
flow->out_cs, DP_COM_CONF_CSC_DEF_FG); flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/bitmap.h> #include <linux/bitmap.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/of.h> #include <linux/of.h>
#include <drm/drm_color_mgmt.h>
#include <media/v4l2-mediabus.h> #include <media/v4l2-mediabus.h>
#include <video/videomode.h> #include <video/videomode.h>
...@@ -330,6 +331,7 @@ int ipu_dp_enable_channel(struct ipu_dp *dp); ...@@ -330,6 +331,7 @@ int ipu_dp_enable_channel(struct ipu_dp *dp);
void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync); void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync);
void ipu_dp_disable(struct ipu_soc *ipu); void ipu_dp_disable(struct ipu_soc *ipu);
int ipu_dp_setup_channel(struct ipu_dp *dp, int ipu_dp_setup_channel(struct ipu_dp *dp,
enum drm_color_encoding ycbcr_enc, enum drm_color_range range,
enum ipu_color_space in, enum ipu_color_space out); enum ipu_color_space in, enum ipu_color_space out);
int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos); int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos);
int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha, int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha,
......
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