summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Kwong <akwong@codeaurora.org>2016-07-29 03:06:44 -0400
committerAlan Kwong <akwong@codeaurora.org>2016-08-04 11:39:30 -0400
commitb05a124d2f5bcdb699adad308a5a90c91faca889 (patch)
treef17aebad5a681fd54bdabe19c1a6479ab9fd0685
parent95095bdaa2c897890c63b591a1037b8498f92ddf (diff)
drm/msm/sde: add hardware driver support for chroma down module
Chroma down module is used to perform color space conversion and downsampling of luma/chroma components. This patch adds support for chroma down hardware driver to control the hardware block using hardware abstraction api common across families of hardware. Change-Id: Ic7f420572d06b312aafbba19832d053a9e1a4aea Signed-off-by: Alan Kwong <akwong@codeaurora.org>
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_cdm.c74
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_cdm.h12
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_top.c15
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_top.h19
4 files changed, 100 insertions, 20 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_cdm.c b/drivers/gpu/drm/msm/sde/sde_hw_cdm.c
index c6ec854d01b7..f610f0044b34 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_cdm.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_cdm.c
@@ -33,11 +33,11 @@
#define CDM_CDWN2_OUT_SIZE 0x130
#define CDM_HDMI_PACK_OP_MODE 0x200
-#define CDM_CSC_10_MATRIX_COEFF_0 0x204
+#define CDM_CSC_10_MATRIX_COEFF_0 0x004
/**
- * Horizontal coeffiecients for cosite chroma downscale
- * s13 repesentation of coefficients
+ * Horizontal coefficients for cosite chroma downscale
+ * s13 representation of coefficients
*/
static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
@@ -92,11 +92,49 @@ static void sde_hw_cdm_setup_csc_10bit(struct sde_hw_cdm *ctx,
struct sde_csc_cfg *data)
{
struct sde_hw_blk_reg_map *c = &ctx->hw;
-
- sde_hw_csc_setup(c, CDM_CSC_10_MATRIX_COEFF_0, data);
+ u32 csc_reg_off = CDM_CSC_10_MATRIX_COEFF_0;
+ u32 val;
+
+ /* matrix coeff */
+ val = data->csc_mv[0] | (data->csc_mv[1] << 16);
+ SDE_REG_WRITE(c, csc_reg_off, val);
+ val = data->csc_mv[2] | (data->csc_mv[3] << 16);
+ SDE_REG_WRITE(c, csc_reg_off + 0x4, val);
+ val = data->csc_mv[4] | (data->csc_mv[5] << 16);
+ SDE_REG_WRITE(c, csc_reg_off + 0x8, val);
+ val = data->csc_mv[6] | (data->csc_mv[7] << 16);
+ SDE_REG_WRITE(c, csc_reg_off + 0xc, val);
+ val = data->csc_mv[8];
+ SDE_REG_WRITE(c, csc_reg_off + 0x10, val);
+
+ /* Pre clamp */
+ val = (data->csc_pre_lv[0] << 16) | data->csc_pre_lv[1];
+ SDE_REG_WRITE(c, csc_reg_off + 0x14, val);
+ val = (data->csc_pre_lv[2] << 16) | data->csc_pre_lv[3];
+ SDE_REG_WRITE(c, csc_reg_off + 0x18, val);
+ val = (data->csc_pre_lv[4] << 16) | data->csc_pre_lv[5];
+ SDE_REG_WRITE(c, csc_reg_off + 0x1c, val);
+
+ /* Post clamp */
+ val = (data->csc_post_lv[0] << 16) | data->csc_post_lv[1];
+ SDE_REG_WRITE(c, csc_reg_off + 0x20, val);
+ val = (data->csc_post_lv[2] << 16) | data->csc_post_lv[3];
+ SDE_REG_WRITE(c, csc_reg_off + 0x24, val);
+ val = (data->csc_post_lv[4] << 16) | data->csc_post_lv[5];
+ SDE_REG_WRITE(c, csc_reg_off + 0x28, val);
+
+ /* Pre-Bias */
+ SDE_REG_WRITE(c, csc_reg_off + 0x2c, data->csc_pre_bv[0]);
+ SDE_REG_WRITE(c, csc_reg_off + 0x30, data->csc_pre_bv[1]);
+ SDE_REG_WRITE(c, csc_reg_off + 0x34, data->csc_pre_bv[2]);
+
+ /* Post-Bias */
+ SDE_REG_WRITE(c, csc_reg_off + 0x38, data->csc_post_bv[0]);
+ SDE_REG_WRITE(c, csc_reg_off + 0x3c, data->csc_post_bv[1]);
+ SDE_REG_WRITE(c, csc_reg_off + 0x40, data->csc_post_bv[2]);
}
-int sde_hw_cdm_setup_cdwn(struct sde_hw_cdm *ctx,
+static int sde_hw_cdm_setup_cdwn(struct sde_hw_cdm *ctx,
struct sde_hw_cdm_cfg *cfg)
{
struct sde_hw_blk_reg_map *c = &ctx->hw;
@@ -218,31 +256,31 @@ int sde_hw_cdm_enable(struct sde_hw_cdm *ctx,
struct sde_hw_cdm_cfg *cdm)
{
struct sde_hw_blk_reg_map *c = &ctx->hw;
- struct sde_format *fmt = cdm->output_fmt;
+ const struct sde_format *fmt = cdm->output_fmt;
+ struct cdm_output_cfg cdm_cfg = { 0 };
u32 opmode = 0;
- u32 cdm_enable = 0;
u32 csc = 0;
if (!SDE_FORMAT_IS_YUV(fmt))
- return 0;
+ return -EINVAL;
if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
if (fmt->chroma_sample != SDE_CHROMA_H1V2)
return -EINVAL; /*unsupported format */
opmode = BIT(0);
opmode |= (fmt->chroma_sample << 1);
- cdm_enable |= BIT(19);
+ cdm_cfg.intf_en = true;
} else {
opmode = 0;
- cdm_enable = BIT(24);
+ cdm_cfg.wb_en = true;
}
csc |= BIT(2);
csc &= ~BIT(1);
csc |= BIT(0);
- /* For this register we need to offset it to MDP TOP BLOCK */
- SDE_REG_WRITE(c, MDP_OUT_CTL_0, cdm_enable);
+ if (ctx->hw_mdp && ctx->hw_mdp->ops.setup_cdm_output)
+ ctx->hw_mdp->ops.setup_cdm_output(ctx->hw_mdp, &cdm_cfg);
SDE_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
SDE_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
@@ -251,10 +289,10 @@ int sde_hw_cdm_enable(struct sde_hw_cdm *ctx,
void sde_hw_cdm_disable(struct sde_hw_cdm *ctx)
{
- struct sde_hw_blk_reg_map *c = &ctx->hw;
+ struct cdm_output_cfg cdm_cfg = { 0 };
- /* mdp top block */
- SDE_REG_WRITE(c, MDP_OUT_CTL_0, 0); /* bypass mode */
+ if (ctx->hw_mdp && ctx->hw_mdp->ops.setup_cdm_output)
+ ctx->hw_mdp->ops.setup_cdm_output(ctx->hw_mdp, &cdm_cfg);
}
static void _setup_cdm_ops(struct sde_hw_cdm_ops *ops,
@@ -268,7 +306,8 @@ static void _setup_cdm_ops(struct sde_hw_cdm_ops *ops,
struct sde_hw_cdm *sde_hw_cdm_init(enum sde_cdm idx,
void __iomem *addr,
- struct sde_mdss_cfg *m)
+ struct sde_mdss_cfg *m,
+ struct sde_hw_mdp *hw_mdp)
{
struct sde_hw_cdm *c;
struct sde_cdm_cfg *cfg;
@@ -286,6 +325,7 @@ struct sde_hw_cdm *sde_hw_cdm_init(enum sde_cdm idx,
c->idx = idx;
c->cdm_hw_cap = cfg;
_setup_cdm_ops(&c->ops, c->cdm_hw_cap->features);
+ c->hw_mdp = hw_mdp;
/*
* Perform any default initialization for the chroma down module
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_cdm.h b/drivers/gpu/drm/msm/sde/sde_hw_cdm.h
index dfec7e0c21c0..e3155dd4b344 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_cdm.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_cdm.h
@@ -14,6 +14,7 @@
#define _SDE_HW_CDM_H
#include "sde_hw_mdss.h"
+#include "sde_hw_top.h"
struct sde_hw_cdm;
@@ -23,7 +24,7 @@ struct sde_hw_cdm_cfg {
u32 output_bit_depth;
u32 h_cdwn_type;
u32 v_cdwn_type;
- struct sde_format *output_fmt;
+ const struct sde_format *output_fmt;
u32 output_type;
int flags;
};
@@ -59,7 +60,7 @@ enum sde_hw_cdwn_output_bit_depth {
struct sde_hw_cdm_ops {
/**
* Programs the CSC matrix for conversion from RGB space to YUV space,
- * it is optinal to call this function as this matrix is automatically
+ * it is optional to call this function as this matrix is automatically
* set during initialization, user should call this if it wants
* to program a different matrix than default matrix.
* @cdm: Pointer to the chroma down context structure
@@ -97,6 +98,9 @@ struct sde_hw_cdm {
const struct sde_cdm_cfg *cdm_hw_cap;
enum sde_cdm idx;
+ /* mdp top hw driver */
+ struct sde_hw_mdp *hw_mdp;
+
/* ops */
struct sde_hw_cdm_ops ops;
};
@@ -107,9 +111,11 @@ struct sde_hw_cdm {
* @idx: cdm index for which driver object is required
* @addr: mapped register io address of MDP
* @m : pointer to mdss catalog data
+ * @hw_mdp: pointer to mdp top hw driver object
*/
struct sde_hw_cdm *sde_hw_cdm_init(enum sde_cdm idx,
void __iomem *addr,
- struct sde_mdss_cfg *m);
+ struct sde_mdss_cfg *m,
+ struct sde_hw_mdp *hw_mdp);
#endif /*_SDE_HW_CDM_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.c b/drivers/gpu/drm/msm/sde/sde_hw_top.c
index 31d5ccef9b64..9e31187a9849 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_top.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_top.c
@@ -70,6 +70,20 @@ static void sde_hw_setup_split_pipe_control(struct sde_hw_mdp *mdp,
SDE_REG_WRITE(c, SPLIT_DISPLAY_ENABLE, cfg->en & 0x1);
}
+static void sde_hw_setup_cdm_output(struct sde_hw_mdp *mdp,
+ struct cdm_output_cfg *cfg)
+{
+ struct sde_hw_blk_reg_map *c = &mdp->hw;
+ u32 out_ctl = 0;
+
+ if (cfg->wb_en)
+ out_ctl |= BIT(24);
+ else if (cfg->intf_en)
+ out_ctl |= BIT(19);
+
+ SDE_REG_WRITE(c, MDP_OUT_CTL_0, out_ctl);
+}
+
static void sde_hw_setup_traffic_shaper(struct sde_hw_mdp *mdp,
struct traffic_shaper_cfg *cfg)
{
@@ -98,6 +112,7 @@ static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
unsigned long cap)
{
ops->setup_split_pipe = sde_hw_setup_split_pipe_control;
+ ops->setup_cdm_output = sde_hw_setup_cdm_output;
ops->setup_traffic_shaper = sde_hw_setup_traffic_shaper;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.h b/drivers/gpu/drm/msm/sde/sde_hw_top.h
index a0c8bbeeb414..d310afd75096 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_top.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_top.h
@@ -53,9 +53,20 @@ struct split_pipe_cfg {
};
/**
+ * struct cdm_output_cfg: output configuration for cdm
+ * @wb_en : enable/disable writeback output
+ * @intf_en : enable/disable interface output
+ */
+struct cdm_output_cfg {
+ bool wb_en;
+ bool intf_en;
+};
+
+/**
* struct sde_hw_mdp_ops - interface to the MDP TOP Hw driver functions
* Assumption is these functions will be called after clocks are enabled.
* @setup_split_pipe : Programs the pipe control registers
+ * @setup_cdm_output : programs cdm control
* @setup_traffic_shaper : programs traffic shaper control
*/
struct sde_hw_mdp_ops {
@@ -68,6 +79,14 @@ struct sde_hw_mdp_ops {
struct split_pipe_cfg *p);
/**
+ * setup_cdm_output() : Setup selection control of the cdm data path
+ * @mdp : mdp top context driver
+ * @cfg : cdm output configuration
+ */
+ void (*setup_cdm_output)(struct sde_hw_mdp *mdp,
+ struct cdm_output_cfg *cfg);
+
+ /**
* setup_traffic_shaper() : Setup traffic shaper control
* @mdp : mdp top context driver
* @cfg : traffic shaper configuration