blob: 4c000b7bfb220216ce850e20643f5c285ec9c5da [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 handle_session_error(enum hal_command_response cmd, void *data);
74static void msm_vidc_print_running_insts(struct msm_vidc_core *core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080075
76bool msm_comm_turbo_session(struct msm_vidc_inst *inst)
77{
78 return !!(inst->flags & VIDC_TURBO);
79}
80
81static inline bool is_thumbnail_session(struct msm_vidc_inst *inst)
82{
83 return !!(inst->flags & VIDC_THUMBNAIL);
84}
85
86static inline bool is_low_power_session(struct msm_vidc_inst *inst)
87{
88 return !!(inst->flags & VIDC_LOW_POWER);
89}
90
91static inline bool is_realtime_session(struct msm_vidc_inst *inst)
92{
93 return !!(inst->flags & VIDC_REALTIME);
94}
95
96int msm_comm_g_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl)
97{
98 return v4l2_g_ctrl(&inst->ctrl_handler, ctrl);
99}
100
101int msm_comm_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl)
102{
103 return v4l2_s_ctrl(NULL, &inst->ctrl_handler, ctrl);
104}
105
106int msm_comm_g_ctrl_for_id(struct msm_vidc_inst *inst, int id)
107{
108 int rc = 0;
109 struct v4l2_control ctrl = {
110 .id = id,
111 };
112
113 rc = msm_comm_g_ctrl(inst, &ctrl);
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -0700114 return rc ? rc : ctrl.value;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800115}
116
117static struct v4l2_ctrl **get_super_cluster(struct msm_vidc_inst *inst,
118 int num_ctrls)
119{
120 int c = 0;
121 struct v4l2_ctrl **cluster = kmalloc(sizeof(struct v4l2_ctrl *) *
122 num_ctrls, GFP_KERNEL);
123
Maheshwar Ajja69639bd2017-07-05 17:58:15 -0700124 if (!cluster || !inst) {
125 kfree(cluster);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800126 return NULL;
Maheshwar Ajja69639bd2017-07-05 17:58:15 -0700127 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800128
129 for (c = 0; c < num_ctrls; c++)
130 cluster[c] = inst->ctrls[c];
131
132 return cluster;
133}
134
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800135int msm_comm_hal_to_v4l2(int id, int value)
136{
137 switch (id) {
138 /* H264 */
139 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
140 switch (value) {
141 case HAL_H264_PROFILE_BASELINE:
142 return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
143 case HAL_H264_PROFILE_CONSTRAINED_BASE:
144 return
145 V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE;
146 case HAL_H264_PROFILE_MAIN:
147 return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800148 case HAL_H264_PROFILE_HIGH:
149 return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700150 case HAL_H264_PROFILE_STEREO_HIGH:
151 return V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH;
152 case HAL_H264_PROFILE_MULTIVIEW_HIGH:
153 return V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH;
154 case HAL_H264_PROFILE_CONSTRAINED_HIGH:
155 return V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800156 default:
157 goto unknown_value;
158 }
159 case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
160 switch (value) {
161 case HAL_H264_LEVEL_1:
162 return V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
163 case HAL_H264_LEVEL_1b:
164 return V4L2_MPEG_VIDEO_H264_LEVEL_1B;
165 case HAL_H264_LEVEL_11:
166 return V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
167 case HAL_H264_LEVEL_12:
168 return V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
169 case HAL_H264_LEVEL_13:
170 return V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
171 case HAL_H264_LEVEL_2:
172 return V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
173 case HAL_H264_LEVEL_21:
174 return V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
175 case HAL_H264_LEVEL_22:
176 return V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
177 case HAL_H264_LEVEL_3:
178 return V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
179 case HAL_H264_LEVEL_31:
180 return V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
181 case HAL_H264_LEVEL_32:
182 return V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
183 case HAL_H264_LEVEL_4:
184 return V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
185 case HAL_H264_LEVEL_41:
186 return V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
187 case HAL_H264_LEVEL_42:
188 return V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
189 case HAL_H264_LEVEL_5:
190 return V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
191 case HAL_H264_LEVEL_51:
192 return V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700193 case HAL_H264_LEVEL_52:
194 return V4L2_MPEG_VIDEO_H264_LEVEL_5_2;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800195 default:
196 goto unknown_value;
197 }
198
199 case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
200 switch (value) {
201 case HAL_H264_ENTROPY_CAVLC:
202 return V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
203 case HAL_H264_ENTROPY_CABAC:
204 return V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC;
205 default:
206 goto unknown_value;
207 }
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700208 case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
209 switch (value) {
210 case HAL_HEVC_PROFILE_MAIN:
211 return V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN;
212 case HAL_HEVC_PROFILE_MAIN10:
213 return V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10;
214 case HAL_HEVC_PROFILE_MAIN_STILL_PIC:
215 return V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC;
216 default:
217 goto unknown_value;
218 }
219 case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
220 switch (value) {
221 case HAL_HEVC_MAIN_TIER_LEVEL_1:
222 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1;
223 case HAL_HEVC_MAIN_TIER_LEVEL_2:
224 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2;
225 case HAL_HEVC_MAIN_TIER_LEVEL_2_1:
226 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1;
227 case HAL_HEVC_MAIN_TIER_LEVEL_3:
228 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3;
229 case HAL_HEVC_MAIN_TIER_LEVEL_3_1:
230 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1;
231 case HAL_HEVC_MAIN_TIER_LEVEL_4:
232 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4;
233 case HAL_HEVC_MAIN_TIER_LEVEL_4_1:
234 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1;
235 case HAL_HEVC_MAIN_TIER_LEVEL_5:
236 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5;
237 case HAL_HEVC_MAIN_TIER_LEVEL_5_1:
238 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1;
239 case HAL_HEVC_MAIN_TIER_LEVEL_5_2:
240 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2;
241 case HAL_HEVC_MAIN_TIER_LEVEL_6:
242 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6;
243 case HAL_HEVC_MAIN_TIER_LEVEL_6_1:
244 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1;
245 case HAL_HEVC_MAIN_TIER_LEVEL_6_2:
246 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_2;
247 case HAL_HEVC_HIGH_TIER_LEVEL_1:
248 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1;
249 case HAL_HEVC_HIGH_TIER_LEVEL_2:
250 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2;
251 case HAL_HEVC_HIGH_TIER_LEVEL_2_1:
252 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1;
253 case HAL_HEVC_HIGH_TIER_LEVEL_3:
254 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3;
255 case HAL_HEVC_HIGH_TIER_LEVEL_3_1:
256 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1;
257 case HAL_HEVC_HIGH_TIER_LEVEL_4:
258 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4;
259 case HAL_HEVC_HIGH_TIER_LEVEL_4_1:
260 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1;
261 case HAL_HEVC_HIGH_TIER_LEVEL_5:
262 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5;
263 case HAL_HEVC_HIGH_TIER_LEVEL_5_1:
264 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1;
265 case HAL_HEVC_HIGH_TIER_LEVEL_5_2:
266 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2;
267 case HAL_HEVC_HIGH_TIER_LEVEL_6:
268 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6;
269 case HAL_HEVC_HIGH_TIER_LEVEL_6_1:
270 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1;
271 case HAL_HEVC_HIGH_TIER_LEVEL_6_2:
272 return V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_2;
273 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_UNKNOWN:
274 return HAL_HEVC_TIER_LEVEL_UNKNOWN;
275 default:
276 goto unknown_value;
277 }
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800278 case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700279 switch (value) {
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700280 case HAL_VP8_LEVEL_VERSION_0:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700281 return V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0;
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700282 case HAL_VP8_LEVEL_VERSION_1:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700283 return V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1;
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700284 case HAL_VP8_LEVEL_VERSION_2:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700285 return V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_2;
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700286 case HAL_VP8_LEVEL_VERSION_3:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700287 return V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_3;
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700288 case HAL_VP8_LEVEL_UNUSED:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700289 return V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED;
290 default:
291 goto unknown_value;
292 }
Vaibhav Deshu Venkateshb69518e2017-08-21 12:22:49 -0700293 case V4L2_CID_MPEG_VIDC_VIDEO_VP9_PROFILE:
294 switch (value) {
295 case HAL_VP9_PROFILE_P0:
296 return V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_P0;
297 case HAL_VP9_PROFILE_P2_10:
298 return V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_P2_10;
299 case HAL_VP9_PROFILE_UNUSED:
300 return V4L2_MPEG_VIDC_VIDEO_VP9_PROFILE_UNUSED;
301 default:
302 goto unknown_value;
303 }
304 case V4L2_CID_MPEG_VIDC_VIDEO_VP9_LEVEL:
305 switch (value) {
306 case HAL_VP9_LEVEL_1:
307 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_1;
308 case HAL_VP9_LEVEL_11:
309 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_11;
310 case HAL_VP9_LEVEL_2:
311 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_2;
312 case HAL_VP9_LEVEL_21:
313 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_21;
314 case HAL_VP9_LEVEL_3:
315 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_3;
316 case HAL_VP9_LEVEL_31:
317 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_31;
318 case HAL_VP9_LEVEL_4:
319 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_4;
320 case HAL_VP9_LEVEL_41:
321 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_41;
322 case HAL_VP9_LEVEL_5:
323 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_5;
324 case HAL_VP9_LEVEL_51:
325 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_51;
326 case HAL_VP9_LEVEL_UNUSED:
327 return V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_UNUSED;
328 default:
329 goto unknown_value;
330 }
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800331 case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700332 switch (value) {
333 case HAL_MPEG2_PROFILE_SIMPLE:
334 return V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_SIMPLE;
335 case HAL_MPEG2_PROFILE_MAIN:
336 return V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_MAIN;
337 default:
338 goto unknown_value;
339 }
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800340 case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700341 /* This mapping is not defined properly in V4L2 */
342 switch (value) {
343 case HAL_MPEG2_LEVEL_LL:
344 return V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_0;
345 case HAL_MPEG2_LEVEL_ML:
346 return V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_1;
347 case HAL_MPEG2_LEVEL_HL:
348 return V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_2;
349 default:
350 goto unknown_value;
351 }
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800352 }
353
354unknown_value:
355 dprintk(VIDC_WARN, "Unknown control (%x, %d)\n", id, value);
356 return -EINVAL;
357}
358
359int msm_comm_v4l2_to_hal(int id, int value)
360{
361 switch (id) {
362 /* H264 */
363 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
364 switch (value) {
365 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
366 return HAL_H264_PROFILE_BASELINE;
367 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
368 return HAL_H264_PROFILE_CONSTRAINED_BASE;
369 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
370 return HAL_H264_PROFILE_MAIN;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800371 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
372 return HAL_H264_PROFILE_HIGH;
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700373 case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
374 return HAL_H264_PROFILE_STEREO_HIGH;
375 case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
376 return HAL_H264_PROFILE_MULTIVIEW_HIGH;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800377 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
378 return HAL_H264_PROFILE_CONSTRAINED_HIGH;
379 default:
380 goto unknown_value;
381 }
382 case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
383 switch (value) {
384 case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
385 return HAL_H264_LEVEL_1;
386 case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
387 return HAL_H264_LEVEL_1b;
388 case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
389 return HAL_H264_LEVEL_11;
390 case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
391 return HAL_H264_LEVEL_12;
392 case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
393 return HAL_H264_LEVEL_13;
394 case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
395 return HAL_H264_LEVEL_2;
396 case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
397 return HAL_H264_LEVEL_21;
398 case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
399 return HAL_H264_LEVEL_22;
400 case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
401 return HAL_H264_LEVEL_3;
402 case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
403 return HAL_H264_LEVEL_31;
404 case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
405 return HAL_H264_LEVEL_32;
406 case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
407 return HAL_H264_LEVEL_4;
408 case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
409 return HAL_H264_LEVEL_41;
410 case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
411 return HAL_H264_LEVEL_42;
412 case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
413 return HAL_H264_LEVEL_5;
414 case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
415 return HAL_H264_LEVEL_51;
416 case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
417 return HAL_H264_LEVEL_52;
Vaibhav Deshu Venkatesh234b4dc2017-03-21 16:54:28 -0700418 case V4L2_MPEG_VIDEO_H264_LEVEL_UNKNOWN:
419 return HAL_H264_LEVEL_UNKNOWN;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800420 default:
421 goto unknown_value;
422 }
423 case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
424 switch (value) {
425 case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC:
426 return HAL_H264_ENTROPY_CAVLC;
427 case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
428 return HAL_H264_ENTROPY_CABAC;
429 default:
430 goto unknown_value;
431 }
432 case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL:
433 switch (value) {
434 case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_0:
435 return HAL_H264_CABAC_MODEL_0;
436 case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_1:
437 return HAL_H264_CABAC_MODEL_1;
438 case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_2:
439 return HAL_H264_CABAC_MODEL_2;
440 default:
441 goto unknown_value;
442 }
443 case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
444 switch (value) {
445 case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700446 return HAL_VP8_LEVEL_VERSION_0;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800447 case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700448 return HAL_VP8_LEVEL_VERSION_1;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800449 case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_2:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700450 return HAL_VP8_LEVEL_VERSION_2;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800451 case V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_3:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700452 return HAL_VP8_LEVEL_VERSION_3;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800453 case V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED:
Vaibhav Deshu Venkatesh0ad53f02017-08-07 13:21:47 -0700454 return HAL_VP8_LEVEL_UNUSED;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800455 default:
456 goto unknown_value;
457 }
458 case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
459 switch (value) {
460 case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN:
461 return HAL_HEVC_PROFILE_MAIN;
462 case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10:
463 return HAL_HEVC_PROFILE_MAIN10;
464 case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN_STILL_PIC:
465 return HAL_HEVC_PROFILE_MAIN_STILL_PIC;
466 default:
467 goto unknown_value;
468 }
469 case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
470 switch (value) {
471 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1:
472 return HAL_HEVC_MAIN_TIER_LEVEL_1;
473 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2:
474 return HAL_HEVC_MAIN_TIER_LEVEL_2;
475 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1:
476 return HAL_HEVC_MAIN_TIER_LEVEL_2_1;
477 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3:
478 return HAL_HEVC_MAIN_TIER_LEVEL_3;
479 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1:
480 return HAL_HEVC_MAIN_TIER_LEVEL_3_1;
481 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4:
482 return HAL_HEVC_MAIN_TIER_LEVEL_4;
483 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1:
484 return HAL_HEVC_MAIN_TIER_LEVEL_4_1;
485 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5:
486 return HAL_HEVC_MAIN_TIER_LEVEL_5;
487 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1:
488 return HAL_HEVC_MAIN_TIER_LEVEL_5_1;
489 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2:
490 return HAL_HEVC_MAIN_TIER_LEVEL_5_2;
491 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6:
492 return HAL_HEVC_MAIN_TIER_LEVEL_6;
493 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1:
494 return HAL_HEVC_MAIN_TIER_LEVEL_6_1;
495 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_2:
496 return HAL_HEVC_MAIN_TIER_LEVEL_6_2;
497 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1:
498 return HAL_HEVC_HIGH_TIER_LEVEL_1;
499 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2:
500 return HAL_HEVC_HIGH_TIER_LEVEL_2;
501 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1:
502 return HAL_HEVC_HIGH_TIER_LEVEL_2_1;
503 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3:
504 return HAL_HEVC_HIGH_TIER_LEVEL_3;
505 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1:
506 return HAL_HEVC_HIGH_TIER_LEVEL_3_1;
507 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4:
508 return HAL_HEVC_HIGH_TIER_LEVEL_4;
509 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1:
510 return HAL_HEVC_HIGH_TIER_LEVEL_4_1;
511 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5:
512 return HAL_HEVC_HIGH_TIER_LEVEL_5;
513 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1:
514 return HAL_HEVC_HIGH_TIER_LEVEL_5_1;
515 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2:
516 return HAL_HEVC_HIGH_TIER_LEVEL_5_2;
517 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6:
518 return HAL_HEVC_HIGH_TIER_LEVEL_6;
519 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1:
520 return HAL_HEVC_HIGH_TIER_LEVEL_6_1;
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -0700521 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_2:
522 return HAL_HEVC_HIGH_TIER_LEVEL_6_2;
Vaibhav Deshu Venkatesh234b4dc2017-03-21 16:54:28 -0700523 case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_UNKNOWN:
524 return HAL_HEVC_TIER_LEVEL_UNKNOWN;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800525 default:
526 goto unknown_value;
527 }
Surajit Poddere502daa2017-05-30 19:17:45 +0530528 case V4L2_CID_MPEG_VIDC_VIDEO_TME_PROFILE:
529 switch (value) {
530 case V4L2_MPEG_VIDC_VIDEO_TME_PROFILE_0:
531 return HAL_TME_PROFILE_0;
532 case V4L2_MPEG_VIDC_VIDEO_TME_PROFILE_1:
533 return HAL_TME_PROFILE_1;
534 case V4L2_MPEG_VIDC_VIDEO_TME_PROFILE_2:
535 return HAL_TME_PROFILE_2;
536 case V4L2_MPEG_VIDC_VIDEO_TME_PROFILE_3:
537 return HAL_TME_PROFILE_3;
538 default:
539 goto unknown_value;
540 }
541 case V4L2_CID_MPEG_VIDC_VIDEO_TME_LEVEL:
542 switch (value) {
543 case V4L2_MPEG_VIDC_VIDEO_TME_LEVEL_INTEGER:
544 return HAL_TME_LEVEL_INTEGER;
545 default:
546 goto unknown_value;
547 }
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800548 case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION:
549 switch (value) {
550 case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_NONE:
551 return HAL_ROTATE_NONE;
552 case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90:
553 return HAL_ROTATE_90;
554 case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_180:
555 return HAL_ROTATE_180;
556 case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270:
557 return HAL_ROTATE_270;
558 default:
559 goto unknown_value;
560 }
Chinmay Sawarkar87754272017-09-01 14:50:10 -0700561 case V4L2_CID_MPEG_VIDC_VIDEO_FLIP:
562 switch (value) {
563 case V4L2_CID_MPEG_VIDC_VIDEO_FLIP_NONE:
564 return HAL_FLIP_NONE;
565 case V4L2_CID_MPEG_VIDC_VIDEO_FLIP_HORI:
566 return HAL_FLIP_HORIZONTAL;
567 case V4L2_CID_MPEG_VIDC_VIDEO_FLIP_VERT:
568 return HAL_FLIP_VERTICAL;
569 case V4L2_CID_MPEG_VIDC_VIDEO_FLIP_BOTH:
570 return HAL_FLIP_BOTH;
571 default:
572 goto unknown_value;
573 }
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -0800574 case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
575 switch (value) {
576 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED:
577 return HAL_H264_DB_MODE_DISABLE;
578 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED:
579 return HAL_H264_DB_MODE_ALL_BOUNDARY;
580 case L_MODE:
581 return HAL_H264_DB_MODE_SKIP_SLICE_BOUNDARY;
582 default:
583 goto unknown_value;
584 }
585 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE:
586 switch (value) {
587 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT:
588 return HAL_IFRAMESIZE_TYPE_DEFAULT;
589 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM:
590 return HAL_IFRAMESIZE_TYPE_MEDIUM;
591 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE:
592 return HAL_IFRAMESIZE_TYPE_HUGE;
593 case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED:
594 return HAL_IFRAMESIZE_TYPE_UNLIMITED;
595 default:
596 goto unknown_value;
597 }
598 }
599
600unknown_value:
601 dprintk(VIDC_WARN, "Unknown control (%x, %d)\n", id, value);
602 return -EINVAL;
603}
604
Umesh Pandey92bd41d2017-08-10 14:52:33 -0700605int msm_comm_get_v4l2_profile(int fourcc, int profile)
606{
607 switch (fourcc) {
608 case V4L2_PIX_FMT_H264:
609 return msm_comm_hal_to_v4l2(
610 V4L2_CID_MPEG_VIDEO_H264_PROFILE,
611 profile);
612 case V4L2_PIX_FMT_HEVC:
613 return msm_comm_hal_to_v4l2(
614 V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE,
615 profile);
616 case V4L2_PIX_FMT_VP8:
617 case V4L2_PIX_FMT_VP9:
618 case V4L2_PIX_FMT_MPEG2:
619 return 0;
620 default:
621 dprintk(VIDC_WARN, "Unknown codec id %x\n", fourcc);
622 return 0;
623 }
624}
625
626int msm_comm_get_v4l2_level(int fourcc, int level)
627{
628 switch (fourcc) {
629 case V4L2_PIX_FMT_H264:
630 return msm_comm_hal_to_v4l2(
631 V4L2_CID_MPEG_VIDEO_H264_LEVEL,
632 level);
633 case V4L2_PIX_FMT_HEVC:
634 return msm_comm_hal_to_v4l2(
635 V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL,
636 level);
637 case V4L2_PIX_FMT_VP8:
638 return msm_comm_hal_to_v4l2(
639 V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL,
640 level);
641 case V4L2_PIX_FMT_VP9:
642 case V4L2_PIX_FMT_MPEG2:
643 return 0;
644 default:
645 dprintk(VIDC_WARN, "Unknown codec id %x\n", fourcc);
646 return 0;
647 }
648}
649
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800650int msm_comm_ctrl_init(struct msm_vidc_inst *inst,
651 struct msm_vidc_ctrl *drv_ctrls, u32 num_ctrls,
652 const struct v4l2_ctrl_ops *ctrl_ops)
653{
654 int idx = 0;
655 struct v4l2_ctrl_config ctrl_cfg = {0};
656 int ret_val = 0;
657
658 if (!inst || !drv_ctrls || !ctrl_ops || !num_ctrls) {
659 dprintk(VIDC_ERR, "%s - invalid input\n", __func__);
660 return -EINVAL;
661 }
662
663 inst->ctrls = kcalloc(num_ctrls, sizeof(struct v4l2_ctrl *),
664 GFP_KERNEL);
665 if (!inst->ctrls) {
666 dprintk(VIDC_ERR, "%s - failed to allocate ctrl\n", __func__);
667 return -ENOMEM;
668 }
669
670 ret_val = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls);
671
672 if (ret_val) {
673 dprintk(VIDC_ERR, "CTRL ERR: Control handler init failed, %d\n",
674 inst->ctrl_handler.error);
675 return ret_val;
676 }
677
678 for (; idx < num_ctrls; idx++) {
679 struct v4l2_ctrl *ctrl = NULL;
680
Maheshwar Ajja1f801492017-05-10 16:55:26 -0700681 if (IS_PRIV_CTRL(drv_ctrls[idx].id)) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800682 /*add private control*/
683 ctrl_cfg.def = drv_ctrls[idx].default_value;
684 ctrl_cfg.flags = 0;
685 ctrl_cfg.id = drv_ctrls[idx].id;
686 ctrl_cfg.max = drv_ctrls[idx].maximum;
687 ctrl_cfg.min = drv_ctrls[idx].minimum;
688 ctrl_cfg.menu_skip_mask =
689 drv_ctrls[idx].menu_skip_mask;
690 ctrl_cfg.name = drv_ctrls[idx].name;
691 ctrl_cfg.ops = ctrl_ops;
692 ctrl_cfg.step = drv_ctrls[idx].step;
693 ctrl_cfg.type = drv_ctrls[idx].type;
694 ctrl_cfg.qmenu = drv_ctrls[idx].qmenu;
695
696 ctrl = v4l2_ctrl_new_custom(&inst->ctrl_handler,
697 &ctrl_cfg, NULL);
698 } else {
699 if (drv_ctrls[idx].type == V4L2_CTRL_TYPE_MENU) {
700 ctrl = v4l2_ctrl_new_std_menu(
701 &inst->ctrl_handler,
702 ctrl_ops,
703 drv_ctrls[idx].id,
704 drv_ctrls[idx].maximum,
705 drv_ctrls[idx].menu_skip_mask,
706 drv_ctrls[idx].default_value);
707 } else {
708 ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler,
709 ctrl_ops,
710 drv_ctrls[idx].id,
711 drv_ctrls[idx].minimum,
712 drv_ctrls[idx].maximum,
713 drv_ctrls[idx].step,
714 drv_ctrls[idx].default_value);
715 }
716 }
717
718 if (!ctrl) {
719 dprintk(VIDC_ERR, "%s - invalid ctrl %s\n", __func__,
720 drv_ctrls[idx].name);
721 return -EINVAL;
722 }
723
724 ret_val = inst->ctrl_handler.error;
725 if (ret_val) {
726 dprintk(VIDC_ERR,
727 "Error adding ctrl (%s) to ctrl handle, %d\n",
728 drv_ctrls[idx].name, inst->ctrl_handler.error);
729 return ret_val;
730 }
731
732 ctrl->flags |= drv_ctrls[idx].flags;
733 inst->ctrls[idx] = ctrl;
734 }
735
736 /* Construct a super cluster of all controls */
737 inst->cluster = get_super_cluster(inst, num_ctrls);
738 if (!inst->cluster) {
739 dprintk(VIDC_WARN,
740 "Failed to setup super cluster\n");
741 return -EINVAL;
742 }
743
744 v4l2_ctrl_cluster(num_ctrls, inst->cluster);
745
746 return ret_val;
747}
748
749int msm_comm_ctrl_deinit(struct msm_vidc_inst *inst)
750{
751 if (!inst) {
752 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
753 return -EINVAL;
754 }
755
756 kfree(inst->ctrls);
757 kfree(inst->cluster);
758 v4l2_ctrl_handler_free(&inst->ctrl_handler);
759
760 return 0;
761}
762
763enum multi_stream msm_comm_get_stream_output_mode(struct msm_vidc_inst *inst)
764{
765 switch (msm_comm_g_ctrl_for_id(inst,
766 V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE)) {
767 case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY:
768 return HAL_VIDEO_DECODER_SECONDARY;
769 case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY:
770 default:
771 return HAL_VIDEO_DECODER_PRIMARY;
772 }
773}
774
775static int msm_comm_get_mbs_per_sec(struct msm_vidc_inst *inst)
776{
777 int output_port_mbs, capture_port_mbs;
778 int fps;
779
780 output_port_mbs = inst->in_reconfig ?
781 NUM_MBS_PER_FRAME(inst->reconfig_width,
782 inst->reconfig_height) :
783 NUM_MBS_PER_FRAME(inst->prop.width[OUTPUT_PORT],
784 inst->prop.height[OUTPUT_PORT]);
785
786 capture_port_mbs = NUM_MBS_PER_FRAME(inst->prop.width[CAPTURE_PORT],
787 inst->prop.height[CAPTURE_PORT]);
788
Praneeth Paladugue5fd0872017-04-19 11:24:28 -0700789 if (inst->clk_data.operating_rate) {
790 fps = (inst->clk_data.operating_rate >> 16) ?
791 inst->clk_data.operating_rate >> 16 : 1;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800792 /*
793 * Check if operating rate is less than fps.
794 * If Yes, then use fps to scale clocks
795 */
796 fps = fps > inst->prop.fps ? fps : inst->prop.fps;
797 return max(output_port_mbs, capture_port_mbs) * fps;
798 } else {
799 return max(output_port_mbs, capture_port_mbs) * inst->prop.fps;
800 }
801}
802
803int msm_comm_get_inst_load(struct msm_vidc_inst *inst,
804 enum load_calc_quirks quirks)
805{
806 int load = 0;
807
808 mutex_lock(&inst->lock);
809
810 if (!(inst->state >= MSM_VIDC_OPEN_DONE &&
811 inst->state < MSM_VIDC_STOP_DONE))
812 goto exit;
813
814 load = msm_comm_get_mbs_per_sec(inst);
815
816 if (is_thumbnail_session(inst)) {
817 if (quirks & LOAD_CALC_IGNORE_THUMBNAIL_LOAD)
818 load = 0;
819 }
820
821 if (msm_comm_turbo_session(inst)) {
822 if (!(quirks & LOAD_CALC_IGNORE_TURBO_LOAD))
823 load = inst->core->resources.max_load;
824 }
825
826 /* Clock and Load calculations for REALTIME/NON-REALTIME
827 * OPERATING RATE SET/NO OPERATING RATE SET
828 *
829 * | OPERATING RATE SET | OPERATING RATE NOT SET |
830 * ----------------|--------------------- |------------------------|
831 * REALTIME | load = res * op_rate | load = res * fps |
832 * | clk = res * op_rate | clk = res * fps |
833 * ----------------|----------------------|------------------------|
834 * NON-REALTIME | load = res * 1 fps | load = res * 1 fps |
835 * | clk = res * op_rate | clk = res * fps |
836 * ----------------|----------------------|------------------------|
837 */
838
839 if (!is_realtime_session(inst) &&
840 (quirks & LOAD_CALC_IGNORE_NON_REALTIME_LOAD)) {
841 if (!inst->prop.fps) {
842 dprintk(VIDC_INFO, "instance:%pK fps = 0\n", inst);
843 load = 0;
844 } else {
845 load = msm_comm_get_mbs_per_sec(inst) / inst->prop.fps;
846 }
847 }
848
849exit:
850 mutex_unlock(&inst->lock);
851 return load;
852}
853
Saurabh Kothawade305547e2017-08-14 14:35:21 -0700854int msm_comm_get_inst_load_per_core(struct msm_vidc_inst *inst,
855 enum load_calc_quirks quirks)
856{
857 int load = msm_comm_get_inst_load(inst, quirks);
858
859 if (inst->clk_data.core_id == VIDC_CORE_ID_3)
860 load = load / 2;
861
862 return load;
863}
864
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800865int msm_comm_get_load(struct msm_vidc_core *core,
866 enum session_type type, enum load_calc_quirks quirks)
867{
868 struct msm_vidc_inst *inst = NULL;
869 int num_mbs_per_sec = 0;
870
871 if (!core) {
872 dprintk(VIDC_ERR, "Invalid args: %pK\n", core);
873 return -EINVAL;
874 }
875
876 mutex_lock(&core->lock);
877 list_for_each_entry(inst, &core->instances, list) {
878 if (inst->session_type != type)
879 continue;
880
881 num_mbs_per_sec += msm_comm_get_inst_load(inst, quirks);
882 }
883 mutex_unlock(&core->lock);
884
885 return num_mbs_per_sec;
886}
887
888enum hal_domain get_hal_domain(int session_type)
889{
890 enum hal_domain domain;
891
892 switch (session_type) {
893 case MSM_VIDC_ENCODER:
894 domain = HAL_VIDEO_DOMAIN_ENCODER;
895 break;
896 case MSM_VIDC_DECODER:
897 domain = HAL_VIDEO_DOMAIN_DECODER;
898 break;
899 default:
900 dprintk(VIDC_ERR, "Wrong domain\n");
901 domain = HAL_UNUSED_DOMAIN;
902 break;
903 }
904
905 return domain;
906}
907
908enum hal_video_codec get_hal_codec(int fourcc)
909{
910 enum hal_video_codec codec;
911
912 switch (fourcc) {
913 case V4L2_PIX_FMT_H264:
914 case V4L2_PIX_FMT_H264_NO_SC:
915 codec = HAL_VIDEO_CODEC_H264;
916 break;
917 case V4L2_PIX_FMT_H264_MVC:
918 codec = HAL_VIDEO_CODEC_MVC;
919 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800920 case V4L2_PIX_FMT_MPEG1:
921 codec = HAL_VIDEO_CODEC_MPEG1;
922 break;
923 case V4L2_PIX_FMT_MPEG2:
924 codec = HAL_VIDEO_CODEC_MPEG2;
925 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800926 case V4L2_PIX_FMT_VP8:
927 codec = HAL_VIDEO_CODEC_VP8;
928 break;
929 case V4L2_PIX_FMT_VP9:
930 codec = HAL_VIDEO_CODEC_VP9;
931 break;
932 case V4L2_PIX_FMT_HEVC:
933 codec = HAL_VIDEO_CODEC_HEVC;
934 break;
Surajit Poddere502daa2017-05-30 19:17:45 +0530935 case V4L2_PIX_FMT_TME:
936 codec = HAL_VIDEO_CODEC_TME;
937 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800938 default:
939 dprintk(VIDC_ERR, "Wrong codec: %d\n", fourcc);
940 codec = HAL_UNUSED_CODEC;
941 break;
942 }
943
944 return codec;
945}
946
Praneeth Paladugu319e7922017-03-16 11:09:06 -0700947enum hal_uncompressed_format msm_comm_get_hal_uncompressed(int fourcc)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800948{
949 enum hal_uncompressed_format format = HAL_UNUSED_COLOR;
950
951 switch (fourcc) {
952 case V4L2_PIX_FMT_NV12:
953 format = HAL_COLOR_FORMAT_NV12;
954 break;
955 case V4L2_PIX_FMT_NV21:
956 format = HAL_COLOR_FORMAT_NV21;
957 break;
958 case V4L2_PIX_FMT_NV12_UBWC:
959 format = HAL_COLOR_FORMAT_NV12_UBWC;
960 break;
961 case V4L2_PIX_FMT_NV12_TP10_UBWC:
962 format = HAL_COLOR_FORMAT_NV12_TP10_UBWC;
963 break;
Zhongbo Shie4e1fbc2017-11-20 14:15:45 +0800964 case V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS:
Zhongbo Shi6bd5f5f2017-08-16 17:20:08 +0800965 format = HAL_COLOR_FORMAT_P010;
966 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800967 default:
968 format = HAL_UNUSED_COLOR;
969 break;
970 }
971
972 return format;
973}
974
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800975struct msm_vidc_core *get_vidc_core(int core_id)
976{
977 struct msm_vidc_core *core;
978 int found = 0;
979
980 if (core_id > MSM_VIDC_CORES_MAX) {
981 dprintk(VIDC_ERR, "Core id = %d is greater than max = %d\n",
982 core_id, MSM_VIDC_CORES_MAX);
983 return NULL;
984 }
985 mutex_lock(&vidc_driver->lock);
986 list_for_each_entry(core, &vidc_driver->cores, list) {
987 if (core->id == core_id) {
988 found = 1;
989 break;
990 }
991 }
992 mutex_unlock(&vidc_driver->lock);
993 if (found)
994 return core;
995 return NULL;
996}
997
998const struct msm_vidc_format *msm_comm_get_pixel_fmt_index(
999 const struct msm_vidc_format fmt[], int size, int index, int fmt_type)
1000{
1001 int i, k = 0;
1002
1003 if (!fmt || index < 0) {
1004 dprintk(VIDC_ERR, "Invalid inputs, fmt = %pK, index = %d\n",
1005 fmt, index);
1006 return NULL;
1007 }
1008 for (i = 0; i < size; i++) {
1009 if (fmt[i].type != fmt_type)
1010 continue;
1011 if (k == index)
1012 break;
1013 k++;
1014 }
1015 if (i == size) {
1016 dprintk(VIDC_INFO, "Format not found\n");
1017 return NULL;
1018 }
1019 return &fmt[i];
1020}
1021struct msm_vidc_format *msm_comm_get_pixel_fmt_fourcc(
1022 struct msm_vidc_format fmt[], int size, int fourcc, int fmt_type)
1023{
1024 int i;
1025
1026 if (!fmt) {
1027 dprintk(VIDC_ERR, "Invalid inputs, fmt = %pK\n", fmt);
1028 return NULL;
1029 }
1030 for (i = 0; i < size; i++) {
1031 if (fmt[i].fourcc == fourcc)
1032 break;
1033 }
1034 if (i == size) {
1035 dprintk(VIDC_INFO, "Format not found\n");
1036 return NULL;
1037 }
1038 return &fmt[i];
1039}
1040
1041struct buf_queue *msm_comm_get_vb2q(
1042 struct msm_vidc_inst *inst, enum v4l2_buf_type type)
1043{
1044 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1045 return &inst->bufq[CAPTURE_PORT];
1046 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1047 return &inst->bufq[OUTPUT_PORT];
1048 return NULL;
1049}
1050
1051static void handle_sys_init_done(enum hal_command_response cmd, void *data)
1052{
1053 struct msm_vidc_cb_cmd_done *response = data;
1054 struct msm_vidc_core *core;
1055 struct vidc_hal_sys_init_done *sys_init_msg;
1056 u32 index;
1057
1058 if (!IS_HAL_SYS_CMD(cmd)) {
1059 dprintk(VIDC_ERR, "%s - invalid cmd\n", __func__);
1060 return;
1061 }
1062
1063 index = SYS_MSG_INDEX(cmd);
1064
1065 if (!response) {
1066 dprintk(VIDC_ERR,
1067 "Failed to get valid response for sys init\n");
1068 return;
1069 }
1070 core = get_vidc_core(response->device_id);
1071 if (!core) {
1072 dprintk(VIDC_ERR, "Wrong device_id received\n");
1073 return;
1074 }
1075 sys_init_msg = &response->data.sys_init_done;
1076 if (!sys_init_msg) {
1077 dprintk(VIDC_ERR, "sys_init_done message not proper\n");
1078 return;
1079 }
1080
1081 core->enc_codec_supported = sys_init_msg->enc_codec_supported;
1082 core->dec_codec_supported = sys_init_msg->dec_codec_supported;
1083
1084 /* This should come from sys_init_done */
1085 core->resources.max_inst_count =
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -07001086 sys_init_msg->max_sessions_supported ?
Karthikeyan Periasamy4b5e7332017-07-28 12:07:42 -07001087 min_t(u32, sys_init_msg->max_sessions_supported,
1088 MAX_SUPPORTED_INSTANCES) : MAX_SUPPORTED_INSTANCES;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001089
1090 core->resources.max_secure_inst_count =
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -07001091 core->resources.max_secure_inst_count ?
1092 core->resources.max_secure_inst_count :
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001093 core->resources.max_inst_count;
1094
1095 if (core->id == MSM_VIDC_CORE_VENUS &&
1096 (core->dec_codec_supported & HAL_VIDEO_CODEC_H264))
1097 core->dec_codec_supported |=
1098 HAL_VIDEO_CODEC_MVC;
1099
1100 core->codec_count = sys_init_msg->codec_count;
1101 memcpy(core->capabilities, sys_init_msg->capabilities,
1102 sys_init_msg->codec_count * sizeof(struct msm_vidc_capability));
1103
1104 dprintk(VIDC_DBG,
1105 "%s: supported_codecs[%d]: enc = %#x, dec = %#x\n",
1106 __func__, core->codec_count, core->enc_codec_supported,
1107 core->dec_codec_supported);
1108
1109 complete(&(core->completions[index]));
1110}
1111
Maheshwar Ajja69639bd2017-07-05 17:58:15 -07001112static void put_inst_helper(struct kref *kref)
1113{
1114 struct msm_vidc_inst *inst = container_of(kref,
1115 struct msm_vidc_inst, kref);
1116
1117 msm_vidc_destroy(inst);
1118}
1119
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001120static void put_inst(struct msm_vidc_inst *inst)
1121{
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001122 if (!inst)
1123 return;
1124
1125 kref_put(&inst->kref, put_inst_helper);
1126}
1127
1128static struct msm_vidc_inst *get_inst(struct msm_vidc_core *core,
1129 void *session_id)
1130{
1131 struct msm_vidc_inst *inst = NULL;
1132 bool matches = false;
1133
1134 if (!core || !session_id)
1135 return NULL;
1136
1137 mutex_lock(&core->lock);
1138 /*
1139 * This is as good as !list_empty(!inst->list), but at this point
1140 * we don't really know if inst was kfree'd via close syscall before
1141 * hardware could respond. So manually walk thru the list of active
1142 * sessions
1143 */
1144 list_for_each_entry(inst, &core->instances, list) {
1145 if (inst == session_id) {
1146 /*
1147 * Even if the instance is valid, we really shouldn't
1148 * be receiving or handling callbacks when we've deleted
1149 * our session with HFI
1150 */
1151 matches = !!inst->session;
1152 break;
1153 }
1154 }
1155
1156 /*
1157 * kref_* is atomic_int backed, so no need for inst->lock. But we can
1158 * always acquire inst->lock and release it in put_inst for a stronger
1159 * locking system.
1160 */
1161 inst = (matches && kref_get_unless_zero(&inst->kref)) ? inst : NULL;
1162 mutex_unlock(&core->lock);
1163
1164 return inst;
1165}
1166
1167static void handle_session_release_buf_done(enum hal_command_response cmd,
1168 void *data)
1169{
1170 struct msm_vidc_cb_cmd_done *response = data;
1171 struct msm_vidc_inst *inst;
1172 struct internal_buf *buf;
1173 struct list_head *ptr, *next;
1174 struct hal_buffer_info *buffer;
1175 u32 buf_found = false;
1176 u32 address;
1177
1178 if (!response) {
1179 dprintk(VIDC_ERR, "Invalid release_buf_done response\n");
1180 return;
1181 }
1182
1183 inst = get_inst(get_vidc_core(response->device_id),
1184 response->session_id);
1185 if (!inst) {
1186 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1187 return;
1188 }
1189
1190 buffer = &response->data.buffer_info;
1191 address = buffer->buffer_addr;
1192
1193 mutex_lock(&inst->scratchbufs.lock);
1194 list_for_each_safe(ptr, next, &inst->scratchbufs.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 scratch: %x\n",
1198 buf->smem.device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001199 buf_found = true;
1200 }
1201 }
1202 mutex_unlock(&inst->scratchbufs.lock);
1203
1204 mutex_lock(&inst->persistbufs.lock);
1205 list_for_each_safe(ptr, next, &inst->persistbufs.list) {
1206 buf = list_entry(ptr, struct internal_buf, list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001207 if (address == buf->smem.device_addr) {
1208 dprintk(VIDC_DBG, "releasing persist: %x\n",
1209 buf->smem.device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001210 buf_found = true;
1211 }
1212 }
1213 mutex_unlock(&inst->persistbufs.lock);
1214
1215 if (!buf_found)
1216 dprintk(VIDC_ERR, "invalid buffer received from firmware");
1217 if (IS_HAL_SESSION_CMD(cmd))
1218 complete(&inst->completions[SESSION_MSG_INDEX(cmd)]);
1219 else
1220 dprintk(VIDC_ERR, "Invalid inst cmd response: %d\n", cmd);
1221
1222 put_inst(inst);
1223}
1224
1225static void handle_sys_release_res_done(
1226 enum hal_command_response cmd, void *data)
1227{
1228 struct msm_vidc_cb_cmd_done *response = data;
1229 struct msm_vidc_core *core;
1230
1231 if (!response) {
1232 dprintk(VIDC_ERR,
1233 "Failed to get valid response for sys init\n");
1234 return;
1235 }
1236 core = get_vidc_core(response->device_id);
1237 if (!core) {
1238 dprintk(VIDC_ERR, "Wrong device_id received\n");
1239 return;
1240 }
1241 complete(&core->completions[
1242 SYS_MSG_INDEX(HAL_SYS_RELEASE_RESOURCE_DONE)]);
1243}
1244
1245static void change_inst_state(struct msm_vidc_inst *inst,
1246 enum instance_state state)
1247{
1248 if (!inst) {
1249 dprintk(VIDC_ERR, "Invalid parameter %s\n", __func__);
1250 return;
1251 }
1252 mutex_lock(&inst->lock);
1253 if (inst->state == MSM_VIDC_CORE_INVALID) {
1254 dprintk(VIDC_DBG,
1255 "Inst: %pK is in bad state can't change state to %d\n",
1256 inst, state);
1257 goto exit;
1258 }
1259 dprintk(VIDC_DBG, "Moved inst: %pK from state: %d to state: %d\n",
1260 inst, inst->state, state);
1261 inst->state = state;
1262exit:
1263 mutex_unlock(&inst->lock);
1264}
1265
1266static int signal_session_msg_receipt(enum hal_command_response cmd,
1267 struct msm_vidc_inst *inst)
1268{
1269 if (!inst) {
1270 dprintk(VIDC_ERR, "Invalid(%pK) instance id\n", inst);
1271 return -EINVAL;
1272 }
1273 if (IS_HAL_SESSION_CMD(cmd)) {
1274 complete(&inst->completions[SESSION_MSG_INDEX(cmd)]);
1275 } else {
1276 dprintk(VIDC_ERR, "Invalid inst cmd response: %d\n", cmd);
1277 return -EINVAL;
1278 }
1279 return 0;
1280}
1281
1282static int wait_for_sess_signal_receipt(struct msm_vidc_inst *inst,
1283 enum hal_command_response cmd)
1284{
1285 int rc = 0;
1286 struct hfi_device *hdev;
1287
1288 if (!IS_HAL_SESSION_CMD(cmd)) {
1289 dprintk(VIDC_ERR, "Invalid inst cmd response: %d\n", cmd);
1290 return -EINVAL;
1291 }
1292 hdev = (struct hfi_device *)(inst->core->device);
1293 rc = wait_for_completion_timeout(
1294 &inst->completions[SESSION_MSG_INDEX(cmd)],
Praneeth Paladugud5bf7bc2017-05-29 23:41:04 -07001295 msecs_to_jiffies(
1296 inst->core->resources.msm_vidc_hw_rsp_timeout));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001297 if (!rc) {
1298 dprintk(VIDC_ERR, "Wait interrupted or timed out: %d\n",
1299 SESSION_MSG_INDEX(cmd));
Surajit Podder878ede02017-02-07 12:20:10 +05301300 msm_comm_kill_session(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001301 rc = -EIO;
1302 } else {
1303 rc = 0;
1304 }
1305 return rc;
1306}
1307
1308static int wait_for_state(struct msm_vidc_inst *inst,
1309 enum instance_state flipped_state,
1310 enum instance_state desired_state,
1311 enum hal_command_response hal_cmd)
1312{
1313 int rc = 0;
1314
1315 if (IS_ALREADY_IN_STATE(flipped_state, desired_state)) {
1316 dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
1317 inst, inst->state);
1318 goto err_same_state;
1319 }
1320 dprintk(VIDC_DBG, "Waiting for hal_cmd: %d\n", hal_cmd);
1321 rc = wait_for_sess_signal_receipt(inst, hal_cmd);
1322 if (!rc)
1323 change_inst_state(inst, desired_state);
1324err_same_state:
1325 return rc;
1326}
1327
1328void msm_vidc_queue_v4l2_event(struct msm_vidc_inst *inst, int event_type)
1329{
1330 struct v4l2_event event = {.id = 0, .type = event_type};
1331
1332 v4l2_event_queue_fh(&inst->event_handler, &event);
1333}
1334
1335static void msm_comm_generate_max_clients_error(struct msm_vidc_inst *inst)
1336{
1337 enum hal_command_response cmd = HAL_SESSION_ERROR;
1338 struct msm_vidc_cb_cmd_done response = {0};
1339
1340 if (!inst) {
1341 dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
1342 return;
1343 }
1344 dprintk(VIDC_ERR, "%s: Too many clients\n", __func__);
1345 response.session_id = inst;
1346 response.status = VIDC_ERR_MAX_CLIENTS;
1347 handle_session_error(cmd, (void *)&response);
1348}
1349
1350static void print_cap(const char *type,
1351 struct hal_capability_supported *cap)
1352{
1353 dprintk(VIDC_DBG,
1354 "%-24s: %-8d %-8d %-8d\n",
1355 type, cap->min, cap->max, cap->step_size);
1356}
1357
Praneeth Paladugue1679112017-01-27 10:07:15 -08001358static int msm_vidc_comm_update_ctrl(struct msm_vidc_inst *inst,
1359 u32 id, struct hal_capability_supported *capability)
1360{
1361 struct v4l2_ctrl *ctrl = NULL;
1362 int rc = 0;
1363
1364 ctrl = v4l2_ctrl_find(&inst->ctrl_handler, id);
1365 if (ctrl) {
1366 v4l2_ctrl_modify_range(ctrl, capability->min,
1367 capability->max, ctrl->step,
Maheshwar Ajja850be3c2017-07-06 17:47:40 -07001368 ctrl->default_value);
Praneeth Paladugue1679112017-01-27 10:07:15 -08001369 dprintk(VIDC_DBG,
1370 "%s: Updated Range = %lld --> %lld Def value = %lld\n",
1371 ctrl->name, ctrl->minimum, ctrl->maximum,
1372 ctrl->default_value);
1373 } else {
1374 dprintk(VIDC_ERR,
1375 "Failed to find Conrol %d\n", id);
1376 rc = -EINVAL;
1377 }
1378
1379 return rc;
1380 }
1381
1382static void msm_vidc_comm_update_ctrl_limits(struct msm_vidc_inst *inst)
1383{
Chinmay Sawarkar468c2672017-04-14 14:32:18 -07001384 if (inst->session_type == MSM_VIDC_ENCODER) {
Surajit Poddere502daa2017-05-30 19:17:45 +05301385 if (get_hal_codec(inst->fmts[CAPTURE_PORT].fourcc) ==
1386 HAL_VIDEO_CODEC_TME)
1387 return;
Chinmay Sawarkar468c2672017-04-14 14:32:18 -07001388 msm_vidc_comm_update_ctrl(inst,
1389 V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE,
1390 &inst->capability.hier_p_hybrid);
1391 msm_vidc_comm_update_ctrl(inst,
1392 V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS,
1393 &inst->capability.hier_b);
1394 msm_vidc_comm_update_ctrl(inst,
1395 V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS,
1396 &inst->capability.hier_p);
1397 msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDEO_BITRATE,
1398 &inst->capability.bitrate);
1399 msm_vidc_comm_update_ctrl(inst,
1400 V4L2_CID_MPEG_VIDC_VENC_PARAM_LAYER_BITRATE,
1401 &inst->capability.bitrate);
1402 msm_vidc_comm_update_ctrl(inst,
1403 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1404 &inst->capability.peakbitrate);
1405 msm_vidc_comm_update_ctrl(inst,
1406 V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP,
1407 &inst->capability.i_qp);
1408 msm_vidc_comm_update_ctrl(inst,
1409 V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP,
1410 &inst->capability.p_qp);
1411 msm_vidc_comm_update_ctrl(inst,
1412 V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP,
1413 &inst->capability.b_qp);
1414 msm_vidc_comm_update_ctrl(inst,
1415 V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MIN,
1416 &inst->capability.i_qp);
1417 msm_vidc_comm_update_ctrl(inst,
1418 V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MIN,
1419 &inst->capability.p_qp);
1420 msm_vidc_comm_update_ctrl(inst,
1421 V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MIN,
1422 &inst->capability.b_qp);
1423 msm_vidc_comm_update_ctrl(inst,
1424 V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MAX,
1425 &inst->capability.i_qp);
1426 msm_vidc_comm_update_ctrl(inst,
1427 V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MAX,
1428 &inst->capability.p_qp);
1429 msm_vidc_comm_update_ctrl(inst,
1430 V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MAX,
1431 &inst->capability.b_qp);
1432 msm_vidc_comm_update_ctrl(inst,
1433 V4L2_CID_MPEG_VIDC_VIDEO_BLUR_WIDTH,
1434 &inst->capability.blur_width);
1435 msm_vidc_comm_update_ctrl(inst,
1436 V4L2_CID_MPEG_VIDC_VIDEO_BLUR_HEIGHT,
1437 &inst->capability.blur_height);
1438 msm_vidc_comm_update_ctrl(inst,
1439 V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
1440 &inst->capability.slice_bytes);
1441 msm_vidc_comm_update_ctrl(inst,
1442 V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
1443 &inst->capability.slice_mbs);
1444 msm_vidc_comm_update_ctrl(inst,
1445 V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT,
1446 &inst->capability.ltr_count);
1447 msm_vidc_comm_update_ctrl(inst,
1448 V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES,
1449 &inst->capability.bframe);
1450 }
Saurabh Kothawade501be792017-08-29 11:41:38 -07001451 msm_vidc_comm_update_ctrl(inst,
1452 V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE,
1453 &inst->capability.frame_rate);
Praneeth Paladugue1679112017-01-27 10:07:15 -08001454}
1455
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001456static void handle_session_init_done(enum hal_command_response cmd, void *data)
1457{
1458 struct msm_vidc_cb_cmd_done *response = data;
1459 struct msm_vidc_inst *inst = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001460 struct msm_vidc_capability *capability = NULL;
1461 struct hfi_device *hdev;
1462 struct msm_vidc_core *core;
1463 u32 i, codec;
1464
1465 if (!response) {
1466 dprintk(VIDC_ERR,
1467 "Failed to get valid response for session init\n");
1468 return;
1469 }
1470
1471 inst = get_inst(get_vidc_core(response->device_id),
1472 response->session_id);
1473
1474 if (!inst) {
1475 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1476 return;
1477 }
1478
1479 if (response->status) {
1480 dprintk(VIDC_ERR,
1481 "Session init response from FW : %#x\n",
1482 response->status);
1483 if (response->status == VIDC_ERR_MAX_CLIENTS)
1484 msm_comm_generate_max_clients_error(inst);
1485 else
1486 msm_comm_generate_session_error(inst);
1487
1488 signal_session_msg_receipt(cmd, inst);
1489 put_inst(inst);
1490 return;
1491 }
1492
1493 core = inst->core;
1494 hdev = inst->core->device;
1495 codec = inst->session_type == MSM_VIDC_DECODER ?
1496 inst->fmts[OUTPUT_PORT].fourcc :
1497 inst->fmts[CAPTURE_PORT].fourcc;
1498
1499 /* check if capabilities are available for this session */
1500 for (i = 0; i < VIDC_MAX_SESSIONS; i++) {
1501 if (core->capabilities[i].codec ==
1502 get_hal_codec(codec) &&
1503 core->capabilities[i].domain ==
1504 get_hal_domain(inst->session_type)) {
1505 capability = &core->capabilities[i];
1506 break;
1507 }
1508 }
1509
1510 if (capability) {
1511 dprintk(VIDC_DBG,
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001512 "%s: capabilities for codec 0x%x, domain %#x\n",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001513 __func__, capability->codec, capability->domain);
1514 memcpy(&inst->capability, capability,
1515 sizeof(struct msm_vidc_capability));
1516 } else {
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001517 dprintk(VIDC_ERR,
1518 "Watch out : Some property may fail inst %pK\n", inst);
1519 dprintk(VIDC_ERR,
1520 "Caps N/A for codec 0x%x, domain %#x\n",
1521 inst->capability.codec, inst->capability.domain);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001522 }
1523 inst->capability.pixelprocess_capabilities =
1524 call_hfi_op(hdev, get_core_capabilities, hdev->hfi_device_data);
1525
1526 dprintk(VIDC_DBG,
1527 "Capability type : min max step size\n");
1528 print_cap("width", &inst->capability.width);
1529 print_cap("height", &inst->capability.height);
1530 print_cap("mbs_per_frame", &inst->capability.mbs_per_frame);
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001531 print_cap("mbs_per_sec", &inst->capability.mbs_per_sec);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001532 print_cap("frame_rate", &inst->capability.frame_rate);
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001533 print_cap("bitrate", &inst->capability.bitrate);
1534 print_cap("peak_bitrate", &inst->capability.peakbitrate);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001535 print_cap("scale_x", &inst->capability.scale_x);
1536 print_cap("scale_y", &inst->capability.scale_y);
1537 print_cap("hier_p", &inst->capability.hier_p);
1538 print_cap("ltr_count", &inst->capability.ltr_count);
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001539 print_cap("bframe", &inst->capability.bframe);
1540 print_cap("secure_output2_threshold",
1541 &inst->capability.secure_output2_threshold);
1542 print_cap("hier_b", &inst->capability.hier_b);
1543 print_cap("lcu_size", &inst->capability.lcu_size);
1544 print_cap("hier_p_hybrid", &inst->capability.hier_p_hybrid);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001545 print_cap("mbs_per_sec_low_power",
1546 &inst->capability.mbs_per_sec_power_save);
Praneeth Paladugu520c7592017-01-26 13:53:14 -08001547 print_cap("extradata", &inst->capability.extradata);
1548 print_cap("profile", &inst->capability.profile);
1549 print_cap("level", &inst->capability.level);
1550 print_cap("i_qp", &inst->capability.i_qp);
1551 print_cap("p_qp", &inst->capability.p_qp);
1552 print_cap("b_qp", &inst->capability.b_qp);
1553 print_cap("rc_modes", &inst->capability.rc_modes);
1554 print_cap("blur_width", &inst->capability.blur_width);
1555 print_cap("blur_height", &inst->capability.blur_height);
1556 print_cap("slice_delivery_mode", &inst->capability.slice_delivery_mode);
1557 print_cap("slice_bytes", &inst->capability.slice_bytes);
1558 print_cap("slice_mbs", &inst->capability.slice_mbs);
1559 print_cap("secure", &inst->capability.secure);
1560 print_cap("max_num_b_frames", &inst->capability.max_num_b_frames);
1561 print_cap("max_video_cores", &inst->capability.max_video_cores);
1562 print_cap("max_work_modes", &inst->capability.max_work_modes);
1563 print_cap("ubwc_cr_stats", &inst->capability.ubwc_cr_stats);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001564
Vaibhav Deshu Venkateshf962e1c2017-07-24 16:19:01 -07001565 dprintk(VIDC_DBG, "profile count : %u",
1566 inst->capability.profile_level.profile_count);
1567 for (i = 0; i < inst->capability.profile_level.profile_count; i++) {
1568 dprintk(VIDC_DBG, "profile : %u ", inst->capability.
1569 profile_level.profile_level[i].profile);
1570 dprintk(VIDC_DBG, "level : %u ", inst->capability.
1571 profile_level.profile_level[i].level);
1572 }
1573
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001574 signal_session_msg_receipt(cmd, inst);
Praneeth Paladugue1679112017-01-27 10:07:15 -08001575
1576 /*
1577 * Update controls after informing session_init_done to avoid
1578 * timeouts.
1579 */
1580
1581 msm_vidc_comm_update_ctrl_limits(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001582 put_inst(inst);
1583}
1584
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001585static void msm_vidc_queue_rbr_event(struct msm_vidc_inst *inst,
1586 int fd, u32 offset)
1587{
1588 struct v4l2_event buf_event = {0};
1589 u32 *ptr;
1590
1591 buf_event.type = V4L2_EVENT_RELEASE_BUFFER_REFERENCE;
1592 ptr = (u32 *)buf_event.u.data;
1593 ptr[0] = fd;
1594 ptr[1] = offset;
1595
1596 v4l2_event_queue_fh(&inst->event_handler, &buf_event);
1597}
1598
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001599static void handle_event_change(enum hal_command_response cmd, void *data)
1600{
1601 struct msm_vidc_inst *inst = NULL;
1602 struct msm_vidc_cb_event *event_notify = data;
1603 int event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
1604 struct v4l2_event seq_changed_event = {0};
1605 int rc = 0;
1606 struct hfi_device *hdev;
1607 u32 *ptr = NULL;
Praneeth Paladugu6e637472017-05-16 16:06:46 -07001608 struct hal_buffer_requirements *bufreq;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001609
1610 if (!event_notify) {
1611 dprintk(VIDC_WARN, "Got an empty event from hfi\n");
1612 return;
1613 }
1614
1615 inst = get_inst(get_vidc_core(event_notify->device_id),
1616 event_notify->session_id);
1617 if (!inst || !inst->core || !inst->core->device) {
1618 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1619 goto err_bad_event;
1620 }
1621 hdev = inst->core->device;
1622
1623 switch (event_notify->hal_event_type) {
1624 case HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES:
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001625 event = V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001626 break;
1627 case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
1628 event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
1629 break;
1630 case HAL_EVENT_RELEASE_BUFFER_REFERENCE:
1631 {
Maheshwar Ajjacca04052017-07-12 17:59:45 -07001632 struct msm_vidc_buffer *mbuf;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001633 u32 planes[VIDEO_MAX_PLANES] = {0};
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001634
1635 dprintk(VIDC_DBG,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001636 "%s: inst: %pK data_buffer: %x extradata_buffer: %x\n",
1637 __func__, inst, event_notify->packet_buffer,
1638 event_notify->extra_data_buffer);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001639
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001640 planes[0] = event_notify->packet_buffer;
1641 planes[1] = event_notify->extra_data_buffer;
Maheshwar Ajjacca04052017-07-12 17:59:45 -07001642 mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
1643 if (!mbuf || !kref_get_mbuf(inst, mbuf)) {
1644 dprintk(VIDC_ERR,
1645 "%s: data_addr %x, extradata_addr %x not found\n",
1646 __func__, planes[0], planes[1]);
1647 } else {
1648 handle_release_buffer_reference(inst, mbuf);
1649 kref_put_mbuf(mbuf);
1650 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001651 goto err_bad_event;
1652 }
1653 default:
1654 break;
1655 }
1656
1657 /* Bit depth and pic struct changed event are combined into a single
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001658 * event (insufficient event) for the userspace. Currently bitdepth
1659 * changes is only for HEVC and interlaced support is for all
1660 * codecs except HEVC
1661 * event data is now as follows:
1662 * u32 *ptr = seq_changed_event.u.data;
1663 * ptr[0] = height
1664 * ptr[1] = width
1665 * ptr[2] = bit depth
1666 * ptr[3] = pic struct (progressive or interlaced)
1667 * ptr[4] = colour space
Umesh Pandey92bd41d2017-08-10 14:52:33 -07001668 * ptr[5] = crop_data(top)
1669 * ptr[6] = crop_data(left)
1670 * ptr[7] = crop_data(height)
1671 * ptr[8] = crop_data(width)
1672 * ptr[9] = profile
1673 * ptr[10] = level
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001674 */
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001675
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -07001676 inst->entropy_mode = event_notify->entropy_mode;
1677 inst->profile = event_notify->profile;
1678 inst->level = event_notify->level;
Praneeth Paladugu520e9b22017-05-31 13:25:18 -07001679 inst->prop.crop_info.left =
1680 event_notify->crop_data.left;
1681 inst->prop.crop_info.top =
1682 event_notify->crop_data.top;
1683 inst->prop.crop_info.height =
1684 event_notify->crop_data.height;
1685 inst->prop.crop_info.width =
1686 event_notify->crop_data.width;
Praneeth Paladuguf597ddd2017-09-27 11:00:31 -07001687 /* HW returns progressive_only flag in pic_struct. */
1688 inst->pic_struct =
1689 event_notify->pic_struct ?
1690 MSM_VIDC_PIC_STRUCT_PROGRESSIVE :
1691 MSM_VIDC_PIC_STRUCT_MAYBE_INTERLACED;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -08001692
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001693 ptr = (u32 *)seq_changed_event.u.data;
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001694 ptr[0] = event_notify->height;
1695 ptr[1] = event_notify->width;
1696 ptr[2] = event_notify->bit_depth;
1697 ptr[3] = event_notify->pic_struct;
1698 ptr[4] = event_notify->colour_space;
Praneeth Paladugu72fa67b2017-05-30 11:20:01 -07001699 ptr[5] = event_notify->crop_data.top;
1700 ptr[6] = event_notify->crop_data.left;
1701 ptr[7] = event_notify->crop_data.height;
1702 ptr[8] = event_notify->crop_data.width;
Umesh Pandey92bd41d2017-08-10 14:52:33 -07001703 ptr[9] = msm_comm_get_v4l2_profile(
1704 inst->fmts[OUTPUT_PORT].fourcc,
1705 event_notify->profile);
1706 ptr[10] = msm_comm_get_v4l2_level(
1707 inst->fmts[OUTPUT_PORT].fourcc,
1708 event_notify->level);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001709
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001710 dprintk(VIDC_DBG,
Umesh Pandey92bd41d2017-08-10 14:52:33 -07001711 "Event payload: height = %d width = %d profile = %d level = %d\n",
1712 event_notify->height, event_notify->width,
1713 ptr[9], ptr[10]);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001714
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001715 dprintk(VIDC_DBG,
1716 "Event payload: bit_depth = %d pic_struct = %d colour_space = %d\n",
1717 event_notify->bit_depth, event_notify->pic_struct,
1718 event_notify->colour_space);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001719
Praneeth Paladugu520e9b22017-05-31 13:25:18 -07001720 dprintk(VIDC_DBG,
1721 "Event payload: CROP top = %d left = %d Height = %d Width = %d\n",
1722 event_notify->crop_data.top,
1723 event_notify->crop_data.left,
1724 event_notify->crop_data.height,
1725 event_notify->crop_data.width);
1726
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001727 mutex_lock(&inst->lock);
1728 inst->in_reconfig = true;
1729 inst->reconfig_height = event_notify->height;
1730 inst->reconfig_width = event_notify->width;
Praneeth Paladugu6e637472017-05-16 16:06:46 -07001731
1732 if (msm_comm_get_stream_output_mode(inst) ==
1733 HAL_VIDEO_DECODER_SECONDARY) {
1734
1735 bufreq = get_buff_req_buffer(inst,
1736 HAL_BUFFER_OUTPUT);
1737 if (!bufreq) {
1738 dprintk(VIDC_ERR,
1739 "Failed : No buffer requirements : %x\n",
1740 HAL_BUFFER_OUTPUT);
1741 return;
1742 }
1743
1744 bufreq->buffer_count_min = event_notify->capture_buf_count;
1745
1746 bufreq = get_buff_req_buffer(inst,
1747 HAL_BUFFER_OUTPUT2);
1748 if (!bufreq) {
1749 dprintk(VIDC_ERR,
1750 "Failed : No buffer requirements : %x\n",
1751 HAL_BUFFER_OUTPUT2);
1752 return;
1753 }
1754
1755 bufreq->buffer_count_min = event_notify->capture_buf_count;
1756 } else {
1757
1758 bufreq = get_buff_req_buffer(inst,
1759 HAL_BUFFER_OUTPUT);
1760 if (!bufreq) {
1761 dprintk(VIDC_ERR,
1762 "Failed : No buffer requirements : %x\n",
1763 HAL_BUFFER_OUTPUT);
1764 return;
1765 }
1766 bufreq->buffer_count_min = event_notify->capture_buf_count;
Praneeth Paladugu6e637472017-05-16 16:06:46 -07001767 }
1768
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001769 mutex_unlock(&inst->lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001770
1771 if (event == V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT) {
1772 dprintk(VIDC_DBG, "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT\n");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001773 } else {
1774 dprintk(VIDC_DBG, "V4L2_EVENT_SEQ_CHANGED_SUFFICIENT\n");
1775 dprintk(VIDC_DBG,
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001776 "event_notify->height = %d event_notify->width = %d\n",
1777 event_notify->height,
1778 event_notify->width);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001779 }
1780
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001781 rc = msm_vidc_check_session_supported(inst);
1782 if (!rc) {
1783 seq_changed_event.type = event;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001784 v4l2_event_queue_fh(&inst->event_handler, &seq_changed_event);
1785 } else if (rc == -ENOTSUPP) {
1786 msm_vidc_queue_v4l2_event(inst,
1787 V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED);
1788 } else if (rc == -EBUSY) {
1789 msm_vidc_queue_v4l2_event(inst,
1790 V4L2_EVENT_MSM_VIDC_HW_OVERLOAD);
1791 }
1792
1793err_bad_event:
1794 put_inst(inst);
1795}
1796
1797static void handle_session_prop_info(enum hal_command_response cmd, void *data)
1798{
1799 struct msm_vidc_cb_cmd_done *response = data;
1800 struct getprop_buf *getprop;
1801 struct msm_vidc_inst *inst;
1802
1803 if (!response) {
1804 dprintk(VIDC_ERR,
1805 "Failed to get valid response for prop info\n");
1806 return;
1807 }
1808
1809 inst = get_inst(get_vidc_core(response->device_id),
1810 response->session_id);
1811 if (!inst) {
1812 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1813 return;
1814 }
1815
1816 getprop = kzalloc(sizeof(*getprop), GFP_KERNEL);
1817 if (!getprop) {
1818 dprintk(VIDC_ERR, "%s: getprop kzalloc failed\n", __func__);
1819 goto err_prop_info;
1820 }
1821
1822 getprop->data = kmemdup(&response->data.property,
1823 sizeof(union hal_get_property), GFP_KERNEL);
1824 if (!getprop->data) {
1825 dprintk(VIDC_ERR, "%s: kmemdup failed\n", __func__);
1826 kfree(getprop);
1827 goto err_prop_info;
1828 }
1829
1830 mutex_lock(&inst->pending_getpropq.lock);
1831 list_add_tail(&getprop->list, &inst->pending_getpropq.list);
1832 mutex_unlock(&inst->pending_getpropq.lock);
1833
1834 signal_session_msg_receipt(cmd, inst);
1835err_prop_info:
1836 put_inst(inst);
1837}
1838
1839static void handle_load_resource_done(enum hal_command_response cmd, void *data)
1840{
1841 struct msm_vidc_cb_cmd_done *response = data;
1842 struct msm_vidc_inst *inst;
1843
1844 if (!response) {
1845 dprintk(VIDC_ERR,
1846 "Failed to get valid response for load resource\n");
1847 return;
1848 }
1849
1850 inst = get_inst(get_vidc_core(response->device_id),
1851 response->session_id);
1852 if (!inst) {
1853 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1854 return;
1855 }
1856
1857 if (response->status) {
1858 dprintk(VIDC_ERR,
1859 "Load resource response from FW : %#x\n",
1860 response->status);
1861 msm_comm_generate_session_error(inst);
1862 }
1863
1864 put_inst(inst);
1865}
1866
1867static void handle_start_done(enum hal_command_response cmd, void *data)
1868{
1869 struct msm_vidc_cb_cmd_done *response = data;
1870 struct msm_vidc_inst *inst;
1871
1872 if (!response) {
1873 dprintk(VIDC_ERR, "Failed to get valid response for start\n");
1874 return;
1875 }
1876
1877 inst = get_inst(get_vidc_core(response->device_id),
1878 response->session_id);
1879 if (!inst) {
1880 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1881 return;
1882 }
1883
1884 signal_session_msg_receipt(cmd, inst);
1885 put_inst(inst);
1886}
1887
1888static void handle_stop_done(enum hal_command_response cmd, void *data)
1889{
1890 struct msm_vidc_cb_cmd_done *response = data;
1891 struct msm_vidc_inst *inst;
1892
1893 if (!response) {
1894 dprintk(VIDC_ERR, "Failed to get valid response for stop\n");
1895 return;
1896 }
1897
1898 inst = get_inst(get_vidc_core(response->device_id),
1899 response->session_id);
1900 if (!inst) {
1901 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1902 return;
1903 }
1904
1905 signal_session_msg_receipt(cmd, inst);
1906 put_inst(inst);
1907}
1908
1909static void handle_release_res_done(enum hal_command_response cmd, void *data)
1910{
1911 struct msm_vidc_cb_cmd_done *response = data;
1912 struct msm_vidc_inst *inst;
1913
1914 if (!response) {
1915 dprintk(VIDC_ERR,
1916 "Failed to get valid response for release resource\n");
1917 return;
1918 }
1919
1920 inst = get_inst(get_vidc_core(response->device_id),
1921 response->session_id);
1922 if (!inst) {
1923 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
1924 return;
1925 }
1926
1927 signal_session_msg_receipt(cmd, inst);
1928 put_inst(inst);
1929}
1930
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08001931void msm_comm_validate_output_buffers(struct msm_vidc_inst *inst)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001932{
1933 struct internal_buf *binfo;
1934 u32 buffers_owned_by_driver = 0;
1935 struct hal_buffer_requirements *output_buf;
1936
1937 output_buf = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
1938
1939 if (!output_buf) {
1940 dprintk(VIDC_DBG,
1941 "This output buffer not required, buffer_type: %x\n",
1942 HAL_BUFFER_OUTPUT);
1943 return;
1944 }
1945 mutex_lock(&inst->outputbufs.lock);
Maheshwar Ajja850be3c2017-07-06 17:47:40 -07001946 if (list_empty(&inst->outputbufs.list)) {
1947 dprintk(VIDC_DBG, "%s: no OUTPUT buffers allocated\n",
1948 __func__);
1949 mutex_unlock(&inst->outputbufs.lock);
1950 return;
1951 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001952 list_for_each_entry(binfo, &inst->outputbufs.list, list) {
1953 if (binfo->buffer_ownership != DRIVER) {
1954 dprintk(VIDC_DBG,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001955 "This buffer is with FW %x\n",
1956 binfo->smem.device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001957 continue;
1958 }
1959 buffers_owned_by_driver++;
1960 }
1961 mutex_unlock(&inst->outputbufs.lock);
1962
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08001963 if (buffers_owned_by_driver != output_buf->buffer_count_actual) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001964 dprintk(VIDC_WARN,
1965 "OUTPUT Buffer count mismatch %d of %d\n",
1966 buffers_owned_by_driver,
1967 output_buf->buffer_count_actual);
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08001968 msm_vidc_handle_hw_error(inst->core);
1969 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001970}
1971
1972int msm_comm_queue_output_buffers(struct msm_vidc_inst *inst)
1973{
1974 struct internal_buf *binfo;
1975 struct hfi_device *hdev;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001976 struct vidc_frame_data frame_data = {0};
1977 struct hal_buffer_requirements *output_buf, *extra_buf;
1978 int rc = 0;
1979
1980 if (!inst || !inst->core || !inst->core->device) {
1981 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
1982 return -EINVAL;
1983 }
1984
1985 hdev = inst->core->device;
1986
1987 output_buf = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
1988 if (!output_buf) {
1989 dprintk(VIDC_DBG,
1990 "This output buffer not required, buffer_type: %x\n",
1991 HAL_BUFFER_OUTPUT);
1992 return 0;
1993 }
1994 dprintk(VIDC_DBG,
1995 "output: num = %d, size = %d\n",
1996 output_buf->buffer_count_actual,
1997 output_buf->buffer_size);
1998
1999 extra_buf = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_OUTPUT);
2000
2001 mutex_lock(&inst->outputbufs.lock);
2002 list_for_each_entry(binfo, &inst->outputbufs.list, list) {
2003 if (binfo->buffer_ownership != DRIVER)
2004 continue;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002005 frame_data.alloc_len = output_buf->buffer_size;
2006 frame_data.filled_len = 0;
2007 frame_data.offset = 0;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002008 frame_data.device_addr = binfo->smem.device_addr;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002009 frame_data.flags = 0;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002010 frame_data.extradata_addr = binfo->smem.device_addr +
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002011 output_buf->buffer_size;
2012 frame_data.buffer_type = HAL_BUFFER_OUTPUT;
2013 frame_data.extradata_size = extra_buf ?
2014 extra_buf->buffer_size : 0;
2015 rc = call_hfi_op(hdev, session_ftb,
2016 (void *) inst->session, &frame_data);
2017 binfo->buffer_ownership = FIRMWARE;
2018 }
2019 mutex_unlock(&inst->outputbufs.lock);
2020
2021 return 0;
2022}
2023
2024static void handle_session_flush(enum hal_command_response cmd, void *data)
2025{
2026 struct msm_vidc_cb_cmd_done *response = data;
2027 struct msm_vidc_inst *inst;
2028 struct v4l2_event flush_event = {0};
2029 u32 *ptr = NULL;
2030 enum hal_flush flush_type;
2031 int rc;
2032
2033 if (!response) {
2034 dprintk(VIDC_ERR, "Failed to get valid response for flush\n");
2035 return;
2036 }
2037
2038 inst = get_inst(get_vidc_core(response->device_id),
2039 response->session_id);
2040 if (!inst) {
2041 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2042 return;
2043 }
2044
2045 if (msm_comm_get_stream_output_mode(inst) ==
2046 HAL_VIDEO_DECODER_SECONDARY) {
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08002047
2048 if (!(inst->fmts[OUTPUT_PORT].defer_outputs &&
2049 inst->in_reconfig))
2050 msm_comm_validate_output_buffers(inst);
2051
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002052 if (!inst->in_reconfig) {
2053 rc = msm_comm_queue_output_buffers(inst);
2054 if (rc) {
2055 dprintk(VIDC_ERR,
2056 "Failed to queue output buffers: %d\n",
2057 rc);
2058 }
2059 }
2060 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002061 inst->in_flush = false;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002062 flush_event.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
2063 ptr = (u32 *)flush_event.u.data;
2064
2065 flush_type = response->data.flush_type;
2066 switch (flush_type) {
2067 case HAL_FLUSH_INPUT:
2068 ptr[0] = V4L2_QCOM_CMD_FLUSH_OUTPUT;
2069 break;
2070 case HAL_FLUSH_OUTPUT:
2071 ptr[0] = V4L2_QCOM_CMD_FLUSH_CAPTURE;
2072 break;
2073 case HAL_FLUSH_ALL:
2074 ptr[0] |= V4L2_QCOM_CMD_FLUSH_CAPTURE;
2075 ptr[0] |= V4L2_QCOM_CMD_FLUSH_OUTPUT;
2076 break;
2077 default:
2078 dprintk(VIDC_ERR, "Invalid flush type received!");
2079 goto exit;
2080 }
2081
2082 dprintk(VIDC_DBG,
2083 "Notify flush complete, flush_type: %x\n", flush_type);
2084 v4l2_event_queue_fh(&inst->event_handler, &flush_event);
2085
2086exit:
2087 put_inst(inst);
2088}
2089
2090static void handle_session_error(enum hal_command_response cmd, void *data)
2091{
2092 struct msm_vidc_cb_cmd_done *response = data;
2093 struct hfi_device *hdev = NULL;
2094 struct msm_vidc_inst *inst = NULL;
2095 int event = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
2096
2097 if (!response) {
2098 dprintk(VIDC_ERR,
2099 "Failed to get valid response for session error\n");
2100 return;
2101 }
2102
2103 inst = get_inst(get_vidc_core(response->device_id),
2104 response->session_id);
2105 if (!inst) {
2106 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2107 return;
2108 }
2109
2110 hdev = inst->core->device;
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07002111 dprintk(VIDC_ERR, "Session error received for inst %pK session %x\n",
2112 inst, hash32_ptr(inst->session));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002113
2114 if (response->status == VIDC_ERR_MAX_CLIENTS) {
2115 dprintk(VIDC_WARN, "Too many clients, rejecting %pK", inst);
2116 event = V4L2_EVENT_MSM_VIDC_MAX_CLIENTS;
2117
2118 /*
2119 * Clean the HFI session now. Since inst->state is moved to
2120 * INVALID, forward thread doesn't know FW has valid session
2121 * or not. This is the last place driver knows that there is
2122 * no session in FW. Hence clean HFI session now.
2123 */
2124
2125 msm_comm_session_clean(inst);
2126 } else if (response->status == VIDC_ERR_NOT_SUPPORTED) {
2127 dprintk(VIDC_WARN, "Unsupported bitstream in %pK", inst);
2128 event = V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED;
2129 } else {
2130 dprintk(VIDC_WARN, "Unknown session error (%d) for %pK\n",
2131 response->status, inst);
2132 event = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
2133 }
2134
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07002135 /* change state before sending error to client */
2136 change_inst_state(inst, MSM_VIDC_CORE_INVALID);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002137 msm_vidc_queue_v4l2_event(inst, event);
2138 put_inst(inst);
2139}
2140
2141static void msm_comm_clean_notify_client(struct msm_vidc_core *core)
2142{
2143 struct msm_vidc_inst *inst = NULL;
2144
2145 if (!core) {
2146 dprintk(VIDC_ERR, "%s: Invalid params\n", __func__);
2147 return;
2148 }
2149
2150 dprintk(VIDC_WARN, "%s: Core %pK\n", __func__, core);
2151 mutex_lock(&core->lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002152
2153 list_for_each_entry(inst, &core->instances, list) {
2154 mutex_lock(&inst->lock);
2155 inst->state = MSM_VIDC_CORE_INVALID;
2156 mutex_unlock(&inst->lock);
2157 dprintk(VIDC_WARN,
2158 "%s Send sys error for inst %pK\n", __func__, inst);
2159 msm_vidc_queue_v4l2_event(inst,
2160 V4L2_EVENT_MSM_VIDC_SYS_ERROR);
2161 }
2162 mutex_unlock(&core->lock);
2163}
2164
2165static void handle_sys_error(enum hal_command_response cmd, void *data)
2166{
2167 struct msm_vidc_cb_cmd_done *response = data;
2168 struct msm_vidc_core *core = NULL;
2169 struct hfi_device *hdev = NULL;
2170 struct msm_vidc_inst *inst = NULL;
2171 int rc = 0;
2172
2173 subsystem_crashed("venus");
2174 if (!response) {
2175 dprintk(VIDC_ERR,
2176 "Failed to get valid response for sys error\n");
2177 return;
2178 }
2179
2180 core = get_vidc_core(response->device_id);
2181 if (!core) {
2182 dprintk(VIDC_ERR,
2183 "Got SYS_ERR but unable to identify core\n");
2184 return;
2185 }
Maheshwar Ajjac35d7fc2017-09-01 16:44:46 -07002186 hdev = core->device;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002187
2188 mutex_lock(&core->lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002189 if (core->state == VIDC_CORE_UNINIT) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002190 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07002191 "%s: Core %pK already moved to state %d\n",
2192 __func__, core, core->state);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002193 mutex_unlock(&core->lock);
2194 return;
2195 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002196
Maheshwar Ajja99422322017-07-07 17:31:15 -07002197 dprintk(VIDC_WARN, "SYS_ERROR received for core %pK\n", core);
Maheshwar Ajja9ff81a22017-08-05 13:25:55 -07002198 msm_vidc_noc_error_info(core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002199 call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002200 list_for_each_entry(inst, &core->instances, list) {
2201 dprintk(VIDC_WARN,
2202 "%s: Send sys error for inst %pK\n", __func__, inst);
2203 change_inst_state(inst, MSM_VIDC_CORE_INVALID);
2204 msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_SYS_ERROR);
Surajit Poddercd14ed92017-09-12 19:40:56 +05302205 if (!core->trigger_ssr)
2206 msm_comm_print_inst_info(inst);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002207 }
Maheshwar Ajjab94e8192017-10-26 09:34:20 -07002208 /* handle the hw error before core released to get full debug info */
2209 msm_vidc_handle_hw_error(core);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002210 dprintk(VIDC_DBG, "Calling core_release\n");
2211 rc = call_hfi_op(hdev, core_release, hdev->hfi_device_data);
2212 if (rc) {
2213 dprintk(VIDC_ERR, "core_release failed\n");
2214 mutex_unlock(&core->lock);
2215 return;
2216 }
2217 core->state = VIDC_CORE_UNINIT;
2218 mutex_unlock(&core->lock);
2219
Maheshwar Ajjab94e8192017-10-26 09:34:20 -07002220 dprintk(VIDC_WARN, "SYS_ERROR handled.\n");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002221}
2222
2223void msm_comm_session_clean(struct msm_vidc_inst *inst)
2224{
2225 int rc = 0;
2226 struct hfi_device *hdev = NULL;
2227
2228 if (!inst || !inst->core || !inst->core->device) {
2229 dprintk(VIDC_ERR, "%s invalid params\n", __func__);
2230 return;
2231 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002232 if (!inst->session) {
2233 dprintk(VIDC_DBG, "%s: inst %pK session already cleaned\n",
2234 __func__, inst);
2235 return;
2236 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002237
2238 hdev = inst->core->device;
2239 mutex_lock(&inst->lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002240 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
2241 rc = call_hfi_op(hdev, session_clean,
2242 (void *)inst->session);
2243 if (rc) {
2244 dprintk(VIDC_ERR,
2245 "Session clean failed :%pK\n", inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002246 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002247 inst->session = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002248 mutex_unlock(&inst->lock);
2249}
2250
2251static void handle_session_close(enum hal_command_response cmd, void *data)
2252{
2253 struct msm_vidc_cb_cmd_done *response = data;
2254 struct msm_vidc_inst *inst;
2255
2256 if (!response) {
2257 dprintk(VIDC_ERR,
2258 "Failed to get valid response for session close\n");
2259 return;
2260 }
2261
2262 inst = get_inst(get_vidc_core(response->device_id),
2263 response->session_id);
2264 if (!inst) {
2265 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2266 return;
2267 }
2268
2269 signal_session_msg_receipt(cmd, inst);
2270 show_stats(inst);
2271 put_inst(inst);
2272}
2273
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002274struct vb2_buffer *msm_comm_get_vb_using_vidc_buffer(
2275 struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002276{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002277 u32 port = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002278 struct vb2_buffer *vb = NULL;
2279 struct vb2_queue *q = NULL;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002280 bool found = false;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002281
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002282 if (mbuf->vvb.vb2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
2283 port = CAPTURE_PORT;
2284 } else if (mbuf->vvb.vb2_buf.type ==
2285 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
2286 port = OUTPUT_PORT;
2287 } else {
2288 dprintk(VIDC_ERR, "%s: invalid type %d\n",
2289 __func__, mbuf->vvb.vb2_buf.type);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002290 return NULL;
2291 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002292
2293 q = &inst->bufq[port].vb2_bufq;
2294 mutex_lock(&inst->bufq[port].lock);
2295 found = false;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002296 list_for_each_entry(vb, &q->queued_list, queued_entry) {
Maheshwar Ajja58c8c222017-09-13 09:02:53 -07002297 if (vb->state != VB2_BUF_STATE_ACTIVE)
2298 continue;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002299 if (msm_comm_compare_vb2_planes(inst, mbuf, vb)) {
2300 found = true;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002301 break;
2302 }
2303 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002304 mutex_unlock(&inst->bufq[port].lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002305 if (!found) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002306 print_vidc_buffer(VIDC_ERR, "vb2 not found for", inst, mbuf);
2307 return NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002308 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002309
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002310 return vb;
2311}
2312
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002313int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst,
2314 struct vb2_buffer *vb)
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002315{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002316 u32 port;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002317
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002318 if (!inst || !vb) {
2319 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
2320 __func__, inst, vb);
2321 return -EINVAL;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002322 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002323
2324 if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
2325 port = CAPTURE_PORT;
2326 } else if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
2327 port = OUTPUT_PORT;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002328 } else {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002329 dprintk(VIDC_ERR, "%s: invalid type %d\n",
2330 __func__, vb->type);
2331 return -EINVAL;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002332 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002333
2334 mutex_lock(&inst->bufq[port].lock);
2335 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
2336 mutex_unlock(&inst->bufq[port].lock);
2337
2338 return 0;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08002339}
2340
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07002341static bool is_eos_buffer(struct msm_vidc_inst *inst, u32 device_addr)
2342{
2343 struct eos_buf *temp, *next;
2344 bool found = false;
2345
2346 mutex_lock(&inst->eosbufs.lock);
2347 list_for_each_entry_safe(temp, next, &inst->eosbufs.list, list) {
2348 if (temp->smem.device_addr == device_addr) {
2349 found = true;
2350 list_del(&temp->list);
2351 msm_comm_smem_free(inst, &temp->smem);
2352 kfree(temp);
2353 break;
2354 }
2355 }
2356 mutex_unlock(&inst->eosbufs.lock);
2357
2358 return found;
2359}
2360
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002361static void handle_ebd(enum hal_command_response cmd, void *data)
2362{
2363 struct msm_vidc_cb_data_done *response = data;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002364 struct msm_vidc_buffer *mbuf;
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002365 struct vb2_buffer *vb, *vb2;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002366 struct msm_vidc_inst *inst;
2367 struct vidc_hal_ebd *empty_buf_done;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002368 struct vb2_v4l2_buffer *vbuf;
2369 u32 planes[VIDEO_MAX_PLANES] = {0};
2370 u32 extra_idx = 0, i;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002371
2372 if (!response) {
2373 dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
2374 return;
2375 }
2376
2377 inst = get_inst(get_vidc_core(response->device_id),
2378 response->session_id);
2379 if (!inst) {
2380 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2381 return;
2382 }
2383
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002384 empty_buf_done = (struct vidc_hal_ebd *)&response->input_done;
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07002385 /* If this is internal EOS buffer, handle it in driver */
2386 if (is_eos_buffer(inst, empty_buf_done->packet_buffer)) {
Maria Yu5d853f82017-09-26 16:13:19 +08002387 dprintk(VIDC_DBG, "Received EOS buffer 0x%x\n",
2388 empty_buf_done->packet_buffer);
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07002389 goto exit;
2390 }
2391
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002392 planes[0] = empty_buf_done->packet_buffer;
2393 planes[1] = empty_buf_done->extra_data_buffer;
2394
2395 mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002396 if (!mbuf || !kref_get_mbuf(inst, mbuf)) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002397 dprintk(VIDC_ERR,
2398 "%s: data_addr %x, extradata_addr %x not found\n",
2399 __func__, planes[0], planes[1]);
2400 goto exit;
2401 }
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002402 vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
2403
2404 /*
2405 * take registeredbufs.lock to update mbuf & vb2 variables together
2406 * so that both are in sync else if mbuf and vb2 variables are not
2407 * in sync msm_comm_compare_vb2_planes() returns false for the
2408 * right buffer due to data_offset field mismatch.
2409 */
2410 mutex_lock(&inst->registeredbufs.lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002411 vb = &mbuf->vvb.vb2_buf;
2412
2413 vb->planes[0].bytesused = response->input_done.filled_len;
2414 if (vb->planes[0].bytesused > vb->planes[0].length)
2415 dprintk(VIDC_INFO, "bytesused overflow length\n");
2416
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002417 vb->planes[0].data_offset = response->input_done.offset;
2418 if (vb->planes[0].data_offset > vb->planes[0].length)
2419 dprintk(VIDC_INFO, "data_offset overflow length\n");
2420
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002421 if (empty_buf_done->status == VIDC_ERR_NOT_SUPPORTED) {
2422 dprintk(VIDC_INFO, "Failed : Unsupported input stream\n");
2423 mbuf->vvb.flags |= V4L2_QCOM_BUF_INPUT_UNSUPPORTED;
2424 }
2425 if (empty_buf_done->status == VIDC_ERR_BITSTREAM_ERR) {
2426 dprintk(VIDC_INFO, "Failed : Corrupted input stream\n");
2427 mbuf->vvb.flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
2428 }
2429 if (empty_buf_done->flags & HAL_BUFFERFLAG_SYNCFRAME)
2430 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME |
2431 V4L2_BUF_FLAG_KEYFRAME;
2432
2433 extra_idx = EXTRADATA_IDX(inst->bufq[OUTPUT_PORT].num_planes);
2434 if (extra_idx && extra_idx < VIDEO_MAX_PLANES)
2435 vb->planes[extra_idx].bytesused = vb->planes[extra_idx].length;
2436
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002437 if (vb2) {
2438 vbuf = to_vb2_v4l2_buffer(vb2);
2439 vbuf->flags |= mbuf->vvb.flags;
2440 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
2441 vb2->planes[i].bytesused =
2442 mbuf->vvb.vb2_buf.planes[i].bytesused;
2443 vb2->planes[i].data_offset =
2444 mbuf->vvb.vb2_buf.planes[i].data_offset;
2445 }
2446 }
2447 mutex_unlock(&inst->registeredbufs.lock);
2448
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002449 update_recon_stats(inst, &empty_buf_done->recon_stats);
2450 msm_vidc_clear_freq_entry(inst, mbuf->smem[0].device_addr);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002451 /*
2452 * put_buffer should be done before vb2_buffer_done else
2453 * client might queue the same buffer before it is unmapped
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002454 * in put_buffer.
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002455 */
2456 msm_comm_put_vidc_buffer(inst, mbuf);
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002457 msm_comm_vb2_buffer_done(inst, vb2);
Qiwei Liuf7d96082017-10-19 17:51:09 +08002458 msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_EBD);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002459 kref_put_mbuf(mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002460exit:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002461 put_inst(inst);
2462}
2463
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002464static int handle_multi_stream_buffers(struct msm_vidc_inst *inst,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002465 u32 dev_addr)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002466{
2467 struct internal_buf *binfo;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002468 struct msm_smem *smem;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002469 bool found = false;
2470
2471 mutex_lock(&inst->outputbufs.lock);
2472 list_for_each_entry(binfo, &inst->outputbufs.list, list) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002473 smem = &binfo->smem;
2474 if (smem && dev_addr == smem->device_addr) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002475 if (binfo->buffer_ownership == DRIVER) {
2476 dprintk(VIDC_ERR,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002477 "FW returned same buffer: %x\n",
2478 dev_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002479 break;
2480 }
2481 binfo->buffer_ownership = DRIVER;
2482 found = true;
2483 break;
2484 }
2485 }
2486 mutex_unlock(&inst->outputbufs.lock);
2487
2488 if (!found) {
2489 dprintk(VIDC_ERR,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002490 "Failed to find output buffer in queued list: %x\n",
2491 dev_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002492 }
2493
2494 return 0;
2495}
2496
2497enum hal_buffer msm_comm_get_hal_output_buffer(struct msm_vidc_inst *inst)
2498{
2499 if (msm_comm_get_stream_output_mode(inst) ==
2500 HAL_VIDEO_DECODER_SECONDARY)
2501 return HAL_BUFFER_OUTPUT2;
2502 else
2503 return HAL_BUFFER_OUTPUT;
2504}
2505
2506static void handle_fbd(enum hal_command_response cmd, void *data)
2507{
2508 struct msm_vidc_cb_data_done *response = data;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002509 struct msm_vidc_buffer *mbuf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002510 struct msm_vidc_inst *inst;
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002511 struct vb2_buffer *vb, *vb2;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002512 struct vidc_hal_fbd *fill_buf_done;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002513 struct vb2_v4l2_buffer *vbuf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002514 enum hal_buffer buffer_type;
Vaibhav Deshu Venkateshe5800332017-03-21 14:27:11 -07002515 u64 time_usec = 0;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002516 u32 planes[VIDEO_MAX_PLANES] = {0};
2517 u32 extra_idx, i;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002518
2519 if (!response) {
2520 dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
2521 return;
2522 }
2523
2524 inst = get_inst(get_vidc_core(response->device_id),
2525 response->session_id);
2526 if (!inst) {
2527 dprintk(VIDC_WARN, "Got a response for an inactive session\n");
2528 return;
2529 }
2530
2531 fill_buf_done = (struct vidc_hal_fbd *)&response->output_done;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002532 planes[0] = fill_buf_done->packet_buffer1;
2533 planes[1] = fill_buf_done->extra_data_buffer;
2534
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002535 buffer_type = msm_comm_get_hal_output_buffer(inst);
2536 if (fill_buf_done->buffer_type == buffer_type) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002537 mbuf = msm_comm_get_buffer_using_device_planes(inst, planes);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002538 if (!mbuf || !kref_get_mbuf(inst, mbuf)) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002539 dprintk(VIDC_ERR,
2540 "%s: data_addr %x, extradata_addr %x not found\n",
2541 __func__, planes[0], planes[1]);
2542 goto exit;
2543 }
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002544 vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002545 } else {
2546 if (handle_multi_stream_buffers(inst,
2547 fill_buf_done->packet_buffer1))
2548 dprintk(VIDC_ERR,
2549 "Failed : Output buffer not found %pa\n",
2550 &fill_buf_done->packet_buffer1);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002551 goto exit;
2552 }
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002553
2554 /*
2555 * take registeredbufs.lock to update mbuf & vb2 variables together
2556 * so that both are in sync else if mbuf and vb2 variables are not
2557 * in sync msm_comm_compare_vb2_planes() returns false for the
2558 * right buffer due to data_offset field mismatch.
2559 */
2560 mutex_lock(&inst->registeredbufs.lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002561 vb = &mbuf->vvb.vb2_buf;
2562
2563 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME ||
2564 fill_buf_done->flags1 & HAL_BUFFERFLAG_DECODEONLY)
2565 fill_buf_done->filled_len1 = 0;
2566 vb->planes[0].bytesused = fill_buf_done->filled_len1;
2567 if (vb->planes[0].bytesused > vb->planes[0].length)
2568 dprintk(VIDC_INFO,
2569 "fbd:Overflow bytesused = %d; length = %d\n",
2570 vb->planes[0].bytesused,
2571 vb->planes[0].length);
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002572 vb->planes[0].data_offset = fill_buf_done->offset1;
2573 if (vb->planes[0].data_offset > vb->planes[0].length)
2574 dprintk(VIDC_INFO,
2575 "fbd:Overflow data_offset = %d; length = %d\n",
2576 vb->planes[0].data_offset,
2577 vb->planes[0].length);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002578 if (!(fill_buf_done->flags1 & HAL_BUFFERFLAG_TIMESTAMPINVALID)) {
2579 time_usec = fill_buf_done->timestamp_hi;
2580 time_usec = (time_usec << 32) | fill_buf_done->timestamp_lo;
2581 } else {
2582 time_usec = 0;
2583 dprintk(VIDC_DBG,
2584 "Set zero timestamp for buffer %pa, filled: %d, (hi:%u, lo:%u)\n",
2585 &fill_buf_done->packet_buffer1,
2586 fill_buf_done->filled_len1,
2587 fill_buf_done->timestamp_hi,
2588 fill_buf_done->timestamp_lo);
2589 }
2590 vb->timestamp = (time_usec * NSEC_PER_USEC);
2591
Qiwei Liu551a22222017-08-23 15:28:29 +08002592 if (inst->session_type == MSM_VIDC_DECODER) {
2593 msm_comm_store_mark_data(&inst->fbd_data, vb->index,
2594 fill_buf_done->mark_data, fill_buf_done->mark_target);
2595 }
2596
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002597 extra_idx = EXTRADATA_IDX(inst->bufq[CAPTURE_PORT].num_planes);
2598 if (extra_idx && extra_idx < VIDEO_MAX_PLANES)
2599 vb->planes[extra_idx].bytesused = vb->planes[extra_idx].length;
2600
2601 mbuf->vvb.flags = 0;
2602 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_READONLY)
2603 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_READONLY;
2604 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOS)
2605 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_EOS;
2606 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_CODECCONFIG)
2607 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_CODECCONFIG;
2608 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_SYNCFRAME)
2609 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
2610 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOSEQ)
2611 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_EOSEQ;
2612 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DECODEONLY ||
2613 fill_buf_done->flags1 & HAL_BUFFERFLAG_DROP_FRAME)
2614 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_DECODEONLY;
2615 if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DATACORRUPT)
2616 mbuf->vvb.flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
2617 switch (fill_buf_done->picture_type) {
2618 case HAL_PICTURE_IDR:
2619 mbuf->vvb.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
2620 mbuf->vvb.flags |= V4L2_BUF_FLAG_KEYFRAME;
2621 break;
2622 case HAL_PICTURE_I:
2623 mbuf->vvb.flags |= V4L2_BUF_FLAG_KEYFRAME;
2624 break;
2625 case HAL_PICTURE_P:
2626 mbuf->vvb.flags |= V4L2_BUF_FLAG_PFRAME;
2627 break;
2628 case HAL_PICTURE_B:
2629 mbuf->vvb.flags |= V4L2_BUF_FLAG_BFRAME;
2630 break;
2631 case HAL_FRAME_NOTCODED:
2632 case HAL_UNUSED_PICT:
2633 /* Do we need to care about these? */
2634 case HAL_FRAME_YUV:
2635 break;
2636 default:
2637 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002638 }
2639
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002640 if (vb2) {
2641 vbuf = to_vb2_v4l2_buffer(vb2);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002642 vbuf->flags = mbuf->vvb.flags;
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002643 vb2->timestamp = mbuf->vvb.vb2_buf.timestamp;
2644 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
2645 vb2->planes[i].bytesused =
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002646 mbuf->vvb.vb2_buf.planes[i].bytesused;
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002647 vb2->planes[i].data_offset =
2648 mbuf->vvb.vb2_buf.planes[i].data_offset;
2649 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002650 }
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002651 mutex_unlock(&inst->registeredbufs.lock);
2652
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002653 /*
2654 * put_buffer should be done before vb2_buffer_done else
2655 * client might queue the same buffer before it is unmapped
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002656 * in put_buffer.
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002657 */
2658 msm_comm_put_vidc_buffer(inst, mbuf);
Maheshwar Ajjab0d989a2017-07-18 17:33:08 -07002659 msm_comm_vb2_buffer_done(inst, vb2);
Qiwei Liuf7d96082017-10-19 17:51:09 +08002660 msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FBD);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07002661 kref_put_mbuf(mbuf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002662
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07002663exit:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002664 put_inst(inst);
2665}
2666
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002667void handle_cmd_response(enum hal_command_response cmd, void *data)
2668{
2669 dprintk(VIDC_DBG, "Command response = %d\n", cmd);
2670 switch (cmd) {
2671 case HAL_SYS_INIT_DONE:
2672 handle_sys_init_done(cmd, data);
2673 break;
2674 case HAL_SYS_RELEASE_RESOURCE_DONE:
2675 handle_sys_release_res_done(cmd, data);
2676 break;
2677 case HAL_SESSION_INIT_DONE:
2678 handle_session_init_done(cmd, data);
2679 break;
2680 case HAL_SESSION_PROPERTY_INFO:
2681 handle_session_prop_info(cmd, data);
2682 break;
2683 case HAL_SESSION_LOAD_RESOURCE_DONE:
2684 handle_load_resource_done(cmd, data);
2685 break;
2686 case HAL_SESSION_START_DONE:
2687 handle_start_done(cmd, data);
2688 break;
2689 case HAL_SESSION_ETB_DONE:
2690 handle_ebd(cmd, data);
2691 break;
2692 case HAL_SESSION_FTB_DONE:
2693 handle_fbd(cmd, data);
2694 break;
2695 case HAL_SESSION_STOP_DONE:
2696 handle_stop_done(cmd, data);
2697 break;
2698 case HAL_SESSION_RELEASE_RESOURCE_DONE:
2699 handle_release_res_done(cmd, data);
2700 break;
2701 case HAL_SESSION_END_DONE:
2702 case HAL_SESSION_ABORT_DONE:
2703 handle_session_close(cmd, data);
2704 break;
2705 case HAL_SESSION_EVENT_CHANGE:
2706 handle_event_change(cmd, data);
2707 break;
2708 case HAL_SESSION_FLUSH_DONE:
2709 handle_session_flush(cmd, data);
2710 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002711 case HAL_SYS_WATCHDOG_TIMEOUT:
2712 case HAL_SYS_ERROR:
2713 handle_sys_error(cmd, data);
2714 break;
2715 case HAL_SESSION_ERROR:
2716 handle_session_error(cmd, data);
2717 break;
2718 case HAL_SESSION_RELEASE_BUFFER_DONE:
2719 handle_session_release_buf_done(cmd, data);
2720 break;
2721 default:
2722 dprintk(VIDC_DBG, "response unhandled: %d\n", cmd);
2723 break;
2724 }
2725}
2726
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002727static inline enum msm_vidc_thermal_level msm_comm_vidc_thermal_level(int level)
2728{
2729 switch (level) {
2730 case 0:
2731 return VIDC_THERMAL_NORMAL;
2732 case 1:
2733 return VIDC_THERMAL_LOW;
2734 case 2:
2735 return VIDC_THERMAL_HIGH;
2736 default:
2737 return VIDC_THERMAL_CRITICAL;
2738 }
2739}
2740
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002741static bool is_core_turbo(struct msm_vidc_core *core, unsigned long freq)
2742{
2743 int i = 0;
Praneeth Paladugub71968b2015-08-19 20:47:57 -07002744 struct allowed_clock_rates_table *allowed_clks_tbl = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002745 u32 max_freq = 0;
2746
Praneeth Paladugub71968b2015-08-19 20:47:57 -07002747 allowed_clks_tbl = core->resources.allowed_clks_tbl;
2748 for (i = 0; i < core->resources.allowed_clks_tbl_size; i++) {
2749 if (max_freq < allowed_clks_tbl[i].clock_rate)
2750 max_freq = allowed_clks_tbl[i].clock_rate;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002751 }
2752 return freq >= max_freq;
2753}
2754
2755static bool is_thermal_permissible(struct msm_vidc_core *core)
2756{
2757 enum msm_vidc_thermal_level tl;
2758 unsigned long freq = 0;
2759 bool is_turbo = false;
2760
2761 if (!core->resources.thermal_mitigable)
2762 return true;
2763
2764 if (msm_vidc_thermal_mitigation_disabled) {
2765 dprintk(VIDC_DBG,
2766 "Thermal mitigation not enabled. debugfs %d\n",
2767 msm_vidc_thermal_mitigation_disabled);
2768 return true;
2769 }
2770
2771 tl = msm_comm_vidc_thermal_level(vidc_driver->thermal_level);
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07002772 freq = core->curr_freq;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002773
2774 is_turbo = is_core_turbo(core, freq);
2775 dprintk(VIDC_DBG,
2776 "Core freq %ld Thermal level %d Turbo mode %d\n",
2777 freq, tl, is_turbo);
2778
2779 if (is_turbo && tl >= VIDC_THERMAL_LOW) {
2780 dprintk(VIDC_ERR,
2781 "Video session not allowed. Turbo mode %d Thermal level %d\n",
2782 is_turbo, tl);
2783 return false;
2784 }
2785 return true;
2786}
2787
2788static int msm_comm_session_abort(struct msm_vidc_inst *inst)
2789{
2790 int rc = 0, abort_completion = 0;
2791 struct hfi_device *hdev;
2792
2793 if (!inst || !inst->core || !inst->core->device) {
2794 dprintk(VIDC_ERR, "%s invalid params\n", __func__);
2795 return -EINVAL;
2796 }
2797 hdev = inst->core->device;
2798 abort_completion = SESSION_MSG_INDEX(HAL_SESSION_ABORT_DONE);
2799
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07002800 dprintk(VIDC_WARN, "%s: inst %pK session %x\n", __func__,
2801 inst, hash32_ptr(inst->session));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002802 rc = call_hfi_op(hdev, session_abort, (void *)inst->session);
2803 if (rc) {
2804 dprintk(VIDC_ERR,
2805 "%s session_abort failed rc: %d\n", __func__, rc);
Maheshwar Ajja99422322017-07-07 17:31:15 -07002806 goto exit;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002807 }
2808 rc = wait_for_completion_timeout(
2809 &inst->completions[abort_completion],
Praneeth Paladugud5bf7bc2017-05-29 23:41:04 -07002810 msecs_to_jiffies(
2811 inst->core->resources.msm_vidc_hw_rsp_timeout));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002812 if (!rc) {
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07002813 dprintk(VIDC_ERR, "%s: inst %pK session %x abort timed out\n",
2814 __func__, inst, hash32_ptr(inst->session));
Maheshwar Ajja99422322017-07-07 17:31:15 -07002815 msm_comm_generate_sys_error(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002816 rc = -EBUSY;
2817 } else {
2818 rc = 0;
2819 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002820exit:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002821 return rc;
2822}
2823
2824static void handle_thermal_event(struct msm_vidc_core *core)
2825{
2826 int rc = 0;
2827 struct msm_vidc_inst *inst;
2828
2829 if (!core || !core->device) {
2830 dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
2831 return;
2832 }
2833 mutex_lock(&core->lock);
2834 list_for_each_entry(inst, &core->instances, list) {
2835 if (!inst->session)
2836 continue;
2837
2838 mutex_unlock(&core->lock);
2839 if (inst->state >= MSM_VIDC_OPEN_DONE &&
2840 inst->state < MSM_VIDC_CLOSE_DONE) {
2841 dprintk(VIDC_WARN, "%s: abort inst %pK\n",
2842 __func__, inst);
2843 rc = msm_comm_session_abort(inst);
2844 if (rc) {
2845 dprintk(VIDC_ERR,
2846 "%s session_abort failed rc: %d\n",
2847 __func__, rc);
2848 goto err_sess_abort;
2849 }
2850 change_inst_state(inst, MSM_VIDC_CORE_INVALID);
2851 dprintk(VIDC_WARN,
2852 "%s Send sys error for inst %pK\n",
2853 __func__, inst);
2854 msm_vidc_queue_v4l2_event(inst,
2855 V4L2_EVENT_MSM_VIDC_SYS_ERROR);
2856 } else {
2857 msm_comm_generate_session_error(inst);
2858 }
2859 mutex_lock(&core->lock);
2860 }
2861 mutex_unlock(&core->lock);
2862 return;
2863
2864err_sess_abort:
2865 msm_comm_clean_notify_client(core);
2866}
2867
2868void msm_comm_handle_thermal_event(void)
2869{
2870 struct msm_vidc_core *core;
2871
2872 list_for_each_entry(core, &vidc_driver->cores, list) {
2873 if (!is_thermal_permissible(core)) {
2874 dprintk(VIDC_WARN,
2875 "Thermal level critical, stop all active sessions!\n");
2876 handle_thermal_event(core);
2877 }
2878 }
2879}
2880
2881int msm_comm_check_core_init(struct msm_vidc_core *core)
2882{
2883 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002884
2885 mutex_lock(&core->lock);
2886 if (core->state >= VIDC_CORE_INIT_DONE) {
2887 dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
2888 core->id, core->state);
2889 goto exit;
2890 }
2891 dprintk(VIDC_DBG, "Waiting for SYS_INIT_DONE\n");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002892 rc = wait_for_completion_timeout(
2893 &core->completions[SYS_MSG_INDEX(HAL_SYS_INIT_DONE)],
Praneeth Paladugud5bf7bc2017-05-29 23:41:04 -07002894 msecs_to_jiffies(core->resources.msm_vidc_hw_rsp_timeout));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002895 if (!rc) {
2896 dprintk(VIDC_ERR, "%s: Wait interrupted or timed out: %d\n",
2897 __func__, SYS_MSG_INDEX(HAL_SYS_INIT_DONE));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002898 rc = -EIO;
2899 goto exit;
2900 } else {
2901 core->state = VIDC_CORE_INIT_DONE;
2902 rc = 0;
2903 }
2904 dprintk(VIDC_DBG, "SYS_INIT_DONE!!!\n");
2905exit:
2906 mutex_unlock(&core->lock);
2907 return rc;
2908}
2909
2910static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
2911{
2912 int rc = 0;
2913
2914 rc = msm_comm_check_core_init(inst->core);
2915 if (rc) {
2916 dprintk(VIDC_ERR, "%s - failed to initialize core\n", __func__);
2917 msm_comm_generate_sys_error(inst);
2918 return rc;
2919 }
2920 change_inst_state(inst, MSM_VIDC_CORE_INIT_DONE);
2921 return rc;
2922}
2923
2924static int msm_comm_init_core(struct msm_vidc_inst *inst)
2925{
2926 int rc = 0;
2927 struct hfi_device *hdev;
2928 struct msm_vidc_core *core;
2929
2930 if (!inst || !inst->core || !inst->core->device)
2931 return -EINVAL;
2932
2933 core = inst->core;
2934 hdev = core->device;
2935 mutex_lock(&core->lock);
2936 if (core->state >= VIDC_CORE_INIT) {
2937 dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
2938 core->id, core->state);
2939 goto core_already_inited;
2940 }
2941 if (!core->capabilities) {
2942 core->capabilities = kzalloc(VIDC_MAX_SESSIONS *
2943 sizeof(struct msm_vidc_capability), GFP_KERNEL);
2944 if (!core->capabilities) {
2945 dprintk(VIDC_ERR,
2946 "%s: failed to allocate capabilities\n",
2947 __func__);
2948 rc = -ENOMEM;
2949 goto fail_cap_alloc;
2950 }
2951 } else {
2952 dprintk(VIDC_WARN,
2953 "%s: capabilities memory is expected to be freed\n",
2954 __func__);
2955 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07002956 dprintk(VIDC_DBG, "%s: core %pK\n", __func__, core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002957 rc = call_hfi_op(hdev, core_init, hdev->hfi_device_data);
2958 if (rc) {
2959 dprintk(VIDC_ERR, "Failed to init core, id = %d\n",
2960 core->id);
2961 goto fail_core_init;
2962 }
2963 core->state = VIDC_CORE_INIT;
2964 core->smmu_fault_handled = false;
Maheshwar Ajja8382bec2017-08-11 13:41:35 -07002965 core->trigger_ssr = false;
2966
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002967core_already_inited:
2968 change_inst_state(inst, MSM_VIDC_CORE_INIT);
2969 mutex_unlock(&core->lock);
Praneeth Paladugub71968b2015-08-19 20:47:57 -07002970
2971 rc = msm_comm_scale_clocks_and_bus(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002972 return rc;
2973
2974fail_core_init:
2975 kfree(core->capabilities);
2976fail_cap_alloc:
2977 core->capabilities = NULL;
2978 core->state = VIDC_CORE_UNINIT;
2979 mutex_unlock(&core->lock);
2980 return rc;
2981}
2982
2983static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
2984{
2985 struct msm_vidc_core *core;
2986 struct hfi_device *hdev;
2987
2988 if (!inst || !inst->core || !inst->core->device) {
2989 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
2990 return -EINVAL;
2991 }
2992
2993 core = inst->core;
2994 hdev = core->device;
2995
2996 mutex_lock(&core->lock);
2997 if (core->state == VIDC_CORE_UNINIT) {
2998 dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
2999 core->id, core->state);
3000 goto core_already_uninited;
3001 }
3002 mutex_unlock(&core->lock);
3003
3004 msm_comm_scale_clocks_and_bus(inst);
3005
3006 mutex_lock(&core->lock);
3007
3008 if (!core->resources.never_unload_fw) {
3009 cancel_delayed_work(&core->fw_unload_work);
3010
3011 /*
3012 * Delay unloading of firmware. This is useful
3013 * in avoiding firmware download delays in cases where we
3014 * will have a burst of back to back video playback sessions
3015 * e.g. thumbnail generation.
3016 */
3017 schedule_delayed_work(&core->fw_unload_work,
Maheshwar Ajja99422322017-07-07 17:31:15 -07003018 msecs_to_jiffies(core->state == VIDC_CORE_INIT_DONE ?
3019 core->resources.msm_vidc_firmware_unload_delay : 0));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003020
3021 dprintk(VIDC_DBG, "firmware unload delayed by %u ms\n",
Maheshwar Ajja99422322017-07-07 17:31:15 -07003022 core->state == VIDC_CORE_INIT_DONE ?
3023 core->resources.msm_vidc_firmware_unload_delay : 0);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003024 }
3025
3026core_already_uninited:
3027 change_inst_state(inst, MSM_VIDC_CORE_UNINIT);
3028 mutex_unlock(&core->lock);
3029 return 0;
3030}
3031
3032int msm_comm_force_cleanup(struct msm_vidc_inst *inst)
3033{
3034 msm_comm_kill_session(inst);
3035 return msm_vidc_deinit_core(inst);
3036}
3037
Maheshwar Ajjac35d7fc2017-09-01 16:44:46 -07003038static int msm_comm_session_init_done(int flipped_state,
3039 struct msm_vidc_inst *inst)
3040{
3041 int rc;
3042
3043 dprintk(VIDC_DBG, "inst %pK: waiting for session init done\n", inst);
3044 rc = wait_for_state(inst, flipped_state, MSM_VIDC_OPEN_DONE,
3045 HAL_SESSION_INIT_DONE);
3046 if (rc) {
3047 dprintk(VIDC_ERR, "Session init failed for inst %pK\n", inst);
3048 msm_comm_generate_sys_error(inst);
3049 return rc;
3050 }
3051
3052 return rc;
3053}
3054
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003055static int msm_comm_session_init(int flipped_state,
3056 struct msm_vidc_inst *inst)
3057{
3058 int rc = 0;
3059 int fourcc = 0;
3060 struct hfi_device *hdev;
3061
3062 if (!inst || !inst->core || !inst->core->device) {
3063 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3064 return -EINVAL;
3065 }
3066 hdev = inst->core->device;
3067
3068 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_OPEN)) {
3069 dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
3070 inst, inst->state);
3071 goto exit;
3072 }
3073 if (inst->session_type == MSM_VIDC_DECODER) {
3074 fourcc = inst->fmts[OUTPUT_PORT].fourcc;
3075 } else if (inst->session_type == MSM_VIDC_ENCODER) {
3076 fourcc = inst->fmts[CAPTURE_PORT].fourcc;
3077 } else {
3078 dprintk(VIDC_ERR, "Invalid session\n");
3079 return -EINVAL;
3080 }
3081
Praneeth Paladugub71968b2015-08-19 20:47:57 -07003082 msm_comm_init_clocks_and_bus_data(inst);
3083
Maheshwar Ajja99422322017-07-07 17:31:15 -07003084 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003085 rc = call_hfi_op(hdev, session_init, hdev->hfi_device_data,
3086 inst, get_hal_domain(inst->session_type),
3087 get_hal_codec(fourcc),
3088 &inst->session);
3089
3090 if (rc || !inst->session) {
3091 dprintk(VIDC_ERR,
3092 "Failed to call session init for: %pK, %pK, %d, %d\n",
3093 inst->core->device, inst,
3094 inst->session_type, fourcc);
3095 rc = -EINVAL;
3096 goto exit;
3097 }
3098 change_inst_state(inst, MSM_VIDC_OPEN);
3099exit:
3100 return rc;
3101}
3102
3103static void msm_vidc_print_running_insts(struct msm_vidc_core *core)
3104{
3105 struct msm_vidc_inst *temp;
3106
3107 dprintk(VIDC_ERR, "Running instances:\n");
3108 dprintk(VIDC_ERR, "%4s|%4s|%4s|%4s|%4s\n",
3109 "type", "w", "h", "fps", "prop");
3110
3111 mutex_lock(&core->lock);
3112 list_for_each_entry(temp, &core->instances, list) {
3113 if (temp->state >= MSM_VIDC_OPEN_DONE &&
3114 temp->state < MSM_VIDC_STOP_DONE) {
3115 char properties[4] = "";
3116
3117 if (is_thumbnail_session(temp))
3118 strlcat(properties, "N", sizeof(properties));
3119
3120 if (msm_comm_turbo_session(temp))
3121 strlcat(properties, "T", sizeof(properties));
3122
3123 dprintk(VIDC_ERR, "%4d|%4d|%4d|%4d|%4s\n",
3124 temp->session_type,
3125 max(temp->prop.width[CAPTURE_PORT],
3126 temp->prop.width[OUTPUT_PORT]),
3127 max(temp->prop.height[CAPTURE_PORT],
3128 temp->prop.height[OUTPUT_PORT]),
3129 temp->prop.fps, properties);
3130 }
3131 }
3132 mutex_unlock(&core->lock);
3133}
3134
3135static int msm_vidc_load_resources(int flipped_state,
3136 struct msm_vidc_inst *inst)
3137{
3138 int rc = 0;
3139 struct hfi_device *hdev;
3140 int num_mbs_per_sec = 0, max_load_adj = 0;
3141 struct msm_vidc_core *core;
3142 enum load_calc_quirks quirks = LOAD_CALC_IGNORE_TURBO_LOAD |
3143 LOAD_CALC_IGNORE_THUMBNAIL_LOAD |
3144 LOAD_CALC_IGNORE_NON_REALTIME_LOAD;
3145
3146 if (!inst || !inst->core || !inst->core->device) {
3147 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3148 return -EINVAL;
3149 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003150 if (inst->state == MSM_VIDC_CORE_INVALID) {
3151 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07003152 "%s: inst %pK is in invalid state\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003153 return -EINVAL;
3154 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003155 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
3156 dprintk(VIDC_INFO, "inst: %pK is already in state: %d\n",
3157 inst, inst->state);
3158 goto exit;
3159 }
3160 core = inst->core;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003161
3162 num_mbs_per_sec =
3163 msm_comm_get_load(core, MSM_VIDC_DECODER, quirks) +
3164 msm_comm_get_load(core, MSM_VIDC_ENCODER, quirks);
3165
3166 max_load_adj = core->resources.max_load +
3167 inst->capability.mbs_per_frame.max;
3168
3169 if (num_mbs_per_sec > max_load_adj) {
3170 dprintk(VIDC_ERR, "HW is overloaded, needed: %d max: %d\n",
3171 num_mbs_per_sec, max_load_adj);
3172 msm_vidc_print_running_insts(core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003173 msm_comm_kill_session(inst);
3174 return -EBUSY;
3175 }
3176
3177 hdev = core->device;
Maheshwar Ajja99422322017-07-07 17:31:15 -07003178 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003179 rc = call_hfi_op(hdev, session_load_res, (void *) inst->session);
3180 if (rc) {
3181 dprintk(VIDC_ERR,
3182 "Failed to send load resources\n");
3183 goto exit;
3184 }
3185 change_inst_state(inst, MSM_VIDC_LOAD_RESOURCES);
3186exit:
3187 return rc;
3188}
3189
3190static int msm_vidc_start(int flipped_state, struct msm_vidc_inst *inst)
3191{
3192 int rc = 0;
3193 struct hfi_device *hdev;
3194
3195 if (!inst || !inst->core || !inst->core->device) {
3196 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3197 return -EINVAL;
3198 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003199 if (inst->state == MSM_VIDC_CORE_INVALID) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003200 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07003201 "%s: inst %pK is in invalid\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003202 return -EINVAL;
3203 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003204 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_START)) {
3205 dprintk(VIDC_INFO,
3206 "inst: %pK is already in state: %d\n",
3207 inst, inst->state);
3208 goto exit;
3209 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003210 hdev = inst->core->device;
3211 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003212 rc = call_hfi_op(hdev, session_start, (void *) inst->session);
3213 if (rc) {
3214 dprintk(VIDC_ERR,
3215 "Failed to send start\n");
3216 goto exit;
3217 }
3218 change_inst_state(inst, MSM_VIDC_START);
3219exit:
3220 return rc;
3221}
3222
3223static int msm_vidc_stop(int flipped_state, struct msm_vidc_inst *inst)
3224{
3225 int rc = 0;
3226 struct hfi_device *hdev;
3227
3228 if (!inst || !inst->core || !inst->core->device) {
3229 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3230 return -EINVAL;
3231 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003232 if (inst->state == MSM_VIDC_CORE_INVALID) {
3233 dprintk(VIDC_ERR,
3234 "%s: inst %pK is in invalid state\n", __func__, inst);
3235 return -EINVAL;
3236 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003237 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_STOP)) {
3238 dprintk(VIDC_INFO,
3239 "inst: %pK is already in state: %d\n",
3240 inst, inst->state);
3241 goto exit;
3242 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003243 hdev = inst->core->device;
3244 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003245 rc = call_hfi_op(hdev, session_stop, (void *) inst->session);
3246 if (rc) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07003247 dprintk(VIDC_ERR, "%s: inst %pK session_stop failed\n",
3248 __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003249 goto exit;
3250 }
3251 change_inst_state(inst, MSM_VIDC_STOP);
3252exit:
3253 return rc;
3254}
3255
3256static int msm_vidc_release_res(int flipped_state, struct msm_vidc_inst *inst)
3257{
3258 int rc = 0;
3259 struct hfi_device *hdev;
3260
3261 if (!inst || !inst->core || !inst->core->device) {
3262 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
3263 return -EINVAL;
3264 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003265 if (inst->state == MSM_VIDC_CORE_INVALID) {
3266 dprintk(VIDC_ERR,
3267 "%s: inst %pK is in invalid state\n", __func__, inst);
3268 return -EINVAL;
3269 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003270 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_RELEASE_RESOURCES)) {
3271 dprintk(VIDC_INFO,
3272 "inst: %pK is already in state: %d\n",
3273 inst, inst->state);
3274 goto exit;
3275 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003276 hdev = inst->core->device;
3277 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003278 rc = call_hfi_op(hdev, session_release_res, (void *) inst->session);
3279 if (rc) {
3280 dprintk(VIDC_ERR,
3281 "Failed to send release resources\n");
3282 goto exit;
3283 }
3284 change_inst_state(inst, MSM_VIDC_RELEASE_RESOURCES);
3285exit:
3286 return rc;
3287}
3288
3289static int msm_comm_session_close(int flipped_state,
3290 struct msm_vidc_inst *inst)
3291{
3292 int rc = 0;
3293 struct hfi_device *hdev;
3294
3295 if (!inst || !inst->core || !inst->core->device) {
3296 dprintk(VIDC_ERR, "%s invalid params\n", __func__);
3297 return -EINVAL;
3298 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003299 if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_CLOSE)) {
3300 dprintk(VIDC_INFO,
3301 "inst: %pK is already in state: %d\n",
3302 inst, inst->state);
3303 goto exit;
3304 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003305 hdev = inst->core->device;
3306 dprintk(VIDC_DBG, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003307 rc = call_hfi_op(hdev, session_end, (void *) inst->session);
3308 if (rc) {
3309 dprintk(VIDC_ERR,
3310 "Failed to send close\n");
3311 goto exit;
3312 }
3313 change_inst_state(inst, MSM_VIDC_CLOSE);
3314exit:
3315 return rc;
3316}
3317
3318int msm_comm_suspend(int core_id)
3319{
3320 struct hfi_device *hdev;
3321 struct msm_vidc_core *core;
3322 int rc = 0;
3323
3324 core = get_vidc_core(core_id);
3325 if (!core) {
3326 dprintk(VIDC_ERR,
3327 "%s: Failed to find core for core_id = %d\n",
3328 __func__, core_id);
3329 return -EINVAL;
3330 }
3331
3332 hdev = (struct hfi_device *)core->device;
3333 if (!hdev) {
3334 dprintk(VIDC_ERR, "%s Invalid device handle\n", __func__);
3335 return -EINVAL;
3336 }
3337
3338 mutex_lock(&core->lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003339 rc = call_hfi_op(hdev, suspend, hdev->hfi_device_data);
3340 if (rc)
3341 dprintk(VIDC_WARN, "Failed to suspend\n");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003342 mutex_unlock(&core->lock);
Maheshwar Ajja8f604712017-10-13 14:56:43 -07003343
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003344 return rc;
3345}
3346
3347static int get_flipped_state(int present_state,
3348 int desired_state)
3349{
3350 int flipped_state = present_state;
3351
3352 if (flipped_state < MSM_VIDC_STOP
3353 && desired_state > MSM_VIDC_STOP) {
3354 flipped_state = MSM_VIDC_STOP + (MSM_VIDC_STOP - flipped_state);
3355 flipped_state &= 0xFFFE;
3356 flipped_state = flipped_state - 1;
3357 } else if (flipped_state > MSM_VIDC_STOP
3358 && desired_state < MSM_VIDC_STOP) {
3359 flipped_state = MSM_VIDC_STOP -
3360 (flipped_state - MSM_VIDC_STOP + 1);
3361 flipped_state &= 0xFFFE;
3362 flipped_state = flipped_state - 1;
3363 }
3364 return flipped_state;
3365}
3366
3367struct hal_buffer_requirements *get_buff_req_buffer(
3368 struct msm_vidc_inst *inst, enum hal_buffer buffer_type)
3369{
3370 int i;
3371
3372 for (i = 0; i < HAL_BUFFER_MAX; i++) {
3373 if (inst->buff_req.buffer[i].buffer_type == buffer_type)
3374 return &inst->buff_req.buffer[i];
3375 }
3376 return NULL;
3377}
3378
3379static int set_output_buffers(struct msm_vidc_inst *inst,
3380 enum hal_buffer buffer_type)
3381{
3382 int rc = 0;
Chinmay Sawarkarf8ed8422017-09-29 15:51:51 -07003383 struct internal_buf *binfo = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003384 u32 smem_flags = 0, buffer_size;
3385 struct hal_buffer_requirements *output_buf, *extradata_buf;
3386 int i;
3387 struct hfi_device *hdev;
3388 struct hal_buffer_size_minimum b;
3389
3390 hdev = inst->core->device;
3391
3392 output_buf = get_buff_req_buffer(inst, buffer_type);
3393 if (!output_buf) {
3394 dprintk(VIDC_DBG,
3395 "This output buffer not required, buffer_type: %x\n",
3396 buffer_type);
3397 return 0;
3398 }
Praneeth Paladugu86c7c242017-07-16 19:44:42 -07003399
3400 /* For DPB buffers, Always use FW count */
3401 output_buf->buffer_count_actual = output_buf->buffer_count_min_host =
3402 output_buf->buffer_count_min;
3403
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003404 dprintk(VIDC_DBG,
3405 "output: num = %d, size = %d\n",
3406 output_buf->buffer_count_actual,
3407 output_buf->buffer_size);
3408
3409 buffer_size = output_buf->buffer_size;
3410 b.buffer_type = buffer_type;
3411 b.buffer_size = buffer_size;
3412 rc = call_hfi_op(hdev, session_set_property,
3413 inst->session, HAL_PARAM_BUFFER_SIZE_MINIMUM,
3414 &b);
3415
3416 extradata_buf = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_OUTPUT);
3417 if (extradata_buf) {
3418 dprintk(VIDC_DBG,
3419 "extradata: num = %d, size = %d\n",
3420 extradata_buf->buffer_count_actual,
3421 extradata_buf->buffer_size);
3422 buffer_size += extradata_buf->buffer_size;
3423 } else {
3424 dprintk(VIDC_DBG,
3425 "This extradata buffer not required, buffer_type: %x\n",
3426 buffer_type);
3427 }
3428
3429 if (inst->flags & VIDC_SECURE)
3430 smem_flags |= SMEM_SECURE;
3431
3432 if (output_buf->buffer_size) {
3433 for (i = 0; i < output_buf->buffer_count_actual;
3434 i++) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003435 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
3436 if (!binfo) {
3437 dprintk(VIDC_ERR, "Out of memory\n");
3438 rc = -ENOMEM;
3439 goto fail_kzalloc;
3440 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003441 rc = msm_comm_smem_alloc(inst,
3442 buffer_size, 1, smem_flags,
3443 buffer_type, 0, &binfo->smem);
3444 if (rc) {
3445 dprintk(VIDC_ERR,
3446 "Failed to allocate output memory\n");
3447 goto err_no_mem;
3448 }
3449 rc = msm_comm_smem_cache_operations(inst,
3450 &binfo->smem, SMEM_CACHE_CLEAN);
3451 if (rc) {
3452 dprintk(VIDC_WARN,
3453 "Failed to clean cache may cause undefined behavior\n");
3454 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003455 binfo->buffer_type = buffer_type;
3456 binfo->buffer_ownership = DRIVER;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003457 dprintk(VIDC_DBG, "Output buffer address: %#x\n",
3458 binfo->smem.device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003459
3460 if (inst->buffer_mode_set[CAPTURE_PORT] ==
3461 HAL_BUFFER_MODE_STATIC) {
3462 struct vidc_buffer_addr_info buffer_info = {0};
3463
3464 buffer_info.buffer_size =
3465 output_buf->buffer_size;
3466 buffer_info.buffer_type = buffer_type;
3467 buffer_info.num_buffers = 1;
3468 buffer_info.align_device_addr =
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003469 binfo->smem.device_addr;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003470 buffer_info.extradata_addr =
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003471 binfo->smem.device_addr +
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003472 output_buf->buffer_size;
3473 if (extradata_buf)
3474 buffer_info.extradata_size =
3475 extradata_buf->buffer_size;
3476 rc = call_hfi_op(hdev, session_set_buffers,
3477 (void *) inst->session, &buffer_info);
3478 if (rc) {
3479 dprintk(VIDC_ERR,
3480 "%s : session_set_buffers failed\n",
3481 __func__);
3482 goto fail_set_buffers;
3483 }
3484 }
3485 mutex_lock(&inst->outputbufs.lock);
3486 list_add_tail(&binfo->list, &inst->outputbufs.list);
3487 mutex_unlock(&inst->outputbufs.lock);
3488 }
3489 }
3490 return rc;
3491fail_set_buffers:
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003492 msm_comm_smem_free(inst, &binfo->smem);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003493err_no_mem:
Chinmay Sawarkarf8ed8422017-09-29 15:51:51 -07003494 kfree(binfo);
3495fail_kzalloc:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003496 return rc;
3497}
3498
3499static inline char *get_buffer_name(enum hal_buffer buffer_type)
3500{
3501 switch (buffer_type) {
3502 case HAL_BUFFER_INPUT: return "input";
3503 case HAL_BUFFER_OUTPUT: return "output";
3504 case HAL_BUFFER_OUTPUT2: return "output_2";
3505 case HAL_BUFFER_EXTRADATA_INPUT: return "input_extra";
3506 case HAL_BUFFER_EXTRADATA_OUTPUT: return "output_extra";
3507 case HAL_BUFFER_EXTRADATA_OUTPUT2: return "output2_extra";
3508 case HAL_BUFFER_INTERNAL_SCRATCH: return "scratch";
3509 case HAL_BUFFER_INTERNAL_SCRATCH_1: return "scratch_1";
3510 case HAL_BUFFER_INTERNAL_SCRATCH_2: return "scratch_2";
3511 case HAL_BUFFER_INTERNAL_PERSIST: return "persist";
3512 case HAL_BUFFER_INTERNAL_PERSIST_1: return "persist_1";
3513 case HAL_BUFFER_INTERNAL_CMD_QUEUE: return "queue";
3514 default: return "????";
3515 }
3516}
3517
3518static int set_internal_buf_on_fw(struct msm_vidc_inst *inst,
3519 enum hal_buffer buffer_type,
3520 struct msm_smem *handle, bool reuse)
3521{
3522 struct vidc_buffer_addr_info buffer_info;
3523 struct hfi_device *hdev;
3524 int rc = 0;
3525
3526 if (!inst || !inst->core || !inst->core->device || !handle) {
3527 dprintk(VIDC_ERR, "%s - invalid params\n", __func__);
3528 return -EINVAL;
3529 }
3530
3531 hdev = inst->core->device;
3532
3533 rc = msm_comm_smem_cache_operations(inst,
3534 handle, SMEM_CACHE_CLEAN);
3535 if (rc) {
3536 dprintk(VIDC_WARN,
3537 "Failed to clean cache. Undefined behavior\n");
3538 }
3539
3540 buffer_info.buffer_size = handle->size;
3541 buffer_info.buffer_type = buffer_type;
3542 buffer_info.num_buffers = 1;
3543 buffer_info.align_device_addr = handle->device_addr;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003544 dprintk(VIDC_DBG, "%s %s buffer : %x\n",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003545 reuse ? "Reusing" : "Allocated",
3546 get_buffer_name(buffer_type),
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003547 buffer_info.align_device_addr);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003548
3549 rc = call_hfi_op(hdev, session_set_buffers,
3550 (void *) inst->session, &buffer_info);
3551 if (rc) {
3552 dprintk(VIDC_ERR,
3553 "vidc_hal_session_set_buffers failed\n");
3554 return rc;
3555 }
3556 return 0;
3557}
3558
3559static bool reuse_internal_buffers(struct msm_vidc_inst *inst,
3560 enum hal_buffer buffer_type, struct msm_vidc_list *buf_list)
3561{
3562 struct internal_buf *buf;
3563 int rc = 0;
3564 bool reused = false;
3565
3566 if (!inst || !buf_list) {
3567 dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
3568 return false;
3569 }
3570
3571 mutex_lock(&buf_list->lock);
3572 list_for_each_entry(buf, &buf_list->list, list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003573 if (buf->buffer_type != buffer_type)
3574 continue;
3575
3576 /*
3577 * Persist buffer size won't change with resolution. If they
3578 * are in queue means that they are already allocated and
3579 * given to HW. HW can use them without reallocation. These
3580 * buffers are not released as part of port reconfig. So
3581 * driver no need to set them again.
3582 */
3583
3584 if (buffer_type != HAL_BUFFER_INTERNAL_PERSIST
3585 && buffer_type != HAL_BUFFER_INTERNAL_PERSIST_1) {
3586
3587 rc = set_internal_buf_on_fw(inst, buffer_type,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003588 &buf->smem, true);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003589 if (rc) {
3590 dprintk(VIDC_ERR,
3591 "%s: session_set_buffers failed\n",
3592 __func__);
3593 reused = false;
3594 break;
3595 }
3596 }
3597 reused = true;
3598 dprintk(VIDC_DBG,
3599 "Re-using internal buffer type : %d\n", buffer_type);
3600 }
3601 mutex_unlock(&buf_list->lock);
3602 return reused;
3603}
3604
3605static int allocate_and_set_internal_bufs(struct msm_vidc_inst *inst,
3606 struct hal_buffer_requirements *internal_bufreq,
3607 struct msm_vidc_list *buf_list)
3608{
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003609 struct internal_buf *binfo;
3610 u32 smem_flags = 0;
3611 int rc = 0;
3612 int i = 0;
3613
3614 if (!inst || !internal_bufreq || !buf_list)
3615 return -EINVAL;
3616
3617 if (!internal_bufreq->buffer_size)
3618 return 0;
3619
3620 if (inst->flags & VIDC_SECURE)
3621 smem_flags |= SMEM_SECURE;
3622
3623 for (i = 0; i < internal_bufreq->buffer_count_actual; i++) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003624 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
3625 if (!binfo) {
3626 dprintk(VIDC_ERR, "Out of memory\n");
3627 rc = -ENOMEM;
3628 goto fail_kzalloc;
3629 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003630 rc = msm_comm_smem_alloc(inst, internal_bufreq->buffer_size,
3631 1, smem_flags, internal_bufreq->buffer_type,
3632 0, &binfo->smem);
3633 if (rc) {
3634 dprintk(VIDC_ERR,
3635 "Failed to allocate scratch memory\n");
3636 goto err_no_mem;
3637 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003638
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003639 binfo->buffer_type = internal_bufreq->buffer_type;
3640
3641 rc = set_internal_buf_on_fw(inst, internal_bufreq->buffer_type,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003642 &binfo->smem, false);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003643 if (rc)
3644 goto fail_set_buffers;
3645
3646 mutex_lock(&buf_list->lock);
3647 list_add_tail(&binfo->list, &buf_list->list);
3648 mutex_unlock(&buf_list->lock);
3649 }
3650 return rc;
3651
3652fail_set_buffers:
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003653 msm_comm_smem_free(inst, &binfo->smem);
3654err_no_mem:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003655 kfree(binfo);
3656fail_kzalloc:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003657 return rc;
3658
3659}
3660
3661static int set_internal_buffers(struct msm_vidc_inst *inst,
3662 enum hal_buffer buffer_type, struct msm_vidc_list *buf_list)
3663{
3664 struct hal_buffer_requirements *internal_buf;
3665
3666 internal_buf = get_buff_req_buffer(inst, buffer_type);
3667 if (!internal_buf) {
3668 dprintk(VIDC_DBG,
3669 "This internal buffer not required, buffer_type: %x\n",
3670 buffer_type);
3671 return 0;
3672 }
3673
3674 dprintk(VIDC_DBG, "Buffer type %s: num = %d, size = %d\n",
3675 get_buffer_name(buffer_type),
3676 internal_buf->buffer_count_actual, internal_buf->buffer_size);
3677
3678 /*
3679 * Try reusing existing internal buffers first.
3680 * If it's not possible to reuse, allocate new buffers.
3681 */
3682 if (reuse_internal_buffers(inst, buffer_type, buf_list))
3683 return 0;
3684
3685 return allocate_and_set_internal_bufs(inst, internal_buf,
3686 buf_list);
3687}
3688
3689int msm_comm_try_state(struct msm_vidc_inst *inst, int state)
3690{
3691 int rc = 0;
3692 int flipped_state;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003693
3694 if (!inst) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07003695 dprintk(VIDC_ERR, "%s: invalid params %pK", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003696 return -EINVAL;
3697 }
3698 dprintk(VIDC_DBG,
3699 "Trying to move inst: %pK from: %#x to %#x\n",
3700 inst, inst->state, state);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003701
3702 mutex_lock(&inst->sync_lock);
3703 if (inst->state == MSM_VIDC_CORE_INVALID) {
3704 dprintk(VIDC_ERR, "%s: inst %pK is in invalid\n",
3705 __func__, inst);
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07003706 rc = -EINVAL;
3707 goto exit;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003708 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07003709
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003710 flipped_state = get_flipped_state(inst->state, state);
3711 dprintk(VIDC_DBG,
3712 "flipped_state = %#x\n", flipped_state);
3713 switch (flipped_state) {
3714 case MSM_VIDC_CORE_UNINIT_DONE:
3715 case MSM_VIDC_CORE_INIT:
3716 rc = msm_comm_init_core(inst);
3717 if (rc || state <= get_flipped_state(inst->state, state))
3718 break;
3719 case MSM_VIDC_CORE_INIT_DONE:
3720 rc = msm_comm_init_core_done(inst);
3721 if (rc || state <= get_flipped_state(inst->state, state))
3722 break;
3723 case MSM_VIDC_OPEN:
3724 rc = msm_comm_session_init(flipped_state, inst);
3725 if (rc || state <= get_flipped_state(inst->state, state))
3726 break;
3727 case MSM_VIDC_OPEN_DONE:
Maheshwar Ajjac35d7fc2017-09-01 16:44:46 -07003728 rc = msm_comm_session_init_done(flipped_state, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003729 if (rc || state <= get_flipped_state(inst->state, state))
3730 break;
3731 case MSM_VIDC_LOAD_RESOURCES:
3732 rc = msm_vidc_load_resources(flipped_state, inst);
3733 if (rc || state <= get_flipped_state(inst->state, state))
3734 break;
3735 case MSM_VIDC_LOAD_RESOURCES_DONE:
3736 case MSM_VIDC_START:
3737 rc = msm_vidc_start(flipped_state, inst);
3738 if (rc || state <= get_flipped_state(inst->state, state))
3739 break;
3740 case MSM_VIDC_START_DONE:
3741 rc = wait_for_state(inst, flipped_state, MSM_VIDC_START_DONE,
3742 HAL_SESSION_START_DONE);
3743 if (rc || state <= get_flipped_state(inst->state, state))
3744 break;
3745 case MSM_VIDC_STOP:
3746 rc = msm_vidc_stop(flipped_state, inst);
3747 if (rc || state <= get_flipped_state(inst->state, state))
3748 break;
3749 case MSM_VIDC_STOP_DONE:
3750 rc = wait_for_state(inst, flipped_state, MSM_VIDC_STOP_DONE,
3751 HAL_SESSION_STOP_DONE);
3752 if (rc || state <= get_flipped_state(inst->state, state))
3753 break;
3754 dprintk(VIDC_DBG, "Moving to Stop Done state\n");
3755 case MSM_VIDC_RELEASE_RESOURCES:
3756 rc = msm_vidc_release_res(flipped_state, inst);
3757 if (rc || state <= get_flipped_state(inst->state, state))
3758 break;
3759 case MSM_VIDC_RELEASE_RESOURCES_DONE:
3760 rc = wait_for_state(inst, flipped_state,
3761 MSM_VIDC_RELEASE_RESOURCES_DONE,
3762 HAL_SESSION_RELEASE_RESOURCE_DONE);
3763 if (rc || state <= get_flipped_state(inst->state, state))
3764 break;
3765 dprintk(VIDC_DBG,
3766 "Moving to release resources done state\n");
3767 case MSM_VIDC_CLOSE:
3768 rc = msm_comm_session_close(flipped_state, inst);
3769 if (rc || state <= get_flipped_state(inst->state, state))
3770 break;
3771 case MSM_VIDC_CLOSE_DONE:
3772 rc = wait_for_state(inst, flipped_state, MSM_VIDC_CLOSE_DONE,
3773 HAL_SESSION_END_DONE);
3774 if (rc || state <= get_flipped_state(inst->state, state))
3775 break;
3776 msm_comm_session_clean(inst);
3777 case MSM_VIDC_CORE_UNINIT:
3778 case MSM_VIDC_CORE_INVALID:
3779 dprintk(VIDC_DBG, "Sending core uninit\n");
3780 rc = msm_vidc_deinit_core(inst);
3781 if (rc || state == get_flipped_state(inst->state, state))
3782 break;
3783 default:
3784 dprintk(VIDC_ERR, "State not recognized\n");
3785 rc = -EINVAL;
3786 break;
3787 }
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07003788
3789exit:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003790 mutex_unlock(&inst->sync_lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003791
3792 if (rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003793 dprintk(VIDC_ERR,
3794 "Failed to move from state: %d to %d\n",
3795 inst->state, state);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003796 msm_comm_kill_session(inst);
3797 } else {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003798 trace_msm_vidc_common_state_change((void *)inst,
3799 inst->state, state);
Maheshwar Ajja99422322017-07-07 17:31:15 -07003800 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003801 return rc;
3802}
3803
Praneeth Paladugu54865842017-08-18 01:45:27 -07003804int msm_vidc_send_pending_eos_buffers(struct msm_vidc_inst *inst)
3805{
3806 struct vidc_frame_data data = {0};
3807 struct hfi_device *hdev;
3808 struct eos_buf *binfo = NULL, *temp = NULL;
3809 int rc = 0;
3810
3811 if (!inst || !inst->core || !inst->core->device) {
3812 dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
3813 return -EINVAL;
3814 }
3815
3816 mutex_lock(&inst->eosbufs.lock);
3817 list_for_each_entry_safe(binfo, temp, &inst->eosbufs.list, list) {
3818 data.alloc_len = binfo->smem.size;
3819 data.device_addr = binfo->smem.device_addr;
3820 data.clnt_data = data.device_addr;
3821 data.buffer_type = HAL_BUFFER_INPUT;
3822 data.filled_len = 0;
3823 data.offset = 0;
3824 data.flags = HAL_BUFFERFLAG_EOS;
3825 data.timestamp = LLONG_MAX;
3826 data.extradata_addr = data.device_addr;
3827 data.extradata_size = 0;
Maria Yu5d853f82017-09-26 16:13:19 +08003828 dprintk(VIDC_DBG, "Queueing EOS buffer 0x%x\n",
3829 data.device_addr);
Praneeth Paladugu54865842017-08-18 01:45:27 -07003830 hdev = inst->core->device;
3831
3832 rc = call_hfi_op(hdev, session_etb, inst->session,
3833 &data);
3834 }
3835 mutex_unlock(&inst->eosbufs.lock);
3836
3837 return rc;
3838}
3839
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003840int msm_vidc_comm_cmd(void *instance, union msm_v4l2_cmd *cmd)
3841{
3842 struct msm_vidc_inst *inst = instance;
3843 struct v4l2_decoder_cmd *dec = NULL;
3844 struct v4l2_encoder_cmd *enc = NULL;
3845 struct msm_vidc_core *core;
3846 int which_cmd = 0, flags = 0, rc = 0;
3847
3848 if (!inst || !inst->core || !cmd) {
3849 dprintk(VIDC_ERR, "%s invalid params\n", __func__);
3850 return -EINVAL;
3851 }
3852 core = inst->core;
3853 if (inst->session_type == MSM_VIDC_ENCODER) {
3854 enc = (struct v4l2_encoder_cmd *)cmd;
3855 which_cmd = enc->cmd;
3856 flags = enc->flags;
3857 } else if (inst->session_type == MSM_VIDC_DECODER) {
3858 dec = (struct v4l2_decoder_cmd *)cmd;
3859 which_cmd = dec->cmd;
3860 flags = dec->flags;
3861 }
3862
3863
3864 switch (which_cmd) {
3865 case V4L2_QCOM_CMD_FLUSH:
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003866 rc = msm_comm_flush(inst, flags);
3867 if (rc) {
3868 dprintk(VIDC_ERR,
3869 "Failed to flush buffers: %d\n", rc);
3870 }
3871 break;
3872 case V4L2_DEC_QCOM_CMD_RECONFIG_HINT:
3873 {
3874 u32 *ptr = NULL;
3875 struct hal_buffer_requirements *output_buf;
3876
3877 rc = msm_comm_try_get_bufreqs(inst);
3878 if (rc) {
3879 dprintk(VIDC_ERR,
3880 "Getting buffer requirements failed: %d\n",
3881 rc);
3882 break;
3883 }
3884
3885 output_buf = get_buff_req_buffer(inst,
3886 msm_comm_get_hal_output_buffer(inst));
3887 if (output_buf) {
3888 if (dec) {
3889 ptr = (u32 *)dec->raw.data;
3890 ptr[0] = output_buf->buffer_size;
3891 ptr[1] = output_buf->buffer_count_actual;
3892 dprintk(VIDC_DBG,
3893 "Reconfig hint, size is %u, count is %u\n",
3894 ptr[0], ptr[1]);
3895 } else {
3896 dprintk(VIDC_ERR, "Null decoder\n");
3897 }
3898 } else {
3899 dprintk(VIDC_DBG,
3900 "This output buffer not required, buffer_type: %x\n",
3901 HAL_BUFFER_OUTPUT);
3902 }
3903 break;
3904 }
Umesh Pandeybb3fad02017-03-31 16:49:42 -07003905 case V4L2_QCOM_CMD_SESSION_CONTINUE:
3906 {
3907 rc = msm_comm_session_continue(inst);
3908 break;
3909 }
Praneeth Paladugu940228f2017-08-02 13:52:13 -07003910 /* This case also for V4L2_ENC_CMD_STOP */
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003911 case V4L2_DEC_CMD_STOP:
3912 {
Praneeth Paladugu54865842017-08-18 01:45:27 -07003913 struct eos_buf *binfo = NULL;
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003914 u32 smem_flags = 0;
3915
3916 get_inst(inst->core, inst);
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003917
3918 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
3919 if (!binfo) {
3920 dprintk(VIDC_ERR, "%s: Out of memory\n", __func__);
3921 rc = -ENOMEM;
3922 goto exit;
3923 }
3924
3925 if (inst->flags & VIDC_SECURE)
3926 smem_flags |= SMEM_SECURE;
3927
3928 rc = msm_comm_smem_alloc(inst,
3929 SZ_4K, 1, smem_flags,
3930 HAL_BUFFER_INPUT, 0, &binfo->smem);
3931 if (rc) {
3932 dprintk(VIDC_ERR,
3933 "Failed to allocate output memory\n");
Praneeth Paladugu54865842017-08-18 01:45:27 -07003934 rc = -ENOMEM;
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003935 goto exit;
3936 }
3937
3938 mutex_lock(&inst->eosbufs.lock);
3939 list_add_tail(&binfo->list, &inst->eosbufs.list);
3940 mutex_unlock(&inst->eosbufs.lock);
3941
Praneeth Paladugu54865842017-08-18 01:45:27 -07003942 if (inst->state != MSM_VIDC_START_DONE) {
3943 dprintk(VIDC_DBG,
3944 "Inst = %pK is not ready for EOS\n", inst);
3945 goto exit;
3946 }
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003947
Praneeth Paladugu54865842017-08-18 01:45:27 -07003948 rc = msm_vidc_send_pending_eos_buffers(inst);
3949
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07003950exit:
3951 put_inst(inst);
3952 break;
3953 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003954 default:
3955 dprintk(VIDC_ERR, "Unknown Command %d\n", which_cmd);
3956 rc = -ENOTSUPP;
3957 break;
3958 }
3959 return rc;
3960}
3961
3962static void populate_frame_data(struct vidc_frame_data *data,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003963 struct msm_vidc_buffer *mbuf, struct msm_vidc_inst *inst)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003964{
Vaibhav Deshu Venkateshe5800332017-03-21 14:27:11 -07003965 u64 time_usec;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003966 int extra_idx;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003967 struct vb2_buffer *vb;
3968 struct vb2_v4l2_buffer *vbuf;
3969
3970 if (!inst || !mbuf || !data) {
3971 dprintk(VIDC_ERR, "%s: invalid params %pK %pK %pK\n",
3972 __func__, inst, mbuf, data);
3973 return;
3974 }
3975
3976 vb = &mbuf->vvb.vb2_buf;
3977 vbuf = to_vb2_v4l2_buffer(vb);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003978
Vaibhav Deshu Venkateshe5800332017-03-21 14:27:11 -07003979 time_usec = vb->timestamp;
3980 do_div(time_usec, NSEC_PER_USEC);
3981
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003982 data->alloc_len = vb->planes[0].length;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003983 data->device_addr = mbuf->smem[0].device_addr;
Vaibhav Deshu Venkateshe5800332017-03-21 14:27:11 -07003984 data->timestamp = time_usec;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003985 data->flags = 0;
3986 data->clnt_data = data->device_addr;
3987
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07003988 if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08003989 data->buffer_type = HAL_BUFFER_INPUT;
3990 data->filled_len = vb->planes[0].bytesused;
3991 data->offset = vb->planes[0].data_offset;
3992
3993 if (vbuf->flags & V4L2_QCOM_BUF_FLAG_EOS)
3994 data->flags |= HAL_BUFFERFLAG_EOS;
3995
3996 if (vbuf->flags & V4L2_QCOM_BUF_FLAG_CODECCONFIG)
3997 data->flags |= HAL_BUFFERFLAG_CODECCONFIG;
3998
3999 if (vbuf->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY)
4000 data->flags |= HAL_BUFFERFLAG_DECODEONLY;
4001
4002 if (vbuf->flags & V4L2_QCOM_BUF_TIMESTAMP_INVALID)
4003 data->timestamp = LLONG_MAX;
4004
Qiwei Liu551a22222017-08-23 15:28:29 +08004005 if (inst->session_type == MSM_VIDC_DECODER) {
4006 msm_comm_fetch_mark_data(&inst->etb_data, vb->index,
4007 &data->mark_data, &data->mark_target);
4008 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004009
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004010 } else if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004011 data->buffer_type = msm_comm_get_hal_output_buffer(inst);
4012 }
4013
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004014 extra_idx = EXTRADATA_IDX(vb->num_planes);
4015 if (extra_idx && extra_idx < VIDEO_MAX_PLANES) {
4016 data->extradata_addr = mbuf->smem[extra_idx].device_addr;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004017 data->extradata_size = vb->planes[extra_idx].length;
4018 data->flags |= HAL_BUFFERFLAG_EXTRADATA;
4019 }
4020}
4021
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004022static unsigned int count_single_batch(struct msm_vidc_inst *inst,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004023 enum v4l2_buf_type type)
4024{
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004025 int count = 0;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004026 struct msm_vidc_buffer *mbuf = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004027
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004028 mutex_lock(&inst->registeredbufs.lock);
4029 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
4030 if (mbuf->vvb.vb2_buf.type != type)
4031 continue;
4032
4033 /* count only deferred buffers */
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004034 if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED))
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004035 continue;
4036
4037 ++count;
4038
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004039 if (!(mbuf->vvb.flags & V4L2_MSM_BUF_FLAG_DEFER))
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004040 goto found_batch;
4041 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004042 /* don't have a full batch */
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004043 count = 0;
4044
4045found_batch:
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004046 mutex_unlock(&inst->registeredbufs.lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004047 return count;
4048}
4049
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004050static unsigned int count_buffers(struct msm_vidc_inst *inst,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004051 enum v4l2_buf_type type)
4052{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004053 struct msm_vidc_buffer *mbuf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004054 int count = 0;
4055
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004056 mutex_lock(&inst->registeredbufs.lock);
4057 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
4058 if (mbuf->vvb.vb2_buf.type != type)
4059 continue;
4060
4061 /* count only deferred buffers */
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004062 if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED))
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004063 continue;
4064
4065 ++count;
4066 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004067 mutex_unlock(&inst->registeredbufs.lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004068
4069 return count;
4070}
4071
4072static void log_frame(struct msm_vidc_inst *inst, struct vidc_frame_data *data,
4073 enum v4l2_buf_type type)
4074{
Praneeth Paladugub71968b2015-08-19 20:47:57 -07004075
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004076 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
4077 dprintk(VIDC_DBG,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004078 "Sending etb (%x) to hal: filled: %d, ts: %lld, flags = %#x\n",
4079 data->device_addr, data->filled_len,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004080 data->timestamp, data->flags);
4081 msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_ETB);
4082
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004083 } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
4084 dprintk(VIDC_DBG,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004085 "Sending ftb (%x) to hal: size: %d, ts: %lld, flags = %#x\n",
4086 data->device_addr, data->alloc_len,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004087 data->timestamp, data->flags);
4088 msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FTB);
4089 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004090}
4091
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004092enum hal_buffer get_hal_buffer_type(unsigned int type,
4093 unsigned int plane_num)
4094{
4095 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
4096 if (plane_num == 0)
4097 return HAL_BUFFER_INPUT;
4098 else
4099 return HAL_BUFFER_EXTRADATA_INPUT;
4100 } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
4101 if (plane_num == 0)
4102 return HAL_BUFFER_OUTPUT;
4103 else
4104 return HAL_BUFFER_EXTRADATA_OUTPUT;
4105 } else {
4106 return -EINVAL;
4107 }
4108}
4109
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004110static int msm_comm_qbuf_rbr(struct msm_vidc_inst *inst,
4111 struct msm_vidc_buffer *mbuf)
4112{
4113 int rc = 0;
4114 struct hfi_device *hdev;
4115 struct vidc_frame_data frame_data = {0};
4116
4117 if (!inst || !inst->core || !inst->core->device || !mbuf) {
4118 dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
4119 return -EINVAL;
4120 }
4121
4122 hdev = inst->core->device;
4123
4124 if (inst->state == MSM_VIDC_CORE_INVALID) {
4125 dprintk(VIDC_ERR, "%s: inst is in bad state\n", __func__);
4126 return -EINVAL;
4127 }
4128
4129 rc = msm_comm_scale_clocks_and_bus(inst);
4130 populate_frame_data(&frame_data, mbuf, inst);
4131
4132 rc = call_hfi_op(hdev, session_ftb, inst->session, &frame_data);
4133 if (rc) {
4134 dprintk(VIDC_ERR, "Failed to issue ftb: %d\n", rc);
4135 goto err_bad_input;
4136 }
4137
4138 log_frame(inst, &frame_data, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
4139
4140err_bad_input:
4141 return rc;
4142}
4143
4144
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004145/*
4146 * Attempts to queue `vb` to hardware. If, for various reasons, the buffer
4147 * cannot be queued to hardware, the buffer will be staged for commit in the
4148 * pending queue. Once the hardware reaches a good state (or if `vb` is NULL,
4149 * the subsequent *_qbuf will commit the previously staged buffers to hardware.
4150 */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004151int msm_comm_qbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004152{
4153 int rc = 0, capture_count, output_count;
4154 struct msm_vidc_core *core;
4155 struct hfi_device *hdev;
4156 struct {
4157 struct vidc_frame_data *data;
4158 int count;
4159 } etbs, ftbs;
4160 bool defer = false, batch_mode;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004161 struct msm_vidc_buffer *temp = NULL, *next = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004162
4163 if (!inst) {
4164 dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
4165 return -EINVAL;
4166 }
4167
4168 core = inst->core;
4169 hdev = core->device;
4170
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004171 if (inst->state == MSM_VIDC_CORE_INVALID) {
4172 dprintk(VIDC_ERR, "%s: inst is in bad state\n", __func__);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004173 return -EINVAL;
4174 }
4175
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004176 batch_mode = msm_comm_g_ctrl_for_id(inst, V4L2_CID_VIDC_QBUF_MODE)
4177 == V4L2_VIDC_QBUF_BATCHED;
4178 capture_count = (batch_mode ? &count_single_batch : &count_buffers)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004179 (inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004180 output_count = (batch_mode ? &count_single_batch : &count_buffers)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004181 (inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004182
Maheshwar Ajja98557a22017-10-30 18:23:39 -07004183 if (!batch_mode && mbuf) {
4184 /*
4185 * don't queue output_mplane buffers if buffer queued
4186 * by client is capture_mplane type and vice versa.
4187 */
4188 if (mbuf->vvb.vb2_buf.type ==
4189 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
4190 output_count = 0;
4191 else if (mbuf->vvb.vb2_buf.type ==
4192 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
4193 capture_count = 0;
4194 }
4195
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004196 /*
4197 * Somewhat complicated logic to prevent queuing the buffer to hardware.
4198 * Don't queue if:
4199 * 1) Hardware isn't ready (that's simple)
4200 */
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -07004201 defer = defer ? defer : (inst->state != MSM_VIDC_START_DONE);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004202
4203 /*
4204 * 2) The client explicitly tells us not to because it wants this
4205 * buffer to be batched with future frames. The batch size (on both
4206 * capabilities) is completely determined by the client.
4207 */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004208 defer = defer ? defer :
4209 (mbuf && mbuf->vvb.flags & V4L2_MSM_BUF_FLAG_DEFER);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004210
4211 /* 3) If we're in batch mode, we must have full batches of both types */
Chinmay Sawarkarcbd3f592017-04-10 15:42:30 -07004212 defer = defer ? defer:(batch_mode && (!output_count || !capture_count));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004213
4214 if (defer) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004215 if (mbuf) {
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004216 mbuf->flags |= MSM_VIDC_FLAG_DEFERRED;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004217 print_vidc_buffer(VIDC_DBG, "deferred qbuf",
4218 inst, mbuf);
4219 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004220 return 0;
4221 }
4222
Praneeth Paladugub71968b2015-08-19 20:47:57 -07004223 rc = msm_comm_scale_clocks_and_bus(inst);
4224
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004225 dprintk(VIDC_DBG, "%sing %d etbs and %d ftbs\n",
4226 batch_mode ? "Batch" : "Process",
4227 output_count, capture_count);
4228
4229 etbs.data = kcalloc(output_count, sizeof(*etbs.data), GFP_KERNEL);
4230 ftbs.data = kcalloc(capture_count, sizeof(*ftbs.data), GFP_KERNEL);
4231 /*
4232 * Note that it's perfectly normal for (e|f)tbs.data to be NULL if
4233 * we're not in batch mode (i.e. (output|capture)_count == 0)
4234 */
4235 if ((!etbs.data && output_count) ||
4236 (!ftbs.data && capture_count)) {
4237 dprintk(VIDC_ERR, "Failed to alloc memory for batching\n");
4238 kfree(etbs.data);
4239 etbs.data = NULL;
4240
4241 kfree(ftbs.data);
4242 ftbs.data = NULL;
4243 goto err_no_mem;
4244 }
4245
4246 etbs.count = ftbs.count = 0;
4247
4248 /*
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004249 * Try to collect all deferred buffers into 2 batches of ftb and etb
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004250 * Note that these "batches" might be empty if we're no in batching mode
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004251 * and the deferred is not set for buffers.
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004252 */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004253 mutex_lock(&inst->registeredbufs.lock);
4254 list_for_each_entry_safe(temp, next, &inst->registeredbufs.list, list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004255 struct vidc_frame_data *frame_data = NULL;
4256
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004257 if (!(temp->flags & MSM_VIDC_FLAG_DEFERRED))
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004258 continue;
4259
4260 switch (temp->vvb.vb2_buf.type) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004261 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
4262 if (ftbs.count < capture_count && ftbs.data)
4263 frame_data = &ftbs.data[ftbs.count++];
4264 break;
4265 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
4266 if (etbs.count < output_count && etbs.data)
4267 frame_data = &etbs.data[etbs.count++];
4268 break;
4269 default:
4270 break;
4271 }
4272
4273 if (!frame_data)
4274 continue;
4275
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004276 populate_frame_data(frame_data, temp, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004277
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004278 /* this buffer going to be queued (not deferred) */
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07004279 temp->flags &= ~MSM_VIDC_FLAG_DEFERRED;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004280
4281 print_vidc_buffer(VIDC_DBG, "qbuf", inst, temp);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004282 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004283 mutex_unlock(&inst->registeredbufs.lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004284
4285 /* Finally commit all our frame(s) to H/W */
4286 if (batch_mode) {
4287 int ftb_index = 0, c = 0;
4288
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004289 ftb_index = c;
4290 rc = call_hfi_op(hdev, session_process_batch, inst->session,
4291 etbs.count, etbs.data,
4292 ftbs.count - ftb_index, &ftbs.data[ftb_index]);
4293 if (rc) {
4294 dprintk(VIDC_ERR,
4295 "Failed to queue batch of %d ETBs and %d FTBs\n",
4296 etbs.count, ftbs.count);
4297 goto err_bad_input;
4298 }
4299
4300 for (c = ftb_index; c < ftbs.count; ++c) {
4301 log_frame(inst, &ftbs.data[c],
4302 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
4303 }
4304
4305 for (c = 0; c < etbs.count; ++c) {
4306 log_frame(inst, &etbs.data[c],
4307 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
4308 }
4309 }
4310
4311 if (!batch_mode && etbs.count) {
4312 int c = 0;
4313
4314 for (c = 0; c < etbs.count; ++c) {
4315 struct vidc_frame_data *frame_data = &etbs.data[c];
4316
4317 rc = call_hfi_op(hdev, session_etb, inst->session,
4318 frame_data);
4319 if (rc) {
4320 dprintk(VIDC_ERR, "Failed to issue etb: %d\n",
4321 rc);
4322 goto err_bad_input;
4323 }
4324
4325 log_frame(inst, frame_data,
4326 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
4327 }
4328 }
4329
4330 if (!batch_mode && ftbs.count) {
4331 int c = 0;
4332
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004333 for (; c < ftbs.count; ++c) {
4334 struct vidc_frame_data *frame_data = &ftbs.data[c];
4335
4336 rc = call_hfi_op(hdev, session_ftb,
4337 inst->session, frame_data);
4338 if (rc) {
4339 dprintk(VIDC_ERR, "Failed to issue ftb: %d\n",
4340 rc);
4341 goto err_bad_input;
4342 }
4343
4344 log_frame(inst, frame_data,
4345 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
4346 }
4347 }
4348
4349err_bad_input:
4350 if (rc)
4351 dprintk(VIDC_ERR, "Failed to queue buffer\n");
4352
4353 kfree(etbs.data);
4354 kfree(ftbs.data);
4355err_no_mem:
4356 return rc;
4357}
4358
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07004359int msm_vidc_update_host_buff_counts(struct msm_vidc_inst *inst)
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004360{
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004361 int extra_buffers;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004362 struct hal_buffer_requirements *bufreq;
4363
4364 bufreq = get_buff_req_buffer(inst,
4365 HAL_BUFFER_INPUT);
4366 if (!bufreq) {
4367 dprintk(VIDC_ERR,
4368 "Failed : No buffer requirements : %x\n",
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004369 HAL_BUFFER_INPUT);
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004370 return -EINVAL;
4371 }
4372 extra_buffers = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_INPUT);
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004373 bufreq->buffer_count_min_host = bufreq->buffer_count_min +
4374 extra_buffers;
Maheshwar Ajja83fec052017-07-25 11:18:38 -07004375 bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT);
4376 if (bufreq) {
4377 if (bufreq->buffer_count_min)
4378 bufreq->buffer_count_min_host =
4379 bufreq->buffer_count_min + extra_buffers;
4380 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004381
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004382 if (msm_comm_get_stream_output_mode(inst) ==
4383 HAL_VIDEO_DECODER_SECONDARY) {
4384
4385 bufreq = get_buff_req_buffer(inst,
4386 HAL_BUFFER_OUTPUT);
4387 if (!bufreq) {
4388 dprintk(VIDC_ERR,
4389 "Failed : No buffer requirements : %x\n",
4390 HAL_BUFFER_OUTPUT);
4391 return -EINVAL;
4392 }
4393
4394 /* For DPB buffers, no need to add Extra buffers */
Praneeth Paladugu6e637472017-05-16 16:06:46 -07004395 bufreq->buffer_count_min_host = bufreq->buffer_count_actual =
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004396 bufreq->buffer_count_min;
4397
4398 bufreq = get_buff_req_buffer(inst,
4399 HAL_BUFFER_OUTPUT2);
4400 if (!bufreq) {
4401 dprintk(VIDC_ERR,
4402 "Failed : No buffer requirements : %x\n",
4403 HAL_BUFFER_OUTPUT2);
4404 return -EINVAL;
4405 }
4406
4407 extra_buffers = msm_vidc_get_extra_buff_count(inst,
4408 HAL_BUFFER_OUTPUT);
4409
Praneeth Paladugu6e637472017-05-16 16:06:46 -07004410 bufreq->buffer_count_min_host = bufreq->buffer_count_actual =
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004411 bufreq->buffer_count_min + extra_buffers;
Chinmay Sawarkaraa84fae2017-06-27 12:39:51 -07004412
4413 bufreq = get_buff_req_buffer(inst,
4414 HAL_BUFFER_EXTRADATA_OUTPUT2);
4415 if (!bufreq) {
4416 dprintk(VIDC_DBG,
4417 "No buffer requirements : %x\n",
4418 HAL_BUFFER_EXTRADATA_OUTPUT2);
4419 } else {
4420 if (bufreq->buffer_count_min) {
4421 bufreq->buffer_count_min_host =
4422 bufreq->buffer_count_actual =
4423 bufreq->buffer_count_min + extra_buffers;
4424 }
4425 }
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004426 } else {
4427
4428 bufreq = get_buff_req_buffer(inst,
4429 HAL_BUFFER_OUTPUT);
4430 if (!bufreq) {
4431 dprintk(VIDC_ERR,
4432 "Failed : No buffer requirements : %x\n",
4433 HAL_BUFFER_OUTPUT);
4434 return -EINVAL;
4435 }
4436
4437 extra_buffers = msm_vidc_get_extra_buff_count(inst,
4438 HAL_BUFFER_OUTPUT);
4439
Praneeth Paladugu6e637472017-05-16 16:06:46 -07004440 bufreq->buffer_count_min_host = bufreq->buffer_count_actual =
Praneeth Paladugubdf4a2f2017-04-21 13:32:49 -07004441 bufreq->buffer_count_min + extra_buffers;
Chinmay Sawarkaraa84fae2017-06-27 12:39:51 -07004442
4443 bufreq = get_buff_req_buffer(inst,
4444 HAL_BUFFER_EXTRADATA_OUTPUT);
4445 if (!bufreq) {
4446 dprintk(VIDC_DBG,
4447 "No buffer requirements : %x\n",
4448 HAL_BUFFER_EXTRADATA_OUTPUT);
4449 } else {
4450 if (bufreq->buffer_count_min) {
4451 bufreq->buffer_count_min_host =
4452 bufreq->buffer_count_actual =
4453 bufreq->buffer_count_min + extra_buffers;
4454 }
4455 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004456 }
4457
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004458 return 0;
4459}
4460
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004461int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst)
4462{
4463 int rc = 0, i = 0;
4464 union hal_get_property hprop;
4465
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004466 memset(&hprop, 0x0, sizeof(hprop));
4467
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004468 rc = msm_comm_try_get_prop(inst, HAL_PARAM_GET_BUFFER_REQUIREMENTS,
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004469 &hprop);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004470 if (rc) {
4471 dprintk(VIDC_ERR, "Failed getting buffer requirements: %d", rc);
4472 return rc;
4473 }
4474
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004475 dprintk(VIDC_DBG, "Buffer requirements from HW:\n");
4476 dprintk(VIDC_DBG, "%15s %8s %8s %8s %8s\n",
4477 "buffer type", "count", "mincount_host", "mincount_fw", "size");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004478 for (i = 0; i < HAL_BUFFER_MAX; i++) {
4479 struct hal_buffer_requirements req = hprop.buf_req.buffer[i];
4480
4481 inst->buff_req.buffer[i] = req;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004482 if (req.buffer_type != HAL_BUFFER_NONE) {
4483 dprintk(VIDC_DBG, "%15s %8d %8d %8d %8d\n",
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004484 get_buffer_name(req.buffer_type),
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004485 req.buffer_count_actual,
4486 req.buffer_count_min_host,
4487 req.buffer_count_min, req.buffer_size);
4488 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004489 }
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07004490 if (inst->session_type == MSM_VIDC_ENCODER)
4491 rc = msm_vidc_update_host_buff_counts(inst);
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004492
4493 dprintk(VIDC_DBG, "Buffer requirements host adjusted:\n");
4494 dprintk(VIDC_DBG, "%15s %8s %8s %8s %8s\n",
4495 "buffer type", "count", "mincount_host", "mincount_fw", "size");
4496 for (i = 0; i < HAL_BUFFER_MAX; i++) {
Praneeth Paladugu13c90962017-04-24 13:15:28 -07004497 struct hal_buffer_requirements req = inst->buff_req.buffer[i];
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004498
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07004499 if (req.buffer_type != HAL_BUFFER_NONE) {
4500 dprintk(VIDC_DBG, "%15s %8d %8d %8d %8d\n",
4501 get_buffer_name(req.buffer_type),
4502 req.buffer_count_actual,
4503 req.buffer_count_min_host,
4504 req.buffer_count_min, req.buffer_size);
4505 }
4506 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004507 return rc;
4508}
4509
4510int msm_comm_try_get_prop(struct msm_vidc_inst *inst, enum hal_property ptype,
4511 union hal_get_property *hprop)
4512{
4513 int rc = 0;
4514 struct hfi_device *hdev;
4515 struct getprop_buf *buf;
4516
4517 if (!inst || !inst->core || !inst->core->device) {
4518 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4519 return -EINVAL;
4520 }
4521
4522 hdev = inst->core->device;
4523 mutex_lock(&inst->sync_lock);
4524 if (inst->state < MSM_VIDC_OPEN_DONE ||
4525 inst->state >= MSM_VIDC_CLOSE) {
4526
4527 /* No need to check inst->state == MSM_VIDC_INVALID since
4528 * INVALID is > CLOSE_DONE. When core went to INVALID state,
4529 * we put all the active instances in INVALID. So > CLOSE_DONE
4530 * is enough check to have.
4531 */
4532
4533 dprintk(VIDC_ERR,
4534 "In Wrong state to call Buf Req: Inst %pK or Core %pK\n",
4535 inst, inst->core);
4536 rc = -EAGAIN;
4537 mutex_unlock(&inst->sync_lock);
4538 goto exit;
4539 }
4540 mutex_unlock(&inst->sync_lock);
4541
4542 switch (ptype) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004543 case HAL_PARAM_GET_BUFFER_REQUIREMENTS:
4544 rc = call_hfi_op(hdev, session_get_buf_req, inst->session);
4545 break;
4546 default:
4547 rc = -EAGAIN;
4548 break;
4549 }
4550
4551 if (rc) {
4552 dprintk(VIDC_ERR, "Can't query hardware for property: %d\n",
4553 rc);
4554 goto exit;
4555 }
4556
4557 rc = wait_for_completion_timeout(&inst->completions[
4558 SESSION_MSG_INDEX(HAL_SESSION_PROPERTY_INFO)],
Praneeth Paladugud5bf7bc2017-05-29 23:41:04 -07004559 msecs_to_jiffies(
4560 inst->core->resources.msm_vidc_hw_rsp_timeout));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004561 if (!rc) {
4562 dprintk(VIDC_ERR,
4563 "%s: Wait interrupted or timed out [%pK]: %d\n",
4564 __func__, inst,
4565 SESSION_MSG_INDEX(HAL_SESSION_PROPERTY_INFO));
Surajit Podder878ede02017-02-07 12:20:10 +05304566 msm_comm_kill_session(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004567 rc = -ETIMEDOUT;
4568 goto exit;
4569 } else {
4570 /* wait_for_completion_timeout returns jiffies before expiry */
4571 rc = 0;
4572 }
4573
4574 mutex_lock(&inst->pending_getpropq.lock);
4575 if (!list_empty(&inst->pending_getpropq.list)) {
4576 buf = list_first_entry(&inst->pending_getpropq.list,
4577 struct getprop_buf, list);
4578 *hprop = *(union hal_get_property *)buf->data;
4579 kfree(buf->data);
4580 list_del(&buf->list);
4581 kfree(buf);
4582 } else {
4583 dprintk(VIDC_ERR, "%s getprop list empty\n", __func__);
4584 rc = -EINVAL;
4585 }
4586 mutex_unlock(&inst->pending_getpropq.lock);
4587exit:
4588 return rc;
4589}
4590
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004591int msm_comm_release_output_buffers(struct msm_vidc_inst *inst,
4592 bool force_release)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004593{
4594 struct msm_smem *handle;
4595 struct internal_buf *buf, *dummy;
4596 struct vidc_buffer_addr_info buffer_info;
4597 int rc = 0;
4598 struct msm_vidc_core *core;
4599 struct hfi_device *hdev;
4600
4601 if (!inst) {
4602 dprintk(VIDC_ERR,
4603 "Invalid instance pointer = %pK\n", inst);
4604 return -EINVAL;
4605 }
4606 mutex_lock(&inst->outputbufs.lock);
4607 if (list_empty(&inst->outputbufs.list)) {
4608 dprintk(VIDC_DBG, "%s - No OUTPUT buffers allocated\n",
4609 __func__);
4610 mutex_unlock(&inst->outputbufs.lock);
4611 return 0;
4612 }
4613 mutex_unlock(&inst->outputbufs.lock);
4614
4615 core = inst->core;
4616 if (!core) {
4617 dprintk(VIDC_ERR,
4618 "Invalid core pointer = %pK\n", core);
4619 return -EINVAL;
4620 }
4621 hdev = core->device;
4622 if (!hdev) {
4623 dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev);
4624 return -EINVAL;
4625 }
4626 mutex_lock(&inst->outputbufs.lock);
4627 list_for_each_entry_safe(buf, dummy, &inst->outputbufs.list, list) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004628 handle = &buf->smem;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004629
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004630 if ((buf->buffer_ownership == FIRMWARE) && !force_release) {
4631 dprintk(VIDC_INFO, "DPB is with f/w. Can't free it\n");
4632 continue;
4633 }
4634
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004635 buffer_info.buffer_size = handle->size;
4636 buffer_info.buffer_type = buf->buffer_type;
4637 buffer_info.num_buffers = 1;
4638 buffer_info.align_device_addr = handle->device_addr;
4639 if (inst->buffer_mode_set[CAPTURE_PORT] ==
Maheshwar Ajja99422322017-07-07 17:31:15 -07004640 HAL_BUFFER_MODE_STATIC) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004641 buffer_info.response_required = false;
4642 rc = call_hfi_op(hdev, session_release_buffers,
4643 (void *)inst->session, &buffer_info);
4644 if (rc) {
4645 dprintk(VIDC_WARN,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004646 "Rel output buf fail:%x, %d\n",
4647 buffer_info.align_device_addr,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004648 buffer_info.buffer_size);
4649 }
4650 }
4651
4652 list_del(&buf->list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004653 msm_comm_smem_free(inst, &buf->smem);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004654 kfree(buf);
4655 }
4656
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004657 mutex_unlock(&inst->outputbufs.lock);
4658 return rc;
4659}
4660
4661static enum hal_buffer scratch_buf_sufficient(struct msm_vidc_inst *inst,
4662 enum hal_buffer buffer_type)
4663{
4664 struct hal_buffer_requirements *bufreq = NULL;
4665 struct internal_buf *buf;
4666 int count = 0;
4667
4668 if (!inst) {
4669 dprintk(VIDC_ERR, "%s - invalid param\n", __func__);
4670 goto not_sufficient;
4671 }
4672
4673 bufreq = get_buff_req_buffer(inst, buffer_type);
4674 if (!bufreq)
4675 goto not_sufficient;
4676
4677 /* Check if current scratch buffers are sufficient */
4678 mutex_lock(&inst->scratchbufs.lock);
4679
4680 list_for_each_entry(buf, &inst->scratchbufs.list, list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004681 if (buf->buffer_type == buffer_type &&
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004682 buf->smem.size >= bufreq->buffer_size)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004683 count++;
4684 }
4685 mutex_unlock(&inst->scratchbufs.lock);
4686
4687 if (count != bufreq->buffer_count_actual)
4688 goto not_sufficient;
4689
4690 dprintk(VIDC_DBG,
4691 "Existing scratch buffer is sufficient for buffer type %#x\n",
4692 buffer_type);
4693
4694 return buffer_type;
4695
4696not_sufficient:
4697 return HAL_BUFFER_NONE;
4698}
4699
4700int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst,
4701 bool check_for_reuse)
4702{
4703 struct msm_smem *handle;
4704 struct internal_buf *buf, *dummy;
4705 struct vidc_buffer_addr_info buffer_info;
4706 int rc = 0;
4707 struct msm_vidc_core *core;
4708 struct hfi_device *hdev;
4709 enum hal_buffer sufficiency = HAL_BUFFER_NONE;
4710
4711 if (!inst) {
4712 dprintk(VIDC_ERR,
4713 "Invalid instance pointer = %pK\n", inst);
4714 return -EINVAL;
4715 }
4716 core = inst->core;
4717 if (!core) {
4718 dprintk(VIDC_ERR,
4719 "Invalid core pointer = %pK\n", core);
4720 return -EINVAL;
4721 }
4722 hdev = core->device;
4723 if (!hdev) {
4724 dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev);
4725 return -EINVAL;
4726 }
4727
4728 if (check_for_reuse) {
4729 sufficiency |= scratch_buf_sufficient(inst,
4730 HAL_BUFFER_INTERNAL_SCRATCH);
4731
4732 sufficiency |= scratch_buf_sufficient(inst,
4733 HAL_BUFFER_INTERNAL_SCRATCH_1);
4734
4735 sufficiency |= scratch_buf_sufficient(inst,
4736 HAL_BUFFER_INTERNAL_SCRATCH_2);
4737 }
4738
4739 mutex_lock(&inst->scratchbufs.lock);
4740 list_for_each_entry_safe(buf, dummy, &inst->scratchbufs.list, list) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004741 handle = &buf->smem;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004742 buffer_info.buffer_size = handle->size;
4743 buffer_info.buffer_type = buf->buffer_type;
4744 buffer_info.num_buffers = 1;
4745 buffer_info.align_device_addr = handle->device_addr;
Maheshwar Ajja99422322017-07-07 17:31:15 -07004746 buffer_info.response_required = true;
4747 rc = call_hfi_op(hdev, session_release_buffers,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004748 (void *)inst->session, &buffer_info);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004749 if (!rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004750 mutex_unlock(&inst->scratchbufs.lock);
4751 rc = wait_for_sess_signal_receipt(inst,
4752 HAL_SESSION_RELEASE_BUFFER_DONE);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004753 if (rc)
4754 dprintk(VIDC_WARN,
4755 "%s: wait for signal failed, rc %d\n",
4756 __func__, rc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004757 mutex_lock(&inst->scratchbufs.lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004758 } else {
4759 dprintk(VIDC_WARN,
4760 "Rel scrtch buf fail:%x, %d\n",
4761 buffer_info.align_device_addr,
4762 buffer_info.buffer_size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004763 }
4764
4765 /*If scratch buffers can be reused, do not free the buffers*/
4766 if (sufficiency & buf->buffer_type)
4767 continue;
4768
4769 list_del(&buf->list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004770 msm_comm_smem_free(inst, handle);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004771 kfree(buf);
4772 }
4773
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004774 mutex_unlock(&inst->scratchbufs.lock);
4775 return rc;
4776}
4777
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07004778void msm_comm_release_eos_buffers(struct msm_vidc_inst *inst)
4779{
4780 struct eos_buf *buf, *next;
4781
4782 if (!inst) {
4783 dprintk(VIDC_ERR,
4784 "Invalid instance pointer = %pK\n", inst);
4785 return;
4786 }
4787
4788 mutex_lock(&inst->eosbufs.lock);
4789 list_for_each_entry_safe(buf, next, &inst->eosbufs.list, list) {
4790 list_del(&buf->list);
Maheshwar Ajjaaf35ac12017-09-18 09:59:38 -07004791 msm_comm_smem_free(inst, &buf->smem);
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07004792 kfree(buf);
4793 }
4794 INIT_LIST_HEAD(&inst->eosbufs.list);
4795 mutex_unlock(&inst->eosbufs.lock);
4796}
4797
4798
Praneeth Paladugu319e7922017-03-16 11:09:06 -07004799int msm_comm_release_recon_buffers(struct msm_vidc_inst *inst)
4800{
4801 struct recon_buf *buf, *next;
4802
4803 if (!inst) {
4804 dprintk(VIDC_ERR,
4805 "Invalid instance pointer = %pK\n", inst);
4806 return -EINVAL;
4807 }
4808
4809 mutex_lock(&inst->reconbufs.lock);
4810 list_for_each_entry_safe(buf, next, &inst->reconbufs.list, list) {
4811 list_del(&buf->list);
4812 kfree(buf);
4813 }
4814 INIT_LIST_HEAD(&inst->reconbufs.list);
4815 mutex_unlock(&inst->reconbufs.lock);
4816
4817 return 0;
4818}
4819
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004820int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst)
4821{
4822 struct msm_smem *handle;
4823 struct list_head *ptr, *next;
4824 struct internal_buf *buf;
4825 struct vidc_buffer_addr_info buffer_info;
4826 int rc = 0;
4827 struct msm_vidc_core *core;
4828 struct hfi_device *hdev;
4829
4830 if (!inst) {
4831 dprintk(VIDC_ERR,
4832 "Invalid instance pointer = %pK\n", inst);
4833 return -EINVAL;
4834 }
4835 core = inst->core;
4836 if (!core) {
4837 dprintk(VIDC_ERR,
4838 "Invalid core pointer = %pK\n", core);
4839 return -EINVAL;
4840 }
4841 hdev = core->device;
4842 if (!hdev) {
4843 dprintk(VIDC_ERR, "Invalid device pointer = %pK\n", hdev);
4844 return -EINVAL;
4845 }
4846
4847 mutex_lock(&inst->persistbufs.lock);
4848 list_for_each_safe(ptr, next, &inst->persistbufs.list) {
4849 buf = list_entry(ptr, struct internal_buf, list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004850 handle = &buf->smem;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004851 buffer_info.buffer_size = handle->size;
4852 buffer_info.buffer_type = buf->buffer_type;
4853 buffer_info.num_buffers = 1;
4854 buffer_info.align_device_addr = handle->device_addr;
Maheshwar Ajja99422322017-07-07 17:31:15 -07004855 buffer_info.response_required = true;
4856 rc = call_hfi_op(hdev, session_release_buffers,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004857 (void *)inst->session, &buffer_info);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004858 if (!rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004859 mutex_unlock(&inst->persistbufs.lock);
4860 rc = wait_for_sess_signal_receipt(inst,
4861 HAL_SESSION_RELEASE_BUFFER_DONE);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004862 if (rc)
4863 dprintk(VIDC_WARN,
4864 "%s: wait for signal failed, rc %d\n",
4865 __func__, rc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004866 mutex_lock(&inst->persistbufs.lock);
Maheshwar Ajja99422322017-07-07 17:31:15 -07004867 } else {
4868 dprintk(VIDC_WARN,
4869 "Rel prst buf fail:%x, %d\n",
4870 buffer_info.align_device_addr,
4871 buffer_info.buffer_size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004872 }
4873 list_del(&buf->list);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07004874 msm_comm_smem_free(inst, handle);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004875 kfree(buf);
4876 }
4877 mutex_unlock(&inst->persistbufs.lock);
4878 return rc;
4879}
4880
4881int msm_comm_try_set_prop(struct msm_vidc_inst *inst,
4882 enum hal_property ptype, void *pdata)
4883{
4884 int rc = 0;
4885 struct hfi_device *hdev;
4886
4887 if (!inst) {
4888 dprintk(VIDC_ERR, "Invalid input: %pK\n", inst);
4889 return -EINVAL;
4890 }
4891
4892 if (!inst->core || !inst->core->device) {
4893 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4894 return -EINVAL;
4895 }
4896 hdev = inst->core->device;
4897
4898 mutex_lock(&inst->sync_lock);
4899 if (inst->state < MSM_VIDC_OPEN_DONE || inst->state >= MSM_VIDC_CLOSE) {
4900 dprintk(VIDC_ERR, "Not in proper state to set property\n");
4901 rc = -EAGAIN;
4902 goto exit;
4903 }
4904 rc = call_hfi_op(hdev, session_set_property, (void *)inst->session,
4905 ptype, pdata);
4906 if (rc)
4907 dprintk(VIDC_ERR, "Failed to set hal property for framesize\n");
4908exit:
4909 mutex_unlock(&inst->sync_lock);
4910 return rc;
4911}
4912
4913int msm_comm_set_output_buffers(struct msm_vidc_inst *inst)
4914{
4915 int rc = 0;
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004916 bool force_release = true;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004917
4918 if (!inst || !inst->core || !inst->core->device) {
4919 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4920 return -EINVAL;
4921 }
4922
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004923 if (inst->fmts[OUTPUT_PORT].defer_outputs)
4924 force_release = false;
4925
4926 if (msm_comm_release_output_buffers(inst, force_release))
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004927 dprintk(VIDC_WARN, "Failed to release output buffers\n");
4928
4929 rc = set_output_buffers(inst, HAL_BUFFER_OUTPUT);
4930 if (rc)
4931 goto error;
4932 return rc;
4933error:
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08004934 msm_comm_release_output_buffers(inst, true);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08004935 return rc;
4936}
4937
4938int msm_comm_set_scratch_buffers(struct msm_vidc_inst *inst)
4939{
4940 int rc = 0;
4941
4942 if (!inst || !inst->core || !inst->core->device) {
4943 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4944 return -EINVAL;
4945 }
4946
4947 if (msm_comm_release_scratch_buffers(inst, true))
4948 dprintk(VIDC_WARN, "Failed to release scratch buffers\n");
4949
4950 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_SCRATCH,
4951 &inst->scratchbufs);
4952 if (rc)
4953 goto error;
4954
4955 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_SCRATCH_1,
4956 &inst->scratchbufs);
4957 if (rc)
4958 goto error;
4959
4960 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_SCRATCH_2,
4961 &inst->scratchbufs);
4962 if (rc)
4963 goto error;
4964
4965 return rc;
4966error:
4967 msm_comm_release_scratch_buffers(inst, false);
4968 return rc;
4969}
4970
Praneeth Paladugu319e7922017-03-16 11:09:06 -07004971int msm_comm_set_recon_buffers(struct msm_vidc_inst *inst)
4972{
4973 int rc = 0, i = 0;
4974 struct hal_buffer_requirements *internal_buf;
4975 struct recon_buf *binfo;
4976 struct msm_vidc_list *buf_list = &inst->reconbufs;
4977
4978 if (!inst) {
4979 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
4980 return -EINVAL;
4981 }
4982
4983 if (inst->session_type == MSM_VIDC_ENCODER)
4984 internal_buf = get_buff_req_buffer(inst,
4985 HAL_BUFFER_INTERNAL_RECON);
4986 else if (inst->session_type == MSM_VIDC_DECODER)
4987 internal_buf = get_buff_req_buffer(inst,
4988 msm_comm_get_hal_output_buffer(inst));
4989 else
4990 return -EINVAL;
4991
4992 if (!internal_buf || !internal_buf->buffer_count_actual) {
4993 dprintk(VIDC_DBG, "Inst : %pK Recon buffers not required\n",
4994 inst);
4995 return 0;
4996 }
4997
Praneeth Paladugu7722b4e2017-07-07 11:01:56 -07004998 msm_comm_release_recon_buffers(inst);
Praneeth Paladugu319e7922017-03-16 11:09:06 -07004999
5000 for (i = 0; i < internal_buf->buffer_count_actual; i++) {
5001 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
5002 if (!binfo) {
5003 dprintk(VIDC_ERR, "Out of memory\n");
5004 rc = -ENOMEM;
5005 goto fail_kzalloc;
5006 }
5007
5008 binfo->buffer_index = i;
5009 mutex_lock(&buf_list->lock);
5010 list_add_tail(&binfo->list, &buf_list->list);
5011 mutex_unlock(&buf_list->lock);
5012 }
5013
5014fail_kzalloc:
5015 return rc;
5016}
5017
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005018int msm_comm_set_persist_buffers(struct msm_vidc_inst *inst)
5019{
5020 int rc = 0;
5021
5022 if (!inst || !inst->core || !inst->core->device) {
5023 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
5024 return -EINVAL;
5025 }
5026
5027 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_PERSIST,
5028 &inst->persistbufs);
5029 if (rc)
5030 goto error;
5031
5032 rc = set_internal_buffers(inst, HAL_BUFFER_INTERNAL_PERSIST_1,
5033 &inst->persistbufs);
5034 if (rc)
5035 goto error;
5036 return rc;
5037error:
5038 msm_comm_release_persist_buffers(inst);
5039 return rc;
5040}
5041
5042static void msm_comm_flush_in_invalid_state(struct msm_vidc_inst *inst)
5043{
5044 struct list_head *ptr, *next;
5045 enum vidc_ports ports[] = {OUTPUT_PORT, CAPTURE_PORT};
5046 int c = 0;
5047
Maheshwar Ajja4db26932017-10-30 10:08:37 -07005048 /* before flush ensure venus released all buffers */
5049 msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
5050
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005051 for (c = 0; c < ARRAY_SIZE(ports); ++c) {
5052 enum vidc_ports port = ports[c];
5053
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005054 mutex_lock(&inst->bufq[port].lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005055 list_for_each_safe(ptr, next,
5056 &inst->bufq[port].vb2_bufq.queued_list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005057 struct vb2_buffer *vb = container_of(ptr,
5058 struct vb2_buffer, queued_entry);
Vikash Garodia8d985f32017-08-09 19:52:51 +05305059 if (vb->state == VB2_BUF_STATE_ACTIVE) {
5060 vb->planes[0].bytesused = 0;
5061 print_vb2_buffer(VIDC_ERR, "flush in invalid",
5062 inst, vb);
5063 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
5064 } else {
5065 dprintk(VIDC_WARN,
5066 "%s VB is in state %d not in ACTIVE state\n"
5067 , __func__, vb->state);
5068 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005069 }
5070 mutex_unlock(&inst->bufq[port].lock);
5071 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005072 msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_FLUSH_DONE);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005073 return;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005074}
5075
5076int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
5077{
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07005078 int i, rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005079 bool ip_flush = false;
5080 bool op_flush = false;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005081 struct msm_vidc_buffer *mbuf, *next;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005082 struct msm_vidc_core *core;
5083 struct hfi_device *hdev;
5084
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005085 if (!inst || !inst->core || !inst->core->device) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005086 dprintk(VIDC_ERR,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005087 "Invalid params, inst %pK\n", inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005088 return -EINVAL;
5089 }
5090 core = inst->core;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005091 hdev = core->device;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005092
5093 ip_flush = flags & V4L2_QCOM_CMD_FLUSH_OUTPUT;
5094 op_flush = flags & V4L2_QCOM_CMD_FLUSH_CAPTURE;
5095
5096 if (ip_flush && !op_flush) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005097 dprintk(VIDC_WARN,
5098 "Input only flush not supported, making it flush all\n");
5099 op_flush = true;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005100 return 0;
5101 }
5102
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07005103 msm_clock_data_reset(inst);
Praneeth Paladugu75cf18e2016-12-08 16:12:11 -08005104
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005105 if (inst->state == MSM_VIDC_CORE_INVALID) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005106 dprintk(VIDC_ERR,
5107 "Core %pK and inst %pK are in bad state\n",
5108 core, inst);
5109 msm_comm_flush_in_invalid_state(inst);
5110 return 0;
5111 }
5112
Maheshwar Ajja4db26932017-10-30 10:08:37 -07005113 /* enable in flush */
5114 inst->in_flush = true;
5115
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005116 mutex_lock(&inst->registeredbufs.lock);
5117 list_for_each_entry_safe(mbuf, next, &inst->registeredbufs.list, list) {
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07005118 /* don't flush input buffers if input flush is not requested */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005119 if (!ip_flush && mbuf->vvb.vb2_buf.type ==
5120 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
5121 continue;
5122
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07005123 /* flush only deferred or rbr pending buffers */
5124 if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED ||
5125 mbuf->flags & MSM_VIDC_FLAG_RBR_PENDING))
5126 continue;
5127
5128 /*
5129 * flush buffers which are queued by client already,
5130 * the refcount will be two or more for those buffers.
5131 */
5132 if (!(mbuf->smem[0].refcount >= 2))
5133 continue;
5134
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005135 print_vidc_buffer(VIDC_DBG, "flush buf", inst, mbuf);
5136 msm_comm_flush_vidc_buffer(inst, mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005137
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07005138 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
5139 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
5140 print_vidc_buffer(VIDC_ERR,
5141 "dqbuf: unmap failed.", inst, mbuf);
5142 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
5143 print_vidc_buffer(VIDC_ERR,
5144 "dqbuf: unmap failed..", inst, mbuf);
5145 }
5146 if (!mbuf->smem[0].refcount) {
5147 list_del(&mbuf->list);
5148 kref_put_mbuf(mbuf);
5149 } else {
5150 /* buffer is no more a deferred buffer */
5151 mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
5152 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005153 }
5154 mutex_unlock(&inst->registeredbufs.lock);
5155
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005156 hdev = inst->core->device;
5157 if (ip_flush) {
5158 dprintk(VIDC_DBG, "Send flush on all ports to firmware\n");
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005159 rc = call_hfi_op(hdev, session_flush, inst->session,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005160 HAL_FLUSH_ALL);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005161 } else {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005162 dprintk(VIDC_DBG, "Send flush on output port to firmware\n");
5163 rc = call_hfi_op(hdev, session_flush, inst->session,
5164 HAL_FLUSH_OUTPUT);
5165 }
5166 if (rc) {
5167 dprintk(VIDC_ERR,
5168 "Sending flush to firmware failed, flush out all buffers\n");
5169 msm_comm_flush_in_invalid_state(inst);
5170 /* disable in_flush */
5171 inst->in_flush = false;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005172 }
5173
5174 return rc;
5175}
5176
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005177enum hal_extradata_id msm_comm_get_hal_extradata_index(
5178 enum v4l2_mpeg_vidc_extradata index)
5179{
5180 int ret = 0;
5181
5182 switch (index) {
5183 case V4L2_MPEG_VIDC_EXTRADATA_NONE:
5184 ret = HAL_EXTRADATA_NONE;
5185 break;
5186 case V4L2_MPEG_VIDC_EXTRADATA_MB_QUANTIZATION:
5187 ret = HAL_EXTRADATA_MB_QUANTIZATION;
5188 break;
5189 case V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO:
5190 ret = HAL_EXTRADATA_INTERLACE_VIDEO;
5191 break;
5192 case V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP:
5193 ret = HAL_EXTRADATA_TIMESTAMP;
5194 break;
5195 case V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING:
5196 ret = HAL_EXTRADATA_S3D_FRAME_PACKING;
5197 break;
5198 case V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE:
5199 ret = HAL_EXTRADATA_FRAME_RATE;
5200 break;
5201 case V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW:
5202 ret = HAL_EXTRADATA_PANSCAN_WINDOW;
5203 break;
5204 case V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
5205 ret = HAL_EXTRADATA_RECOVERY_POINT_SEI;
5206 break;
5207 case V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO:
5208 ret = HAL_EXTRADATA_MULTISLICE_INFO;
5209 break;
5210 case V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB:
5211 ret = HAL_EXTRADATA_NUM_CONCEALED_MB;
5212 break;
5213 case V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER:
5214 ret = HAL_EXTRADATA_METADATA_FILLER;
5215 break;
5216 case V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO:
5217 ret = HAL_EXTRADATA_ASPECT_RATIO;
5218 break;
5219 case V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP:
5220 ret = HAL_EXTRADATA_INPUT_CROP;
5221 break;
5222 case V4L2_MPEG_VIDC_EXTRADATA_DIGITAL_ZOOM:
5223 ret = HAL_EXTRADATA_DIGITAL_ZOOM;
5224 break;
5225 case V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP:
5226 ret = HAL_EXTRADATA_MPEG2_SEQDISP;
5227 break;
5228 case V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA:
5229 ret = HAL_EXTRADATA_STREAM_USERDATA;
5230 break;
5231 case V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP:
5232 ret = HAL_EXTRADATA_FRAME_QP;
5233 break;
5234 case V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO:
5235 ret = HAL_EXTRADATA_FRAME_BITS_INFO;
5236 break;
5237 case V4L2_MPEG_VIDC_EXTRADATA_LTR:
5238 ret = HAL_EXTRADATA_LTR_INFO;
5239 break;
5240 case V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI:
5241 ret = HAL_EXTRADATA_METADATA_MBI;
5242 break;
5243 case V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI:
5244 ret = HAL_EXTRADATA_VQZIP_SEI;
5245 break;
5246 case V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS:
5247 ret = HAL_EXTRADATA_YUV_STATS;
5248 break;
5249 case V4L2_MPEG_VIDC_EXTRADATA_ROI_QP:
5250 ret = HAL_EXTRADATA_ROI_QP;
5251 break;
5252 case V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP:
5253 ret = HAL_EXTRADATA_OUTPUT_CROP;
5254 break;
5255 case V4L2_MPEG_VIDC_EXTRADATA_DISPLAY_COLOUR_SEI:
5256 ret = HAL_EXTRADATA_MASTERING_DISPLAY_COLOUR_SEI;
5257 break;
5258 case V4L2_MPEG_VIDC_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI:
5259 ret = HAL_EXTRADATA_CONTENT_LIGHT_LEVEL_SEI;
5260 break;
5261 case V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO:
5262 ret = HAL_EXTRADATA_PQ_INFO;
5263 break;
5264
5265 case V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY:
5266 ret = HAL_EXTRADATA_VUI_DISPLAY_INFO;
5267 break;
5268 case V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE:
5269 ret = HAL_EXTRADATA_VPX_COLORSPACE;
5270 break;
Praneeth Paladugua51b2c42017-06-23 12:48:06 -07005271 case V4L2_MPEG_VIDC_EXTRADATA_UBWC_CR_STATS_INFO:
5272 ret = HAL_EXTRADATA_UBWC_CR_STATS_INFO;
5273 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005274 default:
5275 dprintk(VIDC_WARN, "Extradata not found: %d\n", index);
5276 break;
5277 }
5278 return ret;
5279};
5280
Maheshwar Ajja9ff81a22017-08-05 13:25:55 -07005281int msm_vidc_noc_error_info(struct msm_vidc_core *core)
5282{
5283 struct hfi_device *hdev;
5284
5285 if (!core || !core->device) {
5286 dprintk(VIDC_WARN, "%s: Invalid parameters: %pK\n",
5287 __func__, core);
5288 return -EINVAL;
5289 }
5290
5291 if (!core->resources.non_fatal_pagefaults)
5292 return 0;
5293
5294 if (!core->smmu_fault_handled)
5295 return 0;
5296
5297 hdev = core->device;
5298 call_hfi_op(hdev, noc_error_info, hdev->hfi_device_data);
5299
5300 return 0;
5301}
5302
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005303int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
5304 enum hal_ssr_trigger_type type)
5305{
5306 int rc = 0;
5307 struct hfi_device *hdev;
5308
5309 if (!core || !core->device) {
5310 dprintk(VIDC_WARN, "Invalid parameters: %pK\n", core);
5311 return -EINVAL;
5312 }
5313 hdev = core->device;
Maheshwar Ajja79fe9042017-10-17 16:56:35 -07005314
5315 mutex_lock(&core->lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005316 if (core->state == VIDC_CORE_INIT_DONE) {
5317 /*
5318 * In current implementation user-initiated SSR triggers
5319 * a fatal error from hardware. However, there is no way
5320 * to know if fatal error is due to SSR or not. Handle
5321 * user SSR as non-fatal.
5322 */
Maheshwar Ajja8382bec2017-08-11 13:41:35 -07005323 core->trigger_ssr = true;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005324 rc = call_hfi_op(hdev, core_trigger_ssr,
5325 hdev->hfi_device_data, type);
Maheshwar Ajja8382bec2017-08-11 13:41:35 -07005326 if (rc) {
5327 dprintk(VIDC_ERR, "%s: trigger_ssr failed\n",
5328 __func__);
5329 core->trigger_ssr = false;
5330 }
Maheshwar Ajja79fe9042017-10-17 16:56:35 -07005331 } else {
5332 dprintk(VIDC_WARN, "%s: video core %pK not initialized\n",
5333 __func__, core);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005334 }
Maheshwar Ajja79fe9042017-10-17 16:56:35 -07005335 mutex_unlock(&core->lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005336
5337 return rc;
5338}
5339
5340static int msm_vidc_load_supported(struct msm_vidc_inst *inst)
5341{
5342 int num_mbs_per_sec = 0, max_load_adj = 0;
5343 enum load_calc_quirks quirks = LOAD_CALC_IGNORE_TURBO_LOAD |
5344 LOAD_CALC_IGNORE_THUMBNAIL_LOAD |
5345 LOAD_CALC_IGNORE_NON_REALTIME_LOAD;
5346
5347 if (inst->state == MSM_VIDC_OPEN_DONE) {
Saurabh Kothawade5d7f7d42017-09-15 11:22:49 -07005348 max_load_adj = inst->core->resources.max_load;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005349 num_mbs_per_sec = msm_comm_get_load(inst->core,
5350 MSM_VIDC_DECODER, quirks);
5351 num_mbs_per_sec += msm_comm_get_load(inst->core,
5352 MSM_VIDC_ENCODER, quirks);
5353 if (num_mbs_per_sec > max_load_adj) {
5354 dprintk(VIDC_ERR,
5355 "H/W is overloaded. needed: %d max: %d\n",
5356 num_mbs_per_sec,
5357 max_load_adj);
5358 msm_vidc_print_running_insts(inst->core);
5359 return -EBUSY;
5360 }
5361 }
5362 return 0;
5363}
5364
5365int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst)
5366{
5367 u32 x_min, x_max, y_min, y_max;
5368 u32 input_height, input_width, output_height, output_width;
Chinmay Sawarkar81a02a32017-07-13 12:10:24 -07005369 u32 rotation;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005370
5371 input_height = inst->prop.height[OUTPUT_PORT];
5372 input_width = inst->prop.width[OUTPUT_PORT];
5373 output_height = inst->prop.height[CAPTURE_PORT];
5374 output_width = inst->prop.width[CAPTURE_PORT];
5375
5376 if (!input_height || !input_width || !output_height || !output_width) {
5377 dprintk(VIDC_ERR,
5378 "Invalid : Input height = %d width = %d",
5379 input_height, input_width);
5380 dprintk(VIDC_ERR,
5381 " output height = %d width = %d\n",
5382 output_height, output_width);
5383 return -ENOTSUPP;
5384 }
5385
5386 if (!inst->capability.scale_x.min ||
5387 !inst->capability.scale_x.max ||
5388 !inst->capability.scale_y.min ||
5389 !inst->capability.scale_y.max) {
5390
5391 if (input_width * input_height !=
5392 output_width * output_height) {
5393 dprintk(VIDC_ERR,
5394 "%s: scaling is not supported (%dx%d != %dx%d)\n",
5395 __func__, input_width, input_height,
5396 output_width, output_height);
5397 return -ENOTSUPP;
5398 }
5399
5400 dprintk(VIDC_DBG, "%s: supported WxH = %dx%d\n",
5401 __func__, input_width, input_height);
5402 return 0;
5403 }
5404
Chinmay Sawarkar81a02a32017-07-13 12:10:24 -07005405 rotation = msm_comm_g_ctrl_for_id(inst,
5406 V4L2_CID_MPEG_VIDC_VIDEO_ROTATION);
5407
5408 if ((output_width != output_height) &&
5409 (rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90 ||
5410 rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270)) {
5411
5412 output_width = inst->prop.height[CAPTURE_PORT];
5413 output_height = inst->prop.width[CAPTURE_PORT];
5414 dprintk(VIDC_DBG,
5415 "Rotation=%u Swapped Output W=%u H=%u to check scaling",
5416 rotation, output_width, output_height);
5417 }
5418
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005419 x_min = (1<<16)/inst->capability.scale_x.min;
5420 y_min = (1<<16)/inst->capability.scale_y.min;
5421 x_max = inst->capability.scale_x.max >> 16;
5422 y_max = inst->capability.scale_y.max >> 16;
5423
5424 if (input_height > output_height) {
5425 if (input_height > x_min * output_height) {
5426 dprintk(VIDC_ERR,
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005427 "Unsupported height min height %d vs %d\n",
5428 input_height / x_min, output_height);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005429 return -ENOTSUPP;
5430 }
5431 } else {
5432 if (output_height > x_max * input_height) {
5433 dprintk(VIDC_ERR,
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005434 "Unsupported height max height %d vs %d\n",
5435 x_max * input_height, output_height);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005436 return -ENOTSUPP;
5437 }
5438 }
5439 if (input_width > output_width) {
5440 if (input_width > y_min * output_width) {
5441 dprintk(VIDC_ERR,
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005442 "Unsupported width min width %d vs %d\n",
5443 input_width / y_min, output_width);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005444 return -ENOTSUPP;
5445 }
5446 } else {
5447 if (output_width > y_max * input_width) {
5448 dprintk(VIDC_ERR,
Vaibhav Deshu Venkatesh6beca422017-05-22 15:18:47 -07005449 "Unsupported width max width %d vs %d\n",
5450 y_max * input_width, output_width);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005451 return -ENOTSUPP;
5452 }
5453 }
5454 return 0;
5455}
5456
5457int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
5458{
5459 struct msm_vidc_capability *capability;
5460 int rc = 0;
5461 struct hfi_device *hdev;
5462 struct msm_vidc_core *core;
Praneeth Paladugu38eb1982017-10-07 13:31:23 -07005463 u32 output_height, output_width, input_height, input_width;
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005464 u32 rotation;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005465
5466 if (!inst || !inst->core || !inst->core->device) {
5467 dprintk(VIDC_WARN, "%s: Invalid parameter\n", __func__);
5468 return -EINVAL;
5469 }
5470 capability = &inst->capability;
5471 hdev = inst->core->device;
5472 core = inst->core;
5473 rc = msm_vidc_load_supported(inst);
5474 if (rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005475 dprintk(VIDC_WARN,
5476 "%s: Hardware is overloaded\n", __func__);
5477 return rc;
5478 }
5479
5480 if (!is_thermal_permissible(core)) {
5481 dprintk(VIDC_WARN,
5482 "Thermal level critical, stop all active sessions!\n");
5483 return -ENOTSUPP;
5484 }
5485
Praneeth Paladugu38eb1982017-10-07 13:31:23 -07005486 output_height = inst->prop.height[CAPTURE_PORT];
5487 output_width = inst->prop.width[CAPTURE_PORT];
5488 input_height = inst->prop.height[OUTPUT_PORT];
5489 input_width = inst->prop.width[OUTPUT_PORT];
5490
5491 if (input_width % 2 != 0 || input_height % 2 != 0 ||
5492 output_width % 2 != 0 || output_height % 2 != 0) {
5493 dprintk(VIDC_ERR,
5494 "Height and Width should be even numbers for NV12\n");
5495 dprintk(VIDC_ERR,
5496 "Input WxH = (%u)x(%u), Output WxH = (%u)x(%u)\n",
5497 input_width, input_height,
5498 output_width, output_height);
5499 rc = -ENOTSUPP;
5500 }
5501
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005502 rotation = msm_comm_g_ctrl_for_id(inst,
5503 V4L2_CID_MPEG_VIDC_VIDEO_ROTATION);
5504
Chinmay Sawarkar553044f2017-10-17 10:45:29 -07005505 output_height = ALIGN(inst->prop.height[CAPTURE_PORT], 16);
5506 output_width = ALIGN(inst->prop.width[CAPTURE_PORT], 16);
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005507
5508 if ((output_width != output_height) &&
5509 (rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90 ||
5510 rotation == V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270)) {
5511
Chinmay Sawarkar553044f2017-10-17 10:45:29 -07005512 output_width = ALIGN(inst->prop.height[CAPTURE_PORT], 16);
5513 output_height = ALIGN(inst->prop.width[CAPTURE_PORT], 16);
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005514 dprintk(VIDC_DBG,
5515 "Rotation=%u Swapped Output W=%u H=%u to check capability",
5516 rotation, output_width, output_height);
5517 }
5518
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005519 if (!rc) {
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005520 if (output_width < capability->width.min ||
5521 output_height < capability->height.min) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005522 dprintk(VIDC_ERR,
5523 "Unsupported WxH = (%u)x(%u), min supported is - (%u)x(%u)\n",
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005524 output_width,
5525 output_height,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005526 capability->width.min,
5527 capability->height.min);
5528 rc = -ENOTSUPP;
5529 }
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005530 if (!rc && output_width > capability->width.max) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005531 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07005532 "Unsupported width = %u supported max width = %u\n",
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005533 output_width,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005534 capability->width.max);
5535 rc = -ENOTSUPP;
5536 }
5537
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005538 if (!rc && output_height * output_width >
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005539 capability->width.max * capability->height.max) {
5540 dprintk(VIDC_ERR,
5541 "Unsupported WxH = (%u)x(%u), max supported is - (%u)x(%u)\n",
Chinmay Sawarkar2763dd12017-08-10 11:11:46 -07005542 output_width, output_height,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005543 capability->width.max, capability->height.max);
5544 rc = -ENOTSUPP;
5545 }
5546 }
5547 if (rc) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005548 dprintk(VIDC_ERR,
5549 "%s: Resolution unsupported\n", __func__);
5550 }
5551 return rc;
5552}
5553
Maheshwar Ajja279da4a2017-10-17 21:40:46 -07005554void msm_comm_generate_session_error(struct msm_vidc_inst *inst)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005555{
5556 enum hal_command_response cmd = HAL_SESSION_ERROR;
5557 struct msm_vidc_cb_cmd_done response = {0};
5558
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005559 if (!inst || !inst->core) {
5560 dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
5561 return;
5562 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07005563 dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005564 response.session_id = inst;
5565 response.status = VIDC_ERR_FAIL;
5566 handle_session_error(cmd, (void *)&response);
5567}
5568
Maheshwar Ajja279da4a2017-10-17 21:40:46 -07005569void msm_comm_generate_sys_error(struct msm_vidc_inst *inst)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005570{
5571 struct msm_vidc_core *core;
5572 enum hal_command_response cmd = HAL_SYS_ERROR;
5573 struct msm_vidc_cb_cmd_done response = {0};
5574
5575 if (!inst || !inst->core) {
5576 dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
5577 return;
5578 }
Maheshwar Ajja99422322017-07-07 17:31:15 -07005579 dprintk(VIDC_WARN, "%s: inst %pK\n", __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005580 core = inst->core;
5581 response.device_id = (u32) core->id;
5582 handle_sys_error(cmd, (void *) &response);
5583
5584}
5585
5586int msm_comm_kill_session(struct msm_vidc_inst *inst)
5587{
5588 int rc = 0;
5589
5590 if (!inst || !inst->core || !inst->core->device) {
5591 dprintk(VIDC_ERR, "%s: invalid input parameters\n", __func__);
5592 return -EINVAL;
5593 } else if (!inst->session) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07005594 dprintk(VIDC_ERR, "%s: no session to kill for inst %pK\n",
5595 __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005596 return 0;
5597 }
5598
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07005599 dprintk(VIDC_WARN, "%s: inst %pK, session %x state %d\n", __func__,
Maheshwar Ajja4a0ba212017-10-31 11:26:37 -07005600 inst, hash32_ptr(inst->session), inst->state);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005601 /*
5602 * We're internally forcibly killing the session, if fw is aware of
5603 * the session send session_abort to firmware to clean up and release
5604 * the session, else just kill the session inside the driver.
5605 */
5606 if ((inst->state >= MSM_VIDC_OPEN_DONE &&
5607 inst->state < MSM_VIDC_CLOSE_DONE) ||
5608 inst->state == MSM_VIDC_CORE_INVALID) {
Maheshwar Ajja99422322017-07-07 17:31:15 -07005609 rc = msm_comm_session_abort(inst);
5610 if (rc) {
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07005611 dprintk(VIDC_ERR,
5612 "%s: inst %pK session %x abort failed\n",
5613 __func__, inst, hash32_ptr(inst->session));
Maheshwar Ajja99422322017-07-07 17:31:15 -07005614 change_inst_state(inst, MSM_VIDC_CORE_INVALID);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005615 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005616 }
5617
Maheshwar Ajja99422322017-07-07 17:31:15 -07005618 change_inst_state(inst, MSM_VIDC_CLOSE_DONE);
5619 msm_comm_session_clean(inst);
5620
Maheshwar Ajja5cd01cf2017-10-27 15:26:21 -07005621 dprintk(VIDC_WARN, "%s: inst %pK session %x handled\n", __func__,
5622 inst, hash32_ptr(inst->session));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005623 return rc;
5624}
5625
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005626int msm_comm_smem_alloc(struct msm_vidc_inst *inst,
5627 size_t size, u32 align, u32 flags, enum hal_buffer buffer_type,
5628 int map_kernel, struct msm_smem *smem)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005629{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005630 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005631
5632 if (!inst || !inst->core) {
5633 dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005634 return -EINVAL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005635 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005636 rc = msm_smem_alloc(inst->mem_client, size, align,
5637 flags, buffer_type, map_kernel, smem);
5638 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005639}
5640
5641void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem)
5642{
5643 if (!inst || !inst->core || !mem) {
5644 dprintk(VIDC_ERR,
5645 "%s: invalid params: %pK %pK\n", __func__, inst, mem);
5646 return;
5647 }
5648 msm_smem_free(inst->mem_client, mem);
5649}
5650
5651int msm_comm_smem_cache_operations(struct msm_vidc_inst *inst,
5652 struct msm_smem *mem, enum smem_cache_ops cache_ops)
5653{
5654 if (!inst || !mem) {
5655 dprintk(VIDC_ERR,
5656 "%s: invalid params: %pK %pK\n", __func__, inst, mem);
5657 return -EINVAL;
5658 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005659 return msm_smem_cache_operations(inst->mem_client, mem->handle,
5660 mem->offset, mem->size, cache_ops);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005661}
5662
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005663int msm_comm_qbuf_cache_operations(struct msm_vidc_inst *inst,
5664 struct v4l2_buffer *b)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005665{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005666 int rc = 0, i;
5667 void *dma_buf;
5668 void *handle;
5669 bool skip;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005670
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005671 if (!inst || !b) {
5672 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
5673 __func__, inst, b);
5674 return -EINVAL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005675 }
5676
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005677 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 size = b->m.planes[i].bytesused;
5693 cache_ops = SMEM_CACHE_CLEAN_INVALIDATE;
5694 }
5695 } else if (b->type ==
5696 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
5697 if (!i) { /* yuv */
5698 /* all values are correct */
5699 }
5700 }
5701 } else if (inst->session_type == MSM_VIDC_ENCODER) {
5702 if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
5703 if (!i) { /* yuv */
5704 size = b->m.planes[i].bytesused;
5705 cache_ops = SMEM_CACHE_CLEAN_INVALIDATE;
5706 } else { /* extradata */
5707 cache_ops = SMEM_CACHE_CLEAN_INVALIDATE;
5708 }
5709 } else if (b->type ==
5710 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
5711 if (!i) { /* bitstream */
5712 /* all values are correct */
5713 }
5714 }
5715 }
5716
5717 if (!skip) {
5718 rc = msm_smem_cache_operations(inst->mem_client, handle,
5719 offset, size, cache_ops);
5720 if (rc)
5721 print_v4l2_buffer(VIDC_ERR,
5722 "qbuf cache ops failed", inst, b);
5723 }
5724
5725 msm_smem_put_handle(inst->mem_client, handle);
5726 msm_smem_put_dma_buf(dma_buf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005727 }
5728
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005729 return rc;
5730}
5731
5732int msm_comm_dqbuf_cache_operations(struct msm_vidc_inst *inst,
5733 struct v4l2_buffer *b)
5734{
5735 int rc = 0, i;
5736 void *dma_buf;
5737 void *handle;
5738 bool skip;
5739
5740 if (!inst || !b) {
5741 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
5742 __func__, inst, b);
5743 return -EINVAL;
5744 }
5745
5746 for (i = 0; i < b->length; i++) {
5747 unsigned long offset, size;
5748 enum smem_cache_ops cache_ops;
5749
5750 dma_buf = msm_smem_get_dma_buf(b->m.planes[i].m.fd);
5751 handle = msm_smem_get_handle(inst->mem_client, dma_buf);
5752
5753 offset = b->m.planes[i].data_offset;
5754 size = b->m.planes[i].length;
5755 cache_ops = SMEM_CACHE_INVALIDATE;
5756 skip = false;
5757
5758 if (inst->session_type == MSM_VIDC_DECODER) {
5759 if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
5760 if (!i) /* bitstream */
5761 skip = true;
5762 } else if (b->type ==
5763 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
Maheshwar Ajja6d003902017-11-22 09:30:24 -08005764 if (!i) { /* yuv */
5765 /* all values are correct */
5766 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005767 }
5768 } else if (inst->session_type == MSM_VIDC_ENCODER) {
5769 if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
Maheshwar Ajja07dc9182017-07-28 22:08:15 -07005770 /* yuv and extradata */
5771 skip = true;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005772 } else if (b->type ==
5773 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
5774 if (!i) /* bitstream */
5775 skip = true;
5776 }
5777 }
5778
5779 if (!skip) {
5780 rc = msm_smem_cache_operations(inst->mem_client, handle,
5781 offset, size, cache_ops);
5782 if (rc)
5783 print_v4l2_buffer(VIDC_ERR,
5784 "dqbuf cache ops failed", inst, b);
5785 }
5786
5787 msm_smem_put_handle(inst->mem_client, handle);
5788 msm_smem_put_dma_buf(dma_buf);
5789 }
5790
5791 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005792}
5793
5794void msm_vidc_fw_unload_handler(struct work_struct *work)
5795{
5796 struct msm_vidc_core *core = NULL;
5797 struct hfi_device *hdev = NULL;
5798 int rc = 0;
5799
5800 core = container_of(work, struct msm_vidc_core, fw_unload_work.work);
5801 if (!core || !core->device) {
5802 dprintk(VIDC_ERR, "%s - invalid work or core handle\n",
5803 __func__);
5804 return;
5805 }
5806
5807 hdev = core->device;
5808
5809 mutex_lock(&core->lock);
5810 if (list_empty(&core->instances) &&
5811 core->state != VIDC_CORE_UNINIT) {
5812 if (core->state > VIDC_CORE_INIT) {
5813 dprintk(VIDC_DBG, "Calling vidc_hal_core_release\n");
5814 rc = call_hfi_op(hdev, core_release,
5815 hdev->hfi_device_data);
5816 if (rc) {
5817 dprintk(VIDC_ERR,
5818 "Failed to release core, id = %d\n",
5819 core->id);
5820 mutex_unlock(&core->lock);
5821 return;
5822 }
5823 }
5824 core->state = VIDC_CORE_UNINIT;
5825 kfree(core->capabilities);
5826 core->capabilities = NULL;
5827 }
5828 mutex_unlock(&core->lock);
5829}
5830
5831int msm_comm_set_color_format(struct msm_vidc_inst *inst,
5832 enum hal_buffer buffer_type, int fourcc)
5833{
5834 struct hal_uncompressed_format_select hal_fmt = {0};
5835 enum hal_uncompressed_format format = HAL_UNUSED_COLOR;
5836 int rc = 0;
5837 struct hfi_device *hdev;
5838
5839 if (!inst || !inst->core || !inst->core->device) {
5840 dprintk(VIDC_ERR, "%s - invalid param\n", __func__);
5841 return -EINVAL;
5842 }
5843
5844 hdev = inst->core->device;
5845
Praneeth Paladugu319e7922017-03-16 11:09:06 -07005846 format = msm_comm_get_hal_uncompressed(fourcc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005847 if (format == HAL_UNUSED_COLOR) {
5848 dprintk(VIDC_ERR, "Using unsupported colorformat %#x\n",
5849 fourcc);
5850 rc = -ENOTSUPP;
5851 goto exit;
5852 }
5853
5854 hal_fmt.buffer_type = buffer_type;
5855 hal_fmt.format = format;
5856
5857 rc = call_hfi_op(hdev, session_set_property, inst->session,
5858 HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT, &hal_fmt);
5859 if (rc)
5860 dprintk(VIDC_ERR,
5861 "Failed to set input color format\n");
5862 else
5863 dprintk(VIDC_DBG, "Setting uncompressed colorformat to %#x\n",
5864 format);
5865
5866exit:
5867 return rc;
5868}
5869
5870int msm_vidc_comm_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a)
5871{
5872 u32 property_id = 0;
5873 u64 us_per_frame = 0;
5874 void *pdata;
5875 int rc = 0, fps = 0;
5876 struct hal_frame_rate frame_rate;
5877 struct hfi_device *hdev;
5878
5879 if (!inst || !inst->core || !inst->core->device || !a) {
5880 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
5881 return -EINVAL;
5882 }
5883
5884 hdev = inst->core->device;
5885 property_id = HAL_CONFIG_FRAME_RATE;
5886
5887 if (a->parm.output.timeperframe.denominator) {
5888 switch (a->type) {
5889 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
5890 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
5891 us_per_frame = a->parm.output.timeperframe.numerator *
5892 (u64)USEC_PER_SEC;
5893 do_div(us_per_frame, a->parm.output.
5894 timeperframe.denominator);
5895 break;
5896 default:
5897 dprintk(VIDC_ERR,
5898 "Scale clocks : Unknown buffer type %d\n",
5899 a->type);
5900 break;
5901 }
5902 }
5903
5904 if (!us_per_frame) {
5905 dprintk(VIDC_ERR,
5906 "Failed to scale clocks : time between frames is 0\n");
5907 rc = -EINVAL;
5908 goto exit;
5909 }
5910
Maria Yu5d853f82017-09-26 16:13:19 +08005911 fps = us_per_frame > USEC_PER_SEC ?
5912 0 : USEC_PER_SEC / (u32)us_per_frame;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005913
5914 if (fps % 15 == 14 || fps % 24 == 23)
5915 fps = fps + 1;
5916 else if ((fps > 1) && (fps % 24 == 1 || fps % 15 == 1))
5917 fps = fps - 1;
5918
Praneeth Paladugue1679112017-01-27 10:07:15 -08005919 if (fps < inst->capability.frame_rate.min ||
5920 fps > inst->capability.frame_rate.max) {
5921 dprintk(VIDC_ERR,
5922 "FPS is out of limits : fps = %d Min = %d, Max = %d\n",
5923 fps, inst->capability.frame_rate.min,
5924 inst->capability.frame_rate.max);
5925 rc = -EINVAL;
5926 goto exit;
5927 }
5928
Maheshwar Ajja266828742017-04-20 15:48:33 -07005929 dprintk(VIDC_PROF, "reported fps changed for %pK: %d->%d\n",
5930 inst, inst->prop.fps, fps);
5931 inst->prop.fps = fps;
Surajit Poddere502daa2017-05-30 19:17:45 +05305932 if (inst->session_type == MSM_VIDC_ENCODER &&
5933 get_hal_codec(inst->fmts[CAPTURE_PORT].fourcc) !=
5934 HAL_VIDEO_CODEC_TME) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005935 frame_rate.frame_rate = inst->prop.fps * BIT(16);
5936 frame_rate.buffer_type = HAL_BUFFER_OUTPUT;
5937 pdata = &frame_rate;
Maheshwar Ajja266828742017-04-20 15:48:33 -07005938 rc = call_hfi_op(hdev, session_set_property,
5939 inst->session, property_id, pdata);
5940 if (rc)
5941 dprintk(VIDC_WARN,
5942 "Failed to set frame rate %d\n", rc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005943 }
5944exit:
5945 return rc;
5946}
5947
5948void msm_comm_print_inst_info(struct msm_vidc_inst *inst)
5949{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005950 struct msm_vidc_buffer *mbuf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005951 struct internal_buf *buf;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005952 bool is_decode = false;
5953 enum vidc_ports port;
5954 bool is_secure = false;
5955
5956 if (!inst) {
5957 dprintk(VIDC_ERR, "%s - invalid param %pK\n",
5958 __func__, inst);
5959 return;
5960 }
5961
5962 is_decode = inst->session_type == MSM_VIDC_DECODER;
5963 port = is_decode ? OUTPUT_PORT : CAPTURE_PORT;
5964 is_secure = inst->flags & VIDC_SECURE;
5965 dprintk(VIDC_ERR,
5966 "%s session, %s, Codec type: %s HxW: %d x %d fps: %d bitrate: %d bit-depth: %s\n",
5967 is_decode ? "Decode" : "Encode",
5968 is_secure ? "Secure" : "Non-Secure",
5969 inst->fmts[port].name,
5970 inst->prop.height[port], inst->prop.width[port],
5971 inst->prop.fps, inst->prop.bitrate,
5972 !inst->bit_depth ? "8" : "10");
5973
5974 dprintk(VIDC_ERR,
5975 "---Buffer details for inst: %pK of type: %d---\n",
5976 inst, inst->session_type);
5977 mutex_lock(&inst->registeredbufs.lock);
5978 dprintk(VIDC_ERR, "registered buffer list:\n");
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005979 list_for_each_entry(mbuf, &inst->registeredbufs.list, list)
5980 print_vidc_buffer(VIDC_ERR, "buf", inst, mbuf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005981 mutex_unlock(&inst->registeredbufs.lock);
5982
5983 mutex_lock(&inst->scratchbufs.lock);
5984 dprintk(VIDC_ERR, "scratch buffer list:\n");
5985 list_for_each_entry(buf, &inst->scratchbufs.list, list)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005986 dprintk(VIDC_ERR, "type: %d addr: %x size: %u\n",
5987 buf->buffer_type, buf->smem.device_addr,
5988 buf->smem.size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005989 mutex_unlock(&inst->scratchbufs.lock);
5990
5991 mutex_lock(&inst->persistbufs.lock);
5992 dprintk(VIDC_ERR, "persist buffer list:\n");
5993 list_for_each_entry(buf, &inst->persistbufs.list, list)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07005994 dprintk(VIDC_ERR, "type: %d addr: %x size: %u\n",
5995 buf->buffer_type, buf->smem.device_addr,
5996 buf->smem.size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08005997 mutex_unlock(&inst->persistbufs.lock);
5998
5999 mutex_lock(&inst->outputbufs.lock);
6000 dprintk(VIDC_ERR, "dpb buffer list:\n");
6001 list_for_each_entry(buf, &inst->outputbufs.list, list)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006002 dprintk(VIDC_ERR, "type: %d addr: %x size: %u\n",
6003 buf->buffer_type, buf->smem.device_addr,
6004 buf->smem.size);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08006005 mutex_unlock(&inst->outputbufs.lock);
6006}
6007
Umesh Pandeybb3fad02017-03-31 16:49:42 -07006008int msm_comm_session_continue(void *instance)
6009{
6010 struct msm_vidc_inst *inst = instance;
6011 int rc = 0;
6012 struct hfi_device *hdev;
6013
6014 if (!inst || !inst->core || !inst->core->device)
6015 return -EINVAL;
6016 hdev = inst->core->device;
6017 mutex_lock(&inst->lock);
Praneeth Paladugu4e2143c2017-05-15 16:24:10 -07006018 if (inst->state >= MSM_VIDC_RELEASE_RESOURCES_DONE ||
Maheshwar Ajja99422322017-07-07 17:31:15 -07006019 inst->state < MSM_VIDC_START_DONE) {
Praneeth Paladugu4e2143c2017-05-15 16:24:10 -07006020 dprintk(VIDC_DBG,
6021 "Inst %pK : Not in valid state to call %s\n",
6022 inst, __func__);
6023 goto sess_continue_fail;
6024 }
Umesh Pandeybb3fad02017-03-31 16:49:42 -07006025 if (inst->session_type == MSM_VIDC_DECODER && inst->in_reconfig) {
6026 dprintk(VIDC_DBG, "send session_continue\n");
6027 rc = call_hfi_op(hdev, session_continue,
6028 (void *)inst->session);
6029 if (rc) {
6030 dprintk(VIDC_ERR,
6031 "failed to send session_continue\n");
6032 rc = -EINVAL;
6033 goto sess_continue_fail;
6034 }
6035 inst->in_reconfig = false;
Surajit Poddereef1c482017-08-30 17:05:20 +05306036 inst->prop.height[CAPTURE_PORT] = inst->reconfig_height;
6037 inst->prop.width[CAPTURE_PORT] = inst->reconfig_width;
6038 inst->prop.height[OUTPUT_PORT] = inst->reconfig_height;
6039 inst->prop.width[OUTPUT_PORT] = inst->reconfig_width;
Umesh Pandeybb3fad02017-03-31 16:49:42 -07006040 } else if (inst->session_type == MSM_VIDC_ENCODER) {
6041 dprintk(VIDC_DBG,
6042 "session_continue not supported for encoder");
6043 } else {
6044 dprintk(VIDC_ERR,
6045 "session_continue called in wrong state for decoder");
6046 }
Praneeth Paladugu4e2143c2017-05-15 16:24:10 -07006047
Umesh Pandeybb3fad02017-03-31 16:49:42 -07006048sess_continue_fail:
6049 mutex_unlock(&inst->lock);
6050 return rc;
6051}
Umesh Pandeyf2995f82017-05-01 16:44:45 -07006052
6053u32 get_frame_size_nv12(int plane, u32 height, u32 width)
6054{
6055 return VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
6056}
6057
6058u32 get_frame_size_nv12_ubwc(int plane, u32 height, u32 width)
6059{
6060 return VENUS_BUFFER_SIZE(COLOR_FMT_NV12_UBWC, width, height);
6061}
6062
6063u32 get_frame_size_rgba(int plane, u32 height, u32 width)
6064{
6065 return VENUS_BUFFER_SIZE(COLOR_FMT_RGBA8888, width, height);
6066}
6067
6068u32 get_frame_size_nv21(int plane, u32 height, u32 width)
6069{
6070 return VENUS_BUFFER_SIZE(COLOR_FMT_NV21, width, height);
6071}
6072
6073u32 get_frame_size_tp10_ubwc(int plane, u32 height, u32 width)
6074{
6075 return VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
6076}
Shivendra Kakraniac1f60e02017-04-13 00:07:26 -07006077
Zhongbo Shi6bd5f5f2017-08-16 17:20:08 +08006078u32 get_frame_size_p010(int plane, u32 height, u32 width)
6079{
6080 return VENUS_BUFFER_SIZE(COLOR_FMT_P010, width, height);
6081}
6082
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006083
6084void print_vidc_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
6085 struct msm_vidc_buffer *mbuf)
6086{
6087 struct vb2_buffer *vb2 = NULL;
6088
6089 if (!(tag & msm_vidc_debug) || !inst || !mbuf)
6090 return;
6091
6092 vb2 = &mbuf->vvb.vb2_buf;
6093
6094 if (vb2->num_planes == 1)
6095 dprintk(tag,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006096 "%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 -07006097 str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6098 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6099 vb2->index, vb2->planes[0].m.fd,
6100 vb2->planes[0].data_offset, mbuf->smem[0].device_addr,
6101 vb2->planes[0].length, vb2->planes[0].bytesused,
6102 mbuf->vvb.flags, mbuf->vvb.vb2_buf.timestamp,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006103 mbuf->smem[0].refcount, mbuf->flags);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006104 else
6105 dprintk(tag,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006106 "%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 -07006107 str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6108 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6109 vb2->index, vb2->planes[0].m.fd,
6110 vb2->planes[0].data_offset, mbuf->smem[0].device_addr,
6111 vb2->planes[0].length, vb2->planes[0].bytesused,
6112 mbuf->vvb.flags, mbuf->vvb.vb2_buf.timestamp,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006113 mbuf->smem[0].refcount, mbuf->flags,
6114 vb2->planes[1].m.fd, vb2->planes[1].data_offset,
6115 mbuf->smem[1].device_addr, vb2->planes[1].length,
6116 vb2->planes[1].bytesused, mbuf->smem[1].refcount);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006117}
6118
6119void print_vb2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
6120 struct vb2_buffer *vb2)
6121{
6122 if (!(tag & msm_vidc_debug) || !inst || !vb2)
6123 return;
6124
6125 if (vb2->num_planes == 1)
6126 dprintk(tag,
6127 "%s: %s: %x : idx %2d fd %d off %d size %d filled %d\n",
6128 str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6129 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6130 vb2->index, vb2->planes[0].m.fd,
6131 vb2->planes[0].data_offset, vb2->planes[0].length,
6132 vb2->planes[0].bytesused);
6133 else
6134 dprintk(tag,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006135 "%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 -07006136 str, vb2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6137 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6138 vb2->index, vb2->planes[0].m.fd,
6139 vb2->planes[0].data_offset, vb2->planes[0].length,
6140 vb2->planes[0].bytesused, vb2->planes[1].m.fd,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006141 vb2->planes[1].data_offset, vb2->planes[1].length,
6142 vb2->planes[1].bytesused);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006143}
6144
6145void print_v4l2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
6146 struct v4l2_buffer *v4l2)
6147{
6148 if (!(tag & msm_vidc_debug) || !inst || !v4l2)
6149 return;
6150
6151 if (v4l2->length == 1)
6152 dprintk(tag,
6153 "%s: %s: %x : idx %2d fd %d off %d size %d filled %d\n",
6154 str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6155 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6156 v4l2->index, v4l2->m.planes[0].m.fd,
6157 v4l2->m.planes[0].data_offset,
6158 v4l2->m.planes[0].length,
6159 v4l2->m.planes[0].bytesused);
6160 else
6161 dprintk(tag,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006162 "%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 -07006163 str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
6164 "OUTPUT" : "CAPTURE", hash32_ptr(inst->session),
6165 v4l2->index, v4l2->m.planes[0].m.fd,
6166 v4l2->m.planes[0].data_offset,
6167 v4l2->m.planes[0].length,
6168 v4l2->m.planes[0].bytesused,
6169 v4l2->m.planes[1].m.fd,
6170 v4l2->m.planes[1].data_offset,
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006171 v4l2->m.planes[1].length,
6172 v4l2->m.planes[1].bytesused);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006173}
6174
6175bool msm_comm_compare_vb2_plane(struct msm_vidc_inst *inst,
6176 struct msm_vidc_buffer *mbuf, struct vb2_buffer *vb2, u32 i)
6177{
6178 struct vb2_buffer *vb;
6179
6180 if (!inst || !mbuf || !vb2) {
6181 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
6182 __func__, inst, mbuf, vb2);
6183 return false;
6184 }
6185
6186 vb = &mbuf->vvb.vb2_buf;
6187 if (vb->planes[i].m.fd == vb2->planes[i].m.fd &&
6188 vb->planes[i].data_offset == vb2->planes[i].data_offset &&
6189 vb->planes[i].length == vb2->planes[i].length) {
6190 return true;
6191 }
6192
6193 return false;
6194}
6195
6196bool msm_comm_compare_vb2_planes(struct msm_vidc_inst *inst,
6197 struct msm_vidc_buffer *mbuf, struct vb2_buffer *vb2)
6198{
6199 int i = 0;
6200 struct vb2_buffer *vb;
6201
6202 if (!inst || !mbuf || !vb2) {
6203 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
6204 __func__, inst, mbuf, vb2);
6205 return false;
6206 }
6207
6208 vb = &mbuf->vvb.vb2_buf;
6209
6210 if (vb->num_planes != vb2->num_planes)
6211 return false;
6212
6213 for (i = 0; i < vb->num_planes; i++) {
6214 if (!msm_comm_compare_vb2_plane(inst, mbuf, vb2, i))
6215 return false;
6216 }
6217
6218 return true;
6219}
6220
6221bool msm_comm_compare_dma_plane(struct msm_vidc_inst *inst,
6222 struct msm_vidc_buffer *mbuf, unsigned long *dma_planes, u32 i)
6223{
6224 if (!inst || !mbuf || !dma_planes) {
6225 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
6226 __func__, inst, mbuf, dma_planes);
6227 return false;
6228 }
6229
6230 if ((unsigned long)mbuf->smem[i].dma_buf == dma_planes[i])
6231 return true;
6232
6233 return false;
6234}
6235
6236bool msm_comm_compare_dma_planes(struct msm_vidc_inst *inst,
6237 struct msm_vidc_buffer *mbuf, unsigned long *dma_planes)
6238{
6239 int i = 0;
6240 struct vb2_buffer *vb;
6241
6242 if (!inst || !mbuf || !dma_planes) {
6243 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK %pK\n",
6244 __func__, inst, mbuf, dma_planes);
6245 return false;
6246 }
6247
6248 vb = &mbuf->vvb.vb2_buf;
6249 for (i = 0; i < vb->num_planes; i++) {
6250 if (!msm_comm_compare_dma_plane(inst, mbuf, dma_planes, i))
6251 return false;
6252 }
6253
6254 return true;
6255}
6256
6257
6258bool msm_comm_compare_device_plane(struct msm_vidc_buffer *mbuf,
6259 u32 *planes, u32 i)
6260{
6261 if (!mbuf || !planes) {
6262 dprintk(VIDC_ERR, "%s: invalid params, %pK %pK\n",
6263 __func__, mbuf, planes);
6264 return false;
6265 }
6266
6267 if (mbuf->smem[i].device_addr == planes[i])
6268 return true;
6269
6270 return false;
6271}
6272
6273bool msm_comm_compare_device_planes(struct msm_vidc_buffer *mbuf,
6274 u32 *planes)
6275{
6276 int i = 0;
6277
6278 if (!mbuf || !planes)
6279 return false;
6280
6281 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
6282 if (!msm_comm_compare_device_plane(mbuf, planes, i))
6283 return false;
6284 }
6285
6286 return true;
6287}
6288
6289struct msm_vidc_buffer *msm_comm_get_buffer_using_device_planes(
6290 struct msm_vidc_inst *inst, u32 *planes)
6291{
6292 struct msm_vidc_buffer *mbuf;
6293 bool found = false;
6294
6295 mutex_lock(&inst->registeredbufs.lock);
6296 found = false;
6297 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
6298 if (msm_comm_compare_device_planes(mbuf, planes)) {
6299 found = true;
6300 break;
6301 }
6302 }
6303 mutex_unlock(&inst->registeredbufs.lock);
6304 if (!found) {
6305 dprintk(VIDC_ERR,
6306 "%s: data_addr %x, extradata_addr %x not found\n",
6307 __func__, planes[0], planes[1]);
6308 mbuf = NULL;
6309 }
6310
6311 return mbuf;
6312}
6313
6314int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst,
6315 struct msm_vidc_buffer *mbuf)
6316{
6317 int rc;
6318 struct vb2_buffer *vb;
6319
6320 if (!inst || !mbuf) {
6321 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
6322 __func__, inst, mbuf);
6323 return -EINVAL;
6324 }
6325
6326 vb = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
6327 if (!vb) {
6328 print_vidc_buffer(VIDC_ERR,
6329 "vb not found for buf", inst, mbuf);
6330 return -EINVAL;
6331 }
6332
6333 vb->planes[0].bytesused = 0;
6334 rc = msm_comm_vb2_buffer_done(inst, vb);
6335 if (rc)
6336 print_vidc_buffer(VIDC_ERR,
6337 "vb2_buffer_done failed for", inst, mbuf);
6338
6339 return rc;
6340}
6341
6342struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst,
6343 struct vb2_buffer *vb2)
6344{
6345 int rc = 0;
6346 struct vb2_v4l2_buffer *vbuf;
6347 struct vb2_buffer *vb;
6348 unsigned long dma_planes[VB2_MAX_PLANES] = {0};
6349 struct msm_vidc_buffer *mbuf;
6350 bool found = false;
6351 int i;
6352
6353 if (!inst || !vb2) {
6354 dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
6355 return NULL;
6356 }
6357
6358 for (i = 0; i < vb2->num_planes; i++) {
6359 /*
6360 * always compare dma_buf addresses which is guaranteed
6361 * to be same across the processes (duplicate fds).
6362 */
Maheshwar Ajja07dc9182017-07-28 22:08:15 -07006363 dma_planes[i] = (unsigned long)msm_smem_get_dma_buf(
6364 vb2->planes[i].m.fd);
6365 if (!dma_planes[i])
6366 return NULL;
6367 msm_smem_put_dma_buf((struct dma_buf *)dma_planes[i]);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006368 }
6369
6370 mutex_lock(&inst->registeredbufs.lock);
Maheshwar Ajja848ab822017-09-28 20:33:05 -07006371 if (inst->session_type == MSM_VIDC_DECODER) {
6372 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
6373 if (msm_comm_compare_dma_planes(inst, mbuf,
6374 dma_planes)) {
6375 found = true;
6376 break;
6377 }
6378 }
6379 } else {
6380 /*
6381 * for encoder, client may queue the same buffer with different
6382 * fd before driver returned old buffer to the client. This
6383 * buffer should be treated as new buffer. Search the list with
6384 * fd so that it will be treated as new msm_vidc_buffer.
6385 */
6386 list_for_each_entry(mbuf, &inst->registeredbufs.list, list) {
6387 if (msm_comm_compare_vb2_planes(inst, mbuf, vb2)) {
6388 found = true;
6389 break;
6390 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006391 }
6392 }
6393
6394 if (!found) {
6395 /* this is new vb2_buffer */
6396 mbuf = kzalloc(sizeof(struct msm_vidc_buffer), GFP_KERNEL);
6397 if (!mbuf) {
6398 dprintk(VIDC_ERR, "%s: alloc msm_vidc_buffer failed\n",
6399 __func__);
6400 rc = -ENOMEM;
6401 goto exit;
6402 }
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006403 kref_init(&mbuf->kref);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006404 }
6405
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006406 /* Initially assume all the buffer are going to be deferred */
6407 mbuf->flags |= MSM_VIDC_FLAG_DEFERRED;
6408
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006409 vbuf = to_vb2_v4l2_buffer(vb2);
6410 memcpy(&mbuf->vvb, vbuf, sizeof(struct vb2_v4l2_buffer));
6411 vb = &mbuf->vvb.vb2_buf;
6412
6413 for (i = 0; i < vb->num_planes; i++) {
6414 mbuf->smem[i].buffer_type = get_hal_buffer_type(vb->type, i);
6415 mbuf->smem[i].fd = vb->planes[i].m.fd;
6416 mbuf->smem[i].offset = vb->planes[i].data_offset;
6417 mbuf->smem[i].size = vb->planes[i].length;
6418 rc = msm_smem_map_dma_buf(inst, &mbuf->smem[i]);
6419 if (rc) {
6420 dprintk(VIDC_ERR, "%s: map failed.\n", __func__);
6421 goto exit;
6422 }
6423 /* increase refcount as we get both fbd and rbr */
6424 rc = msm_smem_map_dma_buf(inst, &mbuf->smem[i]);
6425 if (rc) {
6426 dprintk(VIDC_ERR, "%s: map failed..\n", __func__);
6427 goto exit;
6428 }
6429 }
6430
6431 /* special handling for decoder */
6432 if (inst->session_type == MSM_VIDC_DECODER) {
6433 if (found) {
6434 rc = -EEXIST;
6435 } else {
6436 bool found_plane0 = false;
6437 struct msm_vidc_buffer *temp;
6438 /*
6439 * client might have queued same plane[0] but different
6440 * plane[1] search plane[0] and if found don't queue the
6441 * buffer, the buffer will be queued when rbr event
6442 * arrived.
6443 */
6444 list_for_each_entry(temp, &inst->registeredbufs.list,
6445 list) {
6446 if (msm_comm_compare_dma_plane(inst, temp,
6447 dma_planes, 0)) {
6448 found_plane0 = true;
6449 break;
6450 }
6451 }
6452 if (found_plane0)
6453 rc = -EEXIST;
6454 }
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006455 /*
6456 * If RBR pending on this buffer then enable RBR_PENDING flag
6457 * and clear the DEFERRED flag to avoid this buffer getting
6458 * queued to video hardware in msm_comm_qbuf() which tries to
6459 * queue all the DEFERRED buffers.
6460 */
6461 if (rc == -EEXIST) {
6462 mbuf->flags |= MSM_VIDC_FLAG_RBR_PENDING;
6463 mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
6464 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006465 }
6466
6467 /* add the new buffer to list */
6468 if (!found)
6469 list_add_tail(&mbuf->list, &inst->registeredbufs.list);
6470
6471 mutex_unlock(&inst->registeredbufs.lock);
6472 if (rc == -EEXIST) {
6473 print_vidc_buffer(VIDC_DBG, "qbuf upon rbr", inst, mbuf);
6474 return ERR_PTR(rc);
6475 }
6476
6477 return mbuf;
6478
6479exit:
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006480 dprintk(VIDC_ERR, "%s: rc %d\n", __func__, rc);
6481 msm_comm_unmap_vidc_buffer(inst, mbuf);
6482 if (!found)
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006483 kref_put_mbuf(mbuf);
6484 mutex_unlock(&inst->registeredbufs.lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006485
6486 return ERR_PTR(rc);
6487}
6488
6489void msm_comm_put_vidc_buffer(struct msm_vidc_inst *inst,
6490 struct msm_vidc_buffer *mbuf)
6491{
6492 struct msm_vidc_buffer *temp;
6493 bool found = false;
6494 int i = 0;
6495
6496 if (!inst || !mbuf) {
6497 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
6498 __func__, inst, mbuf);
6499 return;
6500 }
6501
6502 mutex_lock(&inst->registeredbufs.lock);
6503 /* check if mbuf was not removed by any chance */
6504 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
6505 if (msm_comm_compare_vb2_planes(inst, mbuf,
6506 &temp->vvb.vb2_buf)) {
6507 found = true;
6508 break;
6509 }
6510 }
6511 if (!found) {
6512 print_vidc_buffer(VIDC_ERR, "buf was removed", inst, mbuf);
6513 goto unlock;
6514 }
6515
6516 print_vidc_buffer(VIDC_DBG, "dqbuf", inst, mbuf);
6517 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
6518 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
6519 print_vidc_buffer(VIDC_ERR,
6520 "dqbuf: unmap failed.", inst, mbuf);
6521
6522 if (!(mbuf->vvb.flags & V4L2_QCOM_BUF_FLAG_READONLY)) {
6523 /* rbr won't come for this buffer */
6524 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
6525 print_vidc_buffer(VIDC_ERR,
6526 "dqbuf: unmap failed..", inst, mbuf);
Maheshwar Ajja1352fb72017-10-18 17:38:55 -07006527 } else {
6528 /* RBR event expected */
6529 mbuf->flags |= MSM_VIDC_FLAG_RBR_PENDING;
6530 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006531 }
6532 /*
6533 * remove the entry if plane[0].refcount is zero else
6534 * don't remove as client queued same buffer that's why
6535 * plane[0].refcount is not zero
6536 */
6537 if (!mbuf->smem[0].refcount) {
6538 list_del(&mbuf->list);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006539 kref_put_mbuf(mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006540 }
6541unlock:
6542 mutex_unlock(&inst->registeredbufs.lock);
6543}
6544
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006545void handle_release_buffer_reference(struct msm_vidc_inst *inst,
6546 struct msm_vidc_buffer *mbuf)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006547{
6548 int rc = 0;
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006549 struct msm_vidc_buffer *temp;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006550 bool found = false;
6551 int i = 0;
6552
6553 mutex_lock(&inst->registeredbufs.lock);
6554 found = false;
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006555 /* check if mbuf was not removed by any chance */
6556 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
6557 if (msm_comm_compare_vb2_planes(inst, mbuf,
6558 &temp->vvb.vb2_buf)) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006559 found = true;
6560 break;
6561 }
6562 }
6563 if (found) {
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006564 /* send RBR event to client */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006565 msm_vidc_queue_rbr_event(inst,
6566 mbuf->vvb.vb2_buf.planes[0].m.fd,
6567 mbuf->vvb.vb2_buf.planes[0].data_offset);
6568
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006569 /* clear RBR_PENDING flag */
6570 mbuf->flags &= ~MSM_VIDC_FLAG_RBR_PENDING;
6571
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006572 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
6573 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
6574 print_vidc_buffer(VIDC_ERR,
6575 "rbr unmap failed.", inst, mbuf);
6576 }
6577 /* refcount is not zero if client queued the same buffer */
6578 if (!mbuf->smem[0].refcount) {
6579 list_del(&mbuf->list);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006580 kref_put_mbuf(mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006581 }
6582 } else {
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006583 print_vidc_buffer(VIDC_ERR, "mbuf not found", inst, mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006584 goto unlock;
6585 }
6586
6587 /*
6588 * 1. client might have pushed same planes in which case mbuf will be
6589 * same and refcounts are positive and buffer wouldn't have been
6590 * removed from the registeredbufs list.
6591 * 2. client might have pushed same planes[0] but different planes[1]
6592 * in which case mbuf will be different.
6593 * 3. in either case we can search mbuf->smem[0].device_addr in the list
6594 * and if found queue it to video hw (if not flushing).
6595 */
6596 found = false;
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006597 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
6598 if (msm_comm_compare_vb2_plane(inst, mbuf,
6599 &temp->vvb.vb2_buf, 0)) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006600 found = true;
6601 break;
6602 }
6603 }
6604 if (!found)
6605 goto unlock;
6606
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006607 /* buffer found means client queued the buffer already */
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006608 if (inst->in_reconfig || inst->in_flush) {
6609 print_vidc_buffer(VIDC_DBG, "rbr flush buf", inst, mbuf);
6610 msm_comm_flush_vidc_buffer(inst, mbuf);
6611 msm_comm_unmap_vidc_buffer(inst, mbuf);
6612 /* remove from list */
6613 list_del(&mbuf->list);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006614 kref_put_mbuf(mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006615
6616 /* don't queue the buffer */
6617 found = false;
6618 }
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006619 /* clear DEFERRED flag, if any, as the buffer is going to be queued */
6620 if (found)
6621 mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
6622
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006623unlock:
6624 mutex_unlock(&inst->registeredbufs.lock);
6625
6626 if (found) {
6627 print_vidc_buffer(VIDC_DBG, "rbr qbuf", inst, mbuf);
Maheshwar Ajjae5765bd2017-08-08 11:59:38 -07006628 rc = msm_comm_qbuf_rbr(inst, mbuf);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07006629 if (rc)
6630 print_vidc_buffer(VIDC_ERR,
6631 "rbr qbuf failed", inst, mbuf);
6632 }
6633}
6634
6635int msm_comm_unmap_vidc_buffer(struct msm_vidc_inst *inst,
6636 struct msm_vidc_buffer *mbuf)
6637{
6638 int rc = 0, i;
6639
6640 if (!inst || !mbuf) {
6641 dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
6642 __func__, inst, mbuf);
6643 return -EINVAL;
6644 }
6645 if (mbuf->vvb.vb2_buf.num_planes > VIDEO_MAX_PLANES) {
6646 dprintk(VIDC_ERR, "%s: invalid num_planes %d\n", __func__,
6647 mbuf->vvb.vb2_buf.num_planes);
6648 return -EINVAL;
6649 }
6650
6651 for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++) {
6652 u32 refcount = mbuf->smem[i].refcount;
6653
6654 while (refcount) {
6655 if (msm_smem_unmap_dma_buf(inst, &mbuf->smem[i]))
6656 print_vidc_buffer(VIDC_ERR,
6657 "unmap failed for buf", inst, mbuf);
6658 refcount--;
6659 }
6660 }
6661
6662 return rc;
6663}
6664
Maheshwar Ajjacca04052017-07-12 17:59:45 -07006665static void kref_free_mbuf(struct kref *kref)
6666{
6667 struct msm_vidc_buffer *mbuf = container_of(kref,
6668 struct msm_vidc_buffer, kref);
6669
6670 kfree(mbuf);
6671}
6672
6673void kref_put_mbuf(struct msm_vidc_buffer *mbuf)
6674{
6675 if (!mbuf)
6676 return;
6677
6678 kref_put(&mbuf->kref, kref_free_mbuf);
6679}
6680
6681bool kref_get_mbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
6682{
6683 struct msm_vidc_buffer *temp;
6684 bool matches = false;
6685 bool ret = false;
6686
6687 if (!inst || !mbuf)
6688 return false;
6689
6690 mutex_lock(&inst->registeredbufs.lock);
6691 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
6692 if (temp == mbuf) {
6693 matches = true;
6694 break;
6695 }
6696 }
6697 ret = (matches && kref_get_unless_zero(&mbuf->kref)) ? true : false;
6698 mutex_unlock(&inst->registeredbufs.lock);
6699
6700 return ret;
6701}
6702
Qiwei Liu551a22222017-08-23 15:28:29 +08006703void msm_comm_store_mark_data(struct msm_vidc_list *data_list,
6704 u32 index, u32 mark_data, u32 mark_target)
6705{
6706 struct msm_vidc_buf_data *pdata = NULL;
6707 bool found = false;
6708
6709 if (!data_list) {
6710 dprintk(VIDC_ERR, "%s: invalid params %pK\n",
6711 __func__, data_list);
6712 return;
6713 }
6714
6715 mutex_lock(&data_list->lock);
6716 list_for_each_entry(pdata, &data_list->list, list) {
6717 if (pdata->index == index) {
6718 pdata->mark_data = mark_data;
6719 pdata->mark_target = mark_target;
6720 found = true;
6721 break;
6722 }
6723 }
6724
6725 if (!found) {
6726 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
6727 if (!pdata) {
6728 dprintk(VIDC_WARN, "%s: malloc failure.\n", __func__);
6729 goto exit;
6730 }
6731 pdata->index = index;
6732 pdata->mark_data = mark_data;
6733 pdata->mark_target = mark_target;
6734 list_add_tail(&pdata->list, &data_list->list);
6735 }
6736
6737exit:
6738 mutex_unlock(&data_list->lock);
6739}
6740
6741void msm_comm_fetch_mark_data(struct msm_vidc_list *data_list,
6742 u32 index, u32 *mark_data, u32 *mark_target)
6743{
6744 struct msm_vidc_buf_data *pdata = NULL;
6745
6746 if (!data_list || !mark_data || !mark_target) {
6747 dprintk(VIDC_ERR, "%s: invalid params %pK %pK %pK\n",
6748 __func__, data_list, mark_data, mark_target);
6749 return;
6750 }
6751
6752 *mark_data = *mark_target = 0;
6753 mutex_lock(&data_list->lock);
6754 list_for_each_entry(pdata, &data_list->list, list) {
6755 if (pdata->index == index) {
6756 *mark_data = pdata->mark_data;
6757 *mark_target = pdata->mark_target;
6758 /* clear after fetch */
6759 pdata->mark_data = pdata->mark_target = 0;
6760 break;
6761 }
6762 }
6763 mutex_unlock(&data_list->lock);
6764}
6765
6766int msm_comm_release_mark_data(struct msm_vidc_inst *inst)
6767{
6768 struct msm_vidc_buf_data *pdata, *next;
6769
6770 if (!inst) {
6771 dprintk(VIDC_ERR, "%s: invalid params %pK\n",
6772 __func__, inst);
6773 return -EINVAL;
6774 }
6775
6776 mutex_lock(&inst->etb_data.lock);
6777 list_for_each_entry_safe(pdata, next, &inst->etb_data.list, list) {
6778 list_del(&pdata->list);
6779 kfree(pdata);
6780 }
6781 mutex_unlock(&inst->etb_data.lock);
6782
6783 mutex_lock(&inst->fbd_data.lock);
6784 list_for_each_entry_safe(pdata, next, &inst->fbd_data.list, list) {
6785 list_del(&pdata->list);
6786 kfree(pdata);
6787 }
6788 mutex_unlock(&inst->fbd_data.lock);
6789
6790 return 0;
6791}
6792