msm_vidc_control.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  4. */
  5. /* Copyright (c) 2022-2023. Qualcomm Innovation Center, Inc. All rights reserved. */
  6. #include "msm_vidc_internal.h"
  7. #include "msm_vidc_driver.h"
  8. #include "msm_venc.h"
  9. #include "msm_vidc_platform.h"
  10. #include "msm_vidc_debug.h"
  11. extern struct msm_vidc_core *g_core;
  12. static bool is_priv_ctrl(u32 id)
  13. {
  14. bool private = false;
  15. if (IS_PRIV_CTRL(id))
  16. return true;
  17. /*
  18. * Treat below standard controls as private because
  19. * we have added custom values to the controls
  20. */
  21. switch (id) {
  22. /*
  23. * TODO: V4L2_CID_MPEG_VIDEO_HEVC_PROFILE is std ctrl. But
  24. * V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10_STILL_PICTURE support is not
  25. * available yet. Hence, make this as private ctrl for time being
  26. */
  27. case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
  28. private = true;
  29. break;
  30. default:
  31. private = false;
  32. break;
  33. }
  34. return private;
  35. }
  36. static const char *const mpeg_video_blur_types[] = {
  37. "Blur None",
  38. "Blur External",
  39. "Blur Adaptive",
  40. NULL,
  41. };
  42. static const char *const mpeg_video_hevc_profile[] = {
  43. "Main",
  44. "Main Still Picture",
  45. "Main 10",
  46. "Main 10 Still Picture",
  47. NULL,
  48. };
  49. static const char * const av1_profile[] = {
  50. "Main",
  51. "High",
  52. "Professional",
  53. NULL,
  54. };
  55. static const char * const av1_level[] = {
  56. "2.0",
  57. "2.1",
  58. "2.2",
  59. "2.3",
  60. "3.0",
  61. "3.1",
  62. "3.2",
  63. "3.3",
  64. "4.0",
  65. "4.1",
  66. "4.2",
  67. "4.3",
  68. "5.0",
  69. "5.1",
  70. "5.2",
  71. "5.3",
  72. "6.0",
  73. "6.1",
  74. "6.2",
  75. "6.3",
  76. "7.0",
  77. "7.1",
  78. "7.2",
  79. "7.3",
  80. NULL,
  81. };
  82. static const char * const av1_tier[] = {
  83. "Main",
  84. "High",
  85. NULL,
  86. };
  87. static const char *const mpeg_video_vidc_ir_type[] = {
  88. "Random",
  89. "Cyclic",
  90. NULL,
  91. };
  92. static const char * const * msm_vidc_get_qmenu_type(
  93. struct msm_vidc_inst *inst, u32 cap_id)
  94. {
  95. switch (cap_id) {
  96. case BLUR_TYPES:
  97. return mpeg_video_blur_types;
  98. case PROFILE:
  99. if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC) {
  100. return mpeg_video_hevc_profile;
  101. } else if (inst->codec == MSM_VIDC_AV1) {
  102. return av1_profile;
  103. } else {
  104. i_vpr_e(inst, "%s: invalid codec type %d for cap id %d\n",
  105. __func__, inst->codec, cap_id);
  106. return NULL;
  107. }
  108. case LEVEL:
  109. if (inst->codec == MSM_VIDC_AV1) {
  110. return av1_level;
  111. } else {
  112. i_vpr_e(inst, "%s: invalid codec type %d for cap id %d\n",
  113. __func__, inst->codec, cap_id);
  114. return NULL;
  115. }
  116. case AV1_TIER:
  117. return av1_tier;
  118. case IR_TYPE:
  119. return mpeg_video_vidc_ir_type;
  120. default:
  121. i_vpr_e(inst, "%s: No available qmenu for cap id %d\n",
  122. __func__, cap_id);
  123. return NULL;
  124. }
  125. }
  126. static inline bool has_children(struct msm_vidc_inst_cap *cap)
  127. {
  128. return !!cap->children[0];
  129. }
  130. static inline bool is_leaf(struct msm_vidc_inst_cap *cap)
  131. {
  132. return !has_children(cap);
  133. }
  134. bool is_valid_cap_id(enum msm_vidc_inst_capability_type cap_id)
  135. {
  136. return cap_id > INST_CAP_NONE && cap_id < INST_CAP_MAX;
  137. }
  138. bool is_valid_cap(struct msm_vidc_inst *inst,
  139. enum msm_vidc_inst_capability_type cap_id)
  140. {
  141. if (!inst)
  142. return false;
  143. if (cap_id <= INST_CAP_NONE || cap_id >= INST_CAP_MAX)
  144. return false;
  145. return !!inst->capabilities[cap_id].cap_id;
  146. }
  147. static inline bool is_all_childrens_visited(
  148. struct msm_vidc_inst_cap *cap, bool lookup[INST_CAP_MAX]) {
  149. bool found = true;
  150. int i;
  151. for (i = 0; i < MAX_CAP_CHILDREN; i++) {
  152. if (cap->children[i] == INST_CAP_NONE)
  153. continue;
  154. if (!lookup[cap->children[i]]) {
  155. found = false;
  156. break;
  157. }
  158. }
  159. return found;
  160. }
  161. static int add_node_list(struct list_head *list, enum msm_vidc_inst_capability_type cap_id)
  162. {
  163. int rc = 0;
  164. struct msm_vidc_inst_cap_entry *entry = NULL;
  165. rc = msm_vidc_vmem_alloc(sizeof(struct msm_vidc_inst_cap_entry),
  166. (void **)&entry, __func__);
  167. if (rc)
  168. return rc;
  169. INIT_LIST_HEAD(&entry->list);
  170. entry->cap_id = cap_id;
  171. list_add(&entry->list, list);
  172. return rc;
  173. }
  174. static int add_node(
  175. struct list_head *list, struct msm_vidc_inst_cap *lcap, bool lookup[INST_CAP_MAX])
  176. {
  177. int rc = 0;
  178. if (lookup[lcap->cap_id])
  179. return 0;
  180. rc = add_node_list(list, lcap->cap_id);
  181. if (rc)
  182. return rc;
  183. lookup[lcap->cap_id] = true;
  184. return 0;
  185. }
  186. static int msm_vidc_add_capid_to_fw_list(struct msm_vidc_inst *inst,
  187. enum msm_vidc_inst_capability_type cap_id)
  188. {
  189. struct msm_vidc_inst_cap_entry *entry = NULL;
  190. int rc = 0;
  191. /* skip adding if cap_id already present in firmware list */
  192. list_for_each_entry(entry, &inst->firmware_list, list) {
  193. if (entry->cap_id == cap_id) {
  194. i_vpr_l(inst,
  195. "%s: cap[%d] %s already present in fw list\n",
  196. __func__, cap_id, cap_name(cap_id));
  197. return 0;
  198. }
  199. }
  200. rc = add_node_list(&inst->firmware_list, cap_id);
  201. if (rc)
  202. return rc;
  203. return 0;
  204. }
  205. static int msm_vidc_add_children(struct msm_vidc_inst *inst,
  206. enum msm_vidc_inst_capability_type cap_id)
  207. {
  208. struct msm_vidc_inst_cap *cap;
  209. int i, rc = 0;
  210. cap = &inst->capabilities[cap_id];
  211. for (i = 0; i < MAX_CAP_CHILDREN; i++) {
  212. if (!cap->children[i])
  213. break;
  214. if (!is_valid_cap_id(cap->children[i]))
  215. continue;
  216. rc = add_node_list(&inst->children_list, cap->children[i]);
  217. if (rc)
  218. return rc;
  219. }
  220. return rc;
  221. }
  222. static int msm_vidc_adjust_cap(struct msm_vidc_inst *inst,
  223. enum msm_vidc_inst_capability_type cap_id,
  224. struct v4l2_ctrl *ctrl, const char *func)
  225. {
  226. struct msm_vidc_inst_cap *cap;
  227. int rc = 0;
  228. /* validate cap_id */
  229. if (!is_valid_cap_id(cap_id))
  230. return 0;
  231. /* validate cap */
  232. cap = &inst->capabilities[cap_id];
  233. if (!is_valid_cap(inst, cap->cap_id))
  234. return 0;
  235. /* check if adjust supported */
  236. if (!cap->adjust) {
  237. if (ctrl)
  238. msm_vidc_update_cap_value(inst, cap_id, ctrl->val, func);
  239. return 0;
  240. }
  241. /* call adjust */
  242. rc = cap->adjust(inst, ctrl);
  243. if (rc) {
  244. i_vpr_e(inst, "%s: adjust cap failed for %s\n", func, cap_name(cap_id));
  245. return rc;
  246. }
  247. return rc;
  248. }
  249. static int msm_vidc_set_cap(struct msm_vidc_inst *inst,
  250. enum msm_vidc_inst_capability_type cap_id,
  251. const char *func)
  252. {
  253. struct msm_vidc_inst_cap *cap;
  254. int rc = 0;
  255. /* validate cap_id */
  256. if (!is_valid_cap_id(cap_id))
  257. return 0;
  258. /* validate cap */
  259. cap = &inst->capabilities[cap_id];
  260. if (!is_valid_cap(inst, cap->cap_id))
  261. return 0;
  262. /* check if set supported */
  263. if (!cap->set)
  264. return 0;
  265. /* call set */
  266. rc = cap->set(inst, cap_id);
  267. if (rc) {
  268. i_vpr_e(inst, "%s: set cap failed for %s\n", func, cap_name(cap_id));
  269. return rc;
  270. }
  271. return rc;
  272. }
  273. static int msm_vidc_adjust_dynamic_property(struct msm_vidc_inst *inst,
  274. enum msm_vidc_inst_capability_type cap_id, struct v4l2_ctrl *ctrl)
  275. {
  276. struct msm_vidc_inst_cap_entry *entry = NULL, *temp = NULL;
  277. struct msm_vidc_inst_cap *cap;
  278. s32 prev_value;
  279. int rc = 0;
  280. if (!inst || !ctrl) {
  281. d_vpr_e("%s: invalid param\n", __func__);
  282. return -EINVAL;
  283. }
  284. cap = &inst->capabilities[0];
  285. /* sanitize cap_id */
  286. if (!is_valid_cap_id(cap_id)) {
  287. i_vpr_e(inst, "%s: invalid cap_id %u\n", __func__, cap_id);
  288. return -EINVAL;
  289. }
  290. if (!(cap[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)) {
  291. i_vpr_h(inst,
  292. "%s: dynamic setting of cap[%d] %s is not allowed\n",
  293. __func__, cap_id, cap_name(cap_id));
  294. return -EBUSY;
  295. }
  296. i_vpr_h(inst, "%s: cap[%d] %s\n", __func__, cap_id, cap_name(cap_id));
  297. prev_value = cap[cap_id].value;
  298. rc = msm_vidc_adjust_cap(inst, cap_id, ctrl, __func__);
  299. if (rc)
  300. return rc;
  301. if (cap[cap_id].value == prev_value && cap_id == GOP_SIZE) {
  302. /*
  303. * Ignore setting same GOP size value to firmware to avoid
  304. * unnecessary generation of IDR frame.
  305. */
  306. return 0;
  307. }
  308. /* add cap_id to firmware list always */
  309. rc = msm_vidc_add_capid_to_fw_list(inst, cap_id);
  310. if (rc)
  311. goto error;
  312. /* add children only if cap value modified */
  313. if (cap[cap_id].value == prev_value)
  314. return 0;
  315. rc = msm_vidc_add_children(inst, cap_id);
  316. if (rc)
  317. goto error;
  318. list_for_each_entry_safe(entry, temp, &inst->children_list, list) {
  319. if (!is_valid_cap_id(entry->cap_id)) {
  320. rc = -EINVAL;
  321. goto error;
  322. }
  323. if (!cap[entry->cap_id].adjust) {
  324. i_vpr_e(inst, "%s: child cap must have ajdust function %s\n",
  325. __func__, cap_name(entry->cap_id));
  326. rc = -EINVAL;
  327. goto error;
  328. }
  329. prev_value = cap[entry->cap_id].value;
  330. rc = msm_vidc_adjust_cap(inst, entry->cap_id, NULL, __func__);
  331. if (rc)
  332. goto error;
  333. /* add children if cap value modified */
  334. if (cap[entry->cap_id].value != prev_value) {
  335. /* add cap_id to firmware list always */
  336. rc = msm_vidc_add_capid_to_fw_list(inst, entry->cap_id);
  337. if (rc)
  338. goto error;
  339. rc = msm_vidc_add_children(inst, entry->cap_id);
  340. if (rc)
  341. goto error;
  342. }
  343. list_del_init(&entry->list);
  344. msm_vidc_vmem_free((void **)&entry);
  345. }
  346. /* expecting children_list to be empty */
  347. if (!list_empty(&inst->children_list)) {
  348. i_vpr_e(inst, "%s: child_list is not empty\n", __func__);
  349. rc = -EINVAL;
  350. goto error;
  351. }
  352. return 0;
  353. error:
  354. list_for_each_entry_safe(entry, temp, &inst->children_list, list) {
  355. i_vpr_e(inst, "%s: child list: %s\n", __func__, cap_name(entry->cap_id));
  356. list_del_init(&entry->list);
  357. msm_vidc_vmem_free((void **)&entry);
  358. }
  359. list_for_each_entry_safe(entry, temp, &inst->firmware_list, list) {
  360. i_vpr_e(inst, "%s: fw list: %s\n", __func__, cap_name(entry->cap_id));
  361. list_del_init(&entry->list);
  362. msm_vidc_vmem_free((void **)&entry);
  363. }
  364. return rc;
  365. }
  366. static int msm_vidc_set_dynamic_property(struct msm_vidc_inst *inst)
  367. {
  368. struct msm_vidc_inst_cap_entry *entry = NULL, *temp = NULL;
  369. int rc = 0;
  370. if (!inst) {
  371. d_vpr_e("%s: invalid params\n", __func__);
  372. return -EINVAL;
  373. }
  374. i_vpr_h(inst, "%s()\n", __func__);
  375. list_for_each_entry_safe(entry, temp, &inst->firmware_list, list) {
  376. rc = msm_vidc_set_cap(inst, entry->cap_id, __func__);
  377. if (rc)
  378. goto error;
  379. list_del_init(&entry->list);
  380. msm_vidc_vmem_free((void **)&entry);
  381. }
  382. return 0;
  383. error:
  384. list_for_each_entry_safe(entry, temp, &inst->firmware_list, list) {
  385. i_vpr_e(inst, "%s: fw list: %s\n", __func__, cap_name(entry->cap_id));
  386. list_del_init(&entry->list);
  387. msm_vidc_vmem_free((void **)&entry);
  388. }
  389. return rc;
  390. }
  391. int msm_vidc_ctrl_deinit(struct msm_vidc_inst *inst)
  392. {
  393. if (!inst) {
  394. d_vpr_e("%s: invalid parameters\n", __func__);
  395. return -EINVAL;
  396. }
  397. i_vpr_h(inst, "%s(): num ctrls %d\n", __func__, inst->num_ctrls);
  398. v4l2_ctrl_handler_free(&inst->ctrl_handler);
  399. memset(&inst->ctrl_handler, 0, sizeof(struct v4l2_ctrl_handler));
  400. msm_vidc_vmem_free((void **)&inst->ctrls);
  401. inst->ctrls = NULL;
  402. return 0;
  403. }
  404. int msm_vidc_ctrl_init(struct msm_vidc_inst *inst)
  405. {
  406. int rc = 0;
  407. struct msm_vidc_inst_cap *cap;
  408. struct msm_vidc_core *core;
  409. int idx = 0;
  410. struct v4l2_ctrl_config ctrl_cfg = {0};
  411. int num_ctrls = 0, ctrl_idx = 0;
  412. if (!inst || !inst->core) {
  413. d_vpr_e("%s: invalid params\n", __func__);
  414. return -EINVAL;
  415. }
  416. core = inst->core;
  417. cap = &inst->capabilities[0];
  418. if (!core->v4l2_ctrl_ops) {
  419. i_vpr_e(inst, "%s: no control ops\n", __func__);
  420. return -EINVAL;
  421. }
  422. for (idx = 0; idx < INST_CAP_MAX; idx++) {
  423. if (cap[idx].v4l2_id)
  424. num_ctrls++;
  425. }
  426. if (!num_ctrls) {
  427. i_vpr_e(inst, "%s: no ctrls available in cap database\n",
  428. __func__);
  429. return -EINVAL;
  430. }
  431. rc = msm_vidc_vmem_alloc(num_ctrls * sizeof(struct v4l2_ctrl *),
  432. (void **)&inst->ctrls, __func__);
  433. if (rc)
  434. return rc;
  435. rc = v4l2_ctrl_handler_init(&inst->ctrl_handler, num_ctrls);
  436. if (rc) {
  437. i_vpr_e(inst, "control handler init failed, %d\n",
  438. inst->ctrl_handler.error);
  439. goto error;
  440. }
  441. for (idx = 0; idx < INST_CAP_MAX; idx++) {
  442. struct v4l2_ctrl *ctrl;
  443. if (!cap[idx].v4l2_id)
  444. continue;
  445. if (ctrl_idx >= num_ctrls) {
  446. i_vpr_e(inst,
  447. "%s: invalid ctrl %#x, max allowed %d\n",
  448. __func__, cap[idx].v4l2_id,
  449. num_ctrls);
  450. rc = -EINVAL;
  451. goto error;
  452. }
  453. i_vpr_l(inst,
  454. "%s: cap[%d] %24s, value %d min %d max %d step_or_mask %#x flags %#x v4l2_id %#x hfi_id %#x\n",
  455. __func__, idx, cap_name(idx),
  456. cap[idx].value,
  457. cap[idx].min,
  458. cap[idx].max,
  459. cap[idx].step_or_mask,
  460. cap[idx].flags,
  461. cap[idx].v4l2_id,
  462. cap[idx].hfi_id);
  463. memset(&ctrl_cfg, 0, sizeof(struct v4l2_ctrl_config));
  464. if (is_priv_ctrl(cap[idx].v4l2_id)) {
  465. /* add private control */
  466. ctrl_cfg.def = cap[idx].value;
  467. ctrl_cfg.flags = 0;
  468. ctrl_cfg.id = cap[idx].v4l2_id;
  469. ctrl_cfg.max = cap[idx].max;
  470. ctrl_cfg.min = cap[idx].min;
  471. ctrl_cfg.ops = core->v4l2_ctrl_ops;
  472. if (cap[idx].flags & CAP_FLAG_MENU)
  473. ctrl_cfg.type = V4L2_CTRL_TYPE_MENU;
  474. else if (cap[idx].flags & CAP_FLAG_BITMASK)
  475. ctrl_cfg.type = V4L2_CTRL_TYPE_BITMASK;
  476. else
  477. ctrl_cfg.type = V4L2_CTRL_TYPE_INTEGER;
  478. if (is_meta_cap(inst, idx)) {
  479. /* bitmask is expected to be enabled for meta controls */
  480. if (ctrl_cfg.type != V4L2_CTRL_TYPE_BITMASK) {
  481. i_vpr_e(inst,
  482. "%s: missing bitmask for cap %s\n",
  483. __func__, cap_name(idx));
  484. rc = -EINVAL;
  485. goto error;
  486. }
  487. }
  488. if (ctrl_cfg.type == V4L2_CTRL_TYPE_MENU) {
  489. ctrl_cfg.menu_skip_mask =
  490. ~(cap[idx].step_or_mask);
  491. ctrl_cfg.qmenu = msm_vidc_get_qmenu_type(inst,
  492. cap[idx].cap_id);
  493. } else {
  494. ctrl_cfg.step =
  495. cap[idx].step_or_mask;
  496. }
  497. ctrl_cfg.name = cap_name(cap[idx].cap_id);
  498. if (!ctrl_cfg.name) {
  499. i_vpr_e(inst, "%s: %#x ctrl name is null\n",
  500. __func__, ctrl_cfg.id);
  501. rc = -EINVAL;
  502. goto error;
  503. }
  504. ctrl = v4l2_ctrl_new_custom(&inst->ctrl_handler,
  505. &ctrl_cfg, NULL);
  506. } else {
  507. if (cap[idx].flags & CAP_FLAG_MENU) {
  508. ctrl = v4l2_ctrl_new_std_menu(
  509. &inst->ctrl_handler,
  510. core->v4l2_ctrl_ops,
  511. cap[idx].v4l2_id,
  512. cap[idx].max,
  513. ~(cap[idx].step_or_mask),
  514. cap[idx].value);
  515. } else {
  516. ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler,
  517. core->v4l2_ctrl_ops,
  518. cap[idx].v4l2_id,
  519. cap[idx].min,
  520. cap[idx].max,
  521. cap[idx].step_or_mask,
  522. cap[idx].value);
  523. }
  524. }
  525. if (!ctrl) {
  526. i_vpr_e(inst, "%s: invalid ctrl %#x cap %24s\n", __func__,
  527. cap[idx].v4l2_id, cap_name(idx));
  528. rc = -EINVAL;
  529. goto error;
  530. }
  531. rc = inst->ctrl_handler.error;
  532. if (rc) {
  533. i_vpr_e(inst,
  534. "error adding ctrl (%#x) to ctrl handle, %d\n",
  535. cap[idx].v4l2_id,
  536. inst->ctrl_handler.error);
  537. goto error;
  538. }
  539. if (cap[idx].flags & CAP_FLAG_VOLATILE)
  540. ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
  541. ctrl->flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
  542. inst->ctrls[ctrl_idx] = ctrl;
  543. ctrl_idx++;
  544. }
  545. inst->num_ctrls = num_ctrls;
  546. i_vpr_h(inst, "%s(): num ctrls %d\n", __func__, inst->num_ctrls);
  547. return 0;
  548. error:
  549. msm_vidc_ctrl_deinit(inst);
  550. return rc;
  551. }
  552. static int msm_vidc_update_buffer_count_if_needed(struct msm_vidc_inst* inst,
  553. enum msm_vidc_inst_capability_type cap_id)
  554. {
  555. int rc = 0;
  556. bool update_input_port = false, update_output_port = false;
  557. if (!inst) {
  558. d_vpr_e("%s: invalid parameters\n", __func__);
  559. return -EINVAL;
  560. }
  561. switch (cap_id) {
  562. case LAYER_TYPE:
  563. case ENH_LAYER_COUNT:
  564. case LAYER_ENABLE:
  565. update_input_port = true;
  566. break;
  567. case THUMBNAIL_MODE:
  568. case PRIORITY:
  569. update_input_port = true;
  570. update_output_port = true;
  571. break;
  572. default:
  573. update_input_port = false;
  574. update_output_port = false;
  575. break;
  576. }
  577. if (update_input_port) {
  578. rc = msm_vidc_update_buffer_count(inst, INPUT_PORT);
  579. if (rc)
  580. return rc;
  581. }
  582. if (update_output_port) {
  583. rc = msm_vidc_update_buffer_count(inst, OUTPUT_PORT);
  584. if (rc)
  585. return rc;
  586. }
  587. return rc;
  588. }
  589. static int msm_vidc_allow_secure_session(struct msm_vidc_inst *inst)
  590. {
  591. int rc = 0;
  592. struct msm_vidc_inst *i;
  593. struct msm_vidc_core *core;
  594. u32 count = 0;
  595. if (!inst || !inst->core) {
  596. d_vpr_e("%s: invalid params\n", __func__);
  597. return -EINVAL;
  598. }
  599. core = inst->core;
  600. core_lock(core, __func__);
  601. list_for_each_entry(i, &core->instances, list) {
  602. if (i->capabilities[SECURE_MODE].value)
  603. count++;
  604. }
  605. if (count > core->capabilities[MAX_SECURE_SESSION_COUNT].value) {
  606. i_vpr_e(inst,
  607. "%s: total secure sessions %d exceeded max limit %d\n",
  608. __func__, count,
  609. core->capabilities[MAX_SECURE_SESSION_COUNT].value);
  610. rc = -EINVAL;
  611. }
  612. core_unlock(core, __func__);
  613. return rc;
  614. }
  615. int msm_v4l2_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
  616. {
  617. int rc = 0;
  618. struct msm_vidc_inst *inst;
  619. if (!ctrl) {
  620. d_vpr_e("%s: invalid ctrl parameter\n", __func__);
  621. return -EINVAL;
  622. }
  623. inst = container_of(ctrl->handler,
  624. struct msm_vidc_inst, ctrl_handler);
  625. inst = get_inst_ref(g_core, inst);
  626. if (!inst) {
  627. d_vpr_e("%s: could not find inst for ctrl %s id %#x\n",
  628. __func__, ctrl->name, ctrl->id);
  629. return -EINVAL;
  630. }
  631. client_lock(inst, __func__);
  632. inst_lock(inst, __func__);
  633. rc = msm_vidc_get_control(inst, ctrl);
  634. if (rc) {
  635. i_vpr_e(inst, "%s: failed for ctrl %s id %#x\n",
  636. __func__, ctrl->name, ctrl->id);
  637. goto unlock;
  638. } else {
  639. i_vpr_h(inst, "%s: ctrl %s id %#x, value %d\n",
  640. __func__, ctrl->name, ctrl->id, ctrl->val);
  641. }
  642. unlock:
  643. inst_unlock(inst, __func__);
  644. client_unlock(inst, __func__);
  645. put_inst(inst);
  646. return rc;
  647. }
  648. static int msm_vidc_update_static_property(struct msm_vidc_inst *inst,
  649. enum msm_vidc_inst_capability_type cap_id, struct v4l2_ctrl *ctrl)
  650. {
  651. int rc = 0;
  652. if (!inst || !ctrl) {
  653. d_vpr_e("%s: invalid params\n", __func__);
  654. return -EINVAL;
  655. }
  656. if (cap_id == DRV_VERSION) {
  657. i_vpr_e(inst, "%s: driver version update not allowed\n",
  658. __func__);
  659. return -EINVAL;
  660. }
  661. /* update value to db */
  662. msm_vidc_update_cap_value(inst, cap_id, ctrl->val, __func__);
  663. if (cap_id == CLIENT_ID) {
  664. rc = msm_vidc_update_debug_str(inst);
  665. if (rc)
  666. return rc;
  667. }
  668. if (cap_id == SECURE_MODE) {
  669. if (ctrl->val) {
  670. rc = msm_vidc_allow_secure_session(inst);
  671. if (rc)
  672. return rc;
  673. }
  674. }
  675. if (cap_id == ROTATION) {
  676. struct v4l2_format *output_fmt;
  677. output_fmt = &inst->fmts[OUTPUT_PORT];
  678. rc = msm_venc_s_fmt_output(inst, output_fmt);
  679. if (rc)
  680. return rc;
  681. }
  682. if (cap_id == DELIVERY_MODE) {
  683. struct v4l2_format *output_fmt;
  684. output_fmt = &inst->fmts[OUTPUT_PORT];
  685. rc = msm_venc_s_fmt_output(inst, output_fmt);
  686. if (rc)
  687. return rc;
  688. }
  689. if (cap_id == BITSTREAM_SIZE_OVERWRITE) {
  690. rc = msm_vidc_update_bitstream_buffer_size(inst);
  691. if (rc)
  692. return rc;
  693. }
  694. /* call this explicitly to adjust client priority */
  695. if (cap_id == PRIORITY) {
  696. rc = msm_vidc_adjust_session_priority(inst, ctrl);
  697. if (rc)
  698. return rc;
  699. }
  700. if (cap_id == CRITICAL_PRIORITY)
  701. msm_vidc_update_cap_value(inst, PRIORITY, 0, __func__);
  702. if (cap_id == ENH_LAYER_COUNT && inst->codec == MSM_VIDC_HEVC) {
  703. u32 enable;
  704. /* enable LAYER_ENABLE cap if HEVC_HIER enh layers > 0 */
  705. if (ctrl->val > 0)
  706. enable = 1;
  707. else
  708. enable = 0;
  709. msm_vidc_update_cap_value(inst, LAYER_ENABLE, enable, __func__);
  710. }
  711. if (is_meta_cap(inst, cap_id)) {
  712. rc = msm_vidc_update_meta_port_settings(inst);
  713. if (rc)
  714. return rc;
  715. }
  716. rc = msm_vidc_update_buffer_count_if_needed(inst, cap_id);
  717. if (rc)
  718. return rc;
  719. return rc;
  720. }
  721. int msm_vidc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
  722. {
  723. enum msm_vidc_inst_capability_type cap_id;
  724. struct msm_vidc_inst_cap *cap;
  725. int rc = 0;
  726. u32 port;
  727. if (!inst || !ctrl) {
  728. d_vpr_e("%s: invalid params\n", __func__);
  729. return -EINVAL;
  730. }
  731. cap = &inst->capabilities[0];
  732. i_vpr_h(inst, FMT_STRING_SET_CTRL,
  733. __func__, state_name(inst->state), ctrl->name, ctrl->id, ctrl->val);
  734. cap_id = msm_vidc_get_cap_id(inst, ctrl->id);
  735. if (!is_valid_cap_id(cap_id)) {
  736. i_vpr_e(inst, "%s: invalid cap_id for ctrl %s\n", __func__, ctrl->name);
  737. return -EINVAL;
  738. }
  739. /* mark client set flag */
  740. cap[cap_id].flags |= CAP_FLAG_CLIENT_SET;
  741. port = is_encode_session(inst) ? OUTPUT_PORT : INPUT_PORT;
  742. if (!inst->bufq[port].vb2q->streaming) {
  743. /* static case */
  744. rc = msm_vidc_update_static_property(inst, cap_id, ctrl);
  745. if (rc)
  746. return rc;
  747. } else {
  748. /* dynamic case */
  749. rc = msm_vidc_adjust_dynamic_property(inst, cap_id, ctrl);
  750. if (rc)
  751. return rc;
  752. rc = msm_vidc_set_dynamic_property(inst);
  753. if (rc)
  754. return rc;
  755. }
  756. return rc;
  757. }
  758. int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
  759. {
  760. struct msm_vidc_inst *inst;
  761. int rc = 0;
  762. if (!ctrl) {
  763. d_vpr_e("%s: invalid ctrl parameter\n", __func__);
  764. return -EINVAL;
  765. }
  766. inst = container_of(ctrl->handler, struct msm_vidc_inst, ctrl_handler);
  767. inst = get_inst_ref(g_core, inst);
  768. if (!inst) {
  769. d_vpr_e("%s: invalid instance\n", __func__);
  770. return -EINVAL;
  771. }
  772. client_lock(inst, __func__);
  773. inst_lock(inst, __func__);
  774. rc = inst->event_handle(inst, MSM_VIDC_S_CTRL, ctrl);
  775. if (rc)
  776. goto unlock;
  777. unlock:
  778. inst_unlock(inst, __func__);
  779. client_unlock(inst, __func__);
  780. put_inst(inst);
  781. return rc;
  782. }
  783. int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst)
  784. {
  785. struct list_head leaf_list, opt_list;
  786. struct msm_vidc_inst_cap *cap, *lcap, *temp_cap;
  787. struct msm_vidc_inst_cap_entry *entry = NULL, *temp = NULL;
  788. bool leaf_visited[INST_CAP_MAX];
  789. bool opt_visited[INST_CAP_MAX];
  790. int tmp_count_total, tmp_count, num_nodes = 0;
  791. int i, rc = 0;
  792. if (!inst) {
  793. d_vpr_e("%s: invalid params\n", __func__);
  794. return -EINVAL;
  795. }
  796. cap = &inst->capabilities[0];
  797. if (!list_empty(&inst->caps_list)) {
  798. i_vpr_h(inst, "%s: dependency list already prepared\n", __func__);
  799. return 0;
  800. }
  801. /* init local list and lookup table entries */
  802. INIT_LIST_HEAD(&leaf_list);
  803. INIT_LIST_HEAD(&opt_list);
  804. memset(&leaf_visited, 0, sizeof(leaf_visited));
  805. memset(&opt_visited, 0, sizeof(opt_visited));
  806. /* populate leaf nodes first */
  807. for (i = 1; i < INST_CAP_MAX; i++) {
  808. lcap = &cap[i];
  809. if (!is_valid_cap(inst, lcap->cap_id))
  810. continue;
  811. /* sanitize cap value */
  812. if (i != lcap->cap_id) {
  813. i_vpr_e(inst, "%s: cap id mismatch. expected %s, actual %s\n",
  814. __func__, cap_name(i), cap_name(lcap->cap_id));
  815. rc = -EINVAL;
  816. goto error;
  817. }
  818. /* add all leaf nodes */
  819. if (is_leaf(lcap)) {
  820. rc = add_node(&leaf_list, lcap, leaf_visited);
  821. if (rc)
  822. goto error;
  823. } else {
  824. rc = add_node(&opt_list, lcap, opt_visited);
  825. if (rc)
  826. goto error;
  827. }
  828. }
  829. /* find total optional list entries */
  830. list_for_each_entry(entry, &opt_list, list)
  831. num_nodes++;
  832. /* used for loop detection */
  833. tmp_count_total = num_nodes;
  834. tmp_count = num_nodes;
  835. /* sort final outstanding nodes */
  836. list_for_each_entry_safe(entry, temp, &opt_list, list) {
  837. /* initially remove entry from opt list */
  838. list_del_init(&entry->list);
  839. opt_visited[entry->cap_id] = false;
  840. tmp_count--;
  841. temp_cap = &cap[entry->cap_id];
  842. /**
  843. * if all child are visited then add this entry to
  844. * leaf list else add it to the end of optional list.
  845. */
  846. if (is_all_childrens_visited(temp_cap, leaf_visited)) {
  847. list_add(&entry->list, &leaf_list);
  848. leaf_visited[entry->cap_id] = true;
  849. tmp_count_total--;
  850. } else {
  851. list_add_tail(&entry->list, &opt_list);
  852. opt_visited[entry->cap_id] = true;
  853. }
  854. /* detect loop */
  855. if (!tmp_count) {
  856. if (num_nodes == tmp_count_total) {
  857. i_vpr_e(inst, "%s: loop detected in subgraph %d\n",
  858. __func__, num_nodes);
  859. rc = -EINVAL;
  860. goto error;
  861. }
  862. num_nodes = tmp_count_total;
  863. tmp_count = tmp_count_total;
  864. }
  865. }
  866. /* expecting opt_list to be empty */
  867. if (!list_empty(&opt_list)) {
  868. i_vpr_e(inst, "%s: opt_list is not empty\n", __func__);
  869. rc = -EINVAL;
  870. goto error;
  871. }
  872. /* move elements to &inst->caps_list from local */
  873. list_replace_init(&leaf_list, &inst->caps_list);
  874. return 0;
  875. error:
  876. list_for_each_entry_safe(entry, temp, &opt_list, list) {
  877. i_vpr_e(inst, "%s: opt_list: %s\n", __func__, cap_name(entry->cap_id));
  878. list_del_init(&entry->list);
  879. msm_vidc_vmem_free((void **)&entry);
  880. }
  881. list_for_each_entry_safe(entry, temp, &leaf_list, list) {
  882. i_vpr_e(inst, "%s: leaf_list: %s\n", __func__, cap_name(entry->cap_id));
  883. list_del_init(&entry->list);
  884. msm_vidc_vmem_free((void **)&entry);
  885. }
  886. return rc;
  887. }
  888. int msm_vidc_adjust_v4l2_properties(struct msm_vidc_inst *inst)
  889. {
  890. struct msm_vidc_inst_cap_entry *entry = NULL, *temp = NULL;
  891. int rc = 0;
  892. if (!inst) {
  893. d_vpr_e("%s: invalid params\n", __func__);
  894. return -EINVAL;
  895. }
  896. i_vpr_h(inst, "%s()\n", __func__);
  897. /* adjust all possible caps from caps_list */
  898. list_for_each_entry_safe(entry, temp, &inst->caps_list, list) {
  899. i_vpr_l(inst, "%s: cap: id %3u, name %s\n", __func__,
  900. entry->cap_id, cap_name(entry->cap_id));
  901. rc = msm_vidc_adjust_cap(inst, entry->cap_id, NULL, __func__);
  902. if (rc)
  903. return rc;
  904. }
  905. return rc;
  906. }
  907. int msm_vidc_set_v4l2_properties(struct msm_vidc_inst *inst)
  908. {
  909. struct msm_vidc_inst_cap_entry *entry = NULL, *temp = NULL;
  910. int rc = 0;
  911. if (!inst) {
  912. d_vpr_e("%s: invalid params\n", __func__);
  913. return -EINVAL;
  914. }
  915. i_vpr_h(inst, "%s()\n", __func__);
  916. /* set all caps from caps_list */
  917. list_for_each_entry_safe(entry, temp, &inst->caps_list, list) {
  918. rc = msm_vidc_set_cap(inst, entry->cap_id, __func__);
  919. if (rc)
  920. return rc;
  921. }
  922. return rc;
  923. }