diff options
| author | Alan Kwong <akwong@codeaurora.org> | 2016-07-29 03:06:44 -0400 |
|---|---|---|
| committer | Alan Kwong <akwong@codeaurora.org> | 2016-08-04 11:39:30 -0400 |
| commit | b05a124d2f5bcdb699adad308a5a90c91faca889 (patch) | |
| tree | f17aebad5a681fd54bdabe19c1a6479ab9fd0685 | |
| parent | 95095bdaa2c897890c63b591a1037b8498f92ddf (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.c | 74 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_hw_cdm.h | 12 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_hw_top.c | 15 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_hw_top.h | 19 |
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 |
