projects/linux·blob master · refs

144 lines · 3.5 KiB

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
12bool 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
26int 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
35bool 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
43bool iris_fmt_is_8bit(u32 pixelformat)
44{
45 return pixelformat == V4L2_PIX_FMT_NV12 ||
46 pixelformat == V4L2_PIX_FMT_QC08C;
47}
48
49bool iris_fmt_is_10bit(u32 pixelformat)
50{
51 return pixelformat == V4L2_PIX_FMT_P010 ||
52 pixelformat == V4L2_PIX_FMT_QC10C;
53}
54
55void 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
70int 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
88struct 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
104int 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
121int 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
140bool 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}