1 /* SPDX-License-Identifier: Apache-2.0 */
2 /*
3 * Copyright (c) 2025 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "vepu580_common"
7
8 #include "mpp_debug.h"
9 #include "vepu580_common.h"
10
vepu580_set_osd(Vepu5xxOsdCfg * cfg)11 MPP_RET vepu580_set_osd(Vepu5xxOsdCfg *cfg)
12 {
13 Vepu580OsdReg *regs = (Vepu580OsdReg *)cfg->reg_base;
14 MppDev dev = cfg->dev;
15 MppDevRegOffCfgs *reg_cfg = cfg->reg_cfg;
16 MppEncOSDPltCfg *plt_cfg = cfg->plt_cfg;
17 MppEncOSDData2 osd;
18
19 if (copy2osd2(&osd, cfg->osd_data, cfg->osd_data2))
20 return MPP_NOK;
21
22 if (osd.num_region == 0)
23 return MPP_OK;
24
25 if (osd.num_region > 8) {
26 mpp_err_f("do NOT support more than 8 regions invalid num %d\n",
27 osd.num_region);
28 mpp_assert(osd.num_region <= 8);
29 return MPP_NOK;
30 }
31
32 if (plt_cfg->type == MPP_ENC_OSD_PLT_TYPE_USERDEF) {
33 memcpy(regs->plt_data, plt_cfg->plt, sizeof(MppEncOSDPlt));
34 regs->reg3074.osd_plt_cks = 1;
35 regs->reg3074.osd_plt_typ = VEPU5xx_OSD_PLT_TYPE_USERDEF;
36 } else {
37 regs->reg3074.osd_plt_cks = 0;
38 regs->reg3074.osd_plt_typ = VEPU5xx_OSD_PLT_TYPE_DEFAULT;
39 }
40
41 regs->reg3074.osd_e = 0;
42 regs->reg3072.osd_lu_inv_en = 0;
43 regs->reg3072.osd_ch_inv_en = 0;
44 regs->reg3072.osd_lu_inv_msk = 0;
45 regs->reg3072.osd_ch_inv_msk = 0;
46
47 RK_U32 num = osd.num_region;
48 RK_U32 k = 0;
49 MppEncOSDRegion2 *region = osd.region;
50 MppEncOSDRegion2 *tmp = region;
51
52 for (k = 0; k < num; k++, tmp++) {
53 regs->reg3074.osd_e |= tmp->enable << k;
54 regs->reg3072.osd_lu_inv_en |= (tmp->inverse) ? (1 << k) : 0;
55 regs->reg3072.osd_ch_inv_en |= (tmp->inverse) ? (1 << k) : 0;
56
57 if (tmp->enable && tmp->num_mb_x && tmp->num_mb_y) {
58 Vepu580OsdPos *pos = ®s->osd_pos[k];
59 size_t blk_len = tmp->num_mb_x * tmp->num_mb_y * 256;
60 RK_S32 fd = -1;
61 size_t buf_size = 0;
62
63 pos->osd_lt_x = tmp->start_mb_x;
64 pos->osd_lt_y = tmp->start_mb_y;
65 pos->osd_rb_x = tmp->start_mb_x + tmp->num_mb_x - 1;
66 pos->osd_rb_y = tmp->start_mb_y + tmp->num_mb_y - 1;
67
68 buf_size = mpp_buffer_get_size(tmp->buf);
69 fd = mpp_buffer_get_fd(tmp->buf);
70 if (fd < 0) {
71 mpp_err_f("invalid osd buffer fd %d\n", fd);
72 return MPP_NOK;
73 }
74 regs->osd_addr[k] = fd;
75
76 if (tmp->buf_offset) {
77 if (reg_cfg)
78 mpp_dev_multi_offset_update(reg_cfg, VEPU580_OSD_ADDR_IDX_BASE + k, tmp->buf_offset);
79 else
80 mpp_dev_set_reg_offset(dev, VEPU580_OSD_ADDR_IDX_BASE + k, tmp->buf_offset);
81 }
82
83 /* There should be enough buffer and offset should be 16B aligned */
84 if (buf_size < tmp->buf_offset + blk_len ||
85 (tmp->buf_offset & 0xf)) {
86 mpp_err_f("invalid osd cfg: %d x:y:w:h:off %d:%d:%d:%d:%x size %x\n",
87 k, tmp->start_mb_x, tmp->start_mb_y,
88 tmp->num_mb_x, tmp->num_mb_y, tmp->buf_offset, buf_size);
89 }
90 }
91 }
92
93 SET_OSD_INV_THR(0, regs->reg3073, region);
94 SET_OSD_INV_THR(1, regs->reg3073, region);
95 SET_OSD_INV_THR(2, regs->reg3073, region);
96 SET_OSD_INV_THR(3, regs->reg3073, region);
97 SET_OSD_INV_THR(4, regs->reg3073, region);
98 SET_OSD_INV_THR(5, regs->reg3073, region);
99 SET_OSD_INV_THR(6, regs->reg3073, region);
100 SET_OSD_INV_THR(7, regs->reg3073, region);
101
102 return MPP_OK;
103 }
104