/* Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd. */ #include #include #include #include "sample_comm.h" #if VO_LT8618SX #include "lt8618sx.h" #endif #ifdef __cplusplus #if __cplusplus #endif #endif /* end of #ifdef __cplusplus */ static td_bool g_vo_hdmi_rgb_mode = TD_FALSE; static sample_vo_sync_info g_vo_sample_sync_info[OT_VO_OUT_BUTT] = { { OT_VO_OUT_PAL, 720, 576, 25 }, { OT_VO_OUT_NTSC, 720, 480, 30 }, { OT_VO_OUT_960H_PAL, 960, 576, 25 }, { OT_VO_OUT_960H_NTSC, 960, 480, 30 }, { OT_VO_OUT_640x480_60, 640, 480, 60 }, { OT_VO_OUT_480P60, 720, 480, 60 }, { OT_VO_OUT_576P50, 720, 576, 50 }, { OT_VO_OUT_800x600_60, 800, 600, 60 }, { OT_VO_OUT_1024x768_60, 1024, 768, 60 }, { OT_VO_OUT_720P50, 1280, 720, 50 }, { OT_VO_OUT_720P60, 1280, 720, 60 }, { OT_VO_OUT_1280x800_60, 1280, 800, 60 }, { OT_VO_OUT_1280x1024_60, 1280, 1024, 60 }, { OT_VO_OUT_1366x768_60, 1366, 768, 60 }, { OT_VO_OUT_1400x1050_60, 1400, 1050, 60 }, { OT_VO_OUT_1440x900_60, 1440, 900, 60 }, { OT_VO_OUT_1680x1050_60, 1680, 1050, 60 }, { OT_VO_OUT_1080P24, 1920, 1080, 24 }, { OT_VO_OUT_1080P25, 1920, 1080, 25 }, { OT_VO_OUT_1080P30, 1920, 1080, 30 }, { OT_VO_OUT_1080I50, 1920, 1080, 25 }, { OT_VO_OUT_1080I60, 1920, 1080, 30 }, { OT_VO_OUT_1080P50, 1920, 1080, 50 }, { OT_VO_OUT_1080P60, 1920, 1080, 60 }, { OT_VO_OUT_1600x1200_60, 1600, 1200, 60 }, { OT_VO_OUT_1920x1200_60, 1920, 1200, 60 }, { OT_VO_OUT_1920x2160_30, 1920, 2160, 30 }, { OT_VO_OUT_2560x1440_30, 2560, 1440, 30 }, { OT_VO_OUT_2560x1440_60, 2560, 1440, 60 }, { OT_VO_OUT_2560x1600_60, 2560, 1600, 60 }, { OT_VO_OUT_3840x2160_24, 3840, 2160, 24 }, { OT_VO_OUT_3840x2160_25, 3840, 2160, 25 }, { OT_VO_OUT_3840x2160_30, 3840, 2160, 30 }, { OT_VO_OUT_3840x2160_50, 3840, 2160, 50 }, { OT_VO_OUT_3840x2160_60, 3840, 2160, 60 }, { OT_VO_OUT_4096x2160_24, 4096, 2160, 24 }, { OT_VO_OUT_4096x2160_25, 4096, 2160, 25 }, { OT_VO_OUT_4096x2160_30, 4096, 2160, 30 }, { OT_VO_OUT_4096x2160_50, 4096, 2160, 50 }, { OT_VO_OUT_4096x2160_60, 4096, 2160, 60 }, { OT_VO_OUT_7680x4320_30, 7680, 4320, 30 }, { OT_VO_OUT_240x320_50, 240, 320, 50 }, { OT_VO_OUT_320x240_50, 320, 240, 50 }, { OT_VO_OUT_240x320_60, 240, 320, 60 }, { OT_VO_OUT_320x240_60, 320, 240, 60 }, { OT_VO_OUT_800x600_50, 800, 600, 50 }, { OT_VO_OUT_720x1280_60, 720, 1280, 60 }, { OT_VO_OUT_1080x1920_60, 1080, 1920, 60 }, { OT_VO_OUT_USER, 0, 0, 0 } }; td_s32 sample_comm_vo_get_width_height(ot_vo_intf_sync intf_sync, td_u32 *width, td_u32 *height, td_u32 *frame_rate) { check_null_ptr_return(width); check_null_ptr_return(height); check_null_ptr_return(frame_rate); if (intf_sync > OT_VO_OUT_USER) { sample_print("vo intf_sync %d not support!\n", intf_sync); return TD_FAILURE; } *width = g_vo_sample_sync_info[intf_sync].width; *height = g_vo_sample_sync_info[intf_sync].height; *frame_rate = g_vo_sample_sync_info[intf_sync].frame_rate; return TD_SUCCESS; } td_s32 sample_comm_vo_start_dev(ot_vo_dev vo_dev, ot_vo_pub_attr *pub_attr) { td_s32 ret; check_null_ptr_return(pub_attr); ret = ss_mpi_vo_set_pub_attr(vo_dev, pub_attr); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } ret = ss_mpi_vo_enable(vo_dev); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } return TD_SUCCESS; } td_s32 sample_comm_vo_stop_dev(ot_vo_dev vo_dev) { td_s32 ret; ret = ss_mpi_vo_disable(vo_dev); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } return TD_SUCCESS; } td_s32 sample_comm_vo_start_layer(ot_vo_layer vo_layer, const ot_vo_video_layer_attr *layer_attr) { td_s32 ret; check_null_ptr_return(layer_attr); ret = ss_mpi_vo_set_video_layer_attr(vo_layer, layer_attr); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } ret = ss_mpi_vo_enable_video_layer(vo_layer); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } return TD_SUCCESS; } td_s32 sample_comm_vo_stop_layer(ot_vo_layer vo_layer) { td_s32 ret; ret = ss_mpi_vo_disable_video_layer(vo_layer); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } return TD_SUCCESS; } static sample_vo_wnd_info g_vo_sample_wnd_info[VO_MODE_BUTT] = { { VO_MODE_1MUX, 1, 1, 0, 0 }, { VO_MODE_2MUX, 2, 2, 0, 0 }, { VO_MODE_4MUX, 4, 2, 0, 0 }, { VO_MODE_8MUX, 8, 3, 0, 0 }, { VO_MODE_9MUX, 9, 3, 0, 0 }, { VO_MODE_16MUX, 16, 4, 0, 0 }, { VO_MODE_25MUX, 25, 5, 0, 0 }, { VO_MODE_36MUX, 36, 6, 0, 0 }, { VO_MODE_49MUX, 49, 7, 0, 0 }, { VO_MODE_64MUX, 64, 8, 0, 0 }, { VO_MODE_2X4, 8, 4, 4, 2 } }; td_s32 sample_comm_vo_get_wnd_info(sample_vo_mode mode, sample_vo_wnd_info *wnd_info) { check_null_ptr_return(wnd_info); if (mode >= VO_MODE_BUTT) { sample_print("vo mode %d not support!\n", mode); return TD_FAILURE; } wnd_info->mode = mode; wnd_info->wnd_num = g_vo_sample_wnd_info[mode].wnd_num; wnd_info->square = g_vo_sample_wnd_info[mode].square; wnd_info->row = g_vo_sample_wnd_info[mode].row; wnd_info->col = g_vo_sample_wnd_info[mode].col; return TD_SUCCESS; } //////////////////////// void sample_vo_chn_switch(int value){ #if 0 //3 lu vo_chn_switch(1,0,1); vo_chn_switch(0,0,1); vo_chn_switch(2,0,1); if(value== 0){ vo_chn_switch(0,1,0); }else if(value ==1 ){ vo_chn_switch(0,0,1); vo_chn_switch(1,1,0); }else if(value == 2){ vo_chn_switch(1,0,1); vo_chn_switch(2,1,0); }else if(value == 3){ vo_chn_switch(2,0,1); } #endif #if 0 vo_chn_switch(0,0,1); vo_chn_switch(1,0,1); vo_chn_switch(2,0,1); vo_chn_switch(3,0,1); vo_chn_switch(4,0,1); #endif #if 0 if(value== 1){ vo_chn_switch(0,1,0); }else if(value ==2 ){ vo_chn_switch(1,2,0); vo_chn_switch(0,0,1); //vo_chn_switch(0,0,1); //vo_chn_switch(1,1,0); }else if(value == 3){ vo_chn_switch(2,3,0); vo_chn_switch(1,0,1); //vo_chn_switch(2,1,0); }else if(value == 4){ vo_chn_switch(3,4,0); vo_chn_switch(2,0,1); }else if(value == 5){ vo_chn_switch(3,0,1); //vo_chn_switch(4,0,1); //5lu //vo_chn_switch(5,0,1); //6lu //vo_chn_switch(0,0,1); //vo_chn_switch(1,0,1); //vo_chn_switch(2,0,1); } #endif #if 0 //5lu if(value== 1){ //vo_chn_switch(1,0,1); //vo_chn_switch(2,0,1); //vo_chn_switch(3,0,1); //vo_chn_switch(4,0,1); vo_chn_switch(0,2,0); }else if(value ==2 ){ vo_chn_switch(1,2,0); vo_chn_switch(0,0,1); //vo_chn_switch(0,0,1); //vo_chn_switch(1,1,0); }else if(value == 3){ vo_chn_switch(3,4,0); vo_chn_switch(1,0,1); //vo_chn_switch(2,1,0); }else if(value == 4){ vo_chn_switch(3,0,0); vo_chn_switch(2,3,0); //vo_chn_switch(2,0,1); }else if(value == 5){ vo_chn_switch(4,5,0); vo_chn_switch(3,0,1); //vo_chn_switch(2,3,0); //vo_chn_switch(3,0,1); }else if(value == 6){ //vo_chn_switch(5,0,1); vo_chn_switch(4,0,1); vo_chn_switch(3,1,1); //6lu vo_chn_switch(0,1,1); vo_chn_switch(1,1,1); vo_chn_switch(2,1,1); } else if(value == 7){ // vo_chn_switch(5,0,1); vo_chn_switch(0,1,1); vo_chn_switch(1,1,1); vo_chn_switch(2,0,1); vo_chn_switch(4,1,1); //5lu vo_chn_switch(3,1,1); //6lu } #endif #if 1 //2lu switch (value) { case 0: /* 布局一 双屏:视频1(左) + 视频2(右),各 960x720 */ vo_chn_switch(0, 1, 1); vo_chn_switch(1, 1, 1); break; case 1: /* 布局一 视频1 全屏 1920x1200,视频2 隐藏 */ vo_chn_switch(0, 2, 0); vo_chn_switch(1, 0, 1); break; case 2: /* 布局一 视频2 全屏 1920x1200,视频1 隐藏 */ vo_chn_switch(1, 2, 0); vo_chn_switch(0, 0, 1); break; case 3: /* 布局二 视频1 右上角 1280x720 */ vo_chn_switch(0, 2, 2); // 视频1(chn0) 右上角 vo_chn_switch(1, 0, 1); // 视频2(chn1) 隐藏 break; case 4: /* 布局二 视频2 右上角 1280x720 */ vo_chn_switch(1, 2, 2); // 视频2(chn1) 右上角 vo_chn_switch(0, 0, 1); // 视频1(chn0) 隐藏 break; default: break; } #endif } void vo_chn_switch(int vo_channel , int priority, int mux ){ int ret; int vo_layer = 0; ot_vo_chn_attr chn_attr; #if 0 int width = 1920; int height = 1200; //ret = ss_mpi_vo_disable_chn(vo_layer, vo_channel); //if (ret != TD_SUCCESS) { // sample_print("failed with %#x!\n", ret); // return TD_FAILURE; //} ret = ss_mpi_vo_get_chn_attr(vo_layer, vo_channel ,&chn_attr); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } if(mux){ #if 1 // 3lu if (vo_channel==0){ chn_attr.rect.x = 0; chn_attr.rect.y = 0; chn_attr.rect.width = 960; chn_attr.rect.height = 600; } else if (vo_channel==1){ chn_attr.rect.x = 960; chn_attr.rect.y = 0; chn_attr.rect.width = 960; chn_attr.rect.height = 600; } else if (vo_channel==2){ chn_attr.rect.x = 0; chn_attr.rect.y = 600; chn_attr.rect.width = 960; chn_attr.rect.height = 600; } else if (vo_channel==3){ chn_attr.rect.x = 960; chn_attr.rect.y = 600; chn_attr.rect.width = 960; chn_attr.rect.height = 600; }else if(vo_channel==4){ chn_attr.rect.x = 0; chn_attr.rect.y = 600; chn_attr.rect.width = 960; chn_attr.rect.height = 600; } #endif #if 0 // 6lu if (vo_channel==0){ chn_attr.rect.x = 0; chn_attr.rect.y = 0; chn_attr.rect.width = 640; chn_attr.rect.height = 600; } else if (vo_channel==1){ chn_attr.rect.x = 0; chn_attr.rect.y = 600; chn_attr.rect.width = 640; chn_attr.rect.height = 600; } else if (vo_channel==2){ chn_attr.rect.x = 640; chn_attr.rect.y = 0; chn_attr.rect.width = 640; chn_attr.rect.height = 600; }else if (vo_channel==3){ chn_attr.rect.x = 640; chn_attr.rect.y = 600; chn_attr.rect.width = 640; chn_attr.rect.height = 600; }else if (vo_channel==4){ chn_attr.rect.x = 1280; chn_attr.rect.y = 0; chn_attr.rect.width = 640; chn_attr.rect.height = 600; }else if (vo_channel==5){ chn_attr.rect.x = 1280; chn_attr.rect.y = 600; chn_attr.rect.width = 640; chn_attr.rect.height = 600; } #endif #if 0 //4lu chn_attr.rect.x = OT_ALIGN_DOWN((width / 2) * (vo_channel % 2), 2); /* 2: 2 aligin */ chn_attr.rect.y = OT_ALIGN_DOWN((height / 2) * (vo_channel / 2), 2); /* 2: 2 aligin */ chn_attr.rect.width = OT_ALIGN_DOWN(width / 2, 2); /* 2: 2 aligin */ chn_attr.rect.height = OT_ALIGN_DOWN(height / 2, 2); #endif if(mux==2){ if (vo_channel==2){ chn_attr.rect.x = 0; chn_attr.rect.y = 0; chn_attr.rect.width = 200; chn_attr.rect.height = 300; } if (vo_channel==4){ chn_attr.rect.x = 0; chn_attr.rect.y = 0; chn_attr.rect.width = 200; chn_attr.rect.height = 300; } } chn_attr.priority = priority; }else{ chn_attr.rect.x = 0; chn_attr.rect.y = 0; chn_attr.rect.width=1920; chn_attr.rect.height=1080;//1200; chn_attr.priority = priority; } ret = ss_mpi_vo_set_chn_attr(vo_layer, vo_channel, &chn_attr); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } // ret = ss_mpi_vo_enable_chn(vo_layer, vo_channel); // if (ret != TD_SUCCESS) { // sample_print("failed with %#x!\n", ret); // return TD_FAILURE; // } } #endif ret = ss_mpi_vo_get_chn_attr(vo_layer, vo_channel, &chn_attr); if (ret != TD_SUCCESS) { sample_print("get vo chn attr failed %#x!\n", ret); return; } if (mux == 1) { /* 双屏窗口 960x720:chn0 在左,chn1 在右 */ chn_attr.rect.x = (vo_channel == 0) ? 0 : 960; chn_attr.rect.y = 0; chn_attr.rect.width = 960; chn_attr.rect.height = 720; } else if (mux == 0) { /* 全屏 1920x1200 */ chn_attr.rect.x = 0; chn_attr.rect.y = 0; chn_attr.rect.width = 1920; chn_attr.rect.height = 1200; } else if (mux == 2) { /* 右上角 1280x720 */ chn_attr.rect.x = 640; /* 1920 - 1280 */ chn_attr.rect.y = 0; chn_attr.rect.width = 1280; chn_attr.rect.height = 720; } chn_attr.priority = priority; ret = ss_mpi_vo_set_chn_attr(vo_layer, vo_channel, &chn_attr); if (ret != TD_SUCCESS) { sample_print("set vo chn attr failed %#x!\n", ret); return; } /* priority>0 才显示;priority==0 保持 disable,即隐藏 */ if (priority > 0) { ret = ss_mpi_vo_enable_chn(vo_layer, vo_channel); if (ret != TD_SUCCESS) { sample_print("enable vo chn failed %#x!\n", ret); } } } ///////////////////////// td_s32 sample_comm_vo_get_chn_attr(sample_vo_wnd_info *wnd_info, ot_vo_video_layer_attr *layer_attr, td_s32 chn, ot_vo_chn_attr *chn_attr) { td_u32 width; td_u32 height; check_null_ptr_return(wnd_info); check_null_ptr_return(layer_attr); check_null_ptr_return(chn_attr); width = layer_attr->img_size.width; height = layer_attr->img_size.height; if (wnd_info->mode != VO_MODE_2X4) { chn_attr->rect.x = OT_ALIGN_DOWN((width / wnd_info->square) * (chn % wnd_info->square), 2); /* 2: 2 aligin */ chn_attr->rect.y = OT_ALIGN_DOWN((height / wnd_info->square) * (chn / wnd_info->square), 2); /* 2: 2 aligin */ chn_attr->rect.width = OT_ALIGN_DOWN(width / wnd_info->square, 2); /* 2: 2 aligin */ chn_attr->rect.height = OT_ALIGN_DOWN(height / wnd_info->square, 2); /* 2: 2 aligin */ } else { chn_attr->rect.x = OT_ALIGN_DOWN((width / wnd_info->col) * (chn % wnd_info->col), 2); /* 2: 2 aligin */ chn_attr->rect.y = OT_ALIGN_DOWN((height / wnd_info->row) * (chn / wnd_info->col), 2); /* 2: 2 aligin */ chn_attr->rect.width = OT_ALIGN_DOWN(width / wnd_info->col, 2); /* 2: 2 aligin */ chn_attr->rect.height = OT_ALIGN_DOWN(height / wnd_info->row, 2); /* 2: 2 aligin */ } chn_attr->priority = 0; chn_attr->deflicker_en = TD_FALSE; return TD_SUCCESS; } td_s32 sample_comm_vo_start_chn(ot_vo_layer vo_layer, sample_vo_mode mode) { td_s32 ret; td_s32 i; sample_vo_wnd_info wnd_info = { 0 }; ot_vo_chn_attr chn_attr; ot_vo_video_layer_attr layer_attr; ret = sample_comm_vo_get_wnd_info(mode, &wnd_info); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return ret; } ret = ss_mpi_vo_get_video_layer_attr(vo_layer, &layer_attr); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } for (i = 0; i < (td_s32)wnd_info.wnd_num; i++) { ret = sample_comm_vo_get_chn_attr(&wnd_info, &layer_attr, i, &chn_attr); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } ret = ss_mpi_vo_set_chn_attr(vo_layer, i, &chn_attr); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } ret = ss_mpi_vo_enable_chn(vo_layer, i); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } } return TD_SUCCESS; } td_s32 sample_comm_vo_stop_chn(ot_vo_layer vo_layer, sample_vo_mode mode) { td_s32 ret; td_s32 i; sample_vo_wnd_info wnd_info = { 0 }; ret = sample_comm_vo_get_wnd_info(mode, &wnd_info); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return ret; } for (i = 0; i < (td_s32)wnd_info.wnd_num; i++) { ret = ss_mpi_vo_disable_chn(vo_layer, i); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } } return ret; } static td_void sample_private_vo_get_def_wbc_attr(ot_vo_wbc_attr *wbc_attr, ot_vo_wbc_src *source) { wbc_attr->target_size.width = FHD_WIDTH; wbc_attr->target_size.height = FHD_HEIGHT; wbc_attr->pixel_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; wbc_attr->frame_rate = 30; /* 30: 30fps */ wbc_attr->compress_mode = OT_COMPRESS_MODE_NONE; wbc_attr->dynamic_range = OT_DYNAMIC_RANGE_SDR8; source->src_type = OT_VO_WBC_SRC_DEV; source->src_id = SAMPLE_VO_DEV_DHD0; } static td_s32 sample_private_vo_start_wbc(ot_vo_wbc vo_wbc, ot_vo_wbc_attr *wbc_attr, ot_vo_wbc_src *source) { td_s32 ret; ret = ss_mpi_vo_set_wbc_src(vo_wbc, source); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } ret = ss_mpi_vo_set_wbc_attr(vo_wbc, wbc_attr); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } ret = ss_mpi_vo_enable_wbc(vo_wbc); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } return TD_SUCCESS; } static td_s32 sample_private_vo_stop_wbc(ot_vo_wbc vo_wbc) { td_s32 ret; ret = ss_mpi_vo_disable_wbc(vo_wbc); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } return TD_SUCCESS; } td_s32 sample_comm_vo_start_wbc(sample_vo_wbc_cfg *wbc_config) { td_s32 ret; check_null_ptr_return(wbc_config); /* set dynaminc range if changed */ if ((td_s32)wbc_config->dynamic_range != -1) { wbc_config->wbc_attr.dynamic_range = wbc_config->dynamic_range; } /* set compress mode if changed */ if ((td_s32)wbc_config->compress_mode != -1) { wbc_config->wbc_attr.compress_mode = wbc_config->compress_mode; } if (wbc_config->depth > -1) { ret = ss_mpi_vo_set_wbc_depth(wbc_config->vo_wbc, 5); /* 5: wbc depth */ if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return ret; } } wbc_config->wbc_source.src_type = wbc_config->source_type; ret = sample_private_vo_start_wbc(wbc_config->vo_wbc, &wbc_config->wbc_attr, &wbc_config->wbc_source); return ret; } td_s32 sample_comm_vo_stop_wbc(sample_vo_wbc_cfg *wbc_config) { check_null_ptr_return(wbc_config); return sample_private_vo_stop_wbc(wbc_config->vo_wbc); } td_s32 sample_comm_vo_get_def_wbc_config(sample_vo_wbc_cfg *wbc_config) { check_null_ptr_return(wbc_config); wbc_config->vo_wbc = 0; wbc_config->source_type = OT_VO_WBC_SRC_DEV; wbc_config->wbc_source.src_type = OT_VO_WBC_SRC_DEV; wbc_config->wbc_source.src_id = 0; wbc_config->dynamic_range = OT_DYNAMIC_RANGE_BUTT; wbc_config->compress_mode = OT_COMPRESS_MODE_BUTT; wbc_config->depth = OT_INVALID_VALUE; sample_private_vo_get_def_wbc_attr(&wbc_config->wbc_attr, &wbc_config->wbc_source); return TD_SUCCESS; } #if VO_LT8618SX static td_s32 g_vo_lt8618sx_fd = OT_INVALID_VALUE; td_s32 sample_comm_vo_bt1120_start(ot_vo_dev vo_dev, ot_vo_pub_attr *pub_attr) { td_s32 ret; td_u32 lt_mode, clk_edge; ot_vo_bt_param bt_param = {0}; check_null_ptr_return(pub_attr); lt_mode = pub_attr->intf_sync; if (!(pub_attr->intf_type & OT_VO_INTF_BT1120)) { return TD_FAILURE; } ret = ss_mpi_vo_get_bt_param(vo_dev, &bt_param); if (ret != TD_SUCCESS) { sample_print("failed with %#x!\n", ret); return TD_FAILURE; } g_vo_lt8618sx_fd = open(LT8618SX_DEV_NAME, O_RDONLY); if (g_vo_lt8618sx_fd < 0) { sample_print("open file (%s) fail!\n", LT8618SX_DEV_NAME); return TD_FAILURE; } /* 0:single, 1:dual, set the clk edge firstly */ clk_edge = (td_u32)bt_param.clk_edge; if (ioctl(g_vo_lt8618sx_fd, LT_CMD_SETCLK, &clk_edge) < 0) { sample_print("ioctl (%s) set clk fail!\n", LT8618SX_DEV_NAME); } if (ioctl(g_vo_lt8618sx_fd, LT_CMD_SETMODE, <_mode) < 0) { sample_print("ioctl (%s) set mode fail!\n", LT8618SX_DEV_NAME); } close(g_vo_lt8618sx_fd); g_vo_lt8618sx_fd = OT_INVALID_VALUE; return TD_SUCCESS; } #else td_s32 sample_comm_vo_bt1120_start(ot_vo_dev vo_dev, ot_vo_pub_attr *pub_attr) { ot_unused(vo_dev); ot_unused(pub_attr); return TD_SUCCESS; } #endif static const ot_hdmi_video_format g_vo_hdmi_sync[OT_VO_OUT_BUTT] = { OT_HDMI_VIDEO_FORMAT_PAL, OT_HDMI_VIDEO_FORMAT_NTSC, OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE, OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE, OT_HDMI_VIDEO_FORMAT_861D_640X480_60, OT_HDMI_VIDEO_FORMAT_480P_60, OT_HDMI_VIDEO_FORMAT_576P_50, OT_HDMI_VIDEO_FORMAT_VESA_800X600_60, OT_HDMI_VIDEO_FORMAT_VESA_1024X768_60, OT_HDMI_VIDEO_FORMAT_720P_50, OT_HDMI_VIDEO_FORMAT_720P_60, OT_HDMI_VIDEO_FORMAT_VESA_1280X800_60, OT_HDMI_VIDEO_FORMAT_VESA_1280X1024_60, OT_HDMI_VIDEO_FORMAT_VESA_1366X768_60, OT_HDMI_VIDEO_FORMAT_VESA_1400X1050_60, OT_HDMI_VIDEO_FORMAT_VESA_1440X900_60, OT_HDMI_VIDEO_FORMAT_VESA_1680X1050_60, OT_HDMI_VIDEO_FORMAT_1080P_24, OT_HDMI_VIDEO_FORMAT_1080P_25, OT_HDMI_VIDEO_FORMAT_1080P_30, OT_HDMI_VIDEO_FORMAT_1080i_50, OT_HDMI_VIDEO_FORMAT_1080i_60, OT_HDMI_VIDEO_FORMAT_1080P_50, OT_HDMI_VIDEO_FORMAT_1080P_60, OT_HDMI_VIDEO_FORMAT_VESA_1600X1200_60, OT_HDMI_VIDEO_FORMAT_VESA_1920X1200_60, OT_HDMI_VIDEO_FORMAT_1920x2160_30, OT_HDMI_VIDEO_FORMAT_2560x1440_30, OT_HDMI_VIDEO_FORMAT_2560x1440_60, OT_HDMI_VIDEO_FORMAT_2560x1600_60, OT_HDMI_VIDEO_FORMAT_3840X2160P_24, OT_HDMI_VIDEO_FORMAT_3840X2160P_25, OT_HDMI_VIDEO_FORMAT_3840X2160P_30, OT_HDMI_VIDEO_FORMAT_3840X2160P_50, OT_HDMI_VIDEO_FORMAT_3840X2160P_60, OT_HDMI_VIDEO_FORMAT_4096X2160P_24, OT_HDMI_VIDEO_FORMAT_4096X2160P_25, OT_HDMI_VIDEO_FORMAT_4096X2160P_30, OT_HDMI_VIDEO_FORMAT_4096X2160P_50, OT_HDMI_VIDEO_FORMAT_4096X2160P_60, OT_HDMI_VIDEO_FORMAT_7680X4320P_30, OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE, OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE, OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE, OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE, OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE, OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE, OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE, OT_HDMI_VIDEO_FORMAT_VESA_CUSTOMER_DEFINE, }; static td_void sample_comm_vo_hdmi_convert_sync(ot_vo_intf_sync intf_sync, ot_hdmi_video_format *video_fmt) { *video_fmt = OT_HDMI_VIDEO_FORMAT_1080P_60; if ((intf_sync >= OT_VO_OUT_PAL) && (intf_sync < OT_VO_OUT_BUTT)) { *video_fmt = g_vo_hdmi_sync[intf_sync]; } } td_s32 sample_comm_vo_hdmi_start(ot_vo_intf_sync intf_sync) { ot_hdmi_attr attr; ot_hdmi_video_format video_fmt; ot_hdmi_id hdmi_id = OT_HDMI_ID_0; sample_comm_vo_hdmi_convert_sync(intf_sync, &video_fmt); check_return(ss_mpi_hdmi_init(), "ss_mpi_hdmi_init"); check_return(ss_mpi_hdmi_open(hdmi_id), "ss_mpi_hdmi_open"); check_return(ss_mpi_hdmi_get_attr(hdmi_id, &attr), "ss_mpi_hdmi_get_attr"); attr.video_format = video_fmt; check_return(ss_mpi_hdmi_set_attr(hdmi_id, &attr), "ss_mpi_hdmi_set_attr"); check_return(ss_mpi_hdmi_start(hdmi_id), "ss_mpi_hdmi_start"); return TD_SUCCESS; } td_s32 sample_comm_vo_hdmi_stop(td_void) { ot_hdmi_id hdmi_id = OT_HDMI_ID_0; check_return(ss_mpi_hdmi_stop(hdmi_id), "ss_mpi_hdmi_stop"); check_return(ss_mpi_hdmi_close(hdmi_id), "ss_mpi_hdmi_close"); check_return(ss_mpi_hdmi_deinit(), "ss_mpi_hdmi_deinit"); return TD_SUCCESS; } td_s32 sample_comm_vo_get_def_config(sample_vo_cfg *vo_config) { ot_rect def_disp_rect = { 0, 0, 1920, 1080 }; ot_size def_img_size = { 1920, 1080 }; check_null_ptr_return(vo_config); vo_config->vo_dev = SAMPLE_VO_DEV_UHD; vo_config->vo_intf_type = OT_VO_INTF_HDMI; vo_config->intf_sync = OT_VO_OUT_1080P60; vo_config->bg_color = COLOR_RGB_BLACK; vo_config->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; vo_config->disp_rect = def_disp_rect; vo_config->image_size = def_img_size; vo_config->vo_part_mode = OT_VO_PARTITION_MODE_SINGLE; vo_config->dis_buf_len = 3; /* 3: def buf len for single */ vo_config->dst_dynamic_range = OT_DYNAMIC_RANGE_SDR8; vo_config->vo_mode = VO_MODE_1MUX; vo_config->compress_mode = OT_COMPRESS_MODE_NONE; return TD_SUCCESS; } static td_s32 sample_comm_vo_get_vo_layer_attr(sample_vo_cfg *vo_config, ot_vo_video_layer_attr *layer_attr) { td_s32 ret; ot_rect def_disp_rect = { 0, 0, 1920, 1080 }; ot_size def_img_size = { 1920, 1080 }; check_null_ptr_return(vo_config); check_null_ptr_return(layer_attr); ret = sample_comm_vo_get_width_height(vo_config->intf_sync, &layer_attr->display_rect.width, &layer_attr->display_rect.height, &layer_attr->display_frame_rate); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_get_width_height failed!\n"); return ret; } layer_attr->cluster_mode_en = TD_FALSE; layer_attr->double_frame_en = TD_FALSE; layer_attr->pixel_format = vo_config->pix_format; layer_attr->display_rect.x = 0; layer_attr->display_rect.y = 0; /* set display rectangle if changed. */ if (memcmp(&vo_config->disp_rect, &def_disp_rect, sizeof(ot_rect)) != 0) { layer_attr->display_rect.width = vo_config->disp_rect.width; layer_attr->display_rect.height = vo_config->disp_rect.height; } layer_attr->img_size.width = layer_attr->display_rect.width; layer_attr->img_size.height = layer_attr->display_rect.height; /* set image size if changed. */ if (memcmp(&vo_config->image_size, &def_img_size, sizeof(ot_size)) != 0) { layer_attr->img_size.width = vo_config->image_size.width; layer_attr->img_size.height = vo_config->image_size.height; } layer_attr->dst_dynamic_range = vo_config->dst_dynamic_range; layer_attr->display_buf_len = vo_config->dis_buf_len; layer_attr->partition_mode = vo_config->vo_part_mode; layer_attr->compress_mode = vo_config->compress_mode; return TD_SUCCESS; } static td_void sample_comm_vo_set_intf_param(sample_vo_cfg *vo_config) { ot_vo_hdmi_param hdmi_param = { 0 }; /* set interface param */ if (g_vo_hdmi_rgb_mode == TD_TRUE) { ss_mpi_vo_get_hdmi_param(vo_config->vo_dev, &hdmi_param); hdmi_param.csc.csc_matrix = OT_VO_CSC_MATRIX_BT709FULL_TO_RGBFULL; ss_mpi_vo_set_hdmi_param(vo_config->vo_dev, &hdmi_param); } } td_void sample_comm_vo_set_hdmi_rgb_mode(td_bool enable) { g_vo_hdmi_rgb_mode = !!enable; } td_s32 sample_comm_vo_start_vo(sample_vo_cfg *vo_config) { /* VO device vo_dev# information declaration. */ td_s32 ret; ot_vo_dev vo_dev; ot_vo_layer vo_layer; ot_vo_pub_attr vo_pub_attr = { 0 }; ot_vo_video_layer_attr layer_attr = { 0 }; check_null_ptr_return(vo_config); vo_dev = vo_config->vo_dev; vo_layer = vo_config->vo_dev; /* set and start VO device vo_dev#. */ vo_pub_attr.intf_type = vo_config->vo_intf_type; vo_pub_attr.intf_sync = vo_config->intf_sync; vo_pub_attr.bg_color = vo_config->bg_color; ret = sample_comm_vo_start_dev(vo_dev, &vo_pub_attr); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_start_dev failed!\n"); return ret; } ret = sample_comm_vo_get_vo_layer_attr(vo_config, &layer_attr); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_start get video layer failed!\n"); (td_void)sample_comm_vo_stop_dev(vo_dev); return ret; } ret = sample_comm_vo_start_layer(vo_layer, &layer_attr); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_start set video layer failed!\n"); (td_void)sample_comm_vo_stop_dev(vo_dev); return ret; } /* set interface param */ sample_comm_vo_set_intf_param(vo_config); /* start vo channels. */ ret = sample_comm_vo_start_chn(vo_layer, vo_config->vo_mode); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_start_chn failed!\n"); (td_void)sample_comm_vo_stop_layer(vo_layer); (td_void)sample_comm_vo_stop_dev(vo_dev); return ret; } /* start hdmi device. note : do this after vo device started. */ if (vo_config->vo_intf_type & OT_VO_INTF_HDMI) { (td_void)sample_comm_vo_hdmi_start(vo_config->intf_sync); } /* start bt1120 device. note : do this after vo device started. */ if (vo_config->vo_intf_type & OT_VO_INTF_BT1120) { (td_void)sample_comm_vo_bt1120_start(vo_dev, &vo_pub_attr); } return TD_SUCCESS; } td_s32 sample_comm_vo_start_pip(sample_vo_cfg *vo_config) { /* VO device vo_dev# information declaration. */ ot_vo_dev vo_dev; ot_vo_layer vo_layer; ot_vo_pub_attr vo_pub_attr = { 0 }; ot_vo_video_layer_attr layer_attr = { 0 }; td_s32 ret; check_null_ptr_return(vo_config); vo_dev = vo_config->vo_dev; vo_layer = SAMPLE_VO_LAYER_PIP; vo_pub_attr.intf_sync = vo_config->intf_sync; /* set and start layer vo_dev#. */ ret = sample_comm_vo_get_width_height(vo_pub_attr.intf_sync, &layer_attr.display_rect.width, &layer_attr.display_rect.height, &layer_attr.display_frame_rate); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_get_width_height failed!\n"); (td_void)sample_comm_vo_stop_dev(vo_dev); return ret; } layer_attr.cluster_mode_en = TD_FALSE; layer_attr.double_frame_en = TD_FALSE; layer_attr.pixel_format = vo_config->pix_format; layer_attr.display_rect.x = 0; layer_attr.display_rect.y = 0; /* set display rectangle if changed. */ layer_attr.display_rect.width /= 2; /* 2: 2x */ layer_attr.display_rect.height /= 2; /* 2: 2x */ layer_attr.img_size.width = layer_attr.display_rect.width; layer_attr.img_size.height = layer_attr.display_rect.height; /* set image size if changed. */ layer_attr.dst_dynamic_range = vo_config->dst_dynamic_range; layer_attr.display_buf_len = vo_config->dis_buf_len; layer_attr.partition_mode = vo_config->vo_part_mode; ret = sample_comm_vo_start_layer(vo_layer, &layer_attr); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_start video layer failed!\n"); (td_void)sample_comm_vo_stop_dev(vo_dev); return ret; } /* start vo channels. */ ret = sample_comm_vo_start_chn(vo_layer, vo_config->vo_mode); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_start_chn failed!\n"); (td_void)sample_comm_vo_stop_layer(vo_layer); (td_void)sample_comm_vo_stop_dev(vo_dev); return ret; } return TD_SUCCESS; } td_s32 sample_comm_vo_stop_vo(const sample_vo_cfg *vo_config) { td_s32 ret; ot_vo_dev vo_dev; ot_vo_layer vo_layer; sample_vo_mode vo_mode; check_null_ptr_return(vo_config); vo_dev = vo_config->vo_dev; vo_layer = vo_config->vo_dev; vo_mode = vo_config->vo_mode; if (OT_VO_INTF_HDMI & vo_config->vo_intf_type) { sample_comm_vo_hdmi_stop(); } ret = sample_comm_vo_stop_chn(vo_layer, vo_mode); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_stop_vo stop chn failed!\n"); return ret; } ret = sample_comm_vo_stop_layer(vo_layer); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_stop_vo stop layer failed!\n"); return ret; } ret = sample_comm_vo_stop_dev(vo_dev); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_stop_vo stop dev failed!\n"); return ret; } return TD_SUCCESS; } td_s32 sample_comm_vo_stop_pip(const sample_vo_cfg *vo_config) { td_s32 ret; ot_vo_layer vo_layer; check_null_ptr_return(vo_config); vo_layer = SAMPLE_VO_LAYER_PIP; ret = sample_comm_vo_stop_chn(vo_layer, vo_config->vo_mode); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_stop_pip stop chn failed!\n"); return ret; } ret = sample_comm_vo_stop_layer(vo_layer); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_stop_pip stop layer failed!\n"); return ret; } return TD_SUCCESS; } td_s32 sample_comm_vo_get_def_layer_config(sample_comm_vo_layer_cfg *vo_layer_config) { ot_rect def_disp_rect = { 0, 0, 1920, 1080 }; ot_size def_img_size = { 1920, 1080 }; check_null_ptr_return(vo_layer_config); vo_layer_config->vo_layer = SAMPLE_VO_LAYER_VHD2; vo_layer_config->intf_sync = OT_VO_OUT_1080P60; vo_layer_config->display_rect = def_disp_rect; vo_layer_config->image_size = def_img_size; vo_layer_config->pix_format = OT_PIXEL_FORMAT_YVU_SEMIPLANAR_420; vo_layer_config->dis_buf_len = 3; /* 3: display buf len */ vo_layer_config->vo_mode = VO_MODE_1MUX; return TD_SUCCESS; } static td_s32 sample_comm_vo_get_layer_layer_attr(sample_comm_vo_layer_cfg *vo_layer_config, ot_vo_video_layer_attr *layer_attr) { td_s32 ret; td_u32 frmt = 0; td_u32 width = 0; td_u32 height = 0; ot_rect def_disp_rect = { 0, 0, 1920, 1080 }; ot_size def_img_size = { 1920, 1080 }; check_null_ptr_return(vo_layer_config); check_null_ptr_return(layer_attr); /* start vo layer. */ ret = sample_comm_vo_get_width_height(vo_layer_config->intf_sync, &width, &height, &frmt); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_get_width_height failed!\n"); return TD_FAILURE; } layer_attr->display_rect.x = 0; layer_attr->display_rect.y = 0; layer_attr->display_rect.width = width; layer_attr->display_rect.height = height; layer_attr->display_frame_rate = frmt; layer_attr->double_frame_en = TD_FALSE; layer_attr->cluster_mode_en = TD_FALSE; layer_attr->pixel_format = vo_layer_config->pix_format; /* set display rectangle if changed. */ if (memcmp(&vo_layer_config->display_rect, &def_disp_rect, sizeof(ot_rect)) != 0) { layer_attr->display_rect.width = vo_layer_config->display_rect.width; layer_attr->display_rect.height = vo_layer_config->display_rect.height; } layer_attr->img_size.width = layer_attr->display_rect.width; layer_attr->img_size.height = layer_attr->display_rect.height; /* set image size if changed. */ if (memcmp(&vo_layer_config->image_size, &def_img_size, sizeof(ot_size)) != 0) { layer_attr->img_size.width = vo_layer_config->image_size.width; layer_attr->img_size.height = vo_layer_config->image_size.height; } layer_attr->dst_dynamic_range = vo_layer_config->dst_dynamic_range; layer_attr->display_buf_len = vo_layer_config->dis_buf_len; return TD_SUCCESS; } td_s32 sample_comm_vo_start_layer_chn(sample_comm_vo_layer_cfg *vo_layer_config) { td_s32 ret; ot_vo_layer vo_layer; ot_vo_video_layer_attr layer_attr = { 0 }; check_null_ptr_return(vo_layer_config); vo_layer = vo_layer_config->vo_layer; ret = sample_comm_vo_get_layer_layer_attr(vo_layer_config, &layer_attr); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_start video layer failed!\n"); return ret; } ret = sample_comm_vo_start_layer(vo_layer, &layer_attr); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_start video layer failed!\n"); return ret; } /* start vo channels. */ ret = sample_comm_vo_start_chn(vo_layer, vo_layer_config->vo_mode); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_start_chn failed!\n"); (td_void)sample_comm_vo_stop_layer(vo_layer); return ret; } return ret; } td_s32 sample_comm_vo_stop_layer_chn(sample_comm_vo_layer_cfg *vo_layer_config) { td_s32 ret; ot_vo_layer vo_layer; check_null_ptr_return(vo_layer_config); vo_layer = vo_layer_config->vo_layer; ret = sample_comm_vo_stop_chn(vo_layer, vo_layer_config->vo_mode); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_stop_layer_chn stop chn failed!\n"); return ret; } ret = sample_comm_vo_stop_layer(vo_layer); if (ret != TD_SUCCESS) { sample_print("sample_comm_vo_stop_layer_chn stop layer failed!\n"); return ret; } return TD_SUCCESS; } #ifdef __cplusplus #if __cplusplus } #endif #endif /* end of #ifdef __cplusplus */