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

Commit cf8e23cc authored by Vikash Garodia's avatar Vikash Garodia Committed by Gerrit - the friendly Code Review server
Browse files

msm: vidc: Add and configure clocks using reset api



Video driver is currently mapping and configuring gcc clocks.
This may lead to unexpected behavior as video and gcc driver
operates on the same clock registers.
With the change, gcc clocks are configured using gcc framework
api. This will ensure that gcc driver manages the clock based
on video client requests.

Change-Id: I2b81ba9a3c8e50fbc68e09e06b597ce978f359ea
Signed-off-by: default avatarVikash Garodia <vgarodia@codeaurora.org>
Signed-off-by: default avatarShivendra Kakrania <shiven@codeaurora.org>
parent ea2ecca6
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -252,8 +252,6 @@ struct msm_vidc_platform_data {
	struct msm_vidc_efuse_data *efuse_data;
	unsigned int efuse_data_length;
	unsigned int sku_version;
	phys_addr_t gcc_register_base;
	uint32_t gcc_register_size;
	uint32_t vpu_ver;
	struct msm_vidc_ubwc_config_data *ubwc_config;
};
+0 −15
Original line number Diff line number Diff line
@@ -58,9 +58,6 @@
	.bank_spreading = bsp,	\
}

#define GCC_VIDEO_AXI_REG_START_ADDR	0x10B024
#define GCC_VIDEO_AXI_REG_SIZE		0xC

static struct msm_vidc_codec_data default_codec_data[] =  {
	CODEC_ENTRY(V4L2_PIX_FMT_H264, MSM_VIDC_ENCODER, 125, 675, 320),
	CODEC_ENTRY(V4L2_PIX_FMT_H264, MSM_VIDC_DECODER, 125, 675, 320),
@@ -551,8 +548,6 @@ static struct msm_vidc_platform_data default_data = {
	.efuse_data = NULL,
	.efuse_data_length = 0,
	.sku_version = 0,
	.gcc_register_base = 0,
	.gcc_register_size = 0,
	.vpu_ver = VPU_VERSION_IRIS2,
	.ubwc_config = 0x0,
};
@@ -568,8 +563,6 @@ static struct msm_vidc_platform_data kona_data = {
	.efuse_data = NULL,
	.efuse_data_length = 0,
	.sku_version = 0,
	.gcc_register_base = 0x10B024,//GCC_VIDEO_AXI0_CBCR,
	.gcc_register_size = 0x8,//GCC_VIDEO_AXI0_CBCR + GCC_VIDEO_AXI1_CBCR,
	.vpu_ver = VPU_VERSION_IRIS2,
	.ubwc_config = kona_ubwc_data,
};
@@ -585,8 +578,6 @@ static struct msm_vidc_platform_data sm6150_data = {
	.efuse_data = NULL,
	.efuse_data_length = 0,
	.sku_version = 0,
	.gcc_register_base = 0,
	.gcc_register_size = 0,
	.vpu_ver = VPU_VERSION_AR50,
	.ubwc_config = 0x0,
};
@@ -602,8 +593,6 @@ static struct msm_vidc_platform_data sm8150_data = {
	.efuse_data = NULL,
	.efuse_data_length = 0,
	.sku_version = 0,
	.gcc_register_base = GCC_VIDEO_AXI_REG_START_ADDR,
	.gcc_register_size = GCC_VIDEO_AXI_REG_SIZE,
	.vpu_ver = VPU_VERSION_IRIS1,
	.ubwc_config = 0x0,
};
@@ -619,8 +608,6 @@ static struct msm_vidc_platform_data sdm845_data = {
	.efuse_data = NULL,
	.efuse_data_length = 0,
	.sku_version = 0,
	.gcc_register_base = 0,
	.gcc_register_size = 0,
	.vpu_ver = VPU_VERSION_AR50,
	.ubwc_config = 0x0,
};
@@ -636,8 +623,6 @@ static struct msm_vidc_platform_data sdm670_data = {
	.efuse_data = sdm670_efuse_data,
	.efuse_data_length = ARRAY_SIZE(sdm670_efuse_data),
	.sku_version = 0,
	.gcc_register_base = 0,
	.gcc_register_size = 0,
	.vpu_ver = VPU_VERSION_AR50,
	.ubwc_config = 0x0,
};
+41 −3
Original line number Diff line number Diff line
@@ -681,6 +681,39 @@ static int msm_vidc_load_clock_table(
	return rc;
}

static int msm_vidc_load_reset_table(
		struct msm_vidc_platform_resources *res)
{
	struct platform_device *pdev = res->pdev;
	struct reset_set *rst = &res->reset_set;
	int num_clocks = 0, c = 0;

	num_clocks = of_property_count_strings(pdev->dev.of_node,
				"reset-names");
	if (num_clocks <= 0) {
		dprintk(VIDC_DBG, "No reset clocks found\n");
		rst->count = 0;
		return 0;
	}

	rst->reset_tbl = devm_kcalloc(&pdev->dev, num_clocks,
			sizeof(*rst->reset_tbl), GFP_KERNEL);
	if (!rst->reset_tbl)
		return -ENOMEM;

	rst->count = num_clocks;
	dprintk(VIDC_DBG, "Found %d reset clocks\n", num_clocks);

	for (c = 0; c < num_clocks; ++c) {
		struct reset_info *rc = &res->reset_set.reset_tbl[c];

		of_property_read_string_index(pdev->dev.of_node,
				"reset-names", c, &rc->name);
	}

	return 0;
}

static int msm_decide_dt_node(
		struct msm_vidc_platform_resources *res)
{
@@ -791,9 +824,6 @@ int read_platform_resources_from_drv_data(

	res->csc_coeff_data = &platform_data->csc_data;

	res->gcc_register_base = platform_data->gcc_register_base;
	res->gcc_register_size = platform_data->gcc_register_size;

	res->vpu_ver = platform_data->vpu_ver;
	res->ubwc_config = platform_data->ubwc_config;

@@ -871,6 +901,13 @@ int read_platform_resources_from_dt(
		goto err_load_allowed_clocks_table;
	}

	rc = msm_vidc_load_reset_table(res);
	if (rc) {
		dprintk(VIDC_ERR,
			"Failed to load reset table: %d\n", rc);
		goto err_load_reset_table;
	}

	rc = msm_vidc_populate_legacy_context_bank(res);
	if (rc) {
		dprintk(VIDC_ERR,
@@ -880,6 +917,7 @@ int read_platform_resources_from_dt(

return rc;

err_load_reset_table:
err_setup_legacy_cb:
	msm_vidc_free_allowed_clocks_table(res);
err_load_allowed_clocks_table:
+11 −2
Original line number Diff line number Diff line
@@ -108,6 +108,16 @@ struct bus_set {
	u32 count;
};

struct reset_info {
	struct reset_control *rst;
	const char *name;
};

struct reset_set {
	struct reset_info *reset_tbl;
	u32 count;
};

struct allowed_clock_rates_table {
	u32 clock_rate;
};
@@ -143,9 +153,7 @@ struct msm_vidc_mem_cdsp {
struct msm_vidc_platform_resources {
	phys_addr_t firmware_base;
	phys_addr_t register_base;
	phys_addr_t gcc_register_base;
	uint32_t register_size;
	uint32_t gcc_register_size;
	uint32_t irq;
	uint32_t sku_version;
	struct allowed_clock_rates_table *allowed_clks_tbl;
@@ -167,6 +175,7 @@ struct msm_vidc_platform_resources {
	struct regulator_set regulator_set;
	struct clock_set clock_set;
	struct bus_set bus_set;
	struct reset_set reset_set;
	bool sw_power_collapsible;
	bool slave_side_cp;
	struct list_head context_banks;
+59 −122
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <soc/qcom/subsystem_restart.h>
#include <linux/dma-mapping.h>
#include <linux/fastcvpd.h>
#include <linux/reset.h>
#include "hfi_packetization.h"
#include "msm_vidc_debug.h"
#include "venus_hfi.h"
@@ -125,7 +126,7 @@ struct venus_hfi_vpu_ops iris2_ops = {
	.interrupt_init = interrupt_init_iris1,
	.setup_dsp_uc_memmap = NULL,
	.clock_config_on_enable = NULL,
	.prepare_ahb2axi_bridge = NULL,
	.prepare_ahb2axi_bridge = prepare_ahb2axi_bridge,
};

/**
@@ -893,33 +894,6 @@ static void __write_register(struct venus_hfi_device *device,
	wmb();
}

static void __write_gcc_register(struct venus_hfi_device *device,
		u32 reg, u32 value)
{
	u32 hwiosymaddr = reg;
	u8 *base_addr;

	__strict_check(device);

	if (!device->power_enabled) {
		dprintk(VIDC_WARN,
			"HFI Write register failed : Power is OFF\n");
		msm_vidc_res_handle_fatal_hw_error(device->res, true);
		return;
	}

	base_addr = device->hal_data->gcc_reg_base;
	dprintk(VIDC_DBG, "GCC Base addr: %pK, writing to: %#x, Value: %#x.\n",
		base_addr, hwiosymaddr, value);
	base_addr += hwiosymaddr;
	writel_relaxed(value, base_addr);

	/*
	 * Memory barrier to make sure value is written into the register.
	 */
	wmb();
}

static int __read_register(struct venus_hfi_device *device, u32 reg)
{
	int rc = 0;
@@ -952,33 +926,6 @@ static int __read_register(struct venus_hfi_device *device, u32 reg)

	return rc;
}
static int __read_gcc_register(struct venus_hfi_device *device, u32 reg)
{
	int rc = 0;
	u8 *base_addr;

	__strict_check(device);

	if (!device->power_enabled) {
		dprintk(VIDC_WARN,
			"HFI Read register failed : Power is OFF\n");
		msm_vidc_res_handle_fatal_hw_error(device->res, true);
		return -EINVAL;
	}

	base_addr = device->hal_data->gcc_reg_base;

	rc = readl_relaxed(base_addr + reg);
	/*
	 * Memory barrier to make sure value is read correctly from the
	 * register.
	 */
	rmb();
	dprintk(VIDC_DBG, "GCC Base addr: %pK, read from: %#x, value: %#x...\n",
		base_addr, reg, rc);

	return rc;
}

static void __set_registers(struct venus_hfi_device *device)
{
@@ -3698,20 +3645,6 @@ static int __init_regs_and_interrupts(struct venus_hfi_device *device,
		goto error_irq_fail;
	}

	if (res->gcc_register_base) {
		hal->gcc_reg_base = devm_ioremap_nocache(&res->pdev->dev,
				res->gcc_register_base,
					res->gcc_register_size);
		hal->gcc_reg_size = res->gcc_register_size;
		if (!hal->gcc_reg_base) {
			dprintk(VIDC_ERR,
				"could not map gcc reg addr %pa of size %d\n",
				&res->gcc_register_base,
				res->gcc_register_size);
			goto error_irq_fail;
		}
	}

	device->hal_data = hal;
	rc = request_irq(res->irq, venus_hfi_isr, IRQF_TRIGGER_HIGH,
			"msm_vidc", device);
@@ -3725,9 +3658,7 @@ static int __init_regs_and_interrupts(struct venus_hfi_device *device,
		"firmware_base = %pa, register_base = %pa, register_size = %d\n",
		&res->firmware_base, &res->register_base,
		res->register_size);
	dprintk(VIDC_INFO,
		"gcc_register_base = %pa, gcc_register_size = %d\n",
		&res->gcc_register_base, res->gcc_register_size);

	return rc;

error_irq_fail:
@@ -3787,6 +3718,43 @@ static inline int __init_clocks(struct venus_hfi_device *device)
	return rc;
}

static int __handle_reset_clk(struct msm_vidc_platform_resources *res,
			enum reset_state state)
{
	int rc = 0;
	struct reset_control *rst;
	struct reset_set *rst_set = &res->reset_set;

	if (!rst_set->reset_tbl)
		return 0;

	dprintk(VIDC_DBG, "%s reset_state %d\n", __func__, state);
	for (int i = 0; i < rst_set->count; i++) {
		rst = rst_set->reset_tbl[i].rst;
		switch (state) {
		case INIT:
			rst = devm_reset_control_get(&res->pdev->dev,
						rst_set->reset_tbl[i].name);
			if (IS_ERR(rst))
				rc = PTR_ERR(rst);

			rst_set->reset_tbl[i].rst = rst;
			break;
		case ASSERT:
			rc = reset_control_assert(rst);
			break;
		case DEASSERT:
			rc = reset_control_deassert(rst);
			break;
		default:
			dprintk(VIDC_ERR, "Invalid reset request\n");
		}

		if (rc)
			return rc;
	}
	return 0;
}

static inline void __disable_unprepare_clks(struct venus_hfi_device *device)
{
@@ -3819,67 +3787,29 @@ static inline void __disable_unprepare_clks(struct venus_hfi_device *device)

static int prepare_ahb2axi_bridge(struct venus_hfi_device *device)
{

	u32 count = 0, axic_cbcr_status = 0, mvs_core_cbcr_status = 0;
	const u32 max_tries = 10;
	int rc = 0;
	int rc;

	if (!device) {
		dprintk(VIDC_ERR, "NULL device\n");
		rc = -EINVAL;
		goto fail_ahb2axi_enable;
		return -EINVAL;
	}

	if (!device->hal_data->gcc_reg_base) {
		dprintk(VIDC_WARN, "Skip resetting ahb2axi bridge\n");
		goto skip_reset_ahb2axi_bridge;
	rc = __handle_reset_clk(device->res, ASSERT);
	if (rc) {
		dprintk(VIDC_ERR, "failed to assert reset clocks\n");
		return rc;
	}

	dprintk(VIDC_DBG, "Resetting ahb2axi bridge\n");
	/* read registers */
	axic_cbcr_status = __read_gcc_register(device, VIDEO_GCC_AXIC_CBCR);
	mvs_core_cbcr_status = __read_register(device, VIDEO_CC_MVSC_CORE_CBCR);

	/* write enable clk_ares */
	__write_gcc_register(device, VIDEO_GCC_AXIC_CBCR,
		axic_cbcr_status|0x4);
	__write_register(device, VIDEO_CC_MVSC_CORE_CBCR,
		mvs_core_cbcr_status|0x4);

	/* wait for deassert */
	usleep_range(150, 250);

	/* write disable clk_ares */
	axic_cbcr_status = axic_cbcr_status & (~0x4);
	mvs_core_cbcr_status = mvs_core_cbcr_status & (~0x4);
	__write_gcc_register(device, VIDEO_GCC_AXIC_CBCR, axic_cbcr_status);
	__write_register(device, VIDEO_CC_MVSC_CORE_CBCR, mvs_core_cbcr_status);

	/* write enable clk */
	axic_cbcr_status = __read_gcc_register(device, VIDEO_GCC_AXIC_CBCR);
	axic_cbcr_status = axic_cbcr_status | 0x1;
	__write_gcc_register(device, VIDEO_GCC_AXIC_CBCR, axic_cbcr_status);
	usleep_range(150, 250);

	while (count < max_tries) {
		axic_cbcr_status =
			__read_gcc_register(device, VIDEO_GCC_AXIC_CBCR);
		if (!(axic_cbcr_status & BIT(31)))
			break;
		usleep_range(150, 250);
		count++;
	}
	if (count == max_tries) {
		dprintk(VIDC_ERR,
			"Unable to enable gcc_axic_cbcr (%#x)\n",
			axic_cbcr_status);
		rc = -EINVAL;
		goto fail_ahb2axi_enable;
	rc = __handle_reset_clk(device->res, DEASSERT);
	if (rc) {
		dprintk(VIDC_ERR, "failed to deassert reset clocks\n");
		return rc;
	}

fail_ahb2axi_enable:
skip_reset_ahb2axi_bridge:
	return rc;
	return 0;
}

static inline int __prepare_enable_clks(struct venus_hfi_device *device)
@@ -4156,6 +4086,13 @@ static int __init_resources(struct venus_hfi_device *device,
		goto err_init_clocks;
	}

	rc = __handle_reset_clk(res, INIT);
	if (rc) {
		dprintk(VIDC_ERR, "Failed to init reset clocks\n");
		rc = -ENODEV;
		goto err_init_reset_clk;
	}

	rc = __init_bus(device);
	if (rc) {
		dprintk(VIDC_ERR, "Failed to init bus: %d\n", rc);
@@ -4172,6 +4109,7 @@ static int __init_resources(struct venus_hfi_device *device,

	return rc;

err_init_reset_clk:
err_init_bus:
	__deinit_clocks(device);
err_init_clocks:
@@ -5154,7 +5092,6 @@ void venus_hfi_delete_device(void *device)
			destroy_workqueue(close->venus_pm_workq);
			free_irq(dev->hal_data->irq, close);
			iounmap(dev->hal_data->register_base);
			iounmap(dev->hal_data->gcc_reg_base);
			kfree(close->hal_data);
			kfree(close->response_pkt);
			kfree(close->raw_packet);
Loading