1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 #include "vou.h"
20 #include "vou_drv.h"
21 #include "vou_hal.h"
22 #include <cpu_func.h>
23
24 static hi_u32 g_bg_color[2] = { 0xFF, 0xFF }; /* 2 devices 0xFF default blue */
25
26 static hi_bool g_inited = HI_FALSE;
27 static hi_rect g_max_rect = {0};
28
29 #define vo_align(val, align) (((val) + (align) - 1) & (~((align) - 1)))
30
vo_dcache_range(unsigned long start_addr,hi_u64 size)31 static hi_void vo_dcache_range(unsigned long start_addr, hi_u64 size)
32 {
33 if (dcache_status()) {
34 flush_dcache_range(start_addr, start_addr + size);
35 }
36 }
37
gfx_convert_layer(unsigned int layer)38 static unsigned int gfx_convert_layer(unsigned int layer)
39 {
40 unsigned int gfx_layer;
41
42 /* hard cursor is not supported. */
43 switch (layer) {
44 case 0: /* 0 layer */
45 gfx_layer = VO_LAYER_G0;
46 break;
47 case 1: /* 1 layer */
48 gfx_layer = VO_LAYER_G1;
49 break;
50 default:
51 gfx_layer = VO_LAYER_G0;
52 break;
53 }
54 return gfx_layer;
55 }
56
gfx_convert_to_hal_layer(unsigned int layer)57 static hal_disp_layer gfx_convert_to_hal_layer(unsigned int layer)
58 {
59 hal_disp_layer hal_gfx_layer;
60
61 /* hard cursor is not supported. */
62 switch (layer) {
63 case 0: /* 0 layer */
64 hal_gfx_layer = HAL_DISP_LAYER_GFX0;
65 break;
66 case 1: /* 1 layer */
67 hal_gfx_layer = HAL_DISP_LAYER_GFX1;
68 break;
69 default:
70 hal_gfx_layer = HAL_DISP_LAYER_GFX0;
71 break;
72 }
73 return hal_gfx_layer;
74 }
video_layer_convert(unsigned int layer)75 static hi_vo_layer video_layer_convert(unsigned int layer)
76 {
77 hi_vo_layer video_layer;
78
79 /* hard cursor is not supported. */
80 switch (layer) {
81 case 0: /* 0 layer */
82 video_layer = VO_LAYER_VHD0;
83 break;
84 case 1: /* 1 layer */
85 video_layer = VO_LAYER_VHD1;
86 break;
87 default:
88 video_layer = VO_LAYER_VHD0;
89 break;
90 }
91 return video_layer;
92 }
93
video_layer_convert_to_hal(unsigned int layer)94 static hal_disp_layer video_layer_convert_to_hal(unsigned int layer)
95 {
96 hal_disp_layer hal_video_layer;
97
98 /* hard cursor is not supported. */
99 switch (layer) {
100 case 0: /* 0 layer */
101 hal_video_layer = HAL_DISP_LAYER_VHD0;
102 break;
103 case 1: /* 1 layer */
104 hal_video_layer = HAL_DISP_LAYER_VHD1;
105 break;
106 default:
107 hal_video_layer = HAL_DISP_LAYER_VHD0;
108 break;
109 }
110 return hal_video_layer;
111 }
112
set_vobg(unsigned int dev,unsigned int rgb)113 int set_vobg(unsigned int dev, unsigned int rgb)
114 {
115 if (dev < 2) { /* 2 device */
116 g_bg_color[dev] = rgb;
117 }
118 return 0;
119 }
120
vo_set_disp_max_size(vo_hal_dev vo_dev,vo_intf_sync vo_out_mode)121 hi_void vo_set_disp_max_size(vo_hal_dev vo_dev, vo_intf_sync vo_out_mode)
122 {
123 /* default is 720x576 */
124 hi_u32 max_width = 720;
125 hi_u32 max_height = 576;
126
127 /* to get the width and height of the sync, not magic num */
128 switch (vo_out_mode) {
129 case VO_OUTPUT_PAL:
130 case VO_OUTPUT_576P50:
131 max_width = 720;
132 max_height = 576;
133 break;
134 case VO_OUTPUT_NTSC:
135 case VO_OUTPUT_480P60:
136 max_width = 720;
137 max_height = 480;
138 break;
139 case VO_OUTPUT_720P60:
140 case VO_OUTPUT_720P50:
141 max_width = 1280;
142 max_height = 720;
143 break;
144 case VO_OUTPUT_1080I50:
145 case VO_OUTPUT_1080I60:
146 case VO_OUTPUT_1080P24:
147 case VO_OUTPUT_1080P25:
148 case VO_OUTPUT_1080P30:
149 case VO_OUTPUT_1080P50:
150 case VO_OUTPUT_1080P60:
151 max_width = 1920;
152 max_height = 1080;
153 break;
154 case VO_OUTPUT_800x600_60:
155 case VO_OUTPUT_800x600_50:
156 max_width = 800;
157 max_height = 600;
158 break;
159 case VO_OUTPUT_1024x768_60:
160 max_width = 1024;
161 max_height = 768;
162 break;
163 case VO_OUTPUT_1280x1024_60:
164 max_width = 1280;
165 max_height = 1024;
166 break;
167 case VO_OUTPUT_1366x768_60:
168 max_width = 1366;
169 max_height = 768;
170 break;
171 case VO_OUTPUT_1440x900_60:
172 max_width = 1440;
173 max_height = 900;
174 break;
175 case VO_OUTPUT_1280x800_60:
176 max_width = 1280;
177 max_height = 800;
178 break;
179 case VO_OUTPUT_1600x1200_60:
180 max_width = 1600;
181 max_height = 1200;
182 break;
183 case VO_OUTPUT_1680x1050_60:
184 max_width = 1680;
185 max_height = 1050;
186 break;
187 case VO_OUTPUT_1920x1200_60:
188 max_width = 1920;
189 max_height = 1200;
190 break;
191 case VO_OUTPUT_640x480_60:
192 max_width = 640;
193 max_height = 480;
194 break;
195 case VO_OUTPUT_1920x2160_30:
196 max_width = 1920;
197 max_height = 2160;
198 break;
199 case VO_OUTPUT_2560x1440_30:
200 case VO_OUTPUT_2560x1440_60:
201 max_width = 2560;
202 max_height = 1440;
203 break;
204 case VO_OUTPUT_2560x1600_60:
205 max_width = 2560;
206 max_height = 1600;
207 break;
208 case VO_OUTPUT_3840x2160_24:
209 case VO_OUTPUT_3840x2160_25:
210 case VO_OUTPUT_3840x2160_30:
211 case VO_OUTPUT_3840x2160_50:
212 case VO_OUTPUT_3840x2160_60:
213 max_width = 3840;
214 max_height = 2160;
215 break;
216 case VO_OUTPUT_4096x2160_24:
217 case VO_OUTPUT_4096x2160_25:
218 case VO_OUTPUT_4096x2160_30:
219 case VO_OUTPUT_4096x2160_50:
220 case VO_OUTPUT_4096x2160_60:
221 max_width = 4096;
222 max_height = 2160;
223 break;
224 case VO_OUTPUT_320x240_50:
225 case VO_OUTPUT_320x240_60: /* just for hi3518ev200 hi3519 */
226 max_width = 320;
227 max_height = 240;
228 break;
229 case VO_OUTPUT_240x320_50: /* just for hi3518ev200 hi3519 */
230 case VO_OUTPUT_240x320_60:
231 max_width = 240;
232 max_height = 320;
233 break;
234 case VO_OUTPUT_720x1280_60:
235 max_width = 720;
236 max_height = 1280;
237 break;
238 case VO_OUTPUT_1080x1920_60:
239 max_width = 1080;
240 max_height = 1920;
241 break;
242 case VO_OUTPUT_7680x4320_30:
243 max_width = 7680;
244 max_height = 4320;
245 break;
246
247 default:
248 max_width = 1920;
249 max_height = 1080;
250 }
251
252 g_max_rect.width = max_width;
253 g_max_rect.height = max_height;
254 }
255
start_vo(unsigned int dev,unsigned int type,unsigned int sync)256 int start_vo(unsigned int dev, unsigned int type, unsigned int sync)
257 {
258 if (g_inited == HI_FALSE) {
259 sys_hal_set_vo_low_power_ctrl(HI_TRUE);
260 sys_hal_vo_bus_reset_sel(HI_FALSE);
261
262 /* open clk */
263 vo_drv_set_all_crg_clk(HI_TRUE);
264 vo_drv_board_init();
265 hal_sys_control();
266
267 g_inited = HI_TRUE;
268 }
269
270 if ((dev == VO_DEV_DHD0) || (dev == VO_DEV_DHD1)) {
271 sys_hal_vo_dev_clk_en(dev, HI_TRUE);
272 }
273
274 vo_drv_def_layer_bind_dev();
275 vo_set_disp_max_size(dev, sync);
276 vo_drv_set_dev_intf_type(dev, type);
277 vo_drv_set_dev_out_sync(dev, sync);
278 vo_drv_set_dev_bk_grd(dev, g_bg_color[dev]);
279 vo_drv_set_dev_clk(dev);
280 vo_drv_open(dev);
281
282 return 0;
283 }
284
stop_vo(unsigned int dev)285 int stop_vo(unsigned int dev)
286 {
287 vo_drv_close(dev);
288 sys_hal_vo_dev_clk_en(dev, HI_FALSE);
289
290 return 0;
291 }
292
video_layer_set_zme_cfg(unsigned int layer,const hi_rect * disp_rect)293 static hi_void video_layer_set_zme_cfg(unsigned int layer, const hi_rect *disp_rect)
294 {
295 vdp_vid_ip_cfg vid_cfg = {0};
296
297 vid_cfg.csc_en = 0;
298 vid_cfg.hfir_en = 1;
299 vid_cfg.vid_iw = disp_rect->width;
300 vid_cfg.vid_ih = disp_rect->height;
301
302 vid_cfg.vid_ow = disp_rect->width;
303 vid_cfg.vid_oh = disp_rect->height;
304 vid_cfg.zme_en = HI_FALSE;
305 vo_vid_set_zme_enable(layer, &vid_cfg);
306 }
307
video_layer_set_csc_by_intf(unsigned int layer,vo_intf_type intf_type)308 static hi_void video_layer_set_csc_by_intf(unsigned int layer, vo_intf_type intf_type)
309 {
310 hi_vo_layer vo_layer;
311 hal_disp_layer hal_video_layer;
312 vo_csc csc;
313 csc_coef_param csc_coef;
314
315 vo_layer = video_layer_convert(layer);
316 hal_video_layer = video_layer_convert_to_hal(layer);
317
318 if ((intf_type & VO_INTF_MIPI) ||
319 (intf_type & VO_INTF_MIPI_SLAVE)) {
320 /* do yuv to rgb. */
321 csc.csc_matrix = VO_CSC_MATRIX_BT709_TO_RGB_PC;
322 csc.luma = 50; /* 50 default value */
323 csc.contrast = 50; /* 50 default value */
324 csc.hue = 50; /* 50 default value */
325 csc.satuature = 50; /* 50 default value */
326 csc_coef.csc_scale2p = GFX_CSC_SCALE;
327 csc_coef.csc_clip_min = GFX_CSC_CLIP_MIN;
328 csc_coef.csc_clip_max = GFX_CSC_CLIP_MAX;
329 /* do rgb to yuv. */
330 vo_drv_set_csc_coef(hal_video_layer, &csc, &csc_coef);
331
332 hal_layer_set_csc_en(vo_layer, HI_TRUE);
333 } else {
334 /* do rgb to rgb or do nothing. */
335 hal_layer_set_csc_en(vo_layer, HI_FALSE);
336 }
337 }
338
start_videolayer(unsigned int layer,unsigned long addr,unsigned int strd,hi_vo_rect layer_rect)339 int start_videolayer(unsigned int layer, unsigned long addr, unsigned int strd, hi_vo_rect layer_rect)
340 {
341 int i;
342 hi_rect disp_rect = { layer_rect.x, layer_rect.y, layer_rect.w, layer_rect.h };
343 hi_vo_layer vo_layer;
344 hal_disp_layer hal_video_layer;
345 const hi_s32 as32_hfir_coef[2][8] = { /* 2 8 hifb coef array */
346 { 0x3f9, 0xc, 0x3ef, 0x19, 0x3da, 0x3a, 0x397, 0x148 },
347 { 0x3f5, 0xf, 0x3ec, 0x1c, 0x3d8, 0x3d, 0x395, 0x14a }
348 };
349 vo_intf_type intf_type;
350
351 vo_dcache_range(addr, strd * layer_rect.h * 3 / 2); /* 3 / 2 times */
352
353 vo_layer = video_layer_convert(layer);
354 hal_video_layer = video_layer_convert_to_hal(layer);
355 hal_layer_set_layer_data_fmt(layer, VO_LAYER_PIXERL_FORMAT_SP_Y_CB_CR_420);
356
357 intf_type = vo_drv_get_dev_intf_type(layer);
358
359 video_layer_set_csc_by_intf(layer, intf_type);
360
361 for (i = 0; i <= HAL_DISP_LAYER_VHD1; i++) {
362 hal_video_set_hfir_mode(i, HAL_HFIRMODE_COPY);
363 hal_video_set_hfir_coef(i, as32_hfir_coef[i]);
364 }
365
366 hal_video_hfir_set_ck_gt_en(layer, HI_TRUE);
367
368 hal_video_set_layer_disp_rect(layer, &disp_rect);
369 hal_video_set_layer_video_rect(layer, &disp_rect);
370 hal_layer_set_layer_in_rect(layer, &disp_rect);
371 hal_layer_set_layer_galpha(layer, 255); /* 255 max alpha */
372 hal_layer_set_src_resolution(layer, &disp_rect);
373
374 hal_layer_set_zme_enable(layer, HAL_DISP_ZMEMODE_ALL, HI_FALSE);
375
376 video_layer_set_zme_cfg(layer, &disp_rect);
377
378 hal_layer_set_zme_info(layer, disp_rect.width, disp_rect.height, HAL_DISP_ZME_OUTFMT422);
379
380 /* area 0 */
381 hal_video_set_multi_area_l_addr(layer, 0, addr, strd);
382 hal_video_set_multi_area_c_addr(layer, 0, addr + strd * vo_align(layer_rect.h, 16), strd); /* align 16 */
383
384 hal_layer_enable_layer(vo_layer, HI_TRUE);
385 hal_layer_set_reg_up(hal_video_layer);
386
387 return 0;
388 }
389
stop_videolayer(unsigned int layer)390 int stop_videolayer(unsigned int layer)
391 {
392 hi_vo_layer vo_layer;
393 hal_disp_layer hal_video_layer;
394
395 vo_layer = video_layer_convert(layer);
396 hal_video_layer = video_layer_convert_to_hal(layer);
397
398 hal_layer_enable_layer(vo_layer, HI_FALSE);
399 hal_layer_set_reg_up(hal_video_layer);
400
401 return 0;
402 }
403
start_gx(unsigned int layer,unsigned long addr,unsigned int strd,hi_vo_rect gx_rect)404 int start_gx(unsigned int layer, unsigned long addr, unsigned int strd, hi_vo_rect gx_rect)
405 {
406 hi_rect disp_rect = { gx_rect.x, gx_rect.y, gx_rect.w, gx_rect.h };
407 hi_vo_layer vo_layer;
408 hal_disp_layer hal_gfx_layer;
409 vo_intf_type intf_type;
410 vo_csc gfx_csc;
411 csc_coef_param csc_coef;
412
413 vo_layer = gfx_convert_layer(layer);
414 hal_gfx_layer = gfx_convert_layer(layer);
415 intf_type = vo_drv_get_dev_intf_type(layer);
416
417 vo_dcache_range(addr, strd * gx_rect.h);
418
419 hal_graphic_set_gfx_ext(vo_layer, HAL_GFX_BITEXTEND_3RD);
420 hal_graphic_set_gfx_palpha(vo_layer, HI_TRUE, HI_TRUE, 0xff, 0xff); /* 0xff max alpha */
421 hal_layer_set_layer_galpha(vo_layer, 0xff); /* 0xff max alpha */
422 hal_graphic_set_gfx_pre_mult(vo_layer, HI_FALSE);
423
424 /* for mipi_tx, close csc */
425 if ((intf_type & VO_INTF_MIPI) ||
426 (intf_type & VO_INTF_MIPI_SLAVE)) {
427 hal_layer_set_csc_en(vo_layer, HI_FALSE);
428 } else {
429 gfx_csc.csc_matrix = VO_CSC_MATRIX_RGB_TO_BT601_TV;
430 gfx_csc.luma = 50; /* 50 default value */
431 gfx_csc.contrast = 50; /* 50 default value */
432 gfx_csc.hue = 50; /* 50 default value */
433 gfx_csc.satuature = 50; /* 50 default value */
434 csc_coef.csc_scale2p = GFX_CSC_SCALE;
435 csc_coef.csc_clip_min = GFX_CSC_CLIP_MIN;
436 csc_coef.csc_clip_max = GFX_CSC_CLIP_MAX;
437 /* do rgb to yuv. */
438 vo_drv_set_csc_coef(hal_gfx_layer, &gfx_csc, &csc_coef);
439 hal_layer_set_csc_en(vo_layer, HI_TRUE);
440 }
441
442 hal_graphic_set_gfx_addr(vo_layer, addr);
443 hal_graphic_set_gfx_stride(vo_layer, strd >> 4); /* 4 to set register */
444 hal_layer_set_layer_in_rect(vo_layer, &disp_rect);
445
446 hal_video_set_layer_disp_rect(vo_layer, &disp_rect);
447 hal_video_set_layer_video_rect(vo_layer, &disp_rect);
448
449 hal_gfx_set_src_resolution(vo_layer, &disp_rect);
450
451 hal_layer_set_layer_data_fmt(vo_layer, HAL_INPUTFMT_ARGB_1555);
452
453 hal_layer_enable_layer(vo_layer, HI_TRUE);
454 hal_layer_set_reg_up(hal_gfx_layer);
455
456 return 0;
457 }
458
stop_gx(unsigned int layer)459 int stop_gx(unsigned int layer)
460 {
461 hi_vo_layer vo_layer;
462 hal_disp_layer hal_gfx_layer;
463
464 vo_layer = gfx_convert_layer(layer);
465 hal_gfx_layer = gfx_convert_to_hal_layer(layer);
466
467 hal_layer_set_reg_up(vo_layer);
468 hal_layer_enable_layer(vo_layer, HI_FALSE);
469 hal_layer_set_reg_up(hal_gfx_layer);
470
471 return 0;
472 }
473
474