1*437bfbebSnyanmisaka /*
2*437bfbebSnyanmisaka * Copyright 2015 Rockchip Electronics Co. LTD
3*437bfbebSnyanmisaka *
4*437bfbebSnyanmisaka * Licensed under the Apache License, Version 2.0 (the "License");
5*437bfbebSnyanmisaka * you may not use this file except in compliance with the License.
6*437bfbebSnyanmisaka * You may obtain a copy of the License at
7*437bfbebSnyanmisaka *
8*437bfbebSnyanmisaka * http://www.apache.org/licenses/LICENSE-2.0
9*437bfbebSnyanmisaka *
10*437bfbebSnyanmisaka * Unless required by applicable law or agreed to in writing, software
11*437bfbebSnyanmisaka * distributed under the License is distributed on an "AS IS" BASIS,
12*437bfbebSnyanmisaka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*437bfbebSnyanmisaka * See the License for the specific language governing permissions and
14*437bfbebSnyanmisaka * limitations under the License.
15*437bfbebSnyanmisaka */
16*437bfbebSnyanmisaka
17*437bfbebSnyanmisaka #define MODULE_TAG "vepu541_common"
18*437bfbebSnyanmisaka
19*437bfbebSnyanmisaka #include <string.h>
20*437bfbebSnyanmisaka
21*437bfbebSnyanmisaka #include "mpp_mem.h"
22*437bfbebSnyanmisaka #include "mpp_debug.h"
23*437bfbebSnyanmisaka #include "mpp_common.h"
24*437bfbebSnyanmisaka #include "vepu5xx_common.h"
25*437bfbebSnyanmisaka #include "vepu541_common.h"
26*437bfbebSnyanmisaka
vepu541_get_roi_buf_size(RK_S32 w,RK_S32 h)27*437bfbebSnyanmisaka RK_S32 vepu541_get_roi_buf_size(RK_S32 w, RK_S32 h)
28*437bfbebSnyanmisaka {
29*437bfbebSnyanmisaka RK_S32 stride_h = MPP_ALIGN(w, 64) / 16;
30*437bfbebSnyanmisaka RK_S32 stride_v = MPP_ALIGN(h, 64) / 16;
31*437bfbebSnyanmisaka RK_S32 buf_size = stride_h * stride_v * sizeof(Vepu541RoiCfg);
32*437bfbebSnyanmisaka
33*437bfbebSnyanmisaka /* extra 32 byte for hardware access padding */
34*437bfbebSnyanmisaka return buf_size + 32;
35*437bfbebSnyanmisaka }
36*437bfbebSnyanmisaka
vepu541_set_one_roi(void * buf,MppEncROIRegion * region,RK_S32 w,RK_S32 h)37*437bfbebSnyanmisaka MPP_RET vepu541_set_one_roi(void *buf, MppEncROIRegion *region, RK_S32 w, RK_S32 h)
38*437bfbebSnyanmisaka {
39*437bfbebSnyanmisaka Vepu541RoiCfg *ptr = (Vepu541RoiCfg *)buf;
40*437bfbebSnyanmisaka RK_S32 mb_w = MPP_ALIGN(w, 16) / 16;
41*437bfbebSnyanmisaka RK_S32 mb_h = MPP_ALIGN(h, 16) / 16;
42*437bfbebSnyanmisaka RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
43*437bfbebSnyanmisaka Vepu541RoiCfg cfg;
44*437bfbebSnyanmisaka MPP_RET ret = MPP_NOK;
45*437bfbebSnyanmisaka
46*437bfbebSnyanmisaka if (NULL == buf || NULL == region) {
47*437bfbebSnyanmisaka mpp_err_f("invalid buf %p roi %p\n", buf, region);
48*437bfbebSnyanmisaka goto DONE;
49*437bfbebSnyanmisaka }
50*437bfbebSnyanmisaka
51*437bfbebSnyanmisaka RK_S32 roi_width = (region->w + 15) / 16;
52*437bfbebSnyanmisaka RK_S32 roi_height = (region->h + 15) / 16;
53*437bfbebSnyanmisaka RK_S32 pos_x_init = region->x / 16;
54*437bfbebSnyanmisaka RK_S32 pos_y_init = region->y / 16;
55*437bfbebSnyanmisaka RK_S32 pos_x_end = pos_x_init + roi_width;
56*437bfbebSnyanmisaka RK_S32 pos_y_end = pos_y_init + roi_height;
57*437bfbebSnyanmisaka RK_S32 x, y;
58*437bfbebSnyanmisaka
59*437bfbebSnyanmisaka pos_x_end = MPP_MIN(pos_x_end, mb_w);
60*437bfbebSnyanmisaka pos_y_end = MPP_MIN(pos_y_end, mb_h);
61*437bfbebSnyanmisaka pos_x_init = MPP_MAX(pos_x_init, 0);
62*437bfbebSnyanmisaka pos_y_init = MPP_MAX(pos_y_init, 0);
63*437bfbebSnyanmisaka
64*437bfbebSnyanmisaka mpp_assert(pos_x_end > pos_x_init);
65*437bfbebSnyanmisaka mpp_assert(pos_y_end > pos_y_init);
66*437bfbebSnyanmisaka
67*437bfbebSnyanmisaka cfg.force_intra = region->intra;
68*437bfbebSnyanmisaka cfg.reserved = 0;
69*437bfbebSnyanmisaka cfg.qp_area_idx = region->qp_area_idx;
70*437bfbebSnyanmisaka // NOTE: When roi is enabled the qp_area_en should be one.
71*437bfbebSnyanmisaka cfg.qp_area_en = 1; // region->area_map_en;
72*437bfbebSnyanmisaka cfg.qp_adj = region->quality;
73*437bfbebSnyanmisaka cfg.qp_adj_mode = region->abs_qp_en;
74*437bfbebSnyanmisaka
75*437bfbebSnyanmisaka ptr += pos_y_init * stride_h + pos_x_init;
76*437bfbebSnyanmisaka roi_width = pos_x_end - pos_x_init;
77*437bfbebSnyanmisaka roi_height = pos_y_end - pos_y_init;
78*437bfbebSnyanmisaka
79*437bfbebSnyanmisaka for (y = 0; y < roi_height; y++) {
80*437bfbebSnyanmisaka Vepu541RoiCfg *dst = ptr;
81*437bfbebSnyanmisaka
82*437bfbebSnyanmisaka for (x = 0; x < roi_width; x++, dst++)
83*437bfbebSnyanmisaka memcpy(dst, &cfg, sizeof(cfg));
84*437bfbebSnyanmisaka
85*437bfbebSnyanmisaka ptr += stride_h;
86*437bfbebSnyanmisaka }
87*437bfbebSnyanmisaka DONE:
88*437bfbebSnyanmisaka return ret;
89*437bfbebSnyanmisaka }
90*437bfbebSnyanmisaka
vepu541_set_roi(void * buf,MppEncROICfg * roi,RK_S32 w,RK_S32 h)91*437bfbebSnyanmisaka MPP_RET vepu541_set_roi(void *buf, MppEncROICfg *roi, RK_S32 w, RK_S32 h)
92*437bfbebSnyanmisaka {
93*437bfbebSnyanmisaka MppEncROIRegion *region = roi->regions;
94*437bfbebSnyanmisaka Vepu541RoiCfg *ptr = (Vepu541RoiCfg *)buf;
95*437bfbebSnyanmisaka RK_S32 mb_w = MPP_ALIGN(w, 16) / 16;
96*437bfbebSnyanmisaka RK_S32 mb_h = MPP_ALIGN(h, 16) / 16;
97*437bfbebSnyanmisaka RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
98*437bfbebSnyanmisaka RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
99*437bfbebSnyanmisaka Vepu541RoiCfg cfg;
100*437bfbebSnyanmisaka MPP_RET ret = MPP_NOK;
101*437bfbebSnyanmisaka RK_S32 i;
102*437bfbebSnyanmisaka
103*437bfbebSnyanmisaka if (NULL == buf || NULL == roi) {
104*437bfbebSnyanmisaka mpp_err_f("invalid buf %p roi %p\n", buf, roi);
105*437bfbebSnyanmisaka goto DONE;
106*437bfbebSnyanmisaka }
107*437bfbebSnyanmisaka
108*437bfbebSnyanmisaka cfg.force_intra = 0;
109*437bfbebSnyanmisaka cfg.reserved = 0;
110*437bfbebSnyanmisaka cfg.qp_area_idx = 0;
111*437bfbebSnyanmisaka cfg.qp_area_en = 1;
112*437bfbebSnyanmisaka cfg.qp_adj = 0;
113*437bfbebSnyanmisaka cfg.qp_adj_mode = 0;
114*437bfbebSnyanmisaka
115*437bfbebSnyanmisaka /* step 1. reset all the config */
116*437bfbebSnyanmisaka for (i = 0; i < stride_h * stride_v; i++, ptr++)
117*437bfbebSnyanmisaka memcpy(ptr, &cfg, sizeof(cfg));
118*437bfbebSnyanmisaka
119*437bfbebSnyanmisaka if (w <= 0 || h <= 0) {
120*437bfbebSnyanmisaka mpp_err_f("invalid size [%d:%d]\n", w, h);
121*437bfbebSnyanmisaka goto DONE;
122*437bfbebSnyanmisaka }
123*437bfbebSnyanmisaka
124*437bfbebSnyanmisaka if (roi->number > VEPU541_MAX_ROI_NUM) {
125*437bfbebSnyanmisaka mpp_err_f("invalid region number %d\n", roi->number);
126*437bfbebSnyanmisaka goto DONE;
127*437bfbebSnyanmisaka }
128*437bfbebSnyanmisaka
129*437bfbebSnyanmisaka /* check region config */
130*437bfbebSnyanmisaka ret = MPP_OK;
131*437bfbebSnyanmisaka for (i = 0; i < (RK_S32)roi->number; i++, region++) {
132*437bfbebSnyanmisaka if (region->x + region->w > w || region->y + region->h > h)
133*437bfbebSnyanmisaka ret = MPP_NOK;
134*437bfbebSnyanmisaka
135*437bfbebSnyanmisaka if (region->intra > 1 || region->qp_area_idx >= VEPU541_MAX_ROI_NUM ||
136*437bfbebSnyanmisaka region->area_map_en > 1 || region->abs_qp_en > 1)
137*437bfbebSnyanmisaka ret = MPP_NOK;
138*437bfbebSnyanmisaka
139*437bfbebSnyanmisaka if ((region->abs_qp_en && region->quality > 51) ||
140*437bfbebSnyanmisaka (!region->abs_qp_en && (region->quality > 51 || region->quality < -51)))
141*437bfbebSnyanmisaka ret = MPP_NOK;
142*437bfbebSnyanmisaka
143*437bfbebSnyanmisaka if (ret) {
144*437bfbebSnyanmisaka mpp_err_f("region %d invalid param:\n", i);
145*437bfbebSnyanmisaka mpp_err_f("position [%d:%d:%d:%d] vs [%d:%d]\n",
146*437bfbebSnyanmisaka region->x, region->y, region->w, region->h, w, h);
147*437bfbebSnyanmisaka mpp_err_f("force intra %d qp area index %d\n",
148*437bfbebSnyanmisaka region->intra, region->qp_area_idx);
149*437bfbebSnyanmisaka mpp_err_f("abs qp mode %d value %d\n",
150*437bfbebSnyanmisaka region->abs_qp_en, region->quality);
151*437bfbebSnyanmisaka goto DONE;
152*437bfbebSnyanmisaka }
153*437bfbebSnyanmisaka }
154*437bfbebSnyanmisaka
155*437bfbebSnyanmisaka region = roi->regions;
156*437bfbebSnyanmisaka /* step 2. setup region for top to bottom */
157*437bfbebSnyanmisaka for (i = 0; i < (RK_S32)roi->number; i++, region++) {
158*437bfbebSnyanmisaka vepu541_set_one_roi(buf, region, w, h);
159*437bfbebSnyanmisaka }
160*437bfbebSnyanmisaka
161*437bfbebSnyanmisaka DONE:
162*437bfbebSnyanmisaka return ret;
163*437bfbebSnyanmisaka }
164*437bfbebSnyanmisaka
165*437bfbebSnyanmisaka /*
166*437bfbebSnyanmisaka * Invert color threshold is for the absolute difference between background
167*437bfbebSnyanmisaka * and foregroud color.
168*437bfbebSnyanmisaka * If background color and foregroud color are close enough then trigger the
169*437bfbebSnyanmisaka * invert color process.
170*437bfbebSnyanmisaka */
171*437bfbebSnyanmisaka #define ENC_DEFAULT_OSD_INV_THR 15
172*437bfbebSnyanmisaka
173*437bfbebSnyanmisaka #define VEPU541_OSD_ADDR_IDX_BASE 124
174*437bfbebSnyanmisaka
175*437bfbebSnyanmisaka #define VEPU541_OSD_CFG_OFFSET 0x01C0
176*437bfbebSnyanmisaka #define VEPU541_OSD_PLT_OFFSET 0x0400
177*437bfbebSnyanmisaka
178*437bfbebSnyanmisaka typedef struct Vepu541OsdReg_t {
179*437bfbebSnyanmisaka /*
180*437bfbebSnyanmisaka * OSD_CFG
181*437bfbebSnyanmisaka * Address offset: 0x01C0 Access type: read and write
182*437bfbebSnyanmisaka * OSD configuration
183*437bfbebSnyanmisaka */
184*437bfbebSnyanmisaka struct {
185*437bfbebSnyanmisaka /* OSD region enable, each bit controls corresponding OSD region. */
186*437bfbebSnyanmisaka RK_U32 osd_e : 8;
187*437bfbebSnyanmisaka /* OSD inverse color enable, each bit controls corresponding region. */
188*437bfbebSnyanmisaka RK_U32 osd_inv_e : 8;
189*437bfbebSnyanmisaka /*
190*437bfbebSnyanmisaka * OSD palette clock selection.
191*437bfbebSnyanmisaka * 1'h0: Configure bus clock domain.
192*437bfbebSnyanmisaka * 1'h1: Core clock domain.
193*437bfbebSnyanmisaka */
194*437bfbebSnyanmisaka RK_U32 osd_plt_cks : 1;
195*437bfbebSnyanmisaka /*
196*437bfbebSnyanmisaka * OSD palette type.
197*437bfbebSnyanmisaka * 1'h1: Default type.
198*437bfbebSnyanmisaka * 1'h0: User defined type.
199*437bfbebSnyanmisaka */
200*437bfbebSnyanmisaka RK_U32 osd_plt_typ : 1;
201*437bfbebSnyanmisaka RK_U32 reserved : 14;
202*437bfbebSnyanmisaka } reg112;
203*437bfbebSnyanmisaka
204*437bfbebSnyanmisaka /*
205*437bfbebSnyanmisaka * OSD_INV
206*437bfbebSnyanmisaka * Address offset: 0x01C4 Access type: read and write
207*437bfbebSnyanmisaka * OSD color inverse configuration
208*437bfbebSnyanmisaka */
209*437bfbebSnyanmisaka struct {
210*437bfbebSnyanmisaka /* Color inverse theshold for OSD region0. */
211*437bfbebSnyanmisaka RK_U32 osd_ithd_r0 : 4;
212*437bfbebSnyanmisaka /* Color inverse theshold for OSD region1. */
213*437bfbebSnyanmisaka RK_U32 osd_ithd_r1 : 4;
214*437bfbebSnyanmisaka /* Color inverse theshold for OSD region2. */
215*437bfbebSnyanmisaka RK_U32 osd_ithd_r2 : 4;
216*437bfbebSnyanmisaka /* Color inverse theshold for OSD region3. */
217*437bfbebSnyanmisaka RK_U32 osd_ithd_r3 : 4;
218*437bfbebSnyanmisaka /* Color inverse theshold for OSD region4. */
219*437bfbebSnyanmisaka RK_U32 osd_ithd_r4 : 4;
220*437bfbebSnyanmisaka /* Color inverse theshold for OSD region5. */
221*437bfbebSnyanmisaka RK_U32 osd_ithd_r5 : 4;
222*437bfbebSnyanmisaka /* Color inverse theshold for OSD region6. */
223*437bfbebSnyanmisaka RK_U32 osd_ithd_r6 : 4;
224*437bfbebSnyanmisaka /* Color inverse theshold for OSD region7. */
225*437bfbebSnyanmisaka RK_U32 osd_ithd_r7 : 4;
226*437bfbebSnyanmisaka } reg113;
227*437bfbebSnyanmisaka
228*437bfbebSnyanmisaka RK_U32 reg114;
229*437bfbebSnyanmisaka RK_U32 reg115;
230*437bfbebSnyanmisaka
231*437bfbebSnyanmisaka /*
232*437bfbebSnyanmisaka * OSD_POS reg116_123
233*437bfbebSnyanmisaka * Address offset: 0x01D0~0x01EC Access type: read and write
234*437bfbebSnyanmisaka * OSD region position
235*437bfbebSnyanmisaka */
236*437bfbebSnyanmisaka Vepu541OsdPos osd_pos[8];
237*437bfbebSnyanmisaka
238*437bfbebSnyanmisaka /*
239*437bfbebSnyanmisaka * ADR_OSD reg124_131
240*437bfbebSnyanmisaka * Address offset: 0x01F0~0x20C Access type: read and write
241*437bfbebSnyanmisaka * Base address for OSD region, 16B aligned
242*437bfbebSnyanmisaka */
243*437bfbebSnyanmisaka RK_U32 osd_addr[8];
244*437bfbebSnyanmisaka } Vepu541OsdReg;
245*437bfbebSnyanmisaka
vepu541_set_osd(Vepu5xxOsdCfg * cfg)246*437bfbebSnyanmisaka MPP_RET vepu541_set_osd(Vepu5xxOsdCfg *cfg)
247*437bfbebSnyanmisaka {
248*437bfbebSnyanmisaka Vepu541OsdReg *regs = (Vepu541OsdReg *)(cfg->reg_base + (size_t)VEPU541_OSD_CFG_OFFSET);
249*437bfbebSnyanmisaka MppDev dev = cfg->dev;
250*437bfbebSnyanmisaka MppEncOSDPltCfg *plt_cfg = cfg->plt_cfg;
251*437bfbebSnyanmisaka MppEncOSDData2 osd;
252*437bfbebSnyanmisaka
253*437bfbebSnyanmisaka if (copy2osd2(&osd, cfg->osd_data, cfg->osd_data2))
254*437bfbebSnyanmisaka return MPP_NOK;
255*437bfbebSnyanmisaka
256*437bfbebSnyanmisaka if (osd.num_region == 0)
257*437bfbebSnyanmisaka return MPP_OK;
258*437bfbebSnyanmisaka
259*437bfbebSnyanmisaka if (osd.num_region > 8) {
260*437bfbebSnyanmisaka mpp_err_f("do NOT support more than 8 regions invalid num %d\n",
261*437bfbebSnyanmisaka osd.num_region);
262*437bfbebSnyanmisaka mpp_assert(osd.num_region <= 8);
263*437bfbebSnyanmisaka return MPP_NOK;
264*437bfbebSnyanmisaka }
265*437bfbebSnyanmisaka
266*437bfbebSnyanmisaka if (plt_cfg->type == MPP_ENC_OSD_PLT_TYPE_USERDEF) {
267*437bfbebSnyanmisaka MppDevRegWrCfg wr_cfg;
268*437bfbebSnyanmisaka
269*437bfbebSnyanmisaka wr_cfg.reg = plt_cfg->plt;
270*437bfbebSnyanmisaka wr_cfg.size = sizeof(MppEncOSDPlt);
271*437bfbebSnyanmisaka wr_cfg.offset = VEPU541_REG_BASE_OSD_PLT;
272*437bfbebSnyanmisaka
273*437bfbebSnyanmisaka mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg);
274*437bfbebSnyanmisaka
275*437bfbebSnyanmisaka regs->reg112.osd_plt_cks = 1;
276*437bfbebSnyanmisaka regs->reg112.osd_plt_typ = VEPU5xx_OSD_PLT_TYPE_USERDEF;
277*437bfbebSnyanmisaka } else {
278*437bfbebSnyanmisaka regs->reg112.osd_plt_cks = 0;
279*437bfbebSnyanmisaka regs->reg112.osd_plt_typ = VEPU5xx_OSD_PLT_TYPE_DEFAULT;
280*437bfbebSnyanmisaka }
281*437bfbebSnyanmisaka
282*437bfbebSnyanmisaka regs->reg112.osd_e = 0;
283*437bfbebSnyanmisaka regs->reg112.osd_inv_e = 0;
284*437bfbebSnyanmisaka
285*437bfbebSnyanmisaka RK_U32 i = 0;
286*437bfbebSnyanmisaka MppEncOSDRegion2 *region = osd.region;
287*437bfbebSnyanmisaka MppEncOSDRegion2 *tmp = region;
288*437bfbebSnyanmisaka RK_U32 num = osd.num_region;
289*437bfbebSnyanmisaka
290*437bfbebSnyanmisaka for (i = 0; i < num; i++, tmp++) {
291*437bfbebSnyanmisaka regs->reg112.osd_e |= tmp->enable << i;
292*437bfbebSnyanmisaka regs->reg112.osd_inv_e |= tmp->inverse << i;
293*437bfbebSnyanmisaka
294*437bfbebSnyanmisaka if (tmp->enable && tmp->num_mb_x && tmp->num_mb_y) {
295*437bfbebSnyanmisaka Vepu541OsdPos *pos = ®s->osd_pos[i];
296*437bfbebSnyanmisaka size_t blk_len = tmp->num_mb_x * tmp->num_mb_y * 256;
297*437bfbebSnyanmisaka RK_S32 fd = 0;
298*437bfbebSnyanmisaka RK_U32 buf_size = 0;
299*437bfbebSnyanmisaka
300*437bfbebSnyanmisaka pos->osd_lt_x = tmp->start_mb_x;
301*437bfbebSnyanmisaka pos->osd_lt_y = tmp->start_mb_y;
302*437bfbebSnyanmisaka pos->osd_rb_x = tmp->start_mb_x + tmp->num_mb_x - 1;
303*437bfbebSnyanmisaka pos->osd_rb_y = tmp->start_mb_y + tmp->num_mb_y - 1;
304*437bfbebSnyanmisaka
305*437bfbebSnyanmisaka buf_size = mpp_buffer_get_size(tmp->buf);
306*437bfbebSnyanmisaka fd = mpp_buffer_get_fd(tmp->buf);
307*437bfbebSnyanmisaka if (fd < 0) {
308*437bfbebSnyanmisaka mpp_err_f("invalid osd buffer fd %d\n", fd);
309*437bfbebSnyanmisaka return MPP_NOK;
310*437bfbebSnyanmisaka }
311*437bfbebSnyanmisaka regs->osd_addr[i] = fd;
312*437bfbebSnyanmisaka
313*437bfbebSnyanmisaka if (tmp->buf_offset)
314*437bfbebSnyanmisaka mpp_dev_set_reg_offset(dev, VEPU541_OSD_ADDR_IDX_BASE + i, tmp->buf_offset);
315*437bfbebSnyanmisaka
316*437bfbebSnyanmisaka /* There should be enough buffer and offset should be 16B aligned */
317*437bfbebSnyanmisaka if (buf_size < tmp->buf_offset + blk_len ||
318*437bfbebSnyanmisaka (tmp->buf_offset & 0xf)) {
319*437bfbebSnyanmisaka mpp_err_f("invalid osd cfg: %d x:y:w:h:off %d:%d:%d:%d:%x\n",
320*437bfbebSnyanmisaka i, tmp->start_mb_x, tmp->start_mb_y,
321*437bfbebSnyanmisaka tmp->num_mb_x, tmp->num_mb_y, tmp->buf_offset);
322*437bfbebSnyanmisaka }
323*437bfbebSnyanmisaka }
324*437bfbebSnyanmisaka }
325*437bfbebSnyanmisaka
326*437bfbebSnyanmisaka SET_OSD_INV_THR(0, regs->reg113, region);
327*437bfbebSnyanmisaka SET_OSD_INV_THR(1, regs->reg113, region);
328*437bfbebSnyanmisaka SET_OSD_INV_THR(2, regs->reg113, region);
329*437bfbebSnyanmisaka SET_OSD_INV_THR(3, regs->reg113, region);
330*437bfbebSnyanmisaka SET_OSD_INV_THR(4, regs->reg113, region);
331*437bfbebSnyanmisaka SET_OSD_INV_THR(5, regs->reg113, region);
332*437bfbebSnyanmisaka SET_OSD_INV_THR(6, regs->reg113, region);
333*437bfbebSnyanmisaka SET_OSD_INV_THR(7, regs->reg113, region);
334*437bfbebSnyanmisaka
335*437bfbebSnyanmisaka return MPP_OK;
336*437bfbebSnyanmisaka }
337*437bfbebSnyanmisaka
338*437bfbebSnyanmisaka #define VEPU540_OSD_CFG_OFFSET 0x0178
339*437bfbebSnyanmisaka
340*437bfbebSnyanmisaka typedef struct Vepu540OsdReg_t {
341*437bfbebSnyanmisaka /*
342*437bfbebSnyanmisaka * OSD_INV_CFG
343*437bfbebSnyanmisaka * Address offset: 0x0178 Access type: read and write
344*437bfbebSnyanmisaka * OSD color inverse configuration
345*437bfbebSnyanmisaka */
346*437bfbebSnyanmisaka struct {
347*437bfbebSnyanmisaka /*
348*437bfbebSnyanmisaka * OSD color inverse enable of chroma component,
349*437bfbebSnyanmisaka * each bit controls corresponding region.
350*437bfbebSnyanmisaka */
351*437bfbebSnyanmisaka RK_U32 osd_ch_inv_en : 8;
352*437bfbebSnyanmisaka /*
353*437bfbebSnyanmisaka * OSD color inverse expression type
354*437bfbebSnyanmisaka * each bit controls corresponding region.
355*437bfbebSnyanmisaka * 1'h0: AND;
356*437bfbebSnyanmisaka * 1'h1: OR
357*437bfbebSnyanmisaka */
358*437bfbebSnyanmisaka RK_U32 osd_itype : 8;
359*437bfbebSnyanmisaka /*
360*437bfbebSnyanmisaka * OSD color inverse expression switch for luma component
361*437bfbebSnyanmisaka * each bit controls corresponding region.
362*437bfbebSnyanmisaka * 1'h0: Expression need to determine the condition;
363*437bfbebSnyanmisaka * 1'h1: Expression don't need to determine the condition;
364*437bfbebSnyanmisaka */
365*437bfbebSnyanmisaka RK_U32 osd_lu_inv_msk : 8;
366*437bfbebSnyanmisaka /*
367*437bfbebSnyanmisaka * OSD color inverse expression switch for chroma component
368*437bfbebSnyanmisaka * each bit controls corresponding region.
369*437bfbebSnyanmisaka * 1'h0: Expression need to determine the condition;
370*437bfbebSnyanmisaka * 1'h1: Expression don't need to determine the condition;
371*437bfbebSnyanmisaka */
372*437bfbebSnyanmisaka RK_U32 osd_ch_inv_msk : 8;
373*437bfbebSnyanmisaka } reg094;
374*437bfbebSnyanmisaka
375*437bfbebSnyanmisaka /* reg gap 095~111 */
376*437bfbebSnyanmisaka RK_U32 reg_095_111[17];
377*437bfbebSnyanmisaka
378*437bfbebSnyanmisaka /*
379*437bfbebSnyanmisaka * OSD_CFG
380*437bfbebSnyanmisaka * Address offset: 0x01C0 Access type: read and write
381*437bfbebSnyanmisaka * OSD configuration
382*437bfbebSnyanmisaka */
383*437bfbebSnyanmisaka struct {
384*437bfbebSnyanmisaka /* OSD region enable, each bit controls corresponding OSD region. */
385*437bfbebSnyanmisaka RK_U32 osd_e : 8;
386*437bfbebSnyanmisaka /* OSD inverse color enable, each bit controls corresponding region. */
387*437bfbebSnyanmisaka RK_U32 osd_lu_inv_en : 8;
388*437bfbebSnyanmisaka /*
389*437bfbebSnyanmisaka * OSD palette clock selection.
390*437bfbebSnyanmisaka * 1'h0: Configure bus clock domain.
391*437bfbebSnyanmisaka * 1'h1: Core clock domain.
392*437bfbebSnyanmisaka */
393*437bfbebSnyanmisaka RK_U32 osd_plt_cks : 1;
394*437bfbebSnyanmisaka /*
395*437bfbebSnyanmisaka * OSD palette type.
396*437bfbebSnyanmisaka * 1'h1: Default type.
397*437bfbebSnyanmisaka * 1'h0: User defined type.
398*437bfbebSnyanmisaka */
399*437bfbebSnyanmisaka RK_U32 osd_plt_typ : 1;
400*437bfbebSnyanmisaka RK_U32 reserved : 14;
401*437bfbebSnyanmisaka } reg112;
402*437bfbebSnyanmisaka
403*437bfbebSnyanmisaka /*
404*437bfbebSnyanmisaka * OSD_INV
405*437bfbebSnyanmisaka * Address offset: 0x01C4 Access type: read and write
406*437bfbebSnyanmisaka * OSD color inverse configuration
407*437bfbebSnyanmisaka */
408*437bfbebSnyanmisaka struct {
409*437bfbebSnyanmisaka /* Color inverse theshold for OSD region0. */
410*437bfbebSnyanmisaka RK_U32 osd_ithd_r0 : 4;
411*437bfbebSnyanmisaka /* Color inverse theshold for OSD region1. */
412*437bfbebSnyanmisaka RK_U32 osd_ithd_r1 : 4;
413*437bfbebSnyanmisaka /* Color inverse theshold for OSD region2. */
414*437bfbebSnyanmisaka RK_U32 osd_ithd_r2 : 4;
415*437bfbebSnyanmisaka /* Color inverse theshold for OSD region3. */
416*437bfbebSnyanmisaka RK_U32 osd_ithd_r3 : 4;
417*437bfbebSnyanmisaka /* Color inverse theshold for OSD region4. */
418*437bfbebSnyanmisaka RK_U32 osd_ithd_r4 : 4;
419*437bfbebSnyanmisaka /* Color inverse theshold for OSD region5. */
420*437bfbebSnyanmisaka RK_U32 osd_ithd_r5 : 4;
421*437bfbebSnyanmisaka /* Color inverse theshold for OSD region6. */
422*437bfbebSnyanmisaka RK_U32 osd_ithd_r6 : 4;
423*437bfbebSnyanmisaka /* Color inverse theshold for OSD region7. */
424*437bfbebSnyanmisaka RK_U32 osd_ithd_r7 : 4;
425*437bfbebSnyanmisaka } reg113;
426*437bfbebSnyanmisaka
427*437bfbebSnyanmisaka RK_U32 reg114;
428*437bfbebSnyanmisaka RK_U32 reg115;
429*437bfbebSnyanmisaka
430*437bfbebSnyanmisaka /*
431*437bfbebSnyanmisaka * OSD_POS reg116_123
432*437bfbebSnyanmisaka * Address offset: 0x01D0~0x01EC Access type: read and write
433*437bfbebSnyanmisaka * OSD region position
434*437bfbebSnyanmisaka */
435*437bfbebSnyanmisaka Vepu541OsdPos osd_pos[8];
436*437bfbebSnyanmisaka
437*437bfbebSnyanmisaka /*
438*437bfbebSnyanmisaka * ADR_OSD reg124_131
439*437bfbebSnyanmisaka * Address offset: 0x01F0~0x20C Access type: read and write
440*437bfbebSnyanmisaka * Base address for OSD region, 16B aligned
441*437bfbebSnyanmisaka */
442*437bfbebSnyanmisaka RK_U32 osd_addr[8];
443*437bfbebSnyanmisaka } Vepu540OsdReg;
444*437bfbebSnyanmisaka
vepu540_set_osd(Vepu5xxOsdCfg * cfg)445*437bfbebSnyanmisaka MPP_RET vepu540_set_osd(Vepu5xxOsdCfg *cfg)
446*437bfbebSnyanmisaka {
447*437bfbebSnyanmisaka Vepu540OsdReg *regs = (Vepu540OsdReg *)(cfg->reg_base + (size_t)VEPU540_OSD_CFG_OFFSET);
448*437bfbebSnyanmisaka MppDev dev = cfg->dev;
449*437bfbebSnyanmisaka MppEncOSDPltCfg *plt_cfg = cfg->plt_cfg;
450*437bfbebSnyanmisaka MppEncOSDData2 osd;
451*437bfbebSnyanmisaka
452*437bfbebSnyanmisaka if (copy2osd2(&osd, cfg->osd_data, cfg->osd_data2))
453*437bfbebSnyanmisaka return MPP_NOK;
454*437bfbebSnyanmisaka
455*437bfbebSnyanmisaka if (osd.num_region == 0)
456*437bfbebSnyanmisaka return MPP_OK;
457*437bfbebSnyanmisaka
458*437bfbebSnyanmisaka if (osd.num_region > 8) {
459*437bfbebSnyanmisaka mpp_err_f("do NOT support more than 8 regions invalid num %d\n",
460*437bfbebSnyanmisaka osd.num_region);
461*437bfbebSnyanmisaka mpp_assert(osd.num_region <= 8);
462*437bfbebSnyanmisaka return MPP_NOK;
463*437bfbebSnyanmisaka }
464*437bfbebSnyanmisaka
465*437bfbebSnyanmisaka if (plt_cfg->type == MPP_ENC_OSD_PLT_TYPE_USERDEF) {
466*437bfbebSnyanmisaka MppDevRegWrCfg wr_cfg;
467*437bfbebSnyanmisaka
468*437bfbebSnyanmisaka wr_cfg.reg = plt_cfg->plt;
469*437bfbebSnyanmisaka wr_cfg.size = sizeof(MppEncOSDPlt);
470*437bfbebSnyanmisaka wr_cfg.offset = VEPU541_REG_BASE_OSD_PLT;
471*437bfbebSnyanmisaka mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg);
472*437bfbebSnyanmisaka
473*437bfbebSnyanmisaka regs->reg112.osd_plt_cks = 1;
474*437bfbebSnyanmisaka regs->reg112.osd_plt_typ = VEPU5xx_OSD_PLT_TYPE_USERDEF;
475*437bfbebSnyanmisaka } else {
476*437bfbebSnyanmisaka regs->reg112.osd_plt_cks = 0;
477*437bfbebSnyanmisaka regs->reg112.osd_plt_typ = VEPU5xx_OSD_PLT_TYPE_DEFAULT;
478*437bfbebSnyanmisaka }
479*437bfbebSnyanmisaka
480*437bfbebSnyanmisaka regs->reg112.osd_e = 0;
481*437bfbebSnyanmisaka regs->reg112.osd_lu_inv_en = 0;
482*437bfbebSnyanmisaka regs->reg094.osd_ch_inv_en = 0;
483*437bfbebSnyanmisaka regs->reg094.osd_lu_inv_msk = 0;
484*437bfbebSnyanmisaka
485*437bfbebSnyanmisaka RK_U32 num = osd.num_region;
486*437bfbebSnyanmisaka RK_U32 k = 0;
487*437bfbebSnyanmisaka MppEncOSDRegion2 *region = osd.region;
488*437bfbebSnyanmisaka MppEncOSDRegion2 *tmp = region;
489*437bfbebSnyanmisaka
490*437bfbebSnyanmisaka for (k = 0; k < num; k++, tmp++) {
491*437bfbebSnyanmisaka regs->reg112.osd_e |= tmp->enable << k;
492*437bfbebSnyanmisaka regs->reg112.osd_lu_inv_en |= (tmp->inverse) ? (1 << k) : 0;
493*437bfbebSnyanmisaka regs->reg094.osd_ch_inv_en |= (tmp->inverse) ? (1 << k) : 0;
494*437bfbebSnyanmisaka
495*437bfbebSnyanmisaka if (tmp->enable && tmp->num_mb_x && tmp->num_mb_y) {
496*437bfbebSnyanmisaka Vepu541OsdPos *pos = ®s->osd_pos[k];
497*437bfbebSnyanmisaka size_t blk_len = tmp->num_mb_x * tmp->num_mb_y * 256;
498*437bfbebSnyanmisaka RK_S32 fd = -1;
499*437bfbebSnyanmisaka size_t buf_size = 0;
500*437bfbebSnyanmisaka
501*437bfbebSnyanmisaka pos->osd_lt_x = tmp->start_mb_x;
502*437bfbebSnyanmisaka pos->osd_lt_y = tmp->start_mb_y;
503*437bfbebSnyanmisaka pos->osd_rb_x = tmp->start_mb_x + tmp->num_mb_x - 1;
504*437bfbebSnyanmisaka pos->osd_rb_y = tmp->start_mb_y + tmp->num_mb_y - 1;
505*437bfbebSnyanmisaka
506*437bfbebSnyanmisaka buf_size = mpp_buffer_get_size(tmp->buf);
507*437bfbebSnyanmisaka fd = mpp_buffer_get_fd(tmp->buf);
508*437bfbebSnyanmisaka if (fd < 0) {
509*437bfbebSnyanmisaka mpp_err_f("invalid osd buffer fd %d\n", fd);
510*437bfbebSnyanmisaka return MPP_NOK;
511*437bfbebSnyanmisaka }
512*437bfbebSnyanmisaka regs->osd_addr[k] = fd;
513*437bfbebSnyanmisaka
514*437bfbebSnyanmisaka if (tmp->buf_offset)
515*437bfbebSnyanmisaka mpp_dev_set_reg_offset(dev, VEPU541_OSD_ADDR_IDX_BASE + k, tmp->buf_offset);
516*437bfbebSnyanmisaka
517*437bfbebSnyanmisaka /* There should be enough buffer and offset should be 16B aligned */
518*437bfbebSnyanmisaka if (buf_size < tmp->buf_offset + blk_len ||
519*437bfbebSnyanmisaka (tmp->buf_offset & 0xf)) {
520*437bfbebSnyanmisaka mpp_err_f("invalid osd cfg: %d x:y:w:h:off %d:%d:%d:%d:%x size %x\n",
521*437bfbebSnyanmisaka k, tmp->start_mb_x, tmp->start_mb_y,
522*437bfbebSnyanmisaka tmp->num_mb_x, tmp->num_mb_y, tmp->buf_offset, buf_size);
523*437bfbebSnyanmisaka }
524*437bfbebSnyanmisaka }
525*437bfbebSnyanmisaka }
526*437bfbebSnyanmisaka
527*437bfbebSnyanmisaka SET_OSD_INV_THR(0, regs->reg113, region);
528*437bfbebSnyanmisaka SET_OSD_INV_THR(1, regs->reg113, region);
529*437bfbebSnyanmisaka SET_OSD_INV_THR(2, regs->reg113, region);
530*437bfbebSnyanmisaka SET_OSD_INV_THR(3, regs->reg113, region);
531*437bfbebSnyanmisaka SET_OSD_INV_THR(4, regs->reg113, region);
532*437bfbebSnyanmisaka SET_OSD_INV_THR(5, regs->reg113, region);
533*437bfbebSnyanmisaka SET_OSD_INV_THR(6, regs->reg113, region);
534*437bfbebSnyanmisaka SET_OSD_INV_THR(7, regs->reg113, region);
535*437bfbebSnyanmisaka
536*437bfbebSnyanmisaka return MPP_OK;
537*437bfbebSnyanmisaka }
538