blob: 5938bd33bd1d2a8168a906713d960909c9c94b82 [file] [log] [blame]
Prateek Shrivastava08846ae2018-01-05 16:54:59 +05301/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/jiffies.h>
15#include <linux/sched.h>
16#include <linux/slab.h>
17#include <linux/kernel.h>
18#include <linux/bitops.h>
19#include <soc/qcom/subsystem_restart.h>
20#include <asm/div64.h>
21#include "msm_vidc_common.h"
22#include "vidc_hfi_api.h"
23#include "msm_vidc_debug.h"
24#include "msm_vidc_clocks.h"
25
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -070026#define IS_ALREADY_IN_STATE(__p, __d) (\
27 (__p >= __d)\
28)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080029
30#define V4L2_EVENT_SEQ_CHANGED_SUFFICIENT \
31 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT
32#define V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT \
33 V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT
34#define V4L2_EVENT_RELEASE_BUFFER_REFERENCE \
35 V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -080036#define L_MODE V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080037
Surajit Podder20ceed02018-01-09 21:23:10 +053038#define TRIGGER_SSR_LOCK_RETRIES 5
39
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080040const char *const mpeg_video_vidc_extradata[] = {
41 "Extradata none",
42 "Extradata MB Quantization",
43 "Extradata Interlace Video",
Chinmay Sawarkar2bacf632017-04-13 14:46:43 -070044 "Reserved",
45 "Reserved",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080046 "Extradata timestamp",
47 "Extradata S3D Frame Packing",
48 "Extradata Frame Rate",
49 "Extradata Panscan Window",
50 "Extradata Recovery point SEI",
51 "Extradata Multislice info",
52 "Extradata number of concealed MB",
53 "Extradata metadata filler",
54 "Extradata input crop",
55 "Extradata digital zoom",
56 "Extradata aspect ratio",
57 "Extradata mpeg2 seqdisp",
58 "Extradata stream userdata",
59 "Extradata frame QP",
60 "Extradata frame bits info",
61 "Extradata LTR",
62 "Extradata macroblock metadata",
63 "Extradata VQZip SEI",
64 "Extradata YUV Stats",
65 "Extradata ROI QP",
66 "Extradata output crop",
67 "Extradata display colour SEI",
68 "Extradata light level SEI",
69 "Extradata PQ Info",
70 "Extradata display VUI",
71 "Extradata vpx color space",
Praneeth Paladugua51b2c42017-06-23 12:48:06 -070072 "Extradata UBWC CR stats info",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080073};
74
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080075static void handle_session_error(enum hal_command_response cmd, void *data);
76static void msm_vidc_print_running_insts(struct msm_vidc_core *core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080077
78bool msm_comm_turbo_session(struct msm_vidc_inst *inst)
79{
80 return !!(inst->flags & VIDC_TURBO);
81}
82
83static inline bool is_thumbnail_session(struct msm_vidc_inst *inst)
84{
85 return !!(inst->flags & VIDC_THUMBNAIL);
86}
87
88static inline bool is_low_power_session(struct msm_vidc_inst *inst)
89{
90 return !!(inst->flags & VIDC_LOW_POWER);
91}
92
93static inline bool is_realtime_session(struct msm_vidc_inst *inst)
94{
95 return !!(inst->flags & VIDC_REALTIME);
96}
97
98int msm_comm_g_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl)
99{
100 return v4l2_g_ctrl(&inst->ctrl_handler, ctrl);
101}
102
103int msm_comm_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl)
104{
105 return v4l2_s_ctrl(NULL, &inst->ctrl_handler, ctrl);
106}
107
108int msm_comm_g_ctrl_for_id(struct msm_vidc_inst *inst, int id)
109{
110 int rc = 0;
111 struct v4l2_control ctrl = {
112 .id = id,
113 };
114
115 rc = msm_comm_g_ctrl(inst, &ctrl);
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -0700116 return rc ? rc : ctrl.value;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800117}
118
119static struct v4l2_ctrl **get_super_cluster(struct msm_vidc_inst *inst,
120 int num_ctrls)
121{
122 int c = 0;
123 struct v4l2_ctrl **cluster = kmalloc(sizeof(struct v4l2_ctrl *) *
124 num_ctrls, GFP_KERNEL);
125
Maheshwar Ajja69639bd2017-07-05 17:58:15 -0700126 if (!cluster || !inst) {
127 kfree(cluster);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800128 return NULL;
Maheshwar Ajja69639bd2017-07-05 17:58:15 -0700129 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800130
131 for (c = 0; c < num_ctrls; c++)
132 cluster[c] = inst->ctrls[c];
133
134 return cluster;
135}
136
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800137int msm_comm_hal_to_v4l2(int id, int value)
138{
139 switch (id) {
140 /* H264 */
141 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
142 switch (value) {
143 case HAL_H264_PROFILE_BASELINE:
144 return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
145 case HAL_H264_PROFILE_CONSTRAINED_BASE:
146 return
147 V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE;
148 case HAL_H264_PROFILE_MAIN:
149 return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800150 case HAL_H264_PROFILE_HIGH:
151 return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700152 case HAL_H264_PROFILE_STEREO_HIGH:
153 return V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH;
154 case HAL_H264_PROFILE_MULTIVIEW_HIGH:
155 return V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH;
156 case HAL_H264_PROFILE_CONSTRAINED_HIGH:
157 return V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800158 default:
159 goto unknown_value;
160 }
161 case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
162 switch (value) {
163 case HAL_H264_LEVEL_1:
164 return V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
165 case HAL_H264_LEVEL_1b:
166 return V4L2_MPEG_VIDEO_H264_LEVEL_1B;
167 case HAL_H264_LEVEL_11:
168 return V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
169 case HAL_H264_LEVEL_12:
170 return V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
171 case HAL_H264_LEVEL_13:
172 return V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
173 case HAL_H264_LEVEL_2:
174 return V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
175 case HAL_H264_LEVEL_21:
176 return V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
177 case HAL_H264_LEVEL_22:
178 return V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
179 case HAL_H264_LEVEL_3:
180 return V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
181 case HAL_H264_LEVEL_31:
182 return V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
183 case HAL_H264_LEVEL_32:
184 return V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
185 case HAL_H264_LEVEL_4:
186 return V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
187 case HAL_H264_LEVEL_41:
188 return V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
189 case HAL_H264_LEVEL_42:
190 return V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
191 case HAL_H264_LEVEL_5:
192 return V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
193 case HAL_H264_LEVEL_51:
194 return V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700195 case HAL_H264_LEVEL_52:
196 return V4L2_MPEG_VIDEO_H264_LEVEL_5_2;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800197 default:
198 goto unknown_value;
199 }
200
201 case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
202 switch (value) {
203 case HAL_H264_ENTROPY_CAVLC:
204 return V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
205 case HAL_H264_ENTROPY_CABAC:
206 return V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC;
207 default:
208 goto unknown_value;
209 }
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700210 case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
211 switch (value) {
212 case HAL_HEVC_PROFILE_MAIN:
213 return V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN;
214 case HAL_HEVC_PROFILE_MAIN10:
215 return V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10;
216 case HAL_HEVC_PROFILE_MAIN_STILL_PIC:
217 return V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC;
218 default:
219 goto unknown_value;
220 }
221 case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
222 switch (value) {
223 case HAL_HEVC_MAIN_TIER_LEVEL_1:
224 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1;
225 case HAL_HEVC_MAIN_TIER_LEVEL_2:
226 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2;
227 case HAL_HEVC_MAIN_TIER_LEVEL_2_1:
228 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1;
229 case HAL_HEVC_MAIN_TIER_LEVEL_3:
230 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3;
231 case HAL_HEVC_MAIN_TIER_LEVEL_3_1:
232 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1;
233 case HAL_HEVC_MAIN_TIER_LEVEL_4:
234 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4;
235 case HAL_HEVC_MAIN_TIER_LEVEL_4_1:
236 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1;
237 case HAL_HEVC_MAIN_TIER_LEVEL_5:
238 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5;
239 case HAL_HEVC_MAIN_TIER_LEVEL_5_1:
240 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1;
241 case HAL_HEVC_MAIN_TIER_LEVEL_5_2:
242 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2;
243 case HAL_HEVC_MAIN_TIER_LEVEL_6:
244 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6;
245 case HAL_HEVC_MAIN_TIER_LEVEL_6_1:
246 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1;
247 case HAL_HEVC_MAIN_TIER_LEVEL_6_2:
248 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_2;
249 case HAL_HEVC_HIGH_TIER_LEVEL_1:
250 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1;
251 case HAL_HEVC_HIGH_TIER_LEVEL_2:
252 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2;
253 case HAL_HEVC_HIGH_TIER_LEVEL_2_1:
254 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1;
255 case HAL_HEVC_HIGH_TIER_LEVEL_3:
256 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3;
257 case HAL_HEVC_HIGH_TIER_LEVEL_3_1:
258 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1;
259 case HAL_HEVC_HIGH_TIER_LEVEL_4:
260 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4;
261 case HAL_HEVC_HIGH_TIER_LEVEL_4_1:
262 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1;
263 case HAL_HEVC_HIGH_TIER_LEVEL_5:
264 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5;
265 case HAL_HEVC_HIGH_TIER_LEVEL_5_1:
266 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1;
267 case HAL_HEVC_HIGH_TIER_LEVEL_5_2:
268 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2;
269 case HAL_HEVC_HIGH_TIER_LEVEL_6:
270 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6;
271 case HAL_HEVC_HIGH_TIER_LEVEL_6_1:
272 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1;
273 case HAL_HEVC_HIGH_TIER_LEVEL_6_2:
274 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_2;
275 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_UNKNOWN:
276 return HAL_HEVC_TIER_LEVEL_UNKNOWN;
277 default:
278 goto unknown_value;
279 }
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800280 case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700281 switch (value) {
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700282 case HAL_VP8_LEVEL_VERSION_0:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700283 return V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0;
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700284 case HAL_VP8_LEVEL_VERSION_1:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700285 return V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1;
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700286 case HAL_VP8_LEVEL_VERSION_2:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700287 return V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_2;
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700288 case HAL_VP8_LEVEL_VERSION_3:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700289 return V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_3;
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700290 case HAL_VP8_LEVEL_UNUSED:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700291 return V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED;
292 default:
293 goto unknown_value;
294 }
Vaibhav Deshu Venkateshb69518e2017-08-21 12:22:49 -0700295 case V4L2_CID_MPEG_VIDC_VIDEO_VP9_PROFILE:
296 switch (value) {
297 case HAL_VP9_PROFILE_P0:
298 return V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_P0;
299 case HAL_VP9_PROFILE_P2_10:
300 return V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_P2_10;
301 case HAL_VP9_PROFILE_UNUSED:
302 return V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_UNUSED;
303 default:
304 goto unknown_value;
305 }
306 case V4L2_CID_MPEG_VIDC_VIDEO_VP9_LEVEL:
307 switch (value) {
308 case HAL_VP9_LEVEL_1:
309 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_1;
310 case HAL_VP9_LEVEL_11:
311 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_11;
312 case HAL_VP9_LEVEL_2:
313 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_2;
314 case HAL_VP9_LEVEL_21:
315 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_21;
316 case HAL_VP9_LEVEL_3:
317 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_3;
318 case HAL_VP9_LEVEL_31:
319 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_31;
320 case HAL_VP9_LEVEL_4:
321 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_4;
322 case HAL_VP9_LEVEL_41:
323 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_41;
324 case HAL_VP9_LEVEL_5:
325 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_5;
326 case HAL_VP9_LEVEL_51:
327 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_51;
328 case HAL_VP9_LEVEL_UNUSED:
329 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_UNUSED;
330 default:
331 goto unknown_value;
332 }
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800333 case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700334 switch (value) {
335 case HAL_MPEG2_PROFILE_SIMPLE:
336 return V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_SIMPLE;
337 case HAL_MPEG2_PROFILE_MAIN:
338 return V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_MAIN;
339 default:
340 goto unknown_value;
341 }
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800342 case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700343 /* This mapping is not defined properly in V4L2 */
344 switch (value) {
345 case HAL_MPEG2_LEVEL_LL:
346 return V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_0;
347 case HAL_MPEG2_LEVEL_ML:
348 return V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_1;
349 case HAL_MPEG2_LEVEL_HL:
350 return V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_2;
351 default:
352 goto unknown_value;
353 }
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800354 }
355
356unknown_value:
357 dprintk(VIDC_WARN, "Unknown control (%x, %d)\n", id, value);
358 return -EINVAL;
359}
360
361int msm_comm_v4l2_to_hal(int id, int value)
362{
363 switch (id) {
364 /* H264 */
365 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
366 switch (value) {
367 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
368 return HAL_H264_PROFILE_BASELINE;
369 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
370 return HAL_H264_PROFILE_CONSTRAINED_BASE;
371 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
372 return HAL_H264_PROFILE_MAIN;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800373 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
374 return HAL_H264_PROFILE_HIGH;
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700375 case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
376 return HAL_H264_PROFILE_STEREO_HIGH;
377 case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
378 return HAL_H264_PROFILE_MULTIVIEW_HIGH;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800379 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
380 return HAL_H264_PROFILE_CONSTRAINED_HIGH;
381 default:
382 goto unknown_value;
383 }
384 case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
385 switch (value) {
386 case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
387 return HAL_H264_LEVEL_1;
388 case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
389 return HAL_H264_LEVEL_1b;
390 case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
391 return HAL_H264_LEVEL_11;
392 case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
393 return HAL_H264_LEVEL_12;
394 case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
395 return HAL_H264_LEVEL_13;
396 case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
397 return HAL_H264_LEVEL_2;
398 case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
399 return HAL_H264_LEVEL_21;
400 case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
401 return HAL_H264_LEVEL_22;
402 case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
403 return HAL_H264_LEVEL_3;
404 case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
405 return HAL_H264_LEVEL_31;
406 case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
407 return HAL_H264_LEVEL_32;
408 case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
409 return HAL_H264_LEVEL_4;
410 case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
411 return HAL_H264_LEVEL_41;
412 case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
413 return HAL_H264_LEVEL_42;
414 case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
415 return HAL_H264_LEVEL_5;
416 case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
417 return HAL_H264_LEVEL_51;
418 case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
419 return HAL_H264_LEVEL_52;
Vaibhav Deshu Venkatesh234b4dc2017-03-21 16:54:28 -0700420 case V4L2_MPEG_VIDEO_H264_LEVEL_UNKNOWN:
421 return HAL_H264_LEVEL_UNKNOWN;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800422 default:
423 goto unknown_value;
424 }
425 case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
426 switch (value) {
427 case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC:
428 return HAL_H264_ENTROPY_CAVLC;
429 case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
430 return HAL_H264_ENTROPY_CABAC;
431 default:
432 goto unknown_value;
433 }
434 case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL:
435 switch (value) {
436 case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_0:
437 return HAL_H264_CABAC_MODEL_0;
438 case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_1:
439 return HAL_H264_CABAC_MODEL_1;
440 case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_2:
441 return HAL_H264_CABAC_MODEL_2;
442 default:
443 goto unknown_value;
444 }
445 case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
446 switch (value) {
447 case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700448 return HAL_VP8_LEVEL_VERSION_0;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800449 case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700450 return HAL_VP8_LEVEL_VERSION_1;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800451 case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_2:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700452 return HAL_VP8_LEVEL_VERSION_2;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800453 case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_3:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700454 return HAL_VP8_LEVEL_VERSION_3;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800455 case V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700456 return HAL_VP8_LEVEL_UNUSED;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800457 default:
458 goto unknown_value;
459 }
460 case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
461 switch (value) {
462 case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN:
463 return HAL_HEVC_PROFILE_MAIN;
464 case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10:
465 return HAL_HEVC_PROFILE_MAIN10;
466 case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC:
467 return HAL_HEVC_PROFILE_MAIN_STILL_PIC;
468 default:
469 goto unknown_value;
470 }
471 case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
472 switch (value) {
473 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1:
474 return HAL_HEVC_MAIN_TIER_LEVEL_1;
475 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2:
476 return HAL_HEVC_MAIN_TIER_LEVEL_2;
477 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1:
478 return HAL_HEVC_MAIN_TIER_LEVEL_2_1;
479 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3:
480 return HAL_HEVC_MAIN_TIER_LEVEL_3;
481 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1:
482 return HAL_HEVC_MAIN_TIER_LEVEL_3_1;
483 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4:
484 return HAL_HEVC_MAIN_TIER_LEVEL_4;
485 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1:
486 return HAL_HEVC_MAIN_TIER_LEVEL_4_1;
487 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5:
488 return HAL_HEVC_MAIN_TIER_LEVEL_5;
489 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1:
490 return HAL_HEVC_MAIN_TIER_LEVEL_5_1;
491 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2:
492 return HAL_HEVC_MAIN_TIER_LEVEL_5_2;
493 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6:
494 return HAL_HEVC_MAIN_TIER_LEVEL_6;
495 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1:
496 return HAL_HEVC_MAIN_TIER_LEVEL_6_1;
497 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_2:
498 return HAL_HEVC_MAIN_TIER_LEVEL_6_2;
499 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1:
500 return HAL_HEVC_HIGH_TIER_LEVEL_1;
501 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2:
502 return HAL_HEVC_HIGH_TIER_LEVEL_2;
503 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1:
504 return HAL_HEVC_HIGH_TIER_LEVEL_2_1;
505 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3:
506 return HAL_HEVC_HIGH_TIER_LEVEL_3;
507 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1:
508 return HAL_HEVC_HIGH_TIER_LEVEL_3_1;
509 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4:
510 return HAL_HEVC_HIGH_TIER_LEVEL_4;
511 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1:
512 return HAL_HEVC_HIGH_TIER_LEVEL_4_1;
513 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5:
514 return HAL_HEVC_HIGH_TIER_LEVEL_5;
515 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1:
516 return HAL_HEVC_HIGH_TIER_LEVEL_5_1;
517 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2:
518 return HAL_HEVC_HIGH_TIER_LEVEL_5_2;
519 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6:
520 return HAL_HEVC_HIGH_TIER_LEVEL_6;
521 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1:
522 return HAL_HEVC_HIGH_TIER_LEVEL_6_1;
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700523 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_2:
524 return HAL_HEVC_HIGH_TIER_LEVEL_6_2;
Vaibhav Deshu Venkatesh234b4dc2017-03-21 16:54:28 -0700525 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_UNKNOWN:
526 return HAL_HEVC_TIER_LEVEL_UNKNOWN;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800527 default:
528 goto unknown_value;
529 }
Surajit Poddere502daa2017-05-30 19:17:45 +0530530 case V4L2_CID_MPEG_VIDC_VIDEO_TME_PROFILE:
531 switch (value) {
532 case V4L2_MPEG_VIDC_VIDEO_TME_PROFILE_0:
533 return HAL_TME_PROFILE_0;
534 case V4L2_MPEG_VIDC_VIDEO_TME_PROFILE_1:
535 return HAL_TME_PROFILE_1;
536 case V4L2_MPEG_VIDC_VIDEO_TME_PROFILE_2:
537 return HAL_TME_PROFILE_2;
538 case V4L2_MPEG_VIDC_VIDEO_TME_PROFILE_3:
539 return HAL_TME_PROFILE_3;
540 default:
541 goto unknown_value;
542 }
543 case V4L2_CID_MPEG_VIDC_VIDEO_TME_LEVEL:
544 switch (value) {
545 case V4L2_MPEG_VIDC_VIDEO_TME_LEVEL_INTEGER:
546 return HAL_TME_LEVEL_INTEGER;
547 default:
548 goto unknown_value;
549 }
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800550 case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION:
551 switch (value) {
552 case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_NONE:
553 return HAL_ROTATE_NONE;
554 case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90:
555 return HAL_ROTATE_90;
556 case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_180:
557 return HAL_ROTATE_180;
558 case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270:
559 return HAL_ROTATE_270;
560 default:
561 goto unknown_value;
562 }
Chinmay Sawarkar87754272017-09-01 14:50:10 -0700563 case V4L2_CID_MPEG_VIDC_VIDEO_FLIP:
564 switch (value) {
565 case V4L2_CID_MPEG_VIDC_VIDEO_FLIP_NONE:
566 return HAL_FLIP_NONE;
567 case V4L2_CID_MPEG_VIDC_VIDEO_FLIP_HORI:
568 return HAL_FLIP_HORIZONTAL;
569 case V4L2_CID_MPEG_VIDC_VIDEO_FLIP_VERT:
570 return HAL_FLIP_VERTICAL;
571 case V4L2_CID_MPEG_VIDC_VIDEO_FLIP_BOTH:
572 return HAL_FLIP_BOTH;
573 default:
574 goto unknown_value;
575 }
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800576 case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
577 switch (value) {
578 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED:
579 return HAL_H264_DB_MODE_DISABLE;
580 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED:
581 return HAL_H264_DB_MODE_ALL_BOUNDARY;
582 case L_MODE:
583 return HAL_H264_DB_MODE_SKIP_SLICE_BOUNDARY;
584 default:
585 goto unknown_value;
586 }
587 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE:
588 switch (value) {
589 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT:
590 return HAL_IFRAMESIZE_TYPE_DEFAULT;
591 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM:
592 return HAL_IFRAMESIZE_TYPE_MEDIUM;
593 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE:
594 return HAL_IFRAMESIZE_TYPE_HUGE;
595 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED:
596 return HAL_IFRAMESIZE_TYPE_UNLIMITED;
597 default:
598 goto unknown_value;
599 }
600 }
601
602unknown_value:
603 dprintk(VIDC_WARN, "Unknown control (%x, %d)\n", id, value);
604 return -EINVAL;
605}
606
Umesh Pandey92bd41d2017-08-10 14:52:33 -0700607int msm_comm_get_v4l2_profile(int fourcc, int profile)
608{
609 switch (fourcc) {
610 case V4L2_PIX_FMT_H264:
611 return msm_comm_hal_to_v4l2(
612 V4L2_CID_MPEG_VIDEO_H264_PROFILE,
613 profile);
614 case V4L2_PIX_FMT_HEVC:
615 return msm_comm_hal_to_v4l2(
616 V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE,
617 profile);
618 case V4L2_PIX_FMT_VP8:
619 case V4L2_PIX_FMT_VP9:
620 case V4L2_PIX_FMT_MPEG2:
621 return 0;
622 default:
623 dprintk(VIDC_WARN, "Unknown codec id %x\n", fourcc);
624 return 0;
625 }
626}
627
628int msm_comm_get_v4l2_level(int fourcc, int level)
629{
630 switch (fourcc) {
631 case V4L2_PIX_FMT_H264:
632 return msm_comm_hal_to_v4l2(
633 V4L2_CID_MPEG_VIDEO_H264_LEVEL,
634 level);
635 case V4L2_PIX_FMT_HEVC:
636 return msm_comm_hal_to_v4l2(
637 V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL,
638 level);
639 case V4L2_PIX_FMT_VP8:
640 return msm_comm_hal_to_v4l2(
641 V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL,
642 level);
643 case V4L2_PIX_FMT_VP9:
644 case V4L2_PIX_FMT_MPEG2:
645 return 0;
646 default:
647 dprintk(VIDC_WARN, "Unknown codec id %x\n", fourcc);
648 return 0;
649 }
650}
651
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800652int msm_comm_ctrl_init(struct msm_vidc_inst *inst,
653 struct msm_vidc_ctrl *drv_ctrls, u32 num_ctrls,
654 const struct v4l2_ctrl_ops *ctrl_ops)
655{
656 int idx = 0;
657 struct v4l2_ctrl_config ctrl_cfg = {0};
658 int ret_val = 0;
659
660 if (!inst || !drv_ctrls || !ctrl_ops || !num_ctrls) {
661 dprintk(VIDC_ERR, "%s - invalid input\n", __func__);
662 return -EINVAL;
663 }
664
665 inst->ctrls = kcalloc(num_ctrls, sizeof(struct v4l2_ctrl *),
666 GFP_KERNEL);
667 if (!inst->ctrls) {
668 dprintk(VIDC_ERR, "%s - failed to allocate ctrl\n", __func__);
669 return -ENOMEM;
670 }
671
672 ret_val = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls);
673
674 if (ret_val) {
675 dprintk(VIDC_ERR, "CTRL ERR: Control handler init failed, %d\n",
676 inst->ctrl_handler.error);
677 return ret_val;
678 }
679
680 for (; idx < num_ctrls; idx++) {
681 struct v4l2_ctrl *ctrl = NULL;
682
Maheshwar Ajja1f801492017-05-10 16:55:26 -0700683 if (IS_PRIV_CTRL(drv_ctrls[idx].id)) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800684 /*add private control*/
685 ctrl_cfg.def = drv_ctrls[idx].default_value;
686 ctrl_cfg.flags = 0;
687 ctrl_cfg.id = drv_ctrls[idx].id;
688 ctrl_cfg.max = drv_ctrls[idx].maximum;
689 ctrl_cfg.min = drv_ctrls[idx].minimum;
690 ctrl_cfg.menu_skip_mask =
691 drv_ctrls[idx].menu_skip_mask;
692 ctrl_cfg.name = drv_ctrls[idx].name;
693 ctrl_cfg.ops = ctrl_ops;
694 ctrl_cfg.step = drv_ctrls[idx].step;
695 ctrl_cfg.type = drv_ctrls[idx].type;
696 ctrl_cfg.qmenu = drv_ctrls[idx].qmenu;
697
698 ctrl = v4l2_ctrl_new_custom(&inst->ctrl_handler,
699 &ctrl_cfg, NULL);
700 } else {
701 if (drv_ctrls[idx].type == V4L2_CTRL_TYPE_MENU) {
702 ctrl = v4l2_ctrl_new_std_menu(
703 &inst->ctrl_handler,
704 ctrl_ops,
705 drv_ctrls[idx].id,
706 drv_ctrls[idx].maximum,
707 drv_ctrls[idx].menu_skip_mask,
708 drv_ctrls[idx].default_value);
709 } else {
710 ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler,
711 ctrl_ops,
712 drv_ctrls[idx].id,
713 drv_ctrls[idx].minimum,
714 drv_ctrls[idx].maximum,
715 drv_ctrls[idx].step,
716 drv_ctrls[idx].default_value);
717 }
718 }
719
720 if (!ctrl) {
721 dprintk(VIDC_ERR, "%s - invalid ctrl %s\n", __func__,
722 drv_ctrls[idx].name);
723 return -EINVAL;
724 }
725
726 ret_val = inst->ctrl_handler.error;
727 if (ret_val) {
728 dprintk(VIDC_ERR,
729 "Error adding ctrl (%s) to ctrl handle, %d\n",
730 drv_ctrls[idx].name, inst->ctrl_handler.error);
731 return ret_val;
732 }
733
734 ctrl->flags |= drv_ctrls[idx].flags;
735 inst->ctrls[idx] = ctrl;
736 }
737
738 /* Construct a super cluster of all controls */
739 inst->cluster = get_super_cluster(inst, num_ctrls);
740 if (!inst->cluster) {
741 dprintk(VIDC_WARN,
742 "Failed to setup super cluster\n");
743 return -EINVAL;
744 }
745
746 v4l2_ctrl_cluster(num_ctrls, inst->cluster);
747
748 return ret_val;
749}
750
751int msm_comm_ctrl_deinit(struct msm_vidc_inst *inst)
752{
753 if (!inst) {
754 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
755 return -EINVAL;
756 }
757
758 kfree(inst->ctrls);
759 kfree(inst->cluster);
760 v4l2_ctrl_handler_free(&inst->ctrl_handler);
761
762 return 0;
763}
764
765enum multi_stream msm_comm_get_stream_output_mode(struct msm_vidc_inst *inst)
766{
767 switch (msm_comm_g_ctrl_for_id(inst,
768 V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE)) {
769 case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY:
770 return HAL_VIDEO_DECODER_SECONDARY;
771 case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY:
772 default:
773 return HAL_VIDEO_DECODER_PRIMARY;
774 }
775}
776
777static int msm_comm_get_mbs_per_sec(struct msm_vidc_inst *inst)
778{
779 int output_port_mbs, capture_port_mbs;
780 int fps;
781
782 output_port_mbs = inst->in_reconfig ?
783 NUM_MBS_PER_FRAME(inst->reconfig_width,
784 inst->reconfig_height) :
785 NUM_MBS_PER_FRAME(inst->prop.width[OUTPUT_PORT],
786 inst->prop.height[OUTPUT_PORT]);
787
788 capture_port_mbs = NUM_MBS_PER_FRAME(inst->prop.width[CAPTURE_PORT],
789 inst->prop.height[CAPTURE_PORT]);
790
Praneeth Paladugue5fd0872017-04-19 11:24:28 -0700791 if (inst->clk_data.operating_rate) {
792 fps = (inst->clk_data.operating_rate >> 16) ?
793 inst->clk_data.operating_rate >> 16 : 1;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800794 /*
795 * Check if operating rate is less than fps.
796 * If Yes, then use fps to scale clocks
797 */
798 fps = fps > inst->prop.fps ? fps : inst->prop.fps;
799 return max(output_port_mbs, capture_port_mbs) * fps;
800 } else {
801 return max(output_port_mbs, capture_port_mbs) * inst->prop.fps;
802 }
803}
804
805int msm_comm_get_inst_load(struct msm_vidc_inst *inst,
806 enum load_calc_quirks quirks)
807{
808 int load = 0;
809
810 mutex_lock(&inst->lock);
811
812 if (!(inst->state >= MSM_VIDC_OPEN_DONE &&
813 inst->state < MSM_VIDC_STOP_DONE))
814 goto exit;
815
816 load = msm_comm_get_mbs_per_sec(inst);
817
818 if (is_thumbnail_session(inst)) {
819 if (quirks & LOAD_CALC_IGNORE_THUMBNAIL_LOAD)
820 load = 0;
821 }
822
823 if (msm_comm_turbo_session(inst)) {
824 if (!(quirks & LOAD_CALC_IGNORE_TURBO_LOAD))
825 load = inst->core->resources.max_load;
826 }
827
828 /* Clock and Load calculations for REALTIME/NON-REALTIME
829 * OPERATING RATE SET/NO OPERATING RATE SET
830 *
831 * | OPERATING RATE SET | OPERATING RATE NOT SET |
832 * ----------------|--------------------- |------------------------|
833 * REALTIME | load = res * op_rate | load = res * fps |
834 * | clk = res * op_rate | clk = res * fps |
835 * ----------------|----------------------|------------------------|
836 * NON-REALTIME | load = res * 1 fps | load = res * 1 fps |
837 * | clk = res * op_rate | clk = res * fps |
838 * ----------------|----------------------|------------------------|
839 */
840
841 if (!is_realtime_session(inst) &&
842 (quirks & LOAD_CALC_IGNORE_NON_REALTIME_LOAD)) {
843 if (!inst->prop.fps) {
844 dprintk(VIDC_INFO, "instance:%pK fps = 0\n", inst);
845 load = 0;
846 } else {
847 load = msm_comm_get_mbs_per_sec(inst) / inst->prop.fps;
848 }
849 }
850
851exit:
852 mutex_unlock(&inst->lock);
853 return load;
854}
855
Saurabh Kothawade305547e2017-08-14 14:35:21 -0700856int msm_comm_get_inst_load_per_core(struct msm_vidc_inst *inst,
857 enum load_calc_quirks quirks)
858{
859 int load = msm_comm_get_inst_load(inst, quirks);
860
861 if (inst->clk_data.core_id == VIDC_CORE_ID_3)
862 load = load / 2;
863
864 return load;
865}
866
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800867int msm_comm_get_load(struct msm_vidc_core *core,
868 enum session_type type, enum load_calc_quirks quirks)
869{
870 struct msm_vidc_inst *inst = NULL;
871 int num_mbs_per_sec = 0;
872
873 if (!core) {
874 dprintk(VIDC_ERR, "Invalid args: %pK\n", core);
875 return -EINVAL;
876 }
877
878 mutex_lock(&core->lock);
879 list_for_each_entry(inst, &core->instances, list) {
880 if (inst->session_type != type)
881 continue;
882
883 num_mbs_per_sec += msm_comm_get_inst_load(inst, quirks);
884 }
885 mutex_unlock(&core->lock);
886
887 return num_mbs_per_sec;
888}
889
890enum hal_domain get_hal_domain(int session_type)
891{
892 enum hal_domain domain;
893
894 switch (session_type) {
895 case MSM_VIDC_ENCODER:
896 domain = HAL_VIDEO_DOMAIN_ENCODER;
897 break;
898 case MSM_VIDC_DECODER:
899 domain = HAL_VIDEO_DOMAIN_DECODER;
900 break;
901 default:
902 dprintk(VIDC_ERR, "Wrong domain\n");
903 domain = HAL_UNUSED_DOMAIN;
904 break;
905 }
906
907 return domain;
908}
909
910enum hal_video_codec get_hal_codec(int fourcc)
911{
912 enum hal_video_codec codec;
913
914 switch (fourcc) {
915 case V4L2_PIX_FMT_H264:
916 case V4L2_PIX_FMT_H264_NO_SC:
917 codec = HAL_VIDEO_CODEC_H264;
918 break;
919 case V4L2_PIX_FMT_H264_MVC:
920 codec = HAL_VIDEO_CODEC_MVC;
921 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800922 case V4L2_PIX_FMT_MPEG1:
923 codec = HAL_VIDEO_CODEC_MPEG1;
924 break;
925 case V4L2_PIX_FMT_MPEG2:
926 codec = HAL_VIDEO_CODEC_MPEG2;
927 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800928 case V4L2_PIX_FMT_VP8:
929 codec = HAL_VIDEO_CODEC_VP8;
930 break;
931 case V4L2_PIX_FMT_VP9:
932 codec = HAL_VIDEO_CODEC_VP9;
933 break;
934 case V4L2_PIX_FMT_HEVC:
935 codec = HAL_VIDEO_CODEC_HEVC;
936 break;
Surajit Poddere502daa2017-05-30 19:17:45 +0530937 case V4L2_PIX_FMT_TME:
938 codec = HAL_VIDEO_CODEC_TME;
939 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800940 default:
941 dprintk(VIDC_ERR, "Wrong codec: %d\n", fourcc);
942 codec = HAL_UNUSED_CODEC;
943 break;
944 }
945
946 return codec;
947}
948
Praneeth Paladugu319e7922017-03-16 11:09:06 -0700949enum hal_uncompressed_format msm_comm_get_hal_uncompressed(int fourcc)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800950{
951 enum hal_uncompressed_format format = HAL_UNUSED_COLOR;
952
953 switch (fourcc) {
954 case V4L2_PIX_FMT_NV12:
955 format = HAL_COLOR_FORMAT_NV12;
956 break;
957 case V4L2_PIX_FMT_NV21:
958 format = HAL_COLOR_FORMAT_NV21;
959 break;
960 case V4L2_PIX_FMT_NV12_UBWC:
961 format = HAL_COLOR_FORMAT_NV12_UBWC;
962 break;
963 case V4L2_PIX_FMT_NV12_TP10_UBWC:
964 format = HAL_COLOR_FORMAT_NV12_TP10_UBWC;
965 break;
Zhongbo Shie4e1fbc2017-11-20 14:15:45 +0800966 case V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS:
Zhongbo Shi6bd5f5f2017-08-16 17:20:08 +0800967 format = HAL_COLOR_FORMAT_P010;
968 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800969 default:
970 format = HAL_UNUSED_COLOR;
971 break;
972 }
973
974 return format;
975}
976
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800977struct msm_vidc_core *get_vidc_core(int core_id)
978{
979 struct msm_vidc_core *core;
980 int found = 0;
981
982 if (core_id > MSM_VIDC_CORES_MAX) {
983 dprintk(VIDC_ERR, "Core id = %d is greater than max = %d\n",
984 core_id, MSM_VIDC_CORES_MAX);
985 return NULL;
986 }
987 mutex_lock(&vidc_driver->lock);
988 list_for_each_entry(core, &vidc_driver->cores, list) {
989 if (core->id == core_id) {
990 found = 1;
991 break;
992 }
993 }
994 mutex_unlock(&vidc_driver->lock);
995 if (found)
996 return core;
997 return NULL;
998}
999
1000const struct msm_vidc_format *msm_comm_get_pixel_fmt_index(
1001 const struct msm_vidc_format fmt[], int size, int index, int fmt_type)
1002{
1003 int i, k = 0;
1004
1005 if (!fmt || index < 0) {
1006 dprintk(VIDC_ERR, "Invalid inputs, fmt = %pK, index = %d\n",
1007 fmt, index);
1008 return NULL;
1009 }
1010 for (i = 0; i < size; i++) {
1011 if (fmt[i].type != fmt_type)
1012 continue;
1013 if (k == index)
1014 break;
1015 k++;
1016 }
1017 if (i == size) {
1018 dprintk(VIDC_INFO, "Format not found\n");
1019 return NULL;
1020 }
1021 return &fmt[i];
1022}
1023struct msm_vidc_format *msm_comm_get_pixel_fmt_fourcc(
1024 struct msm_vidc_format fmt[], int size, int fourcc, int fmt_type)
1025{
1026 int i;
1027
1028 if (!fmt) {
1029 dprintk(VIDC_ERR, "Invalid inputs, fmt = %pK\n", fmt);
1030 return NULL;
1031 }
1032 for (i = 0; i < size; i++) {
1033 if (fmt[i].fourcc == fourcc)
1034 break;
1035 }
1036 if (i == size) {
1037 dprintk(VIDC_INFO, "Format not found\n");
1038 return NULL;
1039 }
1040 return &fmt[i];
1041}
1042
1043struct buf_queue *msm_comm_get_vb2q(
1044 struct msm_vidc_inst *inst, enum v4l2_buf_type type)
1045{
1046 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1047 return &inst->bufq[CAPTURE_PORT];
1048 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1049 return &inst->bufq[OUTPUT_PORT];
1050 return NULL;
1051}
1052
1053static void handle_sys_init_done(enum hal_command_response cmd, void *data)
1054{
1055 struct msm_vidc_cb_cmd_done *response = data;
1056 struct msm_vidc_core *core;
1057 struct vidc_hal_sys_init_done *sys_init_msg;
1058 u32 index;
1059
1060 if (!IS_HAL_SYS_CMD(cmd)) {
1061 dprintk(VIDC_ERR, "%s - invalid cmd\n", __func__);
1062 return;
1063 }
1064
1065 index = SYS_MSG_INDEX(cmd);
1066
1067 if (!response) {
1068 dprintk(VIDC_ERR,
1069 "Failed to get valid response for sys init\n");
1070 return;
1071 }
1072 core = get_vidc_core(response->device_id);
1073 if (!core) {
1074 dprintk(VIDC_ERR, "Wrong device_id received\n");
1075 return;
1076 }
1077 sys_init_msg = &response->data.sys_init_done;
1078 if (!sys_init_msg) {
1079 dprintk(VIDC_ERR, "sys_init_done message not proper\n");
1080 return;
1081 }
1082
1083 core->enc_codec_supported = sys_init_msg->enc_codec_supported;
1084 core->dec_codec_supported = sys_init_msg->dec_codec_supported;
1085
1086 /* This should come from sys_init_done */
1087 core->resources.max_inst_count =
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -07001088 sys_init_msg->max_sessions_supported ?
Karthikeyan Periasamy4b5e7332017-07-28 12:07:42 -07001089 min_t(u32, sys_init_msg->max_sessions_supported,
1090 MAX_SUPPORTED_INSTANCES) : MAX_SUPPORTED_INSTANCES;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001091
1092 core->resources.max_secure_inst_count =
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -07001093 core->resources.max_secure_inst_count ?
1094 core->resources.max_secure_inst_count :
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001095 core->resources.max_inst_count;
1096
1097 if (core->id == MSM_VIDC_CORE_VENUS &&
1098 (core->dec_codec_supported & HAL_VIDEO_CODEC_H264))
1099 core->dec_codec_supported |=
1100 HAL_VIDEO_CODEC_MVC;
1101
1102 core->codec_count = sys_init_msg->codec_count;
1103 memcpy(core->capabilities, sys_init_msg->capabilities,
1104 sys_init_msg->codec_count * sizeof(struct msm_vidc_capability));
1105
1106 dprintk(VIDC_DBG,
1107 "%s: supported_codecs[%d]: enc = %#x, dec = %#x\n",
1108 __func__, core->codec_count, core->enc_codec_supported,
1109 core->dec_codec_supported);
1110
1111 complete(&(core->completions[index]));
1112}
1113
Maheshwar Ajja69639bd2017-07-05 17:58:15 -07001114static void put_inst_helper(struct kref *kref)
1115{
1116 struct msm_vidc_inst *inst = container_of(kref,
1117 struct msm_vidc_inst, kref);
1118
1119 msm_vidc_destroy(inst);
1120}
1121
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001122static void put_inst(struct msm_vidc_inst *inst)
1123{
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001124 if (!inst)
1125 return;
1126
1127 kref_put(&inst->kref, put_inst_helper);
1128}
1129
1130static struct msm_vidc_inst *get_inst(struct msm_vidc_core *core,
1131 void *session_id)
1132{
1133 struct msm_vidc_inst *inst = NULL;
1134 bool matches = false;
1135
1136 if (!core || !session_id)
1137 return NULL;
1138
1139 mutex_lock(&core->lock);
1140 /*
1141 * This is as good as !list_empty(!inst->list), but at this point
1142 * we don't really know if inst was kfree'd via close syscall before
1143 * hardware could respond. So manually walk thru the list of active
1144 * sessions
1145 */
1146 list_for_each_entry(inst, &core->instances, list) {
1147 if (inst == session_id) {
1148 /*
1149 * Even if the instance is valid, we really shouldn't
1150 * be receiving or handling callbacks when we've deleted
1151 * our session with HFI
1152 */
1153 matches = !!inst->session;
1154 break;
1155 }
1156 }
1157
1158 /*
1159 * kref_* is atomic_int backed, so no need for inst->lock. But we can
1160 * always acquire inst->lock and release it in put_inst for a stronger
1161 * locking system.
1162 */
1163 inst = (matches && kref_get_unless_zero(&inst->kref)) ? inst : NULL;
1164 mutex_unlock(&core->lock);
1165
1166 return inst;
1167}
1168
1169static void handle_session_release_buf_done(enum hal_command_response cmd,
1170 void *data)
1171{
1172 struct msm_vidc_cb_cmd_done *response = data;
1173 struct msm_vidc_inst *inst;
1174 struct internal_buf *buf;
1175 struct list_head *ptr, *next;
1176 struct hal_buffer_info *buffer;
1177 u32 buf_found = false;
1178 u32 address;
1179
1180 if (!response) {
1181 dprintk(VIDC_ERR, "Invalid release_buf_done response\n");
1182 return;
1183 }
1184
1185 inst = get_inst(get_vidc_core(response->device_id),
1186 response->session_id);
1187 if (!inst) {
1188 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1189 return;
1190 }
1191
1192 buffer = &response->data.buffer_info;
1193 address = buffer->buffer_addr;
1194
1195 mutex_lock(&inst->scratchbufs.lock);
1196 list_for_each_safe(ptr, next, &inst->scratchbufs.list) {
1197 buf = list_entry(ptr, struct internal_buf, list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001198 if (address == buf->smem.device_addr) {
1199 dprintk(VIDC_DBG, "releasing scratch: %x\n",
1200 buf->smem.device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001201 buf_found = true;
1202 }
1203 }
1204 mutex_unlock(&inst->scratchbufs.lock);
1205
1206 mutex_lock(&inst->persistbufs.lock);
1207 list_for_each_safe(ptr, next, &inst->persistbufs.list) {
1208 buf = list_entry(ptr, struct internal_buf, list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001209 if (address == buf->smem.device_addr) {
1210 dprintk(VIDC_DBG, "releasing persist: %x\n",
1211 buf->smem.device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001212 buf_found = true;
1213 }
1214 }
1215 mutex_unlock(&inst->persistbufs.lock);
1216
1217 if (!buf_found)
1218 dprintk(VIDC_ERR, "invalid buffer received from firmware");
1219 if (IS_HAL_SESSION_CMD(cmd))
1220 complete(&inst->completions[SESSION_MSG_INDEX(cmd)]);
1221 else
1222 dprintk(VIDC_ERR, "Invalid inst cmd response: %d\n", cmd);
1223
1224 put_inst(inst);
1225}
1226
1227static void handle_sys_release_res_done(
1228 enum hal_command_response cmd, void *data)
1229{
1230 struct msm_vidc_cb_cmd_done *response = data;
1231 struct msm_vidc_core *core;
1232
1233 if (!response) {
1234 dprintk(VIDC_ERR,
1235 "Failed to get valid response for sys init\n");
1236 return;
1237 }
1238 core = get_vidc_core(response->device_id);
1239 if (!core) {
1240 dprintk(VIDC_ERR, "Wrong device_id received\n");
1241 return;
1242 }
1243 complete(&core->completions[
1244 SYS_MSG_INDEX(HAL_SYS_RELEASE_RESOURCE_DONE)]);
1245}
1246
1247static void change_inst_state(struct msm_vidc_inst *inst,
1248 enum instance_state state)
1249{
1250 if (!inst) {
1251 dprintk(VIDC_ERR, "Invalid parameter %s\n", __func__);
1252 return;
1253 }
1254 mutex_lock(&inst->lock);
1255 if (inst->state == MSM_VIDC_CORE_INVALID) {
1256 dprintk(VIDC_DBG,
1257 "Inst: %pK is in bad state can't change state to %d\n",
1258 inst, state);
1259 goto exit;
1260 }
1261 dprintk(VIDC_DBG, "Moved inst: %pK from state: %d to state: %d\n",
1262 inst, inst->state, state);
1263 inst->state = state;
1264exit:
1265 mutex_unlock(&inst->lock);
1266}
1267
1268static int signal_session_msg_receipt(enum hal_command_response cmd,
1269 struct msm_vidc_inst *inst)
1270{
1271 if (!inst) {
1272 dprintk(VIDC_ERR, "Invalid(%pK) instance id\n", inst);
1273 return -EINVAL;
1274 }
1275 if (IS_HAL_SESSION_CMD(cmd)) {
1276 complete(&inst->completions[SESSION_MSG_INDEX(cmd)]);
1277 } else {
1278 dprintk(VIDC_ERR, "Invalid inst cmd response: %d\n", cmd);
1279 return -EINVAL;
1280 }
1281 return 0;
1282}
1283
1284static int wait_for_sess_signal_receipt(struct msm_vidc_inst *inst,
1285 enum hal_command_response cmd)
1286{
1287 int rc = 0;
1288 struct hfi_device *hdev;
1289
1290 if (!IS_HAL_SESSION_CMD(cmd)) {
1291 dprintk(VIDC_ERR, "Invalid inst cmd response: %d\n", cmd);
1292 return -EINVAL;
1293 }
1294 hdev = (struct hfi_device *)(inst->core->device);
1295 rc = wait_for_completion_timeout(
1296 &inst->completions[SESSION_MSG_INDEX(cmd)],
Praneeth Paladugud5bf7bc2017-05-29 23:41:04 -07001297 msecs_to_jiffies(
1298 inst->core->resources.msm_vidc_hw_rsp_timeout));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001299 if (!rc) {
1300 dprintk(VIDC_ERR, "Wait interrupted or timed out: %d\n",
1301 SESSION_MSG_INDEX(cmd));
Surajit Podder878ede02017-02-07 12:20:10 +05301302 msm_comm_kill_session(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001303 rc = -EIO;
1304 } else {
1305 rc = 0;
1306 }
1307 return rc;
1308}
1309
1310static int wait_for_state(struct msm_vidc_inst *inst,
1311 enum instance_state flipped_state,
1312 enum instance_state desired_state,
1313 enum hal_command_response hal_cmd)
1314{
1315 int rc = 0;
1316
1317 if (IS_ALREADY_IN_STATE(flipped_state, desired_state)) {
1318 dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
1319 inst, inst->state);
1320 goto err_same_state;
1321 }
1322 dprintk(VIDC_DBG, "Waiting for hal_cmd: %d\n", hal_cmd);
1323 rc = wait_for_sess_signal_receipt(inst, hal_cmd);
1324 if (!rc)
1325 change_inst_state(inst, desired_state);
1326err_same_state:
1327 return rc;
1328}
1329
1330void msm_vidc_queue_v4l2_event(struct msm_vidc_inst *inst, int event_type)
1331{
1332 struct v4l2_event event = {.id = 0, .type = event_type};
1333
1334 v4l2_event_queue_fh(&inst->event_handler, &event);
1335}
1336
1337static void msm_comm_generate_max_clients_error(struct msm_vidc_inst *inst)
1338{
1339 enum hal_command_response cmd = HAL_SESSION_ERROR;
1340 struct msm_vidc_cb_cmd_done response = {0};
1341
1342 if (!inst) {
1343 dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
1344 return;
1345 }
1346 dprintk(VIDC_ERR, "%s: Too many clients\n", __func__);
1347 response.session_id = inst;
1348 response.status = VIDC_ERR_MAX_CLIENTS;
1349 handle_session_error(cmd, (void *)&response);
1350}
1351
1352static void print_cap(const char *type,
1353 struct hal_capability_supported *cap)
1354{
1355 dprintk(VIDC_DBG,
1356 "%-24s: %-8d %-8d %-8d\n",
1357 type, cap->min, cap->max, cap->step_size);
1358}
1359
Praneeth Paladugue1679112017-01-27 10:07:15 -08001360static int msm_vidc_comm_update_ctrl(struct msm_vidc_inst *inst,
1361 u32 id, struct hal_capability_supported *capability)
1362{
1363 struct v4l2_ctrl *ctrl = NULL;
1364 int rc = 0;
1365
1366 ctrl = v4l2_ctrl_find(&inst->ctrl_handler, id);
1367 if (ctrl) {
1368 v4l2_ctrl_modify_range(ctrl, capability->min,
1369 capability->max, ctrl->step,
Maheshwar Ajja850be3c2017-07-06 17:47:40 -07001370 ctrl->default_value);
Praneeth Paladugue1679112017-01-27 10:07:15 -08001371 dprintk(VIDC_DBG,
1372 "%s: Updated Range = %lld --> %lld Def value = %lld\n",
1373 ctrl->name, ctrl->minimum, ctrl->maximum,
1374 ctrl->default_value);
1375 } else {
1376 dprintk(VIDC_ERR,
1377 "Failed to find Conrol %d\n", id);
1378 rc = -EINVAL;
1379 }
1380
1381 return rc;
1382 }
1383
1384static void msm_vidc_comm_update_ctrl_limits(struct msm_vidc_inst *inst)
1385{
Chinmay Sawarkar468c2672017-04-14 14:32:18 -07001386 if (inst->session_type == MSM_VIDC_ENCODER) {
Surajit Poddere502daa2017-05-30 19:17:45 +05301387 if (get_hal_codec(inst->fmts[CAPTURE_PORT].fourcc) ==
1388 HAL_VIDEO_CODEC_TME)
1389 return;
Chinmay Sawarkar468c2672017-04-14 14:32:18 -07001390 msm_vidc_comm_update_ctrl(inst,
1391 V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE,
1392 &inst->capability.hier_p_hybrid);
1393 msm_vidc_comm_update_ctrl(inst,
1394 V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS,
1395 &inst->capability.hier_b);
1396 msm_vidc_comm_update_ctrl(inst,
1397 V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS,
1398 &inst->capability.hier_p);
1399 msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDEO_BITRATE,
1400 &inst->capability.bitrate);
1401 msm_vidc_comm_update_ctrl(inst,
1402 V4L2_CID_MPEG_VIDC_VENC_PARAM_LAYER_BITRATE,
1403 &inst->capability.bitrate);
1404 msm_vidc_comm_update_ctrl(inst,
1405 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1406 &inst->capability.peakbitrate);
1407 msm_vidc_comm_update_ctrl(inst,
1408 V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP,
1409 &inst->capability.i_qp);
1410 msm_vidc_comm_update_ctrl(inst,
1411 V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP,
1412 &inst->capability.p_qp);
1413 msm_vidc_comm_update_ctrl(inst,
1414 V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP,
1415 &inst->capability.b_qp);
1416 msm_vidc_comm_update_ctrl(inst,
1417 V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MIN,
1418 &inst->capability.i_qp);
1419 msm_vidc_comm_update_ctrl(inst,
1420 V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MIN,
1421 &inst->capability.p_qp);
1422 msm_vidc_comm_update_ctrl(inst,
1423 V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MIN,
1424 &inst->capability.b_qp);
1425 msm_vidc_comm_update_ctrl(inst,
1426 V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MAX,
1427 &inst->capability.i_qp);
1428 msm_vidc_comm_update_ctrl(inst,
1429 V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MAX,
1430 &inst->capability.p_qp);
1431 msm_vidc_comm_update_ctrl(inst,
1432 V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MAX,
1433 &inst->capability.b_qp);
1434 msm_vidc_comm_update_ctrl(inst,
1435 V4L2_CID_MPEG_VIDC_VIDEO_BLUR_WIDTH,
1436 &inst->capability.blur_width);
1437 msm_vidc_comm_update_ctrl(inst,
1438 V4L2_CID_MPEG_VIDC_VIDEO_BLUR_HEIGHT,
1439 &inst->capability.blur_height);
1440 msm_vidc_comm_update_ctrl(inst,
1441 V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
1442 &inst->capability.slice_bytes);
1443 msm_vidc_comm_update_ctrl(inst,
1444 V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
1445 &inst->capability.slice_mbs);
1446 msm_vidc_comm_update_ctrl(inst,
1447 V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT,
1448 &inst->capability.ltr_count);
1449 msm_vidc_comm_update_ctrl(inst,
1450 V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES,
1451 &inst->capability.bframe);
1452 }
Saurabh Kothawade501be792017-08-29 11:41:38 -07001453 msm_vidc_comm_update_ctrl(inst,
1454 V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE,
1455 &inst->capability.frame_rate);
Praneeth Paladugue1679112017-01-27 10:07:15 -08001456}
1457
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001458static void handle_session_init_done(enum hal_command_response cmd, void *data)
1459{
1460 struct msm_vidc_cb_cmd_done *response = data;
1461 struct msm_vidc_inst *inst = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001462 struct msm_vidc_capability *capability = NULL;
1463 struct hfi_device *hdev;
1464 struct msm_vidc_core *core;
1465 u32 i, codec;
1466
1467 if (!response) {
1468 dprintk(VIDC_ERR,
1469 "Failed to get valid response for session init\n");
1470 return;
1471 }
1472
1473 inst = get_inst(get_vidc_core(response->device_id),
1474 response->session_id);
1475
1476 if (!inst) {
1477 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1478 return;
1479 }
1480
1481 if (response->status) {
1482 dprintk(VIDC_ERR,
1483 "Session init response from FW : %#x\n",
1484 response->status);
1485 if (response->status == VIDC_ERR_MAX_CLIENTS)
1486 msm_comm_generate_max_clients_error(inst);
1487 else
1488 msm_comm_generate_session_error(inst);
1489
1490 signal_session_msg_receipt(cmd, inst);
1491 put_inst(inst);
1492 return;
1493 }
1494
1495 core = inst->core;
1496 hdev = inst->core->device;
1497 codec = inst->session_type == MSM_VIDC_DECODER ?
1498 inst->fmts[OUTPUT_PORT].fourcc :
1499 inst->fmts[CAPTURE_PORT].fourcc;
1500
1501 /* check if capabilities are available for this session */
1502 for (i = 0; i < VIDC_MAX_SESSIONS; i++) {
1503 if (core->capabilities[i].codec ==
1504 get_hal_codec(codec) &&
1505 core->capabilities[i].domain ==
1506 get_hal_domain(inst->session_type)) {
1507 capability = &core->capabilities[i];
1508 break;
1509 }
1510 }
1511
1512 if (capability) {
1513 dprintk(VIDC_DBG,
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001514 "%s: capabilities for codec 0x%x, domain %#x\n",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001515 __func__, capability->codec, capability->domain);
1516 memcpy(&inst->capability, capability,
1517 sizeof(struct msm_vidc_capability));
1518 } else {
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001519 dprintk(VIDC_ERR,
1520 "Watch out : Some property may fail inst %pK\n", inst);
1521 dprintk(VIDC_ERR,
1522 "Caps N/A for codec 0x%x, domain %#x\n",
1523 inst->capability.codec, inst->capability.domain);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001524 }
1525 inst->capability.pixelprocess_capabilities =
1526 call_hfi_op(hdev, get_core_capabilities, hdev->hfi_device_data);
1527
1528 dprintk(VIDC_DBG,
1529 "Capability type : min max step size\n");
1530 print_cap("width", &inst->capability.width);
1531 print_cap("height", &inst->capability.height);
1532 print_cap("mbs_per_frame", &inst->capability.mbs_per_frame);
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001533 print_cap("mbs_per_sec", &inst->capability.mbs_per_sec);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001534 print_cap("frame_rate", &inst->capability.frame_rate);
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001535 print_cap("bitrate", &inst->capability.bitrate);
1536 print_cap("peak_bitrate", &inst->capability.peakbitrate);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001537 print_cap("scale_x", &inst->capability.scale_x);
1538 print_cap("scale_y", &inst->capability.scale_y);
1539 print_cap("hier_p", &inst->capability.hier_p);
1540 print_cap("ltr_count", &inst->capability.ltr_count);
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001541 print_cap("bframe", &inst->capability.bframe);
1542 print_cap("secure_output2_threshold",
1543 &inst->capability.secure_output2_threshold);
1544 print_cap("hier_b", &inst->capability.hier_b);
1545 print_cap("lcu_size", &inst->capability.lcu_size);
1546 print_cap("hier_p_hybrid", &inst->capability.hier_p_hybrid);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001547 print_cap("mbs_per_sec_low_power",
1548 &inst->capability.mbs_per_sec_power_save);
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001549 print_cap("extradata", &inst->capability.extradata);
1550 print_cap("profile", &inst->capability.profile);
1551 print_cap("level", &inst->capability.level);
1552 print_cap("i_qp", &inst->capability.i_qp);
1553 print_cap("p_qp", &inst->capability.p_qp);
1554 print_cap("b_qp", &inst->capability.b_qp);
1555 print_cap("rc_modes", &inst->capability.rc_modes);
1556 print_cap("blur_width", &inst->capability.blur_width);
1557 print_cap("blur_height", &inst->capability.blur_height);
1558 print_cap("slice_delivery_mode", &inst->capability.slice_delivery_mode);
1559 print_cap("slice_bytes", &inst->capability.slice_bytes);
1560 print_cap("slice_mbs", &inst->capability.slice_mbs);
1561 print_cap("secure", &inst->capability.secure);
1562 print_cap("max_num_b_frames", &inst->capability.max_num_b_frames);
1563 print_cap("max_video_cores", &inst->capability.max_video_cores);
1564 print_cap("max_work_modes", &inst->capability.max_work_modes);
1565 print_cap("ubwc_cr_stats", &inst->capability.ubwc_cr_stats);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001566
Vaibhav Deshu Venkateshf962e1c2017-07-24 16:19:01 -07001567 dprintk(VIDC_DBG, "profile count : %u",
1568 inst->capability.profile_level.profile_count);
1569 for (i = 0; i < inst->capability.profile_level.profile_count; i++) {
1570 dprintk(VIDC_DBG, "profile : %u ", inst->capability.
1571 profile_level.profile_level[i].profile);
1572 dprintk(VIDC_DBG, "level : %u ", inst->capability.
1573 profile_level.profile_level[i].level);
1574 }
1575
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001576 signal_session_msg_receipt(cmd, inst);
Praneeth Paladugue1679112017-01-27 10:07:15 -08001577
1578 /*
1579 * Update controls after informing session_init_done to avoid
1580 * timeouts.
1581 */
1582
1583 msm_vidc_comm_update_ctrl_limits(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001584 put_inst(inst);
1585}
1586
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001587static void msm_vidc_queue_rbr_event(struct msm_vidc_inst *inst,
1588 int fd, u32 offset)
1589{
1590 struct v4l2_event buf_event = {0};
1591 u32 *ptr;
1592
1593 buf_event.type = V4L2_EVENT_RELEASE_BUFFER_REFERENCE;
1594 ptr = (u32 *)buf_event.u.data;
1595 ptr[0] = fd;
1596 ptr[1] = offset;
1597
1598 v4l2_event_queue_fh(&inst->event_handler, &buf_event);
1599}
1600
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001601static void handle_event_change(enum hal_command_response cmd, void *data)
1602{
1603 struct msm_vidc_inst *inst = NULL;
1604 struct msm_vidc_cb_event *event_notify = data;
1605 int event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
1606 struct v4l2_event seq_changed_event = {0};
1607 int rc = 0;
1608 struct hfi_device *hdev;
1609 u32 *ptr = NULL;
Praneeth Paladugu6e637472017-05-16 16:06:46 -07001610 struct hal_buffer_requirements *bufreq;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001611
1612 if (!event_notify) {
1613 dprintk(VIDC_WARN, "Got an empty event from hfi\n");
1614 return;
1615 }
1616
1617 inst = get_inst(get_vidc_core(event_notify->device_id),
1618 event_notify->session_id);
1619 if (!inst || !inst->core || !inst->core->device) {
1620 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1621 goto err_bad_event;
1622 }
1623 hdev = inst->core->device;
1624
1625 switch (event_notify->hal_event_type) {
1626 case HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES:
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001627 event = V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001628 break;
1629 case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
1630 event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
1631 break;
1632 case HAL_EVENT_RELEASE_BUFFER_REFERENCE:
1633 {
Maheshwar Ajjacca04052017-07-12 17:59:45 -07001634 struct msm_vidc_buffer *mbuf;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001635 u32 planes[VIDEO_MAX_PLANES] = {0};
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001636
1637 dprintk(VIDC_DBG,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001638 "%s: inst: %pK data_buffer: %x extradata_buffer: %x\n",
1639 __func__, inst, event_notify->packet_buffer,
1640 event_notify->extra_data_buffer);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001641
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001642 planes[0] = event_notify->packet_buffer;
1643 planes[1] = event_notify->extra_data_buffer;
Maheshwar Ajjacca04052017-07-12 17:59:45 -07001644 mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
1645 if (!mbuf || !kref_get_mbuf(inst, mbuf)) {
1646 dprintk(VIDC_ERR,
1647 "%s: data_addr %x, extradata_addr %x not found\n",
1648 __func__, planes[0], planes[1]);
1649 } else {
1650 handle_release_buffer_reference(inst, mbuf);
1651 kref_put_mbuf(mbuf);
1652 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001653 goto err_bad_event;
1654 }
1655 default:
1656 break;
1657 }
1658
1659 /* Bit depth and pic struct changed event are combined into a single
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001660 * event (insufficient event) for the userspace. Currently bitdepth
1661 * changes is only for HEVC and interlaced support is for all
1662 * codecs except HEVC
1663 * event data is now as follows:
1664 * u32 *ptr = seq_changed_event.u.data;
1665 * ptr[0] = height
1666 * ptr[1] = width
1667 * ptr[2] = bit depth
1668 * ptr[3] = pic struct (progressive or interlaced)
1669 * ptr[4] = colour space
Umesh Pandey92bd41d2017-08-10 14:52:33 -07001670 * ptr[5] = crop_data(top)
1671 * ptr[6] = crop_data(left)
1672 * ptr[7] = crop_data(height)
1673 * ptr[8] = crop_data(width)
1674 * ptr[9] = profile
1675 * ptr[10] = level
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001676 */
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001677
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -07001678 inst->entropy_mode = event_notify->entropy_mode;
1679 inst->profile = event_notify->profile;
1680 inst->level = event_notify->level;
Praneeth Paladugu520e9b22017-05-31 13:25:18 -07001681 inst->prop.crop_info.left =
1682 event_notify->crop_data.left;
1683 inst->prop.crop_info.top =
1684 event_notify->crop_data.top;
1685 inst->prop.crop_info.height =
1686 event_notify->crop_data.height;
1687 inst->prop.crop_info.width =
1688 event_notify->crop_data.width;
Praneeth Paladuguf597ddd2017-09-27 11:00:31 -07001689 /* HW returns progressive_only flag in pic_struct. */
1690 inst->pic_struct =
1691 event_notify->pic_struct ?
1692 MSM_VIDC_PIC_STRUCT_PROGRESSIVE :
1693 MSM_VIDC_PIC_STRUCT_MAYBE_INTERLACED;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -08001694
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001695 ptr = (u32 *)seq_changed_event.u.data;
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001696 ptr[0] = event_notify->height;
1697 ptr[1] = event_notify->width;
1698 ptr[2] = event_notify->bit_depth;
1699 ptr[3] = event_notify->pic_struct;
1700 ptr[4] = event_notify->colour_space;
Praneeth Paladugu72fa67b2017-05-30 11:20:01 -07001701 ptr[5] = event_notify->crop_data.top;
1702 ptr[6] = event_notify->crop_data.left;
1703 ptr[7] = event_notify->crop_data.height;
1704 ptr[8] = event_notify->crop_data.width;
Umesh Pandey92bd41d2017-08-10 14:52:33 -07001705 ptr[9] = msm_comm_get_v4l2_profile(
1706 inst->fmts[OUTPUT_PORT].fourcc,
1707 event_notify->profile);
1708 ptr[10] = msm_comm_get_v4l2_level(
1709 inst->fmts[OUTPUT_PORT].fourcc,
1710 event_notify->level);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001711
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001712 dprintk(VIDC_DBG,
Umesh Pandey92bd41d2017-08-10 14:52:33 -07001713 "Event payload: height = %d width = %d profile = %d level = %d\n",
1714 event_notify->height, event_notify->width,
1715 ptr[9], ptr[10]);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001716
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001717 dprintk(VIDC_DBG,
1718 "Event payload: bit_depth = %d pic_struct = %d colour_space = %d\n",
1719 event_notify->bit_depth, event_notify->pic_struct,
1720 event_notify->colour_space);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001721
Praneeth Paladugu520e9b22017-05-31 13:25:18 -07001722 dprintk(VIDC_DBG,
1723 "Event payload: CROP top = %d left = %d Height = %d Width = %d\n",
1724 event_notify->crop_data.top,
1725 event_notify->crop_data.left,
1726 event_notify->crop_data.height,
1727 event_notify->crop_data.width);
1728
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001729 mutex_lock(&inst->lock);
1730 inst->in_reconfig = true;
1731 inst->reconfig_height = event_notify->height;
1732 inst->reconfig_width = event_notify->width;
Praneeth Paladugu6e637472017-05-16 16:06:46 -07001733
1734 if (msm_comm_get_stream_output_mode(inst) ==
1735 HAL_VIDEO_DECODER_SECONDARY) {
1736
1737 bufreq = get_buff_req_buffer(inst,
1738 HAL_BUFFER_OUTPUT);
1739 if (!bufreq) {
1740 dprintk(VIDC_ERR,
1741 "Failed : No buffer requirements : %x\n",
1742 HAL_BUFFER_OUTPUT);
1743 return;
1744 }
1745
1746 bufreq->buffer_count_min = event_notify->capture_buf_count;
1747
1748 bufreq = get_buff_req_buffer(inst,
1749 HAL_BUFFER_OUTPUT2);
1750 if (!bufreq) {
1751 dprintk(VIDC_ERR,
1752 "Failed : No buffer requirements : %x\n",
1753 HAL_BUFFER_OUTPUT2);
1754 return;
1755 }
1756
1757 bufreq->buffer_count_min = event_notify->capture_buf_count;
1758 } else {
1759
1760 bufreq = get_buff_req_buffer(inst,
1761 HAL_BUFFER_OUTPUT);
1762 if (!bufreq) {
1763 dprintk(VIDC_ERR,
1764 "Failed : No buffer requirements : %x\n",
1765 HAL_BUFFER_OUTPUT);
1766 return;
1767 }
1768 bufreq->buffer_count_min = event_notify->capture_buf_count;
Praneeth Paladugu6e637472017-05-16 16:06:46 -07001769 }
1770
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001771 mutex_unlock(&inst->lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001772
1773 if (event == V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT) {
1774 dprintk(VIDC_DBG, "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT\n");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001775 } else {
1776 dprintk(VIDC_DBG, "V4L2_EVENT_SEQ_CHANGED_SUFFICIENT\n");
1777 dprintk(VIDC_DBG,
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001778 "event_notify->height = %d event_notify->width = %d\n",
1779 event_notify->height,
1780 event_notify->width);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001781 }
1782
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001783 rc = msm_vidc_check_session_supported(inst);
1784 if (!rc) {
1785 seq_changed_event.type = event;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001786 v4l2_event_queue_fh(&inst->event_handler, &seq_changed_event);
1787 } else if (rc == -ENOTSUPP) {
1788 msm_vidc_queue_v4l2_event(inst,
1789 V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED);
1790 } else if (rc == -EBUSY) {
1791 msm_vidc_queue_v4l2_event(inst,
1792 V4L2_EVENT_MSM_VIDC_HW_OVERLOAD);
1793 }
1794
1795err_bad_event:
1796 put_inst(inst);
1797}
1798
1799static void handle_session_prop_info(enum hal_command_response cmd, void *data)
1800{
1801 struct msm_vidc_cb_cmd_done *response = data;
1802 struct getprop_buf *getprop;
1803 struct msm_vidc_inst *inst;
1804
1805 if (!response) {
1806 dprintk(VIDC_ERR,
1807 "Failed to get valid response for prop info\n");
1808 return;
1809 }
1810
1811 inst = get_inst(get_vidc_core(response->device_id),
1812 response->session_id);
1813 if (!inst) {
1814 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1815 return;
1816 }
1817
1818 getprop = kzalloc(sizeof(*getprop), GFP_KERNEL);
1819 if (!getprop) {
1820 dprintk(VIDC_ERR, "%s: getprop kzalloc failed\n", __func__);
1821 goto err_prop_info;
1822 }
1823
1824 getprop->data = kmemdup(&response->data.property,
1825 sizeof(union hal_get_property), GFP_KERNEL);
1826 if (!getprop->data) {
1827 dprintk(VIDC_ERR, "%s: kmemdup failed\n", __func__);
1828 kfree(getprop);
1829 goto err_prop_info;
1830 }
1831
1832 mutex_lock(&inst->pending_getpropq.lock);
1833 list_add_tail(&getprop->list, &inst->pending_getpropq.list);
1834 mutex_unlock(&inst->pending_getpropq.lock);
1835
1836 signal_session_msg_receipt(cmd, inst);
1837err_prop_info:
1838 put_inst(inst);
1839}
1840
1841static void handle_load_resource_done(enum hal_command_response cmd, void *data)
1842{
1843 struct msm_vidc_cb_cmd_done *response = data;
1844 struct msm_vidc_inst *inst;
1845
1846 if (!response) {
1847 dprintk(VIDC_ERR,
1848 "Failed to get valid response for load resource\n");
1849 return;
1850 }
1851
1852 inst = get_inst(get_vidc_core(response->device_id),
1853 response->session_id);
1854 if (!inst) {
1855 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1856 return;
1857 }
1858
1859 if (response->status) {
1860 dprintk(VIDC_ERR,
1861 "Load resource response from FW : %#x\n",
1862 response->status);
1863 msm_comm_generate_session_error(inst);
1864 }
1865
1866 put_inst(inst);
1867}
1868
1869static void handle_start_done(enum hal_command_response cmd, void *data)
1870{
1871 struct msm_vidc_cb_cmd_done *response = data;
1872 struct msm_vidc_inst *inst;
1873
1874 if (!response) {
1875 dprintk(VIDC_ERR, "Failed to get valid response for start\n");
1876 return;
1877 }
1878
1879 inst = get_inst(get_vidc_core(response->device_id),
1880 response->session_id);
1881 if (!inst) {
1882 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1883 return;
1884 }
1885
1886 signal_session_msg_receipt(cmd, inst);
1887 put_inst(inst);
1888}
1889
1890static void handle_stop_done(enum hal_command_response cmd, void *data)
1891{
1892 struct msm_vidc_cb_cmd_done *response = data;
1893 struct msm_vidc_inst *inst;
1894
1895 if (!response) {
1896 dprintk(VIDC_ERR, "Failed to get valid response for stop\n");
1897 return;
1898 }
1899
1900 inst = get_inst(get_vidc_core(response->device_id),
1901 response->session_id);
1902 if (!inst) {
1903 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1904 return;
1905 }
1906
1907 signal_session_msg_receipt(cmd, inst);
1908 put_inst(inst);
1909}
1910
1911static void handle_release_res_done(enum hal_command_response cmd, void *data)
1912{
1913 struct msm_vidc_cb_cmd_done *response = data;
1914 struct msm_vidc_inst *inst;
1915
1916 if (!response) {
1917 dprintk(VIDC_ERR,
1918 "Failed to get valid response for release resource\n");
1919 return;
1920 }
1921
1922 inst = get_inst(get_vidc_core(response->device_id),
1923 response->session_id);
1924 if (!inst) {
1925 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1926 return;
1927 }
1928
1929 signal_session_msg_receipt(cmd, inst);
1930 put_inst(inst);
1931}
1932
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08001933void msm_comm_validate_output_buffers(struct msm_vidc_inst *inst)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001934{
1935 struct internal_buf *binfo;
1936 u32 buffers_owned_by_driver = 0;
1937 struct hal_buffer_requirements *output_buf;
1938
1939 output_buf = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
1940
1941 if (!output_buf) {
1942 dprintk(VIDC_DBG,
1943 "This output buffer not required, buffer_type: %x\n",
1944 HAL_BUFFER_OUTPUT);
1945 return;
1946 }
1947 mutex_lock(&inst->outputbufs.lock);
Maheshwar Ajja850be3c2017-07-06 17:47:40 -07001948 if (list_empty(&inst->outputbufs.list)) {
1949 dprintk(VIDC_DBG, "%s: no OUTPUT buffers allocated\n",
1950 __func__);
1951 mutex_unlock(&inst->outputbufs.lock);
1952 return;
1953 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001954 list_for_each_entry(binfo, &inst->outputbufs.list, list) {
1955 if (binfo->buffer_ownership != DRIVER) {
1956 dprintk(VIDC_DBG,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001957 "This buffer is with FW %x\n",
1958 binfo->smem.device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001959 continue;
1960 }
1961 buffers_owned_by_driver++;
1962 }
1963 mutex_unlock(&inst->outputbufs.lock);
1964
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08001965 if (buffers_owned_by_driver != output_buf->buffer_count_actual) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001966 dprintk(VIDC_WARN,
1967 "OUTPUT Buffer count mismatch %d of %d\n",
1968 buffers_owned_by_driver,
1969 output_buf->buffer_count_actual);
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08001970 msm_vidc_handle_hw_error(inst->core);
1971 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001972}
1973
1974int msm_comm_queue_output_buffers(struct msm_vidc_inst *inst)
1975{
1976 struct internal_buf *binfo;
1977 struct hfi_device *hdev;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001978 struct vidc_frame_data frame_data = {0};
1979 struct hal_buffer_requirements *output_buf, *extra_buf;
1980 int rc = 0;
1981
1982 if (!inst || !inst->core || !inst->core->device) {
1983 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
1984 return -EINVAL;
1985 }
1986
1987 hdev = inst->core->device;
1988
1989 output_buf = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
1990 if (!output_buf) {
1991 dprintk(VIDC_DBG,
1992 "This output buffer not required, buffer_type: %x\n",
1993 HAL_BUFFER_OUTPUT);
1994 return 0;
1995 }
1996 dprintk(VIDC_DBG,
1997 "output: num = %d, size = %d\n",
1998 output_buf->buffer_count_actual,
1999 output_buf->buffer_size);
2000
2001 extra_buf = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_OUTPUT);
2002
2003 mutex_lock(&inst->outputbufs.lock);
2004 list_for_each_entry(binfo, &inst->outputbufs.list, list) {
2005 if (binfo->buffer_ownership != DRIVER)
2006 continue;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002007 frame_data.alloc_len = output_buf->buffer_size;
2008 frame_data.filled_len = 0;
2009 frame_data.offset = 0;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002010 frame_data.device_addr = binfo->smem.device_addr;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002011 frame_data.flags = 0;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002012 frame_data.extradata_addr = binfo->smem.device_addr +
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002013 output_buf->buffer_size;
2014 frame_data.buffer_type = HAL_BUFFER_OUTPUT;
2015 frame_data.extradata_size = extra_buf ?
2016 extra_buf->buffer_size : 0;
2017 rc = call_hfi_op(hdev, session_ftb,
2018 (void *) inst->session, &frame_data);
2019 binfo->buffer_ownership = FIRMWARE;
2020 }
2021 mutex_unlock(&inst->outputbufs.lock);
2022
2023 return 0;
2024}
2025
2026static void handle_session_flush(enum hal_command_response cmd, void *data)
2027{
2028 struct msm_vidc_cb_cmd_done *response = data;
2029 struct msm_vidc_inst *inst;
2030 struct v4l2_event flush_event = {0};
2031 u32 *ptr = NULL;
2032 enum hal_flush flush_type;
2033 int rc;
2034
2035 if (!response) {
2036 dprintk(VIDC_ERR, "Failed to get valid response for flush\n");
2037 return;
2038 }
2039
2040 inst = get_inst(get_vidc_core(response->device_id),
2041 response->session_id);
2042 if (!inst) {
2043 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2044 return;
2045 }
2046
Surajit Podder0d812bf2018-02-02 13:37:24 +05302047 mutex_lock(&inst->flush_lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002048 if (msm_comm_get_stream_output_mode(inst) ==
2049 HAL_VIDEO_DECODER_SECONDARY) {
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08002050
2051 if (!(inst->fmts[OUTPUT_PORT].defer_outputs &&
2052 inst->in_reconfig))
2053 msm_comm_validate_output_buffers(inst);
2054
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002055 if (!inst->in_reconfig) {
2056 rc = msm_comm_queue_output_buffers(inst);
2057 if (rc) {
2058 dprintk(VIDC_ERR,
2059 "Failed to queue output buffers: %d\n",
2060 rc);
2061 }
2062 }
2063 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002064 inst->in_flush = false;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002065 flush_event.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
2066 ptr = (u32 *)flush_event.u.data;
2067
2068 flush_type = response->data.flush_type;
2069 switch (flush_type) {
2070 case HAL_FLUSH_INPUT:
2071 ptr[0] = V4L2_QCOM_CMD_FLUSH_OUTPUT;
2072 break;
2073 case HAL_FLUSH_OUTPUT:
2074 ptr[0] = V4L2_QCOM_CMD_FLUSH_CAPTURE;
2075 break;
2076 case HAL_FLUSH_ALL:
2077 ptr[0] |= V4L2_QCOM_CMD_FLUSH_CAPTURE;
2078 ptr[0] |= V4L2_QCOM_CMD_FLUSH_OUTPUT;
2079 break;
2080 default:
2081 dprintk(VIDC_ERR, "Invalid flush type received!");
2082 goto exit;
2083 }
2084
2085 dprintk(VIDC_DBG,
2086 "Notify flush complete, flush_type: %x\n", flush_type);
2087 v4l2_event_queue_fh(&inst->event_handler, &flush_event);
2088
2089exit:
Surajit Podder0d812bf2018-02-02 13:37:24 +05302090 mutex_unlock(&inst->flush_lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002091 put_inst(inst);
2092}
2093
2094static void handle_session_error(enum hal_command_response cmd, void *data)
2095{
2096 struct msm_vidc_cb_cmd_done *response = data;
2097 struct hfi_device *hdev = NULL;
2098 struct msm_vidc_inst *inst = NULL;
2099 int event = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
2100
2101 if (!response) {
2102 dprintk(VIDC_ERR,
2103 "Failed to get valid response for session error\n");
2104 return;
2105 }
2106
2107 inst = get_inst(get_vidc_core(response->device_id),
2108 response->session_id);
2109 if (!inst) {
2110 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2111 return;
2112 }
2113
2114 hdev = inst->core->device;
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07002115 dprintk(VIDC_ERR, "Session error received for inst %pK session %x\n",
2116 inst, hash32_ptr(inst->session));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002117
2118 if (response->status == VIDC_ERR_MAX_CLIENTS) {
2119 dprintk(VIDC_WARN, "Too many clients, rejecting %pK", inst);
2120 event = V4L2_EVENT_MSM_VIDC_MAX_CLIENTS;
2121
2122 /*
2123 * Clean the HFI session now. Since inst->state is moved to
2124 * INVALID, forward thread doesn't know FW has valid session
2125 * or not. This is the last place driver knows that there is
2126 * no session in FW. Hence clean HFI session now.
2127 */
2128
2129 msm_comm_session_clean(inst);
2130 } else if (response->status == VIDC_ERR_NOT_SUPPORTED) {
2131 dprintk(VIDC_WARN, "Unsupported bitstream in %pK", inst);
2132 event = V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED;
2133 } else {
2134 dprintk(VIDC_WARN, "Unknown session error (%d) for %pK\n",
2135 response->status, inst);
2136 event = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
2137 }
2138
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07002139 /* change state before sending error to client */
2140 change_inst_state(inst, MSM_VIDC_CORE_INVALID);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002141 msm_vidc_queue_v4l2_event(inst, event);
2142 put_inst(inst);
2143}
2144
2145static void msm_comm_clean_notify_client(struct msm_vidc_core *core)
2146{
2147 struct msm_vidc_inst *inst = NULL;
2148
2149 if (!core) {
2150 dprintk(VIDC_ERR, "%s: Invalid params\n", __func__);
2151 return;
2152 }
2153
2154 dprintk(VIDC_WARN, "%s: Core %pK\n", __func__, core);
2155 mutex_lock(&core->lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002156
2157 list_for_each_entry(inst, &core->instances, list) {
2158 mutex_lock(&inst->lock);
2159 inst->state = MSM_VIDC_CORE_INVALID;
2160 mutex_unlock(&inst->lock);
2161 dprintk(VIDC_WARN,
2162 "%s Send sys error for inst %pK\n", __func__, inst);
2163 msm_vidc_queue_v4l2_event(inst,
2164 V4L2_EVENT_MSM_VIDC_SYS_ERROR);
2165 }
2166 mutex_unlock(&core->lock);
2167}
2168
2169static void handle_sys_error(enum hal_command_response cmd, void *data)
2170{
2171 struct msm_vidc_cb_cmd_done *response = data;
2172 struct msm_vidc_core *core = NULL;
2173 struct hfi_device *hdev = NULL;
2174 struct msm_vidc_inst *inst = NULL;
2175 int rc = 0;
2176
2177 subsystem_crashed("venus");
2178 if (!response) {
2179 dprintk(VIDC_ERR,
2180 "Failed to get valid response for sys error\n");
2181 return;
2182 }
2183
2184 core = get_vidc_core(response->device_id);
2185 if (!core) {
2186 dprintk(VIDC_ERR,
2187 "Got SYS_ERR but unable to identify core\n");
2188 return;
2189 }
Maheshwar Ajjac35d7fc2017-09-01 16:44:46 -07002190 hdev = core->device;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002191
2192 mutex_lock(&core->lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002193 if (core->state == VIDC_CORE_UNINIT) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002194 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07002195 "%s: Core %pK already moved to state %d\n",
2196 __func__, core, core->state);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002197 mutex_unlock(&core->lock);
2198 return;
2199 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002200
Maheshwar Ajja99422322017-07-07 17:31:15 -07002201 dprintk(VIDC_WARN, "SYS_ERROR received for core %pK\n", core);
Maheshwar Ajja9ff81a22017-08-05 13:25:55 -07002202 msm_vidc_noc_error_info(core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002203 call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002204 list_for_each_entry(inst, &core->instances, list) {
2205 dprintk(VIDC_WARN,
2206 "%s: Send sys error for inst %pK\n", __func__, inst);
2207 change_inst_state(inst, MSM_VIDC_CORE_INVALID);
2208 msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_SYS_ERROR);
Surajit Poddercd14ed92017-09-12 19:40:56 +05302209 if (!core->trigger_ssr)
2210 msm_comm_print_inst_info(inst);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002211 }
Maheshwar Ajjab94e8192017-10-26 09:34:20 -07002212 /* handle the hw error before core released to get full debug info */
2213 msm_vidc_handle_hw_error(core);
Prateek Shrivastava0727c902018-01-10 16:31:03 +05302214 if (response->status == VIDC_ERR_NOC_ERROR) {
2215 dprintk(VIDC_WARN, "Got NOC error");
2216 MSM_VIDC_ERROR(true);
2217 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002218 dprintk(VIDC_DBG, "Calling core_release\n");
2219 rc = call_hfi_op(hdev, core_release, hdev->hfi_device_data);
2220 if (rc) {
2221 dprintk(VIDC_ERR, "core_release failed\n");
2222 mutex_unlock(&core->lock);
2223 return;
2224 }
2225 core->state = VIDC_CORE_UNINIT;
2226 mutex_unlock(&core->lock);
2227
Maheshwar Ajjab94e8192017-10-26 09:34:20 -07002228 dprintk(VIDC_WARN, "SYS_ERROR handled.\n");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002229}
2230
2231void msm_comm_session_clean(struct msm_vidc_inst *inst)
2232{
2233 int rc = 0;
2234 struct hfi_device *hdev = NULL;
2235
2236 if (!inst || !inst->core || !inst->core->device) {
2237 dprintk(VIDC_ERR, "%s invalid params\n", __func__);
2238 return;
2239 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002240 if (!inst->session) {
2241 dprintk(VIDC_DBG, "%s: inst %pK session already cleaned\n",
2242 __func__, inst);
2243 return;
2244 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002245
2246 hdev = inst->core->device;
2247 mutex_lock(&inst->lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002248 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
2249 rc = call_hfi_op(hdev, session_clean,
2250 (void *)inst->session);
2251 if (rc) {
2252 dprintk(VIDC_ERR,
2253 "Session clean failed :%pK\n", inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002254 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002255 inst->session = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002256 mutex_unlock(&inst->lock);
2257}
2258
2259static void handle_session_close(enum hal_command_response cmd, void *data)
2260{
2261 struct msm_vidc_cb_cmd_done *response = data;
2262 struct msm_vidc_inst *inst;
2263
2264 if (!response) {
2265 dprintk(VIDC_ERR,
2266 "Failed to get valid response for session close\n");
2267 return;
2268 }
2269
2270 inst = get_inst(get_vidc_core(response->device_id),
2271 response->session_id);
2272 if (!inst) {
2273 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2274 return;
2275 }
2276
2277 signal_session_msg_receipt(cmd, inst);
2278 show_stats(inst);
2279 put_inst(inst);
2280}
2281
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002282struct vb2_buffer *msm_comm_get_vb_using_vidc_buffer(
2283 struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002284{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002285 u32 port = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002286 struct vb2_buffer *vb = NULL;
2287 struct vb2_queue *q = NULL;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002288 bool found = false;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002289
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002290 if (mbuf->vvb.vb2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
2291 port = CAPTURE_PORT;
2292 } else if (mbuf->vvb.vb2_buf.type ==
2293 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
2294 port = OUTPUT_PORT;
2295 } else {
2296 dprintk(VIDC_ERR, "%s: invalid type %d\n",
2297 __func__, mbuf->vvb.vb2_buf.type);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002298 return NULL;
2299 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002300
2301 q = &inst->bufq[port].vb2_bufq;
2302 mutex_lock(&inst->bufq[port].lock);
2303 found = false;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002304 list_for_each_entry(vb, &q->queued_list, queued_entry) {
Maheshwar Ajja58c8c222017-09-13 09:02:53 -07002305 if (vb->state != VB2_BUF_STATE_ACTIVE)
2306 continue;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002307 if (msm_comm_compare_vb2_planes(inst, mbuf, vb)) {
2308 found = true;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002309 break;
2310 }
2311 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002312 mutex_unlock(&inst->bufq[port].lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002313 if (!found) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002314 print_vidc_buffer(VIDC_ERR, "vb2 not found for", inst, mbuf);
2315 return NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002316 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002317
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002318 return vb;
2319}
2320
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002321int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst,
2322 struct vb2_buffer *vb)
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002323{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002324 u32 port;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002325
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002326 if (!inst || !vb) {
2327 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
2328 __func__, inst, vb);
2329 return -EINVAL;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002330 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002331
2332 if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
2333 port = CAPTURE_PORT;
2334 } else if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
2335 port = OUTPUT_PORT;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002336 } else {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002337 dprintk(VIDC_ERR, "%s: invalid type %d\n",
2338 __func__, vb->type);
2339 return -EINVAL;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002340 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002341
2342 mutex_lock(&inst->bufq[port].lock);
2343 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
2344 mutex_unlock(&inst->bufq[port].lock);
2345
2346 return 0;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002347}
2348
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07002349static bool is_eos_buffer(struct msm_vidc_inst *inst, u32 device_addr)
2350{
2351 struct eos_buf *temp, *next;
2352 bool found = false;
2353
2354 mutex_lock(&inst->eosbufs.lock);
2355 list_for_each_entry_safe(temp, next, &inst->eosbufs.list, list) {
2356 if (temp->smem.device_addr == device_addr) {
2357 found = true;
2358 list_del(&temp->list);
2359 msm_comm_smem_free(inst, &temp->smem);
2360 kfree(temp);
2361 break;
2362 }
2363 }
2364 mutex_unlock(&inst->eosbufs.lock);
2365
2366 return found;
2367}
2368
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002369static void handle_ebd(enum hal_command_response cmd, void *data)
2370{
2371 struct msm_vidc_cb_data_done *response = data;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002372 struct msm_vidc_buffer *mbuf;
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002373 struct vb2_buffer *vb, *vb2;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002374 struct msm_vidc_inst *inst;
2375 struct vidc_hal_ebd *empty_buf_done;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002376 struct vb2_v4l2_buffer *vbuf;
2377 u32 planes[VIDEO_MAX_PLANES] = {0};
2378 u32 extra_idx = 0, i;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002379
2380 if (!response) {
2381 dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
2382 return;
2383 }
2384
2385 inst = get_inst(get_vidc_core(response->device_id),
2386 response->session_id);
2387 if (!inst) {
2388 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2389 return;
2390 }
2391
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002392 empty_buf_done = (struct vidc_hal_ebd *)&response->input_done;
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07002393 /* If this is internal EOS buffer, handle it in driver */
2394 if (is_eos_buffer(inst, empty_buf_done->packet_buffer)) {
Maria Yu5d853f82017-09-26 16:13:19 +08002395 dprintk(VIDC_DBG, "Received EOS buffer 0x%x\n",
2396 empty_buf_done->packet_buffer);
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07002397 goto exit;
2398 }
2399
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002400 planes[0] = empty_buf_done->packet_buffer;
2401 planes[1] = empty_buf_done->extra_data_buffer;
2402
2403 mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002404 if (!mbuf || !kref_get_mbuf(inst, mbuf)) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002405 dprintk(VIDC_ERR,
2406 "%s: data_addr %x, extradata_addr %x not found\n",
2407 __func__, planes[0], planes[1]);
2408 goto exit;
2409 }
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002410 vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
2411
2412 /*
2413 * take registeredbufs.lock to update mbuf & vb2 variables together
2414 * so that both are in sync else if mbuf and vb2 variables are not
2415 * in sync msm_comm_compare_vb2_planes() returns false for the
2416 * right buffer due to data_offset field mismatch.
2417 */
2418 mutex_lock(&inst->registeredbufs.lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002419 vb = &mbuf->vvb.vb2_buf;
2420
2421 vb->planes[0].bytesused = response->input_done.filled_len;
2422 if (vb->planes[0].bytesused > vb->planes[0].length)
2423 dprintk(VIDC_INFO, "bytesused overflow length\n");
2424
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002425 vb->planes[0].data_offset = response->input_done.offset;
2426 if (vb->planes[0].data_offset > vb->planes[0].length)
2427 dprintk(VIDC_INFO, "data_offset overflow length\n");
2428
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002429 if (empty_buf_done->status == VIDC_ERR_NOT_SUPPORTED) {
2430 dprintk(VIDC_INFO, "Failed : Unsupported input stream\n");
2431 mbuf->vvb.flags |= V4L2_QCOM_BUF_INPUT_UNSUPPORTED;
2432 }
2433 if (empty_buf_done->status == VIDC_ERR_BITSTREAM_ERR) {
2434 dprintk(VIDC_INFO, "Failed : Corrupted input stream\n");
2435 mbuf->vvb.flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
2436 }
2437 if (empty_buf_done->flags & HAL_BUFFERFLAG_SYNCFRAME)
2438 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME |
2439 V4L2_BUF_FLAG_KEYFRAME;
2440
2441 extra_idx = EXTRADATA_IDX(inst->bufq[OUTPUT_PORT].num_planes);
2442 if (extra_idx && extra_idx < VIDEO_MAX_PLANES)
2443 vb->planes[extra_idx].bytesused = vb->planes[extra_idx].length;
2444
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002445 if (vb2) {
2446 vbuf = to_vb2_v4l2_buffer(vb2);
2447 vbuf->flags |= mbuf->vvb.flags;
2448 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
2449 vb2->planes[i].bytesused =
2450 mbuf->vvb.vb2_buf.planes[i].bytesused;
2451 vb2->planes[i].data_offset =
2452 mbuf->vvb.vb2_buf.planes[i].data_offset;
2453 }
2454 }
2455 mutex_unlock(&inst->registeredbufs.lock);
2456
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002457 update_recon_stats(inst, &empty_buf_done->recon_stats);
2458 msm_vidc_clear_freq_entry(inst, mbuf->smem[0].device_addr);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002459 /*
2460 * put_buffer should be done before vb2_buffer_done else
2461 * client might queue the same buffer before it is unmapped
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002462 * in put_buffer.
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002463 */
2464 msm_comm_put_vidc_buffer(inst, mbuf);
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002465 msm_comm_vb2_buffer_done(inst, vb2);
Qiwei Liuf7d96082017-10-19 17:51:09 +08002466 msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_EBD);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002467 kref_put_mbuf(mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002468exit:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002469 put_inst(inst);
2470}
2471
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002472static int handle_multi_stream_buffers(struct msm_vidc_inst *inst,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002473 u32 dev_addr)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002474{
2475 struct internal_buf *binfo;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002476 struct msm_smem *smem;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002477 bool found = false;
2478
2479 mutex_lock(&inst->outputbufs.lock);
2480 list_for_each_entry(binfo, &inst->outputbufs.list, list) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002481 smem = &binfo->smem;
2482 if (smem && dev_addr == smem->device_addr) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002483 if (binfo->buffer_ownership == DRIVER) {
2484 dprintk(VIDC_ERR,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002485 "FW returned same buffer: %x\n",
2486 dev_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002487 break;
2488 }
2489 binfo->buffer_ownership = DRIVER;
2490 found = true;
2491 break;
2492 }
2493 }
2494 mutex_unlock(&inst->outputbufs.lock);
2495
2496 if (!found) {
2497 dprintk(VIDC_ERR,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002498 "Failed to find output buffer in queued list: %x\n",
2499 dev_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002500 }
2501
2502 return 0;
2503}
2504
2505enum hal_buffer msm_comm_get_hal_output_buffer(struct msm_vidc_inst *inst)
2506{
2507 if (msm_comm_get_stream_output_mode(inst) ==
2508 HAL_VIDEO_DECODER_SECONDARY)
2509 return HAL_BUFFER_OUTPUT2;
2510 else
2511 return HAL_BUFFER_OUTPUT;
2512}
2513
2514static void handle_fbd(enum hal_command_response cmd, void *data)
2515{
2516 struct msm_vidc_cb_data_done *response = data;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002517 struct msm_vidc_buffer *mbuf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002518 struct msm_vidc_inst *inst;
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002519 struct vb2_buffer *vb, *vb2;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002520 struct vidc_hal_fbd *fill_buf_done;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002521 struct vb2_v4l2_buffer *vbuf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002522 enum hal_buffer buffer_type;
Vaibhav Deshu Venkateshe5800332017-03-21 14:27:11 -07002523 u64 time_usec = 0;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002524 u32 planes[VIDEO_MAX_PLANES] = {0};
2525 u32 extra_idx, i;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002526
2527 if (!response) {
2528 dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
2529 return;
2530 }
2531
2532 inst = get_inst(get_vidc_core(response->device_id),
2533 response->session_id);
2534 if (!inst) {
2535 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2536 return;
2537 }
2538
2539 fill_buf_done = (struct vidc_hal_fbd *)&response->output_done;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002540 planes[0] = fill_buf_done->packet_buffer1;
2541 planes[1] = fill_buf_done->extra_data_buffer;
2542
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002543 buffer_type = msm_comm_get_hal_output_buffer(inst);
2544 if (fill_buf_done->buffer_type == buffer_type) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002545 mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002546 if (!mbuf || !kref_get_mbuf(inst, mbuf)) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002547 dprintk(VIDC_ERR,
2548 "%s: data_addr %x, extradata_addr %x not found\n",
2549 __func__, planes[0], planes[1]);
2550 goto exit;
2551 }
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002552 vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002553 } else {
2554 if (handle_multi_stream_buffers(inst,
2555 fill_buf_done->packet_buffer1))
2556 dprintk(VIDC_ERR,
2557 "Failed : Output buffer not found %pa\n",
2558 &fill_buf_done->packet_buffer1);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002559 goto exit;
2560 }
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002561
2562 /*
2563 * take registeredbufs.lock to update mbuf & vb2 variables together
2564 * so that both are in sync else if mbuf and vb2 variables are not
2565 * in sync msm_comm_compare_vb2_planes() returns false for the
2566 * right buffer due to data_offset field mismatch.
2567 */
2568 mutex_lock(&inst->registeredbufs.lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002569 vb = &mbuf->vvb.vb2_buf;
2570
2571 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME ||
2572 fill_buf_done->flags1 & HAL_BUFFERFLAG_DECODEONLY)
2573 fill_buf_done->filled_len1 = 0;
2574 vb->planes[0].bytesused = fill_buf_done->filled_len1;
2575 if (vb->planes[0].bytesused > vb->planes[0].length)
2576 dprintk(VIDC_INFO,
2577 "fbd:Overflow bytesused = %d; length = %d\n",
2578 vb->planes[0].bytesused,
2579 vb->planes[0].length);
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002580 vb->planes[0].data_offset = fill_buf_done->offset1;
2581 if (vb->planes[0].data_offset > vb->planes[0].length)
2582 dprintk(VIDC_INFO,
2583 "fbd:Overflow data_offset = %d; length = %d\n",
2584 vb->planes[0].data_offset,
2585 vb->planes[0].length);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002586 if (!(fill_buf_done->flags1 & HAL_BUFFERFLAG_TIMESTAMPINVALID)) {
2587 time_usec = fill_buf_done->timestamp_hi;
2588 time_usec = (time_usec << 32) | fill_buf_done->timestamp_lo;
2589 } else {
2590 time_usec = 0;
2591 dprintk(VIDC_DBG,
2592 "Set zero timestamp for buffer %pa, filled: %d, (hi:%u, lo:%u)\n",
2593 &fill_buf_done->packet_buffer1,
2594 fill_buf_done->filled_len1,
2595 fill_buf_done->timestamp_hi,
2596 fill_buf_done->timestamp_lo);
2597 }
2598 vb->timestamp = (time_usec * NSEC_PER_USEC);
2599
Qiwei Liu551a22222017-08-23 15:28:29 +08002600 if (inst->session_type == MSM_VIDC_DECODER) {
2601 msm_comm_store_mark_data(&inst->fbd_data, vb->index,
2602 fill_buf_done->mark_data, fill_buf_done->mark_target);
2603 }
2604
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002605 extra_idx = EXTRADATA_IDX(inst->bufq[CAPTURE_PORT].num_planes);
2606 if (extra_idx && extra_idx < VIDEO_MAX_PLANES)
2607 vb->planes[extra_idx].bytesused = vb->planes[extra_idx].length;
2608
2609 mbuf->vvb.flags = 0;
2610 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_READONLY)
2611 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_READONLY;
2612 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOS)
2613 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_EOS;
2614 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_CODECCONFIG)
2615 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_CODECCONFIG;
2616 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_SYNCFRAME)
2617 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
2618 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOSEQ)
2619 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_EOSEQ;
2620 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DECODEONLY ||
2621 fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME)
2622 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_DECODEONLY;
2623 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DATACORRUPT)
2624 mbuf->vvb.flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
2625 switch (fill_buf_done->picture_type) {
2626 case HAL_PICTURE_IDR:
2627 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
2628 mbuf->vvb.flags |= V4L2_BUF_FLAG_KEYFRAME;
2629 break;
2630 case HAL_PICTURE_I:
2631 mbuf->vvb.flags |= V4L2_BUF_FLAG_KEYFRAME;
2632 break;
2633 case HAL_PICTURE_P:
2634 mbuf->vvb.flags |= V4L2_BUF_FLAG_PFRAME;
2635 break;
2636 case HAL_PICTURE_B:
2637 mbuf->vvb.flags |= V4L2_BUF_FLAG_BFRAME;
2638 break;
2639 case HAL_FRAME_NOTCODED:
2640 case HAL_UNUSED_PICT:
2641 /* Do we need to care about these? */
2642 case HAL_FRAME_YUV:
2643 break;
2644 default:
2645 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002646 }
2647
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002648 if (vb2) {
2649 vbuf = to_vb2_v4l2_buffer(vb2);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002650 vbuf->flags = mbuf->vvb.flags;
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002651 vb2->timestamp = mbuf->vvb.vb2_buf.timestamp;
2652 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
2653 vb2->planes[i].bytesused =
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002654 mbuf->vvb.vb2_buf.planes[i].bytesused;
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002655 vb2->planes[i].data_offset =
2656 mbuf->vvb.vb2_buf.planes[i].data_offset;
2657 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002658 }
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002659 mutex_unlock(&inst->registeredbufs.lock);
2660
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002661 /*
2662 * put_buffer should be done before vb2_buffer_done else
2663 * client might queue the same buffer before it is unmapped
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002664 * in put_buffer.
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002665 */
2666 msm_comm_put_vidc_buffer(inst, mbuf);
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002667 msm_comm_vb2_buffer_done(inst, vb2);
Qiwei Liuf7d96082017-10-19 17:51:09 +08002668 msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FBD);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002669 kref_put_mbuf(mbuf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002670
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002671exit:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002672 put_inst(inst);
2673}
2674
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002675void handle_cmd_response(enum hal_command_response cmd, void *data)
2676{
2677 dprintk(VIDC_DBG, "Command response = %d\n", cmd);
2678 switch (cmd) {
2679 case HAL_SYS_INIT_DONE:
2680 handle_sys_init_done(cmd, data);
2681 break;
2682 case HAL_SYS_RELEASE_RESOURCE_DONE:
2683 handle_sys_release_res_done(cmd, data);
2684 break;
2685 case HAL_SESSION_INIT_DONE:
2686 handle_session_init_done(cmd, data);
2687 break;
2688 case HAL_SESSION_PROPERTY_INFO:
2689 handle_session_prop_info(cmd, data);
2690 break;
2691 case HAL_SESSION_LOAD_RESOURCE_DONE:
2692 handle_load_resource_done(cmd, data);
2693 break;
2694 case HAL_SESSION_START_DONE:
2695 handle_start_done(cmd, data);
2696 break;
2697 case HAL_SESSION_ETB_DONE:
2698 handle_ebd(cmd, data);
2699 break;
2700 case HAL_SESSION_FTB_DONE:
2701 handle_fbd(cmd, data);
2702 break;
2703 case HAL_SESSION_STOP_DONE:
2704 handle_stop_done(cmd, data);
2705 break;
2706 case HAL_SESSION_RELEASE_RESOURCE_DONE:
2707 handle_release_res_done(cmd, data);
2708 break;
2709 case HAL_SESSION_END_DONE:
2710 case HAL_SESSION_ABORT_DONE:
2711 handle_session_close(cmd, data);
2712 break;
2713 case HAL_SESSION_EVENT_CHANGE:
2714 handle_event_change(cmd, data);
2715 break;
2716 case HAL_SESSION_FLUSH_DONE:
2717 handle_session_flush(cmd, data);
2718 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002719 case HAL_SYS_WATCHDOG_TIMEOUT:
2720 case HAL_SYS_ERROR:
2721 handle_sys_error(cmd, data);
2722 break;
2723 case HAL_SESSION_ERROR:
2724 handle_session_error(cmd, data);
2725 break;
2726 case HAL_SESSION_RELEASE_BUFFER_DONE:
2727 handle_session_release_buf_done(cmd, data);
2728 break;
2729 default:
2730 dprintk(VIDC_DBG, "response unhandled: %d\n", cmd);
2731 break;
2732 }
2733}
2734
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002735static inline enum msm_vidc_thermal_level msm_comm_vidc_thermal_level(int level)
2736{
2737 switch (level) {
2738 case 0:
2739 return VIDC_THERMAL_NORMAL;
2740 case 1:
2741 return VIDC_THERMAL_LOW;
2742 case 2:
2743 return VIDC_THERMAL_HIGH;
2744 default:
2745 return VIDC_THERMAL_CRITICAL;
2746 }
2747}
2748
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002749static bool is_core_turbo(struct msm_vidc_core *core, unsigned long freq)
2750{
2751 int i = 0;
Praneeth Paladugub71968b2015-08-19 20:47:57 -07002752 struct allowed_clock_rates_table *allowed_clks_tbl = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002753 u32 max_freq = 0;
2754
Praneeth Paladugub71968b2015-08-19 20:47:57 -07002755 allowed_clks_tbl = core->resources.allowed_clks_tbl;
2756 for (i = 0; i < core->resources.allowed_clks_tbl_size; i++) {
2757 if (max_freq < allowed_clks_tbl[i].clock_rate)
2758 max_freq = allowed_clks_tbl[i].clock_rate;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002759 }
2760 return freq >= max_freq;
2761}
2762
2763static bool is_thermal_permissible(struct msm_vidc_core *core)
2764{
2765 enum msm_vidc_thermal_level tl;
2766 unsigned long freq = 0;
2767 bool is_turbo = false;
2768
2769 if (!core->resources.thermal_mitigable)
2770 return true;
2771
2772 if (msm_vidc_thermal_mitigation_disabled) {
2773 dprintk(VIDC_DBG,
2774 "Thermal mitigation not enabled. debugfs %d\n",
2775 msm_vidc_thermal_mitigation_disabled);
2776 return true;
2777 }
2778
2779 tl = msm_comm_vidc_thermal_level(vidc_driver->thermal_level);
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07002780 freq = core->curr_freq;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002781
2782 is_turbo = is_core_turbo(core, freq);
2783 dprintk(VIDC_DBG,
2784 "Core freq %ld Thermal level %d Turbo mode %d\n",
2785 freq, tl, is_turbo);
2786
2787 if (is_turbo && tl >= VIDC_THERMAL_LOW) {
2788 dprintk(VIDC_ERR,
2789 "Video session not allowed. Turbo mode %d Thermal level %d\n",
2790 is_turbo, tl);
2791 return false;
2792 }
2793 return true;
2794}
2795
2796static int msm_comm_session_abort(struct msm_vidc_inst *inst)
2797{
2798 int rc = 0, abort_completion = 0;
2799 struct hfi_device *hdev;
2800
2801 if (!inst || !inst->core || !inst->core->device) {
2802 dprintk(VIDC_ERR, "%s invalid params\n", __func__);
2803 return -EINVAL;
2804 }
2805 hdev = inst->core->device;
2806 abort_completion = SESSION_MSG_INDEX(HAL_SESSION_ABORT_DONE);
2807
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07002808 dprintk(VIDC_WARN, "%s: inst %pK session %x\n", __func__,
2809 inst, hash32_ptr(inst->session));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002810 rc = call_hfi_op(hdev, session_abort, (void *)inst->session);
2811 if (rc) {
2812 dprintk(VIDC_ERR,
2813 "%s session_abort failed rc: %d\n", __func__, rc);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002814 goto exit;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002815 }
2816 rc = wait_for_completion_timeout(
2817 &inst->completions[abort_completion],
Praneeth Paladugud5bf7bc2017-05-29 23:41:04 -07002818 msecs_to_jiffies(
2819 inst->core->resources.msm_vidc_hw_rsp_timeout));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002820 if (!rc) {
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07002821 dprintk(VIDC_ERR, "%s: inst %pK session %x abort timed out\n",
2822 __func__, inst, hash32_ptr(inst->session));
Maheshwar Ajja99422322017-07-07 17:31:15 -07002823 msm_comm_generate_sys_error(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002824 rc = -EBUSY;
2825 } else {
2826 rc = 0;
2827 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002828exit:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002829 return rc;
2830}
2831
2832static void handle_thermal_event(struct msm_vidc_core *core)
2833{
2834 int rc = 0;
2835 struct msm_vidc_inst *inst;
2836
2837 if (!core || !core->device) {
2838 dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
2839 return;
2840 }
2841 mutex_lock(&core->lock);
2842 list_for_each_entry(inst, &core->instances, list) {
2843 if (!inst->session)
2844 continue;
2845
2846 mutex_unlock(&core->lock);
2847 if (inst->state >= MSM_VIDC_OPEN_DONE &&
2848 inst->state < MSM_VIDC_CLOSE_DONE) {
2849 dprintk(VIDC_WARN, "%s: abort inst %pK\n",
2850 __func__, inst);
2851 rc = msm_comm_session_abort(inst);
2852 if (rc) {
2853 dprintk(VIDC_ERR,
2854 "%s session_abort failed rc: %d\n",
2855 __func__, rc);
2856 goto err_sess_abort;
2857 }
2858 change_inst_state(inst, MSM_VIDC_CORE_INVALID);
2859 dprintk(VIDC_WARN,
2860 "%s Send sys error for inst %pK\n",
2861 __func__, inst);
2862 msm_vidc_queue_v4l2_event(inst,
2863 V4L2_EVENT_MSM_VIDC_SYS_ERROR);
2864 } else {
2865 msm_comm_generate_session_error(inst);
2866 }
2867 mutex_lock(&core->lock);
2868 }
2869 mutex_unlock(&core->lock);
2870 return;
2871
2872err_sess_abort:
2873 msm_comm_clean_notify_client(core);
2874}
2875
2876void msm_comm_handle_thermal_event(void)
2877{
2878 struct msm_vidc_core *core;
2879
2880 list_for_each_entry(core, &vidc_driver->cores, list) {
2881 if (!is_thermal_permissible(core)) {
2882 dprintk(VIDC_WARN,
2883 "Thermal level critical, stop all active sessions!\n");
2884 handle_thermal_event(core);
2885 }
2886 }
2887}
2888
2889int msm_comm_check_core_init(struct msm_vidc_core *core)
2890{
2891 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002892
2893 mutex_lock(&core->lock);
2894 if (core->state >= VIDC_CORE_INIT_DONE) {
2895 dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
2896 core->id, core->state);
2897 goto exit;
2898 }
2899 dprintk(VIDC_DBG, "Waiting for SYS_INIT_DONE\n");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002900 rc = wait_for_completion_timeout(
2901 &core->completions[SYS_MSG_INDEX(HAL_SYS_INIT_DONE)],
Praneeth Paladugud5bf7bc2017-05-29 23:41:04 -07002902 msecs_to_jiffies(core->resources.msm_vidc_hw_rsp_timeout));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002903 if (!rc) {
2904 dprintk(VIDC_ERR, "%s: Wait interrupted or timed out: %d\n",
2905 __func__, SYS_MSG_INDEX(HAL_SYS_INIT_DONE));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002906 rc = -EIO;
2907 goto exit;
2908 } else {
2909 core->state = VIDC_CORE_INIT_DONE;
2910 rc = 0;
2911 }
2912 dprintk(VIDC_DBG, "SYS_INIT_DONE!!!\n");
2913exit:
2914 mutex_unlock(&core->lock);
2915 return rc;
2916}
2917
2918static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
2919{
2920 int rc = 0;
2921
2922 rc = msm_comm_check_core_init(inst->core);
2923 if (rc) {
2924 dprintk(VIDC_ERR, "%s - failed to initialize core\n", __func__);
2925 msm_comm_generate_sys_error(inst);
2926 return rc;
2927 }
2928 change_inst_state(inst, MSM_VIDC_CORE_INIT_DONE);
2929 return rc;
2930}
2931
2932static int msm_comm_init_core(struct msm_vidc_inst *inst)
2933{
2934 int rc = 0;
2935 struct hfi_device *hdev;
2936 struct msm_vidc_core *core;
2937
2938 if (!inst || !inst->core || !inst->core->device)
2939 return -EINVAL;
2940
2941 core = inst->core;
2942 hdev = core->device;
2943 mutex_lock(&core->lock);
2944 if (core->state >= VIDC_CORE_INIT) {
2945 dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
2946 core->id, core->state);
2947 goto core_already_inited;
2948 }
2949 if (!core->capabilities) {
2950 core->capabilities = kzalloc(VIDC_MAX_SESSIONS *
2951 sizeof(struct msm_vidc_capability), GFP_KERNEL);
2952 if (!core->capabilities) {
2953 dprintk(VIDC_ERR,
2954 "%s: failed to allocate capabilities\n",
2955 __func__);
2956 rc = -ENOMEM;
2957 goto fail_cap_alloc;
2958 }
2959 } else {
2960 dprintk(VIDC_WARN,
2961 "%s: capabilities memory is expected to be freed\n",
2962 __func__);
2963 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002964 dprintk(VIDC_DBG, "%s: core %pK\n", __func__, core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002965 rc = call_hfi_op(hdev, core_init, hdev->hfi_device_data);
2966 if (rc) {
2967 dprintk(VIDC_ERR, "Failed to init core, id = %d\n",
2968 core->id);
2969 goto fail_core_init;
2970 }
2971 core->state = VIDC_CORE_INIT;
2972 core->smmu_fault_handled = false;
Maheshwar Ajja8382bec2017-08-11 13:41:35 -07002973 core->trigger_ssr = false;
2974
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002975core_already_inited:
2976 change_inst_state(inst, MSM_VIDC_CORE_INIT);
2977 mutex_unlock(&core->lock);
Praneeth Paladugub71968b2015-08-19 20:47:57 -07002978
2979 rc = msm_comm_scale_clocks_and_bus(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002980 return rc;
2981
2982fail_core_init:
2983 kfree(core->capabilities);
2984fail_cap_alloc:
2985 core->capabilities = NULL;
2986 core->state = VIDC_CORE_UNINIT;
2987 mutex_unlock(&core->lock);
2988 return rc;
2989}
2990
2991static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
2992{
2993 struct msm_vidc_core *core;
2994 struct hfi_device *hdev;
2995
2996 if (!inst || !inst->core || !inst->core->device) {
2997 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
2998 return -EINVAL;
2999 }
3000
3001 core = inst->core;
3002 hdev = core->device;
3003
3004 mutex_lock(&core->lock);
3005 if (core->state == VIDC_CORE_UNINIT) {
3006 dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
3007 core->id, core->state);
3008 goto core_already_uninited;
3009 }
3010 mutex_unlock(&core->lock);
3011
3012 msm_comm_scale_clocks_and_bus(inst);
3013
3014 mutex_lock(&core->lock);
3015
3016 if (!core->resources.never_unload_fw) {
3017 cancel_delayed_work(&core->fw_unload_work);
3018
3019 /*
3020 * Delay unloading of firmware. This is useful
3021 * in avoiding firmware download delays in cases where we
3022 * will have a burst of back to back video playback sessions
3023 * e.g. thumbnail generation.
3024 */
3025 schedule_delayed_work(&core->fw_unload_work,
Maheshwar Ajja99422322017-07-07 17:31:15 -07003026 msecs_to_jiffies(core->state == VIDC_CORE_INIT_DONE ?
3027 core->resources.msm_vidc_firmware_unload_delay : 0));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003028
3029 dprintk(VIDC_DBG, "firmware unload delayed by %u ms\n",
Maheshwar Ajja99422322017-07-07 17:31:15 -07003030 core->state == VIDC_CORE_INIT_DONE ?
3031 core->resources.msm_vidc_firmware_unload_delay : 0);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003032 }
3033
3034core_already_uninited:
3035 change_inst_state(inst, MSM_VIDC_CORE_UNINIT);
3036 mutex_unlock(&core->lock);
3037 return 0;
3038}
3039
3040int msm_comm_force_cleanup(struct msm_vidc_inst *inst)
3041{
3042 msm_comm_kill_session(inst);
3043 return msm_vidc_deinit_core(inst);
3044}
3045
Maheshwar Ajjac35d7fc2017-09-01 16:44:46 -07003046static int msm_comm_session_init_done(int flipped_state,
3047 struct msm_vidc_inst *inst)
3048{
3049 int rc;
3050
3051 dprintk(VIDC_DBG, "inst %pK: waiting for session init done\n", inst);
3052 rc = wait_for_state(inst, flipped_state, MSM_VIDC_OPEN_DONE,
3053 HAL_SESSION_INIT_DONE);
3054 if (rc) {
3055 dprintk(VIDC_ERR, "Session init failed for inst %pK\n", inst);
3056 msm_comm_generate_sys_error(inst);
3057 return rc;
3058 }
3059
3060 return rc;
3061}
3062
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003063static int msm_comm_session_init(int flipped_state,
3064 struct msm_vidc_inst *inst)
3065{
3066 int rc = 0;
3067 int fourcc = 0;
3068 struct hfi_device *hdev;
3069
3070 if (!inst || !inst->core || !inst->core->device) {
3071 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3072 return -EINVAL;
3073 }
3074 hdev = inst->core->device;
3075
3076 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_OPEN)) {
3077 dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
3078 inst, inst->state);
3079 goto exit;
3080 }
3081 if (inst->session_type == MSM_VIDC_DECODER) {
3082 fourcc = inst->fmts[OUTPUT_PORT].fourcc;
3083 } else if (inst->session_type == MSM_VIDC_ENCODER) {
3084 fourcc = inst->fmts[CAPTURE_PORT].fourcc;
3085 } else {
3086 dprintk(VIDC_ERR, "Invalid session\n");
3087 return -EINVAL;
3088 }
3089
Praneeth Paladugub71968b2015-08-19 20:47:57 -07003090 msm_comm_init_clocks_and_bus_data(inst);
3091
Maheshwar Ajja99422322017-07-07 17:31:15 -07003092 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003093 rc = call_hfi_op(hdev, session_init, hdev->hfi_device_data,
3094 inst, get_hal_domain(inst->session_type),
3095 get_hal_codec(fourcc),
3096 &inst->session);
3097
3098 if (rc || !inst->session) {
3099 dprintk(VIDC_ERR,
3100 "Failed to call session init for: %pK, %pK, %d, %d\n",
3101 inst->core->device, inst,
3102 inst->session_type, fourcc);
3103 rc = -EINVAL;
3104 goto exit;
3105 }
3106 change_inst_state(inst, MSM_VIDC_OPEN);
3107exit:
3108 return rc;
3109}
3110
3111static void msm_vidc_print_running_insts(struct msm_vidc_core *core)
3112{
3113 struct msm_vidc_inst *temp;
3114
3115 dprintk(VIDC_ERR, "Running instances:\n");
3116 dprintk(VIDC_ERR, "%4s|%4s|%4s|%4s|%4s\n",
3117 "type", "w", "h", "fps", "prop");
3118
3119 mutex_lock(&core->lock);
3120 list_for_each_entry(temp, &core->instances, list) {
3121 if (temp->state >= MSM_VIDC_OPEN_DONE &&
3122 temp->state < MSM_VIDC_STOP_DONE) {
3123 char properties[4] = "";
3124
3125 if (is_thumbnail_session(temp))
3126 strlcat(properties, "N", sizeof(properties));
3127
3128 if (msm_comm_turbo_session(temp))
3129 strlcat(properties, "T", sizeof(properties));
3130
3131 dprintk(VIDC_ERR, "%4d|%4d|%4d|%4d|%4s\n",
3132 temp->session_type,
3133 max(temp->prop.width[CAPTURE_PORT],
3134 temp->prop.width[OUTPUT_PORT]),
3135 max(temp->prop.height[CAPTURE_PORT],
3136 temp->prop.height[OUTPUT_PORT]),
3137 temp->prop.fps, properties);
3138 }
3139 }
3140 mutex_unlock(&core->lock);
3141}
3142
3143static int msm_vidc_load_resources(int flipped_state,
3144 struct msm_vidc_inst *inst)
3145{
3146 int rc = 0;
3147 struct hfi_device *hdev;
3148 int num_mbs_per_sec = 0, max_load_adj = 0;
3149 struct msm_vidc_core *core;
3150 enum load_calc_quirks quirks = LOAD_CALC_IGNORE_TURBO_LOAD |
3151 LOAD_CALC_IGNORE_THUMBNAIL_LOAD |
3152 LOAD_CALC_IGNORE_NON_REALTIME_LOAD;
3153
3154 if (!inst || !inst->core || !inst->core->device) {
3155 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3156 return -EINVAL;
3157 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003158 if (inst->state == MSM_VIDC_CORE_INVALID) {
3159 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07003160 "%s: inst %pK is in invalid state\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003161 return -EINVAL;
3162 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003163 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
3164 dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
3165 inst, inst->state);
3166 goto exit;
3167 }
3168 core = inst->core;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003169
3170 num_mbs_per_sec =
3171 msm_comm_get_load(core, MSM_VIDC_DECODER, quirks) +
3172 msm_comm_get_load(core, MSM_VIDC_ENCODER, quirks);
3173
3174 max_load_adj = core->resources.max_load +
3175 inst->capability.mbs_per_frame.max;
3176
3177 if (num_mbs_per_sec > max_load_adj) {
3178 dprintk(VIDC_ERR, "HW is overloaded, needed: %d max: %d\n",
3179 num_mbs_per_sec, max_load_adj);
3180 msm_vidc_print_running_insts(core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003181 msm_comm_kill_session(inst);
3182 return -EBUSY;
3183 }
3184
3185 hdev = core->device;
Maheshwar Ajja99422322017-07-07 17:31:15 -07003186 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003187 rc = call_hfi_op(hdev, session_load_res, (void *) inst->session);
3188 if (rc) {
3189 dprintk(VIDC_ERR,
3190 "Failed to send load resources\n");
3191 goto exit;
3192 }
3193 change_inst_state(inst, MSM_VIDC_LOAD_RESOURCES);
3194exit:
3195 return rc;
3196}
3197
3198static int msm_vidc_start(int flipped_state, struct msm_vidc_inst *inst)
3199{
3200 int rc = 0;
3201 struct hfi_device *hdev;
3202
3203 if (!inst || !inst->core || !inst->core->device) {
3204 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3205 return -EINVAL;
3206 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003207 if (inst->state == MSM_VIDC_CORE_INVALID) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003208 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07003209 "%s: inst %pK is in invalid\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003210 return -EINVAL;
3211 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003212 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_START)) {
3213 dprintk(VIDC_INFO,
3214 "inst: %pK is already in state: %d\n",
3215 inst, inst->state);
3216 goto exit;
3217 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003218 hdev = inst->core->device;
3219 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003220 rc = call_hfi_op(hdev, session_start, (void *) inst->session);
3221 if (rc) {
3222 dprintk(VIDC_ERR,
3223 "Failed to send start\n");
3224 goto exit;
3225 }
3226 change_inst_state(inst, MSM_VIDC_START);
3227exit:
3228 return rc;
3229}
3230
3231static int msm_vidc_stop(int flipped_state, struct msm_vidc_inst *inst)
3232{
3233 int rc = 0;
3234 struct hfi_device *hdev;
3235
3236 if (!inst || !inst->core || !inst->core->device) {
3237 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3238 return -EINVAL;
3239 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003240 if (inst->state == MSM_VIDC_CORE_INVALID) {
3241 dprintk(VIDC_ERR,
3242 "%s: inst %pK is in invalid state\n", __func__, inst);
3243 return -EINVAL;
3244 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003245 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_STOP)) {
3246 dprintk(VIDC_INFO,
3247 "inst: %pK is already in state: %d\n",
3248 inst, inst->state);
3249 goto exit;
3250 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003251 hdev = inst->core->device;
3252 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003253 rc = call_hfi_op(hdev, session_stop, (void *) inst->session);
3254 if (rc) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07003255 dprintk(VIDC_ERR, "%s: inst %pK session_stop failed\n",
3256 __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003257 goto exit;
3258 }
3259 change_inst_state(inst, MSM_VIDC_STOP);
3260exit:
3261 return rc;
3262}
3263
3264static int msm_vidc_release_res(int flipped_state, struct msm_vidc_inst *inst)
3265{
3266 int rc = 0;
3267 struct hfi_device *hdev;
3268
3269 if (!inst || !inst->core || !inst->core->device) {
3270 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3271 return -EINVAL;
3272 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003273 if (inst->state == MSM_VIDC_CORE_INVALID) {
3274 dprintk(VIDC_ERR,
3275 "%s: inst %pK is in invalid state\n", __func__, inst);
3276 return -EINVAL;
3277 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003278 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_RELEASE_RESOURCES)) {
3279 dprintk(VIDC_INFO,
3280 "inst: %pK is already in state: %d\n",
3281 inst, inst->state);
3282 goto exit;
3283 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003284 hdev = inst->core->device;
3285 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003286 rc = call_hfi_op(hdev, session_release_res, (void *) inst->session);
3287 if (rc) {
3288 dprintk(VIDC_ERR,
3289 "Failed to send release resources\n");
3290 goto exit;
3291 }
3292 change_inst_state(inst, MSM_VIDC_RELEASE_RESOURCES);
3293exit:
3294 return rc;
3295}
3296
3297static int msm_comm_session_close(int flipped_state,
3298 struct msm_vidc_inst *inst)
3299{
3300 int rc = 0;
3301 struct hfi_device *hdev;
3302
3303 if (!inst || !inst->core || !inst->core->device) {
3304 dprintk(VIDC_ERR, "%s invalid params\n", __func__);
3305 return -EINVAL;
3306 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003307 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_CLOSE)) {
3308 dprintk(VIDC_INFO,
3309 "inst: %pK is already in state: %d\n",
3310 inst, inst->state);
3311 goto exit;
3312 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003313 hdev = inst->core->device;
3314 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003315 rc = call_hfi_op(hdev, session_end, (void *) inst->session);
3316 if (rc) {
3317 dprintk(VIDC_ERR,
3318 "Failed to send close\n");
3319 goto exit;
3320 }
3321 change_inst_state(inst, MSM_VIDC_CLOSE);
3322exit:
3323 return rc;
3324}
3325
3326int msm_comm_suspend(int core_id)
3327{
3328 struct hfi_device *hdev;
3329 struct msm_vidc_core *core;
3330 int rc = 0;
3331
3332 core = get_vidc_core(core_id);
3333 if (!core) {
3334 dprintk(VIDC_ERR,
3335 "%s: Failed to find core for core_id = %d\n",
3336 __func__, core_id);
3337 return -EINVAL;
3338 }
3339
3340 hdev = (struct hfi_device *)core->device;
3341 if (!hdev) {
3342 dprintk(VIDC_ERR, "%s Invalid device handle\n", __func__);
3343 return -EINVAL;
3344 }
3345
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003346 rc = call_hfi_op(hdev, suspend, hdev->hfi_device_data);
3347 if (rc)
3348 dprintk(VIDC_WARN, "Failed to suspend\n");
Maheshwar Ajja8f604712017-10-13 14:56:43 -07003349
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003350 return rc;
3351}
3352
3353static int get_flipped_state(int present_state,
3354 int desired_state)
3355{
3356 int flipped_state = present_state;
3357
3358 if (flipped_state < MSM_VIDC_STOP
3359 && desired_state > MSM_VIDC_STOP) {
3360 flipped_state = MSM_VIDC_STOP + (MSM_VIDC_STOP - flipped_state);
3361 flipped_state &= 0xFFFE;
3362 flipped_state = flipped_state - 1;
3363 } else if (flipped_state > MSM_VIDC_STOP
3364 && desired_state < MSM_VIDC_STOP) {
3365 flipped_state = MSM_VIDC_STOP -
3366 (flipped_state - MSM_VIDC_STOP + 1);
3367 flipped_state &= 0xFFFE;
3368 flipped_state = flipped_state - 1;
3369 }
3370 return flipped_state;
3371}
3372
3373struct hal_buffer_requirements *get_buff_req_buffer(
3374 struct msm_vidc_inst *inst, enum hal_buffer buffer_type)
3375{
3376 int i;
3377
3378 for (i = 0; i < HAL_BUFFER_MAX; i++) {
3379 if (inst->buff_req.buffer[i].buffer_type == buffer_type)
3380 return &inst->buff_req.buffer[i];
3381 }
3382 return NULL;
3383}
3384
3385static int set_output_buffers(struct msm_vidc_inst *inst,
3386 enum hal_buffer buffer_type)
3387{
3388 int rc = 0;
Chinmay Sawarkarf8ed8422017-09-29 15:51:51 -07003389 struct internal_buf *binfo = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003390 u32 smem_flags = 0, buffer_size;
3391 struct hal_buffer_requirements *output_buf, *extradata_buf;
3392 int i;
3393 struct hfi_device *hdev;
3394 struct hal_buffer_size_minimum b;
3395
3396 hdev = inst->core->device;
3397
3398 output_buf = get_buff_req_buffer(inst, buffer_type);
3399 if (!output_buf) {
3400 dprintk(VIDC_DBG,
3401 "This output buffer not required, buffer_type: %x\n",
3402 buffer_type);
3403 return 0;
3404 }
Praneeth Paladugu86c7c242017-07-16 19:44:42 -07003405
3406 /* For DPB buffers, Always use FW count */
3407 output_buf->buffer_count_actual = output_buf->buffer_count_min_host =
3408 output_buf->buffer_count_min;
3409
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003410 dprintk(VIDC_DBG,
3411 "output: num = %d, size = %d\n",
3412 output_buf->buffer_count_actual,
3413 output_buf->buffer_size);
3414
3415 buffer_size = output_buf->buffer_size;
3416 b.buffer_type = buffer_type;
3417 b.buffer_size = buffer_size;
3418 rc = call_hfi_op(hdev, session_set_property,
3419 inst->session, HAL_PARAM_BUFFER_SIZE_MINIMUM,
3420 &b);
3421
3422 extradata_buf = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_OUTPUT);
3423 if (extradata_buf) {
3424 dprintk(VIDC_DBG,
3425 "extradata: num = %d, size = %d\n",
3426 extradata_buf->buffer_count_actual,
3427 extradata_buf->buffer_size);
3428 buffer_size += extradata_buf->buffer_size;
3429 } else {
3430 dprintk(VIDC_DBG,
3431 "This extradata buffer not required, buffer_type: %x\n",
3432 buffer_type);
3433 }
3434
3435 if (inst->flags & VIDC_SECURE)
3436 smem_flags |= SMEM_SECURE;
3437
3438 if (output_buf->buffer_size) {
3439 for (i = 0; i < output_buf->buffer_count_actual;
3440 i++) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003441 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
3442 if (!binfo) {
3443 dprintk(VIDC_ERR, "Out of memory\n");
3444 rc = -ENOMEM;
3445 goto fail_kzalloc;
3446 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003447 rc = msm_comm_smem_alloc(inst,
3448 buffer_size, 1, smem_flags,
3449 buffer_type, 0, &binfo->smem);
3450 if (rc) {
3451 dprintk(VIDC_ERR,
3452 "Failed to allocate output memory\n");
3453 goto err_no_mem;
3454 }
3455 rc = msm_comm_smem_cache_operations(inst,
3456 &binfo->smem, SMEM_CACHE_CLEAN);
3457 if (rc) {
3458 dprintk(VIDC_WARN,
3459 "Failed to clean cache may cause undefined behavior\n");
3460 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003461 binfo->buffer_type = buffer_type;
3462 binfo->buffer_ownership = DRIVER;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003463 dprintk(VIDC_DBG, "Output buffer address: %#x\n",
3464 binfo->smem.device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003465
3466 if (inst->buffer_mode_set[CAPTURE_PORT] ==
3467 HAL_BUFFER_MODE_STATIC) {
3468 struct vidc_buffer_addr_info buffer_info = {0};
3469
3470 buffer_info.buffer_size =
3471 output_buf->buffer_size;
3472 buffer_info.buffer_type = buffer_type;
3473 buffer_info.num_buffers = 1;
3474 buffer_info.align_device_addr =
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003475 binfo->smem.device_addr;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003476 buffer_info.extradata_addr =
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003477 binfo->smem.device_addr +
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003478 output_buf->buffer_size;
3479 if (extradata_buf)
3480 buffer_info.extradata_size =
3481 extradata_buf->buffer_size;
3482 rc = call_hfi_op(hdev, session_set_buffers,
3483 (void *) inst->session, &buffer_info);
3484 if (rc) {
3485 dprintk(VIDC_ERR,
3486 "%s : session_set_buffers failed\n",
3487 __func__);
3488 goto fail_set_buffers;
3489 }
3490 }
3491 mutex_lock(&inst->outputbufs.lock);
3492 list_add_tail(&binfo->list, &inst->outputbufs.list);
3493 mutex_unlock(&inst->outputbufs.lock);
3494 }
3495 }
3496 return rc;
3497fail_set_buffers:
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003498 msm_comm_smem_free(inst, &binfo->smem);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003499err_no_mem:
Chinmay Sawarkarf8ed8422017-09-29 15:51:51 -07003500 kfree(binfo);
3501fail_kzalloc:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003502 return rc;
3503}
3504
3505static inline char *get_buffer_name(enum hal_buffer buffer_type)
3506{
3507 switch (buffer_type) {
3508 case HAL_BUFFER_INPUT: return "input";
3509 case HAL_BUFFER_OUTPUT: return "output";
3510 case HAL_BUFFER_OUTPUT2: return "output_2";
3511 case HAL_BUFFER_EXTRADATA_INPUT: return "input_extra";
3512 case HAL_BUFFER_EXTRADATA_OUTPUT: return "output_extra";
3513 case HAL_BUFFER_EXTRADATA_OUTPUT2: return "output2_extra";
3514 case HAL_BUFFER_INTERNAL_SCRATCH: return "scratch";
3515 case HAL_BUFFER_INTERNAL_SCRATCH_1: return "scratch_1";
3516 case HAL_BUFFER_INTERNAL_SCRATCH_2: return "scratch_2";
3517 case HAL_BUFFER_INTERNAL_PERSIST: return "persist";
3518 case HAL_BUFFER_INTERNAL_PERSIST_1: return "persist_1";
3519 case HAL_BUFFER_INTERNAL_CMD_QUEUE: return "queue";
3520 default: return "????";
3521 }
3522}
3523
3524static int set_internal_buf_on_fw(struct msm_vidc_inst *inst,
3525 enum hal_buffer buffer_type,
3526 struct msm_smem *handle, bool reuse)
3527{
3528 struct vidc_buffer_addr_info buffer_info;
3529 struct hfi_device *hdev;
3530 int rc = 0;
3531
3532 if (!inst || !inst->core || !inst->core->device || !handle) {
3533 dprintk(VIDC_ERR, "%s - invalid params\n", __func__);
3534 return -EINVAL;
3535 }
3536
3537 hdev = inst->core->device;
3538
3539 rc = msm_comm_smem_cache_operations(inst,
3540 handle, SMEM_CACHE_CLEAN);
3541 if (rc) {
3542 dprintk(VIDC_WARN,
3543 "Failed to clean cache. Undefined behavior\n");
3544 }
3545
3546 buffer_info.buffer_size = handle->size;
3547 buffer_info.buffer_type = buffer_type;
3548 buffer_info.num_buffers = 1;
3549 buffer_info.align_device_addr = handle->device_addr;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003550 dprintk(VIDC_DBG, "%s %s buffer : %x\n",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003551 reuse ? "Reusing" : "Allocated",
3552 get_buffer_name(buffer_type),
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003553 buffer_info.align_device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003554
3555 rc = call_hfi_op(hdev, session_set_buffers,
3556 (void *) inst->session, &buffer_info);
3557 if (rc) {
3558 dprintk(VIDC_ERR,
3559 "vidc_hal_session_set_buffers failed\n");
3560 return rc;
3561 }
3562 return 0;
3563}
3564
3565static bool reuse_internal_buffers(struct msm_vidc_inst *inst,
3566 enum hal_buffer buffer_type, struct msm_vidc_list *buf_list)
3567{
3568 struct internal_buf *buf;
3569 int rc = 0;
3570 bool reused = false;
3571
3572 if (!inst || !buf_list) {
3573 dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
3574 return false;
3575 }
3576
3577 mutex_lock(&buf_list->lock);
3578 list_for_each_entry(buf, &buf_list->list, list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003579 if (buf->buffer_type != buffer_type)
3580 continue;
3581
3582 /*
3583 * Persist buffer size won't change with resolution. If they
3584 * are in queue means that they are already allocated and
3585 * given to HW. HW can use them without reallocation. These
3586 * buffers are not released as part of port reconfig. So
3587 * driver no need to set them again.
3588 */
3589
3590 if (buffer_type != HAL_BUFFER_INTERNAL_PERSIST
3591 && buffer_type != HAL_BUFFER_INTERNAL_PERSIST_1) {
3592
3593 rc = set_internal_buf_on_fw(inst, buffer_type,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003594 &buf->smem, true);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003595 if (rc) {
3596 dprintk(VIDC_ERR,
3597 "%s: session_set_buffers failed\n",
3598 __func__);
3599 reused = false;
3600 break;
3601 }
3602 }
3603 reused = true;
3604 dprintk(VIDC_DBG,
3605 "Re-using internal buffer type : %d\n", buffer_type);
3606 }
3607 mutex_unlock(&buf_list->lock);
3608 return reused;
3609}
3610
3611static int allocate_and_set_internal_bufs(struct msm_vidc_inst *inst,
3612 struct hal_buffer_requirements *internal_bufreq,
3613 struct msm_vidc_list *buf_list)
3614{
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003615 struct internal_buf *binfo;
3616 u32 smem_flags = 0;
3617 int rc = 0;
3618 int i = 0;
3619
3620 if (!inst || !internal_bufreq || !buf_list)
3621 return -EINVAL;
3622
3623 if (!internal_bufreq->buffer_size)
3624 return 0;
3625
3626 if (inst->flags & VIDC_SECURE)
3627 smem_flags |= SMEM_SECURE;
3628
3629 for (i = 0; i < internal_bufreq->buffer_count_actual; i++) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003630 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
3631 if (!binfo) {
3632 dprintk(VIDC_ERR, "Out of memory\n");
3633 rc = -ENOMEM;
3634 goto fail_kzalloc;
3635 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003636 rc = msm_comm_smem_alloc(inst, internal_bufreq->buffer_size,
3637 1, smem_flags, internal_bufreq->buffer_type,
3638 0, &binfo->smem);
3639 if (rc) {
3640 dprintk(VIDC_ERR,
3641 "Failed to allocate scratch memory\n");
3642 goto err_no_mem;
3643 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003644
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003645 binfo->buffer_type = internal_bufreq->buffer_type;
3646
3647 rc = set_internal_buf_on_fw(inst, internal_bufreq->buffer_type,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003648 &binfo->smem, false);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003649 if (rc)
3650 goto fail_set_buffers;
3651
3652 mutex_lock(&buf_list->lock);
3653 list_add_tail(&binfo->list, &buf_list->list);
3654 mutex_unlock(&buf_list->lock);
3655 }
3656 return rc;
3657
3658fail_set_buffers:
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003659 msm_comm_smem_free(inst, &binfo->smem);
3660err_no_mem:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003661 kfree(binfo);
3662fail_kzalloc:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003663 return rc;
3664
3665}
3666
3667static int set_internal_buffers(struct msm_vidc_inst *inst,
3668 enum hal_buffer buffer_type, struct msm_vidc_list *buf_list)
3669{
3670 struct hal_buffer_requirements *internal_buf;
3671
3672 internal_buf = get_buff_req_buffer(inst, buffer_type);
3673 if (!internal_buf) {
3674 dprintk(VIDC_DBG,
3675 "This internal buffer not required, buffer_type: %x\n",
3676 buffer_type);
3677 return 0;
3678 }
3679
3680 dprintk(VIDC_DBG, "Buffer type %s: num = %d, size = %d\n",
3681 get_buffer_name(buffer_type),
3682 internal_buf->buffer_count_actual, internal_buf->buffer_size);
3683
3684 /*
3685 * Try reusing existing internal buffers first.
3686 * If it's not possible to reuse, allocate new buffers.
3687 */
3688 if (reuse_internal_buffers(inst, buffer_type, buf_list))
3689 return 0;
3690
3691 return allocate_and_set_internal_bufs(inst, internal_buf,
3692 buf_list);
3693}
3694
3695int msm_comm_try_state(struct msm_vidc_inst *inst, int state)
3696{
3697 int rc = 0;
3698 int flipped_state;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003699
3700 if (!inst) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07003701 dprintk(VIDC_ERR, "%s: invalid params %pK", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003702 return -EINVAL;
3703 }
3704 dprintk(VIDC_DBG,
3705 "Trying to move inst: %pK from: %#x to %#x\n",
3706 inst, inst->state, state);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003707
3708 mutex_lock(&inst->sync_lock);
3709 if (inst->state == MSM_VIDC_CORE_INVALID) {
3710 dprintk(VIDC_ERR, "%s: inst %pK is in invalid\n",
3711 __func__, inst);
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07003712 rc = -EINVAL;
3713 goto exit;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003714 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003715
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003716 flipped_state = get_flipped_state(inst->state, state);
3717 dprintk(VIDC_DBG,
3718 "flipped_state = %#x\n", flipped_state);
3719 switch (flipped_state) {
3720 case MSM_VIDC_CORE_UNINIT_DONE:
3721 case MSM_VIDC_CORE_INIT:
3722 rc = msm_comm_init_core(inst);
3723 if (rc || state <= get_flipped_state(inst->state, state))
3724 break;
3725 case MSM_VIDC_CORE_INIT_DONE:
3726 rc = msm_comm_init_core_done(inst);
3727 if (rc || state <= get_flipped_state(inst->state, state))
3728 break;
3729 case MSM_VIDC_OPEN:
3730 rc = msm_comm_session_init(flipped_state, inst);
3731 if (rc || state <= get_flipped_state(inst->state, state))
3732 break;
3733 case MSM_VIDC_OPEN_DONE:
Maheshwar Ajjac35d7fc2017-09-01 16:44:46 -07003734 rc = msm_comm_session_init_done(flipped_state, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003735 if (rc || state <= get_flipped_state(inst->state, state))
3736 break;
3737 case MSM_VIDC_LOAD_RESOURCES:
3738 rc = msm_vidc_load_resources(flipped_state, inst);
3739 if (rc || state <= get_flipped_state(inst->state, state))
3740 break;
3741 case MSM_VIDC_LOAD_RESOURCES_DONE:
3742 case MSM_VIDC_START:
3743 rc = msm_vidc_start(flipped_state, inst);
3744 if (rc || state <= get_flipped_state(inst->state, state))
3745 break;
3746 case MSM_VIDC_START_DONE:
3747 rc = wait_for_state(inst, flipped_state, MSM_VIDC_START_DONE,
3748 HAL_SESSION_START_DONE);
3749 if (rc || state <= get_flipped_state(inst->state, state))
3750 break;
3751 case MSM_VIDC_STOP:
3752 rc = msm_vidc_stop(flipped_state, inst);
3753 if (rc || state <= get_flipped_state(inst->state, state))
3754 break;
3755 case MSM_VIDC_STOP_DONE:
3756 rc = wait_for_state(inst, flipped_state, MSM_VIDC_STOP_DONE,
3757 HAL_SESSION_STOP_DONE);
3758 if (rc || state <= get_flipped_state(inst->state, state))
3759 break;
3760 dprintk(VIDC_DBG, "Moving to Stop Done state\n");
3761 case MSM_VIDC_RELEASE_RESOURCES:
3762 rc = msm_vidc_release_res(flipped_state, inst);
3763 if (rc || state <= get_flipped_state(inst->state, state))
3764 break;
3765 case MSM_VIDC_RELEASE_RESOURCES_DONE:
3766 rc = wait_for_state(inst, flipped_state,
3767 MSM_VIDC_RELEASE_RESOURCES_DONE,
3768 HAL_SESSION_RELEASE_RESOURCE_DONE);
3769 if (rc || state <= get_flipped_state(inst->state, state))
3770 break;
3771 dprintk(VIDC_DBG,
3772 "Moving to release resources done state\n");
3773 case MSM_VIDC_CLOSE:
3774 rc = msm_comm_session_close(flipped_state, inst);
3775 if (rc || state <= get_flipped_state(inst->state, state))
3776 break;
3777 case MSM_VIDC_CLOSE_DONE:
3778 rc = wait_for_state(inst, flipped_state, MSM_VIDC_CLOSE_DONE,
3779 HAL_SESSION_END_DONE);
3780 if (rc || state <= get_flipped_state(inst->state, state))
3781 break;
3782 msm_comm_session_clean(inst);
3783 case MSM_VIDC_CORE_UNINIT:
3784 case MSM_VIDC_CORE_INVALID:
3785 dprintk(VIDC_DBG, "Sending core uninit\n");
3786 rc = msm_vidc_deinit_core(inst);
3787 if (rc || state == get_flipped_state(inst->state, state))
3788 break;
3789 default:
3790 dprintk(VIDC_ERR, "State not recognized\n");
3791 rc = -EINVAL;
3792 break;
3793 }
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07003794
3795exit:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003796 mutex_unlock(&inst->sync_lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003797
3798 if (rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003799 dprintk(VIDC_ERR,
3800 "Failed to move from state: %d to %d\n",
3801 inst->state, state);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003802 msm_comm_kill_session(inst);
3803 } else {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003804 trace_msm_vidc_common_state_change((void *)inst,
3805 inst->state, state);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003806 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003807 return rc;
3808}
3809
Praneeth Paladugu54865842017-08-18 01:45:27 -07003810int msm_vidc_send_pending_eos_buffers(struct msm_vidc_inst *inst)
3811{
3812 struct vidc_frame_data data = {0};
3813 struct hfi_device *hdev;
3814 struct eos_buf *binfo = NULL, *temp = NULL;
3815 int rc = 0;
3816
3817 if (!inst || !inst->core || !inst->core->device) {
3818 dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
3819 return -EINVAL;
3820 }
3821
3822 mutex_lock(&inst->eosbufs.lock);
3823 list_for_each_entry_safe(binfo, temp, &inst->eosbufs.list, list) {
3824 data.alloc_len = binfo->smem.size;
3825 data.device_addr = binfo->smem.device_addr;
3826 data.clnt_data = data.device_addr;
3827 data.buffer_type = HAL_BUFFER_INPUT;
3828 data.filled_len = 0;
3829 data.offset = 0;
3830 data.flags = HAL_BUFFERFLAG_EOS;
3831 data.timestamp = LLONG_MAX;
3832 data.extradata_addr = data.device_addr;
3833 data.extradata_size = 0;
Maria Yu5d853f82017-09-26 16:13:19 +08003834 dprintk(VIDC_DBG, "Queueing EOS buffer 0x%x\n",
3835 data.device_addr);
Praneeth Paladugu54865842017-08-18 01:45:27 -07003836 hdev = inst->core->device;
3837
3838 rc = call_hfi_op(hdev, session_etb, inst->session,
3839 &data);
3840 }
3841 mutex_unlock(&inst->eosbufs.lock);
3842
3843 return rc;
3844}
3845
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003846int msm_vidc_comm_cmd(void *instance, union msm_v4l2_cmd *cmd)
3847{
3848 struct msm_vidc_inst *inst = instance;
3849 struct v4l2_decoder_cmd *dec = NULL;
3850 struct v4l2_encoder_cmd *enc = NULL;
3851 struct msm_vidc_core *core;
3852 int which_cmd = 0, flags = 0, rc = 0;
3853
3854 if (!inst || !inst->core || !cmd) {
3855 dprintk(VIDC_ERR, "%s invalid params\n", __func__);
3856 return -EINVAL;
3857 }
3858 core = inst->core;
3859 if (inst->session_type == MSM_VIDC_ENCODER) {
3860 enc = (struct v4l2_encoder_cmd *)cmd;
3861 which_cmd = enc->cmd;
3862 flags = enc->flags;
3863 } else if (inst->session_type == MSM_VIDC_DECODER) {
3864 dec = (struct v4l2_decoder_cmd *)cmd;
3865 which_cmd = dec->cmd;
3866 flags = dec->flags;
3867 }
3868
3869
3870 switch (which_cmd) {
3871 case V4L2_QCOM_CMD_FLUSH:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003872 rc = msm_comm_flush(inst, flags);
3873 if (rc) {
3874 dprintk(VIDC_ERR,
3875 "Failed to flush buffers: %d\n", rc);
3876 }
3877 break;
3878 case V4L2_DEC_QCOM_CMD_RECONFIG_HINT:
3879 {
3880 u32 *ptr = NULL;
3881 struct hal_buffer_requirements *output_buf;
3882
3883 rc = msm_comm_try_get_bufreqs(inst);
3884 if (rc) {
3885 dprintk(VIDC_ERR,
3886 "Getting buffer requirements failed: %d\n",
3887 rc);
3888 break;
3889 }
3890
3891 output_buf = get_buff_req_buffer(inst,
3892 msm_comm_get_hal_output_buffer(inst));
3893 if (output_buf) {
3894 if (dec) {
3895 ptr = (u32 *)dec->raw.data;
3896 ptr[0] = output_buf->buffer_size;
3897 ptr[1] = output_buf->buffer_count_actual;
3898 dprintk(VIDC_DBG,
3899 "Reconfig hint, size is %u, count is %u\n",
3900 ptr[0], ptr[1]);
3901 } else {
3902 dprintk(VIDC_ERR, "Null decoder\n");
3903 }
3904 } else {
3905 dprintk(VIDC_DBG,
3906 "This output buffer not required, buffer_type: %x\n",
3907 HAL_BUFFER_OUTPUT);
3908 }
3909 break;
3910 }
Umesh Pandeybb3fad02017-03-31 16:49:42 -07003911 case V4L2_QCOM_CMD_SESSION_CONTINUE:
3912 {
3913 rc = msm_comm_session_continue(inst);
3914 break;
3915 }
Praneeth Paladugu940228f2017-08-02 13:52:13 -07003916 /* This case also for V4L2_ENC_CMD_STOP */
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003917 case V4L2_DEC_CMD_STOP:
3918 {
Praneeth Paladugu54865842017-08-18 01:45:27 -07003919 struct eos_buf *binfo = NULL;
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003920 u32 smem_flags = 0;
3921
Maheshwar Ajja1f9676d2018-01-18 11:55:30 -08003922 if (inst->state != MSM_VIDC_START_DONE) {
3923 dprintk(VIDC_DBG,
3924 "Inst = %pK is not ready for EOS\n", inst);
3925 break;
3926 }
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003927
3928 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
3929 if (!binfo) {
3930 dprintk(VIDC_ERR, "%s: Out of memory\n", __func__);
3931 rc = -ENOMEM;
Maheshwar Ajja1f9676d2018-01-18 11:55:30 -08003932 break;
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003933 }
3934
3935 if (inst->flags & VIDC_SECURE)
3936 smem_flags |= SMEM_SECURE;
3937
3938 rc = msm_comm_smem_alloc(inst,
3939 SZ_4K, 1, smem_flags,
3940 HAL_BUFFER_INPUT, 0, &binfo->smem);
3941 if (rc) {
Maheshwar Ajja1f9676d2018-01-18 11:55:30 -08003942 kfree(binfo);
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003943 dprintk(VIDC_ERR,
3944 "Failed to allocate output memory\n");
Praneeth Paladugu54865842017-08-18 01:45:27 -07003945 rc = -ENOMEM;
Maheshwar Ajja1f9676d2018-01-18 11:55:30 -08003946 break;
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003947 }
3948
3949 mutex_lock(&inst->eosbufs.lock);
3950 list_add_tail(&binfo->list, &inst->eosbufs.list);
3951 mutex_unlock(&inst->eosbufs.lock);
3952
Praneeth Paladugu54865842017-08-18 01:45:27 -07003953 rc = msm_vidc_send_pending_eos_buffers(inst);
Maheshwar Ajja1f9676d2018-01-18 11:55:30 -08003954 if (rc) {
3955 dprintk(VIDC_ERR,
3956 "Failed pending_eos_buffers sending\n");
3957 list_del(&binfo->list);
3958 kfree(binfo);
3959 break;
3960 }
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003961 break;
3962 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003963 default:
3964 dprintk(VIDC_ERR, "Unknown Command %d\n", which_cmd);
3965 rc = -ENOTSUPP;
3966 break;
3967 }
3968 return rc;
3969}
3970
3971static void populate_frame_data(struct vidc_frame_data *data,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003972 struct msm_vidc_buffer *mbuf, struct msm_vidc_inst *inst)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003973{
Vaibhav Deshu Venkateshe5800332017-03-21 14:27:11 -07003974 u64 time_usec;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003975 int extra_idx;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003976 struct vb2_buffer *vb;
3977 struct vb2_v4l2_buffer *vbuf;
3978
3979 if (!inst || !mbuf || !data) {
3980 dprintk(VIDC_ERR, "%s: invalid params %pK %pK %pK\n",
3981 __func__, inst, mbuf, data);
3982 return;
3983 }
3984
3985 vb = &mbuf->vvb.vb2_buf;
3986 vbuf = to_vb2_v4l2_buffer(vb);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003987
Vaibhav Deshu Venkateshe5800332017-03-21 14:27:11 -07003988 time_usec = vb->timestamp;
3989 do_div(time_usec, NSEC_PER_USEC);
3990
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003991 data->alloc_len = vb->planes[0].length;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003992 data->device_addr = mbuf->smem[0].device_addr;
Vaibhav Deshu Venkateshe5800332017-03-21 14:27:11 -07003993 data->timestamp = time_usec;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003994 data->flags = 0;
3995 data->clnt_data = data->device_addr;
3996
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003997 if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003998 data->buffer_type = HAL_BUFFER_INPUT;
3999 data->filled_len = vb->planes[0].bytesused;
4000 data->offset = vb->planes[0].data_offset;
4001
4002 if (vbuf->flags & V4L2_QCOM_BUF_FLAG_EOS)
4003 data->flags |= HAL_BUFFERFLAG_EOS;
4004
4005 if (vbuf->flags & V4L2_QCOM_BUF_FLAG_CODECCONFIG)
4006 data->flags |= HAL_BUFFERFLAG_CODECCONFIG;
4007
4008 if (vbuf->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY)
4009 data->flags |= HAL_BUFFERFLAG_DECODEONLY;
4010
4011 if (vbuf->flags & V4L2_QCOM_BUF_TIMESTAMP_INVALID)
4012 data->timestamp = LLONG_MAX;
4013
Qiwei Liu551a22222017-08-23 15:28:29 +08004014 if (inst->session_type == MSM_VIDC_DECODER) {
4015 msm_comm_fetch_mark_data(&inst->etb_data, vb->index,
4016 &data->mark_data, &data->mark_target);
4017 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004018
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004019 } else if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004020 data->buffer_type = msm_comm_get_hal_output_buffer(inst);
4021 }
4022
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004023 extra_idx = EXTRADATA_IDX(vb->num_planes);
4024 if (extra_idx && extra_idx < VIDEO_MAX_PLANES) {
4025 data->extradata_addr = mbuf->smem[extra_idx].device_addr;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004026 data->extradata_size = vb->planes[extra_idx].length;
4027 data->flags |= HAL_BUFFERFLAG_EXTRADATA;
4028 }
4029}
4030
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004031static unsigned int count_single_batch(struct msm_vidc_inst *inst,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004032 enum v4l2_buf_type type)
4033{
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004034 int count = 0;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004035 struct msm_vidc_buffer *mbuf = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004036
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004037 mutex_lock(&inst->registeredbufs.lock);
4038 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
4039 if (mbuf->vvb.vb2_buf.type != type)
4040 continue;
4041
4042 /* count only deferred buffers */
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004043 if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED))
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004044 continue;
4045
4046 ++count;
4047
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004048 if (!(mbuf->vvb.flags & V4L2_MSM_BUF_FLAG_DEFER))
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004049 goto found_batch;
4050 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004051 /* don't have a full batch */
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004052 count = 0;
4053
4054found_batch:
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004055 mutex_unlock(&inst->registeredbufs.lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004056 return count;
4057}
4058
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004059static unsigned int count_buffers(struct msm_vidc_inst *inst,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004060 enum v4l2_buf_type type)
4061{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004062 struct msm_vidc_buffer *mbuf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004063 int count = 0;
4064
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004065 mutex_lock(&inst->registeredbufs.lock);
4066 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
4067 if (mbuf->vvb.vb2_buf.type != type)
4068 continue;
4069
4070 /* count only deferred buffers */
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004071 if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED))
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004072 continue;
4073
4074 ++count;
4075 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004076 mutex_unlock(&inst->registeredbufs.lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004077
4078 return count;
4079}
4080
4081static void log_frame(struct msm_vidc_inst *inst, struct vidc_frame_data *data,
4082 enum v4l2_buf_type type)
4083{
Praneeth Paladugub71968b2015-08-19 20:47:57 -07004084
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004085 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
4086 dprintk(VIDC_DBG,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004087 "Sending etb (%x) to hal: filled: %d, ts: %lld, flags = %#x\n",
4088 data->device_addr, data->filled_len,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004089 data->timestamp, data->flags);
4090 msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_ETB);
4091
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004092 } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
4093 dprintk(VIDC_DBG,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004094 "Sending ftb (%x) to hal: size: %d, ts: %lld, flags = %#x\n",
4095 data->device_addr, data->alloc_len,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004096 data->timestamp, data->flags);
4097 msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FTB);
4098 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004099}
4100
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004101enum hal_buffer get_hal_buffer_type(unsigned int type,
4102 unsigned int plane_num)
4103{
4104 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
4105 if (plane_num == 0)
4106 return HAL_BUFFER_INPUT;
4107 else
4108 return HAL_BUFFER_EXTRADATA_INPUT;
4109 } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
4110 if (plane_num == 0)
4111 return HAL_BUFFER_OUTPUT;
4112 else
4113 return HAL_BUFFER_EXTRADATA_OUTPUT;
4114 } else {
4115 return -EINVAL;
4116 }
4117}
4118
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004119static int msm_comm_qbuf_rbr(struct msm_vidc_inst *inst,
4120 struct msm_vidc_buffer *mbuf)
4121{
4122 int rc = 0;
4123 struct hfi_device *hdev;
4124 struct vidc_frame_data frame_data = {0};
4125
4126 if (!inst || !inst->core || !inst->core->device || !mbuf) {
4127 dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
4128 return -EINVAL;
4129 }
4130
4131 hdev = inst->core->device;
4132
4133 if (inst->state == MSM_VIDC_CORE_INVALID) {
4134 dprintk(VIDC_ERR, "%s: inst is in bad state\n", __func__);
4135 return -EINVAL;
4136 }
4137
4138 rc = msm_comm_scale_clocks_and_bus(inst);
4139 populate_frame_data(&frame_data, mbuf, inst);
4140
4141 rc = call_hfi_op(hdev, session_ftb, inst->session, &frame_data);
4142 if (rc) {
4143 dprintk(VIDC_ERR, "Failed to issue ftb: %d\n", rc);
4144 goto err_bad_input;
4145 }
4146
4147 log_frame(inst, &frame_data, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
4148
4149err_bad_input:
4150 return rc;
4151}
4152
4153
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004154/*
4155 * Attempts to queue `vb` to hardware. If, for various reasons, the buffer
4156 * cannot be queued to hardware, the buffer will be staged for commit in the
4157 * pending queue. Once the hardware reaches a good state (or if `vb` is NULL,
4158 * the subsequent *_qbuf will commit the previously staged buffers to hardware.
4159 */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004160int msm_comm_qbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004161{
4162 int rc = 0, capture_count, output_count;
4163 struct msm_vidc_core *core;
4164 struct hfi_device *hdev;
4165 struct {
4166 struct vidc_frame_data *data;
4167 int count;
4168 } etbs, ftbs;
4169 bool defer = false, batch_mode;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004170 struct msm_vidc_buffer *temp = NULL, *next = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004171
4172 if (!inst) {
4173 dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
4174 return -EINVAL;
4175 }
4176
4177 core = inst->core;
4178 hdev = core->device;
4179
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004180 if (inst->state == MSM_VIDC_CORE_INVALID) {
4181 dprintk(VIDC_ERR, "%s: inst is in bad state\n", __func__);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004182 return -EINVAL;
4183 }
4184
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004185 batch_mode = msm_comm_g_ctrl_for_id(inst, V4L2_CID_VIDC_QBUF_MODE)
4186 == V4L2_VIDC_QBUF_BATCHED;
4187 capture_count = (batch_mode ? &count_single_batch : &count_buffers)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004188 (inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004189 output_count = (batch_mode ? &count_single_batch : &count_buffers)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004190 (inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004191
Maheshwar Ajja98557a22017-10-30 18:23:39 -07004192 if (!batch_mode && mbuf) {
4193 /*
4194 * don't queue output_mplane buffers if buffer queued
4195 * by client is capture_mplane type and vice versa.
4196 */
4197 if (mbuf->vvb.vb2_buf.type ==
4198 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
4199 output_count = 0;
4200 else if (mbuf->vvb.vb2_buf.type ==
4201 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
4202 capture_count = 0;
4203 }
4204
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004205 /*
4206 * Somewhat complicated logic to prevent queuing the buffer to hardware.
4207 * Don't queue if:
4208 * 1) Hardware isn't ready (that's simple)
4209 */
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -07004210 defer = defer ? defer : (inst->state != MSM_VIDC_START_DONE);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004211
4212 /*
4213 * 2) The client explicitly tells us not to because it wants this
4214 * buffer to be batched with future frames. The batch size (on both
4215 * capabilities) is completely determined by the client.
4216 */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004217 defer = defer ? defer :
4218 (mbuf && mbuf->vvb.flags & V4L2_MSM_BUF_FLAG_DEFER);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004219
4220 /* 3) If we're in batch mode, we must have full batches of both types */
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -07004221 defer = defer ? defer:(batch_mode && (!output_count || !capture_count));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004222
4223 if (defer) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004224 if (mbuf) {
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004225 mbuf->flags |= MSM_VIDC_FLAG_DEFERRED;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004226 print_vidc_buffer(VIDC_DBG, "deferred qbuf",
4227 inst, mbuf);
4228 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004229 return 0;
4230 }
4231
Praneeth Paladugub71968b2015-08-19 20:47:57 -07004232 rc = msm_comm_scale_clocks_and_bus(inst);
4233
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004234 dprintk(VIDC_DBG, "%sing %d etbs and %d ftbs\n",
4235 batch_mode ? "Batch" : "Process",
4236 output_count, capture_count);
4237
4238 etbs.data = kcalloc(output_count, sizeof(*etbs.data), GFP_KERNEL);
4239 ftbs.data = kcalloc(capture_count, sizeof(*ftbs.data), GFP_KERNEL);
4240 /*
4241 * Note that it's perfectly normal for (e|f)tbs.data to be NULL if
4242 * we're not in batch mode (i.e. (output|capture)_count == 0)
4243 */
4244 if ((!etbs.data && output_count) ||
4245 (!ftbs.data && capture_count)) {
4246 dprintk(VIDC_ERR, "Failed to alloc memory for batching\n");
4247 kfree(etbs.data);
4248 etbs.data = NULL;
4249
4250 kfree(ftbs.data);
4251 ftbs.data = NULL;
4252 goto err_no_mem;
4253 }
4254
4255 etbs.count = ftbs.count = 0;
4256
4257 /*
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004258 * Try to collect all deferred buffers into 2 batches of ftb and etb
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004259 * Note that these "batches" might be empty if we're no in batching mode
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004260 * and the deferred is not set for buffers.
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004261 */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004262 mutex_lock(&inst->registeredbufs.lock);
4263 list_for_each_entry_safe(temp, next, &inst->registeredbufs.list, list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004264 struct vidc_frame_data *frame_data = NULL;
4265
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004266 if (!(temp->flags & MSM_VIDC_FLAG_DEFERRED))
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004267 continue;
4268
4269 switch (temp->vvb.vb2_buf.type) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004270 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
4271 if (ftbs.count < capture_count && ftbs.data)
4272 frame_data = &ftbs.data[ftbs.count++];
4273 break;
4274 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
4275 if (etbs.count < output_count && etbs.data)
4276 frame_data = &etbs.data[etbs.count++];
4277 break;
4278 default:
4279 break;
4280 }
4281
4282 if (!frame_data)
4283 continue;
4284
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004285 populate_frame_data(frame_data, temp, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004286
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004287 /* this buffer going to be queued (not deferred) */
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004288 temp->flags &= ~MSM_VIDC_FLAG_DEFERRED;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004289
4290 print_vidc_buffer(VIDC_DBG, "qbuf", inst, temp);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004291 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004292 mutex_unlock(&inst->registeredbufs.lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004293
4294 /* Finally commit all our frame(s) to H/W */
4295 if (batch_mode) {
4296 int ftb_index = 0, c = 0;
4297
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004298 ftb_index = c;
4299 rc = call_hfi_op(hdev, session_process_batch, inst->session,
4300 etbs.count, etbs.data,
4301 ftbs.count - ftb_index, &ftbs.data[ftb_index]);
4302 if (rc) {
4303 dprintk(VIDC_ERR,
4304 "Failed to queue batch of %d ETBs and %d FTBs\n",
4305 etbs.count, ftbs.count);
4306 goto err_bad_input;
4307 }
4308
4309 for (c = ftb_index; c < ftbs.count; ++c) {
4310 log_frame(inst, &ftbs.data[c],
4311 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
4312 }
4313
4314 for (c = 0; c < etbs.count; ++c) {
4315 log_frame(inst, &etbs.data[c],
4316 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
4317 }
4318 }
4319
4320 if (!batch_mode && etbs.count) {
4321 int c = 0;
4322
4323 for (c = 0; c < etbs.count; ++c) {
4324 struct vidc_frame_data *frame_data = &etbs.data[c];
4325
4326 rc = call_hfi_op(hdev, session_etb, inst->session,
4327 frame_data);
4328 if (rc) {
4329 dprintk(VIDC_ERR, "Failed to issue etb: %d\n",
4330 rc);
4331 goto err_bad_input;
4332 }
4333
4334 log_frame(inst, frame_data,
4335 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
4336 }
4337 }
4338
4339 if (!batch_mode && ftbs.count) {
4340 int c = 0;
4341
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004342 for (; c < ftbs.count; ++c) {
4343 struct vidc_frame_data *frame_data = &ftbs.data[c];
4344
4345 rc = call_hfi_op(hdev, session_ftb,
4346 inst->session, frame_data);
4347 if (rc) {
4348 dprintk(VIDC_ERR, "Failed to issue ftb: %d\n",
4349 rc);
4350 goto err_bad_input;
4351 }
4352
4353 log_frame(inst, frame_data,
4354 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
4355 }
4356 }
4357
4358err_bad_input:
4359 if (rc)
4360 dprintk(VIDC_ERR, "Failed to queue buffer\n");
4361
4362 kfree(etbs.data);
4363 kfree(ftbs.data);
4364err_no_mem:
4365 return rc;
4366}
4367
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07004368int msm_vidc_update_host_buff_counts(struct msm_vidc_inst *inst)
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004369{
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004370 int extra_buffers;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004371 struct hal_buffer_requirements *bufreq;
4372
4373 bufreq = get_buff_req_buffer(inst,
4374 HAL_BUFFER_INPUT);
4375 if (!bufreq) {
4376 dprintk(VIDC_ERR,
4377 "Failed : No buffer requirements : %x\n",
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004378 HAL_BUFFER_INPUT);
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004379 return -EINVAL;
4380 }
4381 extra_buffers = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_INPUT);
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004382 bufreq->buffer_count_min_host = bufreq->buffer_count_min +
4383 extra_buffers;
Maheshwar Ajja83fec052017-07-25 11:18:38 -07004384 bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT);
4385 if (bufreq) {
4386 if (bufreq->buffer_count_min)
4387 bufreq->buffer_count_min_host =
4388 bufreq->buffer_count_min + extra_buffers;
4389 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004390
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004391 if (msm_comm_get_stream_output_mode(inst) ==
4392 HAL_VIDEO_DECODER_SECONDARY) {
4393
4394 bufreq = get_buff_req_buffer(inst,
4395 HAL_BUFFER_OUTPUT);
4396 if (!bufreq) {
4397 dprintk(VIDC_ERR,
4398 "Failed : No buffer requirements : %x\n",
4399 HAL_BUFFER_OUTPUT);
4400 return -EINVAL;
4401 }
4402
4403 /* For DPB buffers, no need to add Extra buffers */
Praneeth Paladugu6e637472017-05-16 16:06:46 -07004404 bufreq->buffer_count_min_host = bufreq->buffer_count_actual =
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004405 bufreq->buffer_count_min;
4406
4407 bufreq = get_buff_req_buffer(inst,
4408 HAL_BUFFER_OUTPUT2);
4409 if (!bufreq) {
4410 dprintk(VIDC_ERR,
4411 "Failed : No buffer requirements : %x\n",
4412 HAL_BUFFER_OUTPUT2);
4413 return -EINVAL;
4414 }
4415
4416 extra_buffers = msm_vidc_get_extra_buff_count(inst,
4417 HAL_BUFFER_OUTPUT);
4418
Praneeth Paladugu6e637472017-05-16 16:06:46 -07004419 bufreq->buffer_count_min_host = bufreq->buffer_count_actual =
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004420 bufreq->buffer_count_min + extra_buffers;
Chinmay Sawarkaraa84fae2017-06-27 12:39:51 -07004421
4422 bufreq = get_buff_req_buffer(inst,
4423 HAL_BUFFER_EXTRADATA_OUTPUT2);
4424 if (!bufreq) {
4425 dprintk(VIDC_DBG,
4426 "No buffer requirements : %x\n",
4427 HAL_BUFFER_EXTRADATA_OUTPUT2);
4428 } else {
4429 if (bufreq->buffer_count_min) {
4430 bufreq->buffer_count_min_host =
4431 bufreq->buffer_count_actual =
4432 bufreq->buffer_count_min + extra_buffers;
4433 }
4434 }
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004435 } else {
4436
4437 bufreq = get_buff_req_buffer(inst,
4438 HAL_BUFFER_OUTPUT);
4439 if (!bufreq) {
4440 dprintk(VIDC_ERR,
4441 "Failed : No buffer requirements : %x\n",
4442 HAL_BUFFER_OUTPUT);
4443 return -EINVAL;
4444 }
4445
4446 extra_buffers = msm_vidc_get_extra_buff_count(inst,
4447 HAL_BUFFER_OUTPUT);
4448
Praneeth Paladugu6e637472017-05-16 16:06:46 -07004449 bufreq->buffer_count_min_host = bufreq->buffer_count_actual =
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004450 bufreq->buffer_count_min + extra_buffers;
Chinmay Sawarkaraa84fae2017-06-27 12:39:51 -07004451
4452 bufreq = get_buff_req_buffer(inst,
4453 HAL_BUFFER_EXTRADATA_OUTPUT);
4454 if (!bufreq) {
4455 dprintk(VIDC_DBG,
4456 "No buffer requirements : %x\n",
4457 HAL_BUFFER_EXTRADATA_OUTPUT);
4458 } else {
4459 if (bufreq->buffer_count_min) {
4460 bufreq->buffer_count_min_host =
4461 bufreq->buffer_count_actual =
4462 bufreq->buffer_count_min + extra_buffers;
4463 }
4464 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004465 }
4466
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004467 return 0;
4468}
4469
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004470int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst)
4471{
4472 int rc = 0, i = 0;
4473 union hal_get_property hprop;
4474
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004475 memset(&hprop, 0x0, sizeof(hprop));
4476
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004477 rc = msm_comm_try_get_prop(inst, HAL_PARAM_GET_BUFFER_REQUIREMENTS,
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004478 &hprop);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004479 if (rc) {
4480 dprintk(VIDC_ERR, "Failed getting buffer requirements: %d", rc);
4481 return rc;
4482 }
4483
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004484 dprintk(VIDC_DBG, "Buffer requirements from HW:\n");
4485 dprintk(VIDC_DBG, "%15s %8s %8s %8s %8s\n",
4486 "buffer type", "count", "mincount_host", "mincount_fw", "size");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004487 for (i = 0; i < HAL_BUFFER_MAX; i++) {
4488 struct hal_buffer_requirements req = hprop.buf_req.buffer[i];
4489
4490 inst->buff_req.buffer[i] = req;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004491 if (req.buffer_type != HAL_BUFFER_NONE) {
4492 dprintk(VIDC_DBG, "%15s %8d %8d %8d %8d\n",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004493 get_buffer_name(req.buffer_type),
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004494 req.buffer_count_actual,
4495 req.buffer_count_min_host,
4496 req.buffer_count_min, req.buffer_size);
4497 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004498 }
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07004499 if (inst->session_type == MSM_VIDC_ENCODER)
4500 rc = msm_vidc_update_host_buff_counts(inst);
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004501
4502 dprintk(VIDC_DBG, "Buffer requirements host adjusted:\n");
4503 dprintk(VIDC_DBG, "%15s %8s %8s %8s %8s\n",
4504 "buffer type", "count", "mincount_host", "mincount_fw", "size");
4505 for (i = 0; i < HAL_BUFFER_MAX; i++) {
Praneeth Paladugu13c90962017-04-24 13:15:28 -07004506 struct hal_buffer_requirements req = inst->buff_req.buffer[i];
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004507
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004508 if (req.buffer_type != HAL_BUFFER_NONE) {
4509 dprintk(VIDC_DBG, "%15s %8d %8d %8d %8d\n",
4510 get_buffer_name(req.buffer_type),
4511 req.buffer_count_actual,
4512 req.buffer_count_min_host,
4513 req.buffer_count_min, req.buffer_size);
4514 }
4515 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004516 return rc;
4517}
4518
4519int msm_comm_try_get_prop(struct msm_vidc_inst *inst, enum hal_property ptype,
4520 union hal_get_property *hprop)
4521{
4522 int rc = 0;
4523 struct hfi_device *hdev;
4524 struct getprop_buf *buf;
4525
4526 if (!inst || !inst->core || !inst->core->device) {
4527 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4528 return -EINVAL;
4529 }
4530
4531 hdev = inst->core->device;
4532 mutex_lock(&inst->sync_lock);
4533 if (inst->state < MSM_VIDC_OPEN_DONE ||
4534 inst->state >= MSM_VIDC_CLOSE) {
4535
4536 /* No need to check inst->state == MSM_VIDC_INVALID since
4537 * INVALID is > CLOSE_DONE. When core went to INVALID state,
4538 * we put all the active instances in INVALID. So > CLOSE_DONE
4539 * is enough check to have.
4540 */
4541
4542 dprintk(VIDC_ERR,
4543 "In Wrong state to call Buf Req: Inst %pK or Core %pK\n",
4544 inst, inst->core);
4545 rc = -EAGAIN;
4546 mutex_unlock(&inst->sync_lock);
4547 goto exit;
4548 }
4549 mutex_unlock(&inst->sync_lock);
4550
4551 switch (ptype) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004552 case HAL_PARAM_GET_BUFFER_REQUIREMENTS:
4553 rc = call_hfi_op(hdev, session_get_buf_req, inst->session);
4554 break;
4555 default:
4556 rc = -EAGAIN;
4557 break;
4558 }
4559
4560 if (rc) {
4561 dprintk(VIDC_ERR, "Can't query hardware for property: %d\n",
4562 rc);
4563 goto exit;
4564 }
4565
4566 rc = wait_for_completion_timeout(&inst->completions[
4567 SESSION_MSG_INDEX(HAL_SESSION_PROPERTY_INFO)],
Praneeth Paladugud5bf7bc2017-05-29 23:41:04 -07004568 msecs_to_jiffies(
4569 inst->core->resources.msm_vidc_hw_rsp_timeout));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004570 if (!rc) {
4571 dprintk(VIDC_ERR,
4572 "%s: Wait interrupted or timed out [%pK]: %d\n",
4573 __func__, inst,
4574 SESSION_MSG_INDEX(HAL_SESSION_PROPERTY_INFO));
Surajit Podder878ede02017-02-07 12:20:10 +05304575 msm_comm_kill_session(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004576 rc = -ETIMEDOUT;
4577 goto exit;
4578 } else {
4579 /* wait_for_completion_timeout returns jiffies before expiry */
4580 rc = 0;
4581 }
4582
4583 mutex_lock(&inst->pending_getpropq.lock);
4584 if (!list_empty(&inst->pending_getpropq.list)) {
4585 buf = list_first_entry(&inst->pending_getpropq.list,
4586 struct getprop_buf, list);
4587 *hprop = *(union hal_get_property *)buf->data;
4588 kfree(buf->data);
4589 list_del(&buf->list);
4590 kfree(buf);
4591 } else {
4592 dprintk(VIDC_ERR, "%s getprop list empty\n", __func__);
4593 rc = -EINVAL;
4594 }
4595 mutex_unlock(&inst->pending_getpropq.lock);
4596exit:
4597 return rc;
4598}
4599
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004600int msm_comm_release_output_buffers(struct msm_vidc_inst *inst,
4601 bool force_release)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004602{
4603 struct msm_smem *handle;
4604 struct internal_buf *buf, *dummy;
4605 struct vidc_buffer_addr_info buffer_info;
4606 int rc = 0;
4607 struct msm_vidc_core *core;
4608 struct hfi_device *hdev;
4609
4610 if (!inst) {
4611 dprintk(VIDC_ERR,
4612 "Invalid instance pointer = %pK\n", inst);
4613 return -EINVAL;
4614 }
4615 mutex_lock(&inst->outputbufs.lock);
4616 if (list_empty(&inst->outputbufs.list)) {
4617 dprintk(VIDC_DBG, "%s - No OUTPUT buffers allocated\n",
4618 __func__);
4619 mutex_unlock(&inst->outputbufs.lock);
4620 return 0;
4621 }
4622 mutex_unlock(&inst->outputbufs.lock);
4623
4624 core = inst->core;
4625 if (!core) {
4626 dprintk(VIDC_ERR,
4627 "Invalid core pointer = %pK\n", core);
4628 return -EINVAL;
4629 }
4630 hdev = core->device;
4631 if (!hdev) {
4632 dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev);
4633 return -EINVAL;
4634 }
4635 mutex_lock(&inst->outputbufs.lock);
4636 list_for_each_entry_safe(buf, dummy, &inst->outputbufs.list, list) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004637 handle = &buf->smem;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004638
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004639 if ((buf->buffer_ownership == FIRMWARE) && !force_release) {
4640 dprintk(VIDC_INFO, "DPB is with f/w. Can't free it\n");
4641 continue;
4642 }
4643
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004644 buffer_info.buffer_size = handle->size;
4645 buffer_info.buffer_type = buf->buffer_type;
4646 buffer_info.num_buffers = 1;
4647 buffer_info.align_device_addr = handle->device_addr;
4648 if (inst->buffer_mode_set[CAPTURE_PORT] ==
Maheshwar Ajja99422322017-07-07 17:31:15 -07004649 HAL_BUFFER_MODE_STATIC) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004650 buffer_info.response_required = false;
4651 rc = call_hfi_op(hdev, session_release_buffers,
4652 (void *)inst->session, &buffer_info);
4653 if (rc) {
4654 dprintk(VIDC_WARN,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004655 "Rel output buf fail:%x, %d\n",
4656 buffer_info.align_device_addr,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004657 buffer_info.buffer_size);
4658 }
4659 }
4660
4661 list_del(&buf->list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004662 msm_comm_smem_free(inst, &buf->smem);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004663 kfree(buf);
4664 }
4665
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004666 mutex_unlock(&inst->outputbufs.lock);
4667 return rc;
4668}
4669
4670static enum hal_buffer scratch_buf_sufficient(struct msm_vidc_inst *inst,
4671 enum hal_buffer buffer_type)
4672{
4673 struct hal_buffer_requirements *bufreq = NULL;
4674 struct internal_buf *buf;
4675 int count = 0;
4676
4677 if (!inst) {
4678 dprintk(VIDC_ERR, "%s - invalid param\n", __func__);
4679 goto not_sufficient;
4680 }
4681
4682 bufreq = get_buff_req_buffer(inst, buffer_type);
4683 if (!bufreq)
4684 goto not_sufficient;
4685
4686 /* Check if current scratch buffers are sufficient */
4687 mutex_lock(&inst->scratchbufs.lock);
4688
4689 list_for_each_entry(buf, &inst->scratchbufs.list, list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004690 if (buf->buffer_type == buffer_type &&
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004691 buf->smem.size >= bufreq->buffer_size)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004692 count++;
4693 }
4694 mutex_unlock(&inst->scratchbufs.lock);
4695
4696 if (count != bufreq->buffer_count_actual)
4697 goto not_sufficient;
4698
4699 dprintk(VIDC_DBG,
4700 "Existing scratch buffer is sufficient for buffer type %#x\n",
4701 buffer_type);
4702
4703 return buffer_type;
4704
4705not_sufficient:
4706 return HAL_BUFFER_NONE;
4707}
4708
4709int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst,
4710 bool check_for_reuse)
4711{
4712 struct msm_smem *handle;
4713 struct internal_buf *buf, *dummy;
4714 struct vidc_buffer_addr_info buffer_info;
4715 int rc = 0;
4716 struct msm_vidc_core *core;
4717 struct hfi_device *hdev;
4718 enum hal_buffer sufficiency = HAL_BUFFER_NONE;
4719
4720 if (!inst) {
4721 dprintk(VIDC_ERR,
4722 "Invalid instance pointer = %pK\n", inst);
4723 return -EINVAL;
4724 }
4725 core = inst->core;
4726 if (!core) {
4727 dprintk(VIDC_ERR,
4728 "Invalid core pointer = %pK\n", core);
4729 return -EINVAL;
4730 }
4731 hdev = core->device;
4732 if (!hdev) {
4733 dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev);
4734 return -EINVAL;
4735 }
4736
4737 if (check_for_reuse) {
4738 sufficiency |= scratch_buf_sufficient(inst,
4739 HAL_BUFFER_INTERNAL_SCRATCH);
4740
4741 sufficiency |= scratch_buf_sufficient(inst,
4742 HAL_BUFFER_INTERNAL_SCRATCH_1);
4743
4744 sufficiency |= scratch_buf_sufficient(inst,
4745 HAL_BUFFER_INTERNAL_SCRATCH_2);
4746 }
4747
4748 mutex_lock(&inst->scratchbufs.lock);
4749 list_for_each_entry_safe(buf, dummy, &inst->scratchbufs.list, list) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004750 handle = &buf->smem;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004751 buffer_info.buffer_size = handle->size;
4752 buffer_info.buffer_type = buf->buffer_type;
4753 buffer_info.num_buffers = 1;
4754 buffer_info.align_device_addr = handle->device_addr;
Maheshwar Ajja99422322017-07-07 17:31:15 -07004755 buffer_info.response_required = true;
4756 rc = call_hfi_op(hdev, session_release_buffers,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004757 (void *)inst->session, &buffer_info);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004758 if (!rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004759 mutex_unlock(&inst->scratchbufs.lock);
4760 rc = wait_for_sess_signal_receipt(inst,
4761 HAL_SESSION_RELEASE_BUFFER_DONE);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004762 if (rc)
4763 dprintk(VIDC_WARN,
4764 "%s: wait for signal failed, rc %d\n",
4765 __func__, rc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004766 mutex_lock(&inst->scratchbufs.lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004767 } else {
4768 dprintk(VIDC_WARN,
4769 "Rel scrtch buf fail:%x, %d\n",
4770 buffer_info.align_device_addr,
4771 buffer_info.buffer_size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004772 }
4773
4774 /*If scratch buffers can be reused, do not free the buffers*/
4775 if (sufficiency & buf->buffer_type)
4776 continue;
4777
4778 list_del(&buf->list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004779 msm_comm_smem_free(inst, handle);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004780 kfree(buf);
4781 }
4782
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004783 mutex_unlock(&inst->scratchbufs.lock);
4784 return rc;
4785}
4786
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07004787void msm_comm_release_eos_buffers(struct msm_vidc_inst *inst)
4788{
4789 struct eos_buf *buf, *next;
4790
4791 if (!inst) {
4792 dprintk(VIDC_ERR,
4793 "Invalid instance pointer = %pK\n", inst);
4794 return;
4795 }
4796
4797 mutex_lock(&inst->eosbufs.lock);
4798 list_for_each_entry_safe(buf, next, &inst->eosbufs.list, list) {
4799 list_del(&buf->list);
Maheshwar Ajjaaf35ac12017-09-18 09:59:38 -07004800 msm_comm_smem_free(inst, &buf->smem);
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07004801 kfree(buf);
4802 }
4803 INIT_LIST_HEAD(&inst->eosbufs.list);
4804 mutex_unlock(&inst->eosbufs.lock);
4805}
4806
4807
Praneeth Paladugu319e7922017-03-16 11:09:06 -07004808int msm_comm_release_recon_buffers(struct msm_vidc_inst *inst)
4809{
4810 struct recon_buf *buf, *next;
4811
4812 if (!inst) {
4813 dprintk(VIDC_ERR,
4814 "Invalid instance pointer = %pK\n", inst);
4815 return -EINVAL;
4816 }
4817
4818 mutex_lock(&inst->reconbufs.lock);
4819 list_for_each_entry_safe(buf, next, &inst->reconbufs.list, list) {
4820 list_del(&buf->list);
4821 kfree(buf);
4822 }
4823 INIT_LIST_HEAD(&inst->reconbufs.list);
4824 mutex_unlock(&inst->reconbufs.lock);
4825
4826 return 0;
4827}
4828
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004829int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst)
4830{
4831 struct msm_smem *handle;
4832 struct list_head *ptr, *next;
4833 struct internal_buf *buf;
4834 struct vidc_buffer_addr_info buffer_info;
4835 int rc = 0;
4836 struct msm_vidc_core *core;
4837 struct hfi_device *hdev;
4838
4839 if (!inst) {
4840 dprintk(VIDC_ERR,
4841 "Invalid instance pointer = %pK\n", inst);
4842 return -EINVAL;
4843 }
4844 core = inst->core;
4845 if (!core) {
4846 dprintk(VIDC_ERR,
4847 "Invalid core pointer = %pK\n", core);
4848 return -EINVAL;
4849 }
4850 hdev = core->device;
4851 if (!hdev) {
4852 dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev);
4853 return -EINVAL;
4854 }
4855
4856 mutex_lock(&inst->persistbufs.lock);
4857 list_for_each_safe(ptr, next, &inst->persistbufs.list) {
4858 buf = list_entry(ptr, struct internal_buf, list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004859 handle = &buf->smem;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004860 buffer_info.buffer_size = handle->size;
4861 buffer_info.buffer_type = buf->buffer_type;
4862 buffer_info.num_buffers = 1;
4863 buffer_info.align_device_addr = handle->device_addr;
Maheshwar Ajja99422322017-07-07 17:31:15 -07004864 buffer_info.response_required = true;
4865 rc = call_hfi_op(hdev, session_release_buffers,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004866 (void *)inst->session, &buffer_info);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004867 if (!rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004868 mutex_unlock(&inst->persistbufs.lock);
4869 rc = wait_for_sess_signal_receipt(inst,
4870 HAL_SESSION_RELEASE_BUFFER_DONE);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004871 if (rc)
4872 dprintk(VIDC_WARN,
4873 "%s: wait for signal failed, rc %d\n",
4874 __func__, rc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004875 mutex_lock(&inst->persistbufs.lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004876 } else {
4877 dprintk(VIDC_WARN,
4878 "Rel prst buf fail:%x, %d\n",
4879 buffer_info.align_device_addr,
4880 buffer_info.buffer_size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004881 }
4882 list_del(&buf->list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004883 msm_comm_smem_free(inst, handle);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004884 kfree(buf);
4885 }
4886 mutex_unlock(&inst->persistbufs.lock);
4887 return rc;
4888}
4889
4890int msm_comm_try_set_prop(struct msm_vidc_inst *inst,
4891 enum hal_property ptype, void *pdata)
4892{
4893 int rc = 0;
4894 struct hfi_device *hdev;
4895
4896 if (!inst) {
4897 dprintk(VIDC_ERR, "Invalid input: %pK\n", inst);
4898 return -EINVAL;
4899 }
4900
4901 if (!inst->core || !inst->core->device) {
4902 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4903 return -EINVAL;
4904 }
4905 hdev = inst->core->device;
4906
4907 mutex_lock(&inst->sync_lock);
4908 if (inst->state < MSM_VIDC_OPEN_DONE || inst->state >= MSM_VIDC_CLOSE) {
4909 dprintk(VIDC_ERR, "Not in proper state to set property\n");
4910 rc = -EAGAIN;
4911 goto exit;
4912 }
4913 rc = call_hfi_op(hdev, session_set_property, (void *)inst->session,
4914 ptype, pdata);
4915 if (rc)
4916 dprintk(VIDC_ERR, "Failed to set hal property for framesize\n");
4917exit:
4918 mutex_unlock(&inst->sync_lock);
4919 return rc;
4920}
4921
4922int msm_comm_set_output_buffers(struct msm_vidc_inst *inst)
4923{
4924 int rc = 0;
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004925 bool force_release = true;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004926
4927 if (!inst || !inst->core || !inst->core->device) {
4928 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4929 return -EINVAL;
4930 }
4931
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004932 if (inst->fmts[OUTPUT_PORT].defer_outputs)
4933 force_release = false;
4934
4935 if (msm_comm_release_output_buffers(inst, force_release))
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004936 dprintk(VIDC_WARN, "Failed to release output buffers\n");
4937
4938 rc = set_output_buffers(inst, HAL_BUFFER_OUTPUT);
4939 if (rc)
4940 goto error;
4941 return rc;
4942error:
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004943 msm_comm_release_output_buffers(inst, true);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004944 return rc;
4945}
4946
4947int msm_comm_set_scratch_buffers(struct msm_vidc_inst *inst)
4948{
4949 int rc = 0;
4950
4951 if (!inst || !inst->core || !inst->core->device) {
4952 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4953 return -EINVAL;
4954 }
4955
4956 if (msm_comm_release_scratch_buffers(inst, true))
4957 dprintk(VIDC_WARN, "Failed to release scratch buffers\n");
4958
4959 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_SCRATCH,
4960 &inst->scratchbufs);
4961 if (rc)
4962 goto error;
4963
4964 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_SCRATCH_1,
4965 &inst->scratchbufs);
4966 if (rc)
4967 goto error;
4968
4969 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_SCRATCH_2,
4970 &inst->scratchbufs);
4971 if (rc)
4972 goto error;
4973
4974 return rc;
4975error:
4976 msm_comm_release_scratch_buffers(inst, false);
4977 return rc;
4978}
4979
Praneeth Paladugu319e7922017-03-16 11:09:06 -07004980int msm_comm_set_recon_buffers(struct msm_vidc_inst *inst)
4981{
4982 int rc = 0, i = 0;
4983 struct hal_buffer_requirements *internal_buf;
4984 struct recon_buf *binfo;
4985 struct msm_vidc_list *buf_list = &inst->reconbufs;
4986
4987 if (!inst) {
4988 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4989 return -EINVAL;
4990 }
4991
4992 if (inst->session_type == MSM_VIDC_ENCODER)
4993 internal_buf = get_buff_req_buffer(inst,
4994 HAL_BUFFER_INTERNAL_RECON);
4995 else if (inst->session_type == MSM_VIDC_DECODER)
4996 internal_buf = get_buff_req_buffer(inst,
4997 msm_comm_get_hal_output_buffer(inst));
4998 else
4999 return -EINVAL;
5000
5001 if (!internal_buf || !internal_buf->buffer_count_actual) {
5002 dprintk(VIDC_DBG, "Inst : %pK Recon buffers not required\n",
5003 inst);
5004 return 0;
5005 }
5006
Praneeth Paladugu7722b4e2017-07-07 11:01:56 -07005007 msm_comm_release_recon_buffers(inst);
Praneeth Paladugu319e7922017-03-16 11:09:06 -07005008
5009 for (i = 0; i < internal_buf->buffer_count_actual; i++) {
5010 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
5011 if (!binfo) {
5012 dprintk(VIDC_ERR, "Out of memory\n");
5013 rc = -ENOMEM;
5014 goto fail_kzalloc;
5015 }
5016
5017 binfo->buffer_index = i;
5018 mutex_lock(&buf_list->lock);
5019 list_add_tail(&binfo->list, &buf_list->list);
5020 mutex_unlock(&buf_list->lock);
5021 }
5022
5023fail_kzalloc:
5024 return rc;
5025}
5026
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005027int msm_comm_set_persist_buffers(struct msm_vidc_inst *inst)
5028{
5029 int rc = 0;
5030
5031 if (!inst || !inst->core || !inst->core->device) {
5032 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
5033 return -EINVAL;
5034 }
5035
5036 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_PERSIST,
5037 &inst->persistbufs);
5038 if (rc)
5039 goto error;
5040
5041 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_PERSIST_1,
5042 &inst->persistbufs);
5043 if (rc)
5044 goto error;
5045 return rc;
5046error:
5047 msm_comm_release_persist_buffers(inst);
5048 return rc;
5049}
5050
5051static void msm_comm_flush_in_invalid_state(struct msm_vidc_inst *inst)
5052{
5053 struct list_head *ptr, *next;
5054 enum vidc_ports ports[] = {OUTPUT_PORT, CAPTURE_PORT};
5055 int c = 0;
5056
Maheshwar Ajja4db26932017-10-30 10:08:37 -07005057 /* before flush ensure venus released all buffers */
5058 msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
5059
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005060 for (c = 0; c < ARRAY_SIZE(ports); ++c) {
5061 enum vidc_ports port = ports[c];
5062
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005063 mutex_lock(&inst->bufq[port].lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005064 list_for_each_safe(ptr, next,
5065 &inst->bufq[port].vb2_bufq.queued_list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005066 struct vb2_buffer *vb = container_of(ptr,
5067 struct vb2_buffer, queued_entry);
Vikash Garodia8d985f32017-08-09 19:52:51 +05305068 if (vb->state == VB2_BUF_STATE_ACTIVE) {
5069 vb->planes[0].bytesused = 0;
5070 print_vb2_buffer(VIDC_ERR, "flush in invalid",
5071 inst, vb);
5072 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
5073 } else {
5074 dprintk(VIDC_WARN,
5075 "%s VB is in state %d not in ACTIVE state\n"
5076 , __func__, vb->state);
5077 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005078 }
5079 mutex_unlock(&inst->bufq[port].lock);
5080 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005081 msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_FLUSH_DONE);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005082 return;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005083}
5084
5085int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
5086{
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07005087 int i, rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005088 bool ip_flush = false;
5089 bool op_flush = false;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005090 struct msm_vidc_buffer *mbuf, *next;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005091 struct msm_vidc_core *core;
5092 struct hfi_device *hdev;
5093
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005094 if (!inst || !inst->core || !inst->core->device) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005095 dprintk(VIDC_ERR,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005096 "Invalid params, inst %pK\n", inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005097 return -EINVAL;
5098 }
5099 core = inst->core;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005100 hdev = core->device;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005101
5102 ip_flush = flags & V4L2_QCOM_CMD_FLUSH_OUTPUT;
5103 op_flush = flags & V4L2_QCOM_CMD_FLUSH_CAPTURE;
5104
5105 if (ip_flush && !op_flush) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005106 dprintk(VIDC_WARN,
5107 "Input only flush not supported, making it flush all\n");
5108 op_flush = true;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005109 return 0;
5110 }
5111
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07005112 msm_clock_data_reset(inst);
Praneeth Paladugu75cf18e2016-12-08 16:12:11 -08005113
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005114 if (inst->state == MSM_VIDC_CORE_INVALID) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005115 dprintk(VIDC_ERR,
5116 "Core %pK and inst %pK are in bad state\n",
5117 core, inst);
5118 msm_comm_flush_in_invalid_state(inst);
5119 return 0;
5120 }
5121
Surajit Podder0d812bf2018-02-02 13:37:24 +05305122 mutex_lock(&inst->flush_lock);
Maheshwar Ajja4db26932017-10-30 10:08:37 -07005123 /* enable in flush */
5124 inst->in_flush = true;
5125
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005126 mutex_lock(&inst->registeredbufs.lock);
5127 list_for_each_entry_safe(mbuf, next, &inst->registeredbufs.list, list) {
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07005128 /* don't flush input buffers if input flush is not requested */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005129 if (!ip_flush && mbuf->vvb.vb2_buf.type ==
5130 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
5131 continue;
5132
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07005133 /* flush only deferred or rbr pending buffers */
5134 if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED ||
5135 mbuf->flags & MSM_VIDC_FLAG_RBR_PENDING))
5136 continue;
5137
5138 /*
5139 * flush buffers which are queued by client already,
5140 * the refcount will be two or more for those buffers.
5141 */
5142 if (!(mbuf->smem[0].refcount >= 2))
5143 continue;
5144
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005145 print_vidc_buffer(VIDC_DBG, "flush buf", inst, mbuf);
5146 msm_comm_flush_vidc_buffer(inst, mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005147
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07005148 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
5149 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
5150 print_vidc_buffer(VIDC_ERR,
5151 "dqbuf: unmap failed.", inst, mbuf);
5152 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
5153 print_vidc_buffer(VIDC_ERR,
5154 "dqbuf: unmap failed..", inst, mbuf);
5155 }
5156 if (!mbuf->smem[0].refcount) {
5157 list_del(&mbuf->list);
5158 kref_put_mbuf(mbuf);
5159 } else {
5160 /* buffer is no more a deferred buffer */
5161 mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
5162 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005163 }
5164 mutex_unlock(&inst->registeredbufs.lock);
5165
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005166 hdev = inst->core->device;
5167 if (ip_flush) {
5168 dprintk(VIDC_DBG, "Send flush on all ports to firmware\n");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005169 rc = call_hfi_op(hdev, session_flush, inst->session,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005170 HAL_FLUSH_ALL);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005171 } else {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005172 dprintk(VIDC_DBG, "Send flush on output port to firmware\n");
5173 rc = call_hfi_op(hdev, session_flush, inst->session,
5174 HAL_FLUSH_OUTPUT);
5175 }
Surajit Podder0d812bf2018-02-02 13:37:24 +05305176 mutex_unlock(&inst->flush_lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005177 if (rc) {
5178 dprintk(VIDC_ERR,
5179 "Sending flush to firmware failed, flush out all buffers\n");
5180 msm_comm_flush_in_invalid_state(inst);
5181 /* disable in_flush */
5182 inst->in_flush = false;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005183 }
5184
5185 return rc;
5186}
5187
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005188enum hal_extradata_id msm_comm_get_hal_extradata_index(
5189 enum v4l2_mpeg_vidc_extradata index)
5190{
5191 int ret = 0;
5192
5193 switch (index) {
5194 case V4L2_MPEG_VIDC_EXTRADATA_NONE:
5195 ret = HAL_EXTRADATA_NONE;
5196 break;
5197 case V4L2_MPEG_VIDC_EXTRADATA_MB_QUANTIZATION:
5198 ret = HAL_EXTRADATA_MB_QUANTIZATION;
5199 break;
5200 case V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO:
5201 ret = HAL_EXTRADATA_INTERLACE_VIDEO;
5202 break;
5203 case V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP:
5204 ret = HAL_EXTRADATA_TIMESTAMP;
5205 break;
5206 case V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING:
5207 ret = HAL_EXTRADATA_S3D_FRAME_PACKING;
5208 break;
5209 case V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE:
5210 ret = HAL_EXTRADATA_FRAME_RATE;
5211 break;
5212 case V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW:
5213 ret = HAL_EXTRADATA_PANSCAN_WINDOW;
5214 break;
5215 case V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
5216 ret = HAL_EXTRADATA_RECOVERY_POINT_SEI;
5217 break;
5218 case V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO:
5219 ret = HAL_EXTRADATA_MULTISLICE_INFO;
5220 break;
5221 case V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB:
5222 ret = HAL_EXTRADATA_NUM_CONCEALED_MB;
5223 break;
5224 case V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER:
5225 ret = HAL_EXTRADATA_METADATA_FILLER;
5226 break;
5227 case V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO:
5228 ret = HAL_EXTRADATA_ASPECT_RATIO;
5229 break;
5230 case V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP:
5231 ret = HAL_EXTRADATA_INPUT_CROP;
5232 break;
5233 case V4L2_MPEG_VIDC_EXTRADATA_DIGITAL_ZOOM:
5234 ret = HAL_EXTRADATA_DIGITAL_ZOOM;
5235 break;
5236 case V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP:
5237 ret = HAL_EXTRADATA_MPEG2_SEQDISP;
5238 break;
5239 case V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA:
5240 ret = HAL_EXTRADATA_STREAM_USERDATA;
5241 break;
5242 case V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP:
5243 ret = HAL_EXTRADATA_FRAME_QP;
5244 break;
5245 case V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO:
5246 ret = HAL_EXTRADATA_FRAME_BITS_INFO;
5247 break;
5248 case V4L2_MPEG_VIDC_EXTRADATA_LTR:
5249 ret = HAL_EXTRADATA_LTR_INFO;
5250 break;
5251 case V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI:
5252 ret = HAL_EXTRADATA_METADATA_MBI;
5253 break;
5254 case V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI:
5255 ret = HAL_EXTRADATA_VQZIP_SEI;
5256 break;
5257 case V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS:
5258 ret = HAL_EXTRADATA_YUV_STATS;
5259 break;
5260 case V4L2_MPEG_VIDC_EXTRADATA_ROI_QP:
5261 ret = HAL_EXTRADATA_ROI_QP;
5262 break;
5263 case V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP:
5264 ret = HAL_EXTRADATA_OUTPUT_CROP;
5265 break;
5266 case V4L2_MPEG_VIDC_EXTRADATA_DISPLAY_COLOUR_SEI:
5267 ret = HAL_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI;
5268 break;
5269 case V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI:
5270 ret = HAL_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI;
5271 break;
5272 case V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO:
5273 ret = HAL_EXTRADATA_PQ_INFO;
5274 break;
5275
5276 case V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY:
5277 ret = HAL_EXTRADATA_VUI_DISPLAY_INFO;
5278 break;
5279 case V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE:
5280 ret = HAL_EXTRADATA_VPX_COLORSPACE;
5281 break;
Praneeth Paladugua51b2c42017-06-23 12:48:06 -07005282 case V4L2_MPEG_VIDC_EXTRADATA_UBWC_CR_STATS_INFO:
5283 ret = HAL_EXTRADATA_UBWC_CR_STATS_INFO;
5284 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005285 default:
5286 dprintk(VIDC_WARN, "Extradata not found: %d\n", index);
5287 break;
5288 }
5289 return ret;
5290};
5291
Maheshwar Ajja9ff81a22017-08-05 13:25:55 -07005292int msm_vidc_noc_error_info(struct msm_vidc_core *core)
5293{
5294 struct hfi_device *hdev;
5295
5296 if (!core || !core->device) {
5297 dprintk(VIDC_WARN, "%s: Invalid parameters: %pK\n",
5298 __func__, core);
5299 return -EINVAL;
5300 }
5301
5302 if (!core->resources.non_fatal_pagefaults)
5303 return 0;
5304
5305 if (!core->smmu_fault_handled)
5306 return 0;
5307
5308 hdev = core->device;
5309 call_hfi_op(hdev, noc_error_info, hdev->hfi_device_data);
5310
5311 return 0;
5312}
5313
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005314int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
5315 enum hal_ssr_trigger_type type)
5316{
5317 int rc = 0;
5318 struct hfi_device *hdev;
Surajit Podder20ceed02018-01-09 21:23:10 +05305319 int try_lock_counter = TRIGGER_SSR_LOCK_RETRIES;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005320
5321 if (!core || !core->device) {
5322 dprintk(VIDC_WARN, "Invalid parameters: %pK\n", core);
5323 return -EINVAL;
5324 }
5325 hdev = core->device;
Maheshwar Ajja79fe9042017-10-17 16:56:35 -07005326
Surajit Podder20ceed02018-01-09 21:23:10 +05305327 while (try_lock_counter) {
5328 if (mutex_trylock(&core->lock))
5329 break;
5330 try_lock_counter--;
5331 if (!try_lock_counter)
5332 return -EBUSY;
5333 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005334 if (core->state == VIDC_CORE_INIT_DONE) {
5335 /*
5336 * In current implementation user-initiated SSR triggers
5337 * a fatal error from hardware. However, there is no way
5338 * to know if fatal error is due to SSR or not. Handle
5339 * user SSR as non-fatal.
5340 */
Maheshwar Ajja8382bec2017-08-11 13:41:35 -07005341 core->trigger_ssr = true;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005342 rc = call_hfi_op(hdev, core_trigger_ssr,
5343 hdev->hfi_device_data, type);
Maheshwar Ajja8382bec2017-08-11 13:41:35 -07005344 if (rc) {
5345 dprintk(VIDC_ERR, "%s: trigger_ssr failed\n",
5346 __func__);
5347 core->trigger_ssr = false;
5348 }
Maheshwar Ajja79fe9042017-10-17 16:56:35 -07005349 } else {
5350 dprintk(VIDC_WARN, "%s: video core %pK not initialized\n",
5351 __func__, core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005352 }
Maheshwar Ajja79fe9042017-10-17 16:56:35 -07005353 mutex_unlock(&core->lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005354
5355 return rc;
5356}
5357
5358static int msm_vidc_load_supported(struct msm_vidc_inst *inst)
5359{
5360 int num_mbs_per_sec = 0, max_load_adj = 0;
5361 enum load_calc_quirks quirks = LOAD_CALC_IGNORE_TURBO_LOAD |
5362 LOAD_CALC_IGNORE_THUMBNAIL_LOAD |
5363 LOAD_CALC_IGNORE_NON_REALTIME_LOAD;
5364
5365 if (inst->state == MSM_VIDC_OPEN_DONE) {
Saurabh Kothawade5d7f7d42017-09-15 11:22:49 -07005366 max_load_adj = inst->core->resources.max_load;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005367 num_mbs_per_sec = msm_comm_get_load(inst->core,
5368 MSM_VIDC_DECODER, quirks);
5369 num_mbs_per_sec += msm_comm_get_load(inst->core,
5370 MSM_VIDC_ENCODER, quirks);
5371 if (num_mbs_per_sec > max_load_adj) {
5372 dprintk(VIDC_ERR,
5373 "H/W is overloaded. needed: %d max: %d\n",
5374 num_mbs_per_sec,
5375 max_load_adj);
5376 msm_vidc_print_running_insts(inst->core);
5377 return -EBUSY;
5378 }
5379 }
5380 return 0;
5381}
5382
5383int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst)
5384{
5385 u32 x_min, x_max, y_min, y_max;
5386 u32 input_height, input_width, output_height, output_width;
Chinmay Sawarkar81a02a32017-07-13 12:10:24 -07005387 u32 rotation;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005388
5389 input_height = inst->prop.height[OUTPUT_PORT];
5390 input_width = inst->prop.width[OUTPUT_PORT];
5391 output_height = inst->prop.height[CAPTURE_PORT];
5392 output_width = inst->prop.width[CAPTURE_PORT];
5393
5394 if (!input_height || !input_width || !output_height || !output_width) {
5395 dprintk(VIDC_ERR,
5396 "Invalid : Input height = %d width = %d",
5397 input_height, input_width);
5398 dprintk(VIDC_ERR,
5399 " output height = %d width = %d\n",
5400 output_height, output_width);
5401 return -ENOTSUPP;
5402 }
5403
5404 if (!inst->capability.scale_x.min ||
5405 !inst->capability.scale_x.max ||
5406 !inst->capability.scale_y.min ||
5407 !inst->capability.scale_y.max) {
5408
5409 if (input_width * input_height !=
5410 output_width * output_height) {
5411 dprintk(VIDC_ERR,
5412 "%s: scaling is not supported (%dx%d != %dx%d)\n",
5413 __func__, input_width, input_height,
5414 output_width, output_height);
5415 return -ENOTSUPP;
5416 }
5417
5418 dprintk(VIDC_DBG, "%s: supported WxH = %dx%d\n",
5419 __func__, input_width, input_height);
5420 return 0;
5421 }
5422
Chinmay Sawarkar81a02a32017-07-13 12:10:24 -07005423 rotation = msm_comm_g_ctrl_for_id(inst,
5424 V4L2_CID_MPEG_VIDC_VIDEO_ROTATION);
5425
5426 if ((output_width != output_height) &&
5427 (rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90 ||
5428 rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270)) {
5429
5430 output_width = inst->prop.height[CAPTURE_PORT];
5431 output_height = inst->prop.width[CAPTURE_PORT];
5432 dprintk(VIDC_DBG,
5433 "Rotation=%u Swapped Output W=%u H=%u to check scaling",
5434 rotation, output_width, output_height);
5435 }
5436
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005437 x_min = (1<<16)/inst->capability.scale_x.min;
5438 y_min = (1<<16)/inst->capability.scale_y.min;
5439 x_max = inst->capability.scale_x.max >> 16;
5440 y_max = inst->capability.scale_y.max >> 16;
5441
5442 if (input_height > output_height) {
5443 if (input_height > x_min * output_height) {
5444 dprintk(VIDC_ERR,
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005445 "Unsupported height min height %d vs %d\n",
5446 input_height / x_min, output_height);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005447 return -ENOTSUPP;
5448 }
5449 } else {
5450 if (output_height > x_max * input_height) {
5451 dprintk(VIDC_ERR,
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005452 "Unsupported height max height %d vs %d\n",
5453 x_max * input_height, output_height);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005454 return -ENOTSUPP;
5455 }
5456 }
5457 if (input_width > output_width) {
5458 if (input_width > y_min * output_width) {
5459 dprintk(VIDC_ERR,
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005460 "Unsupported width min width %d vs %d\n",
5461 input_width / y_min, output_width);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005462 return -ENOTSUPP;
5463 }
5464 } else {
5465 if (output_width > y_max * input_width) {
5466 dprintk(VIDC_ERR,
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005467 "Unsupported width max width %d vs %d\n",
5468 y_max * input_width, output_width);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005469 return -ENOTSUPP;
5470 }
5471 }
5472 return 0;
5473}
5474
5475int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
5476{
5477 struct msm_vidc_capability *capability;
5478 int rc = 0;
5479 struct hfi_device *hdev;
5480 struct msm_vidc_core *core;
Praneeth Paladugu38eb1982017-10-07 13:31:23 -07005481 u32 output_height, output_width, input_height, input_width;
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005482 u32 rotation;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005483
5484 if (!inst || !inst->core || !inst->core->device) {
5485 dprintk(VIDC_WARN, "%s: Invalid parameter\n", __func__);
5486 return -EINVAL;
5487 }
5488 capability = &inst->capability;
5489 hdev = inst->core->device;
5490 core = inst->core;
5491 rc = msm_vidc_load_supported(inst);
5492 if (rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005493 dprintk(VIDC_WARN,
5494 "%s: Hardware is overloaded\n", __func__);
5495 return rc;
5496 }
5497
5498 if (!is_thermal_permissible(core)) {
5499 dprintk(VIDC_WARN,
5500 "Thermal level critical, stop all active sessions!\n");
5501 return -ENOTSUPP;
5502 }
5503
Praneeth Paladugu38eb1982017-10-07 13:31:23 -07005504 output_height = inst->prop.height[CAPTURE_PORT];
5505 output_width = inst->prop.width[CAPTURE_PORT];
5506 input_height = inst->prop.height[OUTPUT_PORT];
5507 input_width = inst->prop.width[OUTPUT_PORT];
5508
Deepak Kushwahc221bed2017-12-02 11:48:54 +05305509 if (inst->session_type == MSM_VIDC_ENCODER && (input_width % 2 != 0 ||
5510 input_height % 2 != 0 || output_width % 2 != 0 ||
5511 output_height % 2 != 0)) {
Praneeth Paladugu38eb1982017-10-07 13:31:23 -07005512 dprintk(VIDC_ERR,
5513 "Height and Width should be even numbers for NV12\n");
5514 dprintk(VIDC_ERR,
5515 "Input WxH = (%u)x(%u), Output WxH = (%u)x(%u)\n",
5516 input_width, input_height,
5517 output_width, output_height);
5518 rc = -ENOTSUPP;
5519 }
5520
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005521 rotation = msm_comm_g_ctrl_for_id(inst,
5522 V4L2_CID_MPEG_VIDC_VIDEO_ROTATION);
5523
Chinmay Sawarkar553044f2017-10-17 10:45:29 -07005524 output_height = ALIGN(inst->prop.height[CAPTURE_PORT], 16);
5525 output_width = ALIGN(inst->prop.width[CAPTURE_PORT], 16);
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005526
5527 if ((output_width != output_height) &&
5528 (rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90 ||
5529 rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270)) {
5530
Chinmay Sawarkar553044f2017-10-17 10:45:29 -07005531 output_width = ALIGN(inst->prop.height[CAPTURE_PORT], 16);
5532 output_height = ALIGN(inst->prop.width[CAPTURE_PORT], 16);
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005533 dprintk(VIDC_DBG,
5534 "Rotation=%u Swapped Output W=%u H=%u to check capability",
5535 rotation, output_width, output_height);
5536 }
5537
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005538 if (!rc) {
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005539 if (output_width < capability->width.min ||
5540 output_height < capability->height.min) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005541 dprintk(VIDC_ERR,
5542 "Unsupported WxH = (%u)x(%u), min supported is - (%u)x(%u)\n",
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005543 output_width,
5544 output_height,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005545 capability->width.min,
5546 capability->height.min);
5547 rc = -ENOTSUPP;
5548 }
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005549 if (!rc && output_width > capability->width.max) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005550 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07005551 "Unsupported width = %u supported max width = %u\n",
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005552 output_width,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005553 capability->width.max);
5554 rc = -ENOTSUPP;
5555 }
5556
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005557 if (!rc && output_height * output_width >
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005558 capability->width.max * capability->height.max) {
5559 dprintk(VIDC_ERR,
5560 "Unsupported WxH = (%u)x(%u), max supported is - (%u)x(%u)\n",
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005561 output_width, output_height,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005562 capability->width.max, capability->height.max);
5563 rc = -ENOTSUPP;
5564 }
5565 }
5566 if (rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005567 dprintk(VIDC_ERR,
5568 "%s: Resolution unsupported\n", __func__);
5569 }
5570 return rc;
5571}
5572
Maheshwar Ajja279da4a2017-10-17 21:40:46 -07005573void msm_comm_generate_session_error(struct msm_vidc_inst *inst)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005574{
5575 enum hal_command_response cmd = HAL_SESSION_ERROR;
5576 struct msm_vidc_cb_cmd_done response = {0};
5577
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005578 if (!inst || !inst->core) {
5579 dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
5580 return;
5581 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07005582 dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005583 response.session_id = inst;
5584 response.status = VIDC_ERR_FAIL;
5585 handle_session_error(cmd, (void *)&response);
5586}
5587
Maheshwar Ajja279da4a2017-10-17 21:40:46 -07005588void msm_comm_generate_sys_error(struct msm_vidc_inst *inst)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005589{
5590 struct msm_vidc_core *core;
5591 enum hal_command_response cmd = HAL_SYS_ERROR;
5592 struct msm_vidc_cb_cmd_done response = {0};
5593
5594 if (!inst || !inst->core) {
5595 dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
5596 return;
5597 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07005598 dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005599 core = inst->core;
5600 response.device_id = (u32) core->id;
5601 handle_sys_error(cmd, (void *) &response);
5602
5603}
5604
5605int msm_comm_kill_session(struct msm_vidc_inst *inst)
5606{
5607 int rc = 0;
5608
5609 if (!inst || !inst->core || !inst->core->device) {
5610 dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
5611 return -EINVAL;
5612 } else if (!inst->session) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07005613 dprintk(VIDC_ERR, "%s: no session to kill for inst %pK\n",
5614 __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005615 return 0;
5616 }
5617
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07005618 dprintk(VIDC_WARN, "%s: inst %pK, session %x state %d\n", __func__,
Maheshwar Ajja4a0ba212017-10-31 11:26:37 -07005619 inst, hash32_ptr(inst->session), inst->state);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005620 /*
5621 * We're internally forcibly killing the session, if fw is aware of
5622 * the session send session_abort to firmware to clean up and release
5623 * the session, else just kill the session inside the driver.
5624 */
5625 if ((inst->state >= MSM_VIDC_OPEN_DONE &&
5626 inst->state < MSM_VIDC_CLOSE_DONE) ||
5627 inst->state == MSM_VIDC_CORE_INVALID) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07005628 rc = msm_comm_session_abort(inst);
5629 if (rc) {
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07005630 dprintk(VIDC_ERR,
5631 "%s: inst %pK session %x abort failed\n",
5632 __func__, inst, hash32_ptr(inst->session));
Maheshwar Ajja99422322017-07-07 17:31:15 -07005633 change_inst_state(inst, MSM_VIDC_CORE_INVALID);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005634 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005635 }
5636
Maheshwar Ajja99422322017-07-07 17:31:15 -07005637 change_inst_state(inst, MSM_VIDC_CLOSE_DONE);
5638 msm_comm_session_clean(inst);
5639
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07005640 dprintk(VIDC_WARN, "%s: inst %pK session %x handled\n", __func__,
5641 inst, hash32_ptr(inst->session));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005642 return rc;
5643}
5644
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005645int msm_comm_smem_alloc(struct msm_vidc_inst *inst,
5646 size_t size, u32 align, u32 flags, enum hal_buffer buffer_type,
5647 int map_kernel, struct msm_smem *smem)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005648{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005649 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005650
5651 if (!inst || !inst->core) {
5652 dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005653 return -EINVAL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005654 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005655 rc = msm_smem_alloc(inst->mem_client, size, align,
5656 flags, buffer_type, map_kernel, smem);
5657 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005658}
5659
5660void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem)
5661{
5662 if (!inst || !inst->core || !mem) {
5663 dprintk(VIDC_ERR,
5664 "%s: invalid params: %pK %pK\n", __func__, inst, mem);
5665 return;
5666 }
5667 msm_smem_free(inst->mem_client, mem);
5668}
5669
5670int msm_comm_smem_cache_operations(struct msm_vidc_inst *inst,
5671 struct msm_smem *mem, enum smem_cache_ops cache_ops)
5672{
5673 if (!inst || !mem) {
5674 dprintk(VIDC_ERR,
5675 "%s: invalid params: %pK %pK\n", __func__, inst, mem);
5676 return -EINVAL;
5677 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005678 return msm_smem_cache_operations(inst->mem_client, mem->handle,
5679 mem->offset, mem->size, cache_ops);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005680}
5681
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005682int msm_comm_qbuf_cache_operations(struct msm_vidc_inst *inst,
5683 struct v4l2_buffer *b)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005684{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005685 int rc = 0, i;
5686 void *dma_buf;
5687 void *handle;
5688 bool skip;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005689
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005690 if (!inst || !b) {
5691 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
5692 __func__, inst, b);
5693 return -EINVAL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005694 }
5695
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005696 for (i = 0; i < b->length; i++) {
5697 unsigned long offset, size;
5698 enum smem_cache_ops cache_ops;
5699
5700 dma_buf = msm_smem_get_dma_buf(b->m.planes[i].m.fd);
5701 handle = msm_smem_get_handle(inst->mem_client, dma_buf);
5702
5703 offset = b->m.planes[i].data_offset;
Maheshwar Ajja56592ec2017-11-27 12:32:33 -08005704 size = b->m.planes[i].length - offset;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005705 cache_ops = SMEM_CACHE_INVALIDATE;
5706 skip = false;
5707
5708 if (inst->session_type == MSM_VIDC_DECODER) {
5709 if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
5710 if (!i) { /* bitstream */
5711 size = b->m.planes[i].bytesused;
5712 cache_ops = SMEM_CACHE_CLEAN_INVALIDATE;
5713 }
5714 } else if (b->type ==
5715 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
5716 if (!i) { /* yuv */
5717 /* all values are correct */
5718 }
5719 }
5720 } else if (inst->session_type == MSM_VIDC_ENCODER) {
5721 if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
5722 if (!i) { /* yuv */
5723 size = b->m.planes[i].bytesused;
5724 cache_ops = SMEM_CACHE_CLEAN_INVALIDATE;
5725 } else { /* extradata */
5726 cache_ops = SMEM_CACHE_CLEAN_INVALIDATE;
5727 }
5728 } else if (b->type ==
5729 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
5730 if (!i) { /* bitstream */
5731 /* all values are correct */
5732 }
5733 }
5734 }
5735
5736 if (!skip) {
5737 rc = msm_smem_cache_operations(inst->mem_client, handle,
5738 offset, size, cache_ops);
5739 if (rc)
5740 print_v4l2_buffer(VIDC_ERR,
5741 "qbuf cache ops failed", inst, b);
5742 }
5743
5744 msm_smem_put_handle(inst->mem_client, handle);
5745 msm_smem_put_dma_buf(dma_buf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005746 }
5747
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005748 return rc;
5749}
5750
5751int msm_comm_dqbuf_cache_operations(struct msm_vidc_inst *inst,
5752 struct v4l2_buffer *b)
5753{
5754 int rc = 0, i;
5755 void *dma_buf;
5756 void *handle;
5757 bool skip;
5758
5759 if (!inst || !b) {
5760 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
5761 __func__, inst, b);
5762 return -EINVAL;
5763 }
5764
5765 for (i = 0; i < b->length; i++) {
5766 unsigned long offset, size;
5767 enum smem_cache_ops cache_ops;
5768
5769 dma_buf = msm_smem_get_dma_buf(b->m.planes[i].m.fd);
5770 handle = msm_smem_get_handle(inst->mem_client, dma_buf);
5771
5772 offset = b->m.planes[i].data_offset;
Maheshwar Ajja56592ec2017-11-27 12:32:33 -08005773 size = b->m.planes[i].length - offset;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005774 cache_ops = SMEM_CACHE_INVALIDATE;
5775 skip = false;
5776
5777 if (inst->session_type == MSM_VIDC_DECODER) {
5778 if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
5779 if (!i) /* bitstream */
5780 skip = true;
5781 } else if (b->type ==
5782 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
Maheshwar Ajja6d003902017-11-22 09:30:24 -08005783 if (!i) { /* yuv */
5784 /* all values are correct */
5785 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005786 }
5787 } else if (inst->session_type == MSM_VIDC_ENCODER) {
5788 if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Maheshwar Ajja07dc9182017-07-28 22:08:15 -07005789 /* yuv and extradata */
5790 skip = true;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005791 } else if (b->type ==
5792 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
Maheshwar Ajja56592ec2017-11-27 12:32:33 -08005793 if (!i) { /* bitstream */
5794 /*
5795 * Include vp8e header bytes as well
5796 * by making offset equal to zero
5797 */
5798 offset = 0;
5799 size = b->m.planes[i].bytesused +
5800 b->m.planes[i].data_offset;
5801 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005802 }
5803 }
5804
5805 if (!skip) {
5806 rc = msm_smem_cache_operations(inst->mem_client, handle,
5807 offset, size, cache_ops);
5808 if (rc)
5809 print_v4l2_buffer(VIDC_ERR,
5810 "dqbuf cache ops failed", inst, b);
5811 }
5812
5813 msm_smem_put_handle(inst->mem_client, handle);
5814 msm_smem_put_dma_buf(dma_buf);
5815 }
5816
5817 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005818}
5819
5820void msm_vidc_fw_unload_handler(struct work_struct *work)
5821{
5822 struct msm_vidc_core *core = NULL;
5823 struct hfi_device *hdev = NULL;
5824 int rc = 0;
5825
5826 core = container_of(work, struct msm_vidc_core, fw_unload_work.work);
5827 if (!core || !core->device) {
5828 dprintk(VIDC_ERR, "%s - invalid work or core handle\n",
5829 __func__);
5830 return;
5831 }
5832
5833 hdev = core->device;
5834
5835 mutex_lock(&core->lock);
5836 if (list_empty(&core->instances) &&
5837 core->state != VIDC_CORE_UNINIT) {
5838 if (core->state > VIDC_CORE_INIT) {
5839 dprintk(VIDC_DBG, "Calling vidc_hal_core_release\n");
5840 rc = call_hfi_op(hdev, core_release,
5841 hdev->hfi_device_data);
5842 if (rc) {
5843 dprintk(VIDC_ERR,
5844 "Failed to release core, id = %d\n",
5845 core->id);
5846 mutex_unlock(&core->lock);
5847 return;
5848 }
5849 }
5850 core->state = VIDC_CORE_UNINIT;
5851 kfree(core->capabilities);
5852 core->capabilities = NULL;
5853 }
5854 mutex_unlock(&core->lock);
5855}
5856
5857int msm_comm_set_color_format(struct msm_vidc_inst *inst,
5858 enum hal_buffer buffer_type, int fourcc)
5859{
5860 struct hal_uncompressed_format_select hal_fmt = {0};
5861 enum hal_uncompressed_format format = HAL_UNUSED_COLOR;
5862 int rc = 0;
5863 struct hfi_device *hdev;
5864
5865 if (!inst || !inst->core || !inst->core->device) {
5866 dprintk(VIDC_ERR, "%s - invalid param\n", __func__);
5867 return -EINVAL;
5868 }
5869
5870 hdev = inst->core->device;
5871
Praneeth Paladugu319e7922017-03-16 11:09:06 -07005872 format = msm_comm_get_hal_uncompressed(fourcc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005873 if (format == HAL_UNUSED_COLOR) {
5874 dprintk(VIDC_ERR, "Using unsupported colorformat %#x\n",
5875 fourcc);
5876 rc = -ENOTSUPP;
5877 goto exit;
5878 }
5879
5880 hal_fmt.buffer_type = buffer_type;
5881 hal_fmt.format = format;
5882
5883 rc = call_hfi_op(hdev, session_set_property, inst->session,
5884 HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT, &hal_fmt);
5885 if (rc)
5886 dprintk(VIDC_ERR,
5887 "Failed to set input color format\n");
5888 else
5889 dprintk(VIDC_DBG, "Setting uncompressed colorformat to %#x\n",
5890 format);
5891
5892exit:
5893 return rc;
5894}
5895
5896int msm_vidc_comm_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a)
5897{
5898 u32 property_id = 0;
5899 u64 us_per_frame = 0;
5900 void *pdata;
5901 int rc = 0, fps = 0;
5902 struct hal_frame_rate frame_rate;
5903 struct hfi_device *hdev;
5904
5905 if (!inst || !inst->core || !inst->core->device || !a) {
5906 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
5907 return -EINVAL;
5908 }
5909
5910 hdev = inst->core->device;
5911 property_id = HAL_CONFIG_FRAME_RATE;
5912
5913 if (a->parm.output.timeperframe.denominator) {
5914 switch (a->type) {
5915 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
5916 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
5917 us_per_frame = a->parm.output.timeperframe.numerator *
5918 (u64)USEC_PER_SEC;
5919 do_div(us_per_frame, a->parm.output.
5920 timeperframe.denominator);
5921 break;
5922 default:
5923 dprintk(VIDC_ERR,
5924 "Scale clocks : Unknown buffer type %d\n",
5925 a->type);
5926 break;
5927 }
5928 }
5929
5930 if (!us_per_frame) {
5931 dprintk(VIDC_ERR,
5932 "Failed to scale clocks : time between frames is 0\n");
5933 rc = -EINVAL;
5934 goto exit;
5935 }
5936
Maria Yu5d853f82017-09-26 16:13:19 +08005937 fps = us_per_frame > USEC_PER_SEC ?
5938 0 : USEC_PER_SEC / (u32)us_per_frame;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005939
5940 if (fps % 15 == 14 || fps % 24 == 23)
5941 fps = fps + 1;
5942 else if ((fps > 1) && (fps % 24 == 1 || fps % 15 == 1))
5943 fps = fps - 1;
5944
Praneeth Paladugue1679112017-01-27 10:07:15 -08005945 if (fps < inst->capability.frame_rate.min ||
5946 fps > inst->capability.frame_rate.max) {
5947 dprintk(VIDC_ERR,
5948 "FPS is out of limits : fps = %d Min = %d, Max = %d\n",
5949 fps, inst->capability.frame_rate.min,
5950 inst->capability.frame_rate.max);
5951 rc = -EINVAL;
5952 goto exit;
5953 }
5954
Maheshwar Ajja266828742017-04-20 15:48:33 -07005955 dprintk(VIDC_PROF, "reported fps changed for %pK: %d->%d\n",
5956 inst, inst->prop.fps, fps);
5957 inst->prop.fps = fps;
Surajit Poddere502daa2017-05-30 19:17:45 +05305958 if (inst->session_type == MSM_VIDC_ENCODER &&
5959 get_hal_codec(inst->fmts[CAPTURE_PORT].fourcc) !=
5960 HAL_VIDEO_CODEC_TME) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005961 frame_rate.frame_rate = inst->prop.fps * BIT(16);
5962 frame_rate.buffer_type = HAL_BUFFER_OUTPUT;
5963 pdata = &frame_rate;
Maheshwar Ajja266828742017-04-20 15:48:33 -07005964 rc = call_hfi_op(hdev, session_set_property,
5965 inst->session, property_id, pdata);
5966 if (rc)
5967 dprintk(VIDC_WARN,
5968 "Failed to set frame rate %d\n", rc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005969 }
5970exit:
5971 return rc;
5972}
5973
5974void msm_comm_print_inst_info(struct msm_vidc_inst *inst)
5975{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005976 struct msm_vidc_buffer *mbuf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005977 struct internal_buf *buf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005978 bool is_decode = false;
5979 enum vidc_ports port;
5980 bool is_secure = false;
5981
5982 if (!inst) {
5983 dprintk(VIDC_ERR, "%s - invalid param %pK\n",
5984 __func__, inst);
5985 return;
5986 }
5987
5988 is_decode = inst->session_type == MSM_VIDC_DECODER;
5989 port = is_decode ? OUTPUT_PORT : CAPTURE_PORT;
5990 is_secure = inst->flags & VIDC_SECURE;
5991 dprintk(VIDC_ERR,
5992 "%s session, %s, Codec type: %s HxW: %d x %d fps: %d bitrate: %d bit-depth: %s\n",
5993 is_decode ? "Decode" : "Encode",
5994 is_secure ? "Secure" : "Non-Secure",
5995 inst->fmts[port].name,
5996 inst->prop.height[port], inst->prop.width[port],
5997 inst->prop.fps, inst->prop.bitrate,
5998 !inst->bit_depth ? "8" : "10");
5999
6000 dprintk(VIDC_ERR,
6001 "---Buffer details for inst: %pK of type: %d---\n",
6002 inst, inst->session_type);
6003 mutex_lock(&inst->registeredbufs.lock);
6004 dprintk(VIDC_ERR, "registered buffer list:\n");
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006005 list_for_each_entry(mbuf, &inst->registeredbufs.list, list)
6006 print_vidc_buffer(VIDC_ERR, "buf", inst, mbuf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08006007 mutex_unlock(&inst->registeredbufs.lock);
6008
6009 mutex_lock(&inst->scratchbufs.lock);
6010 dprintk(VIDC_ERR, "scratch buffer list:\n");
6011 list_for_each_entry(buf, &inst->scratchbufs.list, list)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006012 dprintk(VIDC_ERR, "type: %d addr: %x size: %u\n",
6013 buf->buffer_type, buf->smem.device_addr,
6014 buf->smem.size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08006015 mutex_unlock(&inst->scratchbufs.lock);
6016
6017 mutex_lock(&inst->persistbufs.lock);
6018 dprintk(VIDC_ERR, "persist buffer list:\n");
6019 list_for_each_entry(buf, &inst->persistbufs.list, list)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006020 dprintk(VIDC_ERR, "type: %d addr: %x size: %u\n",
6021 buf->buffer_type, buf->smem.device_addr,
6022 buf->smem.size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08006023 mutex_unlock(&inst->persistbufs.lock);
6024
6025 mutex_lock(&inst->outputbufs.lock);
6026 dprintk(VIDC_ERR, "dpb buffer list:\n");
6027 list_for_each_entry(buf, &inst->outputbufs.list, list)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006028 dprintk(VIDC_ERR, "type: %d addr: %x size: %u\n",
6029 buf->buffer_type, buf->smem.device_addr,
6030 buf->smem.size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08006031 mutex_unlock(&inst->outputbufs.lock);
6032}
6033
Umesh Pandeybb3fad02017-03-31 16:49:42 -07006034int msm_comm_session_continue(void *instance)
6035{
6036 struct msm_vidc_inst *inst = instance;
6037 int rc = 0;
6038 struct hfi_device *hdev;
6039
6040 if (!inst || !inst->core || !inst->core->device)
6041 return -EINVAL;
6042 hdev = inst->core->device;
6043 mutex_lock(&inst->lock);
Praneeth Paladugu4e2143c2017-05-15 16:24:10 -07006044 if (inst->state >= MSM_VIDC_RELEASE_RESOURCES_DONE ||
Maheshwar Ajja99422322017-07-07 17:31:15 -07006045 inst->state < MSM_VIDC_START_DONE) {
Praneeth Paladugu4e2143c2017-05-15 16:24:10 -07006046 dprintk(VIDC_DBG,
6047 "Inst %pK : Not in valid state to call %s\n",
6048 inst, __func__);
6049 goto sess_continue_fail;
6050 }
Umesh Pandeybb3fad02017-03-31 16:49:42 -07006051 if (inst->session_type == MSM_VIDC_DECODER && inst->in_reconfig) {
6052 dprintk(VIDC_DBG, "send session_continue\n");
6053 rc = call_hfi_op(hdev, session_continue,
6054 (void *)inst->session);
6055 if (rc) {
6056 dprintk(VIDC_ERR,
6057 "failed to send session_continue\n");
6058 rc = -EINVAL;
6059 goto sess_continue_fail;
6060 }
6061 inst->in_reconfig = false;
Surajit Poddereef1c482017-08-30 17:05:20 +05306062 inst->prop.height[CAPTURE_PORT] = inst->reconfig_height;
6063 inst->prop.width[CAPTURE_PORT] = inst->reconfig_width;
6064 inst->prop.height[OUTPUT_PORT] = inst->reconfig_height;
6065 inst->prop.width[OUTPUT_PORT] = inst->reconfig_width;
Prateek Shrivastava08846ae2018-01-05 16:54:59 +05306066 if (msm_comm_get_stream_output_mode(inst) ==
6067 HAL_VIDEO_DECODER_SECONDARY) {
6068 rc = msm_comm_queue_output_buffers(inst);
6069 if (rc) {
6070 dprintk(VIDC_ERR,
6071 "Failed to queue output buffers: %d\n",
6072 rc);
6073 goto sess_continue_fail;
6074 }
6075 }
Umesh Pandeybb3fad02017-03-31 16:49:42 -07006076 } else if (inst->session_type == MSM_VIDC_ENCODER) {
6077 dprintk(VIDC_DBG,
6078 "session_continue not supported for encoder");
6079 } else {
6080 dprintk(VIDC_ERR,
6081 "session_continue called in wrong state for decoder");
6082 }
Praneeth Paladugu4e2143c2017-05-15 16:24:10 -07006083
Umesh Pandeybb3fad02017-03-31 16:49:42 -07006084sess_continue_fail:
6085 mutex_unlock(&inst->lock);
6086 return rc;
6087}
Umesh Pandeyf2995f82017-05-01 16:44:45 -07006088
6089u32 get_frame_size_nv12(int plane, u32 height, u32 width)
6090{
6091 return VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
6092}
6093
6094u32 get_frame_size_nv12_ubwc(int plane, u32 height, u32 width)
6095{
6096 return VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height);
6097}
6098
6099u32 get_frame_size_rgba(int plane, u32 height, u32 width)
6100{
6101 return VENUS_BUFFER_SIZE(COLOR_FMT_RGBA8888, width, height);
6102}
6103
6104u32 get_frame_size_nv21(int plane, u32 height, u32 width)
6105{
6106 return VENUS_BUFFER_SIZE(COLOR_FMT_NV21, width, height);
6107}
6108
6109u32 get_frame_size_tp10_ubwc(int plane, u32 height, u32 width)
6110{
6111 return VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
6112}
Shivendra Kakraniac1f60e02017-04-13 00:07:26 -07006113
Zhongbo Shi6bd5f5f2017-08-16 17:20:08 +08006114u32 get_frame_size_p010(int plane, u32 height, u32 width)
6115{
6116 return VENUS_BUFFER_SIZE(COLOR_FMT_P010, width, height);
6117}
6118
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006119
6120void print_vidc_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
6121 struct msm_vidc_buffer *mbuf)
6122{
6123 struct vb2_buffer *vb2 = NULL;
6124
6125 if (!(tag & msm_vidc_debug) || !inst || !mbuf)
6126 return;
6127
6128 vb2 = &mbuf->vvb.vb2_buf;
6129
6130 if (vb2->num_planes == 1)
6131 dprintk(tag,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006132 "%s: %s: %x : idx %2d fd %d off %d daddr %x size %d filled %d flags 0x%x ts %lld refcnt %d mflags 0x%x\n",
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006133 str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6134 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6135 vb2->index, vb2->planes[0].m.fd,
6136 vb2->planes[0].data_offset, mbuf->smem[0].device_addr,
6137 vb2->planes[0].length, vb2->planes[0].bytesused,
6138 mbuf->vvb.flags, mbuf->vvb.vb2_buf.timestamp,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006139 mbuf->smem[0].refcount, mbuf->flags);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006140 else
6141 dprintk(tag,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006142 "%s: %s: %x : idx %2d fd %d off %d daddr %x size %d filled %d flags 0x%x ts %lld refcnt %d mflags 0x%x, extradata: fd %d off %d daddr %x size %d filled %d refcnt %d\n",
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006143 str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6144 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6145 vb2->index, vb2->planes[0].m.fd,
6146 vb2->planes[0].data_offset, mbuf->smem[0].device_addr,
6147 vb2->planes[0].length, vb2->planes[0].bytesused,
6148 mbuf->vvb.flags, mbuf->vvb.vb2_buf.timestamp,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006149 mbuf->smem[0].refcount, mbuf->flags,
6150 vb2->planes[1].m.fd, vb2->planes[1].data_offset,
6151 mbuf->smem[1].device_addr, vb2->planes[1].length,
6152 vb2->planes[1].bytesused, mbuf->smem[1].refcount);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006153}
6154
6155void print_vb2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
6156 struct vb2_buffer *vb2)
6157{
6158 if (!(tag & msm_vidc_debug) || !inst || !vb2)
6159 return;
6160
6161 if (vb2->num_planes == 1)
6162 dprintk(tag,
6163 "%s: %s: %x : idx %2d fd %d off %d size %d filled %d\n",
6164 str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6165 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6166 vb2->index, vb2->planes[0].m.fd,
6167 vb2->planes[0].data_offset, vb2->planes[0].length,
6168 vb2->planes[0].bytesused);
6169 else
6170 dprintk(tag,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006171 "%s: %s: %x : idx %2d fd %d off %d size %d filled %d, extradata: fd %d off %d size %d filled %d\n",
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006172 str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6173 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6174 vb2->index, vb2->planes[0].m.fd,
6175 vb2->planes[0].data_offset, vb2->planes[0].length,
6176 vb2->planes[0].bytesused, vb2->planes[1].m.fd,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006177 vb2->planes[1].data_offset, vb2->planes[1].length,
6178 vb2->planes[1].bytesused);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006179}
6180
6181void print_v4l2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
6182 struct v4l2_buffer *v4l2)
6183{
6184 if (!(tag & msm_vidc_debug) || !inst || !v4l2)
6185 return;
6186
6187 if (v4l2->length == 1)
6188 dprintk(tag,
6189 "%s: %s: %x : idx %2d fd %d off %d size %d filled %d\n",
6190 str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6191 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6192 v4l2->index, v4l2->m.planes[0].m.fd,
6193 v4l2->m.planes[0].data_offset,
6194 v4l2->m.planes[0].length,
6195 v4l2->m.planes[0].bytesused);
6196 else
6197 dprintk(tag,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006198 "%s: %s: %x : idx %2d fd %d off %d size %d filled %d, extradata: fd %d off %d size %d filled %d\n",
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006199 str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6200 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6201 v4l2->index, v4l2->m.planes[0].m.fd,
6202 v4l2->m.planes[0].data_offset,
6203 v4l2->m.planes[0].length,
6204 v4l2->m.planes[0].bytesused,
6205 v4l2->m.planes[1].m.fd,
6206 v4l2->m.planes[1].data_offset,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006207 v4l2->m.planes[1].length,
6208 v4l2->m.planes[1].bytesused);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006209}
6210
6211bool msm_comm_compare_vb2_plane(struct msm_vidc_inst *inst,
6212 struct msm_vidc_buffer *mbuf, struct vb2_buffer *vb2, u32 i)
6213{
6214 struct vb2_buffer *vb;
6215
6216 if (!inst || !mbuf || !vb2) {
6217 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
6218 __func__, inst, mbuf, vb2);
6219 return false;
6220 }
6221
6222 vb = &mbuf->vvb.vb2_buf;
6223 if (vb->planes[i].m.fd == vb2->planes[i].m.fd &&
6224 vb->planes[i].data_offset == vb2->planes[i].data_offset &&
6225 vb->planes[i].length == vb2->planes[i].length) {
6226 return true;
6227 }
6228
6229 return false;
6230}
6231
6232bool msm_comm_compare_vb2_planes(struct msm_vidc_inst *inst,
6233 struct msm_vidc_buffer *mbuf, struct vb2_buffer *vb2)
6234{
6235 int i = 0;
6236 struct vb2_buffer *vb;
6237
6238 if (!inst || !mbuf || !vb2) {
6239 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
6240 __func__, inst, mbuf, vb2);
6241 return false;
6242 }
6243
6244 vb = &mbuf->vvb.vb2_buf;
6245
6246 if (vb->num_planes != vb2->num_planes)
6247 return false;
6248
6249 for (i = 0; i < vb->num_planes; i++) {
6250 if (!msm_comm_compare_vb2_plane(inst, mbuf, vb2, i))
6251 return false;
6252 }
6253
6254 return true;
6255}
6256
6257bool msm_comm_compare_dma_plane(struct msm_vidc_inst *inst,
6258 struct msm_vidc_buffer *mbuf, unsigned long *dma_planes, u32 i)
6259{
6260 if (!inst || !mbuf || !dma_planes) {
6261 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
6262 __func__, inst, mbuf, dma_planes);
6263 return false;
6264 }
6265
6266 if ((unsigned long)mbuf->smem[i].dma_buf == dma_planes[i])
6267 return true;
6268
6269 return false;
6270}
6271
6272bool msm_comm_compare_dma_planes(struct msm_vidc_inst *inst,
6273 struct msm_vidc_buffer *mbuf, unsigned long *dma_planes)
6274{
6275 int i = 0;
6276 struct vb2_buffer *vb;
6277
6278 if (!inst || !mbuf || !dma_planes) {
6279 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
6280 __func__, inst, mbuf, dma_planes);
6281 return false;
6282 }
6283
6284 vb = &mbuf->vvb.vb2_buf;
6285 for (i = 0; i < vb->num_planes; i++) {
6286 if (!msm_comm_compare_dma_plane(inst, mbuf, dma_planes, i))
6287 return false;
6288 }
6289
6290 return true;
6291}
6292
6293
6294bool msm_comm_compare_device_plane(struct msm_vidc_buffer *mbuf,
6295 u32 *planes, u32 i)
6296{
6297 if (!mbuf || !planes) {
6298 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK\n",
6299 __func__, mbuf, planes);
6300 return false;
6301 }
6302
6303 if (mbuf->smem[i].device_addr == planes[i])
6304 return true;
6305
6306 return false;
6307}
6308
6309bool msm_comm_compare_device_planes(struct msm_vidc_buffer *mbuf,
6310 u32 *planes)
6311{
6312 int i = 0;
6313
6314 if (!mbuf || !planes)
6315 return false;
6316
6317 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
6318 if (!msm_comm_compare_device_plane(mbuf, planes, i))
6319 return false;
6320 }
6321
6322 return true;
6323}
6324
6325struct msm_vidc_buffer *msm_comm_get_buffer_using_device_planes(
6326 struct msm_vidc_inst *inst, u32 *planes)
6327{
6328 struct msm_vidc_buffer *mbuf;
6329 bool found = false;
6330
6331 mutex_lock(&inst->registeredbufs.lock);
6332 found = false;
6333 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
6334 if (msm_comm_compare_device_planes(mbuf, planes)) {
6335 found = true;
6336 break;
6337 }
6338 }
6339 mutex_unlock(&inst->registeredbufs.lock);
6340 if (!found) {
6341 dprintk(VIDC_ERR,
6342 "%s: data_addr %x, extradata_addr %x not found\n",
6343 __func__, planes[0], planes[1]);
6344 mbuf = NULL;
6345 }
6346
6347 return mbuf;
6348}
6349
6350int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst,
6351 struct msm_vidc_buffer *mbuf)
6352{
6353 int rc;
6354 struct vb2_buffer *vb;
6355
6356 if (!inst || !mbuf) {
6357 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
6358 __func__, inst, mbuf);
6359 return -EINVAL;
6360 }
6361
6362 vb = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
6363 if (!vb) {
6364 print_vidc_buffer(VIDC_ERR,
6365 "vb not found for buf", inst, mbuf);
6366 return -EINVAL;
6367 }
6368
6369 vb->planes[0].bytesused = 0;
6370 rc = msm_comm_vb2_buffer_done(inst, vb);
6371 if (rc)
6372 print_vidc_buffer(VIDC_ERR,
6373 "vb2_buffer_done failed for", inst, mbuf);
6374
6375 return rc;
6376}
6377
6378struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst,
6379 struct vb2_buffer *vb2)
6380{
6381 int rc = 0;
6382 struct vb2_v4l2_buffer *vbuf;
6383 struct vb2_buffer *vb;
6384 unsigned long dma_planes[VB2_MAX_PLANES] = {0};
6385 struct msm_vidc_buffer *mbuf;
6386 bool found = false;
6387 int i;
6388
6389 if (!inst || !vb2) {
6390 dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
6391 return NULL;
6392 }
6393
6394 for (i = 0; i < vb2->num_planes; i++) {
6395 /*
6396 * always compare dma_buf addresses which is guaranteed
6397 * to be same across the processes (duplicate fds).
6398 */
Maheshwar Ajja07dc9182017-07-28 22:08:15 -07006399 dma_planes[i] = (unsigned long)msm_smem_get_dma_buf(
6400 vb2->planes[i].m.fd);
6401 if (!dma_planes[i])
6402 return NULL;
6403 msm_smem_put_dma_buf((struct dma_buf *)dma_planes[i]);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006404 }
6405
6406 mutex_lock(&inst->registeredbufs.lock);
Maheshwar Ajja848ab822017-09-28 20:33:05 -07006407 if (inst->session_type == MSM_VIDC_DECODER) {
6408 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
6409 if (msm_comm_compare_dma_planes(inst, mbuf,
6410 dma_planes)) {
6411 found = true;
6412 break;
6413 }
6414 }
6415 } else {
6416 /*
6417 * for encoder, client may queue the same buffer with different
6418 * fd before driver returned old buffer to the client. This
6419 * buffer should be treated as new buffer. Search the list with
6420 * fd so that it will be treated as new msm_vidc_buffer.
6421 */
6422 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
6423 if (msm_comm_compare_vb2_planes(inst, mbuf, vb2)) {
6424 found = true;
6425 break;
6426 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006427 }
6428 }
6429
6430 if (!found) {
6431 /* this is new vb2_buffer */
6432 mbuf = kzalloc(sizeof(struct msm_vidc_buffer), GFP_KERNEL);
6433 if (!mbuf) {
6434 dprintk(VIDC_ERR, "%s: alloc msm_vidc_buffer failed\n",
6435 __func__);
6436 rc = -ENOMEM;
6437 goto exit;
6438 }
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006439 kref_init(&mbuf->kref);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006440 }
6441
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006442 /* Initially assume all the buffer are going to be deferred */
6443 mbuf->flags |= MSM_VIDC_FLAG_DEFERRED;
6444
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006445 vbuf = to_vb2_v4l2_buffer(vb2);
6446 memcpy(&mbuf->vvb, vbuf, sizeof(struct vb2_v4l2_buffer));
6447 vb = &mbuf->vvb.vb2_buf;
6448
6449 for (i = 0; i < vb->num_planes; i++) {
6450 mbuf->smem[i].buffer_type = get_hal_buffer_type(vb->type, i);
6451 mbuf->smem[i].fd = vb->planes[i].m.fd;
6452 mbuf->smem[i].offset = vb->planes[i].data_offset;
6453 mbuf->smem[i].size = vb->planes[i].length;
6454 rc = msm_smem_map_dma_buf(inst, &mbuf->smem[i]);
6455 if (rc) {
6456 dprintk(VIDC_ERR, "%s: map failed.\n", __func__);
6457 goto exit;
6458 }
6459 /* increase refcount as we get both fbd and rbr */
6460 rc = msm_smem_map_dma_buf(inst, &mbuf->smem[i]);
6461 if (rc) {
6462 dprintk(VIDC_ERR, "%s: map failed..\n", __func__);
6463 goto exit;
6464 }
6465 }
6466
6467 /* special handling for decoder */
6468 if (inst->session_type == MSM_VIDC_DECODER) {
6469 if (found) {
6470 rc = -EEXIST;
6471 } else {
6472 bool found_plane0 = false;
6473 struct msm_vidc_buffer *temp;
6474 /*
6475 * client might have queued same plane[0] but different
6476 * plane[1] search plane[0] and if found don't queue the
6477 * buffer, the buffer will be queued when rbr event
6478 * arrived.
6479 */
6480 list_for_each_entry(temp, &inst->registeredbufs.list,
6481 list) {
6482 if (msm_comm_compare_dma_plane(inst, temp,
6483 dma_planes, 0)) {
6484 found_plane0 = true;
6485 break;
6486 }
6487 }
6488 if (found_plane0)
6489 rc = -EEXIST;
6490 }
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006491 /*
6492 * If RBR pending on this buffer then enable RBR_PENDING flag
6493 * and clear the DEFERRED flag to avoid this buffer getting
6494 * queued to video hardware in msm_comm_qbuf() which tries to
6495 * queue all the DEFERRED buffers.
6496 */
6497 if (rc == -EEXIST) {
6498 mbuf->flags |= MSM_VIDC_FLAG_RBR_PENDING;
6499 mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
6500 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006501 }
6502
6503 /* add the new buffer to list */
6504 if (!found)
6505 list_add_tail(&mbuf->list, &inst->registeredbufs.list);
6506
6507 mutex_unlock(&inst->registeredbufs.lock);
6508 if (rc == -EEXIST) {
6509 print_vidc_buffer(VIDC_DBG, "qbuf upon rbr", inst, mbuf);
6510 return ERR_PTR(rc);
6511 }
6512
6513 return mbuf;
6514
6515exit:
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006516 dprintk(VIDC_ERR, "%s: rc %d\n", __func__, rc);
6517 msm_comm_unmap_vidc_buffer(inst, mbuf);
6518 if (!found)
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006519 kref_put_mbuf(mbuf);
6520 mutex_unlock(&inst->registeredbufs.lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006521
6522 return ERR_PTR(rc);
6523}
6524
6525void msm_comm_put_vidc_buffer(struct msm_vidc_inst *inst,
6526 struct msm_vidc_buffer *mbuf)
6527{
6528 struct msm_vidc_buffer *temp;
6529 bool found = false;
6530 int i = 0;
6531
6532 if (!inst || !mbuf) {
6533 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
6534 __func__, inst, mbuf);
6535 return;
6536 }
6537
6538 mutex_lock(&inst->registeredbufs.lock);
6539 /* check if mbuf was not removed by any chance */
6540 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
6541 if (msm_comm_compare_vb2_planes(inst, mbuf,
6542 &temp->vvb.vb2_buf)) {
6543 found = true;
6544 break;
6545 }
6546 }
6547 if (!found) {
6548 print_vidc_buffer(VIDC_ERR, "buf was removed", inst, mbuf);
6549 goto unlock;
6550 }
6551
6552 print_vidc_buffer(VIDC_DBG, "dqbuf", inst, mbuf);
6553 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
6554 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
6555 print_vidc_buffer(VIDC_ERR,
6556 "dqbuf: unmap failed.", inst, mbuf);
6557
6558 if (!(mbuf->vvb.flags & V4L2_QCOM_BUF_FLAG_READONLY)) {
6559 /* rbr won't come for this buffer */
6560 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
6561 print_vidc_buffer(VIDC_ERR,
6562 "dqbuf: unmap failed..", inst, mbuf);
Maheshwar Ajja1352fb72017-10-18 17:38:55 -07006563 } else {
6564 /* RBR event expected */
6565 mbuf->flags |= MSM_VIDC_FLAG_RBR_PENDING;
6566 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006567 }
6568 /*
6569 * remove the entry if plane[0].refcount is zero else
6570 * don't remove as client queued same buffer that's why
6571 * plane[0].refcount is not zero
6572 */
6573 if (!mbuf->smem[0].refcount) {
6574 list_del(&mbuf->list);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006575 kref_put_mbuf(mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006576 }
6577unlock:
6578 mutex_unlock(&inst->registeredbufs.lock);
6579}
6580
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006581void handle_release_buffer_reference(struct msm_vidc_inst *inst,
6582 struct msm_vidc_buffer *mbuf)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006583{
6584 int rc = 0;
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006585 struct msm_vidc_buffer *temp;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006586 bool found = false;
6587 int i = 0;
6588
Surajit Podder0d812bf2018-02-02 13:37:24 +05306589 mutex_lock(&inst->flush_lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006590 mutex_lock(&inst->registeredbufs.lock);
6591 found = false;
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006592 /* check if mbuf was not removed by any chance */
6593 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
6594 if (msm_comm_compare_vb2_planes(inst, mbuf,
6595 &temp->vvb.vb2_buf)) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006596 found = true;
6597 break;
6598 }
6599 }
6600 if (found) {
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006601 /* send RBR event to client */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006602 msm_vidc_queue_rbr_event(inst,
6603 mbuf->vvb.vb2_buf.planes[0].m.fd,
6604 mbuf->vvb.vb2_buf.planes[0].data_offset);
6605
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006606 /* clear RBR_PENDING flag */
6607 mbuf->flags &= ~MSM_VIDC_FLAG_RBR_PENDING;
6608
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006609 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
6610 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
6611 print_vidc_buffer(VIDC_ERR,
6612 "rbr unmap failed.", inst, mbuf);
6613 }
6614 /* refcount is not zero if client queued the same buffer */
6615 if (!mbuf->smem[0].refcount) {
6616 list_del(&mbuf->list);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006617 kref_put_mbuf(mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006618 }
6619 } else {
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006620 print_vidc_buffer(VIDC_ERR, "mbuf not found", inst, mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006621 goto unlock;
6622 }
6623
6624 /*
6625 * 1. client might have pushed same planes in which case mbuf will be
6626 * same and refcounts are positive and buffer wouldn't have been
6627 * removed from the registeredbufs list.
6628 * 2. client might have pushed same planes[0] but different planes[1]
6629 * in which case mbuf will be different.
6630 * 3. in either case we can search mbuf->smem[0].device_addr in the list
6631 * and if found queue it to video hw (if not flushing).
6632 */
6633 found = false;
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006634 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
6635 if (msm_comm_compare_vb2_plane(inst, mbuf,
6636 &temp->vvb.vb2_buf, 0)) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006637 found = true;
6638 break;
6639 }
6640 }
6641 if (!found)
6642 goto unlock;
6643
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006644 /* buffer found means client queued the buffer already */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006645 if (inst->in_reconfig || inst->in_flush) {
6646 print_vidc_buffer(VIDC_DBG, "rbr flush buf", inst, mbuf);
6647 msm_comm_flush_vidc_buffer(inst, mbuf);
6648 msm_comm_unmap_vidc_buffer(inst, mbuf);
6649 /* remove from list */
6650 list_del(&mbuf->list);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006651 kref_put_mbuf(mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006652
6653 /* don't queue the buffer */
6654 found = false;
6655 }
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006656 /* clear DEFERRED flag, if any, as the buffer is going to be queued */
6657 if (found)
6658 mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
6659
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006660unlock:
6661 mutex_unlock(&inst->registeredbufs.lock);
6662
6663 if (found) {
6664 print_vidc_buffer(VIDC_DBG, "rbr qbuf", inst, mbuf);
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006665 rc = msm_comm_qbuf_rbr(inst, mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006666 if (rc)
6667 print_vidc_buffer(VIDC_ERR,
6668 "rbr qbuf failed", inst, mbuf);
6669 }
Surajit Podder0d812bf2018-02-02 13:37:24 +05306670 mutex_unlock(&inst->flush_lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006671}
6672
6673int msm_comm_unmap_vidc_buffer(struct msm_vidc_inst *inst,
6674 struct msm_vidc_buffer *mbuf)
6675{
6676 int rc = 0, i;
6677
6678 if (!inst || !mbuf) {
6679 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
6680 __func__, inst, mbuf);
6681 return -EINVAL;
6682 }
6683 if (mbuf->vvb.vb2_buf.num_planes > VIDEO_MAX_PLANES) {
6684 dprintk(VIDC_ERR, "%s: invalid num_planes %d\n", __func__,
6685 mbuf->vvb.vb2_buf.num_planes);
6686 return -EINVAL;
6687 }
6688
6689 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
6690 u32 refcount = mbuf->smem[i].refcount;
6691
6692 while (refcount) {
6693 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
6694 print_vidc_buffer(VIDC_ERR,
6695 "unmap failed for buf", inst, mbuf);
6696 refcount--;
6697 }
6698 }
6699
6700 return rc;
6701}
6702
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006703static void kref_free_mbuf(struct kref *kref)
6704{
6705 struct msm_vidc_buffer *mbuf = container_of(kref,
6706 struct msm_vidc_buffer, kref);
6707
6708 kfree(mbuf);
6709}
6710
6711void kref_put_mbuf(struct msm_vidc_buffer *mbuf)
6712{
6713 if (!mbuf)
6714 return;
6715
6716 kref_put(&mbuf->kref, kref_free_mbuf);
6717}
6718
6719bool kref_get_mbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
6720{
6721 struct msm_vidc_buffer *temp;
6722 bool matches = false;
6723 bool ret = false;
6724
6725 if (!inst || !mbuf)
6726 return false;
6727
6728 mutex_lock(&inst->registeredbufs.lock);
6729 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
6730 if (temp == mbuf) {
6731 matches = true;
6732 break;
6733 }
6734 }
6735 ret = (matches && kref_get_unless_zero(&mbuf->kref)) ? true : false;
6736 mutex_unlock(&inst->registeredbufs.lock);
6737
6738 return ret;
6739}
6740
Qiwei Liu551a22222017-08-23 15:28:29 +08006741void msm_comm_store_mark_data(struct msm_vidc_list *data_list,
6742 u32 index, u32 mark_data, u32 mark_target)
6743{
6744 struct msm_vidc_buf_data *pdata = NULL;
6745 bool found = false;
6746
6747 if (!data_list) {
6748 dprintk(VIDC_ERR, "%s: invalid params %pK\n",
6749 __func__, data_list);
6750 return;
6751 }
6752
6753 mutex_lock(&data_list->lock);
6754 list_for_each_entry(pdata, &data_list->list, list) {
6755 if (pdata->index == index) {
6756 pdata->mark_data = mark_data;
6757 pdata->mark_target = mark_target;
6758 found = true;
6759 break;
6760 }
6761 }
6762
6763 if (!found) {
6764 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
6765 if (!pdata) {
6766 dprintk(VIDC_WARN, "%s: malloc failure.\n", __func__);
6767 goto exit;
6768 }
6769 pdata->index = index;
6770 pdata->mark_data = mark_data;
6771 pdata->mark_target = mark_target;
6772 list_add_tail(&pdata->list, &data_list->list);
6773 }
6774
6775exit:
6776 mutex_unlock(&data_list->lock);
6777}
6778
6779void msm_comm_fetch_mark_data(struct msm_vidc_list *data_list,
6780 u32 index, u32 *mark_data, u32 *mark_target)
6781{
6782 struct msm_vidc_buf_data *pdata = NULL;
6783
6784 if (!data_list || !mark_data || !mark_target) {
6785 dprintk(VIDC_ERR, "%s: invalid params %pK %pK %pK\n",
6786 __func__, data_list, mark_data, mark_target);
6787 return;
6788 }
6789
6790 *mark_data = *mark_target = 0;
6791 mutex_lock(&data_list->lock);
6792 list_for_each_entry(pdata, &data_list->list, list) {
6793 if (pdata->index == index) {
6794 *mark_data = pdata->mark_data;
6795 *mark_target = pdata->mark_target;
6796 /* clear after fetch */
6797 pdata->mark_data = pdata->mark_target = 0;
6798 break;
6799 }
6800 }
6801 mutex_unlock(&data_list->lock);
6802}
6803
6804int msm_comm_release_mark_data(struct msm_vidc_inst *inst)
6805{
6806 struct msm_vidc_buf_data *pdata, *next;
6807
6808 if (!inst) {
6809 dprintk(VIDC_ERR, "%s: invalid params %pK\n",
6810 __func__, inst);
6811 return -EINVAL;
6812 }
6813
6814 mutex_lock(&inst->etb_data.lock);
6815 list_for_each_entry_safe(pdata, next, &inst->etb_data.list, list) {
6816 list_del(&pdata->list);
6817 kfree(pdata);
6818 }
6819 mutex_unlock(&inst->etb_data.lock);
6820
6821 mutex_lock(&inst->fbd_data.lock);
6822 list_for_each_entry_safe(pdata, next, &inst->fbd_data.list, list) {
6823 list_del(&pdata->list);
6824 kfree(pdata);
6825 }
6826 mutex_unlock(&inst->fbd_data.lock);
6827
6828 return 0;
6829}
6830