Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 545df9a2 authored by Harsh Shah's avatar Harsh Shah Committed by Soundrapandian Jeyaprakash
Browse files

msm: camera: isp: Add support for dynamically loadable VFE driver



Implement the remove driver functions for ISP HW drivers. This enables
the dynamic loadable capability to the ISP driver.

Change-Id: I99f70bf8cb57fccbb2b495622752d1f0983580e8
Signed-off-by: default avatarHarsh Shah <harshs@codeaurora.org>
Signed-off-by: default avatarSoundrapandian Jeyaprakash <jsoundra@codeaurora.org>
parent 6ff51ac5
Loading
Loading
Loading
Loading
+44 −2
Original line number Diff line number Diff line
@@ -611,7 +611,7 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info,
		&core_info->vfe_top);
	if (rc) {
		pr_err("Error! cam_vfe_top_init failed\n");
		return rc;
		goto deinit_controller;
	}

	rc = cam_vfe_bus_init(vfe_hw_info->bus_version,
@@ -619,7 +619,7 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info,
		vfe_hw_info->bus_hw_info, NULL, &core_info->vfe_bus);
	if (rc) {
		pr_err("Error! cam_vfe_bus_init failed\n");
		return rc;
		goto deinit_top;
	}

	INIT_LIST_HEAD(&core_info->free_payload_list);
@@ -631,5 +631,47 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info,

	spin_lock_init(&core_info->spin_lock);

	return rc;

deinit_top:
	cam_vfe_top_deinit(vfe_hw_info->top_version,
		&core_info->vfe_top);

deinit_controller:
	cam_irq_controller_deinit(&core_info->vfe_irq_controller);

	return rc;
}

int cam_vfe_core_deinit(struct cam_vfe_hw_core_info  *core_info,
	struct cam_vfe_hw_info                       *vfe_hw_info)
{
	int                rc = -EINVAL;
	int                i;
	unsigned long      flags;

	spin_lock_irqsave(&core_info->spin_lock, flags);

	INIT_LIST_HEAD(&core_info->free_payload_list);
	for (i = 0; i < CAM_VFE_EVT_MAX; i++)
		INIT_LIST_HEAD(&core_info->evt_payload[i].list);

	rc = cam_vfe_bus_deinit(vfe_hw_info->bus_version,
		&core_info->vfe_bus);
	if (rc)
		pr_err("Error cam_vfe_bus_deinit failed rc=%d\n", rc);

	rc = cam_vfe_top_deinit(vfe_hw_info->top_version,
		&core_info->vfe_top);
	if (rc)
		pr_err("Error cam_vfe_top_deinit failed rc=%d\n", rc);

	rc = cam_irq_controller_deinit(&core_info->vfe_irq_controller);
	if (rc)
		pr_err("Error cam_irq_controller_deinit failed rc=%d\n", rc);

	spin_unlock_irqrestore(&core_info->spin_lock, flags);

	return rc;
}
+3 −0
Original line number Diff line number Diff line
@@ -89,4 +89,7 @@ int cam_vfe_core_init(struct cam_vfe_hw_core_info *core_info,
	struct cam_hw_intf                 *hw_intf,
	struct cam_vfe_hw_info             *vfe_hw_info);

int cam_vfe_core_deinit(struct cam_vfe_hw_core_info *core_info,
	struct cam_vfe_hw_info             *vfe_hw_info);

#endif /* _CAM_VFE_CORE_H_ */
+58 −2
Original line number Diff line number Diff line
@@ -88,14 +88,14 @@ int cam_vfe_probe(struct platform_device *pdev)
	rc = cam_vfe_init_soc_resources(&vfe_hw->soc_info, cam_vfe_irq,
		vfe_hw);
	if (rc < 0) {
		pr_err("Failed to init soc\n");
		pr_err("Failed to init soc rc=%d\n", rc);
		goto free_core_info;
	}

	rc = cam_vfe_core_init(core_info, &vfe_hw->soc_info,
		vfe_hw_intf, hw_info);
	if (rc < 0) {
		pr_err("Failed to init core\n");
		pr_err("Failed to init core rc=%d\n", rc);
		goto deinit_soc;
	}

@@ -115,6 +115,8 @@ int cam_vfe_probe(struct platform_device *pdev)
	return rc;

deinit_soc:
	if (cam_vfe_deinit_soc_resources(&vfe_hw->soc_info))
		pr_err("Failed to deinit soc\n");
free_core_info:
	kfree(vfe_hw->core_info);
free_vfe_hw:
@@ -125,6 +127,60 @@ int cam_vfe_probe(struct platform_device *pdev)
	return rc;
}

int cam_vfe_remove(struct platform_device *pdev)
{
	struct cam_hw_info                *vfe_hw = NULL;
	struct cam_hw_intf                *vfe_hw_intf = NULL;
	struct cam_vfe_hw_core_info       *core_info = NULL;
	int                                rc = 0;

	vfe_hw_intf = platform_get_drvdata(pdev);
	if (!vfe_hw_intf) {
		pr_err("Error! No data in pdev\n");
		return -EINVAL;
	}

	CDBG("type %d index %d\n", vfe_hw_intf->hw_type, vfe_hw_intf->hw_idx);

	if (vfe_hw_intf->hw_idx < CAM_VFE_HW_NUM_MAX)
		cam_vfe_hw_list[vfe_hw_intf->hw_idx] = NULL;

	vfe_hw = vfe_hw_intf->hw_priv;
	if (!vfe_hw) {
		pr_err("Error! HW data is NULL\n");
		rc = -ENODEV;
		goto free_vfe_hw_intf;
	}

	core_info = (struct cam_vfe_hw_core_info *)vfe_hw->core_info;
	if (!core_info) {
		pr_err("Error! core data NULL");
		rc = -EINVAL;
		goto deinit_soc;
	}

	rc = cam_vfe_core_deinit(core_info, core_info->vfe_hw_info);
	if (rc < 0)
		pr_err("Failed to deinit core rc=%d\n", rc);

	kfree(vfe_hw->core_info);

deinit_soc:
	rc = cam_vfe_deinit_soc_resources(&vfe_hw->soc_info);
	if (rc < 0)
		pr_err("Failed to deinit soc rc=%d\n", rc);

	mutex_destroy(&vfe_hw->hw_mutex);
	kfree(vfe_hw);

	CDBG("VFE%d remove successful\n", vfe_hw_intf->hw_idx);

free_vfe_hw_intf:
	kfree(vfe_hw_intf);

	return rc;
}

int cam_vfe_hw_init(struct cam_hw_intf **vfe_hw, uint32_t hw_idx)
{
	int rc = 0;
+12 −0
Original line number Diff line number Diff line
@@ -27,4 +27,16 @@
 */
int cam_vfe_probe(struct platform_device *pdev);

/*
 * cam_vfe_remove()
 *
 * @brief:                   Driver remove function
 *
 * @pdev:                    Platform Device pointer
 *
 * @Return:                  0: Success
 *                           Non-zero: Failure
 */
int cam_vfe_remove(struct platform_device *pdev);

#endif /* _CAM_VFE_DEV_H_ */
+50 −8
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ static int cam_vfe_get_dt_properties(struct cam_hw_soc_info *soc_info)

	rc = cam_soc_util_get_dt_properties(soc_info);
	if (rc) {
		pr_err("Error! get DT properties failed\n");
		pr_err("Error! get DT properties failed rc=%d\n", rc);
		return rc;
	}

@@ -40,6 +40,19 @@ static int cam_vfe_request_platform_resource(

	rc = cam_soc_util_request_platform_resource(soc_info, vfe_irq_handler,
		irq_data);
	if (rc)
		pr_err("Error! Request platform resource failed rc=%d\n", rc);

	return rc;
}

static int cam_vfe_release_platform_resource(struct cam_hw_soc_info *soc_info)
{
	int rc = 0;

	rc = cam_soc_util_release_platform_resource(soc_info);
	if (rc)
		pr_err("Error! Release platform resource failed rc=%d\n", rc);

	return rc;
}
@@ -61,14 +74,14 @@ int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info,

	rc = cam_vfe_get_dt_properties(soc_info);
	if (rc < 0) {
		pr_err("Error! Get DT properties failed\n");
		pr_err("Error! Get DT properties failed rc=%d\n", rc);
		goto free_soc_private;
	}

	rc = cam_vfe_request_platform_resource(soc_info, vfe_irq_handler,
		irq_data);
	if (rc < 0) {
		pr_err("Error! Request platform resources failed\n");
		pr_err("Error! Request platform resources failed rc=%d\n", rc);
		goto free_soc_private;
	}

@@ -79,7 +92,7 @@ int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
	cpas_register_param.dev = &soc_info->pdev->dev;
	rc = cam_cpas_register_client(&cpas_register_param);
	if (rc) {
		pr_err("CPAS registration failed\n");
		pr_err("CPAS registration failed rc=%d\n", rc);
		goto release_soc;
	} else {
		soc_private->cpas_handle = cpas_register_param.client_handle;
@@ -95,6 +108,35 @@ int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
	return rc;
}

int cam_vfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info)
{
	int                               rc = 0;
	struct cam_vfe_soc_private       *soc_private;

	if (!soc_info) {
		pr_err("Error! soc_info NULL\n");
		return -ENODEV;
	}

	soc_private = soc_info->soc_private;
	if (!soc_private) {
		pr_err("Error! soc_private NULL\n");
		return -ENODEV;
	}

	rc = cam_cpas_unregister_client(soc_private->cpas_handle);
	if (rc)
		pr_err("CPAS unregistration failed rc=%d\n", rc);

	rc = cam_vfe_release_platform_resource(soc_info);
	if (rc < 0)
		pr_err("Error! Release platform resources failed rc=%d\n", rc);

	kfree(soc_private);

	return rc;
}

int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
{
	int                               rc = 0;
@@ -117,7 +159,7 @@ int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)

	rc = cam_cpas_start(soc_private->cpas_handle, &ahb_vote, &axi_vote);
	if (rc) {
		pr_err("Error! CPAS start failed.\n");
		pr_err("Error! CPAS start failed rc=%d\n", rc);
		rc = -EFAULT;
		goto end;
	}
@@ -125,7 +167,7 @@ int cam_vfe_enable_soc_resources(struct cam_hw_soc_info *soc_info)
	rc = cam_soc_util_enable_platform_resource(soc_info, true,
		CAM_TURBO_VOTE, true);
	if (rc) {
		pr_err("Error! enable platform failed\n");
		pr_err("Error! enable platform failed rc=%d\n", rc);
		goto stop_cpas;
	}

@@ -152,13 +194,13 @@ int cam_vfe_disable_soc_resources(struct cam_hw_soc_info *soc_info)

	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
	if (rc) {
		pr_err("%s: disable platform failed\n", __func__);
		pr_err("Disable platform failed rc=%d\n", rc);
		return rc;
	}

	rc = cam_cpas_stop(soc_private->cpas_handle);
	if (rc) {
		pr_err("Error! CPAS stop failed.\n");
		pr_err("Error! CPAS stop failed rc=%d\n", rc);
		return rc;
	}

Loading