blob: 428bf71d3c333663f179713b92822861f6335258 [file] [log] [blame]
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
2 *
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
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080038const char *const mpeg_video_vidc_extradata[] = {
39 "Extradata none",
40 "Extradata MB Quantization",
41 "Extradata Interlace Video",
Chinmay Sawarkar2bacf632017-04-13 14:46:43 -070042 "Reserved",
43 "Reserved",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080044 "Extradata timestamp",
45 "Extradata S3D Frame Packing",
46 "Extradata Frame Rate",
47 "Extradata Panscan Window",
48 "Extradata Recovery point SEI",
49 "Extradata Multislice info",
50 "Extradata number of concealed MB",
51 "Extradata metadata filler",
52 "Extradata input crop",
53 "Extradata digital zoom",
54 "Extradata aspect ratio",
55 "Extradata mpeg2 seqdisp",
56 "Extradata stream userdata",
57 "Extradata frame QP",
58 "Extradata frame bits info",
59 "Extradata LTR",
60 "Extradata macroblock metadata",
61 "Extradata VQZip SEI",
62 "Extradata YUV Stats",
63 "Extradata ROI QP",
64 "Extradata output crop",
65 "Extradata display colour SEI",
66 "Extradata light level SEI",
67 "Extradata PQ Info",
68 "Extradata display VUI",
69 "Extradata vpx color space",
Praneeth Paladugua51b2c42017-06-23 12:48:06 -070070 "Extradata UBWC CR stats info",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080071};
72
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080073static void msm_comm_generate_session_error(struct msm_vidc_inst *inst);
74static void msm_comm_generate_sys_error(struct msm_vidc_inst *inst);
75static 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 }
563 case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
564 switch (value) {
565 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED:
566 return HAL_H264_DB_MODE_DISABLE;
567 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED:
568 return HAL_H264_DB_MODE_ALL_BOUNDARY;
569 case L_MODE:
570 return HAL_H264_DB_MODE_SKIP_SLICE_BOUNDARY;
571 default:
572 goto unknown_value;
573 }
574 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE:
575 switch (value) {
576 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT:
577 return HAL_IFRAMESIZE_TYPE_DEFAULT;
578 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM:
579 return HAL_IFRAMESIZE_TYPE_MEDIUM;
580 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE:
581 return HAL_IFRAMESIZE_TYPE_HUGE;
582 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED:
583 return HAL_IFRAMESIZE_TYPE_UNLIMITED;
584 default:
585 goto unknown_value;
586 }
587 }
588
589unknown_value:
590 dprintk(VIDC_WARN, "Unknown control (%x, %d)\n", id, value);
591 return -EINVAL;
592}
593
Umesh Pandey92bd41d2017-08-10 14:52:33 -0700594int msm_comm_get_v4l2_profile(int fourcc, int profile)
595{
596 switch (fourcc) {
597 case V4L2_PIX_FMT_H264:
598 return msm_comm_hal_to_v4l2(
599 V4L2_CID_MPEG_VIDEO_H264_PROFILE,
600 profile);
601 case V4L2_PIX_FMT_HEVC:
602 return msm_comm_hal_to_v4l2(
603 V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE,
604 profile);
605 case V4L2_PIX_FMT_VP8:
606 case V4L2_PIX_FMT_VP9:
607 case V4L2_PIX_FMT_MPEG2:
608 return 0;
609 default:
610 dprintk(VIDC_WARN, "Unknown codec id %x\n", fourcc);
611 return 0;
612 }
613}
614
615int msm_comm_get_v4l2_level(int fourcc, int level)
616{
617 switch (fourcc) {
618 case V4L2_PIX_FMT_H264:
619 return msm_comm_hal_to_v4l2(
620 V4L2_CID_MPEG_VIDEO_H264_LEVEL,
621 level);
622 case V4L2_PIX_FMT_HEVC:
623 return msm_comm_hal_to_v4l2(
624 V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL,
625 level);
626 case V4L2_PIX_FMT_VP8:
627 return msm_comm_hal_to_v4l2(
628 V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL,
629 level);
630 case V4L2_PIX_FMT_VP9:
631 case V4L2_PIX_FMT_MPEG2:
632 return 0;
633 default:
634 dprintk(VIDC_WARN, "Unknown codec id %x\n", fourcc);
635 return 0;
636 }
637}
638
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800639int msm_comm_ctrl_init(struct msm_vidc_inst *inst,
640 struct msm_vidc_ctrl *drv_ctrls, u32 num_ctrls,
641 const struct v4l2_ctrl_ops *ctrl_ops)
642{
643 int idx = 0;
644 struct v4l2_ctrl_config ctrl_cfg = {0};
645 int ret_val = 0;
646
647 if (!inst || !drv_ctrls || !ctrl_ops || !num_ctrls) {
648 dprintk(VIDC_ERR, "%s - invalid input\n", __func__);
649 return -EINVAL;
650 }
651
652 inst->ctrls = kcalloc(num_ctrls, sizeof(struct v4l2_ctrl *),
653 GFP_KERNEL);
654 if (!inst->ctrls) {
655 dprintk(VIDC_ERR, "%s - failed to allocate ctrl\n", __func__);
656 return -ENOMEM;
657 }
658
659 ret_val = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls);
660
661 if (ret_val) {
662 dprintk(VIDC_ERR, "CTRL ERR: Control handler init failed, %d\n",
663 inst->ctrl_handler.error);
664 return ret_val;
665 }
666
667 for (; idx < num_ctrls; idx++) {
668 struct v4l2_ctrl *ctrl = NULL;
669
Maheshwar Ajja1f801492017-05-10 16:55:26 -0700670 if (IS_PRIV_CTRL(drv_ctrls[idx].id)) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800671 /*add private control*/
672 ctrl_cfg.def = drv_ctrls[idx].default_value;
673 ctrl_cfg.flags = 0;
674 ctrl_cfg.id = drv_ctrls[idx].id;
675 ctrl_cfg.max = drv_ctrls[idx].maximum;
676 ctrl_cfg.min = drv_ctrls[idx].minimum;
677 ctrl_cfg.menu_skip_mask =
678 drv_ctrls[idx].menu_skip_mask;
679 ctrl_cfg.name = drv_ctrls[idx].name;
680 ctrl_cfg.ops = ctrl_ops;
681 ctrl_cfg.step = drv_ctrls[idx].step;
682 ctrl_cfg.type = drv_ctrls[idx].type;
683 ctrl_cfg.qmenu = drv_ctrls[idx].qmenu;
684
685 ctrl = v4l2_ctrl_new_custom(&inst->ctrl_handler,
686 &ctrl_cfg, NULL);
687 } else {
688 if (drv_ctrls[idx].type == V4L2_CTRL_TYPE_MENU) {
689 ctrl = v4l2_ctrl_new_std_menu(
690 &inst->ctrl_handler,
691 ctrl_ops,
692 drv_ctrls[idx].id,
693 drv_ctrls[idx].maximum,
694 drv_ctrls[idx].menu_skip_mask,
695 drv_ctrls[idx].default_value);
696 } else {
697 ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler,
698 ctrl_ops,
699 drv_ctrls[idx].id,
700 drv_ctrls[idx].minimum,
701 drv_ctrls[idx].maximum,
702 drv_ctrls[idx].step,
703 drv_ctrls[idx].default_value);
704 }
705 }
706
707 if (!ctrl) {
708 dprintk(VIDC_ERR, "%s - invalid ctrl %s\n", __func__,
709 drv_ctrls[idx].name);
710 return -EINVAL;
711 }
712
713 ret_val = inst->ctrl_handler.error;
714 if (ret_val) {
715 dprintk(VIDC_ERR,
716 "Error adding ctrl (%s) to ctrl handle, %d\n",
717 drv_ctrls[idx].name, inst->ctrl_handler.error);
718 return ret_val;
719 }
720
721 ctrl->flags |= drv_ctrls[idx].flags;
722 inst->ctrls[idx] = ctrl;
723 }
724
725 /* Construct a super cluster of all controls */
726 inst->cluster = get_super_cluster(inst, num_ctrls);
727 if (!inst->cluster) {
728 dprintk(VIDC_WARN,
729 "Failed to setup super cluster\n");
730 return -EINVAL;
731 }
732
733 v4l2_ctrl_cluster(num_ctrls, inst->cluster);
734
735 return ret_val;
736}
737
738int msm_comm_ctrl_deinit(struct msm_vidc_inst *inst)
739{
740 if (!inst) {
741 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
742 return -EINVAL;
743 }
744
745 kfree(inst->ctrls);
746 kfree(inst->cluster);
747 v4l2_ctrl_handler_free(&inst->ctrl_handler);
748
749 return 0;
750}
751
752enum multi_stream msm_comm_get_stream_output_mode(struct msm_vidc_inst *inst)
753{
754 switch (msm_comm_g_ctrl_for_id(inst,
755 V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE)) {
756 case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY:
757 return HAL_VIDEO_DECODER_SECONDARY;
758 case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY:
759 default:
760 return HAL_VIDEO_DECODER_PRIMARY;
761 }
762}
763
764static int msm_comm_get_mbs_per_sec(struct msm_vidc_inst *inst)
765{
766 int output_port_mbs, capture_port_mbs;
767 int fps;
768
769 output_port_mbs = inst->in_reconfig ?
770 NUM_MBS_PER_FRAME(inst->reconfig_width,
771 inst->reconfig_height) :
772 NUM_MBS_PER_FRAME(inst->prop.width[OUTPUT_PORT],
773 inst->prop.height[OUTPUT_PORT]);
774
775 capture_port_mbs = NUM_MBS_PER_FRAME(inst->prop.width[CAPTURE_PORT],
776 inst->prop.height[CAPTURE_PORT]);
777
Praneeth Paladugue5fd0872017-04-19 11:24:28 -0700778 if (inst->clk_data.operating_rate) {
779 fps = (inst->clk_data.operating_rate >> 16) ?
780 inst->clk_data.operating_rate >> 16 : 1;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800781 /*
782 * Check if operating rate is less than fps.
783 * If Yes, then use fps to scale clocks
784 */
785 fps = fps > inst->prop.fps ? fps : inst->prop.fps;
786 return max(output_port_mbs, capture_port_mbs) * fps;
787 } else {
788 return max(output_port_mbs, capture_port_mbs) * inst->prop.fps;
789 }
790}
791
792int msm_comm_get_inst_load(struct msm_vidc_inst *inst,
793 enum load_calc_quirks quirks)
794{
795 int load = 0;
796
797 mutex_lock(&inst->lock);
798
799 if (!(inst->state >= MSM_VIDC_OPEN_DONE &&
800 inst->state < MSM_VIDC_STOP_DONE))
801 goto exit;
802
803 load = msm_comm_get_mbs_per_sec(inst);
804
805 if (is_thumbnail_session(inst)) {
806 if (quirks & LOAD_CALC_IGNORE_THUMBNAIL_LOAD)
807 load = 0;
808 }
809
810 if (msm_comm_turbo_session(inst)) {
811 if (!(quirks & LOAD_CALC_IGNORE_TURBO_LOAD))
812 load = inst->core->resources.max_load;
813 }
814
815 /* Clock and Load calculations for REALTIME/NON-REALTIME
816 * OPERATING RATE SET/NO OPERATING RATE SET
817 *
818 * | OPERATING RATE SET | OPERATING RATE NOT SET |
819 * ----------------|--------------------- |------------------------|
820 * REALTIME | load = res * op_rate | load = res * fps |
821 * | clk = res * op_rate | clk = res * fps |
822 * ----------------|----------------------|------------------------|
823 * NON-REALTIME | load = res * 1 fps | load = res * 1 fps |
824 * | clk = res * op_rate | clk = res * fps |
825 * ----------------|----------------------|------------------------|
826 */
827
828 if (!is_realtime_session(inst) &&
829 (quirks & LOAD_CALC_IGNORE_NON_REALTIME_LOAD)) {
830 if (!inst->prop.fps) {
831 dprintk(VIDC_INFO, "instance:%pK fps = 0\n", inst);
832 load = 0;
833 } else {
834 load = msm_comm_get_mbs_per_sec(inst) / inst->prop.fps;
835 }
836 }
837
838exit:
839 mutex_unlock(&inst->lock);
840 return load;
841}
842
Saurabh Kothawade305547e2017-08-14 14:35:21 -0700843int msm_comm_get_inst_load_per_core(struct msm_vidc_inst *inst,
844 enum load_calc_quirks quirks)
845{
846 int load = msm_comm_get_inst_load(inst, quirks);
847
848 if (inst->clk_data.core_id == VIDC_CORE_ID_3)
849 load = load / 2;
850
851 return load;
852}
853
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800854int msm_comm_get_load(struct msm_vidc_core *core,
855 enum session_type type, enum load_calc_quirks quirks)
856{
857 struct msm_vidc_inst *inst = NULL;
858 int num_mbs_per_sec = 0;
859
860 if (!core) {
861 dprintk(VIDC_ERR, "Invalid args: %pK\n", core);
862 return -EINVAL;
863 }
864
865 mutex_lock(&core->lock);
866 list_for_each_entry(inst, &core->instances, list) {
867 if (inst->session_type != type)
868 continue;
869
870 num_mbs_per_sec += msm_comm_get_inst_load(inst, quirks);
871 }
872 mutex_unlock(&core->lock);
873
874 return num_mbs_per_sec;
875}
876
877enum hal_domain get_hal_domain(int session_type)
878{
879 enum hal_domain domain;
880
881 switch (session_type) {
882 case MSM_VIDC_ENCODER:
883 domain = HAL_VIDEO_DOMAIN_ENCODER;
884 break;
885 case MSM_VIDC_DECODER:
886 domain = HAL_VIDEO_DOMAIN_DECODER;
887 break;
888 default:
889 dprintk(VIDC_ERR, "Wrong domain\n");
890 domain = HAL_UNUSED_DOMAIN;
891 break;
892 }
893
894 return domain;
895}
896
897enum hal_video_codec get_hal_codec(int fourcc)
898{
899 enum hal_video_codec codec;
900
901 switch (fourcc) {
902 case V4L2_PIX_FMT_H264:
903 case V4L2_PIX_FMT_H264_NO_SC:
904 codec = HAL_VIDEO_CODEC_H264;
905 break;
906 case V4L2_PIX_FMT_H264_MVC:
907 codec = HAL_VIDEO_CODEC_MVC;
908 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800909 case V4L2_PIX_FMT_MPEG1:
910 codec = HAL_VIDEO_CODEC_MPEG1;
911 break;
912 case V4L2_PIX_FMT_MPEG2:
913 codec = HAL_VIDEO_CODEC_MPEG2;
914 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800915 case V4L2_PIX_FMT_VP8:
916 codec = HAL_VIDEO_CODEC_VP8;
917 break;
918 case V4L2_PIX_FMT_VP9:
919 codec = HAL_VIDEO_CODEC_VP9;
920 break;
921 case V4L2_PIX_FMT_HEVC:
922 codec = HAL_VIDEO_CODEC_HEVC;
923 break;
Surajit Poddere502daa2017-05-30 19:17:45 +0530924 case V4L2_PIX_FMT_TME:
925 codec = HAL_VIDEO_CODEC_TME;
926 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800927 default:
928 dprintk(VIDC_ERR, "Wrong codec: %d\n", fourcc);
929 codec = HAL_UNUSED_CODEC;
930 break;
931 }
932
933 return codec;
934}
935
Praneeth Paladugu319e7922017-03-16 11:09:06 -0700936enum hal_uncompressed_format msm_comm_get_hal_uncompressed(int fourcc)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800937{
938 enum hal_uncompressed_format format = HAL_UNUSED_COLOR;
939
940 switch (fourcc) {
941 case V4L2_PIX_FMT_NV12:
942 format = HAL_COLOR_FORMAT_NV12;
943 break;
944 case V4L2_PIX_FMT_NV21:
945 format = HAL_COLOR_FORMAT_NV21;
946 break;
947 case V4L2_PIX_FMT_NV12_UBWC:
948 format = HAL_COLOR_FORMAT_NV12_UBWC;
949 break;
950 case V4L2_PIX_FMT_NV12_TP10_UBWC:
951 format = HAL_COLOR_FORMAT_NV12_TP10_UBWC;
952 break;
Zhongbo Shi6bd5f5f2017-08-16 17:20:08 +0800953 case V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010:
954 format = HAL_COLOR_FORMAT_P010;
955 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800956 default:
957 format = HAL_UNUSED_COLOR;
958 break;
959 }
960
961 return format;
962}
963
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800964struct msm_vidc_core *get_vidc_core(int core_id)
965{
966 struct msm_vidc_core *core;
967 int found = 0;
968
969 if (core_id > MSM_VIDC_CORES_MAX) {
970 dprintk(VIDC_ERR, "Core id = %d is greater than max = %d\n",
971 core_id, MSM_VIDC_CORES_MAX);
972 return NULL;
973 }
974 mutex_lock(&vidc_driver->lock);
975 list_for_each_entry(core, &vidc_driver->cores, list) {
976 if (core->id == core_id) {
977 found = 1;
978 break;
979 }
980 }
981 mutex_unlock(&vidc_driver->lock);
982 if (found)
983 return core;
984 return NULL;
985}
986
987const struct msm_vidc_format *msm_comm_get_pixel_fmt_index(
988 const struct msm_vidc_format fmt[], int size, int index, int fmt_type)
989{
990 int i, k = 0;
991
992 if (!fmt || index < 0) {
993 dprintk(VIDC_ERR, "Invalid inputs, fmt = %pK, index = %d\n",
994 fmt, index);
995 return NULL;
996 }
997 for (i = 0; i < size; i++) {
998 if (fmt[i].type != fmt_type)
999 continue;
1000 if (k == index)
1001 break;
1002 k++;
1003 }
1004 if (i == size) {
1005 dprintk(VIDC_INFO, "Format not found\n");
1006 return NULL;
1007 }
1008 return &fmt[i];
1009}
1010struct msm_vidc_format *msm_comm_get_pixel_fmt_fourcc(
1011 struct msm_vidc_format fmt[], int size, int fourcc, int fmt_type)
1012{
1013 int i;
1014
1015 if (!fmt) {
1016 dprintk(VIDC_ERR, "Invalid inputs, fmt = %pK\n", fmt);
1017 return NULL;
1018 }
1019 for (i = 0; i < size; i++) {
1020 if (fmt[i].fourcc == fourcc)
1021 break;
1022 }
1023 if (i == size) {
1024 dprintk(VIDC_INFO, "Format not found\n");
1025 return NULL;
1026 }
1027 return &fmt[i];
1028}
1029
1030struct buf_queue *msm_comm_get_vb2q(
1031 struct msm_vidc_inst *inst, enum v4l2_buf_type type)
1032{
1033 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1034 return &inst->bufq[CAPTURE_PORT];
1035 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1036 return &inst->bufq[OUTPUT_PORT];
1037 return NULL;
1038}
1039
1040static void handle_sys_init_done(enum hal_command_response cmd, void *data)
1041{
1042 struct msm_vidc_cb_cmd_done *response = data;
1043 struct msm_vidc_core *core;
1044 struct vidc_hal_sys_init_done *sys_init_msg;
1045 u32 index;
1046
1047 if (!IS_HAL_SYS_CMD(cmd)) {
1048 dprintk(VIDC_ERR, "%s - invalid cmd\n", __func__);
1049 return;
1050 }
1051
1052 index = SYS_MSG_INDEX(cmd);
1053
1054 if (!response) {
1055 dprintk(VIDC_ERR,
1056 "Failed to get valid response for sys init\n");
1057 return;
1058 }
1059 core = get_vidc_core(response->device_id);
1060 if (!core) {
1061 dprintk(VIDC_ERR, "Wrong device_id received\n");
1062 return;
1063 }
1064 sys_init_msg = &response->data.sys_init_done;
1065 if (!sys_init_msg) {
1066 dprintk(VIDC_ERR, "sys_init_done message not proper\n");
1067 return;
1068 }
1069
1070 core->enc_codec_supported = sys_init_msg->enc_codec_supported;
1071 core->dec_codec_supported = sys_init_msg->dec_codec_supported;
1072
1073 /* This should come from sys_init_done */
1074 core->resources.max_inst_count =
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -07001075 sys_init_msg->max_sessions_supported ?
Karthikeyan Periasamy4b5e7332017-07-28 12:07:42 -07001076 min_t(u32, sys_init_msg->max_sessions_supported,
1077 MAX_SUPPORTED_INSTANCES) : MAX_SUPPORTED_INSTANCES;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001078
1079 core->resources.max_secure_inst_count =
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -07001080 core->resources.max_secure_inst_count ?
1081 core->resources.max_secure_inst_count :
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001082 core->resources.max_inst_count;
1083
1084 if (core->id == MSM_VIDC_CORE_VENUS &&
1085 (core->dec_codec_supported & HAL_VIDEO_CODEC_H264))
1086 core->dec_codec_supported |=
1087 HAL_VIDEO_CODEC_MVC;
1088
1089 core->codec_count = sys_init_msg->codec_count;
1090 memcpy(core->capabilities, sys_init_msg->capabilities,
1091 sys_init_msg->codec_count * sizeof(struct msm_vidc_capability));
1092
1093 dprintk(VIDC_DBG,
1094 "%s: supported_codecs[%d]: enc = %#x, dec = %#x\n",
1095 __func__, core->codec_count, core->enc_codec_supported,
1096 core->dec_codec_supported);
1097
1098 complete(&(core->completions[index]));
1099}
1100
Maheshwar Ajja69639bd2017-07-05 17:58:15 -07001101static void put_inst_helper(struct kref *kref)
1102{
1103 struct msm_vidc_inst *inst = container_of(kref,
1104 struct msm_vidc_inst, kref);
1105
1106 msm_vidc_destroy(inst);
1107}
1108
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001109static void put_inst(struct msm_vidc_inst *inst)
1110{
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001111 if (!inst)
1112 return;
1113
1114 kref_put(&inst->kref, put_inst_helper);
1115}
1116
1117static struct msm_vidc_inst *get_inst(struct msm_vidc_core *core,
1118 void *session_id)
1119{
1120 struct msm_vidc_inst *inst = NULL;
1121 bool matches = false;
1122
1123 if (!core || !session_id)
1124 return NULL;
1125
1126 mutex_lock(&core->lock);
1127 /*
1128 * This is as good as !list_empty(!inst->list), but at this point
1129 * we don't really know if inst was kfree'd via close syscall before
1130 * hardware could respond. So manually walk thru the list of active
1131 * sessions
1132 */
1133 list_for_each_entry(inst, &core->instances, list) {
1134 if (inst == session_id) {
1135 /*
1136 * Even if the instance is valid, we really shouldn't
1137 * be receiving or handling callbacks when we've deleted
1138 * our session with HFI
1139 */
1140 matches = !!inst->session;
1141 break;
1142 }
1143 }
1144
1145 /*
1146 * kref_* is atomic_int backed, so no need for inst->lock. But we can
1147 * always acquire inst->lock and release it in put_inst for a stronger
1148 * locking system.
1149 */
1150 inst = (matches && kref_get_unless_zero(&inst->kref)) ? inst : NULL;
1151 mutex_unlock(&core->lock);
1152
1153 return inst;
1154}
1155
1156static void handle_session_release_buf_done(enum hal_command_response cmd,
1157 void *data)
1158{
1159 struct msm_vidc_cb_cmd_done *response = data;
1160 struct msm_vidc_inst *inst;
1161 struct internal_buf *buf;
1162 struct list_head *ptr, *next;
1163 struct hal_buffer_info *buffer;
1164 u32 buf_found = false;
1165 u32 address;
1166
1167 if (!response) {
1168 dprintk(VIDC_ERR, "Invalid release_buf_done response\n");
1169 return;
1170 }
1171
1172 inst = get_inst(get_vidc_core(response->device_id),
1173 response->session_id);
1174 if (!inst) {
1175 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1176 return;
1177 }
1178
1179 buffer = &response->data.buffer_info;
1180 address = buffer->buffer_addr;
1181
1182 mutex_lock(&inst->scratchbufs.lock);
1183 list_for_each_safe(ptr, next, &inst->scratchbufs.list) {
1184 buf = list_entry(ptr, struct internal_buf, list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001185 if (address == buf->smem.device_addr) {
1186 dprintk(VIDC_DBG, "releasing scratch: %x\n",
1187 buf->smem.device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001188 buf_found = true;
1189 }
1190 }
1191 mutex_unlock(&inst->scratchbufs.lock);
1192
1193 mutex_lock(&inst->persistbufs.lock);
1194 list_for_each_safe(ptr, next, &inst->persistbufs.list) {
1195 buf = list_entry(ptr, struct internal_buf, list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001196 if (address == buf->smem.device_addr) {
1197 dprintk(VIDC_DBG, "releasing persist: %x\n",
1198 buf->smem.device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001199 buf_found = true;
1200 }
1201 }
1202 mutex_unlock(&inst->persistbufs.lock);
1203
1204 if (!buf_found)
1205 dprintk(VIDC_ERR, "invalid buffer received from firmware");
1206 if (IS_HAL_SESSION_CMD(cmd))
1207 complete(&inst->completions[SESSION_MSG_INDEX(cmd)]);
1208 else
1209 dprintk(VIDC_ERR, "Invalid inst cmd response: %d\n", cmd);
1210
1211 put_inst(inst);
1212}
1213
1214static void handle_sys_release_res_done(
1215 enum hal_command_response cmd, void *data)
1216{
1217 struct msm_vidc_cb_cmd_done *response = data;
1218 struct msm_vidc_core *core;
1219
1220 if (!response) {
1221 dprintk(VIDC_ERR,
1222 "Failed to get valid response for sys init\n");
1223 return;
1224 }
1225 core = get_vidc_core(response->device_id);
1226 if (!core) {
1227 dprintk(VIDC_ERR, "Wrong device_id received\n");
1228 return;
1229 }
1230 complete(&core->completions[
1231 SYS_MSG_INDEX(HAL_SYS_RELEASE_RESOURCE_DONE)]);
1232}
1233
1234static void change_inst_state(struct msm_vidc_inst *inst,
1235 enum instance_state state)
1236{
1237 if (!inst) {
1238 dprintk(VIDC_ERR, "Invalid parameter %s\n", __func__);
1239 return;
1240 }
1241 mutex_lock(&inst->lock);
1242 if (inst->state == MSM_VIDC_CORE_INVALID) {
1243 dprintk(VIDC_DBG,
1244 "Inst: %pK is in bad state can't change state to %d\n",
1245 inst, state);
1246 goto exit;
1247 }
1248 dprintk(VIDC_DBG, "Moved inst: %pK from state: %d to state: %d\n",
1249 inst, inst->state, state);
1250 inst->state = state;
1251exit:
1252 mutex_unlock(&inst->lock);
1253}
1254
1255static int signal_session_msg_receipt(enum hal_command_response cmd,
1256 struct msm_vidc_inst *inst)
1257{
1258 if (!inst) {
1259 dprintk(VIDC_ERR, "Invalid(%pK) instance id\n", inst);
1260 return -EINVAL;
1261 }
1262 if (IS_HAL_SESSION_CMD(cmd)) {
1263 complete(&inst->completions[SESSION_MSG_INDEX(cmd)]);
1264 } else {
1265 dprintk(VIDC_ERR, "Invalid inst cmd response: %d\n", cmd);
1266 return -EINVAL;
1267 }
1268 return 0;
1269}
1270
1271static int wait_for_sess_signal_receipt(struct msm_vidc_inst *inst,
1272 enum hal_command_response cmd)
1273{
1274 int rc = 0;
1275 struct hfi_device *hdev;
1276
1277 if (!IS_HAL_SESSION_CMD(cmd)) {
1278 dprintk(VIDC_ERR, "Invalid inst cmd response: %d\n", cmd);
1279 return -EINVAL;
1280 }
1281 hdev = (struct hfi_device *)(inst->core->device);
1282 rc = wait_for_completion_timeout(
1283 &inst->completions[SESSION_MSG_INDEX(cmd)],
Praneeth Paladugud5bf7bc2017-05-29 23:41:04 -07001284 msecs_to_jiffies(
1285 inst->core->resources.msm_vidc_hw_rsp_timeout));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001286 if (!rc) {
1287 dprintk(VIDC_ERR, "Wait interrupted or timed out: %d\n",
1288 SESSION_MSG_INDEX(cmd));
Surajit Podder878ede02017-02-07 12:20:10 +05301289 msm_comm_kill_session(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001290 rc = -EIO;
1291 } else {
1292 rc = 0;
1293 }
1294 return rc;
1295}
1296
1297static int wait_for_state(struct msm_vidc_inst *inst,
1298 enum instance_state flipped_state,
1299 enum instance_state desired_state,
1300 enum hal_command_response hal_cmd)
1301{
1302 int rc = 0;
1303
1304 if (IS_ALREADY_IN_STATE(flipped_state, desired_state)) {
1305 dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
1306 inst, inst->state);
1307 goto err_same_state;
1308 }
1309 dprintk(VIDC_DBG, "Waiting for hal_cmd: %d\n", hal_cmd);
1310 rc = wait_for_sess_signal_receipt(inst, hal_cmd);
1311 if (!rc)
1312 change_inst_state(inst, desired_state);
1313err_same_state:
1314 return rc;
1315}
1316
1317void msm_vidc_queue_v4l2_event(struct msm_vidc_inst *inst, int event_type)
1318{
1319 struct v4l2_event event = {.id = 0, .type = event_type};
1320
1321 v4l2_event_queue_fh(&inst->event_handler, &event);
1322}
1323
1324static void msm_comm_generate_max_clients_error(struct msm_vidc_inst *inst)
1325{
1326 enum hal_command_response cmd = HAL_SESSION_ERROR;
1327 struct msm_vidc_cb_cmd_done response = {0};
1328
1329 if (!inst) {
1330 dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
1331 return;
1332 }
1333 dprintk(VIDC_ERR, "%s: Too many clients\n", __func__);
1334 response.session_id = inst;
1335 response.status = VIDC_ERR_MAX_CLIENTS;
1336 handle_session_error(cmd, (void *)&response);
1337}
1338
1339static void print_cap(const char *type,
1340 struct hal_capability_supported *cap)
1341{
1342 dprintk(VIDC_DBG,
1343 "%-24s: %-8d %-8d %-8d\n",
1344 type, cap->min, cap->max, cap->step_size);
1345}
1346
Praneeth Paladugue1679112017-01-27 10:07:15 -08001347static int msm_vidc_comm_update_ctrl(struct msm_vidc_inst *inst,
1348 u32 id, struct hal_capability_supported *capability)
1349{
1350 struct v4l2_ctrl *ctrl = NULL;
1351 int rc = 0;
1352
1353 ctrl = v4l2_ctrl_find(&inst->ctrl_handler, id);
1354 if (ctrl) {
1355 v4l2_ctrl_modify_range(ctrl, capability->min,
1356 capability->max, ctrl->step,
Maheshwar Ajja850be3c2017-07-06 17:47:40 -07001357 ctrl->default_value);
Praneeth Paladugue1679112017-01-27 10:07:15 -08001358 dprintk(VIDC_DBG,
1359 "%s: Updated Range = %lld --> %lld Def value = %lld\n",
1360 ctrl->name, ctrl->minimum, ctrl->maximum,
1361 ctrl->default_value);
1362 } else {
1363 dprintk(VIDC_ERR,
1364 "Failed to find Conrol %d\n", id);
1365 rc = -EINVAL;
1366 }
1367
1368 return rc;
1369 }
1370
1371static void msm_vidc_comm_update_ctrl_limits(struct msm_vidc_inst *inst)
1372{
Chinmay Sawarkar468c2672017-04-14 14:32:18 -07001373 if (inst->session_type == MSM_VIDC_ENCODER) {
Surajit Poddere502daa2017-05-30 19:17:45 +05301374 if (get_hal_codec(inst->fmts[CAPTURE_PORT].fourcc) ==
1375 HAL_VIDEO_CODEC_TME)
1376 return;
Chinmay Sawarkar468c2672017-04-14 14:32:18 -07001377 msm_vidc_comm_update_ctrl(inst,
1378 V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE,
1379 &inst->capability.hier_p_hybrid);
1380 msm_vidc_comm_update_ctrl(inst,
1381 V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS,
1382 &inst->capability.hier_b);
1383 msm_vidc_comm_update_ctrl(inst,
1384 V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS,
1385 &inst->capability.hier_p);
1386 msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDEO_BITRATE,
1387 &inst->capability.bitrate);
1388 msm_vidc_comm_update_ctrl(inst,
1389 V4L2_CID_MPEG_VIDC_VENC_PARAM_LAYER_BITRATE,
1390 &inst->capability.bitrate);
1391 msm_vidc_comm_update_ctrl(inst,
1392 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1393 &inst->capability.peakbitrate);
1394 msm_vidc_comm_update_ctrl(inst,
1395 V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP,
1396 &inst->capability.i_qp);
1397 msm_vidc_comm_update_ctrl(inst,
1398 V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP,
1399 &inst->capability.p_qp);
1400 msm_vidc_comm_update_ctrl(inst,
1401 V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP,
1402 &inst->capability.b_qp);
1403 msm_vidc_comm_update_ctrl(inst,
1404 V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MIN,
1405 &inst->capability.i_qp);
1406 msm_vidc_comm_update_ctrl(inst,
1407 V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MIN,
1408 &inst->capability.p_qp);
1409 msm_vidc_comm_update_ctrl(inst,
1410 V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MIN,
1411 &inst->capability.b_qp);
1412 msm_vidc_comm_update_ctrl(inst,
1413 V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MAX,
1414 &inst->capability.i_qp);
1415 msm_vidc_comm_update_ctrl(inst,
1416 V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MAX,
1417 &inst->capability.p_qp);
1418 msm_vidc_comm_update_ctrl(inst,
1419 V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MAX,
1420 &inst->capability.b_qp);
1421 msm_vidc_comm_update_ctrl(inst,
1422 V4L2_CID_MPEG_VIDC_VIDEO_BLUR_WIDTH,
1423 &inst->capability.blur_width);
1424 msm_vidc_comm_update_ctrl(inst,
1425 V4L2_CID_MPEG_VIDC_VIDEO_BLUR_HEIGHT,
1426 &inst->capability.blur_height);
1427 msm_vidc_comm_update_ctrl(inst,
1428 V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
1429 &inst->capability.slice_bytes);
1430 msm_vidc_comm_update_ctrl(inst,
1431 V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
1432 &inst->capability.slice_mbs);
1433 msm_vidc_comm_update_ctrl(inst,
1434 V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT,
1435 &inst->capability.ltr_count);
1436 msm_vidc_comm_update_ctrl(inst,
1437 V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES,
1438 &inst->capability.bframe);
1439 }
Praneeth Paladugue1679112017-01-27 10:07:15 -08001440}
1441
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001442static void handle_session_init_done(enum hal_command_response cmd, void *data)
1443{
1444 struct msm_vidc_cb_cmd_done *response = data;
1445 struct msm_vidc_inst *inst = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001446 struct msm_vidc_capability *capability = NULL;
1447 struct hfi_device *hdev;
1448 struct msm_vidc_core *core;
1449 u32 i, codec;
1450
1451 if (!response) {
1452 dprintk(VIDC_ERR,
1453 "Failed to get valid response for session init\n");
1454 return;
1455 }
1456
1457 inst = get_inst(get_vidc_core(response->device_id),
1458 response->session_id);
1459
1460 if (!inst) {
1461 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1462 return;
1463 }
1464
1465 if (response->status) {
1466 dprintk(VIDC_ERR,
1467 "Session init response from FW : %#x\n",
1468 response->status);
1469 if (response->status == VIDC_ERR_MAX_CLIENTS)
1470 msm_comm_generate_max_clients_error(inst);
1471 else
1472 msm_comm_generate_session_error(inst);
1473
1474 signal_session_msg_receipt(cmd, inst);
1475 put_inst(inst);
1476 return;
1477 }
1478
1479 core = inst->core;
1480 hdev = inst->core->device;
1481 codec = inst->session_type == MSM_VIDC_DECODER ?
1482 inst->fmts[OUTPUT_PORT].fourcc :
1483 inst->fmts[CAPTURE_PORT].fourcc;
1484
1485 /* check if capabilities are available for this session */
1486 for (i = 0; i < VIDC_MAX_SESSIONS; i++) {
1487 if (core->capabilities[i].codec ==
1488 get_hal_codec(codec) &&
1489 core->capabilities[i].domain ==
1490 get_hal_domain(inst->session_type)) {
1491 capability = &core->capabilities[i];
1492 break;
1493 }
1494 }
1495
1496 if (capability) {
1497 dprintk(VIDC_DBG,
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001498 "%s: capabilities for codec 0x%x, domain %#x\n",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001499 __func__, capability->codec, capability->domain);
1500 memcpy(&inst->capability, capability,
1501 sizeof(struct msm_vidc_capability));
1502 } else {
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001503 dprintk(VIDC_ERR,
1504 "Watch out : Some property may fail inst %pK\n", inst);
1505 dprintk(VIDC_ERR,
1506 "Caps N/A for codec 0x%x, domain %#x\n",
1507 inst->capability.codec, inst->capability.domain);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001508 }
1509 inst->capability.pixelprocess_capabilities =
1510 call_hfi_op(hdev, get_core_capabilities, hdev->hfi_device_data);
1511
1512 dprintk(VIDC_DBG,
1513 "Capability type : min max step size\n");
1514 print_cap("width", &inst->capability.width);
1515 print_cap("height", &inst->capability.height);
1516 print_cap("mbs_per_frame", &inst->capability.mbs_per_frame);
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001517 print_cap("mbs_per_sec", &inst->capability.mbs_per_sec);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001518 print_cap("frame_rate", &inst->capability.frame_rate);
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001519 print_cap("bitrate", &inst->capability.bitrate);
1520 print_cap("peak_bitrate", &inst->capability.peakbitrate);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001521 print_cap("scale_x", &inst->capability.scale_x);
1522 print_cap("scale_y", &inst->capability.scale_y);
1523 print_cap("hier_p", &inst->capability.hier_p);
1524 print_cap("ltr_count", &inst->capability.ltr_count);
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001525 print_cap("bframe", &inst->capability.bframe);
1526 print_cap("secure_output2_threshold",
1527 &inst->capability.secure_output2_threshold);
1528 print_cap("hier_b", &inst->capability.hier_b);
1529 print_cap("lcu_size", &inst->capability.lcu_size);
1530 print_cap("hier_p_hybrid", &inst->capability.hier_p_hybrid);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001531 print_cap("mbs_per_sec_low_power",
1532 &inst->capability.mbs_per_sec_power_save);
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001533 print_cap("extradata", &inst->capability.extradata);
1534 print_cap("profile", &inst->capability.profile);
1535 print_cap("level", &inst->capability.level);
1536 print_cap("i_qp", &inst->capability.i_qp);
1537 print_cap("p_qp", &inst->capability.p_qp);
1538 print_cap("b_qp", &inst->capability.b_qp);
1539 print_cap("rc_modes", &inst->capability.rc_modes);
1540 print_cap("blur_width", &inst->capability.blur_width);
1541 print_cap("blur_height", &inst->capability.blur_height);
1542 print_cap("slice_delivery_mode", &inst->capability.slice_delivery_mode);
1543 print_cap("slice_bytes", &inst->capability.slice_bytes);
1544 print_cap("slice_mbs", &inst->capability.slice_mbs);
1545 print_cap("secure", &inst->capability.secure);
1546 print_cap("max_num_b_frames", &inst->capability.max_num_b_frames);
1547 print_cap("max_video_cores", &inst->capability.max_video_cores);
1548 print_cap("max_work_modes", &inst->capability.max_work_modes);
1549 print_cap("ubwc_cr_stats", &inst->capability.ubwc_cr_stats);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001550
Vaibhav Deshu Venkateshf962e1c2017-07-24 16:19:01 -07001551 dprintk(VIDC_DBG, "profile count : %u",
1552 inst->capability.profile_level.profile_count);
1553 for (i = 0; i < inst->capability.profile_level.profile_count; i++) {
1554 dprintk(VIDC_DBG, "profile : %u ", inst->capability.
1555 profile_level.profile_level[i].profile);
1556 dprintk(VIDC_DBG, "level : %u ", inst->capability.
1557 profile_level.profile_level[i].level);
1558 }
1559
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001560 signal_session_msg_receipt(cmd, inst);
Praneeth Paladugue1679112017-01-27 10:07:15 -08001561
1562 /*
1563 * Update controls after informing session_init_done to avoid
1564 * timeouts.
1565 */
1566
1567 msm_vidc_comm_update_ctrl_limits(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001568 put_inst(inst);
1569}
1570
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001571static void msm_vidc_queue_rbr_event(struct msm_vidc_inst *inst,
1572 int fd, u32 offset)
1573{
1574 struct v4l2_event buf_event = {0};
1575 u32 *ptr;
1576
1577 buf_event.type = V4L2_EVENT_RELEASE_BUFFER_REFERENCE;
1578 ptr = (u32 *)buf_event.u.data;
1579 ptr[0] = fd;
1580 ptr[1] = offset;
1581
1582 v4l2_event_queue_fh(&inst->event_handler, &buf_event);
1583}
1584
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001585static void handle_event_change(enum hal_command_response cmd, void *data)
1586{
1587 struct msm_vidc_inst *inst = NULL;
1588 struct msm_vidc_cb_event *event_notify = data;
1589 int event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
1590 struct v4l2_event seq_changed_event = {0};
1591 int rc = 0;
1592 struct hfi_device *hdev;
1593 u32 *ptr = NULL;
Praneeth Paladugu6e637472017-05-16 16:06:46 -07001594 struct hal_buffer_requirements *bufreq;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001595
1596 if (!event_notify) {
1597 dprintk(VIDC_WARN, "Got an empty event from hfi\n");
1598 return;
1599 }
1600
1601 inst = get_inst(get_vidc_core(event_notify->device_id),
1602 event_notify->session_id);
1603 if (!inst || !inst->core || !inst->core->device) {
1604 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1605 goto err_bad_event;
1606 }
1607 hdev = inst->core->device;
1608
1609 switch (event_notify->hal_event_type) {
1610 case HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES:
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001611 event = V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001612 break;
1613 case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
1614 event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
1615 break;
1616 case HAL_EVENT_RELEASE_BUFFER_REFERENCE:
1617 {
Maheshwar Ajjacca04052017-07-12 17:59:45 -07001618 struct msm_vidc_buffer *mbuf;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001619 u32 planes[VIDEO_MAX_PLANES] = {0};
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001620
1621 dprintk(VIDC_DBG,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001622 "%s: inst: %pK data_buffer: %x extradata_buffer: %x\n",
1623 __func__, inst, event_notify->packet_buffer,
1624 event_notify->extra_data_buffer);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001625
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001626 planes[0] = event_notify->packet_buffer;
1627 planes[1] = event_notify->extra_data_buffer;
Maheshwar Ajjacca04052017-07-12 17:59:45 -07001628 mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
1629 if (!mbuf || !kref_get_mbuf(inst, mbuf)) {
1630 dprintk(VIDC_ERR,
1631 "%s: data_addr %x, extradata_addr %x not found\n",
1632 __func__, planes[0], planes[1]);
1633 } else {
1634 handle_release_buffer_reference(inst, mbuf);
1635 kref_put_mbuf(mbuf);
1636 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001637 goto err_bad_event;
1638 }
1639 default:
1640 break;
1641 }
1642
1643 /* Bit depth and pic struct changed event are combined into a single
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001644 * event (insufficient event) for the userspace. Currently bitdepth
1645 * changes is only for HEVC and interlaced support is for all
1646 * codecs except HEVC
1647 * event data is now as follows:
1648 * u32 *ptr = seq_changed_event.u.data;
1649 * ptr[0] = height
1650 * ptr[1] = width
1651 * ptr[2] = bit depth
1652 * ptr[3] = pic struct (progressive or interlaced)
1653 * ptr[4] = colour space
Umesh Pandey92bd41d2017-08-10 14:52:33 -07001654 * ptr[5] = crop_data(top)
1655 * ptr[6] = crop_data(left)
1656 * ptr[7] = crop_data(height)
1657 * ptr[8] = crop_data(width)
1658 * ptr[9] = profile
1659 * ptr[10] = level
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001660 */
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001661
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -07001662 inst->entropy_mode = event_notify->entropy_mode;
1663 inst->profile = event_notify->profile;
1664 inst->level = event_notify->level;
Praneeth Paladugu520e9b22017-05-31 13:25:18 -07001665 inst->prop.crop_info.left =
1666 event_notify->crop_data.left;
1667 inst->prop.crop_info.top =
1668 event_notify->crop_data.top;
1669 inst->prop.crop_info.height =
1670 event_notify->crop_data.height;
1671 inst->prop.crop_info.width =
1672 event_notify->crop_data.width;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -08001673
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001674 ptr = (u32 *)seq_changed_event.u.data;
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001675 ptr[0] = event_notify->height;
1676 ptr[1] = event_notify->width;
1677 ptr[2] = event_notify->bit_depth;
1678 ptr[3] = event_notify->pic_struct;
1679 ptr[4] = event_notify->colour_space;
Praneeth Paladugu72fa67b2017-05-30 11:20:01 -07001680 ptr[5] = event_notify->crop_data.top;
1681 ptr[6] = event_notify->crop_data.left;
1682 ptr[7] = event_notify->crop_data.height;
1683 ptr[8] = event_notify->crop_data.width;
Umesh Pandey92bd41d2017-08-10 14:52:33 -07001684 ptr[9] = msm_comm_get_v4l2_profile(
1685 inst->fmts[OUTPUT_PORT].fourcc,
1686 event_notify->profile);
1687 ptr[10] = msm_comm_get_v4l2_level(
1688 inst->fmts[OUTPUT_PORT].fourcc,
1689 event_notify->level);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001690
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001691 dprintk(VIDC_DBG,
Umesh Pandey92bd41d2017-08-10 14:52:33 -07001692 "Event payload: height = %d width = %d profile = %d level = %d\n",
1693 event_notify->height, event_notify->width,
1694 ptr[9], ptr[10]);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001695
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001696 dprintk(VIDC_DBG,
1697 "Event payload: bit_depth = %d pic_struct = %d colour_space = %d\n",
1698 event_notify->bit_depth, event_notify->pic_struct,
1699 event_notify->colour_space);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001700
Praneeth Paladugu520e9b22017-05-31 13:25:18 -07001701 dprintk(VIDC_DBG,
1702 "Event payload: CROP top = %d left = %d Height = %d Width = %d\n",
1703 event_notify->crop_data.top,
1704 event_notify->crop_data.left,
1705 event_notify->crop_data.height,
1706 event_notify->crop_data.width);
1707
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001708 mutex_lock(&inst->lock);
1709 inst->in_reconfig = true;
1710 inst->reconfig_height = event_notify->height;
1711 inst->reconfig_width = event_notify->width;
Praneeth Paladugu6e637472017-05-16 16:06:46 -07001712
1713 if (msm_comm_get_stream_output_mode(inst) ==
1714 HAL_VIDEO_DECODER_SECONDARY) {
1715
1716 bufreq = get_buff_req_buffer(inst,
1717 HAL_BUFFER_OUTPUT);
1718 if (!bufreq) {
1719 dprintk(VIDC_ERR,
1720 "Failed : No buffer requirements : %x\n",
1721 HAL_BUFFER_OUTPUT);
1722 return;
1723 }
1724
1725 bufreq->buffer_count_min = event_notify->capture_buf_count;
1726
1727 bufreq = get_buff_req_buffer(inst,
1728 HAL_BUFFER_OUTPUT2);
1729 if (!bufreq) {
1730 dprintk(VIDC_ERR,
1731 "Failed : No buffer requirements : %x\n",
1732 HAL_BUFFER_OUTPUT2);
1733 return;
1734 }
1735
1736 bufreq->buffer_count_min = event_notify->capture_buf_count;
1737 } else {
1738
1739 bufreq = get_buff_req_buffer(inst,
1740 HAL_BUFFER_OUTPUT);
1741 if (!bufreq) {
1742 dprintk(VIDC_ERR,
1743 "Failed : No buffer requirements : %x\n",
1744 HAL_BUFFER_OUTPUT);
1745 return;
1746 }
1747 bufreq->buffer_count_min = event_notify->capture_buf_count;
Praneeth Paladugu6e637472017-05-16 16:06:46 -07001748 }
1749
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001750 mutex_unlock(&inst->lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001751
1752 if (event == V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT) {
1753 dprintk(VIDC_DBG, "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT\n");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001754 } else {
1755 dprintk(VIDC_DBG, "V4L2_EVENT_SEQ_CHANGED_SUFFICIENT\n");
1756 dprintk(VIDC_DBG,
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001757 "event_notify->height = %d event_notify->width = %d\n",
1758 event_notify->height,
1759 event_notify->width);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001760 }
1761
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001762 rc = msm_vidc_check_session_supported(inst);
1763 if (!rc) {
1764 seq_changed_event.type = event;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001765 v4l2_event_queue_fh(&inst->event_handler, &seq_changed_event);
1766 } else if (rc == -ENOTSUPP) {
1767 msm_vidc_queue_v4l2_event(inst,
1768 V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED);
1769 } else if (rc == -EBUSY) {
1770 msm_vidc_queue_v4l2_event(inst,
1771 V4L2_EVENT_MSM_VIDC_HW_OVERLOAD);
1772 }
1773
1774err_bad_event:
1775 put_inst(inst);
1776}
1777
1778static void handle_session_prop_info(enum hal_command_response cmd, void *data)
1779{
1780 struct msm_vidc_cb_cmd_done *response = data;
1781 struct getprop_buf *getprop;
1782 struct msm_vidc_inst *inst;
1783
1784 if (!response) {
1785 dprintk(VIDC_ERR,
1786 "Failed to get valid response for prop info\n");
1787 return;
1788 }
1789
1790 inst = get_inst(get_vidc_core(response->device_id),
1791 response->session_id);
1792 if (!inst) {
1793 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1794 return;
1795 }
1796
1797 getprop = kzalloc(sizeof(*getprop), GFP_KERNEL);
1798 if (!getprop) {
1799 dprintk(VIDC_ERR, "%s: getprop kzalloc failed\n", __func__);
1800 goto err_prop_info;
1801 }
1802
1803 getprop->data = kmemdup(&response->data.property,
1804 sizeof(union hal_get_property), GFP_KERNEL);
1805 if (!getprop->data) {
1806 dprintk(VIDC_ERR, "%s: kmemdup failed\n", __func__);
1807 kfree(getprop);
1808 goto err_prop_info;
1809 }
1810
1811 mutex_lock(&inst->pending_getpropq.lock);
1812 list_add_tail(&getprop->list, &inst->pending_getpropq.list);
1813 mutex_unlock(&inst->pending_getpropq.lock);
1814
1815 signal_session_msg_receipt(cmd, inst);
1816err_prop_info:
1817 put_inst(inst);
1818}
1819
1820static void handle_load_resource_done(enum hal_command_response cmd, void *data)
1821{
1822 struct msm_vidc_cb_cmd_done *response = data;
1823 struct msm_vidc_inst *inst;
1824
1825 if (!response) {
1826 dprintk(VIDC_ERR,
1827 "Failed to get valid response for load resource\n");
1828 return;
1829 }
1830
1831 inst = get_inst(get_vidc_core(response->device_id),
1832 response->session_id);
1833 if (!inst) {
1834 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1835 return;
1836 }
1837
1838 if (response->status) {
1839 dprintk(VIDC_ERR,
1840 "Load resource response from FW : %#x\n",
1841 response->status);
1842 msm_comm_generate_session_error(inst);
1843 }
1844
1845 put_inst(inst);
1846}
1847
1848static void handle_start_done(enum hal_command_response cmd, void *data)
1849{
1850 struct msm_vidc_cb_cmd_done *response = data;
1851 struct msm_vidc_inst *inst;
1852
1853 if (!response) {
1854 dprintk(VIDC_ERR, "Failed to get valid response for start\n");
1855 return;
1856 }
1857
1858 inst = get_inst(get_vidc_core(response->device_id),
1859 response->session_id);
1860 if (!inst) {
1861 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1862 return;
1863 }
1864
1865 signal_session_msg_receipt(cmd, inst);
1866 put_inst(inst);
1867}
1868
1869static void handle_stop_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 stop\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_release_res_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,
1897 "Failed to get valid response for release resource\n");
1898 return;
1899 }
1900
1901 inst = get_inst(get_vidc_core(response->device_id),
1902 response->session_id);
1903 if (!inst) {
1904 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1905 return;
1906 }
1907
1908 signal_session_msg_receipt(cmd, inst);
1909 put_inst(inst);
1910}
1911
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08001912void msm_comm_validate_output_buffers(struct msm_vidc_inst *inst)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001913{
1914 struct internal_buf *binfo;
1915 u32 buffers_owned_by_driver = 0;
1916 struct hal_buffer_requirements *output_buf;
1917
1918 output_buf = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
1919
1920 if (!output_buf) {
1921 dprintk(VIDC_DBG,
1922 "This output buffer not required, buffer_type: %x\n",
1923 HAL_BUFFER_OUTPUT);
1924 return;
1925 }
1926 mutex_lock(&inst->outputbufs.lock);
Maheshwar Ajja850be3c2017-07-06 17:47:40 -07001927 if (list_empty(&inst->outputbufs.list)) {
1928 dprintk(VIDC_DBG, "%s: no OUTPUT buffers allocated\n",
1929 __func__);
1930 mutex_unlock(&inst->outputbufs.lock);
1931 return;
1932 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001933 list_for_each_entry(binfo, &inst->outputbufs.list, list) {
1934 if (binfo->buffer_ownership != DRIVER) {
1935 dprintk(VIDC_DBG,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001936 "This buffer is with FW %x\n",
1937 binfo->smem.device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001938 continue;
1939 }
1940 buffers_owned_by_driver++;
1941 }
1942 mutex_unlock(&inst->outputbufs.lock);
1943
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08001944 if (buffers_owned_by_driver != output_buf->buffer_count_actual) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001945 dprintk(VIDC_WARN,
1946 "OUTPUT Buffer count mismatch %d of %d\n",
1947 buffers_owned_by_driver,
1948 output_buf->buffer_count_actual);
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08001949 msm_vidc_handle_hw_error(inst->core);
1950 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001951}
1952
1953int msm_comm_queue_output_buffers(struct msm_vidc_inst *inst)
1954{
1955 struct internal_buf *binfo;
1956 struct hfi_device *hdev;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001957 struct vidc_frame_data frame_data = {0};
1958 struct hal_buffer_requirements *output_buf, *extra_buf;
1959 int rc = 0;
1960
1961 if (!inst || !inst->core || !inst->core->device) {
1962 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
1963 return -EINVAL;
1964 }
1965
1966 hdev = inst->core->device;
1967
1968 output_buf = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
1969 if (!output_buf) {
1970 dprintk(VIDC_DBG,
1971 "This output buffer not required, buffer_type: %x\n",
1972 HAL_BUFFER_OUTPUT);
1973 return 0;
1974 }
1975 dprintk(VIDC_DBG,
1976 "output: num = %d, size = %d\n",
1977 output_buf->buffer_count_actual,
1978 output_buf->buffer_size);
1979
1980 extra_buf = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_OUTPUT);
1981
1982 mutex_lock(&inst->outputbufs.lock);
1983 list_for_each_entry(binfo, &inst->outputbufs.list, list) {
1984 if (binfo->buffer_ownership != DRIVER)
1985 continue;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001986 frame_data.alloc_len = output_buf->buffer_size;
1987 frame_data.filled_len = 0;
1988 frame_data.offset = 0;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001989 frame_data.device_addr = binfo->smem.device_addr;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001990 frame_data.flags = 0;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001991 frame_data.extradata_addr = binfo->smem.device_addr +
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001992 output_buf->buffer_size;
1993 frame_data.buffer_type = HAL_BUFFER_OUTPUT;
1994 frame_data.extradata_size = extra_buf ?
1995 extra_buf->buffer_size : 0;
1996 rc = call_hfi_op(hdev, session_ftb,
1997 (void *) inst->session, &frame_data);
1998 binfo->buffer_ownership = FIRMWARE;
1999 }
2000 mutex_unlock(&inst->outputbufs.lock);
2001
2002 return 0;
2003}
2004
2005static void handle_session_flush(enum hal_command_response cmd, void *data)
2006{
2007 struct msm_vidc_cb_cmd_done *response = data;
2008 struct msm_vidc_inst *inst;
2009 struct v4l2_event flush_event = {0};
2010 u32 *ptr = NULL;
2011 enum hal_flush flush_type;
2012 int rc;
2013
2014 if (!response) {
2015 dprintk(VIDC_ERR, "Failed to get valid response for flush\n");
2016 return;
2017 }
2018
2019 inst = get_inst(get_vidc_core(response->device_id),
2020 response->session_id);
2021 if (!inst) {
2022 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2023 return;
2024 }
2025
2026 if (msm_comm_get_stream_output_mode(inst) ==
2027 HAL_VIDEO_DECODER_SECONDARY) {
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08002028
2029 if (!(inst->fmts[OUTPUT_PORT].defer_outputs &&
2030 inst->in_reconfig))
2031 msm_comm_validate_output_buffers(inst);
2032
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002033 if (!inst->in_reconfig) {
2034 rc = msm_comm_queue_output_buffers(inst);
2035 if (rc) {
2036 dprintk(VIDC_ERR,
2037 "Failed to queue output buffers: %d\n",
2038 rc);
2039 }
2040 }
2041 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002042 inst->in_flush = false;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002043 flush_event.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
2044 ptr = (u32 *)flush_event.u.data;
2045
2046 flush_type = response->data.flush_type;
2047 switch (flush_type) {
2048 case HAL_FLUSH_INPUT:
2049 ptr[0] = V4L2_QCOM_CMD_FLUSH_OUTPUT;
2050 break;
2051 case HAL_FLUSH_OUTPUT:
2052 ptr[0] = V4L2_QCOM_CMD_FLUSH_CAPTURE;
2053 break;
2054 case HAL_FLUSH_ALL:
2055 ptr[0] |= V4L2_QCOM_CMD_FLUSH_CAPTURE;
2056 ptr[0] |= V4L2_QCOM_CMD_FLUSH_OUTPUT;
2057 break;
2058 default:
2059 dprintk(VIDC_ERR, "Invalid flush type received!");
2060 goto exit;
2061 }
2062
2063 dprintk(VIDC_DBG,
2064 "Notify flush complete, flush_type: %x\n", flush_type);
2065 v4l2_event_queue_fh(&inst->event_handler, &flush_event);
2066
2067exit:
2068 put_inst(inst);
2069}
2070
2071static void handle_session_error(enum hal_command_response cmd, void *data)
2072{
2073 struct msm_vidc_cb_cmd_done *response = data;
2074 struct hfi_device *hdev = NULL;
2075 struct msm_vidc_inst *inst = NULL;
2076 int event = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
2077
2078 if (!response) {
2079 dprintk(VIDC_ERR,
2080 "Failed to get valid response for session error\n");
2081 return;
2082 }
2083
2084 inst = get_inst(get_vidc_core(response->device_id),
2085 response->session_id);
2086 if (!inst) {
2087 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2088 return;
2089 }
2090
2091 hdev = inst->core->device;
2092 dprintk(VIDC_WARN, "Session error received for session %pK\n", inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002093
2094 if (response->status == VIDC_ERR_MAX_CLIENTS) {
2095 dprintk(VIDC_WARN, "Too many clients, rejecting %pK", inst);
2096 event = V4L2_EVENT_MSM_VIDC_MAX_CLIENTS;
2097
2098 /*
2099 * Clean the HFI session now. Since inst->state is moved to
2100 * INVALID, forward thread doesn't know FW has valid session
2101 * or not. This is the last place driver knows that there is
2102 * no session in FW. Hence clean HFI session now.
2103 */
2104
2105 msm_comm_session_clean(inst);
2106 } else if (response->status == VIDC_ERR_NOT_SUPPORTED) {
2107 dprintk(VIDC_WARN, "Unsupported bitstream in %pK", inst);
2108 event = V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED;
2109 } else {
2110 dprintk(VIDC_WARN, "Unknown session error (%d) for %pK\n",
2111 response->status, inst);
2112 event = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
2113 }
2114
2115 msm_vidc_queue_v4l2_event(inst, event);
2116 put_inst(inst);
2117}
2118
2119static void msm_comm_clean_notify_client(struct msm_vidc_core *core)
2120{
2121 struct msm_vidc_inst *inst = NULL;
2122
2123 if (!core) {
2124 dprintk(VIDC_ERR, "%s: Invalid params\n", __func__);
2125 return;
2126 }
2127
2128 dprintk(VIDC_WARN, "%s: Core %pK\n", __func__, core);
2129 mutex_lock(&core->lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002130
2131 list_for_each_entry(inst, &core->instances, list) {
2132 mutex_lock(&inst->lock);
2133 inst->state = MSM_VIDC_CORE_INVALID;
2134 mutex_unlock(&inst->lock);
2135 dprintk(VIDC_WARN,
2136 "%s Send sys error for inst %pK\n", __func__, inst);
2137 msm_vidc_queue_v4l2_event(inst,
2138 V4L2_EVENT_MSM_VIDC_SYS_ERROR);
2139 }
2140 mutex_unlock(&core->lock);
2141}
2142
2143static void handle_sys_error(enum hal_command_response cmd, void *data)
2144{
2145 struct msm_vidc_cb_cmd_done *response = data;
2146 struct msm_vidc_core *core = NULL;
2147 struct hfi_device *hdev = NULL;
2148 struct msm_vidc_inst *inst = NULL;
2149 int rc = 0;
2150
2151 subsystem_crashed("venus");
2152 if (!response) {
2153 dprintk(VIDC_ERR,
2154 "Failed to get valid response for sys error\n");
2155 return;
2156 }
2157
2158 core = get_vidc_core(response->device_id);
2159 if (!core) {
2160 dprintk(VIDC_ERR,
2161 "Got SYS_ERR but unable to identify core\n");
2162 return;
2163 }
2164
2165 mutex_lock(&core->lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002166 if (core->state == VIDC_CORE_UNINIT) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002167 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07002168 "%s: Core %pK already moved to state %d\n",
2169 __func__, core, core->state);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002170 mutex_unlock(&core->lock);
2171 return;
2172 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002173
Maheshwar Ajja99422322017-07-07 17:31:15 -07002174 dprintk(VIDC_WARN, "SYS_ERROR received for core %pK\n", core);
Maheshwar Ajja9ff81a22017-08-05 13:25:55 -07002175 msm_vidc_noc_error_info(core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002176 call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002177 list_for_each_entry(inst, &core->instances, list) {
2178 dprintk(VIDC_WARN,
2179 "%s: Send sys error for inst %pK\n", __func__, inst);
2180 change_inst_state(inst, MSM_VIDC_CORE_INVALID);
2181 msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_SYS_ERROR);
2182 msm_comm_print_inst_info(inst);
2183 }
2184 hdev = core->device;
2185 dprintk(VIDC_DBG, "Calling core_release\n");
2186 rc = call_hfi_op(hdev, core_release, hdev->hfi_device_data);
2187 if (rc) {
2188 dprintk(VIDC_ERR, "core_release failed\n");
2189 mutex_unlock(&core->lock);
2190 return;
2191 }
2192 core->state = VIDC_CORE_UNINIT;
2193 mutex_unlock(&core->lock);
2194
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002195 dprintk(VIDC_ERR,
2196 "SYS_ERROR can potentially crash the system\n");
2197
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002198 msm_vidc_handle_hw_error(core);
2199}
2200
2201void msm_comm_session_clean(struct msm_vidc_inst *inst)
2202{
2203 int rc = 0;
2204 struct hfi_device *hdev = NULL;
2205
2206 if (!inst || !inst->core || !inst->core->device) {
2207 dprintk(VIDC_ERR, "%s invalid params\n", __func__);
2208 return;
2209 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002210 if (!inst->session) {
2211 dprintk(VIDC_DBG, "%s: inst %pK session already cleaned\n",
2212 __func__, inst);
2213 return;
2214 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002215
2216 hdev = inst->core->device;
2217 mutex_lock(&inst->lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002218 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
2219 rc = call_hfi_op(hdev, session_clean,
2220 (void *)inst->session);
2221 if (rc) {
2222 dprintk(VIDC_ERR,
2223 "Session clean failed :%pK\n", inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002224 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002225 inst->session = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002226 mutex_unlock(&inst->lock);
2227}
2228
2229static void handle_session_close(enum hal_command_response cmd, void *data)
2230{
2231 struct msm_vidc_cb_cmd_done *response = data;
2232 struct msm_vidc_inst *inst;
2233
2234 if (!response) {
2235 dprintk(VIDC_ERR,
2236 "Failed to get valid response for session close\n");
2237 return;
2238 }
2239
2240 inst = get_inst(get_vidc_core(response->device_id),
2241 response->session_id);
2242 if (!inst) {
2243 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2244 return;
2245 }
2246
2247 signal_session_msg_receipt(cmd, inst);
2248 show_stats(inst);
2249 put_inst(inst);
2250}
2251
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002252struct vb2_buffer *msm_comm_get_vb_using_vidc_buffer(
2253 struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002254{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002255 u32 port = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002256 struct vb2_buffer *vb = NULL;
2257 struct vb2_queue *q = NULL;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002258 bool found = false;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002259
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002260 if (mbuf->vvb.vb2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
2261 port = CAPTURE_PORT;
2262 } else if (mbuf->vvb.vb2_buf.type ==
2263 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
2264 port = OUTPUT_PORT;
2265 } else {
2266 dprintk(VIDC_ERR, "%s: invalid type %d\n",
2267 __func__, mbuf->vvb.vb2_buf.type);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002268 return NULL;
2269 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002270
2271 q = &inst->bufq[port].vb2_bufq;
2272 mutex_lock(&inst->bufq[port].lock);
2273 found = false;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002274 list_for_each_entry(vb, &q->queued_list, queued_entry) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002275 if (msm_comm_compare_vb2_planes(inst, mbuf, vb)) {
2276 found = true;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002277 break;
2278 }
2279 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002280 mutex_unlock(&inst->bufq[port].lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002281 if (!found) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002282 print_vidc_buffer(VIDC_ERR, "vb2 not found for", inst, mbuf);
2283 return NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002284 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002285
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002286 return vb;
2287}
2288
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002289int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst,
2290 struct vb2_buffer *vb)
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002291{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002292 u32 port;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002293
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002294 if (!inst || !vb) {
2295 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
2296 __func__, inst, vb);
2297 return -EINVAL;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002298 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002299
2300 if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
2301 port = CAPTURE_PORT;
2302 } else if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
2303 port = OUTPUT_PORT;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002304 } else {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002305 dprintk(VIDC_ERR, "%s: invalid type %d\n",
2306 __func__, vb->type);
2307 return -EINVAL;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002308 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002309 msm_vidc_debugfs_update(inst, port == CAPTURE_PORT ?
2310 MSM_VIDC_DEBUGFS_EVENT_FBD :
2311 MSM_VIDC_DEBUGFS_EVENT_EBD);
2312
2313 mutex_lock(&inst->bufq[port].lock);
2314 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
2315 mutex_unlock(&inst->bufq[port].lock);
2316
2317 return 0;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002318}
2319
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07002320static bool is_eos_buffer(struct msm_vidc_inst *inst, u32 device_addr)
2321{
2322 struct eos_buf *temp, *next;
2323 bool found = false;
2324
2325 mutex_lock(&inst->eosbufs.lock);
2326 list_for_each_entry_safe(temp, next, &inst->eosbufs.list, list) {
2327 if (temp->smem.device_addr == device_addr) {
2328 found = true;
2329 list_del(&temp->list);
2330 msm_comm_smem_free(inst, &temp->smem);
2331 kfree(temp);
2332 break;
2333 }
2334 }
2335 mutex_unlock(&inst->eosbufs.lock);
2336
2337 return found;
2338}
2339
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002340static void handle_ebd(enum hal_command_response cmd, void *data)
2341{
2342 struct msm_vidc_cb_data_done *response = data;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002343 struct msm_vidc_buffer *mbuf;
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002344 struct vb2_buffer *vb, *vb2;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002345 struct msm_vidc_inst *inst;
2346 struct vidc_hal_ebd *empty_buf_done;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002347 struct vb2_v4l2_buffer *vbuf;
2348 u32 planes[VIDEO_MAX_PLANES] = {0};
2349 u32 extra_idx = 0, i;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002350
2351 if (!response) {
2352 dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
2353 return;
2354 }
2355
2356 inst = get_inst(get_vidc_core(response->device_id),
2357 response->session_id);
2358 if (!inst) {
2359 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2360 return;
2361 }
2362
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002363 empty_buf_done = (struct vidc_hal_ebd *)&response->input_done;
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07002364 /* If this is internal EOS buffer, handle it in driver */
2365 if (is_eos_buffer(inst, empty_buf_done->packet_buffer)) {
2366 dprintk(VIDC_DBG, "Received EOS buffer %pK\n",
2367 (void *)(u64)empty_buf_done->packet_buffer);
2368 goto exit;
2369 }
2370
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002371 planes[0] = empty_buf_done->packet_buffer;
2372 planes[1] = empty_buf_done->extra_data_buffer;
2373
2374 mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002375 if (!mbuf || !kref_get_mbuf(inst, mbuf)) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002376 dprintk(VIDC_ERR,
2377 "%s: data_addr %x, extradata_addr %x not found\n",
2378 __func__, planes[0], planes[1]);
2379 goto exit;
2380 }
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002381 vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
2382
2383 /*
2384 * take registeredbufs.lock to update mbuf & vb2 variables together
2385 * so that both are in sync else if mbuf and vb2 variables are not
2386 * in sync msm_comm_compare_vb2_planes() returns false for the
2387 * right buffer due to data_offset field mismatch.
2388 */
2389 mutex_lock(&inst->registeredbufs.lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002390 vb = &mbuf->vvb.vb2_buf;
2391
2392 vb->planes[0].bytesused = response->input_done.filled_len;
2393 if (vb->planes[0].bytesused > vb->planes[0].length)
2394 dprintk(VIDC_INFO, "bytesused overflow length\n");
2395
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002396 vb->planes[0].data_offset = response->input_done.offset;
2397 if (vb->planes[0].data_offset > vb->planes[0].length)
2398 dprintk(VIDC_INFO, "data_offset overflow length\n");
2399
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002400 if (empty_buf_done->status == VIDC_ERR_NOT_SUPPORTED) {
2401 dprintk(VIDC_INFO, "Failed : Unsupported input stream\n");
2402 mbuf->vvb.flags |= V4L2_QCOM_BUF_INPUT_UNSUPPORTED;
2403 }
2404 if (empty_buf_done->status == VIDC_ERR_BITSTREAM_ERR) {
2405 dprintk(VIDC_INFO, "Failed : Corrupted input stream\n");
2406 mbuf->vvb.flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
2407 }
2408 if (empty_buf_done->flags & HAL_BUFFERFLAG_SYNCFRAME)
2409 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME |
2410 V4L2_BUF_FLAG_KEYFRAME;
2411
2412 extra_idx = EXTRADATA_IDX(inst->bufq[OUTPUT_PORT].num_planes);
2413 if (extra_idx && extra_idx < VIDEO_MAX_PLANES)
2414 vb->planes[extra_idx].bytesused = vb->planes[extra_idx].length;
2415
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002416 if (vb2) {
2417 vbuf = to_vb2_v4l2_buffer(vb2);
2418 vbuf->flags |= mbuf->vvb.flags;
2419 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
2420 vb2->planes[i].bytesused =
2421 mbuf->vvb.vb2_buf.planes[i].bytesused;
2422 vb2->planes[i].data_offset =
2423 mbuf->vvb.vb2_buf.planes[i].data_offset;
2424 }
2425 }
2426 mutex_unlock(&inst->registeredbufs.lock);
2427
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002428 update_recon_stats(inst, &empty_buf_done->recon_stats);
2429 msm_vidc_clear_freq_entry(inst, mbuf->smem[0].device_addr);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002430 /*
2431 * put_buffer should be done before vb2_buffer_done else
2432 * client might queue the same buffer before it is unmapped
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002433 * in put_buffer.
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002434 */
2435 msm_comm_put_vidc_buffer(inst, mbuf);
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002436 msm_comm_vb2_buffer_done(inst, vb2);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002437 kref_put_mbuf(mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002438exit:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002439 put_inst(inst);
2440}
2441
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002442static int handle_multi_stream_buffers(struct msm_vidc_inst *inst,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002443 u32 dev_addr)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002444{
2445 struct internal_buf *binfo;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002446 struct msm_smem *smem;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002447 bool found = false;
2448
2449 mutex_lock(&inst->outputbufs.lock);
2450 list_for_each_entry(binfo, &inst->outputbufs.list, list) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002451 smem = &binfo->smem;
2452 if (smem && dev_addr == smem->device_addr) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002453 if (binfo->buffer_ownership == DRIVER) {
2454 dprintk(VIDC_ERR,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002455 "FW returned same buffer: %x\n",
2456 dev_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002457 break;
2458 }
2459 binfo->buffer_ownership = DRIVER;
2460 found = true;
2461 break;
2462 }
2463 }
2464 mutex_unlock(&inst->outputbufs.lock);
2465
2466 if (!found) {
2467 dprintk(VIDC_ERR,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002468 "Failed to find output buffer in queued list: %x\n",
2469 dev_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002470 }
2471
2472 return 0;
2473}
2474
2475enum hal_buffer msm_comm_get_hal_output_buffer(struct msm_vidc_inst *inst)
2476{
2477 if (msm_comm_get_stream_output_mode(inst) ==
2478 HAL_VIDEO_DECODER_SECONDARY)
2479 return HAL_BUFFER_OUTPUT2;
2480 else
2481 return HAL_BUFFER_OUTPUT;
2482}
2483
2484static void handle_fbd(enum hal_command_response cmd, void *data)
2485{
2486 struct msm_vidc_cb_data_done *response = data;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002487 struct msm_vidc_buffer *mbuf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002488 struct msm_vidc_inst *inst;
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002489 struct vb2_buffer *vb, *vb2;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002490 struct vidc_hal_fbd *fill_buf_done;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002491 struct vb2_v4l2_buffer *vbuf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002492 enum hal_buffer buffer_type;
Vaibhav Deshu Venkateshe5800332017-03-21 14:27:11 -07002493 u64 time_usec = 0;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002494 u32 planes[VIDEO_MAX_PLANES] = {0};
2495 u32 extra_idx, i;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002496
2497 if (!response) {
2498 dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
2499 return;
2500 }
2501
2502 inst = get_inst(get_vidc_core(response->device_id),
2503 response->session_id);
2504 if (!inst) {
2505 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2506 return;
2507 }
2508
2509 fill_buf_done = (struct vidc_hal_fbd *)&response->output_done;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002510 planes[0] = fill_buf_done->packet_buffer1;
2511 planes[1] = fill_buf_done->extra_data_buffer;
2512
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002513 buffer_type = msm_comm_get_hal_output_buffer(inst);
2514 if (fill_buf_done->buffer_type == buffer_type) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002515 mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002516 if (!mbuf || !kref_get_mbuf(inst, mbuf)) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002517 dprintk(VIDC_ERR,
2518 "%s: data_addr %x, extradata_addr %x not found\n",
2519 __func__, planes[0], planes[1]);
2520 goto exit;
2521 }
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002522 vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002523 } else {
2524 if (handle_multi_stream_buffers(inst,
2525 fill_buf_done->packet_buffer1))
2526 dprintk(VIDC_ERR,
2527 "Failed : Output buffer not found %pa\n",
2528 &fill_buf_done->packet_buffer1);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002529 goto exit;
2530 }
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002531
2532 /*
2533 * take registeredbufs.lock to update mbuf & vb2 variables together
2534 * so that both are in sync else if mbuf and vb2 variables are not
2535 * in sync msm_comm_compare_vb2_planes() returns false for the
2536 * right buffer due to data_offset field mismatch.
2537 */
2538 mutex_lock(&inst->registeredbufs.lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002539 vb = &mbuf->vvb.vb2_buf;
2540
2541 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME ||
2542 fill_buf_done->flags1 & HAL_BUFFERFLAG_DECODEONLY)
2543 fill_buf_done->filled_len1 = 0;
2544 vb->planes[0].bytesused = fill_buf_done->filled_len1;
2545 if (vb->planes[0].bytesused > vb->planes[0].length)
2546 dprintk(VIDC_INFO,
2547 "fbd:Overflow bytesused = %d; length = %d\n",
2548 vb->planes[0].bytesused,
2549 vb->planes[0].length);
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002550 vb->planes[0].data_offset = fill_buf_done->offset1;
2551 if (vb->planes[0].data_offset > vb->planes[0].length)
2552 dprintk(VIDC_INFO,
2553 "fbd:Overflow data_offset = %d; length = %d\n",
2554 vb->planes[0].data_offset,
2555 vb->planes[0].length);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002556 if (!(fill_buf_done->flags1 & HAL_BUFFERFLAG_TIMESTAMPINVALID)) {
2557 time_usec = fill_buf_done->timestamp_hi;
2558 time_usec = (time_usec << 32) | fill_buf_done->timestamp_lo;
2559 } else {
2560 time_usec = 0;
2561 dprintk(VIDC_DBG,
2562 "Set zero timestamp for buffer %pa, filled: %d, (hi:%u, lo:%u)\n",
2563 &fill_buf_done->packet_buffer1,
2564 fill_buf_done->filled_len1,
2565 fill_buf_done->timestamp_hi,
2566 fill_buf_done->timestamp_lo);
2567 }
2568 vb->timestamp = (time_usec * NSEC_PER_USEC);
2569
Qiwei Liu551a22222017-08-23 15:28:29 +08002570 if (inst->session_type == MSM_VIDC_DECODER) {
2571 msm_comm_store_mark_data(&inst->fbd_data, vb->index,
2572 fill_buf_done->mark_data, fill_buf_done->mark_target);
2573 }
2574
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002575 extra_idx = EXTRADATA_IDX(inst->bufq[CAPTURE_PORT].num_planes);
2576 if (extra_idx && extra_idx < VIDEO_MAX_PLANES)
2577 vb->planes[extra_idx].bytesused = vb->planes[extra_idx].length;
2578
2579 mbuf->vvb.flags = 0;
2580 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_READONLY)
2581 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_READONLY;
2582 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOS)
2583 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_EOS;
2584 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_CODECCONFIG)
2585 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_CODECCONFIG;
2586 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_SYNCFRAME)
2587 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
2588 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOSEQ)
2589 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_EOSEQ;
2590 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DECODEONLY ||
2591 fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME)
2592 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_DECODEONLY;
2593 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DATACORRUPT)
2594 mbuf->vvb.flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
2595 switch (fill_buf_done->picture_type) {
2596 case HAL_PICTURE_IDR:
2597 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
2598 mbuf->vvb.flags |= V4L2_BUF_FLAG_KEYFRAME;
2599 break;
2600 case HAL_PICTURE_I:
2601 mbuf->vvb.flags |= V4L2_BUF_FLAG_KEYFRAME;
2602 break;
2603 case HAL_PICTURE_P:
2604 mbuf->vvb.flags |= V4L2_BUF_FLAG_PFRAME;
2605 break;
2606 case HAL_PICTURE_B:
2607 mbuf->vvb.flags |= V4L2_BUF_FLAG_BFRAME;
2608 break;
2609 case HAL_FRAME_NOTCODED:
2610 case HAL_UNUSED_PICT:
2611 /* Do we need to care about these? */
2612 case HAL_FRAME_YUV:
2613 break;
2614 default:
2615 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002616 }
2617
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002618 if (vb2) {
2619 vbuf = to_vb2_v4l2_buffer(vb2);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002620 vbuf->flags = mbuf->vvb.flags;
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002621 vb2->timestamp = mbuf->vvb.vb2_buf.timestamp;
2622 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
2623 vb2->planes[i].bytesused =
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002624 mbuf->vvb.vb2_buf.planes[i].bytesused;
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002625 vb2->planes[i].data_offset =
2626 mbuf->vvb.vb2_buf.planes[i].data_offset;
2627 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002628 }
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002629 mutex_unlock(&inst->registeredbufs.lock);
2630
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002631 /*
2632 * put_buffer should be done before vb2_buffer_done else
2633 * client might queue the same buffer before it is unmapped
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002634 * in put_buffer.
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002635 */
2636 msm_comm_put_vidc_buffer(inst, mbuf);
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002637 msm_comm_vb2_buffer_done(inst, vb2);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002638 kref_put_mbuf(mbuf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002639
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002640exit:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002641 put_inst(inst);
2642}
2643
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002644void handle_cmd_response(enum hal_command_response cmd, void *data)
2645{
2646 dprintk(VIDC_DBG, "Command response = %d\n", cmd);
2647 switch (cmd) {
2648 case HAL_SYS_INIT_DONE:
2649 handle_sys_init_done(cmd, data);
2650 break;
2651 case HAL_SYS_RELEASE_RESOURCE_DONE:
2652 handle_sys_release_res_done(cmd, data);
2653 break;
2654 case HAL_SESSION_INIT_DONE:
2655 handle_session_init_done(cmd, data);
2656 break;
2657 case HAL_SESSION_PROPERTY_INFO:
2658 handle_session_prop_info(cmd, data);
2659 break;
2660 case HAL_SESSION_LOAD_RESOURCE_DONE:
2661 handle_load_resource_done(cmd, data);
2662 break;
2663 case HAL_SESSION_START_DONE:
2664 handle_start_done(cmd, data);
2665 break;
2666 case HAL_SESSION_ETB_DONE:
2667 handle_ebd(cmd, data);
2668 break;
2669 case HAL_SESSION_FTB_DONE:
2670 handle_fbd(cmd, data);
2671 break;
2672 case HAL_SESSION_STOP_DONE:
2673 handle_stop_done(cmd, data);
2674 break;
2675 case HAL_SESSION_RELEASE_RESOURCE_DONE:
2676 handle_release_res_done(cmd, data);
2677 break;
2678 case HAL_SESSION_END_DONE:
2679 case HAL_SESSION_ABORT_DONE:
2680 handle_session_close(cmd, data);
2681 break;
2682 case HAL_SESSION_EVENT_CHANGE:
2683 handle_event_change(cmd, data);
2684 break;
2685 case HAL_SESSION_FLUSH_DONE:
2686 handle_session_flush(cmd, data);
2687 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002688 case HAL_SYS_WATCHDOG_TIMEOUT:
2689 case HAL_SYS_ERROR:
2690 handle_sys_error(cmd, data);
2691 break;
2692 case HAL_SESSION_ERROR:
2693 handle_session_error(cmd, data);
2694 break;
2695 case HAL_SESSION_RELEASE_BUFFER_DONE:
2696 handle_session_release_buf_done(cmd, data);
2697 break;
2698 default:
2699 dprintk(VIDC_DBG, "response unhandled: %d\n", cmd);
2700 break;
2701 }
2702}
2703
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002704static inline enum msm_vidc_thermal_level msm_comm_vidc_thermal_level(int level)
2705{
2706 switch (level) {
2707 case 0:
2708 return VIDC_THERMAL_NORMAL;
2709 case 1:
2710 return VIDC_THERMAL_LOW;
2711 case 2:
2712 return VIDC_THERMAL_HIGH;
2713 default:
2714 return VIDC_THERMAL_CRITICAL;
2715 }
2716}
2717
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002718static bool is_core_turbo(struct msm_vidc_core *core, unsigned long freq)
2719{
2720 int i = 0;
Praneeth Paladugub71968b2015-08-19 20:47:57 -07002721 struct allowed_clock_rates_table *allowed_clks_tbl = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002722 u32 max_freq = 0;
2723
Praneeth Paladugub71968b2015-08-19 20:47:57 -07002724 allowed_clks_tbl = core->resources.allowed_clks_tbl;
2725 for (i = 0; i < core->resources.allowed_clks_tbl_size; i++) {
2726 if (max_freq < allowed_clks_tbl[i].clock_rate)
2727 max_freq = allowed_clks_tbl[i].clock_rate;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002728 }
2729 return freq >= max_freq;
2730}
2731
2732static bool is_thermal_permissible(struct msm_vidc_core *core)
2733{
2734 enum msm_vidc_thermal_level tl;
2735 unsigned long freq = 0;
2736 bool is_turbo = false;
2737
2738 if (!core->resources.thermal_mitigable)
2739 return true;
2740
2741 if (msm_vidc_thermal_mitigation_disabled) {
2742 dprintk(VIDC_DBG,
2743 "Thermal mitigation not enabled. debugfs %d\n",
2744 msm_vidc_thermal_mitigation_disabled);
2745 return true;
2746 }
2747
2748 tl = msm_comm_vidc_thermal_level(vidc_driver->thermal_level);
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07002749 freq = core->curr_freq;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002750
2751 is_turbo = is_core_turbo(core, freq);
2752 dprintk(VIDC_DBG,
2753 "Core freq %ld Thermal level %d Turbo mode %d\n",
2754 freq, tl, is_turbo);
2755
2756 if (is_turbo && tl >= VIDC_THERMAL_LOW) {
2757 dprintk(VIDC_ERR,
2758 "Video session not allowed. Turbo mode %d Thermal level %d\n",
2759 is_turbo, tl);
2760 return false;
2761 }
2762 return true;
2763}
2764
2765static int msm_comm_session_abort(struct msm_vidc_inst *inst)
2766{
2767 int rc = 0, abort_completion = 0;
2768 struct hfi_device *hdev;
2769
2770 if (!inst || !inst->core || !inst->core->device) {
2771 dprintk(VIDC_ERR, "%s invalid params\n", __func__);
2772 return -EINVAL;
2773 }
2774 hdev = inst->core->device;
2775 abort_completion = SESSION_MSG_INDEX(HAL_SESSION_ABORT_DONE);
2776
Maheshwar Ajja99422322017-07-07 17:31:15 -07002777 dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002778 rc = call_hfi_op(hdev, session_abort, (void *)inst->session);
2779 if (rc) {
2780 dprintk(VIDC_ERR,
2781 "%s session_abort failed rc: %d\n", __func__, rc);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002782 goto exit;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002783 }
2784 rc = wait_for_completion_timeout(
2785 &inst->completions[abort_completion],
Praneeth Paladugud5bf7bc2017-05-29 23:41:04 -07002786 msecs_to_jiffies(
2787 inst->core->resources.msm_vidc_hw_rsp_timeout));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002788 if (!rc) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07002789 dprintk(VIDC_ERR, "%s: inst %pK abort timed out\n",
2790 __func__, inst);
2791 msm_comm_generate_sys_error(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002792 rc = -EBUSY;
2793 } else {
2794 rc = 0;
2795 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002796exit:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002797 return rc;
2798}
2799
2800static void handle_thermal_event(struct msm_vidc_core *core)
2801{
2802 int rc = 0;
2803 struct msm_vidc_inst *inst;
2804
2805 if (!core || !core->device) {
2806 dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
2807 return;
2808 }
2809 mutex_lock(&core->lock);
2810 list_for_each_entry(inst, &core->instances, list) {
2811 if (!inst->session)
2812 continue;
2813
2814 mutex_unlock(&core->lock);
2815 if (inst->state >= MSM_VIDC_OPEN_DONE &&
2816 inst->state < MSM_VIDC_CLOSE_DONE) {
2817 dprintk(VIDC_WARN, "%s: abort inst %pK\n",
2818 __func__, inst);
2819 rc = msm_comm_session_abort(inst);
2820 if (rc) {
2821 dprintk(VIDC_ERR,
2822 "%s session_abort failed rc: %d\n",
2823 __func__, rc);
2824 goto err_sess_abort;
2825 }
2826 change_inst_state(inst, MSM_VIDC_CORE_INVALID);
2827 dprintk(VIDC_WARN,
2828 "%s Send sys error for inst %pK\n",
2829 __func__, inst);
2830 msm_vidc_queue_v4l2_event(inst,
2831 V4L2_EVENT_MSM_VIDC_SYS_ERROR);
2832 } else {
2833 msm_comm_generate_session_error(inst);
2834 }
2835 mutex_lock(&core->lock);
2836 }
2837 mutex_unlock(&core->lock);
2838 return;
2839
2840err_sess_abort:
2841 msm_comm_clean_notify_client(core);
2842}
2843
2844void msm_comm_handle_thermal_event(void)
2845{
2846 struct msm_vidc_core *core;
2847
2848 list_for_each_entry(core, &vidc_driver->cores, list) {
2849 if (!is_thermal_permissible(core)) {
2850 dprintk(VIDC_WARN,
2851 "Thermal level critical, stop all active sessions!\n");
2852 handle_thermal_event(core);
2853 }
2854 }
2855}
2856
2857int msm_comm_check_core_init(struct msm_vidc_core *core)
2858{
2859 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002860
2861 mutex_lock(&core->lock);
2862 if (core->state >= VIDC_CORE_INIT_DONE) {
2863 dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
2864 core->id, core->state);
2865 goto exit;
2866 }
2867 dprintk(VIDC_DBG, "Waiting for SYS_INIT_DONE\n");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002868 rc = wait_for_completion_timeout(
2869 &core->completions[SYS_MSG_INDEX(HAL_SYS_INIT_DONE)],
Praneeth Paladugud5bf7bc2017-05-29 23:41:04 -07002870 msecs_to_jiffies(core->resources.msm_vidc_hw_rsp_timeout));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002871 if (!rc) {
2872 dprintk(VIDC_ERR, "%s: Wait interrupted or timed out: %d\n",
2873 __func__, SYS_MSG_INDEX(HAL_SYS_INIT_DONE));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002874 rc = -EIO;
2875 goto exit;
2876 } else {
2877 core->state = VIDC_CORE_INIT_DONE;
2878 rc = 0;
2879 }
2880 dprintk(VIDC_DBG, "SYS_INIT_DONE!!!\n");
2881exit:
2882 mutex_unlock(&core->lock);
2883 return rc;
2884}
2885
2886static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
2887{
2888 int rc = 0;
2889
2890 rc = msm_comm_check_core_init(inst->core);
2891 if (rc) {
2892 dprintk(VIDC_ERR, "%s - failed to initialize core\n", __func__);
2893 msm_comm_generate_sys_error(inst);
2894 return rc;
2895 }
2896 change_inst_state(inst, MSM_VIDC_CORE_INIT_DONE);
2897 return rc;
2898}
2899
2900static int msm_comm_init_core(struct msm_vidc_inst *inst)
2901{
2902 int rc = 0;
2903 struct hfi_device *hdev;
2904 struct msm_vidc_core *core;
2905
2906 if (!inst || !inst->core || !inst->core->device)
2907 return -EINVAL;
2908
2909 core = inst->core;
2910 hdev = core->device;
2911 mutex_lock(&core->lock);
2912 if (core->state >= VIDC_CORE_INIT) {
2913 dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
2914 core->id, core->state);
2915 goto core_already_inited;
2916 }
2917 if (!core->capabilities) {
2918 core->capabilities = kzalloc(VIDC_MAX_SESSIONS *
2919 sizeof(struct msm_vidc_capability), GFP_KERNEL);
2920 if (!core->capabilities) {
2921 dprintk(VIDC_ERR,
2922 "%s: failed to allocate capabilities\n",
2923 __func__);
2924 rc = -ENOMEM;
2925 goto fail_cap_alloc;
2926 }
2927 } else {
2928 dprintk(VIDC_WARN,
2929 "%s: capabilities memory is expected to be freed\n",
2930 __func__);
2931 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002932 dprintk(VIDC_DBG, "%s: core %pK\n", __func__, core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002933 rc = call_hfi_op(hdev, core_init, hdev->hfi_device_data);
2934 if (rc) {
2935 dprintk(VIDC_ERR, "Failed to init core, id = %d\n",
2936 core->id);
2937 goto fail_core_init;
2938 }
2939 core->state = VIDC_CORE_INIT;
2940 core->smmu_fault_handled = false;
Maheshwar Ajja8382bec2017-08-11 13:41:35 -07002941 core->trigger_ssr = false;
2942
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002943core_already_inited:
2944 change_inst_state(inst, MSM_VIDC_CORE_INIT);
2945 mutex_unlock(&core->lock);
Praneeth Paladugub71968b2015-08-19 20:47:57 -07002946
2947 rc = msm_comm_scale_clocks_and_bus(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002948 return rc;
2949
2950fail_core_init:
2951 kfree(core->capabilities);
2952fail_cap_alloc:
2953 core->capabilities = NULL;
2954 core->state = VIDC_CORE_UNINIT;
2955 mutex_unlock(&core->lock);
2956 return rc;
2957}
2958
2959static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
2960{
2961 struct msm_vidc_core *core;
2962 struct hfi_device *hdev;
2963
2964 if (!inst || !inst->core || !inst->core->device) {
2965 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
2966 return -EINVAL;
2967 }
2968
2969 core = inst->core;
2970 hdev = core->device;
2971
2972 mutex_lock(&core->lock);
2973 if (core->state == VIDC_CORE_UNINIT) {
2974 dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
2975 core->id, core->state);
2976 goto core_already_uninited;
2977 }
2978 mutex_unlock(&core->lock);
2979
2980 msm_comm_scale_clocks_and_bus(inst);
2981
2982 mutex_lock(&core->lock);
2983
2984 if (!core->resources.never_unload_fw) {
2985 cancel_delayed_work(&core->fw_unload_work);
2986
2987 /*
2988 * Delay unloading of firmware. This is useful
2989 * in avoiding firmware download delays in cases where we
2990 * will have a burst of back to back video playback sessions
2991 * e.g. thumbnail generation.
2992 */
2993 schedule_delayed_work(&core->fw_unload_work,
Maheshwar Ajja99422322017-07-07 17:31:15 -07002994 msecs_to_jiffies(core->state == VIDC_CORE_INIT_DONE ?
2995 core->resources.msm_vidc_firmware_unload_delay : 0));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002996
2997 dprintk(VIDC_DBG, "firmware unload delayed by %u ms\n",
Maheshwar Ajja99422322017-07-07 17:31:15 -07002998 core->state == VIDC_CORE_INIT_DONE ?
2999 core->resources.msm_vidc_firmware_unload_delay : 0);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003000 }
3001
3002core_already_uninited:
3003 change_inst_state(inst, MSM_VIDC_CORE_UNINIT);
3004 mutex_unlock(&core->lock);
3005 return 0;
3006}
3007
3008int msm_comm_force_cleanup(struct msm_vidc_inst *inst)
3009{
3010 msm_comm_kill_session(inst);
3011 return msm_vidc_deinit_core(inst);
3012}
3013
3014static int msm_comm_session_init(int flipped_state,
3015 struct msm_vidc_inst *inst)
3016{
3017 int rc = 0;
3018 int fourcc = 0;
3019 struct hfi_device *hdev;
3020
3021 if (!inst || !inst->core || !inst->core->device) {
3022 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3023 return -EINVAL;
3024 }
3025 hdev = inst->core->device;
3026
3027 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_OPEN)) {
3028 dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
3029 inst, inst->state);
3030 goto exit;
3031 }
3032 if (inst->session_type == MSM_VIDC_DECODER) {
3033 fourcc = inst->fmts[OUTPUT_PORT].fourcc;
3034 } else if (inst->session_type == MSM_VIDC_ENCODER) {
3035 fourcc = inst->fmts[CAPTURE_PORT].fourcc;
3036 } else {
3037 dprintk(VIDC_ERR, "Invalid session\n");
3038 return -EINVAL;
3039 }
3040
Praneeth Paladugub71968b2015-08-19 20:47:57 -07003041 msm_comm_init_clocks_and_bus_data(inst);
3042
Maheshwar Ajja99422322017-07-07 17:31:15 -07003043 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003044 rc = call_hfi_op(hdev, session_init, hdev->hfi_device_data,
3045 inst, get_hal_domain(inst->session_type),
3046 get_hal_codec(fourcc),
3047 &inst->session);
3048
3049 if (rc || !inst->session) {
3050 dprintk(VIDC_ERR,
3051 "Failed to call session init for: %pK, %pK, %d, %d\n",
3052 inst->core->device, inst,
3053 inst->session_type, fourcc);
3054 rc = -EINVAL;
3055 goto exit;
3056 }
3057 change_inst_state(inst, MSM_VIDC_OPEN);
3058exit:
3059 return rc;
3060}
3061
3062static void msm_vidc_print_running_insts(struct msm_vidc_core *core)
3063{
3064 struct msm_vidc_inst *temp;
3065
3066 dprintk(VIDC_ERR, "Running instances:\n");
3067 dprintk(VIDC_ERR, "%4s|%4s|%4s|%4s|%4s\n",
3068 "type", "w", "h", "fps", "prop");
3069
3070 mutex_lock(&core->lock);
3071 list_for_each_entry(temp, &core->instances, list) {
3072 if (temp->state >= MSM_VIDC_OPEN_DONE &&
3073 temp->state < MSM_VIDC_STOP_DONE) {
3074 char properties[4] = "";
3075
3076 if (is_thumbnail_session(temp))
3077 strlcat(properties, "N", sizeof(properties));
3078
3079 if (msm_comm_turbo_session(temp))
3080 strlcat(properties, "T", sizeof(properties));
3081
3082 dprintk(VIDC_ERR, "%4d|%4d|%4d|%4d|%4s\n",
3083 temp->session_type,
3084 max(temp->prop.width[CAPTURE_PORT],
3085 temp->prop.width[OUTPUT_PORT]),
3086 max(temp->prop.height[CAPTURE_PORT],
3087 temp->prop.height[OUTPUT_PORT]),
3088 temp->prop.fps, properties);
3089 }
3090 }
3091 mutex_unlock(&core->lock);
3092}
3093
3094static int msm_vidc_load_resources(int flipped_state,
3095 struct msm_vidc_inst *inst)
3096{
3097 int rc = 0;
3098 struct hfi_device *hdev;
3099 int num_mbs_per_sec = 0, max_load_adj = 0;
3100 struct msm_vidc_core *core;
3101 enum load_calc_quirks quirks = LOAD_CALC_IGNORE_TURBO_LOAD |
3102 LOAD_CALC_IGNORE_THUMBNAIL_LOAD |
3103 LOAD_CALC_IGNORE_NON_REALTIME_LOAD;
3104
3105 if (!inst || !inst->core || !inst->core->device) {
3106 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3107 return -EINVAL;
3108 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003109 if (inst->state == MSM_VIDC_CORE_INVALID) {
3110 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07003111 "%s: inst %pK is in invalid state\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003112 return -EINVAL;
3113 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003114 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
3115 dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
3116 inst, inst->state);
3117 goto exit;
3118 }
3119 core = inst->core;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003120
3121 num_mbs_per_sec =
3122 msm_comm_get_load(core, MSM_VIDC_DECODER, quirks) +
3123 msm_comm_get_load(core, MSM_VIDC_ENCODER, quirks);
3124
3125 max_load_adj = core->resources.max_load +
3126 inst->capability.mbs_per_frame.max;
3127
3128 if (num_mbs_per_sec > max_load_adj) {
3129 dprintk(VIDC_ERR, "HW is overloaded, needed: %d max: %d\n",
3130 num_mbs_per_sec, max_load_adj);
3131 msm_vidc_print_running_insts(core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003132 msm_comm_kill_session(inst);
3133 return -EBUSY;
3134 }
3135
3136 hdev = core->device;
Maheshwar Ajja99422322017-07-07 17:31:15 -07003137 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003138 rc = call_hfi_op(hdev, session_load_res, (void *) inst->session);
3139 if (rc) {
3140 dprintk(VIDC_ERR,
3141 "Failed to send load resources\n");
3142 goto exit;
3143 }
3144 change_inst_state(inst, MSM_VIDC_LOAD_RESOURCES);
3145exit:
3146 return rc;
3147}
3148
3149static int msm_vidc_start(int flipped_state, struct msm_vidc_inst *inst)
3150{
3151 int rc = 0;
3152 struct hfi_device *hdev;
3153
3154 if (!inst || !inst->core || !inst->core->device) {
3155 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3156 return -EINVAL;
3157 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003158 if (inst->state == MSM_VIDC_CORE_INVALID) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003159 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07003160 "%s: inst %pK is in invalid\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003161 return -EINVAL;
3162 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003163 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_START)) {
3164 dprintk(VIDC_INFO,
3165 "inst: %pK is already in state: %d\n",
3166 inst, inst->state);
3167 goto exit;
3168 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003169 hdev = inst->core->device;
3170 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003171 rc = call_hfi_op(hdev, session_start, (void *) inst->session);
3172 if (rc) {
3173 dprintk(VIDC_ERR,
3174 "Failed to send start\n");
3175 goto exit;
3176 }
3177 change_inst_state(inst, MSM_VIDC_START);
3178exit:
3179 return rc;
3180}
3181
3182static int msm_vidc_stop(int flipped_state, struct msm_vidc_inst *inst)
3183{
3184 int rc = 0;
3185 struct hfi_device *hdev;
3186
3187 if (!inst || !inst->core || !inst->core->device) {
3188 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3189 return -EINVAL;
3190 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003191 if (inst->state == MSM_VIDC_CORE_INVALID) {
3192 dprintk(VIDC_ERR,
3193 "%s: inst %pK is in invalid state\n", __func__, inst);
3194 return -EINVAL;
3195 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003196 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_STOP)) {
3197 dprintk(VIDC_INFO,
3198 "inst: %pK is already in state: %d\n",
3199 inst, inst->state);
3200 goto exit;
3201 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003202 hdev = inst->core->device;
3203 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003204 rc = call_hfi_op(hdev, session_stop, (void *) inst->session);
3205 if (rc) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07003206 dprintk(VIDC_ERR, "%s: inst %pK session_stop failed\n",
3207 __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003208 goto exit;
3209 }
3210 change_inst_state(inst, MSM_VIDC_STOP);
3211exit:
3212 return rc;
3213}
3214
3215static int msm_vidc_release_res(int flipped_state, struct msm_vidc_inst *inst)
3216{
3217 int rc = 0;
3218 struct hfi_device *hdev;
3219
3220 if (!inst || !inst->core || !inst->core->device) {
3221 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3222 return -EINVAL;
3223 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003224 if (inst->state == MSM_VIDC_CORE_INVALID) {
3225 dprintk(VIDC_ERR,
3226 "%s: inst %pK is in invalid state\n", __func__, inst);
3227 return -EINVAL;
3228 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003229 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_RELEASE_RESOURCES)) {
3230 dprintk(VIDC_INFO,
3231 "inst: %pK is already in state: %d\n",
3232 inst, inst->state);
3233 goto exit;
3234 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003235 hdev = inst->core->device;
3236 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003237 rc = call_hfi_op(hdev, session_release_res, (void *) inst->session);
3238 if (rc) {
3239 dprintk(VIDC_ERR,
3240 "Failed to send release resources\n");
3241 goto exit;
3242 }
3243 change_inst_state(inst, MSM_VIDC_RELEASE_RESOURCES);
3244exit:
3245 return rc;
3246}
3247
3248static int msm_comm_session_close(int flipped_state,
3249 struct msm_vidc_inst *inst)
3250{
3251 int rc = 0;
3252 struct hfi_device *hdev;
3253
3254 if (!inst || !inst->core || !inst->core->device) {
3255 dprintk(VIDC_ERR, "%s invalid params\n", __func__);
3256 return -EINVAL;
3257 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003258 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_CLOSE)) {
3259 dprintk(VIDC_INFO,
3260 "inst: %pK is already in state: %d\n",
3261 inst, inst->state);
3262 goto exit;
3263 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003264 hdev = inst->core->device;
3265 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003266 rc = call_hfi_op(hdev, session_end, (void *) inst->session);
3267 if (rc) {
3268 dprintk(VIDC_ERR,
3269 "Failed to send close\n");
3270 goto exit;
3271 }
3272 change_inst_state(inst, MSM_VIDC_CLOSE);
3273exit:
3274 return rc;
3275}
3276
3277int msm_comm_suspend(int core_id)
3278{
3279 struct hfi_device *hdev;
3280 struct msm_vidc_core *core;
3281 int rc = 0;
3282
3283 core = get_vidc_core(core_id);
3284 if (!core) {
3285 dprintk(VIDC_ERR,
3286 "%s: Failed to find core for core_id = %d\n",
3287 __func__, core_id);
3288 return -EINVAL;
3289 }
3290
3291 hdev = (struct hfi_device *)core->device;
3292 if (!hdev) {
3293 dprintk(VIDC_ERR, "%s Invalid device handle\n", __func__);
3294 return -EINVAL;
3295 }
3296
3297 mutex_lock(&core->lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003298 if (core->state != VIDC_CORE_INIT_DONE) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003299 dprintk(VIDC_ERR,
3300 "%s - fw is not in proper state, skip suspend\n",
3301 __func__);
3302 rc = -EINVAL;
3303 goto exit;
3304 }
3305
3306 rc = call_hfi_op(hdev, suspend, hdev->hfi_device_data);
3307 if (rc)
3308 dprintk(VIDC_WARN, "Failed to suspend\n");
3309
3310exit:
3311 mutex_unlock(&core->lock);
3312 return rc;
3313}
3314
3315static int get_flipped_state(int present_state,
3316 int desired_state)
3317{
3318 int flipped_state = present_state;
3319
3320 if (flipped_state < MSM_VIDC_STOP
3321 && desired_state > MSM_VIDC_STOP) {
3322 flipped_state = MSM_VIDC_STOP + (MSM_VIDC_STOP - flipped_state);
3323 flipped_state &= 0xFFFE;
3324 flipped_state = flipped_state - 1;
3325 } else if (flipped_state > MSM_VIDC_STOP
3326 && desired_state < MSM_VIDC_STOP) {
3327 flipped_state = MSM_VIDC_STOP -
3328 (flipped_state - MSM_VIDC_STOP + 1);
3329 flipped_state &= 0xFFFE;
3330 flipped_state = flipped_state - 1;
3331 }
3332 return flipped_state;
3333}
3334
3335struct hal_buffer_requirements *get_buff_req_buffer(
3336 struct msm_vidc_inst *inst, enum hal_buffer buffer_type)
3337{
3338 int i;
3339
3340 for (i = 0; i < HAL_BUFFER_MAX; i++) {
3341 if (inst->buff_req.buffer[i].buffer_type == buffer_type)
3342 return &inst->buff_req.buffer[i];
3343 }
3344 return NULL;
3345}
3346
3347static int set_output_buffers(struct msm_vidc_inst *inst,
3348 enum hal_buffer buffer_type)
3349{
3350 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003351 struct internal_buf *binfo;
3352 u32 smem_flags = 0, buffer_size;
3353 struct hal_buffer_requirements *output_buf, *extradata_buf;
3354 int i;
3355 struct hfi_device *hdev;
3356 struct hal_buffer_size_minimum b;
3357
3358 hdev = inst->core->device;
3359
3360 output_buf = get_buff_req_buffer(inst, buffer_type);
3361 if (!output_buf) {
3362 dprintk(VIDC_DBG,
3363 "This output buffer not required, buffer_type: %x\n",
3364 buffer_type);
3365 return 0;
3366 }
Praneeth Paladugu86c7c242017-07-16 19:44:42 -07003367
3368 /* For DPB buffers, Always use FW count */
3369 output_buf->buffer_count_actual = output_buf->buffer_count_min_host =
3370 output_buf->buffer_count_min;
3371
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003372 dprintk(VIDC_DBG,
3373 "output: num = %d, size = %d\n",
3374 output_buf->buffer_count_actual,
3375 output_buf->buffer_size);
3376
3377 buffer_size = output_buf->buffer_size;
3378 b.buffer_type = buffer_type;
3379 b.buffer_size = buffer_size;
3380 rc = call_hfi_op(hdev, session_set_property,
3381 inst->session, HAL_PARAM_BUFFER_SIZE_MINIMUM,
3382 &b);
3383
3384 extradata_buf = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_OUTPUT);
3385 if (extradata_buf) {
3386 dprintk(VIDC_DBG,
3387 "extradata: num = %d, size = %d\n",
3388 extradata_buf->buffer_count_actual,
3389 extradata_buf->buffer_size);
3390 buffer_size += extradata_buf->buffer_size;
3391 } else {
3392 dprintk(VIDC_DBG,
3393 "This extradata buffer not required, buffer_type: %x\n",
3394 buffer_type);
3395 }
3396
3397 if (inst->flags & VIDC_SECURE)
3398 smem_flags |= SMEM_SECURE;
3399
3400 if (output_buf->buffer_size) {
3401 for (i = 0; i < output_buf->buffer_count_actual;
3402 i++) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003403 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
3404 if (!binfo) {
3405 dprintk(VIDC_ERR, "Out of memory\n");
3406 rc = -ENOMEM;
3407 goto fail_kzalloc;
3408 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003409 rc = msm_comm_smem_alloc(inst,
3410 buffer_size, 1, smem_flags,
3411 buffer_type, 0, &binfo->smem);
3412 if (rc) {
3413 dprintk(VIDC_ERR,
3414 "Failed to allocate output memory\n");
3415 goto err_no_mem;
3416 }
3417 rc = msm_comm_smem_cache_operations(inst,
3418 &binfo->smem, SMEM_CACHE_CLEAN);
3419 if (rc) {
3420 dprintk(VIDC_WARN,
3421 "Failed to clean cache may cause undefined behavior\n");
3422 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003423 binfo->buffer_type = buffer_type;
3424 binfo->buffer_ownership = DRIVER;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003425 dprintk(VIDC_DBG, "Output buffer address: %#x\n",
3426 binfo->smem.device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003427
3428 if (inst->buffer_mode_set[CAPTURE_PORT] ==
3429 HAL_BUFFER_MODE_STATIC) {
3430 struct vidc_buffer_addr_info buffer_info = {0};
3431
3432 buffer_info.buffer_size =
3433 output_buf->buffer_size;
3434 buffer_info.buffer_type = buffer_type;
3435 buffer_info.num_buffers = 1;
3436 buffer_info.align_device_addr =
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003437 binfo->smem.device_addr;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003438 buffer_info.extradata_addr =
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003439 binfo->smem.device_addr +
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003440 output_buf->buffer_size;
3441 if (extradata_buf)
3442 buffer_info.extradata_size =
3443 extradata_buf->buffer_size;
3444 rc = call_hfi_op(hdev, session_set_buffers,
3445 (void *) inst->session, &buffer_info);
3446 if (rc) {
3447 dprintk(VIDC_ERR,
3448 "%s : session_set_buffers failed\n",
3449 __func__);
3450 goto fail_set_buffers;
3451 }
3452 }
3453 mutex_lock(&inst->outputbufs.lock);
3454 list_add_tail(&binfo->list, &inst->outputbufs.list);
3455 mutex_unlock(&inst->outputbufs.lock);
3456 }
3457 }
3458 return rc;
3459fail_set_buffers:
3460 kfree(binfo);
3461fail_kzalloc:
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003462 msm_comm_smem_free(inst, &binfo->smem);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003463err_no_mem:
3464 return rc;
3465}
3466
3467static inline char *get_buffer_name(enum hal_buffer buffer_type)
3468{
3469 switch (buffer_type) {
3470 case HAL_BUFFER_INPUT: return "input";
3471 case HAL_BUFFER_OUTPUT: return "output";
3472 case HAL_BUFFER_OUTPUT2: return "output_2";
3473 case HAL_BUFFER_EXTRADATA_INPUT: return "input_extra";
3474 case HAL_BUFFER_EXTRADATA_OUTPUT: return "output_extra";
3475 case HAL_BUFFER_EXTRADATA_OUTPUT2: return "output2_extra";
3476 case HAL_BUFFER_INTERNAL_SCRATCH: return "scratch";
3477 case HAL_BUFFER_INTERNAL_SCRATCH_1: return "scratch_1";
3478 case HAL_BUFFER_INTERNAL_SCRATCH_2: return "scratch_2";
3479 case HAL_BUFFER_INTERNAL_PERSIST: return "persist";
3480 case HAL_BUFFER_INTERNAL_PERSIST_1: return "persist_1";
3481 case HAL_BUFFER_INTERNAL_CMD_QUEUE: return "queue";
3482 default: return "????";
3483 }
3484}
3485
3486static int set_internal_buf_on_fw(struct msm_vidc_inst *inst,
3487 enum hal_buffer buffer_type,
3488 struct msm_smem *handle, bool reuse)
3489{
3490 struct vidc_buffer_addr_info buffer_info;
3491 struct hfi_device *hdev;
3492 int rc = 0;
3493
3494 if (!inst || !inst->core || !inst->core->device || !handle) {
3495 dprintk(VIDC_ERR, "%s - invalid params\n", __func__);
3496 return -EINVAL;
3497 }
3498
3499 hdev = inst->core->device;
3500
3501 rc = msm_comm_smem_cache_operations(inst,
3502 handle, SMEM_CACHE_CLEAN);
3503 if (rc) {
3504 dprintk(VIDC_WARN,
3505 "Failed to clean cache. Undefined behavior\n");
3506 }
3507
3508 buffer_info.buffer_size = handle->size;
3509 buffer_info.buffer_type = buffer_type;
3510 buffer_info.num_buffers = 1;
3511 buffer_info.align_device_addr = handle->device_addr;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003512 dprintk(VIDC_DBG, "%s %s buffer : %x\n",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003513 reuse ? "Reusing" : "Allocated",
3514 get_buffer_name(buffer_type),
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003515 buffer_info.align_device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003516
3517 rc = call_hfi_op(hdev, session_set_buffers,
3518 (void *) inst->session, &buffer_info);
3519 if (rc) {
3520 dprintk(VIDC_ERR,
3521 "vidc_hal_session_set_buffers failed\n");
3522 return rc;
3523 }
3524 return 0;
3525}
3526
3527static bool reuse_internal_buffers(struct msm_vidc_inst *inst,
3528 enum hal_buffer buffer_type, struct msm_vidc_list *buf_list)
3529{
3530 struct internal_buf *buf;
3531 int rc = 0;
3532 bool reused = false;
3533
3534 if (!inst || !buf_list) {
3535 dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
3536 return false;
3537 }
3538
3539 mutex_lock(&buf_list->lock);
3540 list_for_each_entry(buf, &buf_list->list, list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003541 if (buf->buffer_type != buffer_type)
3542 continue;
3543
3544 /*
3545 * Persist buffer size won't change with resolution. If they
3546 * are in queue means that they are already allocated and
3547 * given to HW. HW can use them without reallocation. These
3548 * buffers are not released as part of port reconfig. So
3549 * driver no need to set them again.
3550 */
3551
3552 if (buffer_type != HAL_BUFFER_INTERNAL_PERSIST
3553 && buffer_type != HAL_BUFFER_INTERNAL_PERSIST_1) {
3554
3555 rc = set_internal_buf_on_fw(inst, buffer_type,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003556 &buf->smem, true);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003557 if (rc) {
3558 dprintk(VIDC_ERR,
3559 "%s: session_set_buffers failed\n",
3560 __func__);
3561 reused = false;
3562 break;
3563 }
3564 }
3565 reused = true;
3566 dprintk(VIDC_DBG,
3567 "Re-using internal buffer type : %d\n", buffer_type);
3568 }
3569 mutex_unlock(&buf_list->lock);
3570 return reused;
3571}
3572
3573static int allocate_and_set_internal_bufs(struct msm_vidc_inst *inst,
3574 struct hal_buffer_requirements *internal_bufreq,
3575 struct msm_vidc_list *buf_list)
3576{
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003577 struct internal_buf *binfo;
3578 u32 smem_flags = 0;
3579 int rc = 0;
3580 int i = 0;
3581
3582 if (!inst || !internal_bufreq || !buf_list)
3583 return -EINVAL;
3584
3585 if (!internal_bufreq->buffer_size)
3586 return 0;
3587
3588 if (inst->flags & VIDC_SECURE)
3589 smem_flags |= SMEM_SECURE;
3590
3591 for (i = 0; i < internal_bufreq->buffer_count_actual; i++) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003592 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
3593 if (!binfo) {
3594 dprintk(VIDC_ERR, "Out of memory\n");
3595 rc = -ENOMEM;
3596 goto fail_kzalloc;
3597 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003598 rc = msm_comm_smem_alloc(inst, internal_bufreq->buffer_size,
3599 1, smem_flags, internal_bufreq->buffer_type,
3600 0, &binfo->smem);
3601 if (rc) {
3602 dprintk(VIDC_ERR,
3603 "Failed to allocate scratch memory\n");
3604 goto err_no_mem;
3605 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003606
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003607 binfo->buffer_type = internal_bufreq->buffer_type;
3608
3609 rc = set_internal_buf_on_fw(inst, internal_bufreq->buffer_type,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003610 &binfo->smem, false);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003611 if (rc)
3612 goto fail_set_buffers;
3613
3614 mutex_lock(&buf_list->lock);
3615 list_add_tail(&binfo->list, &buf_list->list);
3616 mutex_unlock(&buf_list->lock);
3617 }
3618 return rc;
3619
3620fail_set_buffers:
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003621 msm_comm_smem_free(inst, &binfo->smem);
3622err_no_mem:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003623 kfree(binfo);
3624fail_kzalloc:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003625 return rc;
3626
3627}
3628
3629static int set_internal_buffers(struct msm_vidc_inst *inst,
3630 enum hal_buffer buffer_type, struct msm_vidc_list *buf_list)
3631{
3632 struct hal_buffer_requirements *internal_buf;
3633
3634 internal_buf = get_buff_req_buffer(inst, buffer_type);
3635 if (!internal_buf) {
3636 dprintk(VIDC_DBG,
3637 "This internal buffer not required, buffer_type: %x\n",
3638 buffer_type);
3639 return 0;
3640 }
3641
3642 dprintk(VIDC_DBG, "Buffer type %s: num = %d, size = %d\n",
3643 get_buffer_name(buffer_type),
3644 internal_buf->buffer_count_actual, internal_buf->buffer_size);
3645
3646 /*
3647 * Try reusing existing internal buffers first.
3648 * If it's not possible to reuse, allocate new buffers.
3649 */
3650 if (reuse_internal_buffers(inst, buffer_type, buf_list))
3651 return 0;
3652
3653 return allocate_and_set_internal_bufs(inst, internal_buf,
3654 buf_list);
3655}
3656
3657int msm_comm_try_state(struct msm_vidc_inst *inst, int state)
3658{
3659 int rc = 0;
3660 int flipped_state;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003661
3662 if (!inst) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07003663 dprintk(VIDC_ERR, "%s: invalid params %pK", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003664 return -EINVAL;
3665 }
3666 dprintk(VIDC_DBG,
3667 "Trying to move inst: %pK from: %#x to %#x\n",
3668 inst, inst->state, state);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003669
3670 mutex_lock(&inst->sync_lock);
3671 if (inst->state == MSM_VIDC_CORE_INVALID) {
3672 dprintk(VIDC_ERR, "%s: inst %pK is in invalid\n",
3673 __func__, inst);
3674 mutex_unlock(&inst->sync_lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003675 return -EINVAL;
3676 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003677
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003678 flipped_state = get_flipped_state(inst->state, state);
3679 dprintk(VIDC_DBG,
3680 "flipped_state = %#x\n", flipped_state);
3681 switch (flipped_state) {
3682 case MSM_VIDC_CORE_UNINIT_DONE:
3683 case MSM_VIDC_CORE_INIT:
3684 rc = msm_comm_init_core(inst);
3685 if (rc || state <= get_flipped_state(inst->state, state))
3686 break;
3687 case MSM_VIDC_CORE_INIT_DONE:
3688 rc = msm_comm_init_core_done(inst);
3689 if (rc || state <= get_flipped_state(inst->state, state))
3690 break;
3691 case MSM_VIDC_OPEN:
3692 rc = msm_comm_session_init(flipped_state, inst);
3693 if (rc || state <= get_flipped_state(inst->state, state))
3694 break;
3695 case MSM_VIDC_OPEN_DONE:
3696 rc = wait_for_state(inst, flipped_state, MSM_VIDC_OPEN_DONE,
3697 HAL_SESSION_INIT_DONE);
3698 if (rc || state <= get_flipped_state(inst->state, state))
3699 break;
3700 case MSM_VIDC_LOAD_RESOURCES:
3701 rc = msm_vidc_load_resources(flipped_state, inst);
3702 if (rc || state <= get_flipped_state(inst->state, state))
3703 break;
3704 case MSM_VIDC_LOAD_RESOURCES_DONE:
3705 case MSM_VIDC_START:
3706 rc = msm_vidc_start(flipped_state, inst);
3707 if (rc || state <= get_flipped_state(inst->state, state))
3708 break;
3709 case MSM_VIDC_START_DONE:
3710 rc = wait_for_state(inst, flipped_state, MSM_VIDC_START_DONE,
3711 HAL_SESSION_START_DONE);
3712 if (rc || state <= get_flipped_state(inst->state, state))
3713 break;
3714 case MSM_VIDC_STOP:
3715 rc = msm_vidc_stop(flipped_state, inst);
3716 if (rc || state <= get_flipped_state(inst->state, state))
3717 break;
3718 case MSM_VIDC_STOP_DONE:
3719 rc = wait_for_state(inst, flipped_state, MSM_VIDC_STOP_DONE,
3720 HAL_SESSION_STOP_DONE);
3721 if (rc || state <= get_flipped_state(inst->state, state))
3722 break;
3723 dprintk(VIDC_DBG, "Moving to Stop Done state\n");
3724 case MSM_VIDC_RELEASE_RESOURCES:
3725 rc = msm_vidc_release_res(flipped_state, inst);
3726 if (rc || state <= get_flipped_state(inst->state, state))
3727 break;
3728 case MSM_VIDC_RELEASE_RESOURCES_DONE:
3729 rc = wait_for_state(inst, flipped_state,
3730 MSM_VIDC_RELEASE_RESOURCES_DONE,
3731 HAL_SESSION_RELEASE_RESOURCE_DONE);
3732 if (rc || state <= get_flipped_state(inst->state, state))
3733 break;
3734 dprintk(VIDC_DBG,
3735 "Moving to release resources done state\n");
3736 case MSM_VIDC_CLOSE:
3737 rc = msm_comm_session_close(flipped_state, inst);
3738 if (rc || state <= get_flipped_state(inst->state, state))
3739 break;
3740 case MSM_VIDC_CLOSE_DONE:
3741 rc = wait_for_state(inst, flipped_state, MSM_VIDC_CLOSE_DONE,
3742 HAL_SESSION_END_DONE);
3743 if (rc || state <= get_flipped_state(inst->state, state))
3744 break;
3745 msm_comm_session_clean(inst);
3746 case MSM_VIDC_CORE_UNINIT:
3747 case MSM_VIDC_CORE_INVALID:
3748 dprintk(VIDC_DBG, "Sending core uninit\n");
3749 rc = msm_vidc_deinit_core(inst);
3750 if (rc || state == get_flipped_state(inst->state, state))
3751 break;
3752 default:
3753 dprintk(VIDC_ERR, "State not recognized\n");
3754 rc = -EINVAL;
3755 break;
3756 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003757 mutex_unlock(&inst->sync_lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003758
3759 if (rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003760 dprintk(VIDC_ERR,
3761 "Failed to move from state: %d to %d\n",
3762 inst->state, state);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003763 msm_comm_kill_session(inst);
3764 } else {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003765 trace_msm_vidc_common_state_change((void *)inst,
3766 inst->state, state);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003767 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003768 return rc;
3769}
3770
Praneeth Paladugu54865842017-08-18 01:45:27 -07003771int msm_vidc_send_pending_eos_buffers(struct msm_vidc_inst *inst)
3772{
3773 struct vidc_frame_data data = {0};
3774 struct hfi_device *hdev;
3775 struct eos_buf *binfo = NULL, *temp = NULL;
3776 int rc = 0;
3777
3778 if (!inst || !inst->core || !inst->core->device) {
3779 dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
3780 return -EINVAL;
3781 }
3782
3783 mutex_lock(&inst->eosbufs.lock);
3784 list_for_each_entry_safe(binfo, temp, &inst->eosbufs.list, list) {
3785 data.alloc_len = binfo->smem.size;
3786 data.device_addr = binfo->smem.device_addr;
3787 data.clnt_data = data.device_addr;
3788 data.buffer_type = HAL_BUFFER_INPUT;
3789 data.filled_len = 0;
3790 data.offset = 0;
3791 data.flags = HAL_BUFFERFLAG_EOS;
3792 data.timestamp = LLONG_MAX;
3793 data.extradata_addr = data.device_addr;
3794 data.extradata_size = 0;
3795 dprintk(VIDC_DBG, "Queueing EOS buffer %pK\n",
3796 (void *)(u64)data.device_addr);
3797 hdev = inst->core->device;
3798
3799 rc = call_hfi_op(hdev, session_etb, inst->session,
3800 &data);
3801 }
3802 mutex_unlock(&inst->eosbufs.lock);
3803
3804 return rc;
3805}
3806
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003807int msm_vidc_comm_cmd(void *instance, union msm_v4l2_cmd *cmd)
3808{
3809 struct msm_vidc_inst *inst = instance;
3810 struct v4l2_decoder_cmd *dec = NULL;
3811 struct v4l2_encoder_cmd *enc = NULL;
3812 struct msm_vidc_core *core;
3813 int which_cmd = 0, flags = 0, rc = 0;
3814
3815 if (!inst || !inst->core || !cmd) {
3816 dprintk(VIDC_ERR, "%s invalid params\n", __func__);
3817 return -EINVAL;
3818 }
3819 core = inst->core;
3820 if (inst->session_type == MSM_VIDC_ENCODER) {
3821 enc = (struct v4l2_encoder_cmd *)cmd;
3822 which_cmd = enc->cmd;
3823 flags = enc->flags;
3824 } else if (inst->session_type == MSM_VIDC_DECODER) {
3825 dec = (struct v4l2_decoder_cmd *)cmd;
3826 which_cmd = dec->cmd;
3827 flags = dec->flags;
3828 }
3829
3830
3831 switch (which_cmd) {
3832 case V4L2_QCOM_CMD_FLUSH:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003833 rc = msm_comm_flush(inst, flags);
3834 if (rc) {
3835 dprintk(VIDC_ERR,
3836 "Failed to flush buffers: %d\n", rc);
3837 }
3838 break;
3839 case V4L2_DEC_QCOM_CMD_RECONFIG_HINT:
3840 {
3841 u32 *ptr = NULL;
3842 struct hal_buffer_requirements *output_buf;
3843
3844 rc = msm_comm_try_get_bufreqs(inst);
3845 if (rc) {
3846 dprintk(VIDC_ERR,
3847 "Getting buffer requirements failed: %d\n",
3848 rc);
3849 break;
3850 }
3851
3852 output_buf = get_buff_req_buffer(inst,
3853 msm_comm_get_hal_output_buffer(inst));
3854 if (output_buf) {
3855 if (dec) {
3856 ptr = (u32 *)dec->raw.data;
3857 ptr[0] = output_buf->buffer_size;
3858 ptr[1] = output_buf->buffer_count_actual;
3859 dprintk(VIDC_DBG,
3860 "Reconfig hint, size is %u, count is %u\n",
3861 ptr[0], ptr[1]);
3862 } else {
3863 dprintk(VIDC_ERR, "Null decoder\n");
3864 }
3865 } else {
3866 dprintk(VIDC_DBG,
3867 "This output buffer not required, buffer_type: %x\n",
3868 HAL_BUFFER_OUTPUT);
3869 }
3870 break;
3871 }
Umesh Pandeybb3fad02017-03-31 16:49:42 -07003872 case V4L2_QCOM_CMD_SESSION_CONTINUE:
3873 {
3874 rc = msm_comm_session_continue(inst);
3875 break;
3876 }
Praneeth Paladugu940228f2017-08-02 13:52:13 -07003877 /* This case also for V4L2_ENC_CMD_STOP */
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003878 case V4L2_DEC_CMD_STOP:
3879 {
Praneeth Paladugu54865842017-08-18 01:45:27 -07003880 struct eos_buf *binfo = NULL;
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003881 u32 smem_flags = 0;
3882
3883 get_inst(inst->core, inst);
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003884
3885 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
3886 if (!binfo) {
3887 dprintk(VIDC_ERR, "%s: Out of memory\n", __func__);
3888 rc = -ENOMEM;
3889 goto exit;
3890 }
3891
3892 if (inst->flags & VIDC_SECURE)
3893 smem_flags |= SMEM_SECURE;
3894
3895 rc = msm_comm_smem_alloc(inst,
3896 SZ_4K, 1, smem_flags,
3897 HAL_BUFFER_INPUT, 0, &binfo->smem);
3898 if (rc) {
3899 dprintk(VIDC_ERR,
3900 "Failed to allocate output memory\n");
Praneeth Paladugu54865842017-08-18 01:45:27 -07003901 rc = -ENOMEM;
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003902 goto exit;
3903 }
3904
3905 mutex_lock(&inst->eosbufs.lock);
3906 list_add_tail(&binfo->list, &inst->eosbufs.list);
3907 mutex_unlock(&inst->eosbufs.lock);
3908
Praneeth Paladugu54865842017-08-18 01:45:27 -07003909 if (inst->state != MSM_VIDC_START_DONE) {
3910 dprintk(VIDC_DBG,
3911 "Inst = %pK is not ready for EOS\n", inst);
3912 goto exit;
3913 }
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003914
Praneeth Paladugu54865842017-08-18 01:45:27 -07003915 rc = msm_vidc_send_pending_eos_buffers(inst);
3916
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003917exit:
3918 put_inst(inst);
3919 break;
3920 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003921 default:
3922 dprintk(VIDC_ERR, "Unknown Command %d\n", which_cmd);
3923 rc = -ENOTSUPP;
3924 break;
3925 }
3926 return rc;
3927}
3928
3929static void populate_frame_data(struct vidc_frame_data *data,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003930 struct msm_vidc_buffer *mbuf, struct msm_vidc_inst *inst)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003931{
Vaibhav Deshu Venkateshe5800332017-03-21 14:27:11 -07003932 u64 time_usec;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003933 int extra_idx;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003934 struct vb2_buffer *vb;
3935 struct vb2_v4l2_buffer *vbuf;
3936
3937 if (!inst || !mbuf || !data) {
3938 dprintk(VIDC_ERR, "%s: invalid params %pK %pK %pK\n",
3939 __func__, inst, mbuf, data);
3940 return;
3941 }
3942
3943 vb = &mbuf->vvb.vb2_buf;
3944 vbuf = to_vb2_v4l2_buffer(vb);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003945
Vaibhav Deshu Venkateshe5800332017-03-21 14:27:11 -07003946 time_usec = vb->timestamp;
3947 do_div(time_usec, NSEC_PER_USEC);
3948
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003949 data->alloc_len = vb->planes[0].length;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003950 data->device_addr = mbuf->smem[0].device_addr;
Vaibhav Deshu Venkateshe5800332017-03-21 14:27:11 -07003951 data->timestamp = time_usec;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003952 data->flags = 0;
3953 data->clnt_data = data->device_addr;
3954
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003955 if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003956 data->buffer_type = HAL_BUFFER_INPUT;
3957 data->filled_len = vb->planes[0].bytesused;
3958 data->offset = vb->planes[0].data_offset;
3959
3960 if (vbuf->flags & V4L2_QCOM_BUF_FLAG_EOS)
3961 data->flags |= HAL_BUFFERFLAG_EOS;
3962
3963 if (vbuf->flags & V4L2_QCOM_BUF_FLAG_CODECCONFIG)
3964 data->flags |= HAL_BUFFERFLAG_CODECCONFIG;
3965
3966 if (vbuf->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY)
3967 data->flags |= HAL_BUFFERFLAG_DECODEONLY;
3968
3969 if (vbuf->flags & V4L2_QCOM_BUF_TIMESTAMP_INVALID)
3970 data->timestamp = LLONG_MAX;
3971
Qiwei Liu551a22222017-08-23 15:28:29 +08003972 if (inst->session_type == MSM_VIDC_DECODER) {
3973 msm_comm_fetch_mark_data(&inst->etb_data, vb->index,
3974 &data->mark_data, &data->mark_target);
3975 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003976
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003977 } else if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003978 data->buffer_type = msm_comm_get_hal_output_buffer(inst);
3979 }
3980
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003981 extra_idx = EXTRADATA_IDX(vb->num_planes);
3982 if (extra_idx && extra_idx < VIDEO_MAX_PLANES) {
3983 data->extradata_addr = mbuf->smem[extra_idx].device_addr;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003984 data->extradata_size = vb->planes[extra_idx].length;
3985 data->flags |= HAL_BUFFERFLAG_EXTRADATA;
3986 }
3987}
3988
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003989static unsigned int count_single_batch(struct msm_vidc_inst *inst,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003990 enum v4l2_buf_type type)
3991{
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003992 int count = 0;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003993 struct msm_vidc_buffer *mbuf = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003994
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003995 mutex_lock(&inst->registeredbufs.lock);
3996 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
3997 if (mbuf->vvb.vb2_buf.type != type)
3998 continue;
3999
4000 /* count only deferred buffers */
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004001 if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED))
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004002 continue;
4003
4004 ++count;
4005
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004006 if (!(mbuf->vvb.flags & V4L2_MSM_BUF_FLAG_DEFER))
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004007 goto found_batch;
4008 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004009 /* don't have a full batch */
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004010 count = 0;
4011
4012found_batch:
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004013 mutex_unlock(&inst->registeredbufs.lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004014 return count;
4015}
4016
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004017static unsigned int count_buffers(struct msm_vidc_inst *inst,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004018 enum v4l2_buf_type type)
4019{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004020 struct msm_vidc_buffer *mbuf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004021 int count = 0;
4022
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004023 mutex_lock(&inst->registeredbufs.lock);
4024 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
4025 if (mbuf->vvb.vb2_buf.type != type)
4026 continue;
4027
4028 /* count only deferred buffers */
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004029 if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED))
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004030 continue;
4031
4032 ++count;
4033 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004034 mutex_unlock(&inst->registeredbufs.lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004035
4036 return count;
4037}
4038
4039static void log_frame(struct msm_vidc_inst *inst, struct vidc_frame_data *data,
4040 enum v4l2_buf_type type)
4041{
Praneeth Paladugub71968b2015-08-19 20:47:57 -07004042
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004043 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
4044 dprintk(VIDC_DBG,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004045 "Sending etb (%x) to hal: filled: %d, ts: %lld, flags = %#x\n",
4046 data->device_addr, data->filled_len,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004047 data->timestamp, data->flags);
4048 msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_ETB);
4049
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004050 } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
4051 dprintk(VIDC_DBG,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004052 "Sending ftb (%x) to hal: size: %d, ts: %lld, flags = %#x\n",
4053 data->device_addr, data->alloc_len,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004054 data->timestamp, data->flags);
4055 msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FTB);
4056 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004057}
4058
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004059enum hal_buffer get_hal_buffer_type(unsigned int type,
4060 unsigned int plane_num)
4061{
4062 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
4063 if (plane_num == 0)
4064 return HAL_BUFFER_INPUT;
4065 else
4066 return HAL_BUFFER_EXTRADATA_INPUT;
4067 } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
4068 if (plane_num == 0)
4069 return HAL_BUFFER_OUTPUT;
4070 else
4071 return HAL_BUFFER_EXTRADATA_OUTPUT;
4072 } else {
4073 return -EINVAL;
4074 }
4075}
4076
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004077static int msm_comm_qbuf_rbr(struct msm_vidc_inst *inst,
4078 struct msm_vidc_buffer *mbuf)
4079{
4080 int rc = 0;
4081 struct hfi_device *hdev;
4082 struct vidc_frame_data frame_data = {0};
4083
4084 if (!inst || !inst->core || !inst->core->device || !mbuf) {
4085 dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
4086 return -EINVAL;
4087 }
4088
4089 hdev = inst->core->device;
4090
4091 if (inst->state == MSM_VIDC_CORE_INVALID) {
4092 dprintk(VIDC_ERR, "%s: inst is in bad state\n", __func__);
4093 return -EINVAL;
4094 }
4095
4096 rc = msm_comm_scale_clocks_and_bus(inst);
4097 populate_frame_data(&frame_data, mbuf, inst);
4098
4099 rc = call_hfi_op(hdev, session_ftb, inst->session, &frame_data);
4100 if (rc) {
4101 dprintk(VIDC_ERR, "Failed to issue ftb: %d\n", rc);
4102 goto err_bad_input;
4103 }
4104
4105 log_frame(inst, &frame_data, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
4106
4107err_bad_input:
4108 return rc;
4109}
4110
4111
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004112/*
4113 * Attempts to queue `vb` to hardware. If, for various reasons, the buffer
4114 * cannot be queued to hardware, the buffer will be staged for commit in the
4115 * pending queue. Once the hardware reaches a good state (or if `vb` is NULL,
4116 * the subsequent *_qbuf will commit the previously staged buffers to hardware.
4117 */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004118int msm_comm_qbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004119{
4120 int rc = 0, capture_count, output_count;
4121 struct msm_vidc_core *core;
4122 struct hfi_device *hdev;
4123 struct {
4124 struct vidc_frame_data *data;
4125 int count;
4126 } etbs, ftbs;
4127 bool defer = false, batch_mode;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004128 struct msm_vidc_buffer *temp = NULL, *next = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004129
4130 if (!inst) {
4131 dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
4132 return -EINVAL;
4133 }
4134
4135 core = inst->core;
4136 hdev = core->device;
4137
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004138 if (inst->state == MSM_VIDC_CORE_INVALID) {
4139 dprintk(VIDC_ERR, "%s: inst is in bad state\n", __func__);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004140 return -EINVAL;
4141 }
4142
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004143 batch_mode = msm_comm_g_ctrl_for_id(inst, V4L2_CID_VIDC_QBUF_MODE)
4144 == V4L2_VIDC_QBUF_BATCHED;
4145 capture_count = (batch_mode ? &count_single_batch : &count_buffers)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004146 (inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004147 output_count = (batch_mode ? &count_single_batch : &count_buffers)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004148 (inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004149
4150 /*
4151 * Somewhat complicated logic to prevent queuing the buffer to hardware.
4152 * Don't queue if:
4153 * 1) Hardware isn't ready (that's simple)
4154 */
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -07004155 defer = defer ? defer : (inst->state != MSM_VIDC_START_DONE);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004156
4157 /*
4158 * 2) The client explicitly tells us not to because it wants this
4159 * buffer to be batched with future frames. The batch size (on both
4160 * capabilities) is completely determined by the client.
4161 */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004162 defer = defer ? defer :
4163 (mbuf && mbuf->vvb.flags & V4L2_MSM_BUF_FLAG_DEFER);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004164
4165 /* 3) If we're in batch mode, we must have full batches of both types */
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -07004166 defer = defer ? defer:(batch_mode && (!output_count || !capture_count));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004167
4168 if (defer) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004169 if (mbuf) {
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004170 mbuf->flags |= MSM_VIDC_FLAG_DEFERRED;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004171 print_vidc_buffer(VIDC_DBG, "deferred qbuf",
4172 inst, mbuf);
4173 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004174 return 0;
4175 }
4176
Praneeth Paladugub71968b2015-08-19 20:47:57 -07004177 rc = msm_comm_scale_clocks_and_bus(inst);
4178
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004179 dprintk(VIDC_DBG, "%sing %d etbs and %d ftbs\n",
4180 batch_mode ? "Batch" : "Process",
4181 output_count, capture_count);
4182
4183 etbs.data = kcalloc(output_count, sizeof(*etbs.data), GFP_KERNEL);
4184 ftbs.data = kcalloc(capture_count, sizeof(*ftbs.data), GFP_KERNEL);
4185 /*
4186 * Note that it's perfectly normal for (e|f)tbs.data to be NULL if
4187 * we're not in batch mode (i.e. (output|capture)_count == 0)
4188 */
4189 if ((!etbs.data && output_count) ||
4190 (!ftbs.data && capture_count)) {
4191 dprintk(VIDC_ERR, "Failed to alloc memory for batching\n");
4192 kfree(etbs.data);
4193 etbs.data = NULL;
4194
4195 kfree(ftbs.data);
4196 ftbs.data = NULL;
4197 goto err_no_mem;
4198 }
4199
4200 etbs.count = ftbs.count = 0;
4201
4202 /*
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004203 * Try to collect all deferred buffers into 2 batches of ftb and etb
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004204 * Note that these "batches" might be empty if we're no in batching mode
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004205 * and the deferred is not set for buffers.
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004206 */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004207 mutex_lock(&inst->registeredbufs.lock);
4208 list_for_each_entry_safe(temp, next, &inst->registeredbufs.list, list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004209 struct vidc_frame_data *frame_data = NULL;
4210
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004211 if (!(temp->flags & MSM_VIDC_FLAG_DEFERRED))
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004212 continue;
4213
4214 switch (temp->vvb.vb2_buf.type) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004215 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
4216 if (ftbs.count < capture_count && ftbs.data)
4217 frame_data = &ftbs.data[ftbs.count++];
4218 break;
4219 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
4220 if (etbs.count < output_count && etbs.data)
4221 frame_data = &etbs.data[etbs.count++];
4222 break;
4223 default:
4224 break;
4225 }
4226
4227 if (!frame_data)
4228 continue;
4229
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004230 populate_frame_data(frame_data, temp, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004231
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004232 /* this buffer going to be queued (not deferred) */
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004233 temp->flags &= ~MSM_VIDC_FLAG_DEFERRED;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004234
4235 print_vidc_buffer(VIDC_DBG, "qbuf", inst, temp);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004236 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004237 mutex_unlock(&inst->registeredbufs.lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004238
4239 /* Finally commit all our frame(s) to H/W */
4240 if (batch_mode) {
4241 int ftb_index = 0, c = 0;
4242
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004243 ftb_index = c;
4244 rc = call_hfi_op(hdev, session_process_batch, inst->session,
4245 etbs.count, etbs.data,
4246 ftbs.count - ftb_index, &ftbs.data[ftb_index]);
4247 if (rc) {
4248 dprintk(VIDC_ERR,
4249 "Failed to queue batch of %d ETBs and %d FTBs\n",
4250 etbs.count, ftbs.count);
4251 goto err_bad_input;
4252 }
4253
4254 for (c = ftb_index; c < ftbs.count; ++c) {
4255 log_frame(inst, &ftbs.data[c],
4256 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
4257 }
4258
4259 for (c = 0; c < etbs.count; ++c) {
4260 log_frame(inst, &etbs.data[c],
4261 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
4262 }
4263 }
4264
4265 if (!batch_mode && etbs.count) {
4266 int c = 0;
4267
4268 for (c = 0; c < etbs.count; ++c) {
4269 struct vidc_frame_data *frame_data = &etbs.data[c];
4270
4271 rc = call_hfi_op(hdev, session_etb, inst->session,
4272 frame_data);
4273 if (rc) {
4274 dprintk(VIDC_ERR, "Failed to issue etb: %d\n",
4275 rc);
4276 goto err_bad_input;
4277 }
4278
4279 log_frame(inst, frame_data,
4280 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
4281 }
4282 }
4283
4284 if (!batch_mode && ftbs.count) {
4285 int c = 0;
4286
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004287 for (; c < ftbs.count; ++c) {
4288 struct vidc_frame_data *frame_data = &ftbs.data[c];
4289
4290 rc = call_hfi_op(hdev, session_ftb,
4291 inst->session, frame_data);
4292 if (rc) {
4293 dprintk(VIDC_ERR, "Failed to issue ftb: %d\n",
4294 rc);
4295 goto err_bad_input;
4296 }
4297
4298 log_frame(inst, frame_data,
4299 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
4300 }
4301 }
4302
4303err_bad_input:
4304 if (rc)
4305 dprintk(VIDC_ERR, "Failed to queue buffer\n");
4306
4307 kfree(etbs.data);
4308 kfree(ftbs.data);
4309err_no_mem:
4310 return rc;
4311}
4312
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07004313int msm_vidc_update_host_buff_counts(struct msm_vidc_inst *inst)
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004314{
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004315 int extra_buffers;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004316 struct hal_buffer_requirements *bufreq;
4317
4318 bufreq = get_buff_req_buffer(inst,
4319 HAL_BUFFER_INPUT);
4320 if (!bufreq) {
4321 dprintk(VIDC_ERR,
4322 "Failed : No buffer requirements : %x\n",
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004323 HAL_BUFFER_INPUT);
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004324 return -EINVAL;
4325 }
4326 extra_buffers = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_INPUT);
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004327 bufreq->buffer_count_min_host = bufreq->buffer_count_min +
4328 extra_buffers;
Maheshwar Ajja83fec052017-07-25 11:18:38 -07004329 bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT);
4330 if (bufreq) {
4331 if (bufreq->buffer_count_min)
4332 bufreq->buffer_count_min_host =
4333 bufreq->buffer_count_min + extra_buffers;
4334 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004335
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004336 if (msm_comm_get_stream_output_mode(inst) ==
4337 HAL_VIDEO_DECODER_SECONDARY) {
4338
4339 bufreq = get_buff_req_buffer(inst,
4340 HAL_BUFFER_OUTPUT);
4341 if (!bufreq) {
4342 dprintk(VIDC_ERR,
4343 "Failed : No buffer requirements : %x\n",
4344 HAL_BUFFER_OUTPUT);
4345 return -EINVAL;
4346 }
4347
4348 /* For DPB buffers, no need to add Extra buffers */
Praneeth Paladugu6e637472017-05-16 16:06:46 -07004349 bufreq->buffer_count_min_host = bufreq->buffer_count_actual =
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004350 bufreq->buffer_count_min;
4351
4352 bufreq = get_buff_req_buffer(inst,
4353 HAL_BUFFER_OUTPUT2);
4354 if (!bufreq) {
4355 dprintk(VIDC_ERR,
4356 "Failed : No buffer requirements : %x\n",
4357 HAL_BUFFER_OUTPUT2);
4358 return -EINVAL;
4359 }
4360
4361 extra_buffers = msm_vidc_get_extra_buff_count(inst,
4362 HAL_BUFFER_OUTPUT);
4363
Praneeth Paladugu6e637472017-05-16 16:06:46 -07004364 bufreq->buffer_count_min_host = bufreq->buffer_count_actual =
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004365 bufreq->buffer_count_min + extra_buffers;
Chinmay Sawarkaraa84fae2017-06-27 12:39:51 -07004366
4367 bufreq = get_buff_req_buffer(inst,
4368 HAL_BUFFER_EXTRADATA_OUTPUT2);
4369 if (!bufreq) {
4370 dprintk(VIDC_DBG,
4371 "No buffer requirements : %x\n",
4372 HAL_BUFFER_EXTRADATA_OUTPUT2);
4373 } else {
4374 if (bufreq->buffer_count_min) {
4375 bufreq->buffer_count_min_host =
4376 bufreq->buffer_count_actual =
4377 bufreq->buffer_count_min + extra_buffers;
4378 }
4379 }
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004380 } else {
4381
4382 bufreq = get_buff_req_buffer(inst,
4383 HAL_BUFFER_OUTPUT);
4384 if (!bufreq) {
4385 dprintk(VIDC_ERR,
4386 "Failed : No buffer requirements : %x\n",
4387 HAL_BUFFER_OUTPUT);
4388 return -EINVAL;
4389 }
4390
4391 extra_buffers = msm_vidc_get_extra_buff_count(inst,
4392 HAL_BUFFER_OUTPUT);
4393
Praneeth Paladugu6e637472017-05-16 16:06:46 -07004394 bufreq->buffer_count_min_host = bufreq->buffer_count_actual =
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004395 bufreq->buffer_count_min + extra_buffers;
Chinmay Sawarkaraa84fae2017-06-27 12:39:51 -07004396
4397 bufreq = get_buff_req_buffer(inst,
4398 HAL_BUFFER_EXTRADATA_OUTPUT);
4399 if (!bufreq) {
4400 dprintk(VIDC_DBG,
4401 "No buffer requirements : %x\n",
4402 HAL_BUFFER_EXTRADATA_OUTPUT);
4403 } else {
4404 if (bufreq->buffer_count_min) {
4405 bufreq->buffer_count_min_host =
4406 bufreq->buffer_count_actual =
4407 bufreq->buffer_count_min + extra_buffers;
4408 }
4409 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004410 }
4411
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004412 return 0;
4413}
4414
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004415int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst)
4416{
4417 int rc = 0, i = 0;
4418 union hal_get_property hprop;
4419
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004420 memset(&hprop, 0x0, sizeof(hprop));
4421
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004422 rc = msm_comm_try_get_prop(inst, HAL_PARAM_GET_BUFFER_REQUIREMENTS,
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004423 &hprop);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004424 if (rc) {
4425 dprintk(VIDC_ERR, "Failed getting buffer requirements: %d", rc);
4426 return rc;
4427 }
4428
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004429 dprintk(VIDC_DBG, "Buffer requirements from HW:\n");
4430 dprintk(VIDC_DBG, "%15s %8s %8s %8s %8s\n",
4431 "buffer type", "count", "mincount_host", "mincount_fw", "size");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004432 for (i = 0; i < HAL_BUFFER_MAX; i++) {
4433 struct hal_buffer_requirements req = hprop.buf_req.buffer[i];
4434
4435 inst->buff_req.buffer[i] = req;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004436 if (req.buffer_type != HAL_BUFFER_NONE) {
4437 dprintk(VIDC_DBG, "%15s %8d %8d %8d %8d\n",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004438 get_buffer_name(req.buffer_type),
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004439 req.buffer_count_actual,
4440 req.buffer_count_min_host,
4441 req.buffer_count_min, req.buffer_size);
4442 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004443 }
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07004444 if (inst->session_type == MSM_VIDC_ENCODER)
4445 rc = msm_vidc_update_host_buff_counts(inst);
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004446
4447 dprintk(VIDC_DBG, "Buffer requirements host adjusted:\n");
4448 dprintk(VIDC_DBG, "%15s %8s %8s %8s %8s\n",
4449 "buffer type", "count", "mincount_host", "mincount_fw", "size");
4450 for (i = 0; i < HAL_BUFFER_MAX; i++) {
Praneeth Paladugu13c90962017-04-24 13:15:28 -07004451 struct hal_buffer_requirements req = inst->buff_req.buffer[i];
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004452
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004453 if (req.buffer_type != HAL_BUFFER_NONE) {
4454 dprintk(VIDC_DBG, "%15s %8d %8d %8d %8d\n",
4455 get_buffer_name(req.buffer_type),
4456 req.buffer_count_actual,
4457 req.buffer_count_min_host,
4458 req.buffer_count_min, req.buffer_size);
4459 }
4460 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004461 return rc;
4462}
4463
4464int msm_comm_try_get_prop(struct msm_vidc_inst *inst, enum hal_property ptype,
4465 union hal_get_property *hprop)
4466{
4467 int rc = 0;
4468 struct hfi_device *hdev;
4469 struct getprop_buf *buf;
4470
4471 if (!inst || !inst->core || !inst->core->device) {
4472 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4473 return -EINVAL;
4474 }
4475
4476 hdev = inst->core->device;
4477 mutex_lock(&inst->sync_lock);
4478 if (inst->state < MSM_VIDC_OPEN_DONE ||
4479 inst->state >= MSM_VIDC_CLOSE) {
4480
4481 /* No need to check inst->state == MSM_VIDC_INVALID since
4482 * INVALID is > CLOSE_DONE. When core went to INVALID state,
4483 * we put all the active instances in INVALID. So > CLOSE_DONE
4484 * is enough check to have.
4485 */
4486
4487 dprintk(VIDC_ERR,
4488 "In Wrong state to call Buf Req: Inst %pK or Core %pK\n",
4489 inst, inst->core);
4490 rc = -EAGAIN;
4491 mutex_unlock(&inst->sync_lock);
4492 goto exit;
4493 }
4494 mutex_unlock(&inst->sync_lock);
4495
4496 switch (ptype) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004497 case HAL_PARAM_GET_BUFFER_REQUIREMENTS:
4498 rc = call_hfi_op(hdev, session_get_buf_req, inst->session);
4499 break;
4500 default:
4501 rc = -EAGAIN;
4502 break;
4503 }
4504
4505 if (rc) {
4506 dprintk(VIDC_ERR, "Can't query hardware for property: %d\n",
4507 rc);
4508 goto exit;
4509 }
4510
4511 rc = wait_for_completion_timeout(&inst->completions[
4512 SESSION_MSG_INDEX(HAL_SESSION_PROPERTY_INFO)],
Praneeth Paladugud5bf7bc2017-05-29 23:41:04 -07004513 msecs_to_jiffies(
4514 inst->core->resources.msm_vidc_hw_rsp_timeout));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004515 if (!rc) {
4516 dprintk(VIDC_ERR,
4517 "%s: Wait interrupted or timed out [%pK]: %d\n",
4518 __func__, inst,
4519 SESSION_MSG_INDEX(HAL_SESSION_PROPERTY_INFO));
Surajit Podder878ede02017-02-07 12:20:10 +05304520 msm_comm_kill_session(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004521 rc = -ETIMEDOUT;
4522 goto exit;
4523 } else {
4524 /* wait_for_completion_timeout returns jiffies before expiry */
4525 rc = 0;
4526 }
4527
4528 mutex_lock(&inst->pending_getpropq.lock);
4529 if (!list_empty(&inst->pending_getpropq.list)) {
4530 buf = list_first_entry(&inst->pending_getpropq.list,
4531 struct getprop_buf, list);
4532 *hprop = *(union hal_get_property *)buf->data;
4533 kfree(buf->data);
4534 list_del(&buf->list);
4535 kfree(buf);
4536 } else {
4537 dprintk(VIDC_ERR, "%s getprop list empty\n", __func__);
4538 rc = -EINVAL;
4539 }
4540 mutex_unlock(&inst->pending_getpropq.lock);
4541exit:
4542 return rc;
4543}
4544
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004545int msm_comm_release_output_buffers(struct msm_vidc_inst *inst,
4546 bool force_release)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004547{
4548 struct msm_smem *handle;
4549 struct internal_buf *buf, *dummy;
4550 struct vidc_buffer_addr_info buffer_info;
4551 int rc = 0;
4552 struct msm_vidc_core *core;
4553 struct hfi_device *hdev;
4554
4555 if (!inst) {
4556 dprintk(VIDC_ERR,
4557 "Invalid instance pointer = %pK\n", inst);
4558 return -EINVAL;
4559 }
4560 mutex_lock(&inst->outputbufs.lock);
4561 if (list_empty(&inst->outputbufs.list)) {
4562 dprintk(VIDC_DBG, "%s - No OUTPUT buffers allocated\n",
4563 __func__);
4564 mutex_unlock(&inst->outputbufs.lock);
4565 return 0;
4566 }
4567 mutex_unlock(&inst->outputbufs.lock);
4568
4569 core = inst->core;
4570 if (!core) {
4571 dprintk(VIDC_ERR,
4572 "Invalid core pointer = %pK\n", core);
4573 return -EINVAL;
4574 }
4575 hdev = core->device;
4576 if (!hdev) {
4577 dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev);
4578 return -EINVAL;
4579 }
4580 mutex_lock(&inst->outputbufs.lock);
4581 list_for_each_entry_safe(buf, dummy, &inst->outputbufs.list, list) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004582 handle = &buf->smem;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004583
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004584 if ((buf->buffer_ownership == FIRMWARE) && !force_release) {
4585 dprintk(VIDC_INFO, "DPB is with f/w. Can't free it\n");
4586 continue;
4587 }
4588
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004589 buffer_info.buffer_size = handle->size;
4590 buffer_info.buffer_type = buf->buffer_type;
4591 buffer_info.num_buffers = 1;
4592 buffer_info.align_device_addr = handle->device_addr;
4593 if (inst->buffer_mode_set[CAPTURE_PORT] ==
Maheshwar Ajja99422322017-07-07 17:31:15 -07004594 HAL_BUFFER_MODE_STATIC) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004595 buffer_info.response_required = false;
4596 rc = call_hfi_op(hdev, session_release_buffers,
4597 (void *)inst->session, &buffer_info);
4598 if (rc) {
4599 dprintk(VIDC_WARN,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004600 "Rel output buf fail:%x, %d\n",
4601 buffer_info.align_device_addr,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004602 buffer_info.buffer_size);
4603 }
4604 }
4605
4606 list_del(&buf->list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004607 msm_comm_smem_free(inst, &buf->smem);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004608 kfree(buf);
4609 }
4610
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004611 mutex_unlock(&inst->outputbufs.lock);
4612 return rc;
4613}
4614
4615static enum hal_buffer scratch_buf_sufficient(struct msm_vidc_inst *inst,
4616 enum hal_buffer buffer_type)
4617{
4618 struct hal_buffer_requirements *bufreq = NULL;
4619 struct internal_buf *buf;
4620 int count = 0;
4621
4622 if (!inst) {
4623 dprintk(VIDC_ERR, "%s - invalid param\n", __func__);
4624 goto not_sufficient;
4625 }
4626
4627 bufreq = get_buff_req_buffer(inst, buffer_type);
4628 if (!bufreq)
4629 goto not_sufficient;
4630
4631 /* Check if current scratch buffers are sufficient */
4632 mutex_lock(&inst->scratchbufs.lock);
4633
4634 list_for_each_entry(buf, &inst->scratchbufs.list, list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004635 if (buf->buffer_type == buffer_type &&
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004636 buf->smem.size >= bufreq->buffer_size)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004637 count++;
4638 }
4639 mutex_unlock(&inst->scratchbufs.lock);
4640
4641 if (count != bufreq->buffer_count_actual)
4642 goto not_sufficient;
4643
4644 dprintk(VIDC_DBG,
4645 "Existing scratch buffer is sufficient for buffer type %#x\n",
4646 buffer_type);
4647
4648 return buffer_type;
4649
4650not_sufficient:
4651 return HAL_BUFFER_NONE;
4652}
4653
4654int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst,
4655 bool check_for_reuse)
4656{
4657 struct msm_smem *handle;
4658 struct internal_buf *buf, *dummy;
4659 struct vidc_buffer_addr_info buffer_info;
4660 int rc = 0;
4661 struct msm_vidc_core *core;
4662 struct hfi_device *hdev;
4663 enum hal_buffer sufficiency = HAL_BUFFER_NONE;
4664
4665 if (!inst) {
4666 dprintk(VIDC_ERR,
4667 "Invalid instance pointer = %pK\n", inst);
4668 return -EINVAL;
4669 }
4670 core = inst->core;
4671 if (!core) {
4672 dprintk(VIDC_ERR,
4673 "Invalid core pointer = %pK\n", core);
4674 return -EINVAL;
4675 }
4676 hdev = core->device;
4677 if (!hdev) {
4678 dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev);
4679 return -EINVAL;
4680 }
4681
4682 if (check_for_reuse) {
4683 sufficiency |= scratch_buf_sufficient(inst,
4684 HAL_BUFFER_INTERNAL_SCRATCH);
4685
4686 sufficiency |= scratch_buf_sufficient(inst,
4687 HAL_BUFFER_INTERNAL_SCRATCH_1);
4688
4689 sufficiency |= scratch_buf_sufficient(inst,
4690 HAL_BUFFER_INTERNAL_SCRATCH_2);
4691 }
4692
4693 mutex_lock(&inst->scratchbufs.lock);
4694 list_for_each_entry_safe(buf, dummy, &inst->scratchbufs.list, list) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004695 handle = &buf->smem;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004696 buffer_info.buffer_size = handle->size;
4697 buffer_info.buffer_type = buf->buffer_type;
4698 buffer_info.num_buffers = 1;
4699 buffer_info.align_device_addr = handle->device_addr;
Maheshwar Ajja99422322017-07-07 17:31:15 -07004700 buffer_info.response_required = true;
4701 rc = call_hfi_op(hdev, session_release_buffers,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004702 (void *)inst->session, &buffer_info);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004703 if (!rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004704 mutex_unlock(&inst->scratchbufs.lock);
4705 rc = wait_for_sess_signal_receipt(inst,
4706 HAL_SESSION_RELEASE_BUFFER_DONE);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004707 if (rc)
4708 dprintk(VIDC_WARN,
4709 "%s: wait for signal failed, rc %d\n",
4710 __func__, rc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004711 mutex_lock(&inst->scratchbufs.lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004712 } else {
4713 dprintk(VIDC_WARN,
4714 "Rel scrtch buf fail:%x, %d\n",
4715 buffer_info.align_device_addr,
4716 buffer_info.buffer_size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004717 }
4718
4719 /*If scratch buffers can be reused, do not free the buffers*/
4720 if (sufficiency & buf->buffer_type)
4721 continue;
4722
4723 list_del(&buf->list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004724 msm_comm_smem_free(inst, handle);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004725 kfree(buf);
4726 }
4727
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004728 mutex_unlock(&inst->scratchbufs.lock);
4729 return rc;
4730}
4731
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07004732void msm_comm_release_eos_buffers(struct msm_vidc_inst *inst)
4733{
4734 struct eos_buf *buf, *next;
4735
4736 if (!inst) {
4737 dprintk(VIDC_ERR,
4738 "Invalid instance pointer = %pK\n", inst);
4739 return;
4740 }
4741
4742 mutex_lock(&inst->eosbufs.lock);
4743 list_for_each_entry_safe(buf, next, &inst->eosbufs.list, list) {
4744 list_del(&buf->list);
4745 kfree(buf);
4746 }
4747 INIT_LIST_HEAD(&inst->eosbufs.list);
4748 mutex_unlock(&inst->eosbufs.lock);
4749}
4750
4751
Praneeth Paladugu319e7922017-03-16 11:09:06 -07004752int msm_comm_release_recon_buffers(struct msm_vidc_inst *inst)
4753{
4754 struct recon_buf *buf, *next;
4755
4756 if (!inst) {
4757 dprintk(VIDC_ERR,
4758 "Invalid instance pointer = %pK\n", inst);
4759 return -EINVAL;
4760 }
4761
4762 mutex_lock(&inst->reconbufs.lock);
4763 list_for_each_entry_safe(buf, next, &inst->reconbufs.list, list) {
4764 list_del(&buf->list);
4765 kfree(buf);
4766 }
4767 INIT_LIST_HEAD(&inst->reconbufs.list);
4768 mutex_unlock(&inst->reconbufs.lock);
4769
4770 return 0;
4771}
4772
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004773int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst)
4774{
4775 struct msm_smem *handle;
4776 struct list_head *ptr, *next;
4777 struct internal_buf *buf;
4778 struct vidc_buffer_addr_info buffer_info;
4779 int rc = 0;
4780 struct msm_vidc_core *core;
4781 struct hfi_device *hdev;
4782
4783 if (!inst) {
4784 dprintk(VIDC_ERR,
4785 "Invalid instance pointer = %pK\n", inst);
4786 return -EINVAL;
4787 }
4788 core = inst->core;
4789 if (!core) {
4790 dprintk(VIDC_ERR,
4791 "Invalid core pointer = %pK\n", core);
4792 return -EINVAL;
4793 }
4794 hdev = core->device;
4795 if (!hdev) {
4796 dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev);
4797 return -EINVAL;
4798 }
4799
4800 mutex_lock(&inst->persistbufs.lock);
4801 list_for_each_safe(ptr, next, &inst->persistbufs.list) {
4802 buf = list_entry(ptr, struct internal_buf, list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004803 handle = &buf->smem;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004804 buffer_info.buffer_size = handle->size;
4805 buffer_info.buffer_type = buf->buffer_type;
4806 buffer_info.num_buffers = 1;
4807 buffer_info.align_device_addr = handle->device_addr;
Maheshwar Ajja99422322017-07-07 17:31:15 -07004808 buffer_info.response_required = true;
4809 rc = call_hfi_op(hdev, session_release_buffers,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004810 (void *)inst->session, &buffer_info);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004811 if (!rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004812 mutex_unlock(&inst->persistbufs.lock);
4813 rc = wait_for_sess_signal_receipt(inst,
4814 HAL_SESSION_RELEASE_BUFFER_DONE);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004815 if (rc)
4816 dprintk(VIDC_WARN,
4817 "%s: wait for signal failed, rc %d\n",
4818 __func__, rc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004819 mutex_lock(&inst->persistbufs.lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004820 } else {
4821 dprintk(VIDC_WARN,
4822 "Rel prst buf fail:%x, %d\n",
4823 buffer_info.align_device_addr,
4824 buffer_info.buffer_size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004825 }
4826 list_del(&buf->list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004827 msm_comm_smem_free(inst, handle);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004828 kfree(buf);
4829 }
4830 mutex_unlock(&inst->persistbufs.lock);
4831 return rc;
4832}
4833
4834int msm_comm_try_set_prop(struct msm_vidc_inst *inst,
4835 enum hal_property ptype, void *pdata)
4836{
4837 int rc = 0;
4838 struct hfi_device *hdev;
4839
4840 if (!inst) {
4841 dprintk(VIDC_ERR, "Invalid input: %pK\n", inst);
4842 return -EINVAL;
4843 }
4844
4845 if (!inst->core || !inst->core->device) {
4846 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4847 return -EINVAL;
4848 }
4849 hdev = inst->core->device;
4850
4851 mutex_lock(&inst->sync_lock);
4852 if (inst->state < MSM_VIDC_OPEN_DONE || inst->state >= MSM_VIDC_CLOSE) {
4853 dprintk(VIDC_ERR, "Not in proper state to set property\n");
4854 rc = -EAGAIN;
4855 goto exit;
4856 }
4857 rc = call_hfi_op(hdev, session_set_property, (void *)inst->session,
4858 ptype, pdata);
4859 if (rc)
4860 dprintk(VIDC_ERR, "Failed to set hal property for framesize\n");
4861exit:
4862 mutex_unlock(&inst->sync_lock);
4863 return rc;
4864}
4865
4866int msm_comm_set_output_buffers(struct msm_vidc_inst *inst)
4867{
4868 int rc = 0;
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004869 bool force_release = true;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004870
4871 if (!inst || !inst->core || !inst->core->device) {
4872 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4873 return -EINVAL;
4874 }
4875
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004876 if (inst->fmts[OUTPUT_PORT].defer_outputs)
4877 force_release = false;
4878
4879 if (msm_comm_release_output_buffers(inst, force_release))
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004880 dprintk(VIDC_WARN, "Failed to release output buffers\n");
4881
4882 rc = set_output_buffers(inst, HAL_BUFFER_OUTPUT);
4883 if (rc)
4884 goto error;
4885 return rc;
4886error:
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004887 msm_comm_release_output_buffers(inst, true);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004888 return rc;
4889}
4890
4891int msm_comm_set_scratch_buffers(struct msm_vidc_inst *inst)
4892{
4893 int rc = 0;
4894
4895 if (!inst || !inst->core || !inst->core->device) {
4896 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4897 return -EINVAL;
4898 }
4899
4900 if (msm_comm_release_scratch_buffers(inst, true))
4901 dprintk(VIDC_WARN, "Failed to release scratch buffers\n");
4902
4903 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_SCRATCH,
4904 &inst->scratchbufs);
4905 if (rc)
4906 goto error;
4907
4908 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_SCRATCH_1,
4909 &inst->scratchbufs);
4910 if (rc)
4911 goto error;
4912
4913 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_SCRATCH_2,
4914 &inst->scratchbufs);
4915 if (rc)
4916 goto error;
4917
4918 return rc;
4919error:
4920 msm_comm_release_scratch_buffers(inst, false);
4921 return rc;
4922}
4923
Praneeth Paladugu319e7922017-03-16 11:09:06 -07004924int msm_comm_set_recon_buffers(struct msm_vidc_inst *inst)
4925{
4926 int rc = 0, i = 0;
4927 struct hal_buffer_requirements *internal_buf;
4928 struct recon_buf *binfo;
4929 struct msm_vidc_list *buf_list = &inst->reconbufs;
4930
4931 if (!inst) {
4932 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4933 return -EINVAL;
4934 }
4935
4936 if (inst->session_type == MSM_VIDC_ENCODER)
4937 internal_buf = get_buff_req_buffer(inst,
4938 HAL_BUFFER_INTERNAL_RECON);
4939 else if (inst->session_type == MSM_VIDC_DECODER)
4940 internal_buf = get_buff_req_buffer(inst,
4941 msm_comm_get_hal_output_buffer(inst));
4942 else
4943 return -EINVAL;
4944
4945 if (!internal_buf || !internal_buf->buffer_count_actual) {
4946 dprintk(VIDC_DBG, "Inst : %pK Recon buffers not required\n",
4947 inst);
4948 return 0;
4949 }
4950
Praneeth Paladugu7722b4e2017-07-07 11:01:56 -07004951 msm_comm_release_recon_buffers(inst);
Praneeth Paladugu319e7922017-03-16 11:09:06 -07004952
4953 for (i = 0; i < internal_buf->buffer_count_actual; i++) {
4954 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
4955 if (!binfo) {
4956 dprintk(VIDC_ERR, "Out of memory\n");
4957 rc = -ENOMEM;
4958 goto fail_kzalloc;
4959 }
4960
4961 binfo->buffer_index = i;
4962 mutex_lock(&buf_list->lock);
4963 list_add_tail(&binfo->list, &buf_list->list);
4964 mutex_unlock(&buf_list->lock);
4965 }
4966
4967fail_kzalloc:
4968 return rc;
4969}
4970
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004971int msm_comm_set_persist_buffers(struct msm_vidc_inst *inst)
4972{
4973 int rc = 0;
4974
4975 if (!inst || !inst->core || !inst->core->device) {
4976 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4977 return -EINVAL;
4978 }
4979
4980 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_PERSIST,
4981 &inst->persistbufs);
4982 if (rc)
4983 goto error;
4984
4985 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_PERSIST_1,
4986 &inst->persistbufs);
4987 if (rc)
4988 goto error;
4989 return rc;
4990error:
4991 msm_comm_release_persist_buffers(inst);
4992 return rc;
4993}
4994
4995static void msm_comm_flush_in_invalid_state(struct msm_vidc_inst *inst)
4996{
4997 struct list_head *ptr, *next;
4998 enum vidc_ports ports[] = {OUTPUT_PORT, CAPTURE_PORT};
4999 int c = 0;
5000
5001 for (c = 0; c < ARRAY_SIZE(ports); ++c) {
5002 enum vidc_ports port = ports[c];
5003
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005004 mutex_lock(&inst->bufq[port].lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005005 list_for_each_safe(ptr, next,
5006 &inst->bufq[port].vb2_bufq.queued_list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005007 struct vb2_buffer *vb = container_of(ptr,
5008 struct vb2_buffer, queued_entry);
Vikash Garodia8d985f32017-08-09 19:52:51 +05305009 if (vb->state == VB2_BUF_STATE_ACTIVE) {
5010 vb->planes[0].bytesused = 0;
5011 print_vb2_buffer(VIDC_ERR, "flush in invalid",
5012 inst, vb);
5013 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
5014 } else {
5015 dprintk(VIDC_WARN,
5016 "%s VB is in state %d not in ACTIVE state\n"
5017 , __func__, vb->state);
5018 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005019 }
5020 mutex_unlock(&inst->bufq[port].lock);
5021 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005022 msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_FLUSH_DONE);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005023 return;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005024}
5025
5026int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
5027{
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07005028 int i, rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005029 bool ip_flush = false;
5030 bool op_flush = false;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005031 struct msm_vidc_buffer *mbuf, *next;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005032 struct msm_vidc_core *core;
5033 struct hfi_device *hdev;
5034
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005035 if (!inst || !inst->core || !inst->core->device) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005036 dprintk(VIDC_ERR,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005037 "Invalid params, inst %pK\n", inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005038 return -EINVAL;
5039 }
5040 core = inst->core;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005041 hdev = core->device;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005042
5043 ip_flush = flags & V4L2_QCOM_CMD_FLUSH_OUTPUT;
5044 op_flush = flags & V4L2_QCOM_CMD_FLUSH_CAPTURE;
5045
5046 if (ip_flush && !op_flush) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005047 dprintk(VIDC_WARN,
5048 "Input only flush not supported, making it flush all\n");
5049 op_flush = true;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005050 return 0;
5051 }
5052
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07005053 msm_clock_data_reset(inst);
Praneeth Paladugu75cf18e2016-12-08 16:12:11 -08005054
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005055 if (inst->state == MSM_VIDC_CORE_INVALID) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005056 dprintk(VIDC_ERR,
5057 "Core %pK and inst %pK are in bad state\n",
5058 core, inst);
5059 msm_comm_flush_in_invalid_state(inst);
5060 return 0;
5061 }
5062
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005063 mutex_lock(&inst->registeredbufs.lock);
5064 list_for_each_entry_safe(mbuf, next, &inst->registeredbufs.list, list) {
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07005065 /* don't flush input buffers if input flush is not requested */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005066 if (!ip_flush && mbuf->vvb.vb2_buf.type ==
5067 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
5068 continue;
5069
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07005070 /* flush only deferred or rbr pending buffers */
5071 if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED ||
5072 mbuf->flags & MSM_VIDC_FLAG_RBR_PENDING))
5073 continue;
5074
5075 /*
5076 * flush buffers which are queued by client already,
5077 * the refcount will be two or more for those buffers.
5078 */
5079 if (!(mbuf->smem[0].refcount >= 2))
5080 continue;
5081
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005082 print_vidc_buffer(VIDC_DBG, "flush buf", inst, mbuf);
5083 msm_comm_flush_vidc_buffer(inst, mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005084
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07005085 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
5086 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
5087 print_vidc_buffer(VIDC_ERR,
5088 "dqbuf: unmap failed.", inst, mbuf);
5089 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
5090 print_vidc_buffer(VIDC_ERR,
5091 "dqbuf: unmap failed..", inst, mbuf);
5092 }
5093 if (!mbuf->smem[0].refcount) {
5094 list_del(&mbuf->list);
5095 kref_put_mbuf(mbuf);
5096 } else {
5097 /* buffer is no more a deferred buffer */
5098 mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
5099 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005100 }
5101 mutex_unlock(&inst->registeredbufs.lock);
5102
5103 /* enable in flush */
5104 inst->in_flush = true;
5105
5106 hdev = inst->core->device;
5107 if (ip_flush) {
5108 dprintk(VIDC_DBG, "Send flush on all ports to firmware\n");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005109 rc = call_hfi_op(hdev, session_flush, inst->session,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005110 HAL_FLUSH_ALL);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005111 } else {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005112 dprintk(VIDC_DBG, "Send flush on output port to firmware\n");
5113 rc = call_hfi_op(hdev, session_flush, inst->session,
5114 HAL_FLUSH_OUTPUT);
5115 }
5116 if (rc) {
5117 dprintk(VIDC_ERR,
5118 "Sending flush to firmware failed, flush out all buffers\n");
5119 msm_comm_flush_in_invalid_state(inst);
5120 /* disable in_flush */
5121 inst->in_flush = false;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005122 }
5123
5124 return rc;
5125}
5126
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005127enum hal_extradata_id msm_comm_get_hal_extradata_index(
5128 enum v4l2_mpeg_vidc_extradata index)
5129{
5130 int ret = 0;
5131
5132 switch (index) {
5133 case V4L2_MPEG_VIDC_EXTRADATA_NONE:
5134 ret = HAL_EXTRADATA_NONE;
5135 break;
5136 case V4L2_MPEG_VIDC_EXTRADATA_MB_QUANTIZATION:
5137 ret = HAL_EXTRADATA_MB_QUANTIZATION;
5138 break;
5139 case V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO:
5140 ret = HAL_EXTRADATA_INTERLACE_VIDEO;
5141 break;
5142 case V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP:
5143 ret = HAL_EXTRADATA_TIMESTAMP;
5144 break;
5145 case V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING:
5146 ret = HAL_EXTRADATA_S3D_FRAME_PACKING;
5147 break;
5148 case V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE:
5149 ret = HAL_EXTRADATA_FRAME_RATE;
5150 break;
5151 case V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW:
5152 ret = HAL_EXTRADATA_PANSCAN_WINDOW;
5153 break;
5154 case V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
5155 ret = HAL_EXTRADATA_RECOVERY_POINT_SEI;
5156 break;
5157 case V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO:
5158 ret = HAL_EXTRADATA_MULTISLICE_INFO;
5159 break;
5160 case V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB:
5161 ret = HAL_EXTRADATA_NUM_CONCEALED_MB;
5162 break;
5163 case V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER:
5164 ret = HAL_EXTRADATA_METADATA_FILLER;
5165 break;
5166 case V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO:
5167 ret = HAL_EXTRADATA_ASPECT_RATIO;
5168 break;
5169 case V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP:
5170 ret = HAL_EXTRADATA_INPUT_CROP;
5171 break;
5172 case V4L2_MPEG_VIDC_EXTRADATA_DIGITAL_ZOOM:
5173 ret = HAL_EXTRADATA_DIGITAL_ZOOM;
5174 break;
5175 case V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP:
5176 ret = HAL_EXTRADATA_MPEG2_SEQDISP;
5177 break;
5178 case V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA:
5179 ret = HAL_EXTRADATA_STREAM_USERDATA;
5180 break;
5181 case V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP:
5182 ret = HAL_EXTRADATA_FRAME_QP;
5183 break;
5184 case V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO:
5185 ret = HAL_EXTRADATA_FRAME_BITS_INFO;
5186 break;
5187 case V4L2_MPEG_VIDC_EXTRADATA_LTR:
5188 ret = HAL_EXTRADATA_LTR_INFO;
5189 break;
5190 case V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI:
5191 ret = HAL_EXTRADATA_METADATA_MBI;
5192 break;
5193 case V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI:
5194 ret = HAL_EXTRADATA_VQZIP_SEI;
5195 break;
5196 case V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS:
5197 ret = HAL_EXTRADATA_YUV_STATS;
5198 break;
5199 case V4L2_MPEG_VIDC_EXTRADATA_ROI_QP:
5200 ret = HAL_EXTRADATA_ROI_QP;
5201 break;
5202 case V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP:
5203 ret = HAL_EXTRADATA_OUTPUT_CROP;
5204 break;
5205 case V4L2_MPEG_VIDC_EXTRADATA_DISPLAY_COLOUR_SEI:
5206 ret = HAL_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI;
5207 break;
5208 case V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI:
5209 ret = HAL_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI;
5210 break;
5211 case V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO:
5212 ret = HAL_EXTRADATA_PQ_INFO;
5213 break;
5214
5215 case V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY:
5216 ret = HAL_EXTRADATA_VUI_DISPLAY_INFO;
5217 break;
5218 case V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE:
5219 ret = HAL_EXTRADATA_VPX_COLORSPACE;
5220 break;
Praneeth Paladugua51b2c42017-06-23 12:48:06 -07005221 case V4L2_MPEG_VIDC_EXTRADATA_UBWC_CR_STATS_INFO:
5222 ret = HAL_EXTRADATA_UBWC_CR_STATS_INFO;
5223 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005224 default:
5225 dprintk(VIDC_WARN, "Extradata not found: %d\n", index);
5226 break;
5227 }
5228 return ret;
5229};
5230
Maheshwar Ajja9ff81a22017-08-05 13:25:55 -07005231int msm_vidc_noc_error_info(struct msm_vidc_core *core)
5232{
5233 struct hfi_device *hdev;
5234
5235 if (!core || !core->device) {
5236 dprintk(VIDC_WARN, "%s: Invalid parameters: %pK\n",
5237 __func__, core);
5238 return -EINVAL;
5239 }
5240
5241 if (!core->resources.non_fatal_pagefaults)
5242 return 0;
5243
5244 if (!core->smmu_fault_handled)
5245 return 0;
5246
5247 hdev = core->device;
5248 call_hfi_op(hdev, noc_error_info, hdev->hfi_device_data);
5249
5250 return 0;
5251}
5252
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005253int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
5254 enum hal_ssr_trigger_type type)
5255{
5256 int rc = 0;
5257 struct hfi_device *hdev;
5258
5259 if (!core || !core->device) {
5260 dprintk(VIDC_WARN, "Invalid parameters: %pK\n", core);
5261 return -EINVAL;
5262 }
5263 hdev = core->device;
5264 if (core->state == VIDC_CORE_INIT_DONE) {
5265 /*
5266 * In current implementation user-initiated SSR triggers
5267 * a fatal error from hardware. However, there is no way
5268 * to know if fatal error is due to SSR or not. Handle
5269 * user SSR as non-fatal.
5270 */
Maheshwar Ajja8382bec2017-08-11 13:41:35 -07005271 core->trigger_ssr = true;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005272 rc = call_hfi_op(hdev, core_trigger_ssr,
5273 hdev->hfi_device_data, type);
Maheshwar Ajja8382bec2017-08-11 13:41:35 -07005274 if (rc) {
5275 dprintk(VIDC_ERR, "%s: trigger_ssr failed\n",
5276 __func__);
5277 core->trigger_ssr = false;
5278 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005279 }
5280
5281 return rc;
5282}
5283
5284static int msm_vidc_load_supported(struct msm_vidc_inst *inst)
5285{
5286 int num_mbs_per_sec = 0, max_load_adj = 0;
5287 enum load_calc_quirks quirks = LOAD_CALC_IGNORE_TURBO_LOAD |
5288 LOAD_CALC_IGNORE_THUMBNAIL_LOAD |
5289 LOAD_CALC_IGNORE_NON_REALTIME_LOAD;
5290
5291 if (inst->state == MSM_VIDC_OPEN_DONE) {
5292 max_load_adj = inst->core->resources.max_load +
5293 inst->capability.mbs_per_frame.max;
5294 num_mbs_per_sec = msm_comm_get_load(inst->core,
5295 MSM_VIDC_DECODER, quirks);
5296 num_mbs_per_sec += msm_comm_get_load(inst->core,
5297 MSM_VIDC_ENCODER, quirks);
5298 if (num_mbs_per_sec > max_load_adj) {
5299 dprintk(VIDC_ERR,
5300 "H/W is overloaded. needed: %d max: %d\n",
5301 num_mbs_per_sec,
5302 max_load_adj);
5303 msm_vidc_print_running_insts(inst->core);
5304 return -EBUSY;
5305 }
5306 }
5307 return 0;
5308}
5309
5310int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst)
5311{
5312 u32 x_min, x_max, y_min, y_max;
5313 u32 input_height, input_width, output_height, output_width;
Chinmay Sawarkar81a02a32017-07-13 12:10:24 -07005314 u32 rotation;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005315
5316 input_height = inst->prop.height[OUTPUT_PORT];
5317 input_width = inst->prop.width[OUTPUT_PORT];
5318 output_height = inst->prop.height[CAPTURE_PORT];
5319 output_width = inst->prop.width[CAPTURE_PORT];
5320
5321 if (!input_height || !input_width || !output_height || !output_width) {
5322 dprintk(VIDC_ERR,
5323 "Invalid : Input height = %d width = %d",
5324 input_height, input_width);
5325 dprintk(VIDC_ERR,
5326 " output height = %d width = %d\n",
5327 output_height, output_width);
5328 return -ENOTSUPP;
5329 }
5330
5331 if (!inst->capability.scale_x.min ||
5332 !inst->capability.scale_x.max ||
5333 !inst->capability.scale_y.min ||
5334 !inst->capability.scale_y.max) {
5335
5336 if (input_width * input_height !=
5337 output_width * output_height) {
5338 dprintk(VIDC_ERR,
5339 "%s: scaling is not supported (%dx%d != %dx%d)\n",
5340 __func__, input_width, input_height,
5341 output_width, output_height);
5342 return -ENOTSUPP;
5343 }
5344
5345 dprintk(VIDC_DBG, "%s: supported WxH = %dx%d\n",
5346 __func__, input_width, input_height);
5347 return 0;
5348 }
5349
Chinmay Sawarkar81a02a32017-07-13 12:10:24 -07005350 rotation = msm_comm_g_ctrl_for_id(inst,
5351 V4L2_CID_MPEG_VIDC_VIDEO_ROTATION);
5352
5353 if ((output_width != output_height) &&
5354 (rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90 ||
5355 rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270)) {
5356
5357 output_width = inst->prop.height[CAPTURE_PORT];
5358 output_height = inst->prop.width[CAPTURE_PORT];
5359 dprintk(VIDC_DBG,
5360 "Rotation=%u Swapped Output W=%u H=%u to check scaling",
5361 rotation, output_width, output_height);
5362 }
5363
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005364 x_min = (1<<16)/inst->capability.scale_x.min;
5365 y_min = (1<<16)/inst->capability.scale_y.min;
5366 x_max = inst->capability.scale_x.max >> 16;
5367 y_max = inst->capability.scale_y.max >> 16;
5368
5369 if (input_height > output_height) {
5370 if (input_height > x_min * output_height) {
5371 dprintk(VIDC_ERR,
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005372 "Unsupported height min height %d vs %d\n",
5373 input_height / x_min, output_height);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005374 return -ENOTSUPP;
5375 }
5376 } else {
5377 if (output_height > x_max * input_height) {
5378 dprintk(VIDC_ERR,
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005379 "Unsupported height max height %d vs %d\n",
5380 x_max * input_height, output_height);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005381 return -ENOTSUPP;
5382 }
5383 }
5384 if (input_width > output_width) {
5385 if (input_width > y_min * output_width) {
5386 dprintk(VIDC_ERR,
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005387 "Unsupported width min width %d vs %d\n",
5388 input_width / y_min, output_width);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005389 return -ENOTSUPP;
5390 }
5391 } else {
5392 if (output_width > y_max * input_width) {
5393 dprintk(VIDC_ERR,
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005394 "Unsupported width max width %d vs %d\n",
5395 y_max * input_width, output_width);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005396 return -ENOTSUPP;
5397 }
5398 }
5399 return 0;
5400}
5401
5402int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
5403{
5404 struct msm_vidc_capability *capability;
5405 int rc = 0;
5406 struct hfi_device *hdev;
5407 struct msm_vidc_core *core;
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005408 u32 output_height, output_width;
5409 u32 rotation;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005410
5411 if (!inst || !inst->core || !inst->core->device) {
5412 dprintk(VIDC_WARN, "%s: Invalid parameter\n", __func__);
5413 return -EINVAL;
5414 }
5415 capability = &inst->capability;
5416 hdev = inst->core->device;
5417 core = inst->core;
5418 rc = msm_vidc_load_supported(inst);
5419 if (rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005420 dprintk(VIDC_WARN,
5421 "%s: Hardware is overloaded\n", __func__);
5422 return rc;
5423 }
5424
5425 if (!is_thermal_permissible(core)) {
5426 dprintk(VIDC_WARN,
5427 "Thermal level critical, stop all active sessions!\n");
5428 return -ENOTSUPP;
5429 }
5430
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005431 rotation = msm_comm_g_ctrl_for_id(inst,
5432 V4L2_CID_MPEG_VIDC_VIDEO_ROTATION);
5433
5434 output_height = inst->prop.height[CAPTURE_PORT];
5435 output_width = inst->prop.width[CAPTURE_PORT];
5436
5437 if ((output_width != output_height) &&
5438 (rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90 ||
5439 rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270)) {
5440
5441 output_width = inst->prop.height[CAPTURE_PORT];
5442 output_height = inst->prop.width[CAPTURE_PORT];
5443 dprintk(VIDC_DBG,
5444 "Rotation=%u Swapped Output W=%u H=%u to check capability",
5445 rotation, output_width, output_height);
5446 }
5447
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005448 if (!rc) {
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005449 if (output_width < capability->width.min ||
5450 output_height < capability->height.min) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005451 dprintk(VIDC_ERR,
5452 "Unsupported WxH = (%u)x(%u), min supported is - (%u)x(%u)\n",
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005453 output_width,
5454 output_height,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005455 capability->width.min,
5456 capability->height.min);
5457 rc = -ENOTSUPP;
5458 }
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005459 if (!rc && output_width > capability->width.max) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005460 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07005461 "Unsupported width = %u supported max width = %u\n",
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005462 output_width,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005463 capability->width.max);
5464 rc = -ENOTSUPP;
5465 }
5466
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005467 if (!rc && output_height * output_width >
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005468 capability->width.max * capability->height.max) {
5469 dprintk(VIDC_ERR,
5470 "Unsupported WxH = (%u)x(%u), max supported is - (%u)x(%u)\n",
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005471 output_width, output_height,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005472 capability->width.max, capability->height.max);
5473 rc = -ENOTSUPP;
5474 }
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005475
5476 if (!rc && msm_vidc_check_scaling_supported(inst)) {
5477 rc = -ENOTSUPP;
5478 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005479 }
5480 if (rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005481 dprintk(VIDC_ERR,
5482 "%s: Resolution unsupported\n", __func__);
5483 }
5484 return rc;
5485}
5486
5487static void msm_comm_generate_session_error(struct msm_vidc_inst *inst)
5488{
5489 enum hal_command_response cmd = HAL_SESSION_ERROR;
5490 struct msm_vidc_cb_cmd_done response = {0};
5491
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005492 if (!inst || !inst->core) {
5493 dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
5494 return;
5495 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07005496 dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005497 response.session_id = inst;
5498 response.status = VIDC_ERR_FAIL;
5499 handle_session_error(cmd, (void *)&response);
5500}
5501
5502static void msm_comm_generate_sys_error(struct msm_vidc_inst *inst)
5503{
5504 struct msm_vidc_core *core;
5505 enum hal_command_response cmd = HAL_SYS_ERROR;
5506 struct msm_vidc_cb_cmd_done response = {0};
5507
5508 if (!inst || !inst->core) {
5509 dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
5510 return;
5511 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07005512 dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005513 core = inst->core;
5514 response.device_id = (u32) core->id;
5515 handle_sys_error(cmd, (void *) &response);
5516
5517}
5518
5519int msm_comm_kill_session(struct msm_vidc_inst *inst)
5520{
5521 int rc = 0;
5522
5523 if (!inst || !inst->core || !inst->core->device) {
5524 dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
5525 return -EINVAL;
5526 } else if (!inst->session) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07005527 dprintk(VIDC_ERR, "%s: no session to kill for inst %pK\n",
5528 __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005529 return 0;
5530 }
5531
Maheshwar Ajja99422322017-07-07 17:31:15 -07005532 dprintk(VIDC_WARN, "%s: inst %pK, state %d\n", __func__,
5533 inst, inst->state);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005534 /*
5535 * We're internally forcibly killing the session, if fw is aware of
5536 * the session send session_abort to firmware to clean up and release
5537 * the session, else just kill the session inside the driver.
5538 */
5539 if ((inst->state >= MSM_VIDC_OPEN_DONE &&
5540 inst->state < MSM_VIDC_CLOSE_DONE) ||
5541 inst->state == MSM_VIDC_CORE_INVALID) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07005542 rc = msm_comm_session_abort(inst);
5543 if (rc) {
5544 dprintk(VIDC_WARN, "%s: inst %pK abort failed\n",
5545 __func__, inst);
5546 change_inst_state(inst, MSM_VIDC_CORE_INVALID);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005547 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005548 }
5549
Maheshwar Ajja99422322017-07-07 17:31:15 -07005550 change_inst_state(inst, MSM_VIDC_CLOSE_DONE);
5551 msm_comm_session_clean(inst);
5552
5553 dprintk(VIDC_WARN, "%s: inst %pK handled\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005554 return rc;
5555}
5556
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005557int msm_comm_smem_alloc(struct msm_vidc_inst *inst,
5558 size_t size, u32 align, u32 flags, enum hal_buffer buffer_type,
5559 int map_kernel, struct msm_smem *smem)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005560{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005561 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005562
5563 if (!inst || !inst->core) {
5564 dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005565 return -EINVAL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005566 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005567 rc = msm_smem_alloc(inst->mem_client, size, align,
5568 flags, buffer_type, map_kernel, smem);
5569 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005570}
5571
5572void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem)
5573{
5574 if (!inst || !inst->core || !mem) {
5575 dprintk(VIDC_ERR,
5576 "%s: invalid params: %pK %pK\n", __func__, inst, mem);
5577 return;
5578 }
5579 msm_smem_free(inst->mem_client, mem);
5580}
5581
5582int msm_comm_smem_cache_operations(struct msm_vidc_inst *inst,
5583 struct msm_smem *mem, enum smem_cache_ops cache_ops)
5584{
5585 if (!inst || !mem) {
5586 dprintk(VIDC_ERR,
5587 "%s: invalid params: %pK %pK\n", __func__, inst, mem);
5588 return -EINVAL;
5589 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005590 return msm_smem_cache_operations(inst->mem_client, mem->handle,
5591 mem->offset, mem->size, cache_ops);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005592}
5593
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005594int msm_comm_qbuf_cache_operations(struct msm_vidc_inst *inst,
5595 struct v4l2_buffer *b)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005596{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005597 int rc = 0, i;
5598 void *dma_buf;
5599 void *handle;
5600 bool skip;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005601
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005602 if (!inst || !b) {
5603 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
5604 __func__, inst, b);
5605 return -EINVAL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005606 }
5607
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005608 for (i = 0; i < b->length; i++) {
5609 unsigned long offset, size;
5610 enum smem_cache_ops cache_ops;
5611
5612 dma_buf = msm_smem_get_dma_buf(b->m.planes[i].m.fd);
5613 handle = msm_smem_get_handle(inst->mem_client, dma_buf);
5614
5615 offset = b->m.planes[i].data_offset;
5616 size = b->m.planes[i].length;
5617 cache_ops = SMEM_CACHE_INVALIDATE;
5618 skip = false;
5619
5620 if (inst->session_type == MSM_VIDC_DECODER) {
5621 if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
5622 if (!i) { /* bitstream */
5623 size = b->m.planes[i].bytesused;
5624 cache_ops = SMEM_CACHE_CLEAN_INVALIDATE;
5625 }
5626 } else if (b->type ==
5627 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
5628 if (!i) { /* yuv */
5629 /* all values are correct */
5630 }
5631 }
5632 } else if (inst->session_type == MSM_VIDC_ENCODER) {
5633 if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
5634 if (!i) { /* yuv */
5635 size = b->m.planes[i].bytesused;
5636 cache_ops = SMEM_CACHE_CLEAN_INVALIDATE;
5637 } else { /* extradata */
5638 cache_ops = SMEM_CACHE_CLEAN_INVALIDATE;
5639 }
5640 } else if (b->type ==
5641 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
5642 if (!i) { /* bitstream */
5643 /* all values are correct */
5644 }
5645 }
5646 }
5647
5648 if (!skip) {
5649 rc = msm_smem_cache_operations(inst->mem_client, handle,
5650 offset, size, cache_ops);
5651 if (rc)
5652 print_v4l2_buffer(VIDC_ERR,
5653 "qbuf cache ops failed", inst, b);
5654 }
5655
5656 msm_smem_put_handle(inst->mem_client, handle);
5657 msm_smem_put_dma_buf(dma_buf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005658 }
5659
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005660 return rc;
5661}
5662
5663int msm_comm_dqbuf_cache_operations(struct msm_vidc_inst *inst,
5664 struct v4l2_buffer *b)
5665{
5666 int rc = 0, i;
5667 void *dma_buf;
5668 void *handle;
5669 bool skip;
5670
5671 if (!inst || !b) {
5672 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
5673 __func__, inst, b);
5674 return -EINVAL;
5675 }
5676
5677 for (i = 0; i < b->length; i++) {
5678 unsigned long offset, size;
5679 enum smem_cache_ops cache_ops;
5680
5681 dma_buf = msm_smem_get_dma_buf(b->m.planes[i].m.fd);
5682 handle = msm_smem_get_handle(inst->mem_client, dma_buf);
5683
5684 offset = b->m.planes[i].data_offset;
5685 size = b->m.planes[i].length;
5686 cache_ops = SMEM_CACHE_INVALIDATE;
5687 skip = false;
5688
5689 if (inst->session_type == MSM_VIDC_DECODER) {
5690 if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
5691 if (!i) /* bitstream */
5692 skip = true;
5693 } else if (b->type ==
5694 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
5695 if (!i) /* yuv */
5696 skip = true;
5697 }
5698 } else if (inst->session_type == MSM_VIDC_ENCODER) {
5699 if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Maheshwar Ajja07dc9182017-07-28 22:08:15 -07005700 /* yuv and extradata */
5701 skip = true;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005702 } else if (b->type ==
5703 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
5704 if (!i) /* bitstream */
5705 skip = true;
5706 }
5707 }
5708
5709 if (!skip) {
5710 rc = msm_smem_cache_operations(inst->mem_client, handle,
5711 offset, size, cache_ops);
5712 if (rc)
5713 print_v4l2_buffer(VIDC_ERR,
5714 "dqbuf cache ops failed", inst, b);
5715 }
5716
5717 msm_smem_put_handle(inst->mem_client, handle);
5718 msm_smem_put_dma_buf(dma_buf);
5719 }
5720
5721 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005722}
5723
5724void msm_vidc_fw_unload_handler(struct work_struct *work)
5725{
5726 struct msm_vidc_core *core = NULL;
5727 struct hfi_device *hdev = NULL;
5728 int rc = 0;
5729
5730 core = container_of(work, struct msm_vidc_core, fw_unload_work.work);
5731 if (!core || !core->device) {
5732 dprintk(VIDC_ERR, "%s - invalid work or core handle\n",
5733 __func__);
5734 return;
5735 }
5736
5737 hdev = core->device;
5738
5739 mutex_lock(&core->lock);
5740 if (list_empty(&core->instances) &&
5741 core->state != VIDC_CORE_UNINIT) {
5742 if (core->state > VIDC_CORE_INIT) {
5743 dprintk(VIDC_DBG, "Calling vidc_hal_core_release\n");
5744 rc = call_hfi_op(hdev, core_release,
5745 hdev->hfi_device_data);
5746 if (rc) {
5747 dprintk(VIDC_ERR,
5748 "Failed to release core, id = %d\n",
5749 core->id);
5750 mutex_unlock(&core->lock);
5751 return;
5752 }
5753 }
5754 core->state = VIDC_CORE_UNINIT;
5755 kfree(core->capabilities);
5756 core->capabilities = NULL;
5757 }
5758 mutex_unlock(&core->lock);
5759}
5760
5761int msm_comm_set_color_format(struct msm_vidc_inst *inst,
5762 enum hal_buffer buffer_type, int fourcc)
5763{
5764 struct hal_uncompressed_format_select hal_fmt = {0};
5765 enum hal_uncompressed_format format = HAL_UNUSED_COLOR;
5766 int rc = 0;
5767 struct hfi_device *hdev;
5768
5769 if (!inst || !inst->core || !inst->core->device) {
5770 dprintk(VIDC_ERR, "%s - invalid param\n", __func__);
5771 return -EINVAL;
5772 }
5773
5774 hdev = inst->core->device;
5775
Praneeth Paladugu319e7922017-03-16 11:09:06 -07005776 format = msm_comm_get_hal_uncompressed(fourcc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005777 if (format == HAL_UNUSED_COLOR) {
5778 dprintk(VIDC_ERR, "Using unsupported colorformat %#x\n",
5779 fourcc);
5780 rc = -ENOTSUPP;
5781 goto exit;
5782 }
5783
5784 hal_fmt.buffer_type = buffer_type;
5785 hal_fmt.format = format;
5786
5787 rc = call_hfi_op(hdev, session_set_property, inst->session,
5788 HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT, &hal_fmt);
5789 if (rc)
5790 dprintk(VIDC_ERR,
5791 "Failed to set input color format\n");
5792 else
5793 dprintk(VIDC_DBG, "Setting uncompressed colorformat to %#x\n",
5794 format);
5795
5796exit:
5797 return rc;
5798}
5799
5800int msm_vidc_comm_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a)
5801{
5802 u32 property_id = 0;
5803 u64 us_per_frame = 0;
5804 void *pdata;
5805 int rc = 0, fps = 0;
5806 struct hal_frame_rate frame_rate;
5807 struct hfi_device *hdev;
5808
5809 if (!inst || !inst->core || !inst->core->device || !a) {
5810 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
5811 return -EINVAL;
5812 }
5813
5814 hdev = inst->core->device;
5815 property_id = HAL_CONFIG_FRAME_RATE;
5816
5817 if (a->parm.output.timeperframe.denominator) {
5818 switch (a->type) {
5819 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
5820 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
5821 us_per_frame = a->parm.output.timeperframe.numerator *
5822 (u64)USEC_PER_SEC;
5823 do_div(us_per_frame, a->parm.output.
5824 timeperframe.denominator);
5825 break;
5826 default:
5827 dprintk(VIDC_ERR,
5828 "Scale clocks : Unknown buffer type %d\n",
5829 a->type);
5830 break;
5831 }
5832 }
5833
5834 if (!us_per_frame) {
5835 dprintk(VIDC_ERR,
5836 "Failed to scale clocks : time between frames is 0\n");
5837 rc = -EINVAL;
5838 goto exit;
5839 }
5840
5841 fps = USEC_PER_SEC;
5842 do_div(fps, us_per_frame);
5843
5844 if (fps % 15 == 14 || fps % 24 == 23)
5845 fps = fps + 1;
5846 else if ((fps > 1) && (fps % 24 == 1 || fps % 15 == 1))
5847 fps = fps - 1;
5848
Praneeth Paladugue1679112017-01-27 10:07:15 -08005849 if (fps < inst->capability.frame_rate.min ||
5850 fps > inst->capability.frame_rate.max) {
5851 dprintk(VIDC_ERR,
5852 "FPS is out of limits : fps = %d Min = %d, Max = %d\n",
5853 fps, inst->capability.frame_rate.min,
5854 inst->capability.frame_rate.max);
5855 rc = -EINVAL;
5856 goto exit;
5857 }
5858
Maheshwar Ajja266828742017-04-20 15:48:33 -07005859 dprintk(VIDC_PROF, "reported fps changed for %pK: %d->%d\n",
5860 inst, inst->prop.fps, fps);
5861 inst->prop.fps = fps;
Surajit Poddere502daa2017-05-30 19:17:45 +05305862 if (inst->session_type == MSM_VIDC_ENCODER &&
5863 get_hal_codec(inst->fmts[CAPTURE_PORT].fourcc) !=
5864 HAL_VIDEO_CODEC_TME) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005865 frame_rate.frame_rate = inst->prop.fps * BIT(16);
5866 frame_rate.buffer_type = HAL_BUFFER_OUTPUT;
5867 pdata = &frame_rate;
Maheshwar Ajja266828742017-04-20 15:48:33 -07005868 rc = call_hfi_op(hdev, session_set_property,
5869 inst->session, property_id, pdata);
5870 if (rc)
5871 dprintk(VIDC_WARN,
5872 "Failed to set frame rate %d\n", rc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005873 }
5874exit:
5875 return rc;
5876}
5877
5878void msm_comm_print_inst_info(struct msm_vidc_inst *inst)
5879{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005880 struct msm_vidc_buffer *mbuf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005881 struct internal_buf *buf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005882 bool is_decode = false;
5883 enum vidc_ports port;
5884 bool is_secure = false;
5885
5886 if (!inst) {
5887 dprintk(VIDC_ERR, "%s - invalid param %pK\n",
5888 __func__, inst);
5889 return;
5890 }
5891
5892 is_decode = inst->session_type == MSM_VIDC_DECODER;
5893 port = is_decode ? OUTPUT_PORT : CAPTURE_PORT;
5894 is_secure = inst->flags & VIDC_SECURE;
5895 dprintk(VIDC_ERR,
5896 "%s session, %s, Codec type: %s HxW: %d x %d fps: %d bitrate: %d bit-depth: %s\n",
5897 is_decode ? "Decode" : "Encode",
5898 is_secure ? "Secure" : "Non-Secure",
5899 inst->fmts[port].name,
5900 inst->prop.height[port], inst->prop.width[port],
5901 inst->prop.fps, inst->prop.bitrate,
5902 !inst->bit_depth ? "8" : "10");
5903
5904 dprintk(VIDC_ERR,
5905 "---Buffer details for inst: %pK of type: %d---\n",
5906 inst, inst->session_type);
5907 mutex_lock(&inst->registeredbufs.lock);
5908 dprintk(VIDC_ERR, "registered buffer list:\n");
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005909 list_for_each_entry(mbuf, &inst->registeredbufs.list, list)
5910 print_vidc_buffer(VIDC_ERR, "buf", inst, mbuf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005911 mutex_unlock(&inst->registeredbufs.lock);
5912
5913 mutex_lock(&inst->scratchbufs.lock);
5914 dprintk(VIDC_ERR, "scratch buffer list:\n");
5915 list_for_each_entry(buf, &inst->scratchbufs.list, list)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005916 dprintk(VIDC_ERR, "type: %d addr: %x size: %u\n",
5917 buf->buffer_type, buf->smem.device_addr,
5918 buf->smem.size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005919 mutex_unlock(&inst->scratchbufs.lock);
5920
5921 mutex_lock(&inst->persistbufs.lock);
5922 dprintk(VIDC_ERR, "persist buffer list:\n");
5923 list_for_each_entry(buf, &inst->persistbufs.list, list)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005924 dprintk(VIDC_ERR, "type: %d addr: %x size: %u\n",
5925 buf->buffer_type, buf->smem.device_addr,
5926 buf->smem.size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005927 mutex_unlock(&inst->persistbufs.lock);
5928
5929 mutex_lock(&inst->outputbufs.lock);
5930 dprintk(VIDC_ERR, "dpb buffer list:\n");
5931 list_for_each_entry(buf, &inst->outputbufs.list, list)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005932 dprintk(VIDC_ERR, "type: %d addr: %x size: %u\n",
5933 buf->buffer_type, buf->smem.device_addr,
5934 buf->smem.size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005935 mutex_unlock(&inst->outputbufs.lock);
5936}
5937
Umesh Pandeybb3fad02017-03-31 16:49:42 -07005938int msm_comm_session_continue(void *instance)
5939{
5940 struct msm_vidc_inst *inst = instance;
5941 int rc = 0;
5942 struct hfi_device *hdev;
5943
5944 if (!inst || !inst->core || !inst->core->device)
5945 return -EINVAL;
5946 hdev = inst->core->device;
5947 mutex_lock(&inst->lock);
Praneeth Paladugu4e2143c2017-05-15 16:24:10 -07005948 if (inst->state >= MSM_VIDC_RELEASE_RESOURCES_DONE ||
Maheshwar Ajja99422322017-07-07 17:31:15 -07005949 inst->state < MSM_VIDC_START_DONE) {
Praneeth Paladugu4e2143c2017-05-15 16:24:10 -07005950 dprintk(VIDC_DBG,
5951 "Inst %pK : Not in valid state to call %s\n",
5952 inst, __func__);
5953 goto sess_continue_fail;
5954 }
Umesh Pandeybb3fad02017-03-31 16:49:42 -07005955 if (inst->session_type == MSM_VIDC_DECODER && inst->in_reconfig) {
5956 dprintk(VIDC_DBG, "send session_continue\n");
5957 rc = call_hfi_op(hdev, session_continue,
5958 (void *)inst->session);
5959 if (rc) {
5960 dprintk(VIDC_ERR,
5961 "failed to send session_continue\n");
5962 rc = -EINVAL;
5963 goto sess_continue_fail;
5964 }
5965 inst->in_reconfig = false;
Surajit Poddereef1c482017-08-30 17:05:20 +05305966 inst->prop.height[CAPTURE_PORT] = inst->reconfig_height;
5967 inst->prop.width[CAPTURE_PORT] = inst->reconfig_width;
5968 inst->prop.height[OUTPUT_PORT] = inst->reconfig_height;
5969 inst->prop.width[OUTPUT_PORT] = inst->reconfig_width;
Umesh Pandeybb3fad02017-03-31 16:49:42 -07005970 } else if (inst->session_type == MSM_VIDC_ENCODER) {
5971 dprintk(VIDC_DBG,
5972 "session_continue not supported for encoder");
5973 } else {
5974 dprintk(VIDC_ERR,
5975 "session_continue called in wrong state for decoder");
5976 }
Praneeth Paladugu4e2143c2017-05-15 16:24:10 -07005977
Umesh Pandeybb3fad02017-03-31 16:49:42 -07005978sess_continue_fail:
5979 mutex_unlock(&inst->lock);
5980 return rc;
5981}
Umesh Pandeyf2995f82017-05-01 16:44:45 -07005982
5983u32 get_frame_size_nv12(int plane, u32 height, u32 width)
5984{
5985 return VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
5986}
5987
5988u32 get_frame_size_nv12_ubwc(int plane, u32 height, u32 width)
5989{
5990 return VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height);
5991}
5992
5993u32 get_frame_size_rgba(int plane, u32 height, u32 width)
5994{
5995 return VENUS_BUFFER_SIZE(COLOR_FMT_RGBA8888, width, height);
5996}
5997
5998u32 get_frame_size_nv21(int plane, u32 height, u32 width)
5999{
6000 return VENUS_BUFFER_SIZE(COLOR_FMT_NV21, width, height);
6001}
6002
6003u32 get_frame_size_tp10_ubwc(int plane, u32 height, u32 width)
6004{
6005 return VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
6006}
Shivendra Kakraniac1f60e02017-04-13 00:07:26 -07006007
Zhongbo Shi6bd5f5f2017-08-16 17:20:08 +08006008u32 get_frame_size_p010(int plane, u32 height, u32 width)
6009{
6010 return VENUS_BUFFER_SIZE(COLOR_FMT_P010, width, height);
6011}
6012
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006013
6014void print_vidc_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
6015 struct msm_vidc_buffer *mbuf)
6016{
6017 struct vb2_buffer *vb2 = NULL;
6018
6019 if (!(tag & msm_vidc_debug) || !inst || !mbuf)
6020 return;
6021
6022 vb2 = &mbuf->vvb.vb2_buf;
6023
6024 if (vb2->num_planes == 1)
6025 dprintk(tag,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006026 "%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 -07006027 str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6028 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6029 vb2->index, vb2->planes[0].m.fd,
6030 vb2->planes[0].data_offset, mbuf->smem[0].device_addr,
6031 vb2->planes[0].length, vb2->planes[0].bytesused,
6032 mbuf->vvb.flags, mbuf->vvb.vb2_buf.timestamp,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006033 mbuf->smem[0].refcount, mbuf->flags);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006034 else
6035 dprintk(tag,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006036 "%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 -07006037 str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6038 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6039 vb2->index, vb2->planes[0].m.fd,
6040 vb2->planes[0].data_offset, mbuf->smem[0].device_addr,
6041 vb2->planes[0].length, vb2->planes[0].bytesused,
6042 mbuf->vvb.flags, mbuf->vvb.vb2_buf.timestamp,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006043 mbuf->smem[0].refcount, mbuf->flags,
6044 vb2->planes[1].m.fd, vb2->planes[1].data_offset,
6045 mbuf->smem[1].device_addr, vb2->planes[1].length,
6046 vb2->planes[1].bytesused, mbuf->smem[1].refcount);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006047}
6048
6049void print_vb2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
6050 struct vb2_buffer *vb2)
6051{
6052 if (!(tag & msm_vidc_debug) || !inst || !vb2)
6053 return;
6054
6055 if (vb2->num_planes == 1)
6056 dprintk(tag,
6057 "%s: %s: %x : idx %2d fd %d off %d size %d filled %d\n",
6058 str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6059 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6060 vb2->index, vb2->planes[0].m.fd,
6061 vb2->planes[0].data_offset, vb2->planes[0].length,
6062 vb2->planes[0].bytesused);
6063 else
6064 dprintk(tag,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006065 "%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 -07006066 str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6067 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6068 vb2->index, vb2->planes[0].m.fd,
6069 vb2->planes[0].data_offset, vb2->planes[0].length,
6070 vb2->planes[0].bytesused, vb2->planes[1].m.fd,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006071 vb2->planes[1].data_offset, vb2->planes[1].length,
6072 vb2->planes[1].bytesused);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006073}
6074
6075void print_v4l2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
6076 struct v4l2_buffer *v4l2)
6077{
6078 if (!(tag & msm_vidc_debug) || !inst || !v4l2)
6079 return;
6080
6081 if (v4l2->length == 1)
6082 dprintk(tag,
6083 "%s: %s: %x : idx %2d fd %d off %d size %d filled %d\n",
6084 str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6085 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6086 v4l2->index, v4l2->m.planes[0].m.fd,
6087 v4l2->m.planes[0].data_offset,
6088 v4l2->m.planes[0].length,
6089 v4l2->m.planes[0].bytesused);
6090 else
6091 dprintk(tag,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006092 "%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 -07006093 str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6094 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6095 v4l2->index, v4l2->m.planes[0].m.fd,
6096 v4l2->m.planes[0].data_offset,
6097 v4l2->m.planes[0].length,
6098 v4l2->m.planes[0].bytesused,
6099 v4l2->m.planes[1].m.fd,
6100 v4l2->m.planes[1].data_offset,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006101 v4l2->m.planes[1].length,
6102 v4l2->m.planes[1].bytesused);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006103}
6104
6105bool msm_comm_compare_vb2_plane(struct msm_vidc_inst *inst,
6106 struct msm_vidc_buffer *mbuf, struct vb2_buffer *vb2, u32 i)
6107{
6108 struct vb2_buffer *vb;
6109
6110 if (!inst || !mbuf || !vb2) {
6111 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
6112 __func__, inst, mbuf, vb2);
6113 return false;
6114 }
6115
6116 vb = &mbuf->vvb.vb2_buf;
6117 if (vb->planes[i].m.fd == vb2->planes[i].m.fd &&
6118 vb->planes[i].data_offset == vb2->planes[i].data_offset &&
6119 vb->planes[i].length == vb2->planes[i].length) {
6120 return true;
6121 }
6122
6123 return false;
6124}
6125
6126bool msm_comm_compare_vb2_planes(struct msm_vidc_inst *inst,
6127 struct msm_vidc_buffer *mbuf, struct vb2_buffer *vb2)
6128{
6129 int i = 0;
6130 struct vb2_buffer *vb;
6131
6132 if (!inst || !mbuf || !vb2) {
6133 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
6134 __func__, inst, mbuf, vb2);
6135 return false;
6136 }
6137
6138 vb = &mbuf->vvb.vb2_buf;
6139
6140 if (vb->num_planes != vb2->num_planes)
6141 return false;
6142
6143 for (i = 0; i < vb->num_planes; i++) {
6144 if (!msm_comm_compare_vb2_plane(inst, mbuf, vb2, i))
6145 return false;
6146 }
6147
6148 return true;
6149}
6150
6151bool msm_comm_compare_dma_plane(struct msm_vidc_inst *inst,
6152 struct msm_vidc_buffer *mbuf, unsigned long *dma_planes, u32 i)
6153{
6154 if (!inst || !mbuf || !dma_planes) {
6155 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
6156 __func__, inst, mbuf, dma_planes);
6157 return false;
6158 }
6159
6160 if ((unsigned long)mbuf->smem[i].dma_buf == dma_planes[i])
6161 return true;
6162
6163 return false;
6164}
6165
6166bool msm_comm_compare_dma_planes(struct msm_vidc_inst *inst,
6167 struct msm_vidc_buffer *mbuf, unsigned long *dma_planes)
6168{
6169 int i = 0;
6170 struct vb2_buffer *vb;
6171
6172 if (!inst || !mbuf || !dma_planes) {
6173 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
6174 __func__, inst, mbuf, dma_planes);
6175 return false;
6176 }
6177
6178 vb = &mbuf->vvb.vb2_buf;
6179 for (i = 0; i < vb->num_planes; i++) {
6180 if (!msm_comm_compare_dma_plane(inst, mbuf, dma_planes, i))
6181 return false;
6182 }
6183
6184 return true;
6185}
6186
6187
6188bool msm_comm_compare_device_plane(struct msm_vidc_buffer *mbuf,
6189 u32 *planes, u32 i)
6190{
6191 if (!mbuf || !planes) {
6192 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK\n",
6193 __func__, mbuf, planes);
6194 return false;
6195 }
6196
6197 if (mbuf->smem[i].device_addr == planes[i])
6198 return true;
6199
6200 return false;
6201}
6202
6203bool msm_comm_compare_device_planes(struct msm_vidc_buffer *mbuf,
6204 u32 *planes)
6205{
6206 int i = 0;
6207
6208 if (!mbuf || !planes)
6209 return false;
6210
6211 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
6212 if (!msm_comm_compare_device_plane(mbuf, planes, i))
6213 return false;
6214 }
6215
6216 return true;
6217}
6218
6219struct msm_vidc_buffer *msm_comm_get_buffer_using_device_planes(
6220 struct msm_vidc_inst *inst, u32 *planes)
6221{
6222 struct msm_vidc_buffer *mbuf;
6223 bool found = false;
6224
6225 mutex_lock(&inst->registeredbufs.lock);
6226 found = false;
6227 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
6228 if (msm_comm_compare_device_planes(mbuf, planes)) {
6229 found = true;
6230 break;
6231 }
6232 }
6233 mutex_unlock(&inst->registeredbufs.lock);
6234 if (!found) {
6235 dprintk(VIDC_ERR,
6236 "%s: data_addr %x, extradata_addr %x not found\n",
6237 __func__, planes[0], planes[1]);
6238 mbuf = NULL;
6239 }
6240
6241 return mbuf;
6242}
6243
6244int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst,
6245 struct msm_vidc_buffer *mbuf)
6246{
6247 int rc;
6248 struct vb2_buffer *vb;
6249
6250 if (!inst || !mbuf) {
6251 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
6252 __func__, inst, mbuf);
6253 return -EINVAL;
6254 }
6255
6256 vb = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
6257 if (!vb) {
6258 print_vidc_buffer(VIDC_ERR,
6259 "vb not found for buf", inst, mbuf);
6260 return -EINVAL;
6261 }
6262
6263 vb->planes[0].bytesused = 0;
6264 rc = msm_comm_vb2_buffer_done(inst, vb);
6265 if (rc)
6266 print_vidc_buffer(VIDC_ERR,
6267 "vb2_buffer_done failed for", inst, mbuf);
6268
6269 return rc;
6270}
6271
6272struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst,
6273 struct vb2_buffer *vb2)
6274{
6275 int rc = 0;
6276 struct vb2_v4l2_buffer *vbuf;
6277 struct vb2_buffer *vb;
6278 unsigned long dma_planes[VB2_MAX_PLANES] = {0};
6279 struct msm_vidc_buffer *mbuf;
6280 bool found = false;
6281 int i;
6282
6283 if (!inst || !vb2) {
6284 dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
6285 return NULL;
6286 }
6287
6288 for (i = 0; i < vb2->num_planes; i++) {
6289 /*
6290 * always compare dma_buf addresses which is guaranteed
6291 * to be same across the processes (duplicate fds).
6292 */
Maheshwar Ajja07dc9182017-07-28 22:08:15 -07006293 dma_planes[i] = (unsigned long)msm_smem_get_dma_buf(
6294 vb2->planes[i].m.fd);
6295 if (!dma_planes[i])
6296 return NULL;
6297 msm_smem_put_dma_buf((struct dma_buf *)dma_planes[i]);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006298 }
6299
6300 mutex_lock(&inst->registeredbufs.lock);
6301 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
6302 if (msm_comm_compare_dma_planes(inst, mbuf, dma_planes)) {
6303 found = true;
6304 break;
6305 }
6306 }
6307
6308 if (!found) {
6309 /* this is new vb2_buffer */
6310 mbuf = kzalloc(sizeof(struct msm_vidc_buffer), GFP_KERNEL);
6311 if (!mbuf) {
6312 dprintk(VIDC_ERR, "%s: alloc msm_vidc_buffer failed\n",
6313 __func__);
6314 rc = -ENOMEM;
6315 goto exit;
6316 }
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006317 kref_init(&mbuf->kref);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006318 }
6319
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006320 /* Initially assume all the buffer are going to be deferred */
6321 mbuf->flags |= MSM_VIDC_FLAG_DEFERRED;
6322
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006323 vbuf = to_vb2_v4l2_buffer(vb2);
6324 memcpy(&mbuf->vvb, vbuf, sizeof(struct vb2_v4l2_buffer));
6325 vb = &mbuf->vvb.vb2_buf;
6326
6327 for (i = 0; i < vb->num_planes; i++) {
6328 mbuf->smem[i].buffer_type = get_hal_buffer_type(vb->type, i);
6329 mbuf->smem[i].fd = vb->planes[i].m.fd;
6330 mbuf->smem[i].offset = vb->planes[i].data_offset;
6331 mbuf->smem[i].size = vb->planes[i].length;
6332 rc = msm_smem_map_dma_buf(inst, &mbuf->smem[i]);
6333 if (rc) {
6334 dprintk(VIDC_ERR, "%s: map failed.\n", __func__);
6335 goto exit;
6336 }
6337 /* increase refcount as we get both fbd and rbr */
6338 rc = msm_smem_map_dma_buf(inst, &mbuf->smem[i]);
6339 if (rc) {
6340 dprintk(VIDC_ERR, "%s: map failed..\n", __func__);
6341 goto exit;
6342 }
6343 }
6344
6345 /* special handling for decoder */
6346 if (inst->session_type == MSM_VIDC_DECODER) {
6347 if (found) {
6348 rc = -EEXIST;
6349 } else {
6350 bool found_plane0 = false;
6351 struct msm_vidc_buffer *temp;
6352 /*
6353 * client might have queued same plane[0] but different
6354 * plane[1] search plane[0] and if found don't queue the
6355 * buffer, the buffer will be queued when rbr event
6356 * arrived.
6357 */
6358 list_for_each_entry(temp, &inst->registeredbufs.list,
6359 list) {
6360 if (msm_comm_compare_dma_plane(inst, temp,
6361 dma_planes, 0)) {
6362 found_plane0 = true;
6363 break;
6364 }
6365 }
6366 if (found_plane0)
6367 rc = -EEXIST;
6368 }
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006369 /*
6370 * If RBR pending on this buffer then enable RBR_PENDING flag
6371 * and clear the DEFERRED flag to avoid this buffer getting
6372 * queued to video hardware in msm_comm_qbuf() which tries to
6373 * queue all the DEFERRED buffers.
6374 */
6375 if (rc == -EEXIST) {
6376 mbuf->flags |= MSM_VIDC_FLAG_RBR_PENDING;
6377 mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
6378 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006379 }
6380
6381 /* add the new buffer to list */
6382 if (!found)
6383 list_add_tail(&mbuf->list, &inst->registeredbufs.list);
6384
6385 mutex_unlock(&inst->registeredbufs.lock);
6386 if (rc == -EEXIST) {
6387 print_vidc_buffer(VIDC_DBG, "qbuf upon rbr", inst, mbuf);
6388 return ERR_PTR(rc);
6389 }
6390
6391 return mbuf;
6392
6393exit:
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006394 dprintk(VIDC_ERR, "%s: rc %d\n", __func__, rc);
6395 msm_comm_unmap_vidc_buffer(inst, mbuf);
6396 if (!found)
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006397 kref_put_mbuf(mbuf);
6398 mutex_unlock(&inst->registeredbufs.lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006399
6400 return ERR_PTR(rc);
6401}
6402
6403void msm_comm_put_vidc_buffer(struct msm_vidc_inst *inst,
6404 struct msm_vidc_buffer *mbuf)
6405{
6406 struct msm_vidc_buffer *temp;
6407 bool found = false;
6408 int i = 0;
6409
6410 if (!inst || !mbuf) {
6411 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
6412 __func__, inst, mbuf);
6413 return;
6414 }
6415
6416 mutex_lock(&inst->registeredbufs.lock);
6417 /* check if mbuf was not removed by any chance */
6418 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
6419 if (msm_comm_compare_vb2_planes(inst, mbuf,
6420 &temp->vvb.vb2_buf)) {
6421 found = true;
6422 break;
6423 }
6424 }
6425 if (!found) {
6426 print_vidc_buffer(VIDC_ERR, "buf was removed", inst, mbuf);
6427 goto unlock;
6428 }
6429
6430 print_vidc_buffer(VIDC_DBG, "dqbuf", inst, mbuf);
6431 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
6432 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
6433 print_vidc_buffer(VIDC_ERR,
6434 "dqbuf: unmap failed.", inst, mbuf);
6435
6436 if (!(mbuf->vvb.flags & V4L2_QCOM_BUF_FLAG_READONLY)) {
6437 /* rbr won't come for this buffer */
6438 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
6439 print_vidc_buffer(VIDC_ERR,
6440 "dqbuf: unmap failed..", inst, mbuf);
6441 } /* else RBR event expected */
6442 }
6443 /*
6444 * remove the entry if plane[0].refcount is zero else
6445 * don't remove as client queued same buffer that's why
6446 * plane[0].refcount is not zero
6447 */
6448 if (!mbuf->smem[0].refcount) {
6449 list_del(&mbuf->list);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006450 kref_put_mbuf(mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006451 }
6452unlock:
6453 mutex_unlock(&inst->registeredbufs.lock);
6454}
6455
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006456void handle_release_buffer_reference(struct msm_vidc_inst *inst,
6457 struct msm_vidc_buffer *mbuf)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006458{
6459 int rc = 0;
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006460 struct msm_vidc_buffer *temp;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006461 bool found = false;
6462 int i = 0;
6463
6464 mutex_lock(&inst->registeredbufs.lock);
6465 found = false;
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006466 /* check if mbuf was not removed by any chance */
6467 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
6468 if (msm_comm_compare_vb2_planes(inst, mbuf,
6469 &temp->vvb.vb2_buf)) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006470 found = true;
6471 break;
6472 }
6473 }
6474 if (found) {
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006475 /* send RBR event to client */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006476 msm_vidc_queue_rbr_event(inst,
6477 mbuf->vvb.vb2_buf.planes[0].m.fd,
6478 mbuf->vvb.vb2_buf.planes[0].data_offset);
6479
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006480 /* clear RBR_PENDING flag */
6481 mbuf->flags &= ~MSM_VIDC_FLAG_RBR_PENDING;
6482
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006483 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
6484 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
6485 print_vidc_buffer(VIDC_ERR,
6486 "rbr unmap failed.", inst, mbuf);
6487 }
6488 /* refcount is not zero if client queued the same buffer */
6489 if (!mbuf->smem[0].refcount) {
6490 list_del(&mbuf->list);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006491 kref_put_mbuf(mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006492 }
6493 } else {
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006494 print_vidc_buffer(VIDC_ERR, "mbuf not found", inst, mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006495 goto unlock;
6496 }
6497
6498 /*
6499 * 1. client might have pushed same planes in which case mbuf will be
6500 * same and refcounts are positive and buffer wouldn't have been
6501 * removed from the registeredbufs list.
6502 * 2. client might have pushed same planes[0] but different planes[1]
6503 * in which case mbuf will be different.
6504 * 3. in either case we can search mbuf->smem[0].device_addr in the list
6505 * and if found queue it to video hw (if not flushing).
6506 */
6507 found = false;
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006508 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
6509 if (msm_comm_compare_vb2_plane(inst, mbuf,
6510 &temp->vvb.vb2_buf, 0)) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006511 found = true;
6512 break;
6513 }
6514 }
6515 if (!found)
6516 goto unlock;
6517
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006518 /* buffer found means client queued the buffer already */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006519 if (inst->in_reconfig || inst->in_flush) {
6520 print_vidc_buffer(VIDC_DBG, "rbr flush buf", inst, mbuf);
6521 msm_comm_flush_vidc_buffer(inst, mbuf);
6522 msm_comm_unmap_vidc_buffer(inst, mbuf);
6523 /* remove from list */
6524 list_del(&mbuf->list);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006525 kref_put_mbuf(mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006526
6527 /* don't queue the buffer */
6528 found = false;
6529 }
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006530 /* clear DEFERRED flag, if any, as the buffer is going to be queued */
6531 if (found)
6532 mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
6533
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006534unlock:
6535 mutex_unlock(&inst->registeredbufs.lock);
6536
6537 if (found) {
6538 print_vidc_buffer(VIDC_DBG, "rbr qbuf", inst, mbuf);
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006539 rc = msm_comm_qbuf_rbr(inst, mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006540 if (rc)
6541 print_vidc_buffer(VIDC_ERR,
6542 "rbr qbuf failed", inst, mbuf);
6543 }
6544}
6545
6546int msm_comm_unmap_vidc_buffer(struct msm_vidc_inst *inst,
6547 struct msm_vidc_buffer *mbuf)
6548{
6549 int rc = 0, i;
6550
6551 if (!inst || !mbuf) {
6552 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
6553 __func__, inst, mbuf);
6554 return -EINVAL;
6555 }
6556 if (mbuf->vvb.vb2_buf.num_planes > VIDEO_MAX_PLANES) {
6557 dprintk(VIDC_ERR, "%s: invalid num_planes %d\n", __func__,
6558 mbuf->vvb.vb2_buf.num_planes);
6559 return -EINVAL;
6560 }
6561
6562 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
6563 u32 refcount = mbuf->smem[i].refcount;
6564
6565 while (refcount) {
6566 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
6567 print_vidc_buffer(VIDC_ERR,
6568 "unmap failed for buf", inst, mbuf);
6569 refcount--;
6570 }
6571 }
6572
6573 return rc;
6574}
6575
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006576static void kref_free_mbuf(struct kref *kref)
6577{
6578 struct msm_vidc_buffer *mbuf = container_of(kref,
6579 struct msm_vidc_buffer, kref);
6580
6581 kfree(mbuf);
6582}
6583
6584void kref_put_mbuf(struct msm_vidc_buffer *mbuf)
6585{
6586 if (!mbuf)
6587 return;
6588
6589 kref_put(&mbuf->kref, kref_free_mbuf);
6590}
6591
6592bool kref_get_mbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
6593{
6594 struct msm_vidc_buffer *temp;
6595 bool matches = false;
6596 bool ret = false;
6597
6598 if (!inst || !mbuf)
6599 return false;
6600
6601 mutex_lock(&inst->registeredbufs.lock);
6602 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
6603 if (temp == mbuf) {
6604 matches = true;
6605 break;
6606 }
6607 }
6608 ret = (matches && kref_get_unless_zero(&mbuf->kref)) ? true : false;
6609 mutex_unlock(&inst->registeredbufs.lock);
6610
6611 return ret;
6612}
6613
Qiwei Liu551a22222017-08-23 15:28:29 +08006614void msm_comm_store_mark_data(struct msm_vidc_list *data_list,
6615 u32 index, u32 mark_data, u32 mark_target)
6616{
6617 struct msm_vidc_buf_data *pdata = NULL;
6618 bool found = false;
6619
6620 if (!data_list) {
6621 dprintk(VIDC_ERR, "%s: invalid params %pK\n",
6622 __func__, data_list);
6623 return;
6624 }
6625
6626 mutex_lock(&data_list->lock);
6627 list_for_each_entry(pdata, &data_list->list, list) {
6628 if (pdata->index == index) {
6629 pdata->mark_data = mark_data;
6630 pdata->mark_target = mark_target;
6631 found = true;
6632 break;
6633 }
6634 }
6635
6636 if (!found) {
6637 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
6638 if (!pdata) {
6639 dprintk(VIDC_WARN, "%s: malloc failure.\n", __func__);
6640 goto exit;
6641 }
6642 pdata->index = index;
6643 pdata->mark_data = mark_data;
6644 pdata->mark_target = mark_target;
6645 list_add_tail(&pdata->list, &data_list->list);
6646 }
6647
6648exit:
6649 mutex_unlock(&data_list->lock);
6650}
6651
6652void msm_comm_fetch_mark_data(struct msm_vidc_list *data_list,
6653 u32 index, u32 *mark_data, u32 *mark_target)
6654{
6655 struct msm_vidc_buf_data *pdata = NULL;
6656
6657 if (!data_list || !mark_data || !mark_target) {
6658 dprintk(VIDC_ERR, "%s: invalid params %pK %pK %pK\n",
6659 __func__, data_list, mark_data, mark_target);
6660 return;
6661 }
6662
6663 *mark_data = *mark_target = 0;
6664 mutex_lock(&data_list->lock);
6665 list_for_each_entry(pdata, &data_list->list, list) {
6666 if (pdata->index == index) {
6667 *mark_data = pdata->mark_data;
6668 *mark_target = pdata->mark_target;
6669 /* clear after fetch */
6670 pdata->mark_data = pdata->mark_target = 0;
6671 break;
6672 }
6673 }
6674 mutex_unlock(&data_list->lock);
6675}
6676
6677int msm_comm_release_mark_data(struct msm_vidc_inst *inst)
6678{
6679 struct msm_vidc_buf_data *pdata, *next;
6680
6681 if (!inst) {
6682 dprintk(VIDC_ERR, "%s: invalid params %pK\n",
6683 __func__, inst);
6684 return -EINVAL;
6685 }
6686
6687 mutex_lock(&inst->etb_data.lock);
6688 list_for_each_entry_safe(pdata, next, &inst->etb_data.list, list) {
6689 list_del(&pdata->list);
6690 kfree(pdata);
6691 }
6692 mutex_unlock(&inst->etb_data.lock);
6693
6694 mutex_lock(&inst->fbd_data.lock);
6695 list_for_each_entry_safe(pdata, next, &inst->fbd_data.list, list) {
6696 list_del(&pdata->list);
6697 kfree(pdata);
6698 }
6699 mutex_unlock(&inst->fbd_data.lock);
6700
6701 return 0;
6702}
6703