summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuoniu.Zhou <guoniu.zhou@nxp.com>2017-09-04 16:42:41 +0800
committerGuoniu.Zhou <guoniu.zhou@nxp.com>2017-09-07 17:46:46 +0800
commit7c62393a556d043f88dd188edac3c0d250039358 (patch)
tree936a5b6d9159cbf54a5dcb8d221470ddf61699a2
parentd3d04781d776a3f1befc8a97cb0364ea7cc86d71 (diff)
MLK-16374-1: PxP: add alpha blending back compatible
In support of both g2d and pxp lib alpha blending, there must be two alpha blending versions. So there is one rule that user should obey for different usage cases. 1) g2d alpha blending: user should set combine_enable member of struct pxp_proc_data. 2) pxp lib alpha blending: user should set combine_enable member of struct pxp_layer_param if the pxp_layer_param describe overlay buffer parameters. Signed-off-by: Guoniu.Zhou <guoniu.zhou@nxp.com> Reviewed-by: Robby Cai <robby.cai@nxp.com> Reviewed-by: Fancy Fang <chen.fang@nxp.com>
-rw-r--r--drivers/dma/pxp/pxp_dma_v3.c200
1 files changed, 152 insertions, 48 deletions
diff --git a/drivers/dma/pxp/pxp_dma_v3.c b/drivers/dma/pxp/pxp_dma_v3.c
index 5f407848f0dc..a059a690f08d 100644
--- a/drivers/dma/pxp/pxp_dma_v3.c
+++ b/drivers/dma/pxp/pxp_dma_v3.c
@@ -197,11 +197,29 @@ static struct kmem_cache *edge_node_cache;
static struct pxp_collision_info col_info;
static dma_addr_t paddr;
static bool v3p_flag;
+static int alpha_blending_version;
struct pxp_dma {
struct dma_device dma;
};
+enum pxp_alpha_blending_version {
+ PXP_ALPHA_BLENDING_NONE = 0x0,
+ PXP_ALPHA_BLENDING_V1 = 0x1,
+ PXP_ALPHA_BLENDING_V2 = 0x2,
+};
+
+struct pxp_alpha_global {
+ unsigned int color_key_enable;
+ bool combine_enable;
+ bool global_alpha_enable;
+ bool global_override;
+ bool alpha_invert;
+ bool local_alpha_enable;
+ unsigned char global_alpha;
+ int comp_mask;
+};
+
struct rectangle {
uint16_t x;
uint16_t y;
@@ -271,6 +289,7 @@ struct pxp_pixmap {
uint32_t flags;
bool valid;
dma_addr_t paddr;
+ struct pxp_alpha_global g_alpha;
};
struct pxp_task_info {
@@ -1082,6 +1101,10 @@ static void dump_pxp_reg(struct pxps *pxp)
__raw_readl(pxp->base + HW_PXP_LUT_EXTMEM));
dev_dbg(pxp->dev, "PXP_CFA 0x%x",
__raw_readl(pxp->base + HW_PXP_CFA));
+ dev_dbg(pxp->dev, "PXP_ALPHA_A_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_ALPHA_A_CTRL));
+ dev_dbg(pxp->dev, "PXP_ALPHA_B_CTRL 0x%x",
+ __raw_readl(pxp->base + HW_PXP_ALPHA_B_CTRL));
dev_dbg(pxp->dev, "PXP_POWER_REG0 0x%x",
__raw_readl(pxp->base + HW_PXP_POWER_REG0));
dev_dbg(pxp->dev, "PXP_NEXT 0x%x",
@@ -2413,9 +2436,40 @@ static int pxp_as_config(struct pxp_pixmap *input,
memset((void*)&ctrl, 0x0, sizeof(ctrl));
ctrl.format = pxp_parse_as_fmt(input->format);
+
+ if (alpha_blending_version == PXP_ALPHA_BLENDING_V1) {
+ if (input->format == PXP_PIX_FMT_BGRA32) {
+ if (!input->g_alpha.combine_enable) {
+ ctrl.alpha_ctrl = BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs;
+ ctrl.rop = 0x3;
+ }
+ }
+
+ if (input->g_alpha.global_alpha_enable) {
+ if (input->g_alpha.global_override)
+ ctrl.alpha_ctrl = BV_PXP_AS_CTRL_ALPHA_CTRL__Override;
+ else
+ ctrl.alpha_ctrl = BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply;
+
+ if (input->g_alpha.alpha_invert)
+ ctrl.alpha0_invert = 0x1;
+ }
+
+ if (input->g_alpha.color_key_enable) {
+ ctrl.enable_colorkey = 1;
+ }
+
+ ctrl.alpha = input->g_alpha.global_alpha;
+ }
+
out_as_ulc.x = out_as_ulc.y = 0;
- out_as_lrc.x = output->crop.width - 1;
- out_as_lrc.y = output->crop.height - 1;
+ if (input->g_alpha.combine_enable) {
+ out_as_lrc.x = input->width - 1;
+ out_as_lrc.y = input->height - 1;
+ } else {
+ out_as_lrc.x = output->crop.width - 1;
+ out_as_lrc.y = output->crop.height - 1;
+ }
offset = input->crop.y * input->pitch +
input->crop.x * (input->bpp >> 3);
@@ -2647,6 +2701,12 @@ static int pxp_out_config(struct pxp_pixmap *output)
pxp_writel(output->pitch, HW_PXP_OUT_PITCH);
+ /* set global alpha if necessary */
+ if (output->g_alpha.global_alpha_enable) {
+ pxp_writel(output->g_alpha.global_alpha << 24, HW_PXP_OUT_CTRL_SET);
+ pxp_writel(BM_PXP_OUT_CTRL_ALPHA_OUTPUT, HW_PXP_OUT_CTRL_SET);
+ }
+
pxp_writel(BF_PXP_CTRL_ENABLE_PS_AS_OUT(1) |
BF_PXP_CTRL_IRQ_ENABLE(1),
HW_PXP_CTRL_SET);
@@ -2738,54 +2798,57 @@ static int pxp_alpha_config(struct pxp_op_info *op,
memset((void*)&alpha_ctrl, 0x0, sizeof(alpha_ctrl));
- if (alpha->alpha_mode == ALPHA_MODE_ROP) {
+ if (alpha_blending_version != PXP_ALPHA_BLENDING_V1) {
+ if (alpha->alpha_mode == ALPHA_MODE_ROP) {
+ switch (alpha_node) {
+ case PXP_2D_ALPHA0_S0:
+ as_ctrl = __raw_readl(pxp_reg_base + HW_PXP_AS_CTRL);
+ as_ctrl |= BF_PXP_AS_CTRL_ALPHA_CTRL(BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs);
+ as_ctrl |= BF_PXP_AS_CTRL_ROP(alpha->rop_type);
+ pxp_writel(as_ctrl, HW_PXP_AS_CTRL);
+ break;
+ case PXP_2D_ALPHA1_S0:
+ pxp_writel(BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE |
+ BF_PXP_ALPHA_B_CTRL_1_ROP(alpha->rop_type),
+ HW_PXP_ALPHA_B_CTRL_1);
+ pxp_writel(BF_PXP_CTRL_ENABLE_ALPHA_B(1), HW_PXP_CTRL_SET);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+ }
+
+ s0_alpha = &alpha->s0_alpha;
+ s1_alpha = &alpha->s1_alpha;
+
+ alpha_ctrl.poter_duff_enable = 1;
+
+ alpha_ctrl.s0_s1_factor_mode = s1_alpha->factor_mode;
+ alpha_ctrl.s0_global_alpha_mode = s0_alpha->global_alpha_mode;
+ alpha_ctrl.s0_alpha_mode = s0_alpha->alpha_mode;
+ alpha_ctrl.s0_color_mode = s0_alpha->color_mode;
+
+ alpha_ctrl.s1_s0_factor_mode = s0_alpha->factor_mode;
+ alpha_ctrl.s1_global_alpha_mode = s1_alpha->global_alpha_mode;
+ alpha_ctrl.s1_alpha_mode = s1_alpha->alpha_mode;
+ alpha_ctrl.s1_color_mode = s1_alpha->color_mode;
+
+ alpha_ctrl.s0_global_alpha = s0_alpha->global_alpha_value;
+ alpha_ctrl.s1_global_alpha = s1_alpha->global_alpha_value;
+
switch (alpha_node) {
case PXP_2D_ALPHA0_S0:
- as_ctrl = __raw_readl(pxp_reg_base + HW_PXP_AS_CTRL);
- as_ctrl |= BF_PXP_AS_CTRL_ALPHA_CTRL(BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs);
- as_ctrl |= BF_PXP_AS_CTRL_ROP(alpha->rop_type);
- pxp_writel(as_ctrl, HW_PXP_AS_CTRL);
+ pxp_writel(*(uint32_t *)&alpha_ctrl, HW_PXP_ALPHA_A_CTRL);
break;
case PXP_2D_ALPHA1_S0:
- pxp_writel(BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE |
- BF_PXP_ALPHA_B_CTRL_1_ROP(alpha->rop_type),
- HW_PXP_ALPHA_B_CTRL_1);
+ pxp_writel(*(uint32_t *)&alpha_ctrl, HW_PXP_ALPHA_B_CTRL);
pxp_writel(BF_PXP_CTRL_ENABLE_ALPHA_B(1), HW_PXP_CTRL_SET);
break;
default:
break;
}
-
- return 0;
- }
-
- s0_alpha = &alpha->s0_alpha;
- s1_alpha = &alpha->s1_alpha;
- alpha_ctrl.poter_duff_enable = 1;
-
- alpha_ctrl.s0_s1_factor_mode = s1_alpha->factor_mode;
- alpha_ctrl.s0_global_alpha_mode = s0_alpha->global_alpha_mode;
- alpha_ctrl.s0_alpha_mode = s0_alpha->alpha_mode;
- alpha_ctrl.s0_color_mode = s0_alpha->color_mode;
-
- alpha_ctrl.s1_s0_factor_mode = s0_alpha->factor_mode;
- alpha_ctrl.s1_global_alpha_mode = s1_alpha->global_alpha_mode;
- alpha_ctrl.s1_alpha_mode = s1_alpha->alpha_mode;
- alpha_ctrl.s1_color_mode = s1_alpha->color_mode;
-
- alpha_ctrl.s0_global_alpha = s0_alpha->global_alpha_value;
- alpha_ctrl.s1_global_alpha = s1_alpha->global_alpha_value;
-
- switch (alpha_node) {
- case PXP_2D_ALPHA0_S0:
- pxp_writel(*(uint32_t *)&alpha_ctrl, HW_PXP_ALPHA_A_CTRL);
- break;
- case PXP_2D_ALPHA1_S0:
- pxp_writel(*(uint32_t *)&alpha_ctrl, HW_PXP_ALPHA_B_CTRL);
- pxp_writel(BF_PXP_CTRL_ENABLE_ALPHA_B(1), HW_PXP_CTRL_SET);
- break;
- default:
- break;
}
return 0;
@@ -3208,8 +3271,11 @@ reparse:
possible_outputs = (1 << PXP_2D_OUT) |
(1 << PXP_2D_INPUT_STORE0);
- if (input_s0->rotate || input_s0->flip)
+ if (input_s0->rotate || input_s0->flip) {
input_s0->flags |= IN_NEED_ROTATE_FLIP;
+ output->rotate = input_s0->rotate;
+ output->flip = input_s0->flip;
+ }
if (input_s1->rotate || input_s1->flip) {
input_s1->flags |= IN_NEED_ROTATE_FLIP;
clear_bit(PXP_2D_AS,
@@ -3357,6 +3423,11 @@ alpha1:
/* To workaround an IC bug */
path_ctrl0.mux4_sel = 0x0;
config:
+ if (nodes_in_path_s0 & (1 << PXP_2D_ROTATION1)) {
+ clear_bit(PXP_2D_ROTATION1, (unsigned long *)&nodes_in_path_s0);
+ set_bit(PXP_2D_ROTATION0, (unsigned long *)&nodes_in_path_s0);
+ }
+
pr_debug("%s: nodes_in_path_s0 = 0x%x, nodes_used_s0 = 0x%x, nodes_in_path_s1 = 0x%x, nodes_used_s1 = 0x%x\n",
__func__, nodes_in_path_s0, nodes_used_s0, nodes_in_path_s1, nodes_used_s1);
pxp_2d_calc_mux(nodes_in_path_s0, &path_ctrl0);
@@ -3364,6 +3435,12 @@ config:
pr_debug("%s: s0 paddr = 0x%x, s1 paddr = 0x%x, out paddr = 0x%x\n",
__func__, input_s0->paddr, input_s1->paddr, output->paddr);
+
+ if (nodes_used_s0 & (1 << PXP_2D_ROTATION1)) {
+ clear_bit(PXP_2D_ROTATION1, (unsigned long *)&nodes_used_s0);
+ set_bit(PXP_2D_ROTATION0, (unsigned long *)&nodes_used_s0);
+ }
+
pxp_2d_task_config(input_s0, output, op, nodes_used_s0);
pxp_2d_task_config(input_s1, output, op, nodes_used_s1);
break;
@@ -3372,7 +3449,7 @@ config:
}
__raw_writel(proc_data->bgcolor,
- pxp->base + HW_PXP_PS_BACKGROUND_0);
+ pxp->base + HW_PXP_PS_BACKGROUND_0);
if (proc_data->lut_transform && pxp_is_v3(pxp))
set_mux(&path_ctrl0);
@@ -3547,6 +3624,15 @@ static int convert_param_to_pixmap(struct pxp_pixmap *pixmap,
pixmap->crop.width = param->crop.width;
pixmap->crop.height = param->crop.height;
+ pixmap->g_alpha.color_key_enable = param->color_key_enable;
+ pixmap->g_alpha.combine_enable = param->combine_enable;
+ pixmap->g_alpha.global_alpha_enable = param->global_alpha_enable;
+ pixmap->g_alpha.global_override = param->global_override;
+ pixmap->g_alpha.global_alpha = param->global_alpha;
+ pixmap->g_alpha.alpha_invert = param->alpha_invert;
+ pixmap->g_alpha.local_alpha_enable = param->local_alpha_enable;
+ pixmap->g_alpha.comp_mask = param->comp_mask;
+
return 0;
}
@@ -3565,6 +3651,7 @@ static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
struct pxp_layer_param *param = NULL;
struct pxp_pixmap *input, *output;
int i = 0, ret;
+ bool combine_enable = false;
memset(&pxp->pxp_conf_state.s0_param, 0, sizeof(struct pxp_layer_param));
memset(&pxp->pxp_conf_state.out_param, 0, sizeof(struct pxp_layer_param));
@@ -3579,6 +3666,11 @@ static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
memcpy(&pxp->pxp_conf_state.proc_data,
&desc->proc_data, sizeof(struct pxp_proc_data));
+ if (proc_data->combine_enable)
+ alpha_blending_version = PXP_ALPHA_BLENDING_V2;
+ else
+ alpha_blending_version = PXP_ALPHA_BLENDING_NONE;
+
/* Save PxP configuration */
list_for_each_entry(child, &desc->tx_list, list) {
if (i == 0) { /* Output */
@@ -3589,6 +3681,11 @@ static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
memcpy(&pxp->pxp_conf_state.ol_param[i - 1],
&child->layer_param.ol_param,
sizeof(struct pxp_layer_param));
+ if (pxp->pxp_conf_state.ol_param[i - 1].width != 0 &&
+ pxp->pxp_conf_state.ol_param[i - 1].height != 0) {
+ if (pxp->pxp_conf_state.ol_param[i - 1].combine_enable)
+ alpha_blending_version = PXP_ALPHA_BLENDING_V1;
+ }
}
if (proc_data->engine_enable & PXP_ENABLE_DITHER) {
@@ -3656,7 +3753,12 @@ static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
if (!op->op_type) {
op->op_type = PXP_OP_TYPE_2D;
- if (proc_data->combine_enable)
+
+ if ((alpha_blending_version == PXP_ALPHA_BLENDING_V1) ||
+ (alpha_blending_version == PXP_ALPHA_BLENDING_V2))
+ combine_enable = true;
+
+ if (combine_enable)
task->input_num = 2;
else if (proc_data->fill_en)
task->input_num = 0;
@@ -3690,6 +3792,7 @@ static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
(proc_data->vflip) ? PXP_V_FLIP : 0;
break;
case 2:
+ /* s0 */
param = &pxp->pxp_conf_state.s0_param;
input = &task->input[0];
@@ -3701,17 +3804,18 @@ static void __pxpdma_dostart(struct pxp_channel *pxp_chan)
input->crop.height = proc_data->srect.height;
alpha->s0_alpha = param->alpha;
+ input->rotate = proc_data->rotate;
+ input->flip = (proc_data->hflip) ? PXP_H_FLIP :
+ (proc_data->vflip) ? PXP_V_FLIP : 0;
+
+ /* overlay */
param = &pxp->pxp_conf_state.ol_param[0];
input = &task->input[1];
ret = convert_param_to_pixmap(input, param);
BUG_ON(ret < 0);
alpha->s1_alpha = param->alpha;
-
alpha->alpha_mode = proc_data->alpha_mode;
- input->rotate = proc_data->rotate;
- input->flip = (proc_data->hflip) ? PXP_H_FLIP :
- (proc_data->vflip) ? PXP_V_FLIP : 0;
break;
}