xref: /OK3568_Linux_fs/external/mpp/mpp/hal/rkenc/common/vepu541_common.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2015 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define MODULE_TAG  "vepu541_common"
18 
19 #include <string.h>
20 
21 #include "mpp_mem.h"
22 #include "mpp_debug.h"
23 #include "mpp_common.h"
24 
25 #include "vepu541_common.h"
26 
27 static const RK_S32 zeros[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
28 
29 static VepuFmtCfg vepu541_yuv_cfg[MPP_FMT_YUV_BUTT] = {
30     {   /* MPP_FMT_YUV420SP */
31         .format     = VEPU541_FMT_YUV420SP,
32         .alpha_swap = 0,
33         .rbuv_swap  = 0,
34         .src_range  = 1,
35         .src_endian = 0,
36         .weight     = zeros,
37         .offset     = zeros,
38     },
39     {   /* MPP_FMT_YUV420SP_10BIT */
40         .format     = VEPU541_FMT_NONE,
41         .alpha_swap = 0,
42         .rbuv_swap  = 0,
43         .src_range  = 1,
44         .src_endian = 0,
45         .weight     = zeros,
46         .offset     = zeros,
47     },
48     {   /* MPP_FMT_YUV422SP */
49         .format     = VEPU541_FMT_YUV422SP,
50         .alpha_swap = 0,
51         .rbuv_swap  = 0,
52         .src_range  = 1,
53         .src_endian = 0,
54         .weight     = zeros,
55         .offset     = zeros,
56     },
57     {   /* MPP_FMT_YUV422SP_10BIT */
58         .format     = VEPU541_FMT_NONE,
59         .alpha_swap = 0,
60         .rbuv_swap  = 0,
61         .src_range  = 1,
62         .src_endian = 0,
63         .weight     = zeros,
64         .offset     = zeros,
65     },
66     {   /* MPP_FMT_YUV420P */
67         .format     = VEPU541_FMT_YUV420P,
68         .alpha_swap = 0,
69         .rbuv_swap  = 0,
70         .src_range  = 1,
71         .src_endian = 0,
72         .weight     = zeros,
73         .offset     = zeros,
74     },
75     {   /* MPP_FMT_YUV420SP_VU   */
76         .format     = VEPU541_FMT_YUV420SP,
77         .alpha_swap = 0,
78         .rbuv_swap  = 1,
79         .src_range  = 1,
80         .src_endian = 0,
81         .weight     = zeros,
82         .offset     = zeros,
83     },
84     {   /* MPP_FMT_YUV422P */
85         .format     = VEPU541_FMT_YUV422P,
86         .alpha_swap = 0,
87         .rbuv_swap  = 0,
88         .src_range  = 1,
89         .src_endian = 0,
90         .weight     = zeros,
91         .offset     = zeros,
92     },
93     {   /* MPP_FMT_YUV422SP_VU */
94         .format     = VEPU541_FMT_YUV422SP,
95         .alpha_swap = 0,
96         .rbuv_swap  = 1,
97         .src_range  = 1,
98         .src_endian = 0,
99         .weight     = zeros,
100         .offset     = zeros,
101     },
102     {   /* MPP_FMT_YUV422_YUYV */
103         .format     = VEPU541_FMT_YUYV422,
104         .alpha_swap = 0,
105         .rbuv_swap  = 0,
106         .src_range  = 1,
107         .src_endian = 0,
108         .weight     = zeros,
109         .offset     = zeros,
110     },
111     {   /* MPP_FMT_YUV422_YVYU */
112         .format     = VEPU541_FMT_YUYV422,
113         .alpha_swap = 0,
114         .rbuv_swap  = 1,
115         .src_range  = 1,
116         .src_endian = 0,
117         .weight     = zeros,
118         .offset     = zeros,
119     },
120     {   /* MPP_FMT_YUV422_UYVY */
121         .format     = VEPU541_FMT_UYVY422,
122         .alpha_swap = 0,
123         .rbuv_swap  = 0,
124         .src_range  = 1,
125         .src_endian = 0,
126         .weight     = zeros,
127         .offset     = zeros,
128     },
129     {   /* MPP_FMT_YUV422_VYUY */
130         .format     = VEPU541_FMT_UYVY422,
131         .alpha_swap = 0,
132         .rbuv_swap  = 1,
133         .src_range  = 1,
134         .src_endian = 0,
135         .weight     = zeros,
136         .offset     = zeros,
137     },
138     {   /* MPP_FMT_YUV400 */
139         .format     = VEPU541_FMT_NONE,
140         .alpha_swap = 0,
141         .rbuv_swap  = 0,
142         .src_range  = 1,
143         .src_endian = 0,
144         .weight     = zeros,
145         .offset     = zeros,
146     },
147     {   /* MPP_FMT_YUV440SP */
148         .format     = VEPU541_FMT_NONE,
149         .alpha_swap = 0,
150         .rbuv_swap  = 0,
151         .src_range  = 1,
152         .src_endian = 0,
153         .weight     = zeros,
154         .offset     = zeros,
155     },
156     {   /* MPP_FMT_YUV411SP */
157         .format     = VEPU541_FMT_NONE,
158         .alpha_swap = 0,
159         .rbuv_swap  = 0,
160         .src_range  = 1,
161         .src_endian = 0,
162         .weight     = zeros,
163         .offset     = zeros,
164     },
165     {   /* MPP_FMT_YUV444SP */
166         .format     = VEPU580_FMT_YUV444SP,
167         .alpha_swap = 0,
168         .rbuv_swap  = 0,
169         .src_range  = 1,
170         .src_endian = 0,
171         .weight     = zeros,
172         .offset     = zeros,
173     },
174     {   /* MPP_FMT_YUV444P */
175         .format     = VEPU580_FMT_YUV444P,
176         .alpha_swap = 0,
177         .rbuv_swap  = 1,
178         .src_range  = 1,
179         .src_endian = 0,
180         .weight     = zeros,
181         .offset     = zeros,
182     },
183 };
184 
185 static VepuFmtCfg vepu541_rgb_cfg[MPP_FMT_RGB_BUTT - MPP_FRAME_FMT_RGB] = {
186     {   /* MPP_FMT_RGB565 */
187         .format     = VEPU541_FMT_BGR565,
188         .alpha_swap = 0,
189         .rbuv_swap  = 1,
190         .src_range  = 1,
191         .src_endian = 1,
192         .weight     = zeros,
193         .offset     = zeros,
194     },
195     {   /* MPP_FMT_BGR565 */
196         .format     = VEPU541_FMT_BGR565,
197         .alpha_swap = 0,
198         .rbuv_swap  = 0,
199         .src_range  = 1,
200         .src_endian = 1,
201         .weight     = zeros,
202         .offset     = zeros,
203     },
204     {   /* MPP_FMT_RGB555 */
205         .format     = VEPU541_FMT_NONE,
206         .alpha_swap = 0,
207         .rbuv_swap  = 0,
208         .src_range  = 1,
209         .src_endian = 0,
210         .weight     = zeros,
211         .offset     = zeros,
212     },
213     {   /* MPP_FMT_BGR555 */
214         .format     = VEPU541_FMT_NONE,
215         .alpha_swap = 0,
216         .rbuv_swap  = 0,
217         .src_range  = 1,
218         .src_endian = 0,
219         .weight     = zeros,
220         .offset     = zeros,
221     },
222     {   /* MPP_FMT_RGB444 */
223         .format     = VEPU541_FMT_NONE,
224         .alpha_swap = 0,
225         .rbuv_swap  = 0,
226         .src_range  = 1,
227         .src_endian = 0,
228         .weight     = zeros,
229         .offset     = zeros,
230     },
231     {   /* MPP_FMT_BGR444 */
232         .format     = VEPU541_FMT_NONE,
233         .alpha_swap = 0,
234         .rbuv_swap  = 0,
235         .src_range  = 1,
236         .src_endian = 0,
237         .weight     = zeros,
238         .offset     = zeros,
239     },
240     {   /* MPP_FMT_RGB888 */
241         .format     = VEPU541_FMT_BGR888,
242         .alpha_swap = 0,
243         .rbuv_swap  = 0,
244         .src_range  = 1,
245         .src_endian = 0,
246         .weight     = zeros,
247         .offset     = zeros,
248     },
249     {   /* MPP_FMT_BGR888 */
250         .format     = VEPU541_FMT_BGR888,
251         .alpha_swap = 0,
252         .rbuv_swap  = 1,
253         .src_range  = 1,
254         .src_endian = 0,
255         .weight     = zeros,
256         .offset     = zeros,
257     },
258     {   /* MPP_FMT_RGB101010 */
259         .format     = VEPU541_FMT_NONE,
260         .alpha_swap = 0,
261         .rbuv_swap  = 0,
262         .src_range  = 1,
263         .src_endian = 0,
264         .weight     = zeros,
265         .offset     = zeros,
266     },
267     {   /* MPP_FMT_BGR101010 */
268         .format     = VEPU541_FMT_NONE,
269         .alpha_swap = 0,
270         .rbuv_swap  = 0,
271         .src_range  = 1,
272         .src_endian = 0,
273         .weight     = zeros,
274         .offset     = zeros,
275     },
276     {   /* MPP_FMT_ARGB8888 */
277         .format     = VEPU541_FMT_BGRA8888,
278         .alpha_swap = 1,
279         .rbuv_swap  = 1,
280         .src_range  = 1,
281         .src_endian = 0,
282         .weight     = zeros,
283         .offset     = zeros,
284     },
285     {   /* MPP_FMT_ABGR8888 */
286         .format     = VEPU541_FMT_BGRA8888,
287         .alpha_swap = 1,
288         .rbuv_swap  = 0,
289         .src_range  = 1,
290         .src_endian = 0,
291         .weight     = zeros,
292         .offset     = zeros,
293     },
294     {   /* MPP_FMT_BGRA8888 */
295         .format     = VEPU541_FMT_BGRA8888,
296         .alpha_swap = 0,
297         .rbuv_swap  = 0,
298         .src_range  = 1,
299         .src_endian = 0,
300         .weight     = zeros,
301         .offset     = zeros,
302     },
303     {   /* MPP_FMT_RGBA8888 */
304         .format     = VEPU541_FMT_BGRA8888,
305         .alpha_swap = 0,
306         .rbuv_swap  = 1,
307         .src_endian = 0,
308         .src_range  = 1,
309         .weight     = zeros,
310         .offset     = zeros,
311     },
312 };
313 
vepu541_set_fmt(VepuFmtCfg * cfg,MppFrameFormat format)314 MPP_RET vepu541_set_fmt(VepuFmtCfg *cfg, MppFrameFormat format)
315 {
316     VepuFmtCfg *fmt = NULL;
317     MPP_RET ret = MPP_OK;
318 
319     format &= MPP_FRAME_FMT_MASK;
320 
321     if (MPP_FRAME_FMT_IS_YUV(format)) {
322         fmt = &vepu541_yuv_cfg[format - MPP_FRAME_FMT_YUV];
323     } else if (MPP_FRAME_FMT_IS_RGB(format)) {
324         fmt = &vepu541_rgb_cfg[format - MPP_FRAME_FMT_RGB];
325     } else {
326         memset(cfg, 0, sizeof(*cfg));
327         cfg->format = VEPU541_FMT_NONE;
328     }
329 
330     if (fmt && fmt->format != VEPU541_FMT_NONE) {
331         memcpy(cfg, fmt, sizeof(*cfg));
332     } else {
333         mpp_err_f("unsupport frame format %x\n", format);
334         cfg->format = VEPU541_FMT_NONE;
335         ret = MPP_NOK;
336     }
337 
338     return ret;
339 }
340 
vepu541_get_roi_buf_size(RK_S32 w,RK_S32 h)341 RK_S32 vepu541_get_roi_buf_size(RK_S32 w, RK_S32 h)
342 {
343     RK_S32 stride_h = MPP_ALIGN(w, 64) / 16;
344     RK_S32 stride_v = MPP_ALIGN(h, 64) / 16;
345     RK_S32 buf_size = stride_h * stride_v * sizeof(Vepu541RoiCfg);
346 
347     /* extra 32 byte for hardware access padding */
348     return buf_size + 32;
349 }
350 
vepu541_set_one_roi(void * buf,MppEncROIRegion * region,RK_S32 w,RK_S32 h)351 MPP_RET vepu541_set_one_roi(void *buf, MppEncROIRegion *region, RK_S32 w, RK_S32 h)
352 {
353     Vepu541RoiCfg *ptr = (Vepu541RoiCfg *)buf;
354     RK_S32 mb_w = MPP_ALIGN(w, 16) / 16;
355     RK_S32 mb_h = MPP_ALIGN(h, 16) / 16;
356     RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
357     Vepu541RoiCfg cfg;
358     MPP_RET ret = MPP_NOK;
359 
360     if (NULL == buf || NULL == region) {
361         mpp_err_f("invalid buf %p roi %p\n", buf, region);
362         goto DONE;
363     }
364 
365     RK_S32 roi_width  = (region->w + 15) / 16;
366     RK_S32 roi_height = (region->h + 15) / 16;
367     RK_S32 pos_x_init = region->x / 16;
368     RK_S32 pos_y_init = region->y / 16;
369     RK_S32 pos_x_end  = pos_x_init + roi_width;
370     RK_S32 pos_y_end  = pos_y_init + roi_height;
371     RK_S32 x, y;
372 
373     pos_x_end = MPP_MIN(pos_x_end, mb_w);
374     pos_y_end = MPP_MIN(pos_y_end, mb_h);
375     pos_x_init = MPP_MAX(pos_x_init, 0);
376     pos_y_init = MPP_MAX(pos_y_init, 0);
377 
378     mpp_assert(pos_x_end > pos_x_init);
379     mpp_assert(pos_y_end > pos_y_init);
380 
381     cfg.force_intra = region->intra;
382     cfg.reserved    = 0;
383     cfg.qp_area_idx = region->qp_area_idx;
384     // NOTE: When roi is enabled the qp_area_en should be one.
385     cfg.qp_area_en  = 1;    // region->area_map_en;
386     cfg.qp_adj      = region->quality;
387     cfg.qp_adj_mode = region->abs_qp_en;
388 
389     ptr += pos_y_init * stride_h + pos_x_init;
390     roi_width = pos_x_end - pos_x_init;
391     roi_height = pos_y_end - pos_y_init;
392 
393     for (y = 0; y < roi_height; y++) {
394         Vepu541RoiCfg *dst = ptr;
395 
396         for (x = 0; x < roi_width; x++, dst++)
397             memcpy(dst, &cfg, sizeof(cfg));
398 
399         ptr += stride_h;
400     }
401 DONE:
402     return ret;
403 }
404 
vepu541_set_roi(void * buf,MppEncROICfg * roi,RK_S32 w,RK_S32 h)405 MPP_RET vepu541_set_roi(void *buf, MppEncROICfg *roi, RK_S32 w, RK_S32 h)
406 {
407     MppEncROIRegion *region = roi->regions;
408     Vepu541RoiCfg *ptr = (Vepu541RoiCfg *)buf;
409     RK_S32 mb_w = MPP_ALIGN(w, 16) / 16;
410     RK_S32 mb_h = MPP_ALIGN(h, 16) / 16;
411     RK_S32 stride_h = MPP_ALIGN(mb_w, 4);
412     RK_S32 stride_v = MPP_ALIGN(mb_h, 4);
413     Vepu541RoiCfg cfg;
414     MPP_RET ret = MPP_NOK;
415     RK_S32 i;
416 
417     if (NULL == buf || NULL == roi) {
418         mpp_err_f("invalid buf %p roi %p\n", buf, roi);
419         goto DONE;
420     }
421 
422     cfg.force_intra = 0;
423     cfg.reserved    = 0;
424     cfg.qp_area_idx = 0;
425     cfg.qp_area_en  = 1;
426     cfg.qp_adj      = 0;
427     cfg.qp_adj_mode = 0;
428 
429     /* step 1. reset all the config */
430     for (i = 0; i < stride_h * stride_v; i++, ptr++)
431         memcpy(ptr, &cfg, sizeof(cfg));
432 
433     if (w <= 0 || h <= 0) {
434         mpp_err_f("invalid size [%d:%d]\n", w, h);
435         goto DONE;
436     }
437 
438     if (roi->number > VEPU541_MAX_ROI_NUM) {
439         mpp_err_f("invalid region number %d\n", roi->number);
440         goto DONE;
441     }
442 
443     /* check region config */
444     ret = MPP_OK;
445     for (i = 0; i < (RK_S32)roi->number; i++, region++) {
446         if (region->x + region->w > w || region->y + region->h > h)
447             ret = MPP_NOK;
448 
449         if (region->intra > 1 || region->qp_area_idx >= VEPU541_MAX_ROI_NUM ||
450             region->area_map_en > 1 || region->abs_qp_en > 1)
451             ret = MPP_NOK;
452 
453         if ((region->abs_qp_en && region->quality > 51) ||
454             (!region->abs_qp_en && (region->quality > 51 || region->quality < -51)))
455             ret = MPP_NOK;
456 
457         if (ret) {
458             mpp_err_f("region %d invalid param:\n", i);
459             mpp_err_f("position [%d:%d:%d:%d] vs [%d:%d]\n",
460                       region->x, region->y, region->w, region->h, w, h);
461             mpp_err_f("force intra %d qp area index %d\n",
462                       region->intra, region->qp_area_idx);
463             mpp_err_f("abs qp mode %d value %d\n",
464                       region->abs_qp_en, region->quality);
465             goto DONE;
466         }
467     }
468 
469     region = roi->regions;
470     /* step 2. setup region for top to bottom */
471     for (i = 0; i < (RK_S32)roi->number; i++, region++) {
472         vepu541_set_one_roi(buf, region, w, h);
473     }
474 
475 DONE:
476     return ret;
477 }
478 
479 /*
480  * Invert color threshold is for the absolute difference between background
481  * and foregroud color.
482  * If background color and foregroud color are close enough then trigger the
483  * invert color process.
484  */
485 #define ENC_DEFAULT_OSD_INV_THR         15
486 
487 #define VEPU541_OSD_ADDR_IDX_BASE       124
488 #define VEPU580_OSD_ADDR_IDX_BASE       3092
489 
490 #define VEPU541_OSD_CFG_OFFSET          0x01C0
491 #define VEPU541_OSD_PLT_OFFSET          0x0400
492 
493 typedef enum Vepu541OsdPltType_e {
494     VEPU541_OSD_PLT_TYPE_USERDEF    = 0,
495     VEPU541_OSD_PLT_TYPE_DEFAULT    = 1,
496 } Vepu541OsdPltType;
497 
498 typedef struct Vepu541OsdReg_t {
499     /*
500      * OSD_CFG
501      * Address offset: 0x01C0 Access type: read and write
502      * OSD configuration
503      */
504     struct {
505         /* OSD region enable, each bit controls corresponding OSD region. */
506         RK_U32  osd_e                   : 8;
507         /* OSD inverse color enable, each bit controls corresponding region. */
508         RK_U32  osd_inv_e               : 8;
509         /*
510          * OSD palette clock selection.
511          * 1'h0: Configure bus clock domain.
512          * 1'h1: Core clock domain.
513          */
514         RK_U32  osd_plt_cks             : 1;
515         /*
516          * OSD palette type.
517          * 1'h1: Default type.
518          * 1'h0: User defined type.
519          */
520         RK_U32  osd_plt_typ             : 1;
521         RK_U32  reserved                : 14;
522     } reg112;
523 
524     /*
525      * OSD_INV
526      * Address offset: 0x01C4 Access type: read and write
527      * OSD color inverse configuration
528      */
529     struct {
530         /* Color inverse theshold for OSD region0. */
531         RK_U32  osd_ithd_r0             : 4;
532         /* Color inverse theshold for OSD region1. */
533         RK_U32  osd_ithd_r1             : 4;
534         /* Color inverse theshold for OSD region2. */
535         RK_U32  osd_ithd_r2             : 4;
536         /* Color inverse theshold for OSD region3. */
537         RK_U32  osd_ithd_r3             : 4;
538         /* Color inverse theshold for OSD region4. */
539         RK_U32  osd_ithd_r4             : 4;
540         /* Color inverse theshold for OSD region5. */
541         RK_U32  osd_ithd_r5             : 4;
542         /* Color inverse theshold for OSD region6. */
543         RK_U32  osd_ithd_r6             : 4;
544         /* Color inverse theshold for OSD region7. */
545         RK_U32  osd_ithd_r7             : 4;
546     } reg113;
547 
548     RK_U32 reg114;
549     RK_U32 reg115;
550 
551     /*
552      * OSD_POS reg116_123
553      * Address offset: 0x01D0~0x01EC Access type: read and write
554      * OSD region position
555      */
556     Vepu541OsdPos  osd_pos[8];
557 
558     /*
559      * ADR_OSD reg124_131
560      * Address offset: 0x01F0~0x20C Access type: read and write
561      * Base address for OSD region, 16B aligned
562      */
563     RK_U32  osd_addr[8];
564 } Vepu541OsdReg;
565 
566 #define SET_OSD_INV_THR(index, reg, region)\
567     if(region[index].inverse)   \
568         reg.osd_ithd_r##index = ENC_DEFAULT_OSD_INV_THR;
569 
copy2osd2(MppEncOSDData2 * dst,MppEncOSDData * src1,MppEncOSDData2 * src2)570 static MPP_RET copy2osd2(MppEncOSDData2* dst, MppEncOSDData *src1, MppEncOSDData2 *src2)
571 {
572     MPP_RET ret = MPP_OK;
573     RK_U32 i = 0;
574 
575     if (src1) {
576         dst->num_region = src1->num_region;
577         for (i = 0; i < src1->num_region; i++) {
578             dst->region[i].enable       = src1->region[i].enable;
579             dst->region[i].inverse      = src1->region[i].inverse;
580             dst->region[i].start_mb_x   = src1->region[i].start_mb_x;
581             dst->region[i].start_mb_y   = src1->region[i].start_mb_y;
582             dst->region[i].num_mb_x     = src1->region[i].num_mb_x;
583             dst->region[i].num_mb_y     = src1->region[i].num_mb_y;
584             dst->region[i].buf_offset   = src1->region[i].buf_offset;
585             dst->region[i].buf          = src1->buf;
586         }
587         ret = MPP_OK;
588     } else if (src2) {
589         memcpy(dst, src2, sizeof(MppEncOSDData2));
590         ret = MPP_OK;
591     } else {
592         ret = MPP_NOK;
593     }
594     return ret;
595 }
596 
vepu541_set_osd(Vepu541OsdCfg * cfg)597 MPP_RET vepu541_set_osd(Vepu541OsdCfg *cfg)
598 {
599     Vepu541OsdReg *regs = (Vepu541OsdReg *)(cfg->reg_base + (size_t)VEPU541_OSD_CFG_OFFSET);
600     MppDev dev = cfg->dev;
601     MppEncOSDPltCfg *plt_cfg = cfg->plt_cfg;
602     MppEncOSDData2 osd;
603 
604     if (copy2osd2(&osd, cfg->osd_data, cfg->osd_data2))
605         return MPP_NOK;
606 
607     if (osd.num_region == 0)
608         return MPP_OK;
609 
610     if (osd.num_region > 8) {
611         mpp_err_f("do NOT support more than 8 regions invalid num %d\n",
612                   osd.num_region);
613         mpp_assert(osd.num_region <= 8);
614         return MPP_NOK;
615     }
616 
617     if (plt_cfg->type == MPP_ENC_OSD_PLT_TYPE_USERDEF) {
618         MppDevRegWrCfg wr_cfg;
619 
620         wr_cfg.reg = plt_cfg->plt;
621         wr_cfg.size = sizeof(MppEncOSDPlt);
622         wr_cfg.offset = VEPU541_REG_BASE_OSD_PLT;
623 
624         mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg);
625 
626         regs->reg112.osd_plt_cks = 1;
627         regs->reg112.osd_plt_typ = VEPU541_OSD_PLT_TYPE_USERDEF;
628     } else {
629         regs->reg112.osd_plt_cks = 0;
630         regs->reg112.osd_plt_typ = VEPU541_OSD_PLT_TYPE_DEFAULT;
631     }
632 
633     regs->reg112.osd_e = 0;
634     regs->reg112.osd_inv_e = 0;
635 
636     RK_U32 i = 0;
637     MppEncOSDRegion2 *region = osd.region;
638     MppEncOSDRegion2 *tmp = region;
639     RK_U32 num = osd.num_region;
640 
641     for (i = 0; i < num; i++, tmp++) {
642         regs->reg112.osd_e      |= tmp->enable << i;
643         regs->reg112.osd_inv_e  |= tmp->inverse << i;
644 
645         if (tmp->enable && tmp->num_mb_x && tmp->num_mb_y) {
646             Vepu541OsdPos *pos = &regs->osd_pos[i];
647             size_t blk_len = tmp->num_mb_x * tmp->num_mb_y * 256;
648             RK_S32 fd = 0;
649             RK_U32 buf_size = 0;
650 
651             pos->osd_lt_x = tmp->start_mb_x;
652             pos->osd_lt_y = tmp->start_mb_y;
653             pos->osd_rb_x = tmp->start_mb_x + tmp->num_mb_x - 1;
654             pos->osd_rb_y = tmp->start_mb_y + tmp->num_mb_y - 1;
655 
656             buf_size = mpp_buffer_get_size(tmp->buf);
657             fd = mpp_buffer_get_fd(tmp->buf);
658             if (fd < 0) {
659                 mpp_err_f("invalid osd buffer fd %d\n", fd);
660                 return MPP_NOK;
661             }
662             regs->osd_addr[i] = fd;
663 
664             if (tmp->buf_offset) {
665                 MppDevRegOffsetCfg trans_cfg;
666 
667                 trans_cfg.reg_idx = VEPU541_OSD_ADDR_IDX_BASE + i;
668                 trans_cfg.offset = tmp->buf_offset;
669                 mpp_dev_ioctl(cfg->dev, MPP_DEV_REG_OFFSET, &trans_cfg);
670             }
671 
672             /* There should be enough buffer and offset should be 16B aligned */
673             if (buf_size < tmp->buf_offset + blk_len ||
674                 (tmp->buf_offset & 0xf)) {
675                 mpp_err_f("invalid osd cfg: %d x:y:w:h:off %d:%d:%d:%d:%x\n",
676                           i, tmp->start_mb_x, tmp->start_mb_y,
677                           tmp->num_mb_x, tmp->num_mb_y, tmp->buf_offset);
678             }
679         }
680     }
681 
682     SET_OSD_INV_THR(0, regs->reg113, region);
683     SET_OSD_INV_THR(1, regs->reg113, region);
684     SET_OSD_INV_THR(2, regs->reg113, region);
685     SET_OSD_INV_THR(3, regs->reg113, region);
686     SET_OSD_INV_THR(4, regs->reg113, region);
687     SET_OSD_INV_THR(5, regs->reg113, region);
688     SET_OSD_INV_THR(6, regs->reg113, region);
689     SET_OSD_INV_THR(7, regs->reg113, region);
690 
691     return MPP_OK;
692 }
693 
694 #define VEPU540_OSD_CFG_OFFSET          0x0178
695 
696 typedef struct Vepu540OsdReg_t {
697     /*
698      * OSD_INV_CFG
699      * Address offset: 0x0178 Access type: read and write
700      * OSD color inverse  configuration
701      */
702     struct {
703         /*
704          * OSD color inverse enable of chroma component,
705          * each bit controls corresponding region.
706          */
707         RK_U32  osd_ch_inv_en           : 8;
708         /*
709          * OSD color inverse expression type
710          * each bit controls corresponding region.
711          * 1'h0: AND;
712          * 1'h1: OR
713          */
714         RK_U32  osd_itype               : 8;
715         /*
716          * OSD color inverse expression switch for luma component
717          * each bit controls corresponding region.
718          * 1'h0: Expression need to determine the condition;
719          * 1'h1: Expression don't need to determine the condition;
720          */
721         RK_U32  osd_lu_inv_msk          : 8;
722         /*
723          * OSD color inverse expression switch for chroma component
724          * each bit controls corresponding region.
725          * 1'h0: Expression need to determine the condition;
726          * 1'h1: Expression don't need to determine the condition;
727          */
728         RK_U32  osd_ch_inv_msk          : 8;
729     } reg094;
730 
731     /* reg gap 095~111 */
732     RK_U32 reg_095_111[17];
733 
734     /*
735      * OSD_CFG
736      * Address offset: 0x01C0 Access type: read and write
737      * OSD configuration
738      */
739     struct {
740         /* OSD region enable, each bit controls corresponding OSD region. */
741         RK_U32  osd_e                   : 8;
742         /* OSD inverse color enable, each bit controls corresponding region. */
743         RK_U32  osd_lu_inv_en           : 8;
744         /*
745          * OSD palette clock selection.
746          * 1'h0: Configure bus clock domain.
747          * 1'h1: Core clock domain.
748          */
749         RK_U32  osd_plt_cks             : 1;
750         /*
751          * OSD palette type.
752          * 1'h1: Default type.
753          * 1'h0: User defined type.
754          */
755         RK_U32  osd_plt_typ             : 1;
756         RK_U32  reserved                : 14;
757     } reg112;
758 
759     /*
760      * OSD_INV
761      * Address offset: 0x01C4 Access type: read and write
762      * OSD color inverse configuration
763      */
764     struct {
765         /* Color inverse theshold for OSD region0. */
766         RK_U32  osd_ithd_r0             : 4;
767         /* Color inverse theshold for OSD region1. */
768         RK_U32  osd_ithd_r1             : 4;
769         /* Color inverse theshold for OSD region2. */
770         RK_U32  osd_ithd_r2             : 4;
771         /* Color inverse theshold for OSD region3. */
772         RK_U32  osd_ithd_r3             : 4;
773         /* Color inverse theshold for OSD region4. */
774         RK_U32  osd_ithd_r4             : 4;
775         /* Color inverse theshold for OSD region5. */
776         RK_U32  osd_ithd_r5             : 4;
777         /* Color inverse theshold for OSD region6. */
778         RK_U32  osd_ithd_r6             : 4;
779         /* Color inverse theshold for OSD region7. */
780         RK_U32  osd_ithd_r7             : 4;
781     } reg113;
782 
783     RK_U32 reg114;
784     RK_U32 reg115;
785 
786     /*
787      * OSD_POS reg116_123
788      * Address offset: 0x01D0~0x01EC Access type: read and write
789      * OSD region position
790      */
791     Vepu541OsdPos  osd_pos[8];
792 
793     /*
794      * ADR_OSD reg124_131
795      * Address offset: 0x01F0~0x20C Access type: read and write
796      * Base address for OSD region, 16B aligned
797      */
798     RK_U32  osd_addr[8];
799 } Vepu540OsdReg;
800 
vepu540_set_osd(Vepu541OsdCfg * cfg)801 MPP_RET vepu540_set_osd(Vepu541OsdCfg *cfg)
802 {
803     Vepu540OsdReg *regs = (Vepu540OsdReg *)(cfg->reg_base + (size_t)VEPU540_OSD_CFG_OFFSET);
804     MppDev dev = cfg->dev;
805     MppEncOSDPltCfg *plt_cfg = cfg->plt_cfg;
806     MppEncOSDData2 osd;
807 
808     if (copy2osd2(&osd, cfg->osd_data, cfg->osd_data2))
809         return MPP_NOK;
810 
811     if (osd.num_region == 0)
812         return MPP_OK;
813 
814     if (osd.num_region > 8) {
815         mpp_err_f("do NOT support more than 8 regions invalid num %d\n",
816                   osd.num_region);
817         mpp_assert(osd.num_region <= 8);
818         return MPP_NOK;
819     }
820 
821     if (plt_cfg->type == MPP_ENC_OSD_PLT_TYPE_USERDEF) {
822         MppDevRegWrCfg wr_cfg;
823 
824         wr_cfg.reg = plt_cfg->plt;
825         wr_cfg.size = sizeof(MppEncOSDPlt);
826         wr_cfg.offset = VEPU541_REG_BASE_OSD_PLT;
827         mpp_dev_ioctl(dev, MPP_DEV_REG_WR, &wr_cfg);
828 
829         regs->reg112.osd_plt_cks = 1;
830         regs->reg112.osd_plt_typ = VEPU541_OSD_PLT_TYPE_USERDEF;
831     } else {
832         regs->reg112.osd_plt_cks = 0;
833         regs->reg112.osd_plt_typ = VEPU541_OSD_PLT_TYPE_DEFAULT;
834     }
835 
836     regs->reg112.osd_e = 0;
837     regs->reg112.osd_lu_inv_en = 0;
838     regs->reg094.osd_ch_inv_en = 0;
839     regs->reg094.osd_lu_inv_msk = 0;
840 
841     RK_U32 num = osd.num_region;
842     RK_U32 k = 0;
843     MppEncOSDRegion2 *region = osd.region;
844     MppEncOSDRegion2 *tmp = region;
845 
846     for (k = 0; k < num; k++, tmp++) {
847         regs->reg112.osd_e          |= tmp->enable << k;
848         regs->reg112.osd_lu_inv_en  |= (tmp->inverse) ? (1 << k) : 0;
849         regs->reg094.osd_ch_inv_en  |= (tmp->inverse) ? (1 << k) : 0;
850 
851         if (tmp->enable && tmp->num_mb_x && tmp->num_mb_y) {
852             Vepu541OsdPos *pos = &regs->osd_pos[k];
853             size_t blk_len = tmp->num_mb_x * tmp->num_mb_y * 256;
854             RK_S32 fd = -1;
855             size_t buf_size = 0;
856 
857             pos->osd_lt_x = tmp->start_mb_x;
858             pos->osd_lt_y = tmp->start_mb_y;
859             pos->osd_rb_x = tmp->start_mb_x + tmp->num_mb_x - 1;
860             pos->osd_rb_y = tmp->start_mb_y + tmp->num_mb_y - 1;
861 
862             buf_size = mpp_buffer_get_size(tmp->buf);
863             fd = mpp_buffer_get_fd(tmp->buf);
864             if (fd < 0) {
865                 mpp_err_f("invalid osd buffer fd %d\n", fd);
866                 return MPP_NOK;
867             }
868             regs->osd_addr[k] = fd;
869 
870             if (tmp->buf_offset) {
871                 MppDevRegOffsetCfg trans_cfg;
872 
873                 trans_cfg.reg_idx = VEPU541_OSD_ADDR_IDX_BASE + k;
874                 trans_cfg.offset = tmp->buf_offset;
875                 mpp_dev_ioctl(dev, MPP_DEV_REG_OFFSET, &trans_cfg);
876             }
877 
878             /* There should be enough buffer and offset should be 16B aligned */
879             if (buf_size < tmp->buf_offset + blk_len ||
880                 (tmp->buf_offset & 0xf)) {
881                 mpp_err_f("invalid osd cfg: %d x:y:w:h:off %d:%d:%d:%d:%x size %x\n",
882                           k, tmp->start_mb_x, tmp->start_mb_y,
883                           tmp->num_mb_x, tmp->num_mb_y, tmp->buf_offset, buf_size);
884             }
885         }
886     }
887 
888     SET_OSD_INV_THR(0, regs->reg113, region);
889     SET_OSD_INV_THR(1, regs->reg113, region);
890     SET_OSD_INV_THR(2, regs->reg113, region);
891     SET_OSD_INV_THR(3, regs->reg113, region);
892     SET_OSD_INV_THR(4, regs->reg113, region);
893     SET_OSD_INV_THR(5, regs->reg113, region);
894     SET_OSD_INV_THR(6, regs->reg113, region);
895     SET_OSD_INV_THR(7, regs->reg113, region);
896 
897     return MPP_OK;
898 }
899 
900 typedef struct Vepu580OsdReg_t {
901     /*
902      * OSD_INV_CFG
903      * Address offset: 0x00003000 Access type: read and write
904      * OSD color inverse  configuration
905      */
906     struct {
907         /*
908          * OSD color inverse enable of luma component,
909          * each bit controls corresponding region.
910          */
911         RK_U32  osd_lu_inv_en           : 8;
912 
913         /* OSD color inverse enable of chroma component,
914         * each bit controls corresponding region.
915         */
916         RK_U32  osd_ch_inv_en               : 8;
917         /*
918          * OSD color inverse expression switch for luma component
919          * each bit controls corresponding region.
920          * 1'h0: Expression need to determine the condition;
921          * 1'h1: Expression don't need to determine the condition;
922          */
923         RK_U32  osd_lu_inv_msk          : 8;
924         /*
925          * OSD color inverse expression switch for chroma component
926          * each bit controls corresponding region.
927          * 1'h0: Expression need to determine the condition;
928          * 1'h1: Expression don't need to determine the condition;
929          */
930         RK_U32  osd_ch_inv_msk          : 8;
931     } reg3072;
932 
933     /*
934      * OSD_INV
935      * Address offset: 0x3004 Access type: read and write
936      * OSD color inverse configuration
937      */
938     struct {
939         /* Color inverse theshold for OSD region0. */
940         RK_U32  osd_ithd_r0             : 4;
941         /* Color inverse theshold for OSD region1. */
942         RK_U32  osd_ithd_r1             : 4;
943         /* Color inverse theshold for OSD region2. */
944         RK_U32  osd_ithd_r2             : 4;
945         /* Color inverse theshold for OSD region3. */
946         RK_U32  osd_ithd_r3             : 4;
947         /* Color inverse theshold for OSD region4. */
948         RK_U32  osd_ithd_r4             : 4;
949         /* Color inverse theshold for OSD region5. */
950         RK_U32  osd_ithd_r5             : 4;
951         /* Color inverse theshold for OSD region6. */
952         RK_U32  osd_ithd_r6             : 4;
953         /* Color inverse theshold for OSD region7. */
954         RK_U32  osd_ithd_r7             : 4;
955     } reg3073;
956 
957     /*
958      * OSD_CFG
959      * Address offset: 0x3008 Access type: read and write
960      * OSD configuration
961      */
962     struct {
963         /* OSD region enable, each bit controls corresponding OSD region. */
964         RK_U32  osd_e                   : 8;
965         /*
966          * OSD color inverse expression type
967          * each bit controls corresponding region.
968          * 1'h0: AND;
969          * 1'h1: OR
970          */
971         RK_U32  osd_itype           : 8;
972         /*
973          * OSD palette clock selection.
974          * 1'h0: Configure bus clock domain.
975          * 1'h1: Core clock domain.
976          */
977         RK_U32  osd_plt_cks             : 1;
978         /*
979          * OSD palette type.
980          * 1'h1: Default type.
981          * 1'h0: User defined type.
982          */
983         RK_U32  osd_plt_typ             : 1;
984         RK_U32  reserved                : 14;
985     } reg3074;
986 
987     RK_U32 reserved_3075;
988     /*
989      * OSD_POS reg3076_reg3091
990      * Address offset: 0x3010~0x304c Access type: read and write
991      * OSD region position
992      */
993     Vepu580OsdPos  osd_pos[8];
994 
995     /*
996      * ADR_OSD reg3092_reg3099
997      * Address offset: 0x00003050~reg306c Access type: read and write
998      * Base address for OSD region, 16B aligned
999      */
1000     RK_U32  osd_addr[8];
1001 
1002     RK_U32 reserved3100_3103[4];
1003     Vepu541OsdPltColor plt_data[256];
1004 } Vepu580OsdReg;
1005 
vepu580_set_osd(Vepu541OsdCfg * cfg)1006 MPP_RET vepu580_set_osd(Vepu541OsdCfg *cfg)
1007 {
1008     Vepu580OsdReg *regs = (Vepu580OsdReg *)cfg->reg_base;
1009     MppDev dev = cfg->dev;
1010     MppDevRegOffCfgs *reg_cfg = cfg->reg_cfg;
1011     MppEncOSDPltCfg *plt_cfg = cfg->plt_cfg;
1012     MppEncOSDData2 osd;
1013 
1014     if (copy2osd2(&osd, cfg->osd_data, cfg->osd_data2))
1015         return MPP_NOK;
1016 
1017     if (osd.num_region == 0)
1018         return MPP_OK;
1019 
1020     if (osd.num_region > 8) {
1021         mpp_err_f("do NOT support more than 8 regions invalid num %d\n",
1022                   osd.num_region);
1023         mpp_assert(osd.num_region <= 8);
1024         return MPP_NOK;
1025     }
1026 
1027     if (plt_cfg->type == MPP_ENC_OSD_PLT_TYPE_USERDEF) {
1028         memcpy(regs->plt_data, plt_cfg->plt, sizeof(MppEncOSDPlt));
1029         regs->reg3074.osd_plt_cks = 1;
1030         regs->reg3074.osd_plt_typ = VEPU541_OSD_PLT_TYPE_USERDEF;
1031     } else {
1032         regs->reg3074.osd_plt_cks = 0;
1033         regs->reg3074.osd_plt_typ = VEPU541_OSD_PLT_TYPE_DEFAULT;
1034     }
1035 
1036     regs->reg3074.osd_e = 0;
1037     regs->reg3072.osd_lu_inv_en = 0;
1038     regs->reg3072.osd_ch_inv_en = 0;
1039     regs->reg3072.osd_lu_inv_msk = 0;
1040     regs->reg3072.osd_ch_inv_msk = 0;
1041 
1042     RK_U32 num = osd.num_region;
1043     RK_U32 k = 0;
1044     MppEncOSDRegion2 *region = osd.region;
1045     MppEncOSDRegion2 *tmp = region;
1046 
1047     for (k = 0; k < num; k++, tmp++) {
1048         regs->reg3074.osd_e          |= tmp->enable << k;
1049         regs->reg3072.osd_lu_inv_en  |= (tmp->inverse) ? (1 << k) : 0;
1050         regs->reg3072.osd_ch_inv_en  |= (tmp->inverse) ? (1 << k) : 0;
1051 
1052         if (tmp->enable && tmp->num_mb_x && tmp->num_mb_y) {
1053             Vepu580OsdPos *pos = &regs->osd_pos[k];
1054             size_t blk_len = tmp->num_mb_x * tmp->num_mb_y * 256;
1055             RK_S32 fd = -1;
1056             size_t buf_size = 0;
1057 
1058             pos->osd_lt_x = tmp->start_mb_x;
1059             pos->osd_lt_y = tmp->start_mb_y;
1060             pos->osd_rb_x = tmp->start_mb_x + tmp->num_mb_x - 1;
1061             pos->osd_rb_y = tmp->start_mb_y + tmp->num_mb_y - 1;
1062 
1063             buf_size = mpp_buffer_get_size(tmp->buf);
1064             fd = mpp_buffer_get_fd(tmp->buf);
1065             if (fd < 0) {
1066                 mpp_err_f("invalid osd buffer fd %d\n", fd);
1067                 return MPP_NOK;
1068             }
1069             regs->osd_addr[k] = fd;
1070 
1071             if (tmp->buf_offset) {
1072                 if (reg_cfg)
1073                     mpp_dev_multi_offset_update(reg_cfg, VEPU580_OSD_ADDR_IDX_BASE + k, tmp->buf_offset);
1074                 else
1075                     mpp_dev_set_reg_offset(dev, VEPU580_OSD_ADDR_IDX_BASE + k, tmp->buf_offset);
1076             }
1077 
1078             /* There should be enough buffer and offset should be 16B aligned */
1079             if (buf_size < tmp->buf_offset + blk_len ||
1080                 (tmp->buf_offset & 0xf)) {
1081                 mpp_err_f("invalid osd cfg: %d x:y:w:h:off %d:%d:%d:%d:%x size %x\n",
1082                           k, tmp->start_mb_x, tmp->start_mb_y,
1083                           tmp->num_mb_x, tmp->num_mb_y, tmp->buf_offset, buf_size);
1084             }
1085         }
1086     }
1087 
1088     SET_OSD_INV_THR(0, regs->reg3073, region);
1089     SET_OSD_INV_THR(1, regs->reg3073, region);
1090     SET_OSD_INV_THR(2, regs->reg3073, region);
1091     SET_OSD_INV_THR(3, regs->reg3073, region);
1092     SET_OSD_INV_THR(4, regs->reg3073, region);
1093     SET_OSD_INV_THR(5, regs->reg3073, region);
1094     SET_OSD_INV_THR(6, regs->reg3073, region);
1095     SET_OSD_INV_THR(7, regs->reg3073, region);
1096 
1097     return MPP_OK;
1098 }
1099