Commit aee3c143 authored by Thierry Reding's avatar Thierry Reding Committed by Mauro Carvalho Chehab
Browse files

media: staging: tegra-vde: Support reference picture marking



Tegra114 and Tegra124 support reference picture marking, which will
cause BSEV to write picture marking data to SDRAM. Make sure there is
a valid destination address for that data to avoid error messages from
the memory controller.

[digetx@gmail.com: added BO support and moved secure BO allocation to kernel]
Tested-by: Anton Bambura <jenneron@protonmail.com> # T114 ASUS TF701T
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
Co-developed-by: default avatarDmitry Osipenko <digetx@gmail.com>
Signed-off-by: default avatarDmitry Osipenko <digetx@gmail.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 41479adb
Loading
Loading
Loading
Loading
+123 −1
Original line number Diff line number Diff line
@@ -84,6 +84,96 @@ static int tegra_vde_wait_mbe(struct tegra_vde *vde)
					  (tmp >= 0x10), 1, 100);
}

static int tegra_vde_alloc_bo(struct tegra_vde *vde,
			      struct tegra_vde_bo **ret_bo,
			      enum dma_data_direction dma_dir,
			      size_t size)
{
	struct device *dev = vde->miscdev.parent;
	struct tegra_vde_bo *bo;
	int err;

	bo = kzalloc(sizeof(*bo), GFP_KERNEL);
	if (!bo)
		return -ENOMEM;

	bo->vde = vde;
	bo->size = size;
	bo->dma_dir = dma_dir;
	bo->dma_attrs = DMA_ATTR_WRITE_COMBINE |
			DMA_ATTR_NO_KERNEL_MAPPING;

	if (!vde->domain)
		bo->dma_attrs |= DMA_ATTR_FORCE_CONTIGUOUS;

	bo->dma_cookie = dma_alloc_attrs(dev, bo->size, &bo->dma_handle,
					 GFP_KERNEL, bo->dma_attrs);
	if (!bo->dma_cookie) {
		dev_err(dev, "Failed to allocate DMA buffer of size: %zu\n",
			bo->size);
		err = -ENOMEM;
		goto free_bo;
	}

	err = dma_get_sgtable_attrs(dev, &bo->sgt, bo->dma_cookie,
				    bo->dma_handle, bo->size, bo->dma_attrs);
	if (err) {
		dev_err(dev, "Failed to get DMA buffer SG table: %d\n", err);
		goto free_attrs;
	}

	err = dma_map_sgtable(dev, &bo->sgt, bo->dma_dir, bo->dma_attrs);
	if (err) {
		dev_err(dev, "Failed to map DMA buffer SG table: %d\n", err);
		goto free_table;
	}

	if (vde->domain) {
		err = tegra_vde_iommu_map(vde, &bo->sgt, &bo->iova, bo->size);
		if (err) {
			dev_err(dev, "Failed to map DMA buffer IOVA: %d\n", err);
			goto unmap_sgtable;
		}

		bo->dma_addr = iova_dma_addr(&vde->iova, bo->iova);
	} else {
		bo->dma_addr = sg_dma_address(bo->sgt.sgl);
	}

	*ret_bo = bo;

	return 0;

unmap_sgtable:
	dma_unmap_sgtable(dev, &bo->sgt, bo->dma_dir, bo->dma_attrs);
free_table:
	sg_free_table(&bo->sgt);
free_attrs:
	dma_free_attrs(dev, bo->size, bo->dma_cookie, bo->dma_handle,
		       bo->dma_attrs);
free_bo:
	kfree(bo);

	return err;
}

static void tegra_vde_free_bo(struct tegra_vde_bo *bo)
{
	struct tegra_vde *vde = bo->vde;
	struct device *dev = vde->miscdev.parent;

	if (vde->domain)
		tegra_vde_iommu_unmap(vde, bo->iova);

	dma_unmap_sgtable(dev, &bo->sgt, bo->dma_dir, bo->dma_attrs);

	sg_free_table(&bo->sgt);

	dma_free_attrs(dev, bo->size, bo->dma_cookie, bo->dma_handle,
		       bo->dma_attrs);
	kfree(bo);
}

static int tegra_vde_setup_mbe_frame_idx(struct tegra_vde *vde,
					 unsigned int refs_nb,
					 bool setup_refs)
@@ -424,6 +514,9 @@ static int tegra_vde_setup_hw_context(struct tegra_vde *vde,

	tegra_vde_writel(vde, bitstream_data_addr, vde->sxe, 0x6C);

	if (vde->soc->supports_ref_pic_marking)
		tegra_vde_writel(vde, vde->secure_bo->dma_addr, vde->sxe, 0x7c);

	value = 0x10000005;
	value |= ctx->pic_width_in_mbs << 11;
	value |= ctx->pic_height_in_mbs << 3;
@@ -958,6 +1051,8 @@ static int tegra_vde_probe(struct platform_device *pdev)

	platform_set_drvdata(pdev, vde);

	vde->soc = of_device_get_match_data(&pdev->dev);

	vde->sxe = devm_platform_ioremap_resource_byname(pdev, "sxe");
	if (IS_ERR(vde->sxe))
		return PTR_ERR(vde->sxe);
@@ -1077,6 +1172,12 @@ static int tegra_vde_probe(struct platform_device *pdev)

	pm_runtime_put(dev);

	err = tegra_vde_alloc_bo(vde, &vde->secure_bo, DMA_FROM_DEVICE, 4096);
	if (err) {
		dev_err(dev, "Failed to allocate secure BO: %d\n", err);
		goto err_pm_runtime;
	}

	return 0;

err_pm_runtime:
@@ -1100,6 +1201,8 @@ static int tegra_vde_remove(struct platform_device *pdev)
	struct tegra_vde *vde = platform_get_drvdata(pdev);
	struct device *dev = &pdev->dev;

	tegra_vde_free_bo(vde->secure_bo);

	/*
	 * As it increments RPM usage_count even on errors, we don't need to
	 * check the returned code here.
@@ -1173,8 +1276,27 @@ static const struct dev_pm_ops tegra_vde_pm_ops = {
				tegra_vde_pm_resume)
};

static const struct tegra_vde_soc tegra124_vde_soc = {
	.supports_ref_pic_marking = true,
};

static const struct tegra_vde_soc tegra114_vde_soc = {
	.supports_ref_pic_marking = true,
};

static const struct tegra_vde_soc tegra30_vde_soc = {
	.supports_ref_pic_marking = false,
};

static const struct tegra_vde_soc tegra20_vde_soc = {
	.supports_ref_pic_marking = false,
};

static const struct of_device_id tegra_vde_of_match[] = {
	{ .compatible = "nvidia,tegra20-vde", },
	{ .compatible = "nvidia,tegra124-vde", .data = &tegra124_vde_soc },
	{ .compatible = "nvidia,tegra114-vde", .data = &tegra114_vde_soc },
	{ .compatible = "nvidia,tegra30-vde", .data = &tegra30_vde_soc },
	{ .compatible = "nvidia,tegra20-vde", .data = &tegra20_vde_soc },
	{ },
};
MODULE_DEVICE_TABLE(of, tegra_vde_of_match);
+18 −0
Original line number Diff line number Diff line
@@ -24,6 +24,22 @@ struct iommu_domain;
struct reset_control;
struct dma_buf_attachment;

struct tegra_vde_soc {
	bool supports_ref_pic_marking;
};

struct tegra_vde_bo {
	struct iova *iova;
	struct sg_table sgt;
	struct tegra_vde *vde;
	enum dma_data_direction dma_dir;
	unsigned long dma_attrs;
	dma_addr_t dma_handle;
	dma_addr_t dma_addr;
	void *dma_cookie;
	size_t size;
};

struct tegra_vde {
	void __iomem *sxe;
	void __iomem *bsev;
@@ -48,6 +64,8 @@ struct tegra_vde {
	struct iova_domain iova;
	struct iova *iova_resv_static_addresses;
	struct iova *iova_resv_last_page;
	const struct tegra_vde_soc *soc;
	struct tegra_vde_bo *secure_bo;
	dma_addr_t iram_lists_addr;
	u32 *iram;
};