mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-20 22:34:56 -04:00
media: imx-jpeg: Add support for descriptor allocation from SRAM
Add support for optional allocation of bitstream descriptors from SRAM
instead of DRAM. In case the encoder/decoder DT node contains 'sram'
property which points to 'mmio-sram', the driver will attempt to use
the SRAM instead of DRAM for descriptor allocation, which might improve
performance.
This also helps on i.MX95 rev.A with sporadic SLOTn_STATUS IMG_RD_ERR
bit 11 being triggered during JPEG encoding, which is caused by a bug
fixed on later SoC revisions. The bug occurs less often when using the
SRAM for descriptor storage, but is not entirely mitigated. The following
pipeline triggers the bug when descriptors get allocated from DRAM, the
pipeline often hangs after a few seconds and the encoder driver indicates
"timeout, cancel it":
gst-launch-1.0 videotestsrc ! \
video/x-raw,width=256,height=256,format=YUY2 ! \
queue ! v4l2jpegenc ! queue ! fakesink
Tested-by: Ming Qian <ming.qian@oss.nxp.com>
Signed-off-by: Marek Vasut <marek.vasut@mailbox.org>
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
committed by
Hans Verkuil
parent
88fe301896
commit
241e75fe6b
@@ -44,6 +44,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/genalloc.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -783,32 +784,40 @@ static int mxc_get_free_slot(struct mxc_jpeg_slot_data *slot_data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void mxc_jpeg_free(struct mxc_jpeg_dev *jpeg, size_t size, void *addr, dma_addr_t handle)
|
||||
{
|
||||
if (jpeg->sram_pool)
|
||||
gen_pool_free(jpeg->sram_pool, (unsigned long)addr, size);
|
||||
else
|
||||
dma_free_coherent(jpeg->dev, size, addr, handle);
|
||||
}
|
||||
|
||||
static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg)
|
||||
{
|
||||
/* free descriptor for decoding/encoding phase */
|
||||
dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
|
||||
jpeg->slot_data.desc,
|
||||
jpeg->slot_data.desc_handle);
|
||||
mxc_jpeg_free(jpeg, sizeof(struct mxc_jpeg_desc),
|
||||
jpeg->slot_data.desc,
|
||||
jpeg->slot_data.desc_handle);
|
||||
jpeg->slot_data.desc = NULL;
|
||||
jpeg->slot_data.desc_handle = 0;
|
||||
|
||||
/* free descriptor for encoder configuration phase / decoder DHT */
|
||||
dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
|
||||
jpeg->slot_data.cfg_desc,
|
||||
jpeg->slot_data.cfg_desc_handle);
|
||||
mxc_jpeg_free(jpeg, sizeof(struct mxc_jpeg_desc),
|
||||
jpeg->slot_data.cfg_desc,
|
||||
jpeg->slot_data.cfg_desc_handle);
|
||||
jpeg->slot_data.cfg_desc_handle = 0;
|
||||
jpeg->slot_data.cfg_desc = NULL;
|
||||
|
||||
/* free configuration stream */
|
||||
dma_free_coherent(jpeg->dev, MXC_JPEG_MAX_CFG_STREAM,
|
||||
jpeg->slot_data.cfg_stream_vaddr,
|
||||
jpeg->slot_data.cfg_stream_handle);
|
||||
mxc_jpeg_free(jpeg, MXC_JPEG_MAX_CFG_STREAM,
|
||||
jpeg->slot_data.cfg_stream_vaddr,
|
||||
jpeg->slot_data.cfg_stream_handle);
|
||||
jpeg->slot_data.cfg_stream_vaddr = NULL;
|
||||
jpeg->slot_data.cfg_stream_handle = 0;
|
||||
|
||||
dma_free_coherent(jpeg->dev, jpeg->slot_data.cfg_dec_size,
|
||||
jpeg->slot_data.cfg_dec_vaddr,
|
||||
jpeg->slot_data.cfg_dec_daddr);
|
||||
mxc_jpeg_free(jpeg, jpeg->slot_data.cfg_dec_size,
|
||||
jpeg->slot_data.cfg_dec_vaddr,
|
||||
jpeg->slot_data.cfg_dec_daddr);
|
||||
jpeg->slot_data.cfg_dec_size = 0;
|
||||
jpeg->slot_data.cfg_dec_vaddr = NULL;
|
||||
jpeg->slot_data.cfg_dec_daddr = 0;
|
||||
@@ -816,6 +825,15 @@ static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg)
|
||||
jpeg->slot_data.used = false;
|
||||
}
|
||||
|
||||
static struct mxc_jpeg_desc *mxc_jpeg_alloc(struct mxc_jpeg_dev *jpeg, size_t size,
|
||||
dma_addr_t *handle)
|
||||
{
|
||||
if (jpeg->sram_pool)
|
||||
return gen_pool_dma_zalloc(jpeg->sram_pool, size, handle);
|
||||
else
|
||||
return dma_alloc_coherent(jpeg->dev, size, handle, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg)
|
||||
{
|
||||
struct mxc_jpeg_desc *desc;
|
||||
@@ -826,37 +844,29 @@ static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg)
|
||||
goto skip_alloc; /* already allocated, reuse it */
|
||||
|
||||
/* allocate descriptor for decoding/encoding phase */
|
||||
desc = dma_alloc_coherent(jpeg->dev,
|
||||
sizeof(struct mxc_jpeg_desc),
|
||||
&jpeg->slot_data.desc_handle,
|
||||
GFP_ATOMIC);
|
||||
desc = mxc_jpeg_alloc(jpeg, sizeof(struct mxc_jpeg_desc),
|
||||
&jpeg->slot_data.desc_handle);
|
||||
if (!desc)
|
||||
goto err;
|
||||
jpeg->slot_data.desc = desc;
|
||||
|
||||
/* allocate descriptor for configuration phase (encoder only) */
|
||||
cfg_desc = dma_alloc_coherent(jpeg->dev,
|
||||
sizeof(struct mxc_jpeg_desc),
|
||||
&jpeg->slot_data.cfg_desc_handle,
|
||||
GFP_ATOMIC);
|
||||
cfg_desc = mxc_jpeg_alloc(jpeg, sizeof(struct mxc_jpeg_desc),
|
||||
&jpeg->slot_data.cfg_desc_handle);
|
||||
if (!cfg_desc)
|
||||
goto err;
|
||||
jpeg->slot_data.cfg_desc = cfg_desc;
|
||||
|
||||
/* allocate configuration stream */
|
||||
cfg_stm = dma_alloc_coherent(jpeg->dev,
|
||||
MXC_JPEG_MAX_CFG_STREAM,
|
||||
&jpeg->slot_data.cfg_stream_handle,
|
||||
GFP_ATOMIC);
|
||||
cfg_stm = mxc_jpeg_alloc(jpeg, MXC_JPEG_MAX_CFG_STREAM,
|
||||
&jpeg->slot_data.cfg_stream_handle);
|
||||
if (!cfg_stm)
|
||||
goto err;
|
||||
jpeg->slot_data.cfg_stream_vaddr = cfg_stm;
|
||||
|
||||
jpeg->slot_data.cfg_dec_size = MXC_JPEG_PATTERN_WIDTH * MXC_JPEG_PATTERN_HEIGHT * 2;
|
||||
jpeg->slot_data.cfg_dec_vaddr = dma_alloc_coherent(jpeg->dev,
|
||||
jpeg->slot_data.cfg_dec_size,
|
||||
&jpeg->slot_data.cfg_dec_daddr,
|
||||
GFP_ATOMIC);
|
||||
jpeg->slot_data.cfg_dec_vaddr = mxc_jpeg_alloc(jpeg, jpeg->slot_data.cfg_dec_size,
|
||||
&jpeg->slot_data.cfg_dec_daddr);
|
||||
if (!jpeg->slot_data.cfg_dec_vaddr)
|
||||
goto err;
|
||||
|
||||
@@ -2884,6 +2894,10 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
|
||||
jpeg->dev = dev;
|
||||
jpeg->mode = mode;
|
||||
|
||||
/* SRAM pool is optional */
|
||||
jpeg->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0);
|
||||
dev_info(dev, "Using DMA descriptor pool in %cRAM\n", jpeg->sram_pool ? 'S' : 'D');
|
||||
|
||||
/* Get clocks */
|
||||
ret = devm_clk_bulk_get_all(&pdev->dev, &jpeg->clks);
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -141,6 +141,7 @@ struct mxc_jpeg_dev {
|
||||
int num_domains;
|
||||
struct device **pd_dev;
|
||||
struct device_link **pd_link;
|
||||
struct gen_pool *sram_pool;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user