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

Commit cc43db19 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: vidc: Configure Video AHB2AXI for Multimedia(MMCX) power collapse" into msm-4.14

parents f91bef78 bb7000a7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -153,7 +153,7 @@ static struct msm_vidc_common_data sdm855_common_data[] = {
	},
	{
		.key = "qcom,power-collapse-delay",
		.value = 150000,
		.value = 1500,
	},
	{
		.key = "qcom,hw-resp-timeout",
+6 −0
Original line number Diff line number Diff line
@@ -29,6 +29,9 @@ enum clock_properties {

#define PERF_GOV "performance"

#define GCC_VIDEO_AXI_REG_START_ADDR	0x10B024
#define GCC_VIDEO_AXI_REG_SIZE		0xC

static inline struct device *msm_iommu_get_ctx(const char *ctx_name)
{
	return NULL;
@@ -812,6 +815,9 @@ int read_platform_resources_from_dt(
	res->register_base = kres ? kres->start : -1;
	res->register_size = kres ? (kres->end + 1 - kres->start) : -1;

	res->gcc_register_base = GCC_VIDEO_AXI_REG_START_ADDR;
	res->gcc_register_size = GCC_VIDEO_AXI_REG_SIZE;

	kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	res->irq = kres ? kres->start : -1;

+2 −0
Original line number Diff line number Diff line
@@ -146,7 +146,9 @@ struct subcache_set {
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;
+16 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ static struct {
	struct regulator *gdsc;
	const char *reg_name;
	void __iomem *reg_base;
	void __iomem *gcc_base;
	struct device *iommu_ctx_bank_dev;
	struct dma_iommu_mapping *mapping;
	dma_addr_t fw_iova;
@@ -435,6 +436,8 @@ int venus_boot_init(struct msm_vidc_platform_resources *res,
	}
	venus_data->reg_base = ioremap_nocache(res->register_base,
			(unsigned long)res->register_size);
	dprintk(VIDC_DBG, "venus reg: base %x size %x\n",
		 res->register_base, res->register_size);
	if (!venus_data->reg_base) {
		dprintk(VIDC_ERR,
				"could not map reg addr %pa of size %d\n",
@@ -442,6 +445,19 @@ int venus_boot_init(struct msm_vidc_platform_resources *res,
		rc = -ENOMEM;
		goto err_ioremap_fail;
	}

	venus_data->gcc_base = ioremap_nocache(res->gcc_register_base,
			(unsigned long)res->gcc_register_size);
	dprintk(VIDC_DBG, "gcc reg: base %x size %x\n",
		 res->gcc_register_base, res->gcc_register_size);
	if (!venus_data->gcc_base) {
		dprintk(VIDC_ERR,
				"could not map reg addr %pa of size %d\n",
				&res->gcc_register_base,
				res->gcc_register_size);
		rc = -ENOMEM;
		goto err_ioremap_fail;
	}
	venus_data->venus_notif_hdle = subsys_notif_register_notifier("venus",
							&venus_notifier);
	if (IS_ERR(venus_data->venus_notif_hdle)) {
+138 −0
Original line number Diff line number Diff line
@@ -664,6 +664,33 @@ 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, written 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;
@@ -696,6 +723,33 @@ 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)
{
@@ -3389,6 +3443,16 @@ static int __init_regs_and_interrupts(struct venus_hfi_device *device,
		goto error_irq_fail;
	}

	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);
@@ -3402,6 +3466,9 @@ 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:
@@ -3490,6 +3557,70 @@ static inline void __disable_unprepare_clks(struct venus_hfi_device *device)
	}
}

static inline 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;

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

	if (!device->hal_data->gcc_reg_base) {
		dprintk(VIDC_WARN, "Skip resetting ahb2axi bridge\n");
		goto skip_reset_ahb2axi_bridge;
	}

	/* 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;
	}

fail_ahb2axi_enable:
skip_reset_ahb2axi_bridge:
	return rc;
}

static inline int __prepare_enable_clks(struct venus_hfi_device *device)
{
	struct clock_info *cl = NULL, *cl_fail = NULL;
@@ -4130,6 +4261,12 @@ static int __venus_power_on(struct venus_hfi_device *device)
		goto fail_enable_gdsc;
	}

	rc = __prepare_ahb2axi_bridge(device);
	if (rc) {
		dprintk(VIDC_ERR, "Failed to enable ahb2axi: %d\n", rc);
		goto fail_enable_clks;
	}

	rc = __prepare_enable_clks(device);
	if (rc) {
		dprintk(VIDC_ERR, "Failed to enable clocks: %d\n", rc);
@@ -4668,6 +4805,7 @@ 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