1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
6 #include "dpu_hw_catalog.h"
9 #include "dpu_hw_mdss.h"
11 #define LM_OP_MODE 0x00
12 #define LM_OUT_SIZE 0x04
13 #define LM_BORDER_COLOR_0 0x08
14 #define LM_BORDER_COLOR_1 0x010
16 /* These register are offset to mixer base + stage base */
17 #define LM_BLEND0_OP 0x00
18 #define LM_BLEND0_CONST_ALPHA 0x04
19 #define LM_FG_COLOR_FILL_COLOR_0 0x08
20 #define LM_FG_COLOR_FILL_COLOR_1 0x0C
21 #define LM_FG_COLOR_FILL_SIZE 0x10
22 #define LM_FG_COLOR_FILL_XY 0x14
24 #define LM_BLEND0_FG_ALPHA 0x04
25 #define LM_BLEND0_BG_ALPHA 0x08
27 static const struct dpu_lm_cfg
*_lm_offset(enum dpu_lm mixer
,
28 const struct dpu_mdss_cfg
*m
,
30 struct dpu_hw_blk_reg_map
*b
)
34 for (i
= 0; i
< m
->mixer_count
; i
++) {
35 if (mixer
== m
->mixer
[i
].id
) {
37 b
->blk_off
= m
->mixer
[i
].base
;
38 b
->length
= m
->mixer
[i
].len
;
39 b
->hwversion
= m
->hwversion
;
40 b
->log_mask
= DPU_DBG_MASK_LM
;
45 return ERR_PTR(-ENOMEM
);
49 * _stage_offset(): returns the relative offset of the blend registers
50 * for the stage to be setup
51 * @ctx: mixer ctx contains the mixer to be programmed
52 * @stage: stage index to setup
54 static inline int _stage_offset(struct dpu_hw_mixer
*ctx
, enum dpu_stage stage
)
56 const struct dpu_lm_sub_blks
*sblk
= ctx
->cap
->sblk
;
57 if (stage
!= DPU_STAGE_BASE
&& stage
<= sblk
->maxblendstages
)
58 return sblk
->blendstage_base
[stage
- DPU_STAGE_0
];
63 static void dpu_hw_lm_setup_out(struct dpu_hw_mixer
*ctx
,
64 struct dpu_hw_mixer_cfg
*mixer
)
66 struct dpu_hw_blk_reg_map
*c
= &ctx
->hw
;
70 op_mode
= DPU_REG_READ(c
, LM_OP_MODE
);
72 outsize
= mixer
->out_height
<< 16 | mixer
->out_width
;
73 DPU_REG_WRITE(c
, LM_OUT_SIZE
, outsize
);
75 /* SPLIT_LEFT_RIGHT */
76 if (mixer
->right_mixer
)
80 DPU_REG_WRITE(c
, LM_OP_MODE
, op_mode
);
83 static void dpu_hw_lm_setup_border_color(struct dpu_hw_mixer
*ctx
,
84 struct dpu_mdss_color
*color
,
87 struct dpu_hw_blk_reg_map
*c
= &ctx
->hw
;
90 DPU_REG_WRITE(c
, LM_BORDER_COLOR_0
,
91 (color
->color_0
& 0xFFF) |
92 ((color
->color_1
& 0xFFF) << 0x10));
93 DPU_REG_WRITE(c
, LM_BORDER_COLOR_1
,
94 (color
->color_2
& 0xFFF) |
95 ((color
->color_3
& 0xFFF) << 0x10));
99 static void dpu_hw_lm_setup_blend_config_sdm845(struct dpu_hw_mixer
*ctx
,
100 u32 stage
, u32 fg_alpha
, u32 bg_alpha
, u32 blend_op
)
102 struct dpu_hw_blk_reg_map
*c
= &ctx
->hw
;
106 if (stage
== DPU_STAGE_BASE
)
109 stage_off
= _stage_offset(ctx
, stage
);
110 if (WARN_ON(stage_off
< 0))
113 const_alpha
= (bg_alpha
& 0xFF) | ((fg_alpha
& 0xFF) << 16);
114 DPU_REG_WRITE(c
, LM_BLEND0_CONST_ALPHA
+ stage_off
, const_alpha
);
115 DPU_REG_WRITE(c
, LM_BLEND0_OP
+ stage_off
, blend_op
);
118 static void dpu_hw_lm_setup_blend_config(struct dpu_hw_mixer
*ctx
,
119 u32 stage
, u32 fg_alpha
, u32 bg_alpha
, u32 blend_op
)
121 struct dpu_hw_blk_reg_map
*c
= &ctx
->hw
;
124 if (stage
== DPU_STAGE_BASE
)
127 stage_off
= _stage_offset(ctx
, stage
);
128 if (WARN_ON(stage_off
< 0))
131 DPU_REG_WRITE(c
, LM_BLEND0_FG_ALPHA
+ stage_off
, fg_alpha
);
132 DPU_REG_WRITE(c
, LM_BLEND0_BG_ALPHA
+ stage_off
, bg_alpha
);
133 DPU_REG_WRITE(c
, LM_BLEND0_OP
+ stage_off
, blend_op
);
136 static void dpu_hw_lm_setup_color3(struct dpu_hw_mixer
*ctx
,
137 uint32_t mixer_op_mode
)
139 struct dpu_hw_blk_reg_map
*c
= &ctx
->hw
;
142 /* read the existing op_mode configuration */
143 op_mode
= DPU_REG_READ(c
, LM_OP_MODE
);
145 op_mode
= (op_mode
& (BIT(31) | BIT(30))) | mixer_op_mode
;
147 DPU_REG_WRITE(c
, LM_OP_MODE
, op_mode
);
150 static void _setup_mixer_ops(const struct dpu_mdss_cfg
*m
,
151 struct dpu_hw_lm_ops
*ops
,
152 unsigned long features
)
154 ops
->setup_mixer_out
= dpu_hw_lm_setup_out
;
155 if (m
->hwversion
>= DPU_HW_VER_400
)
156 ops
->setup_blend_config
= dpu_hw_lm_setup_blend_config_sdm845
;
158 ops
->setup_blend_config
= dpu_hw_lm_setup_blend_config
;
159 ops
->setup_alpha_out
= dpu_hw_lm_setup_color3
;
160 ops
->setup_border_color
= dpu_hw_lm_setup_border_color
;
163 static struct dpu_hw_blk_ops dpu_hw_ops
;
165 struct dpu_hw_mixer
*dpu_hw_lm_init(enum dpu_lm idx
,
167 const struct dpu_mdss_cfg
*m
)
169 struct dpu_hw_mixer
*c
;
170 const struct dpu_lm_cfg
*cfg
;
172 c
= kzalloc(sizeof(*c
), GFP_KERNEL
);
174 return ERR_PTR(-ENOMEM
);
176 cfg
= _lm_offset(idx
, m
, addr
, &c
->hw
);
177 if (IS_ERR_OR_NULL(cfg
)) {
179 return ERR_PTR(-EINVAL
);
185 _setup_mixer_ops(m
, &c
->ops
, c
->cap
->features
);
187 dpu_hw_blk_init(&c
->base
, DPU_HW_BLK_LM
, idx
, &dpu_hw_ops
);
192 void dpu_hw_lm_destroy(struct dpu_hw_mixer
*lm
)
195 dpu_hw_blk_destroy(&lm
->base
);