Browse Source

Merge "video: driver: fix video node open before probe issue"

qctecmdr 2 years ago
parent
commit
a7d368d03f
1 changed files with 128 additions and 91 deletions
  1. 128 91
      driver/vidc/src/msm_vidc_probe.c

+ 128 - 91
driver/vidc/src/msm_vidc_probe.c

@@ -46,13 +46,18 @@ static inline bool is_video_device(struct device *dev)
 		of_device_is_compatible(dev->of_node, "qcom,sm8650-vidc-v2");
 }
 
+static inline bool is_video_context_bank_device_node(struct device_node *of_node)
+{
+	return !!(of_device_is_compatible(of_node, "qcom,vidc,cb-sec-pxl") ||
+		of_device_is_compatible(of_node, "qcom,vidc,cb-sec-bitstream") ||
+		of_device_is_compatible(of_node, "qcom,vidc,cb-sec-non-pxl") ||
+		of_device_is_compatible(of_node, "qcom,vidc,cb-ns") ||
+		of_device_is_compatible(of_node, "qcom,vidc,cb-ns-pxl"));
+}
+
 static inline bool is_video_context_bank_device(struct device *dev)
 {
-	return !!(of_device_is_compatible(dev->of_node, "qcom,vidc,cb-sec-pxl") ||
-		of_device_is_compatible(dev->of_node, "qcom,vidc,cb-sec-bitstream") ||
-		of_device_is_compatible(dev->of_node, "qcom,vidc,cb-sec-non-pxl") ||
-		of_device_is_compatible(dev->of_node, "qcom,vidc,cb-ns") ||
-		of_device_is_compatible(dev->of_node, "qcom,vidc,cb-ns-pxl"));
+	return is_video_context_bank_device_node(dev->of_node);
 }
 
 static int msm_vidc_init_resources(struct msm_vidc_core *core)
@@ -234,6 +239,78 @@ video_reg_failed:
 	return rc;
 }
 
+static int msm_vidc_initialize_media(struct msm_vidc_core *core)
+{
+	int rc = 0, nr = BASE_DEVICE_NUMBER;
+
+	rc = v4l2_device_register(&core->pdev->dev, &core->v4l2_dev);
+	if (rc) {
+		d_vpr_e("Failed to register v4l2 device\n");
+		return -EINVAL;
+	}
+
+#ifdef CONFIG_MEDIA_CONTROLLER
+	core->media_dev.dev = &core->pdev->dev;
+	strscpy(core->media_dev.model, "msm_vidc_media", sizeof(core->media_dev.model));
+	media_device_init(&core->media_dev);
+	core->media_dev.ops = core->media_device_ops;
+	core->v4l2_dev.mdev = &core->media_dev;
+#endif
+
+	/* setup the decoder device */
+	rc = msm_vidc_register_video_device(core, MSM_VIDC_DECODER, nr);
+	if (rc) {
+		d_vpr_e("Failed to register video decoder\n");
+		goto dec_reg_failed;
+	}
+
+	/* setup the encoder device */
+	rc = msm_vidc_register_video_device(core, MSM_VIDC_ENCODER, nr + 1);
+	if (rc) {
+		d_vpr_e("Failed to register video encoder\n");
+		goto enc_reg_failed;
+	}
+#ifdef CONFIG_MEDIA_CONTROLLER
+	rc = media_device_register(&core->media_dev);
+	if (rc) {
+		d_vpr_e("%s: media_device_register failed with %d\n", __func__, rc);
+		goto media_reg_failed;
+	}
+#endif
+
+	return rc;
+#ifdef CONFIG_MEDIA_CONTROLLER
+media_reg_failed:
+#endif
+	msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
+enc_reg_failed:
+	msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
+dec_reg_failed:
+#ifdef CONFIG_MEDIA_CONTROLLER
+	media_device_cleanup(&core->media_dev);
+#endif
+	v4l2_device_unregister(&core->v4l2_dev);
+
+	return rc;
+}
+
+static int msm_vidc_deinitialize_media(struct msm_vidc_core *core)
+{
+	int rc = 0;
+
+#ifdef CONFIG_MEDIA_CONTROLLER
+	media_device_unregister(&core->media_dev);
+#endif
+	msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
+	msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
+#ifdef CONFIG_MEDIA_CONTROLLER
+	media_device_cleanup(&core->media_dev);
+#endif
+	v4l2_device_unregister(&core->v4l2_dev);
+
+	return rc;
+}
+
 #ifdef CONFIG_MSM_MMRM
 static int msm_vidc_check_mmrm_support(struct msm_vidc_core *core)
 {
@@ -436,26 +513,23 @@ static void msm_vidc_component_release_of(struct device *dev, void *data)
 	of_node_put(data);
 }
 
-static int msm_vidc_component_cb_bind(struct device *dev,
-	struct device *master, void *data)
+static int msm_vidc_component_bind(struct device *dev,
+	struct device *parent, void *data)
 {
 	struct msm_vidc_core *core;
 	int rc = 0;
 
-	if (!dev) {
-		d_vpr_e("%s: invalid device\n", __func__);
+	if (!dev || !parent || !data) {
+		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
-	} else if (!dev->parent) {
+	}
+	core = (struct msm_vidc_core *)data;
+
+	if (!dev->parent || dev->parent != parent) {
 		d_vpr_e("%s: failed to find a parent for %s\n",
 			__func__, dev_name(dev));
 		return -ENODEV;
 	}
-	core = dev_get_drvdata(dev->parent);
-	if (!core) {
-		d_vpr_e("%s: failed to find cookie in parent device %s",
-				__func__, dev_name(dev->parent));
-		return -EINVAL;
-	}
 
 	rc = msm_vidc_setup_context_bank(core, dev);
 	if (rc) {
@@ -470,13 +544,13 @@ static int msm_vidc_component_cb_bind(struct device *dev,
 	return rc;
 }
 
-static void msm_vidc_component_cb_unbind(struct device *dev,
-	struct device *master, void *data)
+static void msm_vidc_component_unbind(struct device *dev,
+	struct device *parent, void *data)
 {
 	d_vpr_h("%s(): %s\n", __func__, dev_name(dev));
 }
 
-static int msm_vidc_component_bind(struct device *dev)
+static int msm_vidc_component_master_bind(struct device *dev)
 {
 	struct msm_vidc_core *core = dev_get_drvdata(dev);
 	int rc = 0;
@@ -489,6 +563,12 @@ static int msm_vidc_component_bind(struct device *dev)
 		return rc;
 	}
 
+	rc = msm_vidc_initialize_media(core);
+	if (rc) {
+		d_vpr_e("%s: media initialization failed\n", __func__);
+		return rc;
+	}
+
 	rc = venus_hfi_queue_init(core);
 	if (rc) {
 		d_vpr_e("%s: interface queues init failed\n", __func__);
@@ -514,7 +594,7 @@ queues_deinit:
 	return 0;
 }
 
-static void msm_vidc_component_unbind(struct device *dev)
+static void msm_vidc_component_master_unbind(struct device *dev)
 {
 	struct msm_vidc_core *core = dev_get_drvdata(dev);
 
@@ -522,21 +602,22 @@ static void msm_vidc_component_unbind(struct device *dev)
 
 	msm_vidc_core_deinit(core, true);
 	venus_hfi_queue_deinit(core);
+	msm_vidc_deinitialize_media(core);
 	component_unbind_all(dev, core);
 
 	d_vpr_h("%s(): succssful\n", __func__);
 }
 
-static const struct component_ops msm_vidc_component_cb_ops = {
-	.bind           = msm_vidc_component_cb_bind,
-	.unbind         = msm_vidc_component_cb_unbind,
-};
-
-static const struct component_master_ops msm_vidc_component_ops = {
+static const struct component_ops msm_vidc_component_ops = {
 	.bind           = msm_vidc_component_bind,
 	.unbind         = msm_vidc_component_unbind,
 };
 
+static const struct component_master_ops msm_vidc_component_master_ops = {
+	.bind           = msm_vidc_component_master_bind,
+	.unbind         = msm_vidc_component_master_unbind,
+};
+
 static int msm_vidc_remove_video_device(struct platform_device *pdev)
 {
 	struct msm_vidc_core* core;
@@ -554,7 +635,7 @@ static int msm_vidc_remove_video_device(struct platform_device *pdev)
 	d_vpr_h("%s()\n", __func__);
 
 	/* destroy component master and deallocate match data */
-	component_master_del(&pdev->dev, &msm_vidc_component_ops);
+	component_master_del(&pdev->dev, &msm_vidc_component_master_ops);
 
 	d_vpr_h("depopulating sub devices\n");
 	/*
@@ -564,19 +645,6 @@ static int msm_vidc_remove_video_device(struct platform_device *pdev)
 	 */
 	of_platform_depopulate(&pdev->dev);
 
-#ifdef CONFIG_MEDIA_CONTROLLER
-	media_device_unregister(&core->media_dev);
-#endif
-	msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
-	msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
-	//device_remove_file(&core->vdev[MSM_VIDC_ENCODER].vdev.dev,
-		//&dev_attr_link_name);
-	//device_remove_file(&core->vdev[MSM_VIDC_DECODER].vdev.dev,
-		//&dev_attr_link_name);
-#ifdef CONFIG_MEDIA_CONTROLLER
-	media_device_cleanup(&core->media_dev);
-#endif
-	v4l2_device_unregister(&core->v4l2_dev);
 	sysfs_remove_group(&pdev->dev.kobj, &msm_vidc_core_attr_group);
 
 	msm_vidc_deinit_instance_caps(core);
@@ -598,7 +666,7 @@ static int msm_vidc_remove_context_bank(struct platform_device *pdev)
 {
 	d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
 
-	component_del(&pdev->dev, &msm_vidc_component_cb_ops);
+	component_del(&pdev->dev, &msm_vidc_component_ops);
 
 	return 0;
 }
@@ -626,7 +694,7 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
 	struct component_match *match = NULL;
 	struct msm_vidc_core *core = NULL;
 	struct device_node *child = NULL;
-	int sub_node_count = 0, nr = BASE_DEVICE_NUMBER;
+	int cb_count = 0;
 
 	d_vpr_h("%s: %s\n", __func__, dev_name(&pdev->dev));
 
@@ -679,40 +747,6 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
 		goto init_group_failed;
 	}
 
-	rc = v4l2_device_register(&pdev->dev, &core->v4l2_dev);
-	if (rc) {
-		d_vpr_e("Failed to register v4l2 device\n");
-		goto v4l2_reg_failed;
-	}
-
-#ifdef CONFIG_MEDIA_CONTROLLER
-	core->media_dev.dev = &core->pdev->dev;
-	strscpy(core->media_dev.model, "msm_vidc_media", sizeof(core->media_dev.model));
-	media_device_init(&core->media_dev);
-	core->media_dev.ops = core->media_device_ops;
-	core->v4l2_dev.mdev = &core->media_dev;
-#endif
-
-	/* setup the decoder device */
-	rc = msm_vidc_register_video_device(core, MSM_VIDC_DECODER, nr);
-	if (rc) {
-		d_vpr_e("Failed to register video decoder\n");
-		goto dec_reg_failed;
-	}
-
-	/* setup the encoder device */
-	rc = msm_vidc_register_video_device(core, MSM_VIDC_ENCODER, nr + 1);
-	if (rc) {
-		d_vpr_e("Failed to register video encoder\n");
-		goto enc_reg_failed;
-	}
-#ifdef CONFIG_MEDIA_CONTROLLER
-	rc = media_device_register(&core->media_dev);
-	if (rc) {
-		d_vpr_e("%s: media_device_register failed with %d\n", __func__, rc);
-		goto media_reg_failed;
-	}
-#endif
 	rc = msm_vidc_check_mmrm_support(core);
 	if (rc) {
 		d_vpr_e("Failed to check MMRM scaling support\n");
@@ -725,8 +759,14 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
 
 	/* registering sub-device with component model framework */
 	for_each_available_child_of_node(pdev->dev.of_node, child) {
-		sub_node_count++;
+		/* consider only context bank devices */
+		if (!is_video_context_bank_device_node(child))
+			continue;
+
+		/* take refcount on device node */
 		of_node_get(child);
+
+		/* add entry into component_match array */
 		component_match_add_release(&pdev->dev, &match, msm_vidc_component_release_of,
 			msm_vidc_component_compare_of, child);
 		if (IS_ERR(match)) {
@@ -735,9 +775,12 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
 			d_vpr_e("%s: component match add release failed\n", __func__);
 			goto sub_dev_failed;
 		}
+
+		/* count context bank devices */
+		cb_count++;
 	}
 
-	d_vpr_h("populating sub devices. count %d\n", sub_node_count);
+	d_vpr_h("populating sub devices. count %d\n", cb_count);
 	/*
 	 * Trigger probe for each sub-device i.e. qcom,msm-vidc,context-bank.
 	 * When msm_vidc_probe is called for each sub-device, parse the
@@ -750,8 +793,12 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
 		goto sub_dev_failed;
 	}
 
-	/* create component master and add match data */
-	rc = component_master_add_with_match(&pdev->dev, &msm_vidc_component_ops, match);
+	/**
+	 * create and try to bring up aggregate device for master.
+	 * match is a component_match_array and acts as a placeholder for
+	 * components added via component_add().
+	 */
+	rc = component_master_add_with_match(&pdev->dev, &msm_vidc_component_master_ops, match);
 	if (rc) {
 		d_vpr_e("%s: component master add with match failed\n", __func__);
 		goto master_add_failed;
@@ -764,16 +811,6 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
 master_add_failed:
 	of_platform_depopulate(&pdev->dev);
 sub_dev_failed:
-#ifdef CONFIG_MEDIA_CONTROLLER
-	media_device_unregister(&core->media_dev);
-media_reg_failed:
-#endif
-	msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
-enc_reg_failed:
-	msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
-dec_reg_failed:
-	v4l2_device_unregister(&core->v4l2_dev);
-v4l2_reg_failed:
 	sysfs_remove_group(&pdev->dev.kobj, &msm_vidc_core_attr_group);
 init_group_failed:
 	msm_vidc_deinit_instance_caps(core);
@@ -796,7 +833,7 @@ static int msm_vidc_probe_context_bank(struct platform_device *pdev)
 {
 	d_vpr_h("%s(): %s\n", __func__, dev_name(&pdev->dev));
 
-	return component_add(&pdev->dev, &msm_vidc_component_cb_ops);
+	return component_add(&pdev->dev, &msm_vidc_component_ops);
 }
 
 static int msm_vidc_probe(struct platform_device *pdev)