diff options
Diffstat (limited to 'drivers/gpu/ipu-v3/ipu-dp.c')
| -rw-r--r-- | drivers/gpu/ipu-v3/ipu-dp.c | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-dp.c b/drivers/gpu/ipu-v3/ipu-dp.c index 9b2b3fa479c4..6a558205db96 100644 --- a/drivers/gpu/ipu-v3/ipu-dp.c +++ b/drivers/gpu/ipu-v3/ipu-dp.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de> * Copyright (C) 2005-2009 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. */ #include <linux/export.h> #include <linux/kernel.h> @@ -19,6 +10,7 @@ #include <linux/io.h> #include <linux/err.h> +#include <drm/drm_color_mgmt.h> #include <video/imx-ipu-v3.h> #include "ipu-prv.h" @@ -134,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); 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 out, u32 place) @@ -157,7 +151,18 @@ static void ipu_dp_csc_init(struct ipu_flow *flow, flow->base + DP_CSC_0); writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30), 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 { + /* BT.601 limited range */ writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0); writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1); writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2); @@ -174,6 +179,8 @@ static void ipu_dp_csc_init(struct ipu_flow *flow, } 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) { @@ -192,18 +199,22 @@ int ipu_dp_setup_channel(struct ipu_dp *dp, * foreground and background are of same colorspace, put * 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); } else { - if (flow->foreground.in_cs == flow->out_cs) + if (flow->foreground.in_cs == IPUV3_COLORSPACE_UNKNOWN || + flow->foreground.in_cs == flow->out_cs) /* * foreground identical to output, apply color * 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); 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); } @@ -261,6 +272,8 @@ void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync) struct ipu_dp_priv *priv = flow->priv; u32 reg, csc; + dp->in_cs = IPUV3_COLORSPACE_UNKNOWN; + if (!dp->foreground) return; @@ -268,8 +281,9 @@ void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync) reg = readl(flow->base + DP_COM_CONF); csc = reg & DP_COM_CONF_CSC_DEF_MASK; - if (csc == DP_COM_CONF_CSC_DEF_FG) - reg &= ~DP_COM_CONF_CSC_DEF_MASK; + reg &= ~DP_COM_CONF_CSC_DEF_MASK; + if (csc == DP_COM_CONF_CSC_DEF_BOTH || csc == DP_COM_CONF_CSC_DEF_BG) + reg |= DP_COM_CONF_CSC_DEF_BG; reg &= ~DP_COM_CONF_FG_EN; writel(reg, flow->base + DP_COM_CONF); @@ -347,6 +361,8 @@ int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base) mutex_init(&priv->mutex); for (i = 0; i < IPUV3_NUM_FLOWS; i++) { + priv->flow[i].background.in_cs = IPUV3_COLORSPACE_UNKNOWN; + priv->flow[i].foreground.in_cs = IPUV3_COLORSPACE_UNKNOWN; priv->flow[i].foreground.foreground = true; priv->flow[i].base = priv->base + ipu_dp_flow_base[i]; priv->flow[i].priv = priv; |
