1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6 #include <linux/pm_runtime.h> 7 #include <media/v4l2-mem2mem.h> 8 9 #include "iris_instance.h" 10 #include "iris_utils.h" 11 12 bool iris_res_is_less_than(u32 width, u32 height, 13 u32 ref_width, u32 ref_height) 14 { 15 u32 num_mbs = NUM_MBS_PER_FRAME(height, width); 16 u32 max_side = max(ref_width, ref_height); 17 18 if (num_mbs < NUM_MBS_PER_FRAME(ref_height, ref_width) && 19 width < max_side && 20 height < max_side) 21 return true; 22 23 return false; 24 } 25 26 int iris_get_mbpf(struct iris_inst *inst) 27 { 28 struct v4l2_format *inp_f = inst->fmt_src; 29 u32 height = max(inp_f->fmt.pix_mp.height, inst->crop.height); 30 u32 width = max(inp_f->fmt.pix_mp.width, inst->crop.width); 31 32 return NUM_MBS_PER_FRAME(height, width); 33 } 34 35 bool iris_split_mode_enabled(struct iris_inst *inst) 36 { 37 return inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_NV12 || 38 inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC08C || 39 inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_P010 || 40 inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC10C; 41 } 42 43 bool iris_fmt_is_8bit(u32 pixelformat) 44 { 45 return pixelformat == V4L2_PIX_FMT_NV12 || 46 pixelformat == V4L2_PIX_FMT_QC08C; 47 } 48 49 bool iris_fmt_is_10bit(u32 pixelformat) 50 { 51 return pixelformat == V4L2_PIX_FMT_P010 || 52 pixelformat == V4L2_PIX_FMT_QC10C; 53 } 54 55 void iris_helper_buffers_done(struct iris_inst *inst, unsigned int type, 56 enum vb2_buffer_state state) 57 { 58 struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx; 59 struct vb2_v4l2_buffer *buf; 60 61 if (V4L2_TYPE_IS_OUTPUT(type)) { 62 while ((buf = v4l2_m2m_src_buf_remove(m2m_ctx))) 63 v4l2_m2m_buf_done(buf, state); 64 } else if (V4L2_TYPE_IS_CAPTURE(type)) { 65 while ((buf = v4l2_m2m_dst_buf_remove(m2m_ctx))) 66 v4l2_m2m_buf_done(buf, state); 67 } 68 } 69 70 int iris_wait_for_session_response(struct iris_inst *inst, bool is_flush) 71 { 72 struct completion *done; 73 int ret; 74 75 done = is_flush ? &inst->flush_completion : &inst->completion; 76 77 mutex_unlock(&inst->lock); 78 ret = wait_for_completion_timeout(done, msecs_to_jiffies(HW_RESPONSE_TIMEOUT_VALUE)); 79 mutex_lock(&inst->lock); 80 if (!ret) { 81 iris_inst_change_state(inst, IRIS_INST_ERROR); 82 return -ETIMEDOUT; 83 } 84 85 return 0; 86 } 87 88 struct iris_inst *iris_get_instance(struct iris_core *core, u32 session_id) 89 { 90 struct iris_inst *inst; 91 92 mutex_lock(&core->lock); 93 list_for_each_entry(inst, &core->instances, list) { 94 if (inst->session_id == session_id) { 95 mutex_unlock(&core->lock); 96 return inst; 97 } 98 } 99 100 mutex_unlock(&core->lock); 101 return NULL; 102 } 103 104 int iris_check_core_mbpf(struct iris_inst *inst) 105 { 106 struct iris_core *core = inst->core; 107 struct iris_inst *instance; 108 u32 total_mbpf = 0; 109 110 mutex_lock(&core->lock); 111 list_for_each_entry(instance, &core->instances, list) 112 total_mbpf += iris_get_mbpf(instance); 113 mutex_unlock(&core->lock); 114 115 if (total_mbpf > core->iris_platform_data->max_core_mbpf) 116 return -ENOMEM; 117 118 return 0; 119 } 120 121 int iris_check_core_mbps(struct iris_inst *inst) 122 { 123 struct iris_core *core = inst->core; 124 struct iris_inst *instance; 125 u32 total_mbps = 0, fps = 0; 126 127 mutex_lock(&core->lock); 128 list_for_each_entry(instance, &core->instances, list) { 129 fps = max(instance->frame_rate, instance->operating_rate); 130 total_mbps += iris_get_mbpf(instance) * fps; 131 } 132 mutex_unlock(&core->lock); 133 134 if (total_mbps > core->iris_platform_data->max_core_mbps) 135 return -ENOMEM; 136 137 return 0; 138 } 139 140 bool is_rotation_90_or_270(struct iris_inst *inst) 141 { 142 return inst->fw_caps[ROTATION].value == 90 || 143 inst->fw_caps[ROTATION].value == 270; 144 } 145