int construct_block_layer_info_offline(uint32_t input_startpos, uint32_t input_width, dss_rect_t src_rect, dss_layer_t *layer_cut_block) { dss_rect_t rect_trsform = {0}; switch (layer_cut_block->transform) { case HISI_FB_TRANSFORM_NOP: case HISI_FB_TRANSFORM_FLIP_V: rect_trsform.x = src_rect.x + input_startpos; rect_trsform.y = src_rect.y; rect_trsform.w = input_width; rect_trsform.h = src_rect.h; break; case HISI_FB_TRANSFORM_FLIP_H: case HISI_FB_TRANSFORM_ROT_180: rect_trsform.x = src_rect.x + src_rect.w - input_startpos - input_width; rect_trsform.y = src_rect.y; rect_trsform.w = input_width; rect_trsform.h = src_rect.h; break; case HISI_FB_TRANSFORM_ROT_90: case HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_H: rect_trsform.x = src_rect.x; rect_trsform.y = src_rect.y + src_rect.h - input_startpos - input_width; rect_trsform.w = src_rect.w; rect_trsform.h = input_width; break; case HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_V: case HISI_FB_TRANSFORM_ROT_270: rect_trsform.x = src_rect.x; rect_trsform.y = src_rect.y + input_startpos; rect_trsform.w = src_rect.w; rect_trsform.h = input_width; break; default: HISI_BA_ERR("unknow dss_layer->transform: %d\n",layer_cut_block->transform); return 1; } /* modify src_rect_mask */ rect_across_rect(rect_trsform, layer_cut_block->src_rect_mask, &layer_cut_block->src_rect_mask); /* modify src */ //layer_cut_block->src.width = rect_trsform.w; //layer_cut_block->src.height = rect_trsform.h; /* modify src_rect */ memcpy(&layer_cut_block->src_rect, &rect_trsform, sizeof(rect_trsform)); return 0; }
int get_block_layers(dss_overlay_t *dss_overlay, dss_rect_t block_rect, dss_overlay_t *dss_overlay_block) { uint32_t i; int status = 0; int block_layer_num = 0; int FirstTile = 0; int LastTile = 0; int layer_index = 0; int input_startpos = 0; int input_endpos = 0; int is_dpe2 = 0; block_cfg_t b_cfg; block_detail_t b_detail; uint32_t output_startpos; /* relative to overlay plane */ uint32_t output_span; dss_layer_t *dss_layer = NULL; dss_rect_t dst_cross_rect; uint32_t src_layer_span; uint32_t acc_hscl = 0; /* if layer has no vertical scf, then horizontal scf input can larger than scf_line_buf */ int scf_linebuf_vertic_check = 1; if (!dss_overlay_block || !block_rect.w || !block_rect.h) { HISI_BA_ERR("invaild args\n"); return -1; } if (!block_algorithm_need(dss_overlay)) { /* must all layer in the block_rect*/ memcpy(dss_overlay_block, dss_overlay, sizeof(dss_overlay_t)); return 0; } /* do some init */ memcpy(&dss_overlay_block->wb_layer_info, &dss_overlay->wb_layer_info, sizeof(dss_wb_layer_t)); dss_overlay_block->layer_nums = 0; //dss_overlay_block->mmu_enable = dss_overlay->mmu_enable; for (i = 0; i < dss_overlay->layer_nums; i++) { dss_layer = &dss_overlay->layer_infos[i]; block_layer_num = dss_overlay_block->layer_nums; status = rect_across_rect(dss_layer->dst_rect, block_rect, &dst_cross_rect); if (status == 0) continue; output_startpos = dst_cross_rect.x - dss_layer->dst_rect.x; output_span = dst_cross_rect.w; if ((output_span < SCF_MIN_OUTPUT) && (dss_layer->need_cap & CAP_SCL)) { HISI_BA_ERR("block layer[%d] scf output smaller than SCF_MIN_OUTPUT, dump some info\ dss_layer dst{%d,%d,%d,%d} block_rect{%d,%d,%d,%d}\n", dss_layer->chn_idx, dss_layer->dst_rect.x,dss_layer->dst_rect.y, dss_layer->dst_rect.w,dss_layer->dst_rect.h, block_rect.x,block_rect.y, block_rect.w,block_rect.h); return -2; } FirstTile = (dss_layer->dst_rect.x >= block_rect.x) ? 1 : 0; LastTile = (block_rect.x + block_rect.w > dss_layer->dst_rect.x + dss_layer->dst_rect.w) ? 1 : 0; memcpy(&dss_overlay_block->layer_infos[block_layer_num], dss_layer, sizeof(dss_layer_t)); dss_overlay_block->layer_nums++; dss_overlay_block->layer_infos[block_layer_num].block_info.first_tile = FirstTile; dss_overlay_block->layer_infos[block_layer_num].block_info.last_tile = LastTile; memcpy(&dss_overlay_block->layer_infos[block_layer_num].dst_rect, &dst_cross_rect, sizeof(dss_rect_t)); dss_overlay_block->layer_infos[block_layer_num].layer_idx = layer_index++; init_block_cfg(&b_detail); if (dss_layer->need_cap & CAP_SCL) { construt_block_info(dss_layer, &b_cfg, &b_detail); if (dss_layer->need_cap & CAP_ROT) { src_layer_span = dss_layer->src_rect.h; scf_linebuf_vertic_check = !(dss_layer->src_rect.w == dss_layer->dst_rect.h); } else { src_layer_span = dss_layer->src_rect.w; scf_linebuf_vertic_check = !(dss_layer->src_rect.h == dss_layer->dst_rect.h); } is_dpe2 = (dss_layer->chn_idx <= DPE2_CHN3) ? 1 : 0; if (GeomInputPlane_offline(FirstTile, LastTile, b_cfg, b_detail.inc_hscl, output_startpos, output_span, 0, src_layer_span, is_dpe2, scf_linebuf_vertic_check, &acc_hscl, &input_startpos, &input_endpos) != 0) return -3; dss_overlay_block->layer_infos[block_layer_num].block_info.acc_hscl = acc_hscl; } else { input_startpos = output_startpos; input_endpos = output_startpos + output_span - 1; } dss_overlay_block->layer_infos[block_layer_num].block_info.h_v_order = b_detail.h_v_order; dss_overlay_block->layer_infos[block_layer_num].block_info.h_ratio = b_detail.inc_hscl; dss_overlay_block->layer_infos[block_layer_num].block_info.v_ratio = b_detail.inc_vscl; construct_block_layer_info_offline(input_startpos, input_endpos - input_startpos + 1, dss_layer->src_rect, &dss_overlay_block->layer_infos[block_layer_num]); }
int k3_ov_offline_play(struct k3_fb_data_type *k3fd, unsigned long *argp) { char __iomem *dss_base = NULL; dss_overlay_t *pov_req = NULL; dss_layer_t *layer = NULL; dss_wb_layer_t *wb_layer = NULL; int i = 0; int k = 0; int ret = 0; struct fb_info *fbi = NULL; int block_num = 0; dss_rect_t wb_block_rect; struct timeval tv; u32 flag; u32 wbe_chn = 0; bool first_valid_block = true; BUG_ON(k3fd == NULL); fbi = k3fd->fbi; BUG_ON(fbi == NULL); pov_req = &(k3fd->ov_req); BUG_ON(pov_req == NULL); dss_base = k3fd->dss_base; do_gettimeofday(&tv); flag = tv.tv_usec; /*lock for k3fd data*/ down(&k3fd->ov_wb_sem); ret = copy_from_user(pov_req, argp, sizeof(dss_overlay_t)); if (ret) { K3_FB_ERR("copy_from_user failed!\n"); goto err_nodump; } wb_layer = &(k3fd->ov_req.wb_layer_info); wbe_chn = wb_layer->chn_idx - WBE1_CHN0; if(wbe_chn >= K3_DSS_OFFLINE_MAX_NUM){ K3_FB_ERR("write back chn:%d not surport!\n",wb_layer->chn_idx); goto err_nodump; } if (fbi->fbops->fb_blank) fbi->fbops->fb_blank(FB_BLANK_UNBLANK, fbi); /*in case of single channel fail.*/ if (k3fd->offline_wb_status[wbe_chn] == e_status_idle) { cmdlist_config_start(k3fd, wbe_chn); k3fd->offline_wb_status[wbe_chn] = e_status_wait; } ret = get_block_rect(pov_req, (wb_layer->dst_rect.x + wb_layer->dst_rect.w), (wb_layer->dst_rect.y + wb_layer->dst_rect.h), &block_num, k3fd->block_rects); if ((ret != 0) || (block_num == 0)|| block_num >= K3_DSS_OFFLINE_MAX_BLOCK) { K3_FB_ERR("get_block_rect failed! ret = %d, block_num[%d]\n", ret, block_num); goto err_return; } for (k = 0; k < block_num; k++) { ret = get_block_layers(pov_req, *k3fd->block_rects[k], k3fd->block_overlay); if (ret != 0) { K3_FB_ERR("get_block_layers err ret = %d\n", ret); goto err_return; } ret = rect_across_rect(*k3fd->block_rects[k], wb_layer->src_rect, &wb_block_rect); if (ret == 0) { K3_FB_ERR("no cross! block_rects[%d]{%d %d %d %d}, wb src_rect{%d %d %d %d}\n", k, k3fd->block_rects[k]->x, k3fd->block_rects[k]->y, k3fd->block_rects[k]->w, k3fd->block_rects[k]->h, wb_layer->src_rect.x, wb_layer->src_rect.y, wb_layer->src_rect.w, wb_layer->src_rect.h); continue; } if (true == first_valid_block) { ret = k3_dss_module_init(k3fd); if (ret != 0) { K3_FB_ERR("k3_dss_module_init failed! ret = %d\n", ret); goto err_return; } } if(g_debug_ovl_offline_cmdlist - 1 == k){ ret = cmdlist_add_new_list(k3fd, &k3fd->offline_cmdlist_head[wbe_chn], TRUE, flag); }else{ ret = cmdlist_add_new_list(k3fd, &k3fd->offline_cmdlist_head[wbe_chn], FALSE, flag); } if(ret != 0){ K3_FB_ERR("cmdlist_add_new_list err:%d \n",ret); return ret; } if (true == first_valid_block) { offline_stop_glb(k3fd, wbe_chn); k3_dss_scf_coef_load(k3fd); first_valid_block = false; } k3_adp_offline_start_disable(k3fd, pov_req); if (g_debug_ovl_offline_composer == 1) { K3_FB_INFO("dump block_overlay:\n"); K3_FB_INFO("{%d %d %d %d} cross {%d %d %d %d} = {%d %d %d %d}\n", k3fd->block_rects[k]->x, k3fd->block_rects[k]->y, k3fd->block_rects[k]->w, k3fd->block_rects[k]->h, wb_layer->src_rect.x, wb_layer->src_rect.y, wb_layer->src_rect.w, wb_layer->src_rect.h, wb_block_rect.x, wb_block_rect.y, wb_block_rect.w, wb_block_rect.h); } k3_dss_handle_cur_ovl_req(k3fd, k3fd->block_overlay); k3_dss_handle_cur_ovl_req_wb(k3fd, k3fd->block_overlay); ret = k3_dss_ovl_base_config(k3fd, &wb_block_rect, k3fd->ov_req.ovl_flags); if (ret != 0) { K3_FB_ERR("k3_dss_ovl_init failed! ret = %d\n", ret); goto err_return; } ret = k3_dss_rdma_bridge_config(k3fd, k3fd->block_overlay); if (ret != 0) { K3_FB_ERR("k3_dss_rdma_bridge_config failed! ret = %d\n", ret); goto err_return; } /* Go through all layers */ for (i = 0; i < k3fd->block_overlay->layer_nums; i++) { layer = &k3fd->block_overlay->layer_infos[i]; ret = k3_dss_offline_one_layer_config(k3fd, layer, &wb_block_rect); if (ret != 0) { K3_FB_ERR("k3_dss_offline_one_layer_config failed, ret = %d\n", ret); goto err_return; } } ret = k3_dss_write_back_config(k3fd, wb_layer, &wb_block_rect); if (ret != 0) { K3_FB_ERR("k3_dss_offline_one_layer_config failed, ret = %d\n", ret); goto err_return; } ret = k3_dss_module_config(k3fd); if (ret != 0) { K3_FB_ERR("k3_dss_module_config failed! ret = %d\n", ret); goto err_return; } k3_adp_offline_start_enable(k3fd, k3fd->block_overlay); if (k < (block_num - 1)) { ret = k3_dss_module_init(k3fd); if (ret != 0) { K3_FB_ERR("k3_dss_module_init failed! ret = %d\n", ret); goto err_return; } k3_dss_handle_prev_ovl_req(k3fd, k3fd->block_overlay); k3_dss_handle_prev_ovl_req_wb(k3fd, k3fd->block_overlay); } } ret = offline_add_pending_frame(k3fd, wbe_chn, flag); if (ret != 0) { K3_FB_ERR("offline_add_virtual_frame failed! ret = %d\n", ret); goto err_return; } cmdlist_frame_valid(&k3fd->offline_cmdlist_head[wbe_chn]); cmdlist_add_nop_list(k3fd, &k3fd->offline_cmdlist_head[wbe_chn], FALSE); #ifdef CONFIG_BUF_SYNC_USED for (i = 0; i < pov_req->layer_nums; i++) { if (pov_req->layer_infos[i].acquire_fence >= 0){ k3fb_buf_sync_wait(pov_req->layer_infos[i].acquire_fence); } } #endif //flush cache before start frame cmdlist_flush_cmdlistmemory_cache(&k3fd->offline_cmdlist_head[wbe_chn], k3fd->ion_client); cmdlist_start_frame(k3fd, wbe_chn); /*unlock for k3fd data*/ up(&k3fd->ov_wb_sem); /*lock if use dpe3 chn0 and chn1*/ offline_chn_lock(k3fd); ret = wait_event_interruptible_timeout(k3fd->offline_writeback_wq[wbe_chn], (k3fd->offline_wb_done[wbe_chn] == flag), msecs_to_jiffies(OFFLINE_COMPOSE_TIMEOUT)); /*unlock if use dpe3 chn0 and chn1*/ offline_chn_unlock(k3fd); /*lock for k3fd data*/ down(&k3fd->ov_wb_sem); cmdlist_prepare_next_frame(k3fd, wbe_chn); cmdlist_free_nop(&k3fd->offline_cmdlist_head[wbe_chn], k3fd->ion_client); if (ret <= 0) { ret = -ETIMEDOUT; if(g_debug_ovl_offline_composer > 0) offline_dump_fail_reg(dss_base, pov_req, tv.tv_sec); offline_fail_proccess(k3fd, wbe_chn, block_num); goto err_return; } ret = 0; err_return: if (ret != 0 && g_debug_ovl_offline_composer > 0) { do_gettimeofday(&tv); offline_dump_fail_info_to_file(pov_req, tv.tv_sec); } err_nodump: cmdlist_free_frame(&k3fd->offline_cmdlist_head[wbe_chn], k3fd->ion_client); k3_dss_rptb_handler(k3fd, false, wbe_chn); k3_dss_rptb_handler(k3fd, true, wbe_chn); if(g_debug_ovl_offline_composer == 3) { do_gettimeofday(&tv); offline_dump_fail_info_to_file(pov_req, tv.tv_sec); g_debug_ovl_offline_composer = 0; } if(first_valid_block == false) k3_dss_scf_coef_unload(k3fd); if ((k3fd->offline_wb_status[0] <= e_status_wait) && (k3fd->offline_wb_status[1] <= e_status_wait) && fbi->fbops->fb_blank && !g_debug_dss_adp_sr) { fbi->fbops->fb_blank(FB_BLANK_POWERDOWN, fbi); } /*unlock for k3fd data*/ up(&k3fd->ov_wb_sem); if(g_debug_ovl_offline_composer == 2) { struct timeval tv_last; u32 use_time = 0; do_gettimeofday(&tv_last); use_time = (tv_last.tv_sec - tv.tv_sec) * 1000 + (tv_last.tv_usec - tv.tv_usec) /1000; printk("--use:%d ms \n",use_time); } return ret; }