/* ** ** Copyright (C) 2008, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef LOG_TAG #undef LOG_TAG #define LOG_TAG "HwDisplay" #endif /* use 'g_disp_mgr' instead of the parameters under */ #if 0 static pthread_mutex_t disp_mgr_lock; static int mInitialized = 0; static int mDisp_fd = -1; static unsigned int mLayerStatus[CHN_NUM][LYL_NUM]; static int mScreen; static int mCurLayerCnt; #endif static struct hwdisp_mgr g_disp_mgr; static int check_hlay_valid(int hlay) { int bValid = 0; int ch = HD2CHN(hlay); int lyl = HD2LYL(hlay); if(ch >=0 && ch < CHN_NUM) { if(lyl >=0 && lyl < LYL_NUM) { bValid = 1; } } return bValid; } int hw_display_init() { LOGD(""); memset(&g_disp_mgr, 0, sizeof(g_disp_mgr)); pthread_mutex_init(&g_disp_mgr.mlock, NULL); g_disp_mgr.disp_fd = -1; return hwd_init(); } int hw_display_deinit() { if (g_disp_mgr.is_init) { hwd_exit(); g_disp_mgr.is_init = 0; pthread_mutex_destroy(&g_disp_mgr.mlock); } return 0; } int layer_release(int hlay) { return hwd_layer_close(hlay); } int layer_config(__DISP_t cmd, disp_layer_config *pinfo) { unsigned long args[4] = {0}; int ret = RET_OK; args[0] = g_disp_mgr.cur_screen; args[1] = (unsigned long)pinfo; args[2] = 1; ret = ioctl(g_disp_mgr.disp_fd, cmd, args); if(ret < 0) { LOGE("ioctl failed: %s", strerror(errno)); ret = RET_FAIL; } return ret; } int layer_get_para(disp_layer_config *pinfo) { /*int ret = layer_config(DISP_LAYER_GET_CONFIG, pinfo); if (ret < 0) LOGE("get para failed");*/ int bValid = 0; if(pinfo != NULL) { if(pinfo->channel < CHN_NUM && pinfo->layer_id < LYL_NUM) { bValid = 1; } else { LOGE("fatal error! pinfo->channel[%d]layer_id[%d] is invalid!", pinfo->channel, pinfo->layer_id); } } else { LOGE("fatal error! pinfo == NULL!"); } int ret = RET_OK; if(bValid) { if(!g_disp_mgr.layer[pinfo->channel][pinfo->layer_id].config.enable) //if disable, then driver will not store para, use our storage. { //LOGD("ch[%d]lyl[%d] disable, use storage value", pinfo->channel, pinfo->layer_id); memcpy(pinfo, &g_disp_mgr.layer[pinfo->channel][pinfo->layer_id].config, sizeof(disp_layer_config)); ret = RET_OK; } else { ret = layer_config(DISP_LAYER_GET_CONFIG, pinfo); if (ret < 0) { LOGE("get para failed"); } else { if(ret > 0) { LOGW("Be careful! layer_config ret[%d] > 0, is it normal?", ret); } /*if(memcmp(&g_disp_mgr.layer[pinfo->channel][pinfo->layer_id].config, pinfo, sizeof(disp_layer_config))!=0) { disp_layer_config *pUserConfig = &g_disp_mgr.layer[pinfo->channel][pinfo->layer_id].config; LOGD("fatal error! ch[%d]lyl[%d] disp layer config is not match!", pinfo->channel, pinfo->layer_id); }*/ } } } else { ret = RET_FAIL; } return ret; } int layer_set_para(disp_layer_config *pinfo) { int ret = layer_config(DISP_LAYER_SET_CONFIG, pinfo); if (ret < 0) { LOGE("set para failed"); } else { if(ret > 0) { LOGW("Be careful! layer_config ret[%d] > 0, is it normal?", ret); } int bValid = 0; if(pinfo != NULL) { if(pinfo->channel < CHN_NUM && pinfo->layer_id < LYL_NUM) { bValid = 1; } else { LOGE("fatal error! pinfo->channel[%d]layer_id[%d] is invalid!", pinfo->channel, pinfo->layer_id); } } else { LOGE("fatal error! pinfo == NULL!"); } if(bValid) { memcpy(&g_disp_mgr.layer[pinfo->channel][pinfo->layer_id].config, pinfo, sizeof(disp_layer_config)); } } return ret; } #define ALIGN_16B(x) (((x) + (15)) & ~(15)) int hwd_layer_set_src(unsigned int hlay, struct src_info *src) { if(!check_hlay_valid(hlay)) { LOGE("fatal error! hlay[%d] invalid!", hlay); return RET_FAIL; } int ret = RET_OK; //pthread_mutex_lock(&g_disp_mgr.mlock); pthread_mutex_lock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); unsigned long args[4] = {0}; disp_layer_config config; memset(&config, 0, sizeof(disp_layer_config)); config.channel = HD2CHN(hlay); config.layer_id = HD2LYL(hlay); layer_get_para(&config); config.info.fb.crop.x = src->crop_x; config.info.fb.crop.y = src->crop_y; config.info.fb.crop.width = (src->crop_w); config.info.fb.crop.height = (src->crop_h); LOGD("x: %lld, y: %lld, width: 0x%llx, height: 0x%llx", config.info.fb.crop.x, config.info.fb.crop.y, config.info.fb.crop.width, config.info.fb.crop.height); config.info.fb.crop.x = config.info.fb.crop.x << 32; config.info.fb.crop.y = config.info.fb.crop.y << 32; config.info.fb.crop.width = config.info.fb.crop.width << 32; config.info.fb.crop.height = config.info.fb.crop.height << 32; LOGD("width: 0x%llx, height: 0x%llx", config.info.fb.crop.width, config.info.fb.crop.height); config.info.fb.size[0].width = src->w; config.info.fb.size[0].height = src->h; config.info.fb.color_space = (disp_color_space)src->color_space; switch(src->format) { case HWC_FORMAT_YUV420PLANAR: // YU12 config.info.fb.format = DISP_FORMAT_YUV420_P; /* config.info.fb.addr[0] = (int)(config.info.fb.addr[0] ); config.info.fb.addr[1] = (int)(config.info.fb.addr[0] + fb_width*fb_height); config.info.fb.addr[2] = (int)(config.info.fb.addr[0] + fb_width*fb_height*5/4); */ config.info.fb.size[1].width = config.info.fb.size[0].width / 2; config.info.fb.size[1].height = config.info.fb.size[0].height / 2; config.info.fb.size[2].width = config.info.fb.size[0].width / 2; config.info.fb.size[2].height = config.info.fb.size[0].height / 2; break; case HWC_FORMAT_YUV420UVC: config.info.fb.format = DISP_FORMAT_YUV420_SP_UVUV; config.info.fb.size[1].width = config.info.fb.size[0].width / 2; config.info.fb.size[1].height = config.info.fb.size[0].height / 2; //config.info.fb.size[2].width = config.info.fb.size[0].width / 2; //config.info.fb.size[2].height = config.info.fb.size[0].height / 2; break; case HWC_FORMAT_YUV420VUC: // NV21 config.info.fb.format = DISP_FORMAT_YUV420_SP_VUVU; config.info.fb.size[1].width = config.info.fb.size[0].width/2; config.info.fb.size[1].height = config.info.fb.size[0].height/2; //config.info.fb.color_space = DISP_YCC; //config.info.fb.size[2].width = config.info.fb.size[0].width/2; //config.info.fb.size[2].height = config.info.fb.size[0].height/2; break; case HWC_FORMAT_YUV444PLANAR: config.info.fb.format = DISP_FORMAT_YUV444_P; /* config.info.fb.addr[0] = (int)(config.info.fb.addr[0]); config.info.fb.addr[1] = (int)(config.info.fb.addr[0] + fb_width*fb_height); config.info.fb.addr[2] = (int)(config.info.fb.addr[0] + fb_width*fb_height*2); */ config.info.fb.size[1].width = config.info.fb.size[0].width; config.info.fb.size[1].height = config.info.fb.size[0].height; config.info.fb.size[2].width = config.info.fb.size[0].width; config.info.fb.size[2].height = config.info.fb.size[0].height; break; case HWC_FORMAT_YUV422PLANAR: config.info.fb.format = DISP_FORMAT_YUV422_P; /* config.info.fb.addr[0] = (int)(config.info.fb.addr[0] ); config.info.fb.addr[1] = (int)(config.info.fb.addr[0] + fb_width*fb_height); config.info.fb.addr[2] = (int)(config.info.fb.addr[0] + fb_width*fb_height*3/2); */ config.info.fb.size[1].width = config.info.fb.size[0].width / 2; config.info.fb.size[1].height = config.info.fb.size[0].height; config.info.fb.size[2].width = config.info.fb.size[0].width / 2; config.info.fb.size[2].height = config.info.fb.size[0].height; break; case HWC_FORMAT_YUV422UVC: config.info.fb.format = DISP_FORMAT_YUV422_SP_UVUV; config.info.fb.size[1].width = config.info.fb.size[0].width / 2; config.info.fb.size[1].height = config.info.fb.size[0].height; config.info.fb.size[2].width = config.info.fb.size[0].width / 2; config.info.fb.size[2].height = config.info.fb.size[0].height; break; case HWC_FORMAT_YUV422VUC: config.info.fb.format = DISP_FORMAT_YUV422_SP_VUVU; config.info.fb.size[1].width = config.info.fb.size[0].width / 2; config.info.fb.size[1].height = config.info.fb.size[0].height; config.info.fb.size[2].width = config.info.fb.size[0].width / 2; config.info.fb.size[2].height = config.info.fb.size[0].height; break; case HWC_FORMAT_YUV411PLANAR: config.info.fb.format = DISP_FORMAT_YUV411_P; /* config.info.fb.addr[0] = (int)(config.info.fb.addr[0] ); config.info.fb.addr[1] = (int)(config.info.fb.addr[0] + fb_width*fb_height); config.info.fb.addr[2] = (int)(config.info.fb.addr[0] + fb_width*fb_height*5/4); */ config.info.fb.size[1].width = config.info.fb.size[0].width / 4; config.info.fb.size[1].height = config.info.fb.size[0].height; config.info.fb.size[2].width = config.info.fb.size[0].width / 4; config.info.fb.size[2].height = config.info.fb.size[0].height; break; case HWC_FORMAT_YUV411UVC: config.info.fb.format = DISP_FORMAT_YUV411_SP_UVUV; config.info.fb.size[1].width = config.info.fb.size[0].width / 4; config.info.fb.size[1].height = config.info.fb.size[0].height; config.info.fb.size[2].width = config.info.fb.size[0].width / 4; config.info.fb.size[2].height = config.info.fb.size[0].height; break; case HWC_FORMAT_YUV411VUC: config.info.fb.format = DISP_FORMAT_YUV411_SP_VUVU; config.info.fb.size[1].width = config.info.fb.size[0].width / 4; config.info.fb.size[1].height = config.info.fb.size[0].height; config.info.fb.size[2].width = config.info.fb.size[0].width / 4; config.info.fb.size[2].height = config.info.fb.size[0].height; break; case HWC_FORMAT_YCbYCr_422_I: //yuyv, yuy2, config.info.fb.format = DISP_FORMAT_YUV422_I_VYUY; break; case HWC_FORMAT_ARGB_8888: { config.info.fb.format = DISP_FORMAT_ARGB_8888; break; } default: /* INTERLEAVED */ /* config.info.fb.addr[0] = (int)(config.info.fb.addr[0] + fb_width*fb_height/3*0); config.info.fb.addr[1] = (int)(config.info.fb.addr[0] + fb_width*fb_height/3*1); config.info.fb.addr[2] = (int)(config.info.fb.addr[0] + fb_width*fb_height/3*2); */ config.info.fb.format = DISP_FORMAT_ARGB_8888; config.info.fb.size[1].width = config.info.fb.size[0].width; config.info.fb.size[1].height = config.info.fb.size[0].height; config.info.fb.size[2].width = config.info.fb.size[0].width; config.info.fb.size[2].height = config.info.fb.size[0].height; break; } LOGD("set fb.format %d %d, color_space %d end, size0[%dx%d], size1[%dx%d]", src->format, config.info.fb.format, config.info.fb.color_space, config.info.fb.size[0].width, config.info.fb.size[0].height, config.info.fb.size[1].width, config.info.fb.size[1].height); ret = layer_set_para(&config); if (0 == ret) { g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].config.info.fb.crop = config.info.fb.crop; g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].config.info.fb.color_space = config.info.fb.color_space; g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].config.info.fb.format = config.info.fb.format; memcpy(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].config.info.fb.size[0], &config.info.fb.size[0], sizeof(config.info.fb.size)); } else { LOGE("fatal error! set para fail[%d]", ret); } //pthread_mutex_unlock(&g_disp_mgr.mlock); pthread_mutex_unlock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); return ret; } int hwd_layer_set_rect(unsigned int hlay, struct view_info *view) { if(!check_hlay_valid(hlay)) { LOGE("fatal error! hlay[%d] invalid!", hlay); return RET_FAIL; } int ret = 0; //pthread_mutex_lock(&g_disp_mgr.mlock); pthread_mutex_lock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); disp_layer_config config; memset(&config, 0, sizeof(disp_layer_config)); config.channel = HD2CHN(hlay); config.layer_id = HD2LYL(hlay); layer_get_para(&config); config.info.screen_win.x = view->x; config.info.screen_win.y = view->y; config.info.screen_win.width = view->w; config.info.screen_win.height = view->h; LOGD("ch[%d]lyl[%d]: screen_win[%d,%d, %dx%d]", config.channel, config.layer_id, config.info.screen_win.x, config.info.screen_win.y, config.info.screen_win.width, config.info.screen_win.height); ret = layer_set_para(&config); if (0 == ret) { g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].config.info.screen_win = config.info.screen_win; } else { LOGE("fatal error! set para fail[%d]", ret); } //pthread_mutex_unlock(&g_disp_mgr.mlock); pthread_mutex_unlock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); return ret; } int hwd_layer_top(unsigned int hlay) { if(!check_hlay_valid(hlay)) { LOGE("fatal error! hlay[%d] invalid!", hlay); return RET_FAIL; } int ret = 0; disp_layer_config config; LOGD("set hlay to top"); memset(&config, 0, sizeof(disp_layer_config)); config.channel = HD2CHN(hlay); config.layer_id = HD2LYL(hlay); //pthread_mutex_lock(&g_disp_mgr.mlock); pthread_mutex_lock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); layer_get_para(&config); config.info.zorder = ZORDER_MAX; ret = layer_set_para(&config); if (0 == ret) { g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].config.info.zorder = config.info.zorder; } //pthread_mutex_unlock(&g_disp_mgr.mlock); pthread_mutex_unlock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); return ret; } int hwd_layer_bottom(unsigned int hlay) { if(!check_hlay_valid(hlay)) { LOGE("fatal error! hlay[%d] invalid!", hlay); return RET_FAIL; } int ret = 0; disp_layer_config config; memset(&config, 0, sizeof(disp_layer_config)); config.channel = HD2CHN(hlay); config.layer_id = HD2LYL(hlay); //pthread_mutex_lock(&g_disp_mgr.mlock); pthread_mutex_lock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); layer_get_para(&config); config.info.zorder = ZORDER_MIN; ret = layer_set_para(&config); if (0 == ret) { g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].config.info.zorder = config.info.zorder; } //pthread_mutex_unlock(&g_disp_mgr.mlock); pthread_mutex_unlock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); return ret; } int hwd_layer_set_zorder(unsigned int hlay, unsigned char zorder) { if(!check_hlay_valid(hlay)) { LOGE("fatal error! hlay[%d] invalid!", hlay); return RET_FAIL; } int ret = 0; if(zorder < ZORDER_MIN || zorder > ZORDER_MAX) { LOGW("zorder[%d] is wrong!", zorder); return RET_FAIL; } disp_layer_config config; memset(&config, 0, sizeof(disp_layer_config)); config.channel = HD2CHN(hlay); config.layer_id = HD2LYL(hlay); //pthread_mutex_lock(&g_disp_mgr.mlock); pthread_mutex_lock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); layer_get_para(&config); config.info.zorder = zorder; ret = layer_set_para(&config); if (0 == ret) { g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].config.info.zorder = config.info.zorder; } //pthread_mutex_unlock(&g_disp_mgr.mlock); pthread_mutex_unlock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); return ret; } int hwd_layer_open(unsigned int hlay) { if(!check_hlay_valid(hlay)) { LOGE("fatal error! hlay[%d] invalid!", hlay); return RET_FAIL; } int ret = 0; disp_layer_config config; memset(&config, 0, sizeof(disp_layer_config)); config.channel = HD2CHN(hlay); config.layer_id = HD2LYL(hlay); //pthread_mutex_lock(&g_disp_mgr.mlock); pthread_mutex_lock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); layer_get_para(&config); config.enable = 1; ret = layer_set_para(&config); if (0 == ret) { g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].open_flag = config.enable; g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].config.enable = config.enable; } //pthread_mutex_unlock(&g_disp_mgr.mlock); pthread_mutex_unlock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); return ret; } int hwd_layer_close(unsigned int hlay) { if(!check_hlay_valid(hlay)) { LOGE("fatal error! hlay[%d] invalid!", hlay); return RET_FAIL; } int ret = 0; disp_layer_config config; memset(&config, 0, sizeof(disp_layer_config)); config.channel = HD2CHN(hlay); config.layer_id = HD2LYL(hlay); //pthread_mutex_lock(&g_disp_mgr.mlock); pthread_mutex_lock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); layer_get_para(&config); config.enable = 0; ret = layer_set_para(&config); if (0 == ret) { g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].open_flag = config.enable; g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].config.enable = config.enable; } //pthread_mutex_unlock(&g_disp_mgr.mlock); pthread_mutex_unlock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); usleep(20*1000); // To wait the actual closing of vo(fix issue of mosaic when rls frm buff of vdec) return ret; } static int hwd_set_fb_rotate(int rot) { int fbfd = -1, ret = -1; struct fb_var_screeninfo vinfo; fbfd = open("/dev/fb0", O_RDWR); if (fbfd < 0) { printf("Open fb0 fail!\n"); goto OUT; } ret = ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo); if (ret) { printf("Get vinfo fail!\n"); goto CLOSE; } vinfo.rotate = rot; vinfo.activate = FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW; ret = ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo); if (ret) { printf("set vinfo fail!\n"); goto CLOSE; } CLOSE: close(fbfd); OUT: return ret; } int hwd_set_rot(int p_chn, int p_layer, int rot) { if(!check_hlay_valid(HLAY(p_chn, p_layer))) { LOGE("fatal error! hlay[%d] invalid!", HLAY(p_chn, p_layer)); return RET_FAIL; } pthread_mutex_lock(&g_disp_mgr.layer[p_chn][p_layer].mlock); int ret = 0; unsigned long args[4]={0}; /* Check input parameter */ if (g_disp_mgr.disp_fd < 0) { LOGW("The hwd is not Init!"); return -1; } hwd_set_fb_rotate(rot); args[1] = p_chn; //channel id args[2] = p_layer; //layer id args[3] = rot; //rotate degree LOGW("Be careful! DISP_ROTATION SW_SET_ROT is not support now."); /*ret = ioctl(g_disp_mgr.disp_fd, DISP_ROTATION_SW_SET_ROT, args); if (ret) { LOGW("Do cmd:DISP_ROTATION_SW_SET_ROT error! ret:%d ", ret); } else g_disp_mgr.layer[p_chn][p_layer].rot_degree = rot;*/ pthread_mutex_unlock(&g_disp_mgr.layer[p_chn][p_layer].mlock); return ret; } void openHdmi(int p_chn, int p_layer, disp_output_type p_disp_type, disp_tv_mode p_tv_mode) { int ret = 0; unsigned long args[4]={0}; if( p_disp_type == DISP_OUTPUT_TYPE_HDMI) { args[1] = DISP_OUTPUT_TYPE_NONE; ret = ioctl(g_disp_mgr.disp_fd, DISP_DEVICE_SWITCH, args); if (ret) { LOGE("disp switch failed, disp_type: [%d], tv_mode: [%d]", p_disp_type, p_tv_mode); } hwd_set_rot(p_chn,p_layer, ROTATION_SW_0); } else { hwd_set_rot(p_chn,p_layer, ROTATION_SW_90); } args[0] = p_layer; args[1] = p_disp_type; args[2] = p_tv_mode; ret = ioctl(g_disp_mgr.disp_fd, DISP_DEVICE_SWITCH, args); if (ret) { LOGE("disp switch failed, disp_type: [%d], tv_mode: [%d]", p_disp_type, p_tv_mode); } } void openHdmi20(int p_chn, int p_layer, disp_output_type p_disp_type, disp_tv_mode p_tv_mode) { int ret = 0; unsigned long args[3]; struct disp_device_config config; memset(&config, 0, sizeof(struct disp_device_config)); config.type = p_disp_type; config.mode = p_tv_mode; config.format = DISP_CSC_TYPE_YUV444; config.bits = DISP_DATA_8BITS; config.eotf = DISP_EOTF_GAMMA22; config.dvi_hdmi = DISP_HDMI; config.range = DISP_COLOR_RANGE_16_235; config.scan = DISP_SCANINFO_NO_DATA; config.aspect_ratio = 8; switch (p_tv_mode) { case DISP_TV_MOD_480I: case DISP_TV_MOD_576I: case DISP_TV_MOD_480P: case DISP_TV_MOD_576P: case DISP_TV_MOD_PAL: case DISP_TV_MOD_PAL_SVIDEO: case DISP_TV_MOD_NTSC: case DISP_TV_MOD_NTSC_SVIDEO: case DISP_TV_MOD_PAL_M: case DISP_TV_MOD_PAL_M_SVIDEO: case DISP_TV_MOD_PAL_NC: case DISP_TV_MOD_PAL_NC_SVIDEO: case DISP_TV_MOD_900_540P_60HZ: case DISP_VGA_MOD_640_480P_60: case DISP_VGA_MOD_800_600P_60: { config.cs = DISP_BT601; } break; default: { config.cs = DISP_BT709; } break; } args[0] = p_layer; args[1] = (unsigned long)&config; if( p_disp_type == DISP_OUTPUT_TYPE_HDMI) { config.type = DISP_OUTPUT_TYPE_NONE; ret = ioctl(g_disp_mgr.disp_fd, DISP_DEVICE_SET_CONFIG, args); if (ret) { LOGE("disp switch failed, disp_type: [%d], tv_mode: [%d]", p_disp_type, p_tv_mode); } config.type = p_disp_type; hwd_set_rot(p_chn,p_layer, ROTATION_SW_0); } else { hwd_set_rot(p_chn,p_layer, ROTATION_SW_90); } ret = ioctl(g_disp_mgr.disp_fd, DISP_DEVICE_SET_CONFIG, args); if (ret) { LOGE("disp switch failed, disp_type: [%d], tv_mode: [%d]", p_disp_type, p_tv_mode); } } int hwd_layer_other_screen(int arg, unsigned int hlay1, unsigned int hlay2,disp_output_type disp_type, disp_tv_mode tv_mode) { pthread_mutex_lock(&g_disp_mgr.mlock); LOGD("hwd_layer_other_screen"); disp_layer_config ui_config, csi_config; csi_config.channel = 0; csi_config.layer_id = 0; layer_get_para(&csi_config); if (arg == SCREEN_1) { //change the ui from (2,0) to (1, 0), so that ui can be scaled ui_config.channel = 2; ui_config.layer_id = 0; layer_get_para(&ui_config); openHdmi20(1, SCREEN_0, disp_type,tv_mode); ui_config.enable = 0; layer_set_para(&ui_config); ui_config.info.screen_win.width = 1280; ui_config.info.screen_win.height = 720; ui_config.channel = 1; ui_config.enable = 1; ui_config.info.zorder = 1; layer_set_para(&ui_config); csi_config.info.zorder = 2; //set the csi layer to the top to avoid be covered by ui layer_set_para(&csi_config); } else { ui_config.channel = 1; ui_config.layer_id = 0; layer_get_para(&ui_config); ui_config.enable = 0; layer_set_para(&ui_config); ui_config.info.screen_win.width = 320; ui_config.info.screen_win.height = 240; ui_config.channel = 2; ui_config.enable = 1; ui_config.info.zorder = 8; layer_set_para(&ui_config); //restore ui to (1,0) csi_config.info.zorder = 0; //set the csi to the bottom, because ui can do alpha with it layer_set_para(&csi_config); openHdmi20(2, SCREEN_0, disp_type,tv_mode); } pthread_mutex_unlock(&g_disp_mgr.mlock); LOGD("hwd_layer_other_screen end"); return 0; } int hwd_layer_render(unsigned int hlay, libhwclayerpara_t *picture) { if(!check_hlay_valid(hlay)) { LOGE("fatal error! hlay[%d] invalid!", hlay); return RET_FAIL; } int ret; disp_layer_config config; //pthread_mutex_lock(&g_disp_mgr.mlock); pthread_mutex_lock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); #if 0 if ((config.enable == 0) && g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].open_flag) { memcpy(&config, &g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].config, sizeof(disp_layer_config)); LOGW("detect one open failed layer, now open it again.\r\n"); LOGW("chn %d, lay %d, enable %d, zorder %d, alpha %d, x %d, y %d, w %d, h %d\r\n", config.channel, config.layer_id, config.enable, config.info.zorder, config.info.alpha_value, config.info.screen_win.x, config.info.screen_win.y, config.info.screen_win.width, config.info.screen_win.height); } #else memcpy(&config, &g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].config, sizeof(disp_layer_config)); #endif config.info.fb.addr[0] = picture->top_y; config.info.fb.addr[1] = picture->top_c; config.info.fb.addr[2] = picture->bottom_y; ret = layer_set_para(&config); //pthread_mutex_unlock(&g_disp_mgr.mlock); pthread_mutex_unlock(&g_disp_mgr.layer[HD2CHN(hlay)][HD2LYL(hlay)].mlock); return ret; } int hwd_layer_exchange(unsigned int hlay1, unsigned int hlay2, int otherOnTop) { if(!check_hlay_valid(hlay1)) { LOGE("fatal error! hlay1[%d] invalid!", hlay1); return RET_FAIL; } if(!check_hlay_valid(hlay2)) { LOGE("fatal error! hlay2[%d] invalid!", hlay2); return RET_FAIL; } disp_layer_config config1; disp_layer_config config2; disp_rect rect_tmp; unsigned char zorder_tmp; memset(&config1, 0, sizeof(disp_layer_config)); memset(&config2, 0, sizeof(disp_layer_config)); config1.channel = HD2CHN(hlay1); config1.layer_id = HD2LYL(hlay1); config2.channel = HD2CHN(hlay2); config2.layer_id = HD2LYL(hlay2); pthread_mutex_lock(&g_disp_mgr.mlock); pthread_mutex_lock(&g_disp_mgr.layer[HD2CHN(hlay1)][HD2LYL(hlay1)].mlock); pthread_mutex_lock(&g_disp_mgr.layer[HD2CHN(hlay2)][HD2LYL(hlay2)].mlock); layer_get_para(&config1); layer_get_para(&config2); rect_tmp = config1.info.screen_win; config1.info.screen_win = config2.info.screen_win; g_disp_mgr.layer[HD2CHN(hlay1)][HD2LYL(hlay1)].config.info.screen_win = config2.info.screen_win; config2.info.screen_win = rect_tmp; g_disp_mgr.layer[HD2CHN(hlay2)][HD2LYL(hlay2)].config.info.screen_win = rect_tmp; zorder_tmp = config1.info.zorder; config1.info.zorder = config2.info.zorder; g_disp_mgr.layer[HD2CHN(hlay1)][HD2LYL(hlay1)].config.info.zorder = config2.info.zorder; config2.info.zorder = zorder_tmp; g_disp_mgr.layer[HD2CHN(hlay2)][HD2LYL(hlay2)].config.info.zorder = zorder_tmp; layer_set_para(&config1); layer_set_para(&config2); pthread_mutex_unlock(&g_disp_mgr.layer[HD2CHN(hlay2)][HD2LYL(hlay2)].mlock); pthread_mutex_unlock(&g_disp_mgr.layer[HD2CHN(hlay1)][HD2LYL(hlay1)].mlock); pthread_mutex_unlock(&g_disp_mgr.mlock); return RET_OK; } int hwd_layer_exchange_zorder(unsigned int hlay1, unsigned int hlay2) { if(!check_hlay_valid(hlay1)) { LOGE("fatal error! hlay1[%d] invalid!", hlay1); return RET_FAIL; } if(!check_hlay_valid(hlay2)) { LOGE("fatal error! hlay2[%d] invalid!", hlay2); return RET_FAIL; } disp_layer_config config1; disp_layer_config config2; unsigned char zorder_tmp; memset(&config1, 0, sizeof(disp_layer_config)); memset(&config2, 0, sizeof(disp_layer_config)); config1.channel = HD2CHN(hlay1); config1.layer_id = HD2LYL(hlay1); config2.channel = HD2CHN(hlay2); config2.layer_id = HD2LYL(hlay2); pthread_mutex_lock(&g_disp_mgr.mlock); pthread_mutex_lock(&g_disp_mgr.layer[HD2CHN(hlay1)][HD2LYL(hlay1)].mlock); pthread_mutex_lock(&g_disp_mgr.layer[HD2CHN(hlay2)][HD2LYL(hlay2)].mlock); layer_get_para(&config1); layer_get_para(&config2); zorder_tmp = config1.info.zorder; config1.info.zorder = config2.info.zorder; g_disp_mgr.layer[HD2CHN(hlay1)][HD2LYL(hlay1)].config.info.zorder = config2.info.zorder; config2.info.zorder = zorder_tmp; g_disp_mgr.layer[HD2CHN(hlay2)][HD2LYL(hlay2)].config.info.zorder = zorder_tmp; layer_set_para(&config1); layer_set_para(&config2); pthread_mutex_unlock(&g_disp_mgr.layer[HD2CHN(hlay2)][HD2LYL(hlay2)].mlock); pthread_mutex_unlock(&g_disp_mgr.layer[HD2CHN(hlay1)][HD2LYL(hlay1)].mlock); pthread_mutex_unlock(&g_disp_mgr.mlock); return RET_OK; } int hwd_layer_switch(unsigned int hlay, int bOpen) { if (1 == bOpen) { return hwd_layer_open(hlay); } else if (0 == bOpen) { return hwd_layer_close(hlay); } return RET_FAIL; } int hwd_layer_release(unsigned int hlay) { if(!check_hlay_valid(hlay)) { LOGE("fatal error! hlay[%d] invalid!", hlay); return RET_FAIL; } int chn = HD2CHN(hlay); int lyl = HD2LYL(hlay); int ret = layer_release(hlay); if (RET_OK == ret) { pthread_mutex_lock(&g_disp_mgr.mlock); if (chn >=0 && lyl >=0 && g_disp_mgr.layer[chn][lyl].req_stat) { g_disp_mgr.layer[chn][lyl].req_stat = 0; g_disp_mgr.req_layer_cnt--; } pthread_mutex_unlock(&g_disp_mgr.mlock); } return ret; } int hwd_screen_capture_start(int screen, disp_capture_info cap_info) { unsigned long args[4]={0}; args[0] = screen; args[1] = (unsigned long)&cap_info; args[2] = 0; args[3] = 0; if(ioctl(g_disp_mgr.disp_fd,DISP_CAPTURE_START,(void*)args) < 0) { LOGD("DISP_CAPTURE_START fail"); return -1; } return 0; } int hwd_screen_capture_commit(int screen, disp_capture_info cap_info) { unsigned long args[4]={0}; args[0] = screen; args[1] = (unsigned long)&cap_info; args[2] = 0; args[3] = 0; if(ioctl(g_disp_mgr.disp_fd,DISP_CAPTURE_COMMIT,(void*)args) < 0) { LOGD("DISP_CAPTURE_COMMIT fail"); return -1; } return 0; } int hwd_screen_capture_stop(int screen, disp_capture_info cap_info) { unsigned long args[4]={0}; args[0] = screen; args[1] = (unsigned long)&cap_info; args[2] = 0; args[3] = 0; if(ioctl(g_disp_mgr.disp_fd,DISP_CAPTURE_STOP,(void*)args) < 0) { LOGD("DISP_CAPTURE_STOP fail"); return -1; } return 0; } void hwd_set_outputtype(int screen, int val) { LOGD("+++++=(%s %d %d)", __FUNCTION__, __LINE__,screen); unsigned long args[4]={0}; args[0] = screen; args[1] = val; ioctl(g_disp_mgr.disp_fd, DISP_DEVICE_SWITCH, args); LOGE("(%s %d)", __FUNCTION__, __LINE__); return ; } void hwd_get_outputtype(int screen, int *val) { LOGD("+++++=(%s %d %d)", __FUNCTION__, __LINE__,screen); if(val == NULL){ LOGD("val addr NULL. (%s %d)", __FUNCTION__, __LINE__); return; } disp_output_type output_type; unsigned int arg[3]; arg[0] = screen; output_type = (disp_output_type)ioctl(g_disp_mgr.disp_fd, DISP_GET_OUTPUT_TYPE, (void*)arg); *val = output_type; return ; } int hwd_init() { LOGD("(%s %d)", __FUNCTION__, __LINE__); int ret = RET_OK; g_disp_mgr.cur_screen = SCREEN_0; if (g_disp_mgr.is_init) { return RET_FAIL; } g_disp_mgr.disp_fd = open(DISP_DEV, O_RDWR); if (g_disp_mgr.disp_fd < 0) { LOGE("Failed to open disp device, ret:%d, errno: %d", g_disp_mgr.disp_fd, errno); return RET_FAIL; } g_disp_mgr.layer[UI_LYCHN][UI_LYLAY].req_stat = HWD_STATUS_REQUESTED; //used by fb0 //display resume int args[4]={0}; args[0] = 0; args[1] = 0; ioctl(g_disp_mgr.disp_fd, DISP_BLANK, args); g_disp_mgr.is_init = 1; g_disp_mgr.req_layer_cnt = 1; int ch; int lyl; int err; for(ch=0; chchannel, pLayerConfig->layer_id, pLayerConfig->enable, pLayerConfig->info.screen_win.x, pLayerConfig->info.screen_win.y, pLayerConfig->info.screen_win.width, pLayerConfig->info.screen_win.height, pLayerConfig->info.zorder, pLayerConfig->info.alpha_mode, pLayerConfig->info.alpha_value); } g_disp_mgr.layer[ch][lyl].config.channel = ch; g_disp_mgr.layer[ch][lyl].config.layer_id = lyl; } } } _exit0: return ret; } int hwd_exit(void) { LOGD("(%s %d)", __FUNCTION__, __LINE__); int ret = RET_OK; int ch; int lyl; int err; for(ch=0; ch 0) { LOGW("This disp_type:%d is not support tv_mode:%d", disp_type, tv_mode); return -1; } args[0] = g_disp_mgr.cur_screen; args[1] = (unsigned long)(¶); ret = ioctl(g_disp_mgr.disp_fd, DISP_GET_OUTPUT, args); if (ret < 0) { LOGW("Do cmd:DISP_GET_OUTPUT error! ret:%d", ret); return ret; } LOGI("Current the disp_type:0x%x tv_mode:0x%x", para.type, para.mode); if (disp_type == para.type) { LOGI("Current the disp_type:%d is not change!", disp_type); return 0; } if (disp_type != DISP_OUTPUT_TYPE_LCD) { LOGI("======= SWITCH HDMI ===== "); openHdmi20(2,g_disp_mgr.cur_screen,disp_type,tv_mode); //ui display chn rotate usleep(30 * 1000); } int ch, id; layerinfo.channel = 2; layerinfo.layer_id = 0; ret = layer_get_para(&layerinfo); if (ret) { LOGW("Do layer_get_para error! ret:%d", ret); return -1; } layerinfo.enable = 0; layer_set_para(&layerinfo); switch (disp_type) { case DISP_OUTPUT_TYPE_TV: layerinfo.info.screen_win.x = 0; layerinfo.info.screen_win.y = 0; layerinfo.info.screen_win.width = 720; layerinfo.info.screen_win.height = 576; break; case DISP_OUTPUT_TYPE_LCD: layerinfo.info.screen_win.x = 0; layerinfo.info.screen_win.y = 0; layerinfo.info.screen_win.width = screen_w; layerinfo.info.screen_win.height = screen_h; break; case DISP_OUTPUT_TYPE_HDMI: layerinfo.info.screen_win.x = 0; layerinfo.info.screen_win.y = 0; layerinfo.info.screen_win.width = 1920; layerinfo.info.screen_win.height = 1080; break; default: break; } layerinfo.enable = 1; ret = layer_set_para(&layerinfo); if (ret) { LOGW("Do layer_set_para error! ret:%d", ret); return -1; } if (disp_type == DISP_OUTPUT_TYPE_LCD) { usleep(10 * 1000); LOGI("======= SWITCH LCD ===== "); openHdmi20(2,g_disp_mgr.cur_screen,disp_type,tv_mode); //Just for fox_V7 2.19LCD switch usleep(20 * 1000); } g_disp_mgr.layer[layerinfo.channel][layerinfo.layer_id].config.info.screen_win = layerinfo.info.screen_win; g_disp_mgr.layer[layerinfo.channel][layerinfo.layer_id].config.enable = layerinfo.enable; return 0; } #else int hwd_switch_vo_device(disp_output_type disp_type, disp_tv_mode tv_mode) { int ret = 0; unsigned long args[4] ={0}; disp_output para; disp_layer_config layerinfo; memset(¶, 0, sizeof(disp_output)); memset(&layerinfo, 0, sizeof(disp_layer_config)); /* Check input parameter */ if (g_disp_mgr.disp_fd < 0) { LOGW("The hwd is not Init!"); return -1; } ret = hwd_is_support_tv_mode(disp_type, tv_mode); if (ret < 0) { LOGW("Inout disp_type:%d error!", disp_type); return -1; } else if(ret > 0) { LOGW("This disp_type:%d is not support tv_mode:%d", disp_type, tv_mode); return -1; } args[0] = g_disp_mgr.cur_screen; args[1] = (unsigned long)(¶); ret = ioctl(g_disp_mgr.disp_fd, DISP_GET_OUTPUT, args); if (ret < 0) { LOGW("Do cmd:DISP_GET_OUTPUT error! ret:%d", ret); return ret; } LOGI("Current the disp_type:0x%x tv_mode:0x%x", para.type, para.mode); if (disp_type == para.type) { LOGI("Current the disp_type:%d is not change!", disp_type); return 0; } args[0] = g_disp_mgr.cur_screen; args[1] = disp_type; args[2] = tv_mode; ret = ioctl(g_disp_mgr.disp_fd, DISP_DEVICE_SWITCH, args); if (ret) { LOGW("Do cmd:DISP_DEVICE_SWITCH error! ret:%d, message:%s", ret, strerror(errno)); return ret; } usleep(30 * 1000); int ch, id; layerinfo.channel = 2; layerinfo.layer_id = 0; layerinfo.enable = 1; ret = layer_get_para(&layerinfo); if (ret) { LOGW("Do layer_get_para error! ret:%d", ret); return -1; } switch (disp_type) { case DISP_OUTPUT_TYPE_TV: layerinfo.info.screen_win.x = 0; layerinfo.info.screen_win.y = 0; layerinfo.info.screen_win.width = 720; layerinfo.info.screen_win.height = 576; break; case DISP_OUTPUT_TYPE_LCD: layerinfo.info.screen_win.x = 0; layerinfo.info.screen_win.y = 0; layerinfo.info.screen_win.width = 720; layerinfo.info.screen_win.height = 1280; break; case DISP_OUTPUT_TYPE_HDMI: layerinfo.info.screen_win.x = 0; layerinfo.info.screen_win.y = 0; layerinfo.info.screen_win.width = 1920; layerinfo.info.screen_win.height = 1080; break; default: break; } ret = layer_set_para(&layerinfo); if (ret) { LOGW("Do layer_set_para error! ret:%d", ret); return -1; } g_disp_mgr.layer[layerinfo.channel][layerinfo.layer_id].config.info.screen_win = layerinfo.info.screen_win; g_disp_mgr.layer[layerinfo.channel][layerinfo.layer_id].config.enable = layerinfo.enable; return 0; } #endif #if 0 int layer_cmd2(int screen, unsigned int hlay) { return 0; } int layer_cmd(unsigned int hlay) //finish { return layer_cmd2(g_disp_mgr.cur_screen, hlay); } int layer_request(int *pCh, int *pId) //finish { LOGD(""); int ch; int id; pthread_mutex_lock(&g_disp_mgr.mlock); for(id=0; idx; config.info.screen_win.y = surface->y; config.info.screen_win.width = surface->w; config.info.screen_win.height = surface->h; config.info.mode = LAYER_MODE_BUFFER; config.info.alpha_mode = 0; config.info.alpha_value = 128; config.info.fb.flags = DISP_BF_NORMAL; config.info.fb.scan = DISP_SCAN_PROGRESSIVE; config.info.fb.color_space = (surface->h<720)?DISP_BT601:DISP_BT709; config.info.zorder = HLAY(ch, id); LOGI("hlay:%d, zorder=%d, cnt:%d", hlay, config.info.zorder, g_disp_mgr.req_layer_cnt); layer_set_para(&config); g_disp_mgr.layer[ch][id].config = config; return hlay; } int hw_layer_request(unsigned char channel_id, unsigned char layer_id, unsigned char zorder, struct view_info *surface) { int hlay; disp_layer_config config; memset(&config, 0, sizeof(disp_layer_config)); if (g_disp_mgr.layer[channel_id][layer_id].req_stat & HWD_STATUS_REQUESTED) { LOGE("channel id: %d, layer id: %d has been requested", channel_id, layer_id); return -1; } config.channel = channel_id; config.layer_id = layer_id; config.enable = 0; config.info.screen_win.x = surface->x; config.info.screen_win.y = surface->y; config.info.screen_win.width = surface->w; config.info.screen_win.height = surface->h; config.info.mode = LAYER_MODE_BUFFER; config.info.alpha_mode = 0; config.info.alpha_value = 128; config.info.fb.flags = DISP_BF_NORMAL; config.info.fb.scan = DISP_SCAN_PROGRESSIVE; config.info.fb.color_space = (surface->h<720)?DISP_BT601:DISP_BT709; config.info.zorder = zorder; layer_set_para(&config); g_disp_mgr.req_layer_cnt++; g_disp_mgr.layer[channel_id][layer_id].req_stat |= HWD_STATUS_REQUESTED; g_disp_mgr.layer[channel_id][layer_id].config = config; hlay = HLAY(channel_id, layer_id); LOGI("hlay:%d, zorder=%d, cnt:%d", hlay, config.info.zorder, g_disp_mgr.req_layer_cnt); return hlay; } int layer_request_v40(int *pCh, int *pId, int ui_video) //finish { LOGD("(%s %d)", __FUNCTION__, __LINE__); int ch = 0; int id = 0; if(ui_video == 0)//for ui { pthread_mutex_lock(&g_disp_mgr.mlock); for(id=0; idx; config.info.screen_win.y = surface->y; config.info.screen_win.width = surface->w; config.info.screen_win.height = surface->h; config.info.mode = LAYER_MODE_BUFFER; config.info.alpha_mode = 0; config.info.alpha_value = 128; config.info.fb.flags = DISP_BF_NORMAL; config.info.fb.scan = DISP_SCAN_PROGRESSIVE; config.info.fb.color_space = (surface->h<720)?DISP_BT601:DISP_BT709; config.info.zorder = HLAY(ch, id); LOGI("hlay:%d, zorder=%d, cnt:%d", hlay, config.info.zorder, g_disp_mgr.req_layer_cnt); layer_set_para(&config); g_disp_mgr.layer[ch][id].config = config; return hlay; } #endif