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 /* 4 devices default 0x00ffff, 0xFF00, 0xFF00, 0xFF00 default background */
25 static hi_u32 g_bg_color[4] = { 0x00ffff, 0xFF00, 0xFF00, 0xFF00 };
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 < 3) { /* 3 devices */
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 /* to get the width and height of the sync, not magic num */
127 switch (vo_out_mode) {
128 case VO_OUTPUT_PAL:
129 case VO_OUTPUT_576P50:
130 max_width = 720;
131 max_height = 576;
132 break;
133 case VO_OUTPUT_NTSC:
134 case VO_OUTPUT_480P60:
135 max_width = 720;
136 max_height = 480;
137 break;
138 case VO_OUTPUT_720P60:
139 case VO_OUTPUT_720P50:
140 max_width = 1280;
141 max_height = 720;
142 break;
143 case VO_OUTPUT_1080I50:
144 case VO_OUTPUT_1080I60:
145 case VO_OUTPUT_1080P24:
146 case VO_OUTPUT_1080P25:
147 case VO_OUTPUT_1080P30:
148 case VO_OUTPUT_1080P50:
149 case VO_OUTPUT_1080P60:
150 max_width = 1920;
151 max_height = 1080;
152 break;
153 case VO_OUTPUT_800x600_60:
154 case VO_OUTPUT_800x600_50:
155 max_width = 800;
156 max_height = 600;
157 break;
158 case VO_OUTPUT_1024x768_60:
159 max_width = 1024;
160 max_height = 768;
161 break;
162 case VO_OUTPUT_1280x1024_60:
163 max_width = 1280;
164 max_height = 1024;
165 break;
166 case VO_OUTPUT_1366x768_60:
167 max_width = 1366;
168 max_height = 768;
169 break;
170 case VO_OUTPUT_1440x900_60:
171 max_width = 1440;
172 max_height = 900;
173 break;
174 case VO_OUTPUT_1280x800_60:
175 max_width = 1280;
176 max_height = 800;
177 break;
178 case VO_OUTPUT_1600x1200_60:
179 max_width = 1600;
180 max_height = 1200;
181 break;
182 case VO_OUTPUT_1680x1050_60:
183 max_width = 1680;
184 max_height = 1050;
185 break;
186 case VO_OUTPUT_1920x1200_60:
187 max_width = 1920;
188 max_height = 1200;
189 break;
190 case VO_OUTPUT_640x480_60:
191 max_width = 640;
192 max_height = 480;
193 break;
194 case VO_OUTPUT_1920x2160_30:
195 max_width = 1920;
196 max_height = 2160;
197 break;
198 case VO_OUTPUT_2560x1440_30:
199 case VO_OUTPUT_2560x1440_60:
200 max_width = 2560;
201 max_height = 1440;
202 break;
203 case VO_OUTPUT_2560x1600_60:
204 max_width = 2560;
205 max_height = 1600;
206 break;
207 case VO_OUTPUT_3840x2160_24:
208 case VO_OUTPUT_3840x2160_25:
209 case VO_OUTPUT_3840x2160_30:
210 case VO_OUTPUT_3840x2160_50:
211 case VO_OUTPUT_3840x2160_60:
212 max_width = 3840;
213 max_height = 2160;
214 break;
215 case VO_OUTPUT_4096x2160_24:
216 case VO_OUTPUT_4096x2160_25:
217 case VO_OUTPUT_4096x2160_30:
218 case VO_OUTPUT_4096x2160_50:
219 case VO_OUTPUT_4096x2160_60:
220 max_width = 4096;
221 max_height = 2160;
222 break;
223 case VO_OUTPUT_320x240_50:
224 case VO_OUTPUT_320x240_60: /* just for hi3518ev200 hi3519 */
225 max_width = 320;
226 max_height = 240;
227 break;
228 case VO_OUTPUT_240x320_50: /* just for hi3518ev200 hi3519 */
229 case VO_OUTPUT_240x320_60:
230 max_width = 240;
231 max_height = 320;
232 break;
233 case VO_OUTPUT_720x1280_60:
234 max_width = 720;
235 max_height = 1280;
236 break;
237 case VO_OUTPUT_1080x1920_60:
238 max_width = 1080;
239 max_height = 1920;
240 break;
241 case VO_OUTPUT_7680x4320_30:
242 max_width = 7680;
243 max_height = 4320;
244 break;
245 default:
246 max_width = 1920;
247 max_height = 1080;
248 }
249
250 g_max_rect.width = max_width;
251 g_max_rect.height = max_height;
252
253 printf("g_max_rect.width:%u, g_max_rect.height: %u.\n", g_max_rect.width, g_max_rect.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 hi_bool clk_en = HI_FALSE;
259 hi_u32 div_mod;
260
261 if (g_inited == HI_FALSE) {
262 sys_hal_vo_vdp_low_power(HI_TRUE);
263 sys_hal_vo_bus_reset_sel(HI_FALSE);
264 sys_hal_vo_bus_clk_en(HI_TRUE);
265 sys_hal_vo_hd_clk_sel(0, 0x0);
266 /* open clk */
267 vo_drv_set_all_crg_clk(HI_TRUE);
268 vo_drv_board_init();
269 hal_sys_control();
270
271 g_inited = HI_TRUE;
272 }
273
274 if ((dev == VO_DEV_DHD0) || (dev == VO_DEV_DHD1)) {
275 sys_hal_vo_dev_clk_en(dev, HI_TRUE);
276 } else {
277 }
278
279 vo_set_disp_max_size(dev, sync);
280 vo_drv_set_dev_intf_type(dev, type);
281 vo_drv_set_dev_out_sync(dev, sync);
282 vo_drv_set_dev_bk_grd(dev, g_bg_color[dev]);
283 if (vo_drv_special_work_flow(dev)) {
284 clk_en = HI_FALSE;
285 div_mod = 0;
286 sys_hal_vo_bt_bp_clk_en(clk_en);
287 sys_hal_vo_hd1_div_mode(dev, div_mod);
288
289 vo_drv_open(dev);
290
291 vo_drv_set_dev_clk(dev);
292
293 clk_en = HI_TRUE;
294 sys_hal_vo_bt_bp_clk_en(clk_en);
295 } else {
296 vo_drv_set_dev_clk(dev);
297 vo_drv_open(dev);
298 }
299
300 return 0;
301 }
302
stop_vo(unsigned int dev)303 int stop_vo(unsigned int dev)
304 {
305 vo_drv_close(dev);
306 sys_hal_vo_dev_clk_en(dev, HI_FALSE);
307
308 return 0;
309 }
310
start_gx(unsigned int layer,unsigned long addr,unsigned int strd,hi_vo_rect gx_rect)311 int start_gx(unsigned int layer, unsigned long addr, unsigned int strd, hi_vo_rect gx_rect)
312 {
313 hi_rect disp_rect = { gx_rect.x, gx_rect.y, gx_rect.w, gx_rect.h };
314 hi_vo_layer vo_layer;
315 hal_disp_layer hal_gfx_layer;
316 vo_intf_type intf_type;
317
318 gf_g0_zme_cfg zme_cfg;
319
320 vo_layer = gfx_convert_layer(layer);
321 hal_gfx_layer = gfx_convert_layer(layer);
322 intf_type = vo_drv_get_dev_intf_type(layer);
323
324 vo_dcache_range(addr, strd * gx_rect.h);
325
326 hal_graphic_set_gfx_ext(vo_layer, HAL_GFX_BITEXTEND_3RD);
327 hal_graphic_set_gfx_palpha(vo_layer, HI_TRUE, HI_TRUE, 0xff, 0xff);
328 hal_layer_set_layer_galpha(vo_layer, 0xff);
329 hal_graphic_set_gfx_pre_mult(vo_layer, HI_FALSE);
330 /* for mipi_tx, do not do this two line. */
331 if ((intf_type == VO_INTF_HDMI) ||
332 (intf_type == VO_INTF_BT1120)) {
333 /* do rgb to yuv. */
334 vo_drv_graphics_set_csc_coef(vo_layer);
335 hal_layer_set_csc_en(vo_layer, HI_TRUE);
336 } else if ((intf_type == VO_INTF_MIPI) ||
337 vo_drv_is_lcd_intf(intf_type)) {
338 /* do rgb to rgb or do nothing. */
339 }
340
341 hal_graphic_set_gfx_addr(vo_layer, addr);
342 hal_graphic_set_gfx_stride(vo_layer, strd >> 4); /* 4 to set regitster */
343 hal_layer_set_layer_in_rect(vo_layer, &disp_rect);
344
345 /* G0:full screen display */
346 if (vo_layer == VO_LAYER_G0) {
347 /* do zme: disprect to maxrect. */
348 zme_cfg.in_width = disp_rect.width;
349 zme_cfg.in_height = disp_rect.height;
350 zme_cfg.out_width = disp_rect.width;
351 zme_cfg.out_height = disp_rect.height;
352 graphic_drv_enable_zme(vo_layer, &zme_cfg, HI_TRUE);
353 hal_video_set_layer_disp_rect(vo_layer, &disp_rect);
354 hal_video_set_layer_video_rect(vo_layer, &disp_rect);
355 } else {
356 hal_video_set_layer_disp_rect(vo_layer, &disp_rect);
357 hal_video_set_layer_video_rect(vo_layer, &disp_rect);
358 }
359
360 hal_gfx_set_src_resolution(vo_layer, &disp_rect);
361
362 hal_layer_set_layer_data_fmt(vo_layer, HAL_INPUTFMT_ARGB_1555);
363
364 hal_layer_enable_layer(vo_layer, HI_TRUE);
365 hal_layer_set_reg_up(hal_gfx_layer);
366
367 return 0;
368 }
369
stop_gx(unsigned int layer)370 int stop_gx(unsigned int layer)
371 {
372 hi_vo_layer vo_layer;
373 hal_disp_layer hal_gfx_layer;
374
375 vo_layer = gfx_convert_layer(layer);
376 hal_gfx_layer = gfx_convert_to_hal_layer(layer);
377
378 hal_layer_set_reg_up(vo_layer);
379 hal_layer_enable_layer(vo_layer, HI_FALSE);
380 hal_layer_set_reg_up(hal_gfx_layer);
381
382 return 0;
383 }
384
video_layer_set_zme_cfg(unsigned int layer,const hi_rect * disp_rect)385 hi_void video_layer_set_zme_cfg(unsigned int layer, const hi_rect *disp_rect)
386 {
387 vdp_vid_ip_cfg vid_cfg = {0};
388
389 /* 0 1 is regitster config */
390 vid_cfg.csc_en = 0;
391 vid_cfg.hfir_en = 1;
392 vid_cfg.vid_iw = disp_rect->width;
393 vid_cfg.vid_ih = disp_rect->height;
394
395 vid_cfg.vid_ow = disp_rect->width;
396 vid_cfg.vid_oh = disp_rect->height;
397 vid_cfg.zme_en = HI_FALSE;
398 vo_vid_set_zme_enable(layer, &vid_cfg);
399 }
400
video_layer_set_csc_by_intf(unsigned int layer,vo_intf_type intf_type)401 hi_void video_layer_set_csc_by_intf(unsigned int layer, vo_intf_type intf_type)
402 {
403 hi_vo_layer vo_layer;
404
405 vo_layer = video_layer_convert(layer);
406
407 /* for mipi_tx, do not do this two line. */
408 if ((intf_type == VO_INTF_HDMI) ||
409 (intf_type == VO_INTF_BT1120)) {
410 /* do rgb to rgb or do nothing. */
411 } else if ((intf_type == VO_INTF_MIPI) ||
412 vo_drv_is_lcd_intf(intf_type)) {
413 /* do yuv to rgb. */
414 vo_drv_video_set_csc_coef(vo_layer);
415 hal_layer_set_csc_en(vo_layer, HI_TRUE);
416 }
417 }
418
start_videolayer(unsigned int layer,unsigned long addr,unsigned int strd,hi_vo_rect layer_rect)419 int start_videolayer(unsigned int layer, unsigned long addr, unsigned int strd, hi_vo_rect layer_rect)
420 {
421 int i;
422 hi_rect disp_rect = { layer_rect.x, layer_rect.y, layer_rect.w, layer_rect.h };
423 hi_vo_layer vo_layer;
424 hal_disp_layer hal_video_layer;
425 const hi_s32 as32_hfir_coef[2][8] = { /* 2 8 hifb coef array */
426 { 0x3f9, 0xc, 0x3ef, 0x19, 0x3da, 0x3a, 0x397, 0x148 },
427 { 0x3f5, 0xf, 0x3ec, 0x1c, 0x3d8, 0x3d, 0x395, 0x14a }
428 };
429 vo_intf_type intf_type;
430
431 vo_dcache_range(addr, strd * layer_rect.h * 3 / 2); /* 3 / 2 times */
432
433 vo_layer = video_layer_convert(layer);
434 hal_video_layer = video_layer_convert_to_hal(layer);
435 hal_layer_set_layer_data_fmt(layer, VO_LAYER_PIXERL_FORMAT_SP_Y_CB_CR_420);
436 intf_type = vo_drv_get_dev_intf_type(layer);
437
438 video_layer_set_csc_by_intf(layer, intf_type);
439
440 for (i = 0; i <= HAL_DISP_LAYER_VHD1; i++) {
441 hal_video_set_hfir_mode(i, HAL_HFIRMODE_COPY);
442 hal_video_set_hfir_coef(i, as32_hfir_coef[i]);
443 }
444
445 hal_video_set_layer_disp_rect(layer, &disp_rect);
446 hal_video_set_layer_video_rect(layer, &disp_rect);
447 hal_layer_set_layer_out_rect(layer, &disp_rect);
448 hal_layer_set_layer_in_rect(layer, &disp_rect);
449 hal_layer_set_layer_galpha(layer, 255); /* 255 max alpha */
450 hal_layer_set_src_resolution(layer, &disp_rect);
451
452 hal_layer_set_zme_enable(layer, HAL_DISP_ZMEMODE_ALL, HI_FALSE);
453 hal_layer_set_zme_msc_enable(layer, HAL_DISP_ZMEMODE_VERC, HI_TRUE);
454
455 video_layer_set_zme_cfg(layer, &disp_rect);
456
457 hal_layer_set_zme_info(layer, disp_rect.width, disp_rect.height, HAL_DISP_ZME_OUTFMT422);
458
459 /* set area 0 */
460 hal_video_set_multi_area_rect(layer, 0, &disp_rect);
461 hal_video_set_multi_area_reso(layer, 0, disp_rect.width);
462 hal_video_set_multi_area_l_addr(layer, 0, addr, strd);
463 hal_video_set_multi_area_c_addr(layer, 0, addr + strd * vo_align(layer_rect.h, 16), strd); /* align 16 */
464 hal_video_set_multi_area_enable(layer, 0, HI_TRUE);
465 hal_layer_enable_layer(vo_layer, HI_TRUE);
466 hal_layer_set_reg_up(hal_video_layer);
467
468 return 0;
469 }
470
stop_videolayer(unsigned int layer)471 int stop_videolayer(unsigned int layer)
472 {
473 hi_vo_layer vo_layer;
474 hal_disp_layer hal_video_layer;
475
476 vo_layer = video_layer_convert(layer);
477 hal_video_layer = video_layer_convert_to_hal(layer);
478
479 hal_video_set_multi_area_enable(layer, 0, HI_FALSE); /* area 0 */
480 hal_layer_enable_layer(vo_layer, HI_FALSE);
481 hal_layer_set_reg_up(hal_video_layer);
482
483 return 0;
484 }
485
486