1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4 * Author: Jacob Chen <jacob-chen@iotwrt.com>
7 #include <linux/pm_runtime.h>
12 enum e_rga_start_pos
{
19 struct rga_addr_offset
{
25 struct rga_corners_addr_offset
{
26 struct rga_addr_offset left_top
;
27 struct rga_addr_offset right_top
;
28 struct rga_addr_offset left_bottom
;
29 struct rga_addr_offset right_bottom
;
32 static unsigned int rga_get_scaling(unsigned int src
, unsigned int dst
)
35 * The rga hw scaling factor is a normalized inverse of the
37 * For example: When source width is 100 and destination width is 200
38 * (scaling of 2x), then the hw factor is NC * 100 / 200.
39 * The normalization factor (NC) is 2^16 = 0x10000.
42 return (src
> dst
) ? ((dst
<< 16) / src
) : ((src
<< 16) / dst
);
45 static struct rga_corners_addr_offset
46 rga_get_addr_offset(struct rga_frame
*frm
, unsigned int x
, unsigned int y
,
47 unsigned int w
, unsigned int h
)
49 struct rga_corners_addr_offset offsets
;
50 struct rga_addr_offset
*lt
, *lb
, *rt
, *rb
;
51 unsigned int x_div
= 0,
52 y_div
= 0, uv_stride
= 0, pixel_width
= 0, uv_factor
= 0;
54 lt
= &offsets
.left_top
;
55 lb
= &offsets
.left_bottom
;
56 rt
= &offsets
.right_top
;
57 rb
= &offsets
.right_bottom
;
59 x_div
= frm
->fmt
->x_div
;
60 y_div
= frm
->fmt
->y_div
;
61 uv_factor
= frm
->fmt
->uv_factor
;
62 uv_stride
= frm
->stride
/ x_div
;
63 pixel_width
= frm
->stride
/ frm
->width
;
65 lt
->y_off
= y
* frm
->stride
+ x
* pixel_width
;
67 frm
->width
* frm
->height
+ (y
/ y_div
) * uv_stride
+ x
/ x_div
;
68 lt
->v_off
= lt
->u_off
+ frm
->width
* frm
->height
/ uv_factor
;
70 lb
->y_off
= lt
->y_off
+ (h
- 1) * frm
->stride
;
71 lb
->u_off
= lt
->u_off
+ (h
/ y_div
- 1) * uv_stride
;
72 lb
->v_off
= lt
->v_off
+ (h
/ y_div
- 1) * uv_stride
;
74 rt
->y_off
= lt
->y_off
+ (w
- 1) * pixel_width
;
75 rt
->u_off
= lt
->u_off
+ w
/ x_div
- 1;
76 rt
->v_off
= lt
->v_off
+ w
/ x_div
- 1;
78 rb
->y_off
= lb
->y_off
+ (w
- 1) * pixel_width
;
79 rb
->u_off
= lb
->u_off
+ w
/ x_div
- 1;
80 rb
->v_off
= lb
->v_off
+ w
/ x_div
- 1;
85 static struct rga_addr_offset
*rga_lookup_draw_pos(struct
86 rga_corners_addr_offset
87 * offsets
, u32 rotate_mode
,
90 static enum e_rga_start_pos rot_mir_point_matrix
[4][4] = {
108 switch (rot_mir_point_matrix
[rotate_mode
][mirr_mode
]) {
110 return &offsets
->left_top
;
112 return &offsets
->left_bottom
;
114 return &offsets
->right_top
;
116 return &offsets
->right_bottom
;
122 static void rga_cmd_set_src_addr(struct rga_ctx
*ctx
, void *mmu_pages
)
124 struct rockchip_rga
*rga
= ctx
->rga
;
125 u32
*dest
= rga
->cmdbuf_virt
;
128 reg
= RGA_MMU_SRC_BASE
- RGA_MODE_BASE_REG
;
129 dest
[reg
>> 2] = virt_to_phys(mmu_pages
) >> 4;
131 reg
= RGA_MMU_CTRL1
- RGA_MODE_BASE_REG
;
132 dest
[reg
>> 2] |= 0x7;
135 static void rga_cmd_set_src1_addr(struct rga_ctx
*ctx
, void *mmu_pages
)
137 struct rockchip_rga
*rga
= ctx
->rga
;
138 u32
*dest
= rga
->cmdbuf_virt
;
141 reg
= RGA_MMU_SRC1_BASE
- RGA_MODE_BASE_REG
;
142 dest
[reg
>> 2] = virt_to_phys(mmu_pages
) >> 4;
144 reg
= RGA_MMU_CTRL1
- RGA_MODE_BASE_REG
;
145 dest
[reg
>> 2] |= 0x7 << 4;
148 static void rga_cmd_set_dst_addr(struct rga_ctx
*ctx
, void *mmu_pages
)
150 struct rockchip_rga
*rga
= ctx
->rga
;
151 u32
*dest
= rga
->cmdbuf_virt
;
154 reg
= RGA_MMU_DST_BASE
- RGA_MODE_BASE_REG
;
155 dest
[reg
>> 2] = virt_to_phys(mmu_pages
) >> 4;
157 reg
= RGA_MMU_CTRL1
- RGA_MODE_BASE_REG
;
158 dest
[reg
>> 2] |= 0x7 << 8;
161 static void rga_cmd_set_trans_info(struct rga_ctx
*ctx
)
163 struct rockchip_rga
*rga
= ctx
->rga
;
164 u32
*dest
= rga
->cmdbuf_virt
;
165 unsigned int scale_dst_w
, scale_dst_h
;
166 unsigned int src_h
, src_w
, src_x
, src_y
, dst_h
, dst_w
, dst_x
, dst_y
;
167 union rga_src_info src_info
;
168 union rga_dst_info dst_info
;
169 union rga_src_x_factor x_factor
;
170 union rga_src_y_factor y_factor
;
171 union rga_src_vir_info src_vir_info
;
172 union rga_src_act_info src_act_info
;
173 union rga_dst_vir_info dst_vir_info
;
174 union rga_dst_act_info dst_act_info
;
176 struct rga_addr_offset
*dst_offset
;
177 struct rga_corners_addr_offset offsets
;
178 struct rga_corners_addr_offset src_offsets
;
180 src_h
= ctx
->in
.crop
.height
;
181 src_w
= ctx
->in
.crop
.width
;
182 src_x
= ctx
->in
.crop
.left
;
183 src_y
= ctx
->in
.crop
.top
;
184 dst_h
= ctx
->out
.crop
.height
;
185 dst_w
= ctx
->out
.crop
.width
;
186 dst_x
= ctx
->out
.crop
.left
;
187 dst_y
= ctx
->out
.crop
.top
;
189 src_info
.val
= dest
[(RGA_SRC_INFO
- RGA_MODE_BASE_REG
) >> 2];
190 dst_info
.val
= dest
[(RGA_DST_INFO
- RGA_MODE_BASE_REG
) >> 2];
191 x_factor
.val
= dest
[(RGA_SRC_X_FACTOR
- RGA_MODE_BASE_REG
) >> 2];
192 y_factor
.val
= dest
[(RGA_SRC_Y_FACTOR
- RGA_MODE_BASE_REG
) >> 2];
193 src_vir_info
.val
= dest
[(RGA_SRC_VIR_INFO
- RGA_MODE_BASE_REG
) >> 2];
194 src_act_info
.val
= dest
[(RGA_SRC_ACT_INFO
- RGA_MODE_BASE_REG
) >> 2];
195 dst_vir_info
.val
= dest
[(RGA_DST_VIR_INFO
- RGA_MODE_BASE_REG
) >> 2];
196 dst_act_info
.val
= dest
[(RGA_DST_ACT_INFO
- RGA_MODE_BASE_REG
) >> 2];
198 src_info
.data
.format
= ctx
->in
.fmt
->hw_format
;
199 src_info
.data
.swap
= ctx
->in
.fmt
->color_swap
;
200 dst_info
.data
.format
= ctx
->out
.fmt
->hw_format
;
201 dst_info
.data
.swap
= ctx
->out
.fmt
->color_swap
;
204 * CSC mode must only be set when the colorspace families differ between
205 * input and output. It must remain unset (zeroed) if both are the same.
208 if (RGA_COLOR_FMT_IS_YUV(ctx
->in
.fmt
->hw_format
) &&
209 RGA_COLOR_FMT_IS_RGB(ctx
->out
.fmt
->hw_format
)) {
210 switch (ctx
->in
.colorspace
) {
211 case V4L2_COLORSPACE_REC709
:
212 src_info
.data
.csc_mode
= RGA_SRC_CSC_MODE_BT709_R0
;
215 src_info
.data
.csc_mode
= RGA_SRC_CSC_MODE_BT601_R0
;
220 if (RGA_COLOR_FMT_IS_RGB(ctx
->in
.fmt
->hw_format
) &&
221 RGA_COLOR_FMT_IS_YUV(ctx
->out
.fmt
->hw_format
)) {
222 switch (ctx
->out
.colorspace
) {
223 case V4L2_COLORSPACE_REC709
:
224 dst_info
.data
.csc_mode
= RGA_SRC_CSC_MODE_BT709_R0
;
227 dst_info
.data
.csc_mode
= RGA_DST_CSC_MODE_BT601_R0
;
233 src_info
.data
.mir_mode
|= RGA_SRC_MIRR_MODE_X
;
236 src_info
.data
.mir_mode
|= RGA_SRC_MIRR_MODE_Y
;
238 switch (ctx
->rotate
) {
240 src_info
.data
.rot_mode
= RGA_SRC_ROT_MODE_90_DEGREE
;
243 src_info
.data
.rot_mode
= RGA_SRC_ROT_MODE_180_DEGREE
;
246 src_info
.data
.rot_mode
= RGA_SRC_ROT_MODE_270_DEGREE
;
249 src_info
.data
.rot_mode
= RGA_SRC_ROT_MODE_0_DEGREE
;
254 * Calculate the up/down scaling mode/factor.
256 * RGA used to scale the picture first, and then rotate second,
257 * so we need to swap the w/h when rotate degree is 90/270.
259 if (src_info
.data
.rot_mode
== RGA_SRC_ROT_MODE_90_DEGREE
||
260 src_info
.data
.rot_mode
== RGA_SRC_ROT_MODE_270_DEGREE
) {
261 if (rga
->version
.major
== 0 || rga
->version
.minor
== 0) {
264 if (abs(src_w
- dst_h
) < 16)
275 if (src_w
== scale_dst_w
) {
276 src_info
.data
.hscl_mode
= RGA_SRC_HSCL_MODE_NO
;
278 } else if (src_w
> scale_dst_w
) {
279 src_info
.data
.hscl_mode
= RGA_SRC_HSCL_MODE_DOWN
;
280 x_factor
.data
.down_scale_factor
=
281 rga_get_scaling(src_w
, scale_dst_w
) + 1;
283 src_info
.data
.hscl_mode
= RGA_SRC_HSCL_MODE_UP
;
284 x_factor
.data
.up_scale_factor
=
285 rga_get_scaling(src_w
- 1, scale_dst_w
- 1);
288 if (src_h
== scale_dst_h
) {
289 src_info
.data
.vscl_mode
= RGA_SRC_VSCL_MODE_NO
;
291 } else if (src_h
> scale_dst_h
) {
292 src_info
.data
.vscl_mode
= RGA_SRC_VSCL_MODE_DOWN
;
293 y_factor
.data
.down_scale_factor
=
294 rga_get_scaling(src_h
, scale_dst_h
) + 1;
296 src_info
.data
.vscl_mode
= RGA_SRC_VSCL_MODE_UP
;
297 y_factor
.data
.up_scale_factor
=
298 rga_get_scaling(src_h
- 1, scale_dst_h
- 1);
302 * Calculate the framebuffer virtual strides and active size,
303 * note that the step of vir_stride / vir_width is 4 byte words
305 src_vir_info
.data
.vir_stride
= ctx
->in
.stride
>> 2;
306 src_vir_info
.data
.vir_width
= ctx
->in
.stride
>> 2;
308 src_act_info
.data
.act_height
= src_h
- 1;
309 src_act_info
.data
.act_width
= src_w
- 1;
311 dst_vir_info
.data
.vir_stride
= ctx
->out
.stride
>> 2;
312 dst_act_info
.data
.act_height
= dst_h
- 1;
313 dst_act_info
.data
.act_width
= dst_w
- 1;
316 * Calculate the source framebuffer base address with offset pixel.
318 src_offsets
= rga_get_addr_offset(&ctx
->in
, src_x
, src_y
,
322 * Configure the dest framebuffer base address with pixel offset.
324 offsets
= rga_get_addr_offset(&ctx
->out
, dst_x
, dst_y
, dst_w
, dst_h
);
325 dst_offset
= rga_lookup_draw_pos(&offsets
, src_info
.data
.rot_mode
,
326 src_info
.data
.mir_mode
);
328 dest
[(RGA_SRC_Y_RGB_BASE_ADDR
- RGA_MODE_BASE_REG
) >> 2] =
329 src_offsets
.left_top
.y_off
;
330 dest
[(RGA_SRC_CB_BASE_ADDR
- RGA_MODE_BASE_REG
) >> 2] =
331 src_offsets
.left_top
.u_off
;
332 dest
[(RGA_SRC_CR_BASE_ADDR
- RGA_MODE_BASE_REG
) >> 2] =
333 src_offsets
.left_top
.v_off
;
335 dest
[(RGA_SRC_X_FACTOR
- RGA_MODE_BASE_REG
) >> 2] = x_factor
.val
;
336 dest
[(RGA_SRC_Y_FACTOR
- RGA_MODE_BASE_REG
) >> 2] = y_factor
.val
;
337 dest
[(RGA_SRC_VIR_INFO
- RGA_MODE_BASE_REG
) >> 2] = src_vir_info
.val
;
338 dest
[(RGA_SRC_ACT_INFO
- RGA_MODE_BASE_REG
) >> 2] = src_act_info
.val
;
340 dest
[(RGA_SRC_INFO
- RGA_MODE_BASE_REG
) >> 2] = src_info
.val
;
342 dest
[(RGA_DST_Y_RGB_BASE_ADDR
- RGA_MODE_BASE_REG
) >> 2] =
344 dest
[(RGA_DST_CB_BASE_ADDR
- RGA_MODE_BASE_REG
) >> 2] =
346 dest
[(RGA_DST_CR_BASE_ADDR
- RGA_MODE_BASE_REG
) >> 2] =
349 dest
[(RGA_DST_VIR_INFO
- RGA_MODE_BASE_REG
) >> 2] = dst_vir_info
.val
;
350 dest
[(RGA_DST_ACT_INFO
- RGA_MODE_BASE_REG
) >> 2] = dst_act_info
.val
;
352 dest
[(RGA_DST_INFO
- RGA_MODE_BASE_REG
) >> 2] = dst_info
.val
;
355 static void rga_cmd_set_mode(struct rga_ctx
*ctx
)
357 struct rockchip_rga
*rga
= ctx
->rga
;
358 u32
*dest
= rga
->cmdbuf_virt
;
359 union rga_mode_ctrl mode
;
360 union rga_alpha_ctrl0 alpha_ctrl0
;
361 union rga_alpha_ctrl1 alpha_ctrl1
;
367 mode
.data
.gradient_sat
= 1;
368 mode
.data
.render
= RGA_MODE_RENDER_BITBLT
;
369 mode
.data
.bitblt
= RGA_MODE_BITBLT_MODE_SRC_TO_DST
;
371 /* disable alpha blending */
372 dest
[(RGA_ALPHA_CTRL0
- RGA_MODE_BASE_REG
) >> 2] = alpha_ctrl0
.val
;
373 dest
[(RGA_ALPHA_CTRL1
- RGA_MODE_BASE_REG
) >> 2] = alpha_ctrl1
.val
;
375 dest
[(RGA_MODE_CTRL
- RGA_MODE_BASE_REG
) >> 2] = mode
.val
;
378 static void rga_cmd_set(struct rga_ctx
*ctx
)
380 struct rockchip_rga
*rga
= ctx
->rga
;
382 memset(rga
->cmdbuf_virt
, 0, RGA_CMDBUF_SIZE
* 4);
384 rga_cmd_set_src_addr(ctx
, rga
->src_mmu_pages
);
386 * Due to hardware bug,
387 * src1 mmu also should be configured when using alpha blending.
389 rga_cmd_set_src1_addr(ctx
, rga
->dst_mmu_pages
);
391 rga_cmd_set_dst_addr(ctx
, rga
->dst_mmu_pages
);
392 rga_cmd_set_mode(ctx
);
394 rga_cmd_set_trans_info(ctx
);
396 rga_write(rga
, RGA_CMD_BASE
, rga
->cmdbuf_phy
);
398 /* sync CMD buf for RGA */
399 dma_sync_single_for_device(rga
->dev
, rga
->cmdbuf_phy
,
400 PAGE_SIZE
, DMA_BIDIRECTIONAL
);
403 void rga_hw_start(struct rockchip_rga
*rga
)
405 struct rga_ctx
*ctx
= rga
->curr
;
409 rga_write(rga
, RGA_SYS_CTRL
, 0x00);
411 rga_write(rga
, RGA_SYS_CTRL
, 0x22);
413 rga_write(rga
, RGA_INT
, 0x600);
415 rga_write(rga
, RGA_CMD_CTRL
, 0x1);