summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0120-media-aspeed-adjust-irq-enabling-timing-and-resource.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0120-media-aspeed-adjust-irq-enabling-timing-and-resource.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0120-media-aspeed-adjust-irq-enabling-timing-and-resource.patch512
1 files changed, 512 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0120-media-aspeed-adjust-irq-enabling-timing-and-resource.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0120-media-aspeed-adjust-irq-enabling-timing-and-resource.patch
new file mode 100644
index 000000000..3474f0c8b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0120-media-aspeed-adjust-irq-enabling-timing-and-resource.patch
@@ -0,0 +1,512 @@
+From 82109f3a6a9d044e7244f186eff53dac0bbe87fe Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Tue, 29 Sep 2020 16:29:28 -0700
+Subject: [PATCH] media: aspeed: adjust irq enabling timing and resource
+ handling
+
+This commit makes irq enabling to be after video engine
+initialization to avoid any garbage interrupt handling in
+uninitialized state. Also, this commit changes behavior of DMA
+memory allocation for frame buffers and JPEG header buffer from
+dynamic to static for better performance and to avoid any potential
+memory corruption issue caused by invalid DMA address or length.
+This commit also changes VR004[5] bit handling logic to set the bit
+only when capture and compression is triggered.
+
+Also, it fixes the clock enabling flow to give a sufficient delay
+to the video engine hardware to make it get stablized itself.
+Currently, only eclk is coupled with SCU04[6] reset flag for
+video engine so 10ms of delay will be made by the clk-aspeed module
+when this driver enables eclk. Thus, clock enabling order should
+be vclk and then eclk to get sufficient delay after enabling
+clocks and resetting the hardware.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/media/platform/aspeed-video.c | 245 ++++++++++++++++----------
+ 1 file changed, 151 insertions(+), 94 deletions(-)
+
+diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c
+index a09cdb148c53..cf49c52fa5f0 100644
+--- a/drivers/media/platform/aspeed-video.c
++++ b/drivers/media/platform/aspeed-video.c
+@@ -52,9 +52,12 @@
+
+ #define VE_MAX_SRC_BUFFER_SIZE 0x8ca000 /* 1920 * 1200, 32bpp */
+ #define VE_JPEG_HEADER_SIZE 0x006000 /* 512 * 12 * 4 */
++#define VE_MAX_COMP_BUFFER_SIZE 0x400000 /* 128KB * 32 */
++#define VE_MAX_BCD_FLAG_BUFFER_SIZE 0x008ca0 /* (1920 / 4) * (1200 / 4) */
+
+ #define VE_PROTECTION_KEY 0x000
+ #define VE_PROTECTION_KEY_UNLOCK 0x1a038aa8
++#define VE_PROTECTION_KEY_LOCK 0x0
+
+ #define VE_SEQ_CTRL 0x004
+ #define VE_SEQ_CTRL_TRIG_MODE_DET BIT(0)
+@@ -105,6 +108,8 @@
+ #define VE_SCALING_FILTER2 0x020
+ #define VE_SCALING_FILTER3 0x024
+
++#define VE_BCD_CTRL 0x02c
++
+ #define VE_CAP_WINDOW 0x030
+ #define VE_COMP_WINDOW 0x034
+ #define VE_COMP_PROC_OFFSET 0x038
+@@ -113,6 +118,7 @@
+ #define VE_SRC0_ADDR 0x044
+ #define VE_SRC_SCANLINE_OFFSET 0x048
+ #define VE_SRC1_ADDR 0x04c
++#define VE_BCD_ADDR 0x050
+ #define VE_COMP_ADDR 0x054
+
+ #define VE_STREAM_BUF_SIZE 0x058
+@@ -168,6 +174,9 @@
+ #define VE_SYNC_STATUS_VSYNC_SHF 16
+ #define VE_SYNC_STATUS_VSYNC GENMASK(27, VE_SYNC_STATUS_VSYNC_SHF)
+
++#define VE_VM_SRC_ADDR 0x244
++#define VE_VM_COMP_ADDR 0x254
++
+ #define VE_INTERRUPT_CTRL 0x304
+ #define VE_INTERRUPT_STATUS 0x308
+ #define VE_INTERRUPT_MODE_DETECT_WD BIT(0)
+@@ -234,8 +243,11 @@ struct aspeed_video {
+ unsigned int sequence;
+
+ unsigned int max_compressed_size;
++ struct reserved_mem *rsvd_mem;
+ struct aspeed_video_addr srcs[2];
+- struct aspeed_video_addr jpeg;
++ struct aspeed_video_addr jpeg_hdr;
++ struct aspeed_video_addr comp;
++ struct aspeed_video_addr bcd;
+
+ bool yuv420;
+ unsigned int frame_rate;
+@@ -439,6 +451,7 @@ static int aspeed_video_start_frame(struct aspeed_video *video)
+ unsigned long flags;
+ struct aspeed_video_buffer *buf;
+ u32 seq_ctrl = aspeed_video_read(video, VE_SEQ_CTRL);
++ u32 comp_ctrl;
+
+ if (video->v4l2_input_status) {
+ dev_dbg(video->dev, "No signal; don't start frame\n");
+@@ -467,12 +480,23 @@ static int aspeed_video_start_frame(struct aspeed_video *video)
+ aspeed_video_write(video, VE_COMP_PROC_OFFSET, 0);
+ aspeed_video_write(video, VE_COMP_OFFSET, 0);
+ aspeed_video_write(video, VE_COMP_ADDR, addr);
++ comp_ctrl = VE_COMP_CTRL_RSVD |
++ FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) |
++ FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10);
++ aspeed_video_update(video, VE_COMP_CTRL,
++ VE_COMP_CTRL_DCT_LUM | VE_COMP_CTRL_DCT_CHR,
++ comp_ctrl);
+
+ aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,
+ VE_INTERRUPT_COMP_COMPLETE);
+
++ /* VE_SEQ_CTRL_AUTO_COMP should be set before VE_SEQ_CTRL_TRIG_COMP */
++ aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_AUTO_COMP);
++ if (video->yuv420)
++ aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_YUV420);
+ aspeed_video_update(video, VE_SEQ_CTRL, 0,
+- VE_SEQ_CTRL_TRIG_CAPTURE | VE_SEQ_CTRL_TRIG_COMP);
++ VE_SEQ_CTRL_TRIG_CAPTURE | VE_SEQ_CTRL_TRIG_COMP |
++ VE_SEQ_CTRL_JPEG_MODE);
+
+ return 0;
+ }
+@@ -497,8 +521,8 @@ static void aspeed_video_off(struct aspeed_video *video)
+ aspeed_video_write(video, VE_INTERRUPT_STATUS, 0xffffffff);
+
+ /* Turn off the relevant clocks */
+- clk_disable(video->vclk);
+ clk_disable(video->eclk);
++ clk_disable(video->vclk);
+
+ clear_bit(VIDEO_CLOCKS_ON, &video->flags);
+ }
+@@ -509,8 +533,8 @@ static void aspeed_video_on(struct aspeed_video *video)
+ return;
+
+ /* Turn on the relevant clocks */
+- clk_enable(video->eclk);
+ clk_enable(video->vclk);
++ clk_enable(video->eclk);
+
+ set_bit(VIDEO_CLOCKS_ON, &video->flags);
+ }
+@@ -602,7 +626,10 @@ static irqreturn_t aspeed_video_irq(int irq, void *arg)
+ aspeed_video_update(video, VE_SEQ_CTRL,
+ VE_SEQ_CTRL_TRIG_CAPTURE |
+ VE_SEQ_CTRL_FORCE_IDLE |
+- VE_SEQ_CTRL_TRIG_COMP, 0);
++ VE_SEQ_CTRL_TRIG_COMP |
++ VE_SEQ_CTRL_AUTO_COMP |
++ VE_SEQ_CTRL_YUV420 |
++ VE_SEQ_CTRL_JPEG_MODE, 0);
+ aspeed_video_update(video, VE_INTERRUPT_CTRL,
+ VE_INTERRUPT_COMP_COMPLETE, 0);
+ aspeed_video_write(video, VE_INTERRUPT_STATUS,
+@@ -686,6 +713,9 @@ static bool aspeed_video_alloc_buf(struct aspeed_video *video,
+ static void aspeed_video_free_buf(struct aspeed_video *video,
+ struct aspeed_video_addr *addr)
+ {
++ if (!addr->virt)
++ return;
++
+ dma_free_coherent(video->dev, addr->size, addr->virt, addr->dma);
+ addr->size = 0;
+ addr->dma = 0ULL;
+@@ -824,14 +854,10 @@ static void aspeed_video_get_resolution(struct aspeed_video *video)
+ det->width = (video->frame_right - video->frame_left) + 1;
+ video->v4l2_input_status = 0;
+
+- /*
+- * Enable mode-detect watchdog, resolution-change watchdog and
+- * automatic compression after frame capture.
+- */
++ /* Enable mode-detect watchdog and resolution-change watchdog */
+ aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,
+ VE_INTERRUPT_MODE_DETECT_WD);
+- aspeed_video_update(video, VE_SEQ_CTRL, 0,
+- VE_SEQ_CTRL_AUTO_COMP | VE_SEQ_CTRL_EN_WATCHDOG);
++ aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_EN_WATCHDOG);
+
+ dev_dbg(video->dev, "Got resolution: %dx%d\n", det->width,
+ det->height);
+@@ -880,64 +906,38 @@ static void aspeed_video_set_resolution(struct aspeed_video *video)
+ } else {
+ aspeed_video_update(video, VE_CTRL, 0, VE_CTRL_DIRECT_FETCH);
+ }
+-
+- size *= 4;
+-
+- if (size != video->srcs[0].size) {
+- if (video->srcs[0].size)
+- aspeed_video_free_buf(video, &video->srcs[0]);
+- if (video->srcs[1].size)
+- aspeed_video_free_buf(video, &video->srcs[1]);
+-
+- if (!aspeed_video_alloc_buf(video, &video->srcs[0], size))
+- goto err_mem;
+- if (!aspeed_video_alloc_buf(video, &video->srcs[1], size))
+- goto err_mem;
+-
+- aspeed_video_write(video, VE_SRC0_ADDR, video->srcs[0].dma);
+- aspeed_video_write(video, VE_SRC1_ADDR, video->srcs[1].dma);
+- }
+-
+- return;
+-
+-err_mem:
+- dev_err(video->dev, "Failed to allocate source buffers\n");
+-
+- if (video->srcs[0].size)
+- aspeed_video_free_buf(video, &video->srcs[0]);
+ }
+
+ static void aspeed_video_init_regs(struct aspeed_video *video)
+ {
+- u32 comp_ctrl = VE_COMP_CTRL_RSVD |
+- FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) |
+- FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10);
+ u32 ctrl = VE_CTRL_AUTO_OR_CURSOR;
+- u32 seq_ctrl = VE_SEQ_CTRL_JPEG_MODE;
+
+ if (video->frame_rate)
+ ctrl |= FIELD_PREP(VE_CTRL_FRC, video->frame_rate);
+
+- if (video->yuv420)
+- seq_ctrl |= VE_SEQ_CTRL_YUV420;
+-
+ /* Unlock VE registers */
+ aspeed_video_write(video, VE_PROTECTION_KEY, VE_PROTECTION_KEY_UNLOCK);
+
++ /* Set buffer addresses */
++ aspeed_video_write(video, VE_MEM_RESTRICT_START, video->rsvd_mem->base);
++ aspeed_video_write(video, VE_MEM_RESTRICT_END,
++ video->rsvd_mem->base + video->rsvd_mem->size);
++ aspeed_video_write(video, VE_JPEG_ADDR, video->jpeg_hdr.dma);
++ aspeed_video_write(video, VE_SRC0_ADDR, video->srcs[0].dma);
++ aspeed_video_write(video, VE_SRC1_ADDR, video->srcs[1].dma);
++ aspeed_video_write(video, VE_BCD_ADDR, video->bcd.dma);
++ aspeed_video_write(video, VE_VM_SRC_ADDR, video->srcs[0].dma);
++ aspeed_video_write(video, VE_VM_COMP_ADDR, video->comp.dma);
++
+ /* Disable interrupts */
+ aspeed_video_write(video, VE_INTERRUPT_CTRL, 0);
+ aspeed_video_write(video, VE_INTERRUPT_STATUS, 0xffffffff);
+
+- /* Clear the offset */
+- aspeed_video_write(video, VE_COMP_PROC_OFFSET, 0);
+- aspeed_video_write(video, VE_COMP_OFFSET, 0);
+-
+- aspeed_video_write(video, VE_JPEG_ADDR, video->jpeg.dma);
+-
+ /* Set control registers */
+- aspeed_video_write(video, VE_SEQ_CTRL, seq_ctrl);
++ aspeed_video_write(video, VE_SEQ_CTRL, 0);
++ aspeed_video_write(video, VE_COMP_CTRL, 0);
++ aspeed_video_write(video, VE_BCD_CTRL, 0);
+ aspeed_video_write(video, VE_CTRL, ctrl);
+- aspeed_video_write(video, VE_COMP_CTRL, comp_ctrl);
+
+ /* Don't downscale */
+ aspeed_video_write(video, VE_SCALING_FACTOR, 0x10001000);
+@@ -975,11 +975,8 @@ static void aspeed_video_stop(struct aspeed_video *video)
+
+ aspeed_video_off(video);
+
+- if (video->srcs[0].size)
+- aspeed_video_free_buf(video, &video->srcs[0]);
+-
+- if (video->srcs[1].size)
+- aspeed_video_free_buf(video, &video->srcs[1]);
++ /* Lock VE registers */
++ aspeed_video_write(video, VE_PROTECTION_KEY, VE_PROTECTION_KEY_LOCK);
+
+ video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;
+ video->flags = 0;
+@@ -1275,8 +1272,9 @@ static void aspeed_video_update_jpeg_quality(struct aspeed_video *video)
+
+ static void aspeed_video_update_subsampling(struct aspeed_video *video)
+ {
+- if (video->jpeg.virt)
+- aspeed_video_init_jpeg_table(video->jpeg.virt, video->yuv420);
++ if (video->jpeg_hdr.virt)
++ aspeed_video_init_jpeg_table(video->jpeg_hdr.virt,
++ video->yuv420);
+
+ if (video->yuv420)
+ aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_YUV420);
+@@ -1511,6 +1509,8 @@ static int aspeed_video_setup_video(struct aspeed_video *video)
+ struct v4l2_device *v4l2_dev = &video->v4l2_dev;
+ struct vb2_queue *vbq = &video->queue;
+ struct video_device *vdev = &video->vdev;
++ struct device *dev = video->dev;
++ int irq;
+ int rc;
+
+ video->pix_fmt.pixelformat = V4L2_PIX_FMT_JPEG;
+@@ -1535,12 +1535,9 @@ static int aspeed_video_setup_video(struct aspeed_video *video)
+ V4L2_JPEG_CHROMA_SUBSAMPLING_444);
+
+ if (video->ctrl_handler.error) {
+- v4l2_ctrl_handler_free(&video->ctrl_handler);
+- v4l2_device_unregister(v4l2_dev);
+-
+ dev_err(video->dev, "Failed to init controls: %d\n",
+ video->ctrl_handler.error);
+- return rc;
++ goto err_release_v4l2_dev;
+ }
+
+ v4l2_dev->ctrl_handler = &video->ctrl_handler;
+@@ -1558,11 +1555,8 @@ static int aspeed_video_setup_video(struct aspeed_video *video)
+
+ rc = vb2_queue_init(vbq);
+ if (rc) {
+- v4l2_ctrl_handler_free(&video->ctrl_handler);
+- v4l2_device_unregister(v4l2_dev);
+-
+ dev_err(video->dev, "Failed to init vb2 queue\n");
+- return rc;
++ goto err_release_v4l2_dev;
+ }
+
+ vdev->queue = vbq;
+@@ -1580,36 +1574,41 @@ static int aspeed_video_setup_video(struct aspeed_video *video)
+ video_set_drvdata(vdev, video);
+ rc = video_register_device(vdev, VFL_TYPE_GRABBER, 0);
+ if (rc) {
+- vb2_queue_release(vbq);
+- v4l2_ctrl_handler_free(&video->ctrl_handler);
+- v4l2_device_unregister(v4l2_dev);
+-
+ dev_err(video->dev, "Failed to register video device\n");
+- return rc;
++ goto err_release_vb2_queue;
+ }
+
+- return 0;
+-}
+-
+-static int aspeed_video_init(struct aspeed_video *video)
+-{
+- int irq;
+- int rc;
+- struct device *dev = video->dev;
+-
+ irq = irq_of_parse_and_map(dev->of_node, 0);
+ if (!irq) {
+ dev_err(dev, "Unable to find IRQ\n");
+- return -ENODEV;
++ rc = -ENODEV;
++ goto err_release_vb2_queue;
+ }
+
+ rc = devm_request_threaded_irq(dev, irq, NULL, aspeed_video_irq,
+ IRQF_ONESHOT, DEVICE_NAME, video);
+- if (rc < 0) {
++ if (rc) {
+ dev_err(dev, "Unable to request IRQ %d\n", irq);
+- return rc;
++ goto err_release_vb2_queue;
+ }
+
++ return 0;
++
++err_release_vb2_queue:
++ vb2_queue_release(vbq);
++err_release_v4l2_dev:
++ v4l2_ctrl_handler_free(&video->ctrl_handler);
++ v4l2_device_unregister(v4l2_dev);
++
++ return rc;
++}
++
++static int aspeed_video_init(struct aspeed_video *video)
++{
++ int rc;
++ struct device *dev = video->dev;
++ struct device_node *node;
++
+ video->eclk = devm_clk_get(dev, "eclk");
+ if (IS_ERR(video->eclk)) {
+ dev_err(dev, "Unable to get ECLK\n");
+@@ -1631,7 +1630,24 @@ static int aspeed_video_init(struct aspeed_video *video)
+ if (rc)
+ goto err_unprepare_eclk;
+
+- of_reserved_mem_device_init(dev);
++ rc = of_reserved_mem_device_init(dev);
++ if (rc) {
++ dev_err(dev, "Unable to get reserved memory %d\n", rc);
++ goto err_unprepare_eclk;
++ }
++
++ node = of_parse_phandle(dev->of_node, "memory-region", 0);
++ if (!node) {
++ rc = -ENOENT;
++ goto err_unprepare_eclk;
++ }
++
++ video->rsvd_mem = of_reserved_mem_lookup(node);
++ of_node_put(node);
++ if (!video->rsvd_mem) {
++ rc = -ENOENT;
++ goto err_unprepare_eclk;
++ }
+
+ rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (rc) {
+@@ -1639,17 +1655,55 @@ static int aspeed_video_init(struct aspeed_video *video)
+ goto err_release_reserved_mem;
+ }
+
+- if (!aspeed_video_alloc_buf(video, &video->jpeg,
++ if (!aspeed_video_alloc_buf(video, &video->jpeg_hdr,
+ VE_JPEG_HEADER_SIZE)) {
+ dev_err(dev, "Failed to allocate DMA for JPEG header\n");
+ rc = -ENOMEM;
+ goto err_release_reserved_mem;
+ }
+
+- aspeed_video_init_jpeg_table(video->jpeg.virt, video->yuv420);
++ if (!aspeed_video_alloc_buf(video, &video->srcs[0],
++ VE_MAX_SRC_BUFFER_SIZE)) {
++ dev_err(dev, "Failed to allocate DMA for SRCS[0]\n");
++ rc = -ENOMEM;
++ goto err_release_dma_mem;
++ }
++
++ if (!aspeed_video_alloc_buf(video, &video->srcs[1],
++ VE_MAX_SRC_BUFFER_SIZE)) {
++ dev_err(dev, "Failed to allocate DMA for SRCS[1]\n");
++ rc = -ENOMEM;
++ goto err_release_dma_mem;
++ }
++
++ if (!aspeed_video_alloc_buf(video, &video->comp,
++ VE_MAX_COMP_BUFFER_SIZE)) {
++ dev_err(dev, "Failed to allocate DMA for compressed video\n");
++ rc = -ENOMEM;
++ goto err_release_dma_mem;
++ }
++
++ if (!aspeed_video_alloc_buf(video, &video->bcd,
++ VE_MAX_BCD_FLAG_BUFFER_SIZE)) {
++ dev_err(dev, "Failed to allocate DMA for BCD flag\n");
++ rc = -ENOMEM;
++ goto err_release_dma_mem;
++ }
++
++ aspeed_video_init_jpeg_table(video->jpeg_hdr.virt, video->yuv420);
++
++ aspeed_video_on(video);
++ aspeed_video_init_regs(video);
++ aspeed_video_off(video);
+
+ return 0;
+
++err_release_dma_mem:
++ aspeed_video_free_buf(video, &video->comp);
++ aspeed_video_free_buf(video, &video->bcd);
++ aspeed_video_free_buf(video, &video->jpeg_hdr);
++ aspeed_video_free_buf(video, &video->srcs[0]);
++ aspeed_video_free_buf(video, &video->srcs[1]);
+ err_release_reserved_mem:
+ of_reserved_mem_device_release(dev);
+ clk_unprepare(video->vclk);
+@@ -1662,7 +1716,6 @@ static int aspeed_video_init(struct aspeed_video *video)
+ static int aspeed_video_probe(struct platform_device *pdev)
+ {
+ int rc;
+- struct resource *res;
+ struct aspeed_video *video =
+ devm_kzalloc(&pdev->dev, sizeof(*video), GFP_KERNEL);
+
+@@ -1677,10 +1730,7 @@ static int aspeed_video_probe(struct platform_device *pdev)
+ INIT_DELAYED_WORK(&video->res_work, aspeed_video_resolution_work);
+ INIT_LIST_HEAD(&video->buffers);
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-
+- video->base = devm_ioremap_resource(video->dev, res);
+-
++ video->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(video->base))
+ return PTR_ERR(video->base);
+
+@@ -1689,8 +1739,12 @@ static int aspeed_video_probe(struct platform_device *pdev)
+ return rc;
+
+ rc = aspeed_video_setup_video(video);
+- if (rc)
++ if (rc) {
++ of_reserved_mem_device_release(video->dev);
++ clk_unprepare(video->vclk);
++ clk_unprepare(video->eclk);
+ return rc;
++ }
+
+ return 0;
+ }
+@@ -1714,8 +1768,11 @@ static int aspeed_video_remove(struct platform_device *pdev)
+
+ v4l2_device_unregister(v4l2_dev);
+
+- dma_free_coherent(video->dev, VE_JPEG_HEADER_SIZE, video->jpeg.virt,
+- video->jpeg.dma);
++ aspeed_video_free_buf(video, &video->comp);
++ aspeed_video_free_buf(video, &video->bcd);
++ aspeed_video_free_buf(video, &video->jpeg_hdr);
++ aspeed_video_free_buf(video, &video->srcs[0]);
++ aspeed_video_free_buf(video, &video->srcs[1]);
+
+ of_reserved_mem_device_release(dev);
+
+--
+2.17.1
+