xref: /rockchip-linux_mpp/mpp/hal/rkenc/common/vepu580_common.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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 = &regs->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