msm_vidc_probe.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/workqueue.h>
  6. #include <linux/module.h>
  7. #include <linux/io.h>
  8. #include <linux/of.h>
  9. #include <linux/of_platform.h>
  10. #include <linux/component.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/iommu.h>
  13. #include <linux/dma-iommu.h>
  14. #ifdef CONFIG_MSM_MMRM
  15. #include <linux/soc/qcom/msm_mmrm.h>
  16. #endif
  17. #include "msm_vidc_internal.h"
  18. #include "msm_vidc_debug.h"
  19. #include "msm_vidc_driver.h"
  20. #include "msm_vidc_platform.h"
  21. #include "msm_vidc_core.h"
  22. #include "msm_vidc_memory.h"
  23. #include "venus_hfi.h"
  24. #include "video_generated_h"
  25. #define BASE_DEVICE_NUMBER 32
  26. struct msm_vidc_core *g_core;
  27. const char video_banner[] = "Video-Banner: (" VIDEO_COMPILE_BY "@"
  28. VIDEO_COMPILE_HOST ") (" VIDEO_COMPILE_TIME ")";
  29. static inline bool is_video_device(struct device *dev)
  30. {
  31. return !!(of_device_is_compatible(dev->of_node, "qcom,sm8450-vidc") ||
  32. of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc") ||
  33. of_device_is_compatible(dev->of_node, "qcom,sm8550-vidc-v2") ||
  34. of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc"));
  35. }
  36. static inline bool is_video_context_bank_device(struct device *dev)
  37. {
  38. return !!(of_device_is_compatible(dev->of_node, "qcom,vidc,cb-sec-pxl") ||
  39. of_device_is_compatible(dev->of_node, "qcom,vidc,cb-sec-bitstream") ||
  40. of_device_is_compatible(dev->of_node, "qcom,vidc,cb-sec-non-pxl") ||
  41. of_device_is_compatible(dev->of_node, "qcom,vidc,cb-ns") ||
  42. of_device_is_compatible(dev->of_node, "qcom,vidc,cb-ns-pxl"));
  43. }
  44. static int msm_vidc_init_resources(struct msm_vidc_core *core)
  45. {
  46. struct msm_vidc_resource *res = NULL;
  47. int rc = 0;
  48. if (!core) {
  49. d_vpr_e("%s: invalid params\n", __func__);
  50. return -EINVAL;
  51. }
  52. res = devm_kzalloc(&core->pdev->dev, sizeof(*res), GFP_KERNEL);
  53. if (!res) {
  54. d_vpr_e("%s: failed to alloc memory for resource\n", __func__);
  55. return -ENOMEM;
  56. }
  57. res->core = core;
  58. core->resource = res;
  59. rc = call_res_op(core, init, core);
  60. if (rc) {
  61. d_vpr_e("%s: Failed to init resources: %d\n", __func__, rc);
  62. return rc;
  63. }
  64. return 0;
  65. }
  66. static ssize_t sku_version_show(struct device *dev,
  67. struct device_attribute *attr, char *buf)
  68. {
  69. struct msm_vidc_core *core;
  70. /*
  71. * Default sku version: 0
  72. * driver possibly not probed yet or not the main device.
  73. */
  74. if (!dev || !dev->driver)
  75. return 0;
  76. core = dev_get_drvdata(dev);
  77. if (!core || !core->platform) {
  78. d_vpr_e("%s: invalid core\n", __func__);
  79. return 0;
  80. }
  81. return scnprintf(buf, PAGE_SIZE, "%d",
  82. core->platform->data.sku_version);
  83. }
  84. static DEVICE_ATTR_RO(sku_version);
  85. static struct attribute *msm_vidc_core_attrs[] = {
  86. &dev_attr_sku_version.attr,
  87. NULL
  88. };
  89. static struct attribute_group msm_vidc_core_attr_group = {
  90. .attrs = msm_vidc_core_attrs,
  91. };
  92. static const struct of_device_id msm_vidc_dt_match[] = {
  93. {.compatible = "qcom,sm8450-vidc"},
  94. {.compatible = "qcom,sm8550-vidc"},
  95. {.compatible = "qcom,sm8550-vidc-v2"},
  96. {.compatible = "qcom,sm8650-vidc"},
  97. {.compatible = "qcom,vidc,cb-ns-pxl"},
  98. {.compatible = "qcom,vidc,cb-ns"},
  99. {.compatible = "qcom,vidc,cb-sec-non-pxl"},
  100. {.compatible = "qcom,vidc,cb-sec-bitstream"},
  101. {.compatible = "qcom,vidc,cb-sec-pxl"},
  102. MSM_VIDC_EMPTY_BRACE
  103. };
  104. MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
  105. static void msm_vidc_release_video_device(struct video_device *vdev)
  106. {
  107. d_vpr_e("%s:\n", __func__);
  108. }
  109. static void msm_vidc_unregister_video_device(struct msm_vidc_core *core,
  110. enum msm_vidc_domain_type type)
  111. {
  112. int index;
  113. d_vpr_h("%s: domain %d\n", __func__, type);
  114. if (type == MSM_VIDC_DECODER)
  115. index = 0;
  116. else if (type == MSM_VIDC_ENCODER)
  117. index = 1;
  118. else
  119. return;
  120. #ifdef CONFIG_MEDIA_CONTROLLER
  121. v4l2_m2m_unregister_media_controller(core->vdev[index].m2m_dev);
  122. v4l2_m2m_release(core->vdev[index].m2m_dev);
  123. #endif
  124. //rc = device_create_file(&core->vdev[index].vdev.dev, &dev_attr_link_name);
  125. video_set_drvdata(&core->vdev[index].vdev, NULL);
  126. video_unregister_device(&core->vdev[index].vdev);
  127. //memset vdev to 0
  128. }
  129. static int msm_vidc_register_video_device(struct msm_vidc_core *core,
  130. enum msm_vidc_domain_type type, int nr)
  131. {
  132. int rc = 0;
  133. int index, media_index;
  134. d_vpr_h("%s: domain %d\n", __func__, type);
  135. if (!core || !core->capabilities) {
  136. d_vpr_e("%s: invalid params\n", __func__);
  137. return -EINVAL;
  138. }
  139. if (type == MSM_VIDC_DECODER) {
  140. index = 0;
  141. media_index = MEDIA_ENT_F_PROC_VIDEO_DECODER;
  142. } else if (type == MSM_VIDC_ENCODER) {
  143. index = 1;
  144. media_index = MEDIA_ENT_F_PROC_VIDEO_ENCODER;
  145. } else {
  146. return -EINVAL;
  147. }
  148. core->vdev[index].vdev.release =
  149. msm_vidc_release_video_device;
  150. core->vdev[index].vdev.fops = core->v4l2_file_ops;
  151. if (type == MSM_VIDC_DECODER)
  152. core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_dec;
  153. else
  154. core->vdev[index].vdev.ioctl_ops = core->v4l2_ioctl_ops_enc;
  155. core->vdev[index].vdev.vfl_dir = VFL_DIR_M2M;
  156. core->vdev[index].type = type;
  157. core->vdev[index].vdev.v4l2_dev = &core->v4l2_dev;
  158. core->vdev[index].vdev.device_caps = core->capabilities[DEVICE_CAPS].value;
  159. rc = video_register_device(&core->vdev[index].vdev,
  160. VFL_TYPE_VIDEO, nr);
  161. if (rc) {
  162. d_vpr_e("Failed to register the video device\n");
  163. return rc;
  164. }
  165. video_set_drvdata(&core->vdev[index].vdev, core);
  166. //rc = device_create_file(&core->vdev[index].vdev.dev, &dev_attr_link_name);
  167. if (rc) {
  168. d_vpr_e("Failed to create video device file\n");
  169. goto video_reg_failed;
  170. }
  171. #ifdef CONFIG_MEDIA_CONTROLLER
  172. core->vdev[index].m2m_dev = v4l2_m2m_init(core->v4l2_m2m_ops);
  173. if (IS_ERR(core->vdev[index].m2m_dev)) {
  174. d_vpr_e("Failed to initialize V4L2 M2M device\n");
  175. rc = PTR_ERR(core->vdev[index].m2m_dev);
  176. goto m2m_init_failed;
  177. }
  178. rc = v4l2_m2m_register_media_controller(core->vdev[index].m2m_dev,
  179. &core->vdev[index].vdev, media_index);
  180. if (rc) {
  181. d_vpr_e("%s: m2m_dev controller register failed for session type %d\n",
  182. __func__, index);
  183. goto m2m_mc_failed;
  184. }
  185. #endif
  186. return 0;
  187. #ifdef CONFIG_MEDIA_CONTROLLER
  188. m2m_mc_failed:
  189. v4l2_m2m_release(core->vdev[index].m2m_dev);
  190. m2m_init_failed:
  191. #endif
  192. video_reg_failed:
  193. video_unregister_device(&core->vdev[index].vdev);
  194. return rc;
  195. }
  196. #ifdef CONFIG_MSM_MMRM
  197. static int msm_vidc_check_mmrm_support(struct msm_vidc_core *core)
  198. {
  199. int rc = 0;
  200. if (!core || !core->platform) {
  201. d_vpr_e("%s: invalid params\n", __func__);
  202. return -EINVAL;
  203. }
  204. if (!is_mmrm_supported(core))
  205. goto exit;
  206. if (!mmrm_client_check_scaling_supported(MMRM_CLIENT_CLOCK, 0)) {
  207. d_vpr_e("%s: MMRM not supported\n", __func__);
  208. core->platform->data.supports_mmrm = 0;
  209. }
  210. exit:
  211. d_vpr_h("%s: %d\n", __func__, is_mmrm_supported(core));
  212. return rc;
  213. }
  214. #else
  215. static int msm_vidc_check_mmrm_support(struct msm_vidc_core *core)
  216. {
  217. if (!core || !core->platform) {
  218. d_vpr_e("%s: invalid params\n", __func__);
  219. return -EINVAL;
  220. }
  221. core->platform->data.supports_mmrm = 0;
  222. return 0;
  223. }
  224. #endif
  225. static int msm_vidc_deinitialize_core(struct msm_vidc_core *core)
  226. {
  227. int rc = 0;
  228. if (!core) {
  229. d_vpr_e("%s: invalid params\n", __func__);
  230. return -EINVAL;
  231. }
  232. d_vpr_h("%s()\n", __func__);
  233. mutex_destroy(&core->lock);
  234. msm_vidc_change_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
  235. msm_vidc_vmem_free((void **)&core->response_packet);
  236. msm_vidc_vmem_free((void **)&core->packet);
  237. core->response_packet = NULL;
  238. core->packet = NULL;
  239. if (core->batch_workq)
  240. destroy_workqueue(core->batch_workq);
  241. if (core->pm_workq)
  242. destroy_workqueue(core->pm_workq);
  243. core->batch_workq = NULL;
  244. core->pm_workq = NULL;
  245. return rc;
  246. }
  247. static int msm_vidc_initialize_core(struct msm_vidc_core *core)
  248. {
  249. int rc = 0;
  250. if (!core) {
  251. d_vpr_e("%s: invalid params\n", __func__);
  252. return -EINVAL;
  253. }
  254. d_vpr_h("%s()\n", __func__);
  255. msm_vidc_change_core_state(core, MSM_VIDC_CORE_DEINIT, __func__);
  256. core->pm_workq = create_singlethread_workqueue("pm_workq");
  257. if (!core->pm_workq) {
  258. d_vpr_e("%s: create pm workq failed\n", __func__);
  259. rc = -EINVAL;
  260. goto exit;
  261. }
  262. core->batch_workq = create_singlethread_workqueue("batch_workq");
  263. if (!core->batch_workq) {
  264. d_vpr_e("%s: create batch workq failed\n", __func__);
  265. rc = -EINVAL;
  266. goto exit;
  267. }
  268. core->packet_size = VIDC_IFACEQ_VAR_HUGE_PKT_SIZE;
  269. rc = msm_vidc_vmem_alloc(core->packet_size,
  270. (void **)&core->packet, "core packet");
  271. if (rc)
  272. goto exit;
  273. rc = msm_vidc_vmem_alloc(core->packet_size,
  274. (void **)&core->response_packet, "core response packet");
  275. if (rc)
  276. goto exit;
  277. mutex_init(&core->lock);
  278. INIT_LIST_HEAD(&core->instances);
  279. INIT_LIST_HEAD(&core->dangling_instances);
  280. INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_work_handler);
  281. INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
  282. INIT_WORK(&core->ssr_work, msm_vidc_ssr_handler);
  283. return 0;
  284. exit:
  285. msm_vidc_vmem_free((void **)&core->response_packet);
  286. msm_vidc_vmem_free((void **)&core->packet);
  287. core->response_packet = NULL;
  288. core->packet = NULL;
  289. if (core->batch_workq)
  290. destroy_workqueue(core->batch_workq);
  291. if (core->pm_workq)
  292. destroy_workqueue(core->pm_workq);
  293. core->batch_workq = NULL;
  294. core->pm_workq = NULL;
  295. return rc;
  296. }
  297. static int msm_vidc_setup_context_bank(struct msm_vidc_core *core,
  298. struct device *dev)
  299. {
  300. struct context_bank_info *cb = NULL;
  301. int rc = 0;
  302. if (!core || !dev) {
  303. d_vpr_e("%s: invalid params\n", __func__);
  304. return -EINVAL;
  305. }
  306. cb = msm_vidc_get_context_bank_for_device(core, dev);
  307. if (!cb) {
  308. d_vpr_e("%s: Failed to get context bank device for %s\n",
  309. __func__, dev_name(dev));
  310. return -EIO;
  311. }
  312. /* populate dev & domain field */
  313. cb->dev = dev;
  314. cb->domain = iommu_get_domain_for_dev(cb->dev);
  315. /*
  316. * When memory is fragmented, below configuration increases the
  317. * possibility to get a mapping for buffer in the configured CB.
  318. */
  319. /* remove kernel version condition once below api is whitelisted in pineapple */
  320. #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0))
  321. iommu_dma_enable_best_fit_algo(cb->dev);
  322. #endif
  323. /*
  324. * configure device segment size and segment boundary to ensure
  325. * iommu mapping returns one mapping (which is required for partial
  326. * cache operations)
  327. */
  328. if (!dev->dma_parms)
  329. dev->dma_parms =
  330. devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL);
  331. dma_set_max_seg_size(dev, (unsigned int)DMA_BIT_MASK(32));
  332. dma_set_seg_boundary(dev, (unsigned long)DMA_BIT_MASK(64));
  333. iommu_set_fault_handler(cb->domain,
  334. msm_vidc_smmu_fault_handler, (void *)core);
  335. d_vpr_h(
  336. "%s: name %s addr start %x size %x secure %d dma_coherant %d region %d dev_name %s domain %pK\n",
  337. __func__, cb->name, cb->addr_range.start,
  338. cb->addr_range.size, cb->secure, cb->dma_coherant,
  339. cb->region, dev_name(cb->dev), cb->domain);
  340. return rc;
  341. }
  342. static int msm_vidc_component_compare_of(struct device *dev, void *data)
  343. {
  344. return dev->of_node == data;
  345. }
  346. static void msm_vidc_component_release_of(struct device *dev, void *data)
  347. {
  348. d_vpr_h("%s(): %s\n", __func__, of_node_full_name(data));
  349. of_node_put(data);
  350. }
  351. static int msm_vidc_component_cb_bind(struct device *dev,
  352. struct device *master, void *data)
  353. {
  354. struct msm_vidc_core *core;
  355. int rc = 0;
  356. if (!dev) {
  357. d_vpr_e("%s: invalid device\n", __func__);
  358. return -EINVAL;
  359. } else if (!dev->parent) {
  360. d_vpr_e("%s: failed to find a parent for %s\n",
  361. __func__, dev_name(dev));
  362. return -ENODEV;
  363. }
  364. core = dev_get_drvdata(dev->parent);
  365. if (!core) {
  366. d_vpr_e("%s: failed to find cookie in parent device %s",
  367. __func__, dev_name(dev->parent));
  368. return -EINVAL;
  369. }
  370. rc = msm_vidc_setup_context_bank(core, dev);
  371. if (rc) {
  372. d_vpr_e("%s: Failed to probe context bank - %s\n",
  373. __func__, dev_name(dev));
  374. return rc;
  375. }
  376. d_vpr_h("%s: Successfully probed context bank - %s\n",
  377. __func__, dev_name(dev));
  378. return rc;
  379. }
  380. static void msm_vidc_component_cb_unbind(struct device *dev,
  381. struct device *master, void *data)
  382. {
  383. d_vpr_h("%s(): %s\n", __func__, dev_name(dev));
  384. }
  385. static int msm_vidc_component_bind(struct device *dev)
  386. {
  387. struct msm_vidc_core *core = dev_get_drvdata(dev);
  388. int rc = 0;
  389. d_vpr_h("%s(): %s\n", __func__, dev_name(dev));
  390. rc = component_bind_all(dev, core);
  391. if (rc) {
  392. d_vpr_e("%s: sub-device bind failed. rc %d\n", __func__, rc);
  393. return rc;
  394. }
  395. rc = venus_hfi_queue_init(core);
  396. if (rc) {
  397. d_vpr_e("%s: interface queues init failed\n", __func__);
  398. goto queues_deinit;
  399. }
  400. rc = msm_vidc_core_init(core);
  401. if (rc) {
  402. d_vpr_e("%s: sys init failed\n", __func__);
  403. goto queues_deinit;
  404. }
  405. d_vpr_h("%s(): succssful\n", __func__);
  406. return 0;
  407. queues_deinit:
  408. venus_hfi_queue_deinit(core);
  409. /**
  410. * queues and core can be inited again during session_open.
  411. * So don't declare as probe failure.
  412. */
  413. return 0;
  414. }
  415. static void msm_vidc_component_unbind(struct device *dev)
  416. {
  417. struct msm_vidc_core *core = dev_get_drvdata(dev);
  418. d_vpr_h("%s(): %s\n", __func__, dev_name(dev));
  419. msm_vidc_core_deinit(core, true);
  420. venus_hfi_queue_deinit(core);
  421. component_unbind_all(dev, core);
  422. d_vpr_h("%s(): succssful\n", __func__);
  423. }
  424. static const struct component_ops msm_vidc_component_cb_ops = {
  425. .bind = msm_vidc_component_cb_bind,
  426. .unbind = msm_vidc_component_cb_unbind,
  427. };
  428. static const struct component_master_ops msm_vidc_component_ops = {
  429. .bind = msm_vidc_component_bind,
  430. .unbind = msm_vidc_component_unbind,
  431. };
  432. static int msm_vidc_remove_video_device(struct platform_device *pdev)
  433. {
  434. struct msm_vidc_core* core;
  435. if (!pdev) {
  436. d_vpr_e("%s: invalid input %pK", __func__, pdev);
  437. return -EINVAL;
  438. }
  439. core = dev_get_drvdata(&pdev->dev);
  440. if (!core) {
  441. d_vpr_e("%s: invalid core", __func__);
  442. return -EINVAL;
  443. }
  444. d_vpr_h("%s()\n", __func__);
  445. /* destroy component master and deallocate match data */
  446. component_master_del(&pdev->dev, &msm_vidc_component_ops);
  447. d_vpr_h("depopulating sub devices\n");
  448. /*
  449. * Trigger remove for each sub-device i.e. qcom,context-bank,xxxx
  450. * When msm_vidc_remove is called for each sub-device, destroy
  451. * context-bank mappings.
  452. */
  453. of_platform_depopulate(&pdev->dev);
  454. #ifdef CONFIG_MEDIA_CONTROLLER
  455. media_device_unregister(&core->media_dev);
  456. #endif
  457. msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
  458. msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
  459. //device_remove_file(&core->vdev[MSM_VIDC_ENCODER].vdev.dev,
  460. //&dev_attr_link_name);
  461. //device_remove_file(&core->vdev[MSM_VIDC_DECODER].vdev.dev,
  462. //&dev_attr_link_name);
  463. #ifdef CONFIG_MEDIA_CONTROLLER
  464. media_device_cleanup(&core->media_dev);
  465. #endif
  466. v4l2_device_unregister(&core->v4l2_dev);
  467. sysfs_remove_group(&pdev->dev.kobj, &msm_vidc_core_attr_group);
  468. msm_vidc_deinit_instance_caps(core);
  469. msm_vidc_deinit_core_caps(core);
  470. msm_vidc_deinit_platform(pdev);
  471. msm_vidc_deinitialize_core(core);
  472. dev_set_drvdata(&pdev->dev, NULL);
  473. debugfs_remove_recursive(core->debugfs_parent);
  474. msm_vidc_vmem_free((void **)&core);
  475. g_core = NULL;
  476. d_vpr_h("%s(): succssful\n", __func__);
  477. return 0;
  478. }
  479. static int msm_vidc_remove_context_bank(struct platform_device *pdev)
  480. {
  481. d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
  482. component_del(&pdev->dev, &msm_vidc_component_cb_ops);
  483. return 0;
  484. }
  485. static int msm_vidc_remove(struct platform_device *pdev)
  486. {
  487. /*
  488. * Sub devices remove will be triggered by of_platform_depopulate()
  489. * after core_deinit(). It return immediately after completing
  490. * sub-device remove.
  491. */
  492. if (is_video_device(&pdev->dev))
  493. return msm_vidc_remove_video_device(pdev);
  494. else if (is_video_context_bank_device(&pdev->dev))
  495. return msm_vidc_remove_context_bank(pdev);
  496. /* How did we end up here? */
  497. WARN_ON(1);
  498. return -EINVAL;
  499. }
  500. static int msm_vidc_probe_video_device(struct platform_device *pdev)
  501. {
  502. int rc = 0;
  503. struct component_match *match = NULL;
  504. struct msm_vidc_core *core = NULL;
  505. struct device_node *child = NULL;
  506. int sub_device_count = 0, nr = BASE_DEVICE_NUMBER;
  507. d_vpr_h("%s: %s\n", __func__, dev_name(&pdev->dev));
  508. rc = msm_vidc_vmem_alloc(sizeof(*core), (void **)&core, __func__);
  509. if (rc)
  510. return rc;
  511. g_core = core;
  512. core->debugfs_parent = msm_vidc_debugfs_init_drv();
  513. if (!core->debugfs_parent)
  514. d_vpr_h("Failed to create debugfs for msm_vidc\n");
  515. core->pdev = pdev;
  516. dev_set_drvdata(&pdev->dev, core);
  517. rc = msm_vidc_initialize_core(core);
  518. if (rc) {
  519. d_vpr_e("%s: init core failed with %d\n", __func__, rc);
  520. goto init_core_failed;
  521. }
  522. rc = msm_vidc_init_platform(pdev);
  523. if (rc) {
  524. d_vpr_e("%s: init platform failed with %d\n", __func__, rc);
  525. rc = -EINVAL;
  526. goto init_plat_failed;
  527. }
  528. rc = msm_vidc_init_resources(core);
  529. if (rc) {
  530. d_vpr_e("%s: init resource failed with %d\n", __func__, rc);
  531. goto init_res_failed;
  532. }
  533. rc = msm_vidc_init_core_caps(core);
  534. if (rc) {
  535. d_vpr_e("%s: init core caps failed with %d\n", __func__, rc);
  536. goto init_res_failed;
  537. }
  538. rc = msm_vidc_init_instance_caps(core);
  539. if (rc) {
  540. d_vpr_e("%s: init inst cap failed with %d\n", __func__, rc);
  541. goto init_inst_caps_fail;
  542. }
  543. rc = sysfs_create_group(&pdev->dev.kobj, &msm_vidc_core_attr_group);
  544. if (rc) {
  545. d_vpr_e("Failed to create attributes\n");
  546. goto init_group_failed;
  547. }
  548. rc = v4l2_device_register(&pdev->dev, &core->v4l2_dev);
  549. if (rc) {
  550. d_vpr_e("Failed to register v4l2 device\n");
  551. goto v4l2_reg_failed;
  552. }
  553. #ifdef CONFIG_MEDIA_CONTROLLER
  554. core->media_dev.dev = &core->pdev->dev;
  555. strscpy(core->media_dev.model, "msm_vidc_media", sizeof(core->media_dev.model));
  556. media_device_init(&core->media_dev);
  557. core->media_dev.ops = core->media_device_ops;
  558. core->v4l2_dev.mdev = &core->media_dev;
  559. #endif
  560. /* setup the decoder device */
  561. rc = msm_vidc_register_video_device(core, MSM_VIDC_DECODER, nr);
  562. if (rc) {
  563. d_vpr_e("Failed to register video decoder\n");
  564. goto dec_reg_failed;
  565. }
  566. /* setup the encoder device */
  567. rc = msm_vidc_register_video_device(core, MSM_VIDC_ENCODER, nr + 1);
  568. if (rc) {
  569. d_vpr_e("Failed to register video encoder\n");
  570. goto enc_reg_failed;
  571. }
  572. #ifdef CONFIG_MEDIA_CONTROLLER
  573. rc = media_device_register(&core->media_dev);
  574. if (rc) {
  575. d_vpr_e("%s: media_device_register failed with %d\n", __func__, rc);
  576. goto media_reg_failed;
  577. }
  578. #endif
  579. rc = msm_vidc_check_mmrm_support(core);
  580. if (rc) {
  581. d_vpr_e("Failed to check MMRM scaling support\n");
  582. rc = 0; /* Ignore error */
  583. }
  584. core->debugfs_root = msm_vidc_debugfs_init_core(core);
  585. if (!core->debugfs_root)
  586. d_vpr_h("Failed to init debugfs core\n");
  587. /* registering sub-device with component model framework */
  588. for_each_available_child_of_node(pdev->dev.of_node, child) {
  589. sub_device_count++;
  590. of_node_get(child);
  591. component_match_add_release(&pdev->dev, &match, msm_vidc_component_release_of,
  592. msm_vidc_component_compare_of, child);
  593. if (IS_ERR(match)) {
  594. of_node_put(child);
  595. rc = PTR_ERR(match) ? PTR_ERR(match) : -ENOMEM;
  596. d_vpr_e("%s: component match add release failed\n", __func__);
  597. goto sub_dev_failed;
  598. }
  599. }
  600. d_vpr_h("populating sub devices. count %d\n", sub_device_count);
  601. /*
  602. * Trigger probe for each sub-device i.e. qcom,msm-vidc,context-bank.
  603. * When msm_vidc_probe is called for each sub-device, parse the
  604. * context-bank details.
  605. */
  606. rc = of_platform_populate(pdev->dev.of_node, msm_vidc_dt_match, NULL,
  607. &pdev->dev);
  608. if (rc) {
  609. d_vpr_e("Failed to trigger probe for sub-devices\n");
  610. goto sub_dev_failed;
  611. }
  612. /* create component master and add match data */
  613. rc = component_master_add_with_match(&pdev->dev, &msm_vidc_component_ops, match);
  614. if (rc) {
  615. d_vpr_e("%s: component master add with match failed\n", __func__);
  616. goto master_add_failed;
  617. }
  618. d_vpr_h("%s(): succssful\n", __func__);
  619. return rc;
  620. master_add_failed:
  621. of_platform_depopulate(&pdev->dev);
  622. sub_dev_failed:
  623. #ifdef CONFIG_MEDIA_CONTROLLER
  624. media_device_unregister(&core->media_dev);
  625. media_reg_failed:
  626. #endif
  627. msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
  628. enc_reg_failed:
  629. msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
  630. dec_reg_failed:
  631. v4l2_device_unregister(&core->v4l2_dev);
  632. v4l2_reg_failed:
  633. sysfs_remove_group(&pdev->dev.kobj, &msm_vidc_core_attr_group);
  634. init_group_failed:
  635. msm_vidc_deinit_instance_caps(core);
  636. init_inst_caps_fail:
  637. msm_vidc_deinit_core_caps(core);
  638. init_res_failed:
  639. msm_vidc_deinit_platform(pdev);
  640. init_plat_failed:
  641. msm_vidc_deinitialize_core(core);
  642. init_core_failed:
  643. dev_set_drvdata(&pdev->dev, NULL);
  644. debugfs_remove_recursive(core->debugfs_parent);
  645. msm_vidc_vmem_free((void **)&core);
  646. g_core = NULL;
  647. return rc;
  648. }
  649. static int msm_vidc_probe_context_bank(struct platform_device *pdev)
  650. {
  651. d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
  652. return component_add(&pdev->dev, &msm_vidc_component_cb_ops);
  653. }
  654. static int msm_vidc_probe(struct platform_device *pdev)
  655. {
  656. d_vpr_h("%s()\n", __func__);
  657. /*
  658. * Sub devices probe will be triggered by of_platform_populate() towards
  659. * the end of the probe function after msm-vidc device probe is
  660. * completed. Return immediately after completing sub-device probe.
  661. */
  662. if (is_video_device(&pdev->dev))
  663. return msm_vidc_probe_video_device(pdev);
  664. else if (is_video_context_bank_device(&pdev->dev))
  665. return msm_vidc_probe_context_bank(pdev);
  666. /* How did we end up here? */
  667. WARN_ON(1);
  668. return -EINVAL;
  669. }
  670. static int msm_vidc_pm_suspend(struct device *dev)
  671. {
  672. int rc = 0;
  673. struct msm_vidc_core *core;
  674. bool allow = false;
  675. /*
  676. * Bail out if
  677. * - driver possibly not probed yet
  678. * - not the main device. We don't support power management on
  679. * subdevices (e.g. context banks)
  680. */
  681. if (!dev || !dev->driver || !is_video_device(dev))
  682. return 0;
  683. core = dev_get_drvdata(dev);
  684. if (!core) {
  685. d_vpr_e("%s: invalid core\n", __func__);
  686. return -EINVAL;
  687. }
  688. core_lock(core, __func__);
  689. allow = msm_vidc_allow_pm_suspend(core);
  690. if (!allow) {
  691. d_vpr_e("%s: pm suspend not allowed\n", __func__);
  692. rc = 0;
  693. goto unlock;
  694. }
  695. d_vpr_h("%s\n", __func__);
  696. rc = msm_vidc_suspend_locked(core);
  697. if (rc == -ENOTSUPP)
  698. rc = 0;
  699. else if (rc)
  700. d_vpr_e("Failed to suspend: %d\n", rc);
  701. else
  702. msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_PM_SUSPEND, __func__);
  703. unlock:
  704. core_unlock(core, __func__);
  705. return rc;
  706. }
  707. static int msm_vidc_pm_resume(struct device *dev)
  708. {
  709. struct msm_vidc_core *core;
  710. /*
  711. * Bail out if
  712. * - driver possibly not probed yet
  713. * - not the main device. We don't support power management on
  714. * subdevices (e.g. context banks)
  715. */
  716. if (!dev || !dev->driver || !is_video_device(dev))
  717. return 0;
  718. core = dev_get_drvdata(dev);
  719. if (!core) {
  720. d_vpr_e("%s: invalid core\n", __func__);
  721. return -EINVAL;
  722. }
  723. d_vpr_h("%s\n", __func__);
  724. /* remove PM suspend from core sub_state */
  725. core_lock(core, __func__);
  726. msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_PM_SUSPEND, 0, __func__);
  727. core_unlock(core, __func__);
  728. return 0;
  729. }
  730. static const struct dev_pm_ops msm_vidc_pm_ops = {
  731. SET_SYSTEM_SLEEP_PM_OPS(msm_vidc_pm_suspend, msm_vidc_pm_resume)
  732. };
  733. struct platform_driver msm_vidc_driver = {
  734. .probe = msm_vidc_probe,
  735. .remove = msm_vidc_remove,
  736. .driver = {
  737. .name = "msm_vidc_v4l2",
  738. .of_match_table = msm_vidc_dt_match,
  739. .pm = &msm_vidc_pm_ops,
  740. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  741. },
  742. };
  743. static int __init msm_vidc_init(void)
  744. {
  745. int rc = 0;
  746. d_vpr_h("%s: %s\n", __func__, video_banner);
  747. rc = platform_driver_register(&msm_vidc_driver);
  748. if (rc) {
  749. d_vpr_e("Failed to register platform driver\n");
  750. return rc;
  751. }
  752. d_vpr_h("%s(): succssful\n", __func__);
  753. return 0;
  754. }
  755. static void __exit msm_vidc_exit(void)
  756. {
  757. d_vpr_h("%s()\n", __func__);
  758. platform_driver_unregister(&msm_vidc_driver);
  759. d_vpr_h("%s(): succssful\n", __func__);
  760. }
  761. module_init(msm_vidc_init);
  762. module_exit(msm_vidc_exit);
  763. MODULE_SOFTDEP("pre: subsys-pil-tz msm-mmrm");
  764. MODULE_LICENSE("GPL v2");