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

Commit 9120f4eb authored by Arun Menon's avatar Arun Menon
Browse files

msm: vidc: Load firmware during vidc probe



This change will load the firmware during v4l2 video driver
probe. If there are no active video sessions, then video
hardware will be power collapsed. On targets which can afford
to keep firmware always loaded in memory, this change will help
overcome the delay associated with loading firmware when a new
video session is instantiated.

Change-Id: I4f9981d8db4ff62d652628681bb58fa79ee9b7d4
Signed-off-by: default avatarArun Menon <avmenon@codeaurora.org>
parent f68ea676
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -97,6 +97,9 @@ Optional properties:
  gate-able = 0x2 (if the driver should disable the clock if no load)
- qcom,sw-power-collapse = A bool indicating if video hardware core can be
  power collapsed in idle state.
- qcom,early-fw-load = A bool indicating if video firmware should be loaded
  during probe. When no video session is active, the video hardware will be
  power collapsed.
- qcom,use-non-secure-pil = A bool indicating which type of pil to use to load
  the fw.
- qcom,use-dynamic-bw-update = A bool indicating whether dynamic bandwidth
@@ -133,6 +136,7 @@ Example:
		clock-names = "foo_clk", "bar_clk", "baz_clk";
		qcom,clock-configs = <0x3 0x1 0x0>;
		qcom,sw-power-collapse;
		qcom,early-fw-load;
		qcom,enable-idle-indicator;
		qcom,msm-bus-clients {
			qcom,msm-bus-client@0 {
+64 −3
Original line number Diff line number Diff line
@@ -23,15 +23,17 @@
#include <linux/qcom_iommu.h>
#include <linux/msm_iommu_domains.h>
#include <media/msm_vidc.h>
#include "msm_vidc_internal.h"
#include "msm_vidc_common.h"
#include "msm_vidc_debug.h"
#include "vidc_hfi_api.h"
#include "vidc_hfi_api.h"
#include "msm_vidc_internal.h"
#include "msm_vidc_resources.h"
#include "msm_vidc_res_parse.h"
#include "venus_boot.h"
#include "vidc_hfi_api.h"


#define BASE_DEVICE_NUMBER 32
#define EARLY_FIRMWARE_LOAD_DELAY 1000

struct msm_vidc_drv *vidc_driver;

@@ -432,6 +434,62 @@ static struct attribute_group msm_vidc_core_attr_group = {
		.attrs = msm_vidc_core_attrs,
};

struct fw_load_handler_data {
	struct msm_vidc_core *core;
	struct delayed_work work;
};


static void fw_load_handler(struct work_struct *work)
{
	struct msm_vidc_core *core = NULL;
	struct fw_load_handler_data *handler = NULL;
	int rc = 0;

	handler = container_of(work, struct fw_load_handler_data,
			work.work);
	if (!handler || !handler->core) {
		dprintk(VIDC_ERR, "%s - invalid work or core handle\n",
				__func__);
		goto exit;
	}
	core = handler->core;

	rc = msm_comm_load_fw(core);
	if (rc) {
		dprintk(VIDC_ERR, "%s - failed to load fw\n", __func__);
		goto exit;
	}

	rc = msm_comm_check_core_init(core);
	if (rc) {
		dprintk(VIDC_ERR, "%s - failed to init core\n", __func__);
		goto exit;
	}
	dprintk(VIDC_DBG, "%s - firmware loaded successfully\n", __func__);

	msm_vidc_suspend(core->id);
exit:
	kfree(handler);
}

static void load_firmware(struct msm_vidc_core *core)
{
	struct fw_load_handler_data *handler = NULL;

	handler = kzalloc(sizeof(*handler), GFP_KERNEL);
	if (!handler) {
		dprintk(VIDC_ERR,
			"%s - failed to allocate sys error handler\n",
			__func__);
		return;
	}
	handler->core = core;
	INIT_DELAYED_WORK(&handler->work, fw_load_handler);
	schedule_delayed_work(&handler->work,
			msecs_to_jiffies(EARLY_FIRMWARE_LOAD_DELAY));
}

static int msm_vidc_probe(struct platform_device *pdev)
{
	int rc = 0;
@@ -551,6 +609,9 @@ static int msm_vidc_probe(struct platform_device *pdev)
	core->debugfs_root = msm_vidc_debugfs_init_core(
		core, vidc_driver->debugfs_root);
	pdev->dev.platform_data = core;

	load_firmware(core);

	return rc;
err_non_sec_pil_init:
	vidc_hfi_deinitialize(core->hfi_type, core->device);
+50 −14
Original line number Diff line number Diff line
@@ -2310,15 +2310,15 @@ void msm_comm_handle_thermal_event()
	}
}

static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
int msm_comm_check_core_init(struct msm_vidc_core *core)
{
	struct msm_vidc_core *core = inst->core;
	int rc = 0;

	mutex_lock(&core->lock);
	if (core->state >= VIDC_CORE_INIT_DONE) {
		dprintk(VIDC_INFO, "Video core: %d is already in state: %d\n",
				core->id, core->state);
		goto core_already_inited;
		goto exit;
	}
	dprintk(VIDC_DBG, "Waiting for SYS_INIT_DONE\n");
	rc = wait_for_completion_timeout(
@@ -2331,20 +2331,30 @@ static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
		goto exit;
	} else {
		core->state = VIDC_CORE_INIT_DONE;
		rc = 0;
	}
	dprintk(VIDC_DBG, "SYS_INIT_DONE!!!\n");
core_already_inited:
	change_inst_state(inst, MSM_VIDC_CORE_INIT_DONE);
	rc = 0;
exit:
	mutex_unlock(&core->lock);
	return rc;
}

static int msm_comm_init_core(struct msm_vidc_inst *inst)
static int msm_comm_init_core_done(struct msm_vidc_inst *inst)
{
	int rc = 0;

	rc = msm_comm_check_core_init(inst->core);
	if (rc) {
		dprintk(VIDC_ERR, "%s - failed to initialize core\n", __func__);
		return rc;
	}
	change_inst_state(inst, MSM_VIDC_CORE_INIT_DONE);
	return rc;
}

int msm_comm_load_fw(struct msm_vidc_core *core)
{
	int rc = 0;
	struct msm_vidc_core *core = inst->core;
	struct hfi_device *hdev;

	if (!core || !core->device)
@@ -2399,7 +2409,6 @@ static int msm_comm_init_core(struct msm_vidc_inst *inst)
	}

core_already_inited:
	change_inst_state(inst, MSM_VIDC_CORE_INIT);
	mutex_unlock(&core->lock);
	return rc;

@@ -2414,6 +2423,23 @@ fail_vote_bus:
	return rc;
}

static int msm_comm_init_core(struct msm_vidc_inst *inst)
{
	int rc = 0;

	if (!inst || !inst->core)
		return -EINVAL;

	rc = msm_comm_load_fw(inst->core);
	if (rc) {
		dprintk(VIDC_ERR, "%s - firmware loading failed\n", __func__);
		return rc;
	}

	change_inst_state(inst, MSM_VIDC_CORE_INIT);
	return rc;
}

static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
{
	struct msm_vidc_core *core;
@@ -2438,6 +2464,16 @@ static int msm_vidc_deinit_core(struct msm_vidc_inst *inst)
	msm_comm_scale_clocks_and_bus(inst);

	mutex_lock(&core->lock);

	/*
	 * If firmware is configured to be always loaded in memory,
	 * then unload it only if the core has gone in to bad state.
	 */
	if (core->resources.early_fw_load &&
		core->state != VIDC_CORE_INVALID) {
			goto core_already_uninited;
	}

	if (list_empty(&core->instances)) {
		cancel_delayed_work(&core->fw_unload_work);

+2 −0
Original line number Diff line number Diff line
@@ -73,4 +73,6 @@ int msm_comm_smem_get_domain_partition(struct msm_vidc_inst *inst,
			u32 flags, enum hal_buffer buffer_type,
			int *domain_num, int *partition_num);
enum hal_video_codec get_hal_codec_type(int fourcc);
int msm_comm_load_fw(struct msm_vidc_core *core);
int msm_comm_check_core_init(struct msm_vidc_core *core);
#endif
+5 −0
Original line number Diff line number Diff line
@@ -577,6 +577,11 @@ static int msm_vidc_load_clock_table(
	dprintk(VIDC_DBG, "Power collapse supported = %s\n",
		res->sw_power_collapsible ? "yes" : "no");

	res->early_fw_load = of_property_read_bool(pdev->dev.of_node,
				"qcom,early-fw-load");
	dprintk(VIDC_DBG, "Early fw load = %s\n",
				res->early_fw_load ? "yes" : "no");

	return 0;

err_load_clk_prop_fail:
Loading