int fimc_is_dvfs_sel_static(struct fimc_is_device_ischain *device) { struct fimc_is_core *core; struct fimc_is_dvfs_ctrl *dvfs_ctrl; struct fimc_is_dvfs_scenario_ctrl *static_ctrl; struct fimc_is_dvfs_scenario *scenarios; struct fimc_is_resourcemgr *resourcemgr; int i, scenario_id, scenario_cnt; BUG_ON(!device); BUG_ON(!device->interface); core = (struct fimc_is_core *)device->interface->core; resourcemgr = device->resourcemgr; dvfs_ctrl = &(resourcemgr->dvfs_ctrl); static_ctrl = dvfs_ctrl->static_ctrl; /* static scenario */ if (!static_ctrl) { err("static_dvfs_ctrl is NULL\n"); return -EINVAL; } if (static_ctrl->scenario_cnt == 0) { pr_debug("static_scenario's count is zero\n"); return -EINVAL; } scenarios = static_ctrl->scenarios; scenario_cnt = static_ctrl->scenario_cnt; for (i = 0; i < scenario_cnt; i++) { if (!scenarios[i].check_func) { warn("check_func[%d] is NULL\n", i); continue; } if ((scenarios[i].check_func(device)) > 0) { scenario_id = scenarios[i].scenario_id; static_ctrl->cur_scenario_id = scenario_id; static_ctrl->cur_scenario_idx = i; static_ctrl->cur_frame_tick = scenarios[i].keep_frame_tick; return scenario_id; } } warn("couldn't find static dvfs scenario [sensor:(%d/%d)/fps:%d/setfile:%d/scp size:(%d/%d)]\n", fimc_is_get_open_sensor_cnt(core), device->sensor->pdev->id, fimc_is_sensor_g_framerate(device->sensor), (device->setfile & FIMC_IS_SETFILE_MASK), device->scp.output.width, device->scp.output.height); static_ctrl->cur_scenario_id = FIMC_IS_SN_DEFAULT; static_ctrl->cur_scenario_idx = -1; static_ctrl->cur_frame_tick = -1; return FIMC_IS_SN_DEFAULT; }
int fimc_is_dvfs_sel_dynamic(struct fimc_is_device_ischain *device) { struct fimc_is_dvfs_ctrl *dvfs_ctrl; struct fimc_is_dvfs_scenario_ctrl *dynamic_ctrl; struct fimc_is_dvfs_scenario *scenarios; struct fimc_is_resourcemgr *resourcemgr; int i, scenario_id, scenario_cnt; int position, resol, fps; BUG_ON(!device); resourcemgr = device->resourcemgr; dvfs_ctrl = &(resourcemgr->dvfs_ctrl); dynamic_ctrl = dvfs_ctrl->dynamic_ctrl; if (!test_bit(FIMC_IS_DVFS_SEL_TABLE, &dvfs_ctrl->state)) { err("dvfs table is NOT selected"); return -EINVAL; } /* dynamic scenario */ if (!dynamic_ctrl) { err("dynamic_dvfs_ctrl is NULL"); return -EINVAL; } if (dynamic_ctrl->scenario_cnt == 0) { pr_debug("dynamic_scenario's count is zero"); return -EINVAL; } scenarios = dynamic_ctrl->scenarios; scenario_cnt = dynamic_ctrl->scenario_cnt; if (dynamic_ctrl->cur_frame_tick >= 0) { (dynamic_ctrl->cur_frame_tick)--; /* * when cur_frame_tick is lower than 0, clear current scenario. * This means that current frame tick to keep dynamic scenario * was expired. */ if (dynamic_ctrl->cur_frame_tick < 0) { dynamic_ctrl->cur_scenario_id = -1; dynamic_ctrl->cur_scenario_idx = -1; } } if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state)) return -EAGAIN; position = fimc_is_sensor_g_postion(device->sensor); resol = fimc_is_get_target_resol(device); fps = fimc_is_sensor_g_framerate(device->sensor); for (i = 0; i < scenario_cnt; i++) { if (!scenarios[i].check_func) { warn("check_func[%d] is NULL\n", i); continue; } if ((scenarios[i].check_func(device, position, resol, fps, 0)) > 0) { scenario_id = scenarios[i].scenario_id; dynamic_ctrl->cur_scenario_id = scenario_id; dynamic_ctrl->cur_scenario_idx = i; dynamic_ctrl->cur_frame_tick = scenarios[i].keep_frame_tick; return scenario_id; } } return -EAGAIN; }
int fimc_is_dvfs_sel_static(struct fimc_is_device_ischain *device) { struct fimc_is_core *core; struct fimc_is_dvfs_ctrl *dvfs_ctrl; struct fimc_is_dvfs_scenario_ctrl *static_ctrl; struct fimc_is_dvfs_scenario *scenarios; struct fimc_is_resourcemgr *resourcemgr; int i, scenario_id, scenario_cnt; int position, resol, fps, stream_cnt; BUG_ON(!device); BUG_ON(!device->interface); core = (struct fimc_is_core *)device->interface->core; resourcemgr = device->resourcemgr; dvfs_ctrl = &(resourcemgr->dvfs_ctrl); static_ctrl = dvfs_ctrl->static_ctrl; if (!test_bit(FIMC_IS_DVFS_SEL_TABLE, &dvfs_ctrl->state)) { err("dvfs table is NOT selected"); return -EINVAL; } /* static scenario */ if (!static_ctrl) { err("static_dvfs_ctrl is NULL"); return -EINVAL; } if (static_ctrl->scenario_cnt == 0) { pr_debug("static_scenario's count is zero"); return -EINVAL; } scenarios = static_ctrl->scenarios; scenario_cnt = static_ctrl->scenario_cnt; position = fimc_is_sensor_g_postion(device->sensor); resol = fimc_is_get_target_resol(device); fps = fimc_is_sensor_g_framerate(device->sensor); stream_cnt = fimc_is_get_start_sensor_cnt(core); for (i = 0; i < scenario_cnt; i++) { if (!scenarios[i].check_func) { warn("check_func[%d] is NULL\n", i); continue; } if ((scenarios[i].check_func(device, position, resol, fps, stream_cnt)) > 0) { scenario_id = scenarios[i].scenario_id; static_ctrl->cur_scenario_id = scenario_id; static_ctrl->cur_scenario_idx = i; static_ctrl->cur_frame_tick = scenarios[i].keep_frame_tick; return scenario_id; } } warn("couldn't find static dvfs scenario [sensor:(%d/%d)/fps:%d/setfile:%d/resol:(%d)]\n", fimc_is_get_start_sensor_cnt(core), device->sensor->pdev->id, fps, (device->setfile & FIMC_IS_SETFILE_MASK), resol); static_ctrl->cur_scenario_id = FIMC_IS_SN_DEFAULT; static_ctrl->cur_scenario_idx = -1; static_ctrl->cur_frame_tick = -1; return FIMC_IS_SN_DEFAULT; }
int fimc_is_dvfs_sel_scenario(u32 type, struct fimc_is_device_ischain *device, struct fimc_is_frame *frame) { struct fimc_is_dvfs_ctrl *dvfs_ctrl; struct fimc_is_dvfs_scenario_ctrl *static_ctrl, *dynamic_ctrl; struct fimc_is_dvfs_scenario *scenarios; struct fimc_is_dvfs_scenario *cur_scenario; struct fimc_is_resourcemgr *resourcemgr; int i, scenario_id, scenario_cnt; if (device == NULL) { err("device is NULL\n"); return -EINVAL; } resourcemgr = device->resourcemgr; dvfs_ctrl = &(resourcemgr->dvfs_ctrl); static_ctrl = dvfs_ctrl->static_ctrl; dynamic_ctrl = dvfs_ctrl->dynamic_ctrl; if (type == FIMC_IS_DYNAMIC_SN) { /* dynamic scenario */ if (!dynamic_ctrl) { err("dynamic_dvfs_ctrl is NULL\n"); return -EINVAL; } if (dynamic_ctrl->scenario_cnt == 0) { pr_debug("dynamic_scenario's count is jero\n"); return -EINVAL; } scenarios = dynamic_ctrl->scenarios; scenario_cnt = dynamic_ctrl->scenario_cnt; if (dynamic_ctrl->cur_frame_tick >= 0) { (dynamic_ctrl->cur_frame_tick)--; /* * when cur_frame_tick is lower than 0, clear current scenario. * This means that current frame tick to keep dynamic scenario * was expired. */ if (dynamic_ctrl->cur_frame_tick < 0) { dynamic_ctrl->cur_scenario_id = -1; dynamic_ctrl->cur_scenario_idx = -1; } } } else { /* static scenario */ if (!static_ctrl) { err("static_dvfs_ctrl is NULL\n"); return -EINVAL; } if (static_ctrl->scenario_cnt == 0) { pr_debug("static_scenario's count is jero\n"); return -EINVAL; } scenarios = static_ctrl->scenarios; scenario_cnt = static_ctrl->scenario_cnt; } for (i = 0; i < scenario_cnt; i++) { if (!scenarios[i].check_func) { warn("check_func[%d] is NULL\n", i); continue; } if ((scenarios[i].check_func(device, frame)) > 0) { scenario_id = scenarios[i].scenario_id; if (type == FIMC_IS_DYNAMIC_SN) { cur_scenario = &scenarios[dynamic_ctrl->cur_scenario_idx]; /* * if condition 1 or 2 is true * condition 1 : There's no dynamic scenario applied. * condition 2 : Finded scenario's prority was higher than current */ if ((dynamic_ctrl->cur_scenario_id <= 0) || (scenarios[i].priority < (cur_scenario->priority))) { dynamic_ctrl->cur_scenario_id = scenarios[i].scenario_id; dynamic_ctrl->cur_scenario_idx = i; dynamic_ctrl->cur_frame_tick = scenarios[i].keep_frame_tick; } else { /* if finded scenario is same */ if (scenarios[i].priority == (cur_scenario->priority)) dynamic_ctrl->cur_frame_tick = scenarios[i].keep_frame_tick; return -EAGAIN; } } else { static_ctrl->cur_scenario_id = scenario_id; static_ctrl->cur_scenario_idx = i; static_ctrl->cur_frame_tick = scenarios[i].keep_frame_tick; } return scenario_id; } } if (type == FIMC_IS_DYNAMIC_SN) return -EAGAIN; { struct fimc_is_core *core; int sensor_cnt = 0; core = (struct fimc_is_core *)device->interface->core; sensor_cnt = fimc_is_get_open_sensor_cnt(core); warn("couldn't find static dvfs scenario [sensor:(%d/%d)/fps:%d/setfile:%d/scp size:(%d/%d)]\n", sensor_cnt, device->sensor->pdev->id, fimc_is_sensor_g_framerate(device->sensor), (device->setfile & FIMC_IS_SETFILE_MASK), device->chain3_width, device->chain3_height); } static_ctrl->cur_scenario_id = FIMC_IS_SN_DEFAULT; static_ctrl->cur_scenario_idx = -1; static_ctrl->cur_frame_tick = -1; return FIMC_IS_SN_DEFAULT; }
static void monitor_report(void *group_data, void *frame_data) { u32 index, shotindex; u32 fduration, ctime, dtime; u32 temp1, temp2, temp3, temp4, temp; struct fimc_is_monitor *mp; struct fimc_is_device_ischain *device; struct fimc_is_group *group; struct fimc_is_frame *frame; struct fimc_is_time *time; bool valid = true; BUG_ON(!group_data); BUG_ON(!frame_data); group = group_data; device = group->device; time = &group->time; frame = frame_data; mp = frame->mpoint; fduration = (1000000 / fimc_is_sensor_g_framerate(device->sensor)) + MONITOR_TIMEOUT; ctime = 15000; dtime = 15000; /* Q interval */ if (!frame->result && mp[TMM_QUEUE].check && mp[TMM_START].check) { temp1 = fimc_is_get_time(&mp[TMM_QUEUE].time, &mp[TMM_START].time); if (temp1 > fduration) { mgrinfo("[TIM] Q(%dus > %dus)\n", device, group, frame, temp1, fduration); } } else { valid = false; } /* Callback interval */ if (!frame->result && mp[TMM_SCALL].check && mp[TMM_ECALL].check) { temp2 = fimc_is_get_time(&mp[TMM_SCALL].time, &mp[TMM_ECALL].time); if (temp2 > ctime) { mgrinfo("[TIM] C(%dus > %dus)\n", device, group, frame, temp2, ctime); for (index = TMM_SCALL; index < TMM_ECALL; ++index) { temp = fimc_is_get_time(&mp[index].time, &mp[index + 1].time); mgrinfo("[TIM] %02d-%02d(%dus)\n", device, group, frame, index, index + 1, temp); } } } else { valid = false; } /* Shot interval */ if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) { shotindex = TMM_SHOT2; } else { shotindex = TMM_SHOT1; } if (!frame->result && mp[shotindex].check && mp[TMM_SDONE].check) { temp3 = fimc_is_get_time(&mp[shotindex].time, &mp[TMM_SDONE].time); if (temp3 > fduration) { mgrinfo("[TIM] S(%dus > %dus)\n", device, group, frame, temp3, fduration); } } else { valid = false; } /* Deque interval */ if (!frame->result && mp[TMM_SDONE].check && mp[TMM_DEQUE].check) { temp4 = fimc_is_get_time(&mp[TMM_SDONE].time, &mp[TMM_DEQUE].time); if (temp4 > dtime) { mgrinfo("[TIM] D(%dus > %dus)\n", device, group, frame, temp4, dtime); for (index = TMM_SDONE; index < TMM_DEQUE; ++index) { temp = fimc_is_get_time(&mp[index].time, &mp[index + 1].time); mgrinfo("[TIM] %02d-%02d(%dus)\n", device, group, frame, index, index + 1, temp); } } } else { valid = false; } for (index = 0; index < TMM_END; ++index) mp[index].check = false; if (!valid) return; #ifdef MONITOR_REPORT temp1 += temp2; temp2 = temp3; temp3 = temp4; if (!time->time_count) { time->time1_min = temp1; time->time1_max = temp1; time->time2_min = temp2; time->time2_max = temp2; time->time3_min = temp3; time->time3_max = temp3; } else { if (time->time1_min > temp1) time->time1_min = temp1; if (time->time1_max < temp1) time->time1_max = temp1; if (time->time2_min > temp2) time->time2_min = temp2; if (time->time2_max < temp2) time->time2_max = temp2; if (time->time3_min > temp3) time->time3_min = temp3; if (time->time3_max < temp3) time->time3_max = temp3; } time->time1_tot += temp1; time->time2_tot += temp2; time->time3_tot += temp3; time->time4_cur = mp[TMM_QUEUE].time.tv_sec * 1000000 + mp[TMM_QUEUE].time.tv_usec; time->time4_tot += (time->time4_cur - time->time4_old); time->time4_old = time->time4_cur; time->time_count++; if (time->time_count % time->report_period) return; mginfo("[TIM] Q(%05d,%05d,%05d), S(%05d,%05d,%05d), D(%05d,%05d,%05d) : %d(%dfps)\n", device, group, temp1, time->time1_max, time->time1_tot / time->time_count, temp2, time->time2_max, time->time2_tot / time->time_count, temp3, time->time3_max, time->time3_tot / time->time_count, time->time4_tot / time->report_period, (1000000 * time->report_period) / time->time4_tot); time->time_count = 0; time->time1_tot = 0; time->time2_tot = 0; time->time3_tot = 0; time->time4_tot = 0; #endif }
static int fimc_is_ischain_dis_cfg(struct fimc_is_subdev *leader, void *device_data, struct fimc_is_frame *frame, struct fimc_is_crop *incrop, struct fimc_is_crop *otcrop, u32 *lindex, u32 *hindex, u32 *indexes) { int ret = 0; struct fimc_is_group *group; struct fimc_is_queue *queue; struct param_otf_input *otf_input; struct param_otf_output *otf_output; struct param_dma_input *dma_input; struct fimc_is_device_ischain *device; u32 width, height, dis_width, dis_height; int fps; u32 setfile; bool full_bypass; device = (struct fimc_is_device_ischain *)device_data; BUG_ON(!leader); BUG_ON(!device); BUG_ON(!incrop); BUG_ON(!lindex); BUG_ON(!hindex); BUG_ON(!indexes); otf_input = NULL; otf_output = NULL; dma_input = NULL; width = incrop->w; height = incrop->h; dis_width = otcrop->w; dis_height = otcrop->h; group = &device->group_dis; otf_output = NULL; dma_input = NULL; queue = GET_SUBDEV_QUEUE(leader); if (!queue) { merr("queue is NULL", device); ret = -EINVAL; goto p_err; } /* * Full bypass enable condition * 1) 120fps, 240fps * 2) UHD@60fps * 3) DUAL(PIP) */ fps = fimc_is_sensor_g_framerate(device->sensor); setfile = device->setfile; if (fps > 60 || (fps > 30 && ((width * height) >= SIZE_UHD)) || ((setfile & FIMC_IS_SETFILE_MASK) == ISS_SUB_SCENARIO_DUAL_STILL) || ((setfile & FIMC_IS_SETFILE_MASK) == ISS_SUB_SCENARIO_DUAL_VIDEO)) full_bypass = true; else full_bypass = false; /* control setting */ fimc_is_ischain_dis_ctrl(device, frame, lindex, hindex, indexes, full_bypass); otf_input = fimc_is_itf_g_param(device, frame, PARAM_TPU_OTF_INPUT); if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) otf_input->cmd = OTF_INPUT_COMMAND_ENABLE; else otf_input->cmd = OTF_INPUT_COMMAND_DISABLE; otf_input->width = width; otf_input->height = height; otf_input->format = OTF_YUV_FORMAT; *lindex |= LOWBIT_OF(PARAM_TPU_OTF_INPUT); *hindex |= HIGHBIT_OF(PARAM_TPU_OTF_INPUT); (*indexes)++; dma_input = fimc_is_itf_g_param(device, frame, PARAM_TPU_DMA_INPUT); if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) dma_input->cmd = DMA_INPUT_COMMAND_DISABLE; else dma_input->cmd = DMA_INPUT_COMMAND_ENABLE; dma_input->width = width; dma_input->height = height; dma_input->format = DMA_INPUT_FORMAT_YUV422_CHUNKER; *lindex |= LOWBIT_OF(PARAM_TPU_DMA_INPUT); *hindex |= HIGHBIT_OF(PARAM_TPU_DMA_INPUT); (*indexes)++; otf_output = fimc_is_itf_g_param(device, frame, PARAM_TPU_OTF_OUTPUT); otf_output->width = dis_width; otf_output->height = dis_height; otf_output->format = OTF_YUV_FORMAT; *lindex |= LOWBIT_OF(PARAM_TPU_OTF_OUTPUT); *hindex |= HIGHBIT_OF(PARAM_TPU_OTF_OUTPUT); (*indexes)++; leader->input.crop = *incrop; p_err: return ret; }