mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 15:42:46 +00:00
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: Thierry Reding <treding@nvidia.com> Co-developed-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
parent
41479adb5e
commit
aee3c14363
2 changed files with 141 additions and 1 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue