msm_vidc_control.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095
  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 || !inst->capabilities)
  142. return false;
  143. if (cap_id <= INST_CAP_NONE || cap_id >= INST_CAP_MAX)
  144. return false;
  145. return !!inst->capabilities->cap[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[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[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[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_capability *capability;
  278. s32 prev_value;
  279. int rc = 0;
  280. if (!inst || !inst->capabilities || !ctrl) {
  281. d_vpr_e("%s: invalid param\n", __func__);
  282. return -EINVAL;
  283. }
  284. capability = inst->capabilities;
  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 (!(capability->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 = capability->cap[cap_id].value;
  298. rc = msm_vidc_adjust_cap(inst, cap_id, ctrl, __func__);
  299. if (rc)
  300. return rc;
  301. if (capability->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 (capability->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 (!capability->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 = capability->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 (capability->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_capability *capability;
  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 || !inst->capabilities) {
  413. d_vpr_e("%s: invalid params\n", __func__);
  414. return -EINVAL;
  415. }
  416. core = inst->core;
  417. capability = inst->capabilities;
  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 (capability->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 (!capability->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__, capability->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. capability->cap[idx].value,
  457. capability->cap[idx].min,
  458. capability->cap[idx].max,
  459. capability->cap[idx].step_or_mask,
  460. capability->cap[idx].flags,
  461. capability->cap[idx].v4l2_id,
  462. capability->cap[idx].hfi_id);
  463. memset(&ctrl_cfg, 0, sizeof(struct v4l2_ctrl_config));
  464. if (is_priv_ctrl(capability->cap[idx].v4l2_id)) {
  465. /* add private control */
  466. ctrl_cfg.def = capability->cap[idx].value;
  467. ctrl_cfg.flags = 0;
  468. ctrl_cfg.id = capability->cap[idx].v4l2_id;
  469. ctrl_cfg.max = capability->cap[idx].max;
  470. ctrl_cfg.min = capability->cap[idx].min;
  471. ctrl_cfg.ops = core->v4l2_ctrl_ops;
  472. if (capability->cap[idx].flags & CAP_FLAG_MENU)
  473. ctrl_cfg.type = V4L2_CTRL_TYPE_MENU;
  474. else if (capability->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. ~(capability->cap[idx].step_or_mask);
  491. ctrl_cfg.qmenu = msm_vidc_get_qmenu_type(inst,
  492. capability->cap[idx].cap_id);
  493. } else {
  494. ctrl_cfg.step =
  495. capability->cap[idx].step_or_mask;
  496. }
  497. ctrl_cfg.name = cap_name(capability->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 (capability->cap[idx].flags & CAP_FLAG_MENU) {
  508. ctrl = v4l2_ctrl_new_std_menu(
  509. &inst->ctrl_handler,
  510. core->v4l2_ctrl_ops,
  511. capability->cap[idx].v4l2_id,
  512. capability->cap[idx].max,
  513. ~(capability->cap[idx].step_or_mask),
  514. capability->cap[idx].value);
  515. } else {
  516. ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler,
  517. core->v4l2_ctrl_ops,
  518. capability->cap[idx].v4l2_id,
  519. capability->cap[idx].min,
  520. capability->cap[idx].max,
  521. capability->cap[idx].step_or_mask,
  522. capability->cap[idx].value);
  523. }
  524. }
  525. if (!ctrl) {
  526. i_vpr_e(inst, "%s: invalid ctrl %#x cap %24s\n", __func__,
  527. capability->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. capability->cap[idx].v4l2_id,
  536. inst->ctrl_handler.error);
  537. goto error;
  538. }
  539. if (capability->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. if (!core->capabilities) {
  601. i_vpr_e(inst, "%s: invalid params\n", __func__);
  602. return -EINVAL;
  603. }
  604. core_lock(core, __func__);
  605. list_for_each_entry(i, &core->instances, list) {
  606. if (i->capabilities) {
  607. if (i->capabilities->cap[SECURE_MODE].value)
  608. count++;
  609. }
  610. }
  611. if (count > core->capabilities[MAX_SECURE_SESSION_COUNT].value) {
  612. i_vpr_e(inst,
  613. "%s: total secure sessions %d exceeded max limit %d\n",
  614. __func__, count,
  615. core->capabilities[MAX_SECURE_SESSION_COUNT].value);
  616. rc = -EINVAL;
  617. }
  618. core_unlock(core, __func__);
  619. return rc;
  620. }
  621. int msm_v4l2_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
  622. {
  623. int rc = 0;
  624. struct msm_vidc_inst *inst;
  625. if (!ctrl) {
  626. d_vpr_e("%s: invalid ctrl parameter\n", __func__);
  627. return -EINVAL;
  628. }
  629. inst = container_of(ctrl->handler,
  630. struct msm_vidc_inst, ctrl_handler);
  631. inst = get_inst_ref(g_core, inst);
  632. if (!inst) {
  633. d_vpr_e("%s: could not find inst for ctrl %s id %#x\n",
  634. __func__, ctrl->name, ctrl->id);
  635. return -EINVAL;
  636. }
  637. client_lock(inst, __func__);
  638. inst_lock(inst, __func__);
  639. rc = msm_vidc_get_control(inst, ctrl);
  640. if (rc) {
  641. i_vpr_e(inst, "%s: failed for ctrl %s id %#x\n",
  642. __func__, ctrl->name, ctrl->id);
  643. goto unlock;
  644. } else {
  645. i_vpr_h(inst, "%s: ctrl %s id %#x, value %d\n",
  646. __func__, ctrl->name, ctrl->id, ctrl->val);
  647. }
  648. unlock:
  649. inst_unlock(inst, __func__);
  650. client_unlock(inst, __func__);
  651. put_inst(inst);
  652. return rc;
  653. }
  654. static int msm_vidc_update_static_property(struct msm_vidc_inst *inst,
  655. enum msm_vidc_inst_capability_type cap_id, struct v4l2_ctrl *ctrl)
  656. {
  657. int rc = 0;
  658. if (!inst || !ctrl) {
  659. d_vpr_e("%s: invalid params\n", __func__);
  660. return -EINVAL;
  661. }
  662. if (cap_id == DRV_VERSION) {
  663. i_vpr_e(inst, "%s: driver version update not allowed\n",
  664. __func__);
  665. return -EINVAL;
  666. }
  667. /* update value to db */
  668. msm_vidc_update_cap_value(inst, cap_id, ctrl->val, __func__);
  669. if (cap_id == CLIENT_ID) {
  670. rc = msm_vidc_update_debug_str(inst);
  671. if (rc)
  672. return rc;
  673. }
  674. if (cap_id == SECURE_MODE) {
  675. if (ctrl->val) {
  676. rc = msm_vidc_allow_secure_session(inst);
  677. if (rc)
  678. return rc;
  679. }
  680. }
  681. if (cap_id == ROTATION) {
  682. struct v4l2_format *output_fmt;
  683. output_fmt = &inst->fmts[OUTPUT_PORT];
  684. rc = msm_venc_s_fmt_output(inst, output_fmt);
  685. if (rc)
  686. return rc;
  687. }
  688. if (cap_id == DELIVERY_MODE) {
  689. struct v4l2_format *output_fmt;
  690. output_fmt = &inst->fmts[OUTPUT_PORT];
  691. rc = msm_venc_s_fmt_output(inst, output_fmt);
  692. if (rc)
  693. return rc;
  694. }
  695. if (cap_id == BITSTREAM_SIZE_OVERWRITE) {
  696. rc = msm_vidc_update_bitstream_buffer_size(inst);
  697. if (rc)
  698. return rc;
  699. }
  700. /* call this explicitly to adjust client priority */
  701. if (cap_id == PRIORITY) {
  702. rc = msm_vidc_adjust_session_priority(inst, ctrl);
  703. if (rc)
  704. return rc;
  705. }
  706. if (cap_id == CRITICAL_PRIORITY)
  707. msm_vidc_update_cap_value(inst, PRIORITY, 0, __func__);
  708. if (cap_id == ENH_LAYER_COUNT && inst->codec == MSM_VIDC_HEVC) {
  709. u32 enable;
  710. /* enable LAYER_ENABLE cap if HEVC_HIER enh layers > 0 */
  711. if (ctrl->val > 0)
  712. enable = 1;
  713. else
  714. enable = 0;
  715. msm_vidc_update_cap_value(inst, LAYER_ENABLE, enable, __func__);
  716. }
  717. if (is_meta_cap(inst, cap_id)) {
  718. rc = msm_vidc_update_meta_port_settings(inst);
  719. if (rc)
  720. return rc;
  721. }
  722. rc = msm_vidc_update_buffer_count_if_needed(inst, cap_id);
  723. if (rc)
  724. return rc;
  725. return rc;
  726. }
  727. int msm_vidc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
  728. {
  729. enum msm_vidc_inst_capability_type cap_id;
  730. struct msm_vidc_inst_capability *capability;
  731. int rc = 0;
  732. u32 port;
  733. if (!inst || !inst->capabilities || !ctrl) {
  734. d_vpr_e("%s: invalid params\n", __func__);
  735. return -EINVAL;
  736. }
  737. capability = inst->capabilities;
  738. i_vpr_h(inst, FMT_STRING_SET_CTRL,
  739. __func__, state_name(inst->state), ctrl->name, ctrl->id, ctrl->val);
  740. cap_id = msm_vidc_get_cap_id(inst, ctrl->id);
  741. if (!is_valid_cap_id(cap_id)) {
  742. i_vpr_e(inst, "%s: invalid cap_id for ctrl %s\n", __func__, ctrl->name);
  743. return -EINVAL;
  744. }
  745. /* mark client set flag */
  746. capability->cap[cap_id].flags |= CAP_FLAG_CLIENT_SET;
  747. port = is_encode_session(inst) ? OUTPUT_PORT : INPUT_PORT;
  748. if (!inst->bufq[port].vb2q->streaming) {
  749. /* static case */
  750. rc = msm_vidc_update_static_property(inst, cap_id, ctrl);
  751. if (rc)
  752. return rc;
  753. } else {
  754. /* dynamic case */
  755. rc = msm_vidc_adjust_dynamic_property(inst, cap_id, ctrl);
  756. if (rc)
  757. return rc;
  758. rc = msm_vidc_set_dynamic_property(inst);
  759. if (rc)
  760. return rc;
  761. }
  762. return rc;
  763. }
  764. int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
  765. {
  766. struct msm_vidc_inst *inst;
  767. int rc = 0;
  768. if (!ctrl) {
  769. d_vpr_e("%s: invalid ctrl parameter\n", __func__);
  770. return -EINVAL;
  771. }
  772. inst = container_of(ctrl->handler, struct msm_vidc_inst, ctrl_handler);
  773. inst = get_inst_ref(g_core, inst);
  774. if (!inst) {
  775. d_vpr_e("%s: invalid instance\n", __func__);
  776. return -EINVAL;
  777. }
  778. client_lock(inst, __func__);
  779. inst_lock(inst, __func__);
  780. rc = inst->event_handle(inst, MSM_VIDC_S_CTRL, ctrl);
  781. if (rc)
  782. goto unlock;
  783. unlock:
  784. inst_unlock(inst, __func__);
  785. client_unlock(inst, __func__);
  786. put_inst(inst);
  787. return rc;
  788. }
  789. int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst)
  790. {
  791. struct list_head leaf_list, opt_list;
  792. struct msm_vidc_inst_capability *capability;
  793. struct msm_vidc_inst_cap *cap, *lcap;
  794. struct msm_vidc_inst_cap_entry *entry = NULL, *temp = NULL;
  795. bool leaf_visited[INST_CAP_MAX];
  796. bool opt_visited[INST_CAP_MAX];
  797. int tmp_count_total, tmp_count, num_nodes = 0;
  798. int i, rc = 0;
  799. if (!inst || !inst->capabilities) {
  800. d_vpr_e("%s: invalid params\n", __func__);
  801. return -EINVAL;
  802. }
  803. capability = inst->capabilities;
  804. if (!list_empty(&inst->caps_list)) {
  805. i_vpr_h(inst, "%s: dependency list already prepared\n", __func__);
  806. return 0;
  807. }
  808. /* init local list and lookup table entries */
  809. INIT_LIST_HEAD(&leaf_list);
  810. INIT_LIST_HEAD(&opt_list);
  811. memset(&leaf_visited, 0, sizeof(leaf_visited));
  812. memset(&opt_visited, 0, sizeof(opt_visited));
  813. /* populate leaf nodes first */
  814. for (i = 1; i < INST_CAP_MAX; i++) {
  815. lcap = &capability->cap[i];
  816. if (!is_valid_cap(inst, lcap->cap_id))
  817. continue;
  818. /* sanitize cap value */
  819. if (i != lcap->cap_id) {
  820. i_vpr_e(inst, "%s: cap id mismatch. expected %s, actual %s\n",
  821. __func__, cap_name(i), cap_name(lcap->cap_id));
  822. rc = -EINVAL;
  823. goto error;
  824. }
  825. /* add all leaf nodes */
  826. if (is_leaf(lcap)) {
  827. rc = add_node(&leaf_list, lcap, leaf_visited);
  828. if (rc)
  829. goto error;
  830. } else {
  831. rc = add_node(&opt_list, lcap, opt_visited);
  832. if (rc)
  833. goto error;
  834. }
  835. }
  836. /* find total optional list entries */
  837. list_for_each_entry(entry, &opt_list, list)
  838. num_nodes++;
  839. /* used for loop detection */
  840. tmp_count_total = num_nodes;
  841. tmp_count = num_nodes;
  842. /* sort final outstanding nodes */
  843. list_for_each_entry_safe(entry, temp, &opt_list, list) {
  844. /* initially remove entry from opt list */
  845. list_del_init(&entry->list);
  846. opt_visited[entry->cap_id] = false;
  847. tmp_count--;
  848. cap = &capability->cap[entry->cap_id];
  849. /**
  850. * if all child are visited then add this entry to
  851. * leaf list else add it to the end of optional list.
  852. */
  853. if (is_all_childrens_visited(cap, leaf_visited)) {
  854. list_add(&entry->list, &leaf_list);
  855. leaf_visited[entry->cap_id] = true;
  856. tmp_count_total--;
  857. } else {
  858. list_add_tail(&entry->list, &opt_list);
  859. opt_visited[entry->cap_id] = true;
  860. }
  861. /* detect loop */
  862. if (!tmp_count) {
  863. if (num_nodes == tmp_count_total) {
  864. i_vpr_e(inst, "%s: loop detected in subgraph %d\n",
  865. __func__, num_nodes);
  866. rc = -EINVAL;
  867. goto error;
  868. }
  869. num_nodes = tmp_count_total;
  870. tmp_count = tmp_count_total;
  871. }
  872. }
  873. /* expecting opt_list to be empty */
  874. if (!list_empty(&opt_list)) {
  875. i_vpr_e(inst, "%s: opt_list is not empty\n", __func__);
  876. rc = -EINVAL;
  877. goto error;
  878. }
  879. /* move elements to &inst->caps_list from local */
  880. list_replace_init(&leaf_list, &inst->caps_list);
  881. return 0;
  882. error:
  883. list_for_each_entry_safe(entry, temp, &opt_list, list) {
  884. i_vpr_e(inst, "%s: opt_list: %s\n", __func__, cap_name(entry->cap_id));
  885. list_del_init(&entry->list);
  886. msm_vidc_vmem_free((void **)&entry);
  887. }
  888. list_for_each_entry_safe(entry, temp, &leaf_list, list) {
  889. i_vpr_e(inst, "%s: leaf_list: %s\n", __func__, cap_name(entry->cap_id));
  890. list_del_init(&entry->list);
  891. msm_vidc_vmem_free((void **)&entry);
  892. }
  893. return rc;
  894. }
  895. int msm_vidc_adjust_v4l2_properties(struct msm_vidc_inst *inst)
  896. {
  897. struct msm_vidc_inst_cap_entry *entry = NULL, *temp = NULL;
  898. int rc = 0;
  899. if (!inst || !inst->capabilities) {
  900. d_vpr_e("%s: invalid params\n", __func__);
  901. return -EINVAL;
  902. }
  903. i_vpr_h(inst, "%s()\n", __func__);
  904. /* adjust all possible caps from caps_list */
  905. list_for_each_entry_safe(entry, temp, &inst->caps_list, list) {
  906. i_vpr_l(inst, "%s: cap: id %3u, name %s\n", __func__,
  907. entry->cap_id, cap_name(entry->cap_id));
  908. rc = msm_vidc_adjust_cap(inst, entry->cap_id, NULL, __func__);
  909. if (rc)
  910. return rc;
  911. }
  912. return rc;
  913. }
  914. int msm_vidc_set_v4l2_properties(struct msm_vidc_inst *inst)
  915. {
  916. struct msm_vidc_inst_cap_entry *entry = NULL, *temp = NULL;
  917. int rc = 0;
  918. if (!inst || !inst->capabilities) {
  919. d_vpr_e("%s: invalid params\n", __func__);
  920. return -EINVAL;
  921. }
  922. i_vpr_h(inst, "%s()\n", __func__);
  923. /* set all caps from caps_list */
  924. list_for_each_entry_safe(entry, temp, &inst->caps_list, list) {
  925. rc = msm_vidc_set_cap(inst, entry->cap_id, __func__);
  926. if (rc)
  927. return rc;
  928. }
  929. return rc;
  930. }