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