linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Support jpeg encode for MT8195
@ 2021-06-23  6:05 kyrie.wu
  2021-06-23  6:05 ` [PATCH 1/3] dt-bindings: mtk-jpeg: Add binding for MT8195 JPG kyrie.wu
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: kyrie.wu @ 2021-06-23  6:05 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Rick Chang,
	Bin Liu, Matthias Brugger, Tzung-Bi Shih
  Cc: Project_Global_Chrome_Upstream_Group, linux-media, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek, Tomasz Figa,
	xia.jiang, maoguang.meng, srv_heupstream, kyrie.wu

add component fromework to using multi-HW for MT8195 jpeg encode.

kyrie.wu (3):
  dt-bindings: mtk-jpeg: Add binding for MT8195 JPG
  media: mtk-jpegenc: use component framework to manage jpg HW
  media: mtk-jpegenc: design SW algorithm for using multi-HW of jpegenc

 .../bindings/media/mediatek-jpeg-encoder.txt       |   3 +
 drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c    | 631 +++++++++++++++++----
 drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h    |  80 ++-
 drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c  | 209 +++++++
 4 files changed, 820 insertions(+), 103 deletions(-)

-- 
2.6.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] dt-bindings: mtk-jpeg: Add binding for MT8195 JPG
  2021-06-23  6:05 [PATCH 0/3] Support jpeg encode for MT8195 kyrie.wu
@ 2021-06-23  6:05 ` kyrie.wu
  2021-06-25  9:18   ` Tzung-Bi Shih
  2021-06-23  6:05 ` [PATCH 2/3] media: mtk-jpegenc: use component framework to manage jpg HW kyrie.wu
  2021-06-23  6:05 ` [PATCH 3/3] media: mtk-jpegenc: design SW algorithm for using multi-HW of jpegenc kyrie.wu
  2 siblings, 1 reply; 10+ messages in thread
From: kyrie.wu @ 2021-06-23  6:05 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Rick Chang,
	Bin Liu, Matthias Brugger, Tzung-Bi Shih
  Cc: Project_Global_Chrome_Upstream_Group, linux-media, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek, Tomasz Figa,
	xia.jiang, maoguang.meng, srv_heupstream, kyrie.wu

Updates binding document for mt8195 jpeg driver.

Signed-off-by: kyrie.wu <kyrie.wu@mediatek.com>
---
 Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.txt b/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.txt
index 5e53c6a..ba30525 100644
--- a/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.txt
+++ b/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.txt
@@ -4,6 +4,9 @@ MediaTek JPEG Encoder is the JPEG encode hardware present in MediaTek SoCs
 
 Required properties:
 - compatible : "mediatek,mt2701-jpgenc"
+- compatible : "mediatek,mt8195-jpgenc"
+- compatible : "mediatek,mt8195-jpgenc0"
+- compatible : "mediatek,mt8195-jpgenc1"
   followed by "mediatek,mtk-jpgenc"
 - reg : physical base address of the JPEG encoder registers and length of
   memory mapped region.
-- 
2.6.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] media: mtk-jpegenc: use component framework to manage jpg HW
  2021-06-23  6:05 [PATCH 0/3] Support jpeg encode for MT8195 kyrie.wu
  2021-06-23  6:05 ` [PATCH 1/3] dt-bindings: mtk-jpeg: Add binding for MT8195 JPG kyrie.wu
@ 2021-06-23  6:05 ` kyrie.wu
  2021-06-25  9:18   ` Tzung-Bi Shih
  2021-06-29  7:33   ` Dafna Hirschfeld
  2021-06-23  6:05 ` [PATCH 3/3] media: mtk-jpegenc: design SW algorithm for using multi-HW of jpegenc kyrie.wu
  2 siblings, 2 replies; 10+ messages in thread
From: kyrie.wu @ 2021-06-23  6:05 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Rick Chang,
	Bin Liu, Matthias Brugger, Tzung-Bi Shih
  Cc: Project_Global_Chrome_Upstream_Group, linux-media, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek, Tomasz Figa,
	xia.jiang, maoguang.meng, srv_heupstream, kyrie.wu

Mtk jpeg encoder has several hardware, one HW may register a device
node; use component framework to manage jpg HW device node,
in this case, one device node could represent all jpg HW.

Signed-off-by: kyrie.wu <kyrie.wu@mediatek.com>
---
 drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c   | 467 ++++++++++++++++++----
 drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h   |  80 +++-
 drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c | 209 ++++++++++
 3 files changed, 670 insertions(+), 86 deletions(-)

diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index 88a23bc..c84815a 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -23,6 +23,7 @@
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-contig.h>
 #include <soc/mediatek/smi.h>
+#include <linux/component.h>
 
 #include "mtk_jpeg_enc_hw.h"
 #include "mtk_jpeg_dec_hw.h"
@@ -106,10 +107,45 @@ static struct mtk_jpeg_fmt mtk_jpeg_dec_formats[] = {
 #define MTK_JPEG_ENC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_enc_formats)
 #define MTK_JPEG_DEC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_dec_formats)
 
+/*
+ * mtk_jpeg_enc_param:  General jpeg encoding parameters
+ * @enc_w:		image width
+ * @enc_h:		image height
+ * @enable_exif:	EXIF enable for jpeg encode mode
+ * @enc_quality:	destination image quality in encode mode
+ * @enc_format:		input image format
+ * @restart_interval:	JPEG restart interval for JPEG encoding
+ * @img_stride:		jpeg encoder image stride
+ * @mem_stride:		jpeg encoder memory stride
+ * @total_encdu:	total 8x8 block number
+ */
+struct mtk_jpeg_enc_param {
+	u32 enc_w;
+	u32 enc_h;
+	u32 enable_exif;
+	u32 enc_quality;
+	u32 enc_format;
+	u32 restart_interval;
+	u32 img_stride;
+	u32 mem_stride;
+	u32 total_encdu;
+};
+
 struct mtk_jpeg_src_buf {
 	struct vb2_v4l2_buffer b;
 	struct list_head list;
+	u32 frame_num;
+	u32 bs_size;
+	int flags;
 	struct mtk_jpeg_dec_param dec_param;
+
+	struct mtk_jpeg_enc_param enc_param;
+	struct mtk_jpeg_ctx *curr_ctx;
+};
+
+enum {
+	MTK_JPEG_BUF_FLAGS_INIT	= 0,
+	MTK_JPEG_BUF_FLAGS_LAST_FRAME = 1,
 };
 
 static int debug;
@@ -1053,8 +1089,32 @@ static int mtk_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,
 
 static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg)
 {
-	int ret;
-
+	struct mtk_jpeg_dev *comp_dev;
+	struct mtk_jpegenc_pm *pm;
+	struct mtk_jpegenc_clk *jpegclk;
+	struct mtk_jpegenc_clk_info *clk_info;
+	int ret, i;
+
+	if (jpeg->variant->is_encoder) {
+		for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) {
+			comp_dev = jpeg->hw_dev[i];
+			if (!comp_dev) {
+				pr_err("Failed to get hw dev\n");
+				return;
+			}
+
+			pm = &comp_dev->pm;
+			jpegclk = &pm->venc_clk;
+			clk_info = jpegclk->clk_info;
+			ret = clk_prepare_enable(clk_info->jpegenc_clk);
+			if (ret) {
+				pr_err("jpegenc clk_prepare_enable %d %s fail\n",
+				       i, jpegclk->clk_info->clk_name);
+				return;
+			}
+		}
+		return;
+	}
 	ret = mtk_smi_larb_get(jpeg->larb);
 	if (ret)
 		dev_err(jpeg->dev, "mtk_smi_larb_get larbvdec fail %d\n", ret);
@@ -1067,59 +1127,30 @@ static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg)
 
 static void mtk_jpeg_clk_off(struct mtk_jpeg_dev *jpeg)
 {
+	struct mtk_jpeg_dev *comp_dev;
+	struct mtk_jpegenc_pm *pm;
+	struct mtk_jpegenc_clk *jpegclk;
+	int i;
+
+	if (jpeg->variant->is_encoder) {
+		for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) {
+			comp_dev = jpeg->hw_dev[i];
+			if (!comp_dev) {
+				pr_err("Failed to get hw dev\n");
+				return;
+			}
+
+			pm = &comp_dev->pm;
+			jpegclk = &pm->venc_clk;
+			clk_disable_unprepare(jpegclk->clk_info->jpegenc_clk);
+		}
+		return;
+	}
 	clk_bulk_disable_unprepare(jpeg->variant->num_clks,
 				   jpeg->variant->clks);
 	mtk_smi_larb_put(jpeg->larb);
 }
 
-static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg)
-{
-	struct mtk_jpeg_ctx *ctx;
-	struct vb2_v4l2_buffer *src_buf, *dst_buf;
-	enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
-	u32 result_size;
-
-	ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
-	if (!ctx) {
-		v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n");
-		return IRQ_HANDLED;
-	}
-
-	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-
-	result_size = mtk_jpeg_enc_get_file_size(jpeg->reg_base);
-	vb2_set_plane_payload(&dst_buf->vb2_buf, 0, result_size);
-
-	buf_state = VB2_BUF_STATE_DONE;
-
-	v4l2_m2m_buf_done(src_buf, buf_state);
-	v4l2_m2m_buf_done(dst_buf, buf_state);
-	v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
-	pm_runtime_put(ctx->jpeg->dev);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t mtk_jpeg_enc_irq(int irq, void *priv)
-{
-	struct mtk_jpeg_dev *jpeg = priv;
-	u32 irq_status;
-	irqreturn_t ret = IRQ_NONE;
-
-	cancel_delayed_work(&jpeg->job_timeout_work);
-
-	irq_status = readl(jpeg->reg_base + JPEG_ENC_INT_STS) &
-		     JPEG_ENC_INT_STATUS_MASK_ALLIRQ;
-	if (irq_status)
-		writel(0, jpeg->reg_base + JPEG_ENC_INT_STS);
-
-	if (!(irq_status & JPEG_ENC_INT_STATUS_DONE))
-		return ret;
-
-	ret = mtk_jpeg_enc_done(jpeg);
-	return ret;
-}
-
 static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv)
 {
 	struct mtk_jpeg_dev *jpeg = priv;
@@ -1313,6 +1344,138 @@ static int mtk_jpeg_clk_init(struct mtk_jpeg_dev *jpeg)
 	return 0;
 }
 
+void mtk_jpeg_put_buf(struct mtk_jpeg_dev *jpeg)
+{
+	struct mtk_jpeg_ctx *ctx = NULL;
+	struct vb2_v4l2_buffer *dst_buffer = NULL;
+	struct list_head *temp_entry = NULL;
+	struct list_head *pos = NULL;
+	struct mtk_jpeg_src_buf *dst_done_buf = NULL, *tmp_dst_done_buf = NULL;
+	unsigned long flags;
+
+	ctx = jpeg->hw_param.curr_ctx;
+	if (!ctx) {
+		pr_err("%s : %d, comp_jpeg ctx fail !!!\n", __func__, __LINE__);
+		return;
+	}
+
+	dst_buffer = jpeg->hw_param.dst_buffer;
+	if (!dst_buffer) {
+		pr_err("%s : %d, comp_jpeg dst_buffer fail !!!\n",
+		       __func__, __LINE__);
+		return;
+	}
+
+	dst_done_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buffer->vb2_buf);
+
+	spin_lock_irqsave(&ctx->done_queue_lock, flags);
+	list_add_tail(&dst_done_buf->list, &ctx->dst_done_queue);
+	while (!list_empty(&ctx->dst_done_queue) &&
+	       (pos != &ctx->dst_done_queue)) {
+		list_for_each_prev_safe(pos, temp_entry,
+					(&ctx->dst_done_queue)) {
+			tmp_dst_done_buf = list_entry(pos,
+						      struct mtk_jpeg_src_buf,
+						      list);
+			if (tmp_dst_done_buf->frame_num ==
+				ctx->last_done_frame_num) {
+				list_del(&tmp_dst_done_buf->list);
+				v4l2_m2m_buf_done(&tmp_dst_done_buf->b,
+						  VB2_BUF_STATE_DONE);
+				ctx->last_done_frame_num++;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&ctx->done_queue_lock, flags);
+}
+
+irqreturn_t mtk_jpegenc_hw_irq_handler(int irq, void *priv)
+{
+	struct mtk_jpeg_dev *jpeg = priv;
+	struct mtk_jpeg_ctx *ctx;
+	struct mtk_jpeg_dev *master_jpeg;
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	struct mtk_jpeg_src_buf *jpeg_dst_buf;
+
+	enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
+	u32 result_size;
+	u32 irq_status;
+
+	cancel_delayed_work(&jpeg->job_timeout_work);
+
+	src_buf = jpeg->hw_param.src_buffer;
+	dst_buf = jpeg->hw_param.dst_buffer;
+	ctx = jpeg->hw_param.curr_ctx;
+	master_jpeg = ctx->jpeg;
+	jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf);
+	irq_status = readl(jpeg->reg_base[MTK_JPEGENC_HW0] + JPEG_ENC_INT_STS) &
+		JPEG_ENC_INT_STATUS_MASK_ALLIRQ;
+	if (irq_status)
+		writel(0, jpeg->reg_base[MTK_JPEGENC_HW0] + JPEG_ENC_INT_STS);
+	if (!(irq_status & JPEG_ENC_INT_STATUS_DONE)) {
+		pr_err("%s : %d, jpeg encode failed\n", __func__, __LINE__);
+		goto irq_end;
+	}
+
+	result_size = mtk_jpeg_enc_get_file_size(jpeg->reg_base[0]);
+	vb2_set_plane_payload(&dst_buf->vb2_buf, 0, result_size);
+
+	buf_state = VB2_BUF_STATE_DONE;
+
+irq_end:
+	v4l2_m2m_buf_done(src_buf, buf_state);
+	mtk_jpeg_put_buf(jpeg);
+	pm_runtime_put(jpeg->pm.dev);
+	clk_disable_unprepare(jpeg->pm.venc_clk.clk_info->jpegenc_clk);
+	if (ctx->fh.m2m_ctx &&
+	    (!list_empty(&ctx->fh.m2m_ctx->out_q_ctx.rdy_queue) ||
+	    !list_empty(&ctx->fh.m2m_ctx->cap_q_ctx.rdy_queue))) {
+		queue_work(master_jpeg->workqueue, &ctx->jpeg_work);
+	}
+
+	jpeg->hw_state = MTK_JPEG_HW_IDLE;
+	wake_up(&master_jpeg->hw_wq);
+	atomic_inc(&jpeg->hw_rdy);
+	return IRQ_HANDLED;
+}
+
+void mtk_jpegenc_timeout_work(struct work_struct *work)
+{
+	struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev,
+		job_timeout_work.work);
+	struct mtk_jpeg_ctx *ctx = NULL;
+	struct mtk_jpeg_dev *master_jpeg;
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	struct mtk_jpeg_src_buf *jpeg_src_buf, *jpeg_dst_buf;
+	enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
+
+	src_buf = jpeg->hw_param.src_buffer;
+	dst_buf = jpeg->hw_param.dst_buffer;
+	ctx = jpeg->hw_param.curr_ctx;
+	if (!ctx) {
+		v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n");
+		return;
+	}
+
+	master_jpeg = ctx->jpeg;
+	if (!master_jpeg) {
+		v4l2_err(&jpeg->v4l2_dev, "master_jpeg is NULL\n");
+		return;
+	}
+
+	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
+	jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf);
+
+	mtk_jpeg_enc_reset(jpeg->reg_base[MTK_JPEGENC_HW0]);
+	pm_runtime_put(jpeg->pm.dev);
+	clk_disable_unprepare(jpeg->pm.venc_clk.clk_info->jpegenc_clk);
+	jpeg->hw_state = MTK_JPEG_HW_IDLE;
+	atomic_inc(&jpeg->hw_rdy);
+	wake_up(&master_jpeg->hw_wq);
+	v4l2_m2m_buf_done(src_buf, buf_state);
+	mtk_jpeg_put_buf(jpeg);
+}
+
 static void mtk_jpeg_job_timeout_work(struct work_struct *work)
 {
 	struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev,
@@ -1338,12 +1501,99 @@ static inline void mtk_jpeg_clk_release(struct mtk_jpeg_dev *jpeg)
 	put_device(jpeg->larb);
 }
 
+static  const struct of_device_id mtk_jpegenc_drv_ids[] = {
+	{
+		.compatible = "mediatek,mt8195-jpgenc0",
+		.data = (void *)MTK_JPEGENC_HW0,
+	},
+	{
+		.compatible = "mediatek,mt8195-jpgenc1",
+		.data = (void *)MTK_JPEGENC_HW1,
+	},
+	{},
+};
+
+static inline int mtk_vdec_compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static inline void mtk_vdec_release_of(struct device *dev, void *data)
+{
+	of_node_put(data);
+}
+
+static inline int mtk_jpegenc_bind(struct device *dev)
+{
+	struct mtk_jpeg_dev *data = dev_get_drvdata(dev);
+
+	return component_bind_all(dev, data);
+}
+
+static inline void mtk_jpegenc_unbind(struct device *dev)
+{
+	struct mtk_jpeg_dev *data = dev_get_drvdata(dev);
+
+	component_unbind_all(dev, data);
+}
+
+static const struct component_master_ops mtk_jpegenc_ops = {
+	.bind = mtk_jpegenc_bind,
+	.unbind = mtk_jpegenc_unbind,
+};
+
+struct component_match *mtk_jpegenc_match_add(struct mtk_jpeg_dev *jpeg)
+{
+	struct device *dev = jpeg->dev;
+	struct component_match *match = NULL;
+	int i;
+	char compatible[128] = {0};
+
+	for (i = 0; i < ARRAY_SIZE(mtk_jpegenc_drv_ids); i++) {
+		struct device_node *comp_node;
+		enum mtk_jpegenc_hw_id comp_idx;
+		const struct of_device_id *of_id;
+
+		memcpy(compatible, mtk_jpegenc_drv_ids[i].compatible,
+		       sizeof(mtk_jpegenc_drv_ids[i].compatible));
+
+		comp_node = of_find_compatible_node(NULL, NULL,
+						    compatible);
+		if (!comp_node)
+			continue;
+
+		if (!of_device_is_available(comp_node)) {
+			of_node_put(comp_node);
+			v4l2_err(&jpeg->v4l2_dev, "Fail to get jpeg enc HW node\n");
+			continue;
+		}
+
+		of_id = of_match_node(mtk_jpegenc_drv_ids, comp_node);
+		if (!of_id) {
+			v4l2_err(&jpeg->v4l2_dev, "Failed to get match node\n");
+			return ERR_PTR(-EINVAL);
+		}
+
+		comp_idx = (enum mtk_jpegenc_hw_id)of_id->data;
+		v4l2_info(&jpeg->v4l2_dev, "Get component:hw_id(%d),jpeg_dev(0x%p),comp_node(0x%p)\n",
+			  comp_idx, jpeg, comp_node);
+
+		jpeg->component_node[comp_idx] = comp_node;
+
+		component_match_add_release(dev, &match, mtk_vdec_release_of,
+					    mtk_vdec_compare_of, comp_node);
+	}
+
+	return match;
+}
+
 static int mtk_jpeg_probe(struct platform_device *pdev)
 {
 	struct mtk_jpeg_dev *jpeg;
 	struct resource *res;
 	int jpeg_irq;
 	int ret;
+	struct component_match *match;
 
 	jpeg = devm_kzalloc(&pdev->dev, sizeof(*jpeg), GFP_KERNEL);
 	if (!jpeg)
@@ -1355,31 +1605,47 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
 	jpeg->variant = of_device_get_match_data(jpeg->dev);
 	INIT_DELAYED_WORK(&jpeg->job_timeout_work, mtk_jpeg_job_timeout_work);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	jpeg->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(jpeg->reg_base)) {
-		ret = PTR_ERR(jpeg->reg_base);
-		return ret;
-	}
+	if (!jpeg->variant->is_encoder) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		jpeg->reg_base[MTK_JPEGENC_HW0] =
+			devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(jpeg->reg_base[MTK_JPEGENC_HW0])) {
+			ret = PTR_ERR(jpeg->reg_base[MTK_JPEGENC_HW0]);
+			return ret;
+		}
 
-	jpeg_irq = platform_get_irq(pdev, 0);
-	if (jpeg_irq < 0) {
-		dev_err(&pdev->dev, "Failed to get jpeg_irq %d.\n", jpeg_irq);
-		return jpeg_irq;
-	}
+		jpeg_irq = platform_get_irq(pdev, 0);
+		if (jpeg_irq < 0) {
+			dev_err(&pdev->dev, "Failed to get jpeg_irq %d.\n",
+				jpeg_irq);
+			return jpeg_irq;
+		}
 
-	ret = devm_request_irq(&pdev->dev, jpeg_irq,
-			       jpeg->variant->irq_handler, 0, pdev->name, jpeg);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to request jpeg_irq %d (%d)\n",
-			jpeg_irq, ret);
-		goto err_req_irq;
-	}
+		ret = devm_request_irq(&pdev->dev, jpeg_irq,
+				       jpeg->variant->irq_handler,
+				       0, pdev->name, jpeg);
+		if (ret) {
+			dev_err(&pdev->dev, "Failed to request jpeg_irq %d (%d)\n",
+				jpeg_irq, ret);
+			goto err_req_irq;
+		}
 
-	ret = mtk_jpeg_clk_init(jpeg);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to init clk, err %d\n", ret);
-		goto err_clk_init;
+		ret = mtk_jpeg_clk_init(jpeg);
+		if (ret) {
+			dev_err(&pdev->dev, "Failed to init clk\n");
+			goto err_clk_init;
+		}
+	} else {
+		init_waitqueue_head(&jpeg->hw_wq);
+
+		jpeg->workqueue = alloc_ordered_workqueue(MTK_JPEG_NAME,
+							  WQ_MEM_RECLAIM |
+							  WQ_FREEZABLE);
+		if (!jpeg->workqueue) {
+			dev_err(&pdev->dev, "Failed to create jpeg workqueue!\n");
+			ret = -EINVAL;
+			goto err_alloc_workqueue;
+		}
 	}
 
 	ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
@@ -1390,7 +1656,6 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
 	}
 
 	jpeg->m2m_dev = v4l2_m2m_init(jpeg->variant->m2m_ops);
-
 	if (IS_ERR(jpeg->m2m_dev)) {
 		v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
 		ret = PTR_ERR(jpeg->m2m_dev);
@@ -1422,13 +1687,26 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
 
 	video_set_drvdata(jpeg->vdev, jpeg);
 	v4l2_info(&jpeg->v4l2_dev,
-		  "%s device registered as /dev/video%d (%d,%d)\n",
-		  jpeg->variant->dev_name, jpeg->vdev->num,
-		  VIDEO_MAJOR, jpeg->vdev->minor);
+			  "%s device registered as /dev/video%d (%d,%d)\n",
+			  jpeg->variant->dev_name, jpeg->vdev->num,
+			  VIDEO_MAJOR, jpeg->vdev->minor);
 
 	platform_set_drvdata(pdev, jpeg);
 
-	pm_runtime_enable(&pdev->dev);
+	if (jpeg->variant->is_encoder) {
+		match = mtk_jpegenc_match_add(jpeg);
+		if (IS_ERR_OR_NULL(match))
+			goto err_vfd_jpeg_register;
+
+		video_set_drvdata(jpeg->vdev, jpeg);
+		platform_set_drvdata(pdev, jpeg);
+		ret = component_master_add_with_match(&pdev->dev,
+						      &mtk_jpegenc_ops, match);
+		if (ret < 0)
+			goto err_vfd_jpeg_register;
+	} else {
+		pm_runtime_enable(&pdev->dev);
+	}
 
 	return 0;
 
@@ -1446,6 +1724,8 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
 
 err_clk_init:
 
+err_alloc_workqueue:
+
 err_req_irq:
 
 	return ret;
@@ -1461,6 +1741,8 @@ static int mtk_jpeg_remove(struct platform_device *pdev)
 	v4l2_m2m_release(jpeg->m2m_dev);
 	v4l2_device_unregister(&jpeg->v4l2_dev);
 	mtk_jpeg_clk_release(jpeg);
+	flush_workqueue(jpeg->workqueue);
+	destroy_workqueue(jpeg->workqueue);
 
 	return 0;
 }
@@ -1524,13 +1806,13 @@ static const struct mtk_jpeg_variant mt8173_jpeg_drvdata = {
 	.cap_q_default_fourcc = V4L2_PIX_FMT_YUV420M,
 };
 
-static const struct mtk_jpeg_variant mtk_jpeg_drvdata = {
+static const struct mtk_jpeg_variant mtk_jpegenc_drvdata = {
+	.is_encoder	= true,
 	.clks = mtk_jpeg_clocks,
 	.num_clks = ARRAY_SIZE(mtk_jpeg_clocks),
 	.formats = mtk_jpeg_enc_formats,
 	.num_formats = MTK_JPEG_ENC_NUM_FORMATS,
 	.qops = &mtk_jpeg_enc_qops,
-	.irq_handler = mtk_jpeg_enc_irq,
 	.hw_reset = mtk_jpeg_enc_reset,
 	.m2m_ops = &mtk_jpeg_enc_m2m_ops,
 	.dev_name = "mtk-jpeg-enc",
@@ -1540,6 +1822,9 @@ static const struct mtk_jpeg_variant mtk_jpeg_drvdata = {
 };
 
 static const struct of_device_id mtk_jpeg_match[] = {
+	{	.compatible = "mediatek,mt8195-jpgenc",
+		.data = &mtk_jpegenc_drvdata,
+	},
 	{
 		.compatible = "mediatek,mt8173-jpgdec",
 		.data = &mt8173_jpeg_drvdata,
@@ -1548,10 +1833,6 @@ static const struct of_device_id mtk_jpeg_match[] = {
 		.compatible = "mediatek,mt2701-jpgdec",
 		.data = &mt8173_jpeg_drvdata,
 	},
-	{
-		.compatible = "mediatek,mtk-jpgenc",
-		.data = &mtk_jpeg_drvdata,
-	},
 	{},
 };
 
@@ -1567,7 +1848,25 @@ static struct platform_driver mtk_jpeg_driver = {
 	},
 };
 
-module_platform_driver(mtk_jpeg_driver);
+static struct platform_driver * const mtk_jpeg_source_drivers[] = {
+	&mtk_jpegenc_hw_driver,
+	&mtk_jpeg_driver,
+};
+
+static int __init mtk_jpeg_init(void)
+{
+	return platform_register_drivers(mtk_jpeg_source_drivers,
+					 ARRAY_SIZE(mtk_jpeg_source_drivers));
+}
+
+static void __exit mtk_jpeg_exit(void)
+{
+	platform_unregister_drivers(mtk_jpeg_source_drivers,
+				    ARRAY_SIZE(mtk_jpeg_source_drivers));
+}
+
+module_init(mtk_jpeg_init);
+module_exit(mtk_jpeg_exit);
 
 MODULE_DESCRIPTION("MediaTek JPEG codec driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
index 595f7f1..d4259f9 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
@@ -60,6 +60,7 @@ enum mtk_jpeg_ctx_state {
  * @cap_q_default_fourcc:	capture queue default fourcc
  */
 struct mtk_jpeg_variant {
+	bool is_encoder;
 	struct clk_bulk_data *clks;
 	int num_clks;
 	struct mtk_jpeg_fmt *formats;
@@ -74,6 +75,52 @@ struct mtk_jpeg_variant {
 	u32 cap_q_default_fourcc;
 };
 
+struct mtk_jpeg_hw_param {
+	struct vb2_v4l2_buffer *src_buffer;
+	struct vb2_v4l2_buffer *dst_buffer;
+	struct mtk_jpeg_ctx *curr_ctx;
+};
+
+enum mtk_jpeg_hw_state {
+	MTK_JPEG_HW_IDLE = 0,
+	MTK_JPEG_HW_BUSY = 1,
+};
+
+enum mtk_jpegenc_hw_id {
+	MTK_JPEGENC_HW0,
+	MTK_JPEGENC_HW1,
+	MTK_JPEGENC_HW_MAX,
+};
+
+/** * enum mtk_hw_idx - MTK hw index */
+enum mtk_jpeghw_idx {
+	JPEGENC_HW0,
+	JPEGENC_HW1,
+	JPEGDEC_HW0,
+	JPEGDEC_HW1,
+	JPEGDEC_HW2,
+	NUM_MAX_JPEG_HW,
+};
+
+/** * struct mtk_jpegenc_clk_info - Structure used to store clock name */
+struct mtk_jpegenc_clk_info {
+	const char	*clk_name;
+	struct clk	*jpegenc_clk;
+};
+
+/* struct mtk_vcodec_clk - Structure used to store vcodec clock information */
+struct mtk_jpegenc_clk {
+	struct mtk_jpegenc_clk_info	*clk_info;
+	int	clk_num;
+};
+
+/** * struct mtk_vcodec_pm - Power management data structure */
+struct mtk_jpegenc_pm {
+	struct mtk_jpegenc_clk	venc_clk;
+	struct device	*dev;
+	struct mtk_jpeg_dev	*mtkdev;
+};
+
 /**
  * struct mtk_jpeg_dev - JPEG IP abstraction
  * @lock:		the mutex protecting this structure
@@ -88,6 +135,8 @@ struct mtk_jpeg_variant {
  * @larb:		SMI device
  * @job_timeout_work:	IRQ timeout structure
  * @variant:		driver variant to be used
+ * @irqlock:		spinlock protecting for irq
+ * @dev_mutex:		the mutex protecting for device
  */
 struct mtk_jpeg_dev {
 	struct mutex		lock;
@@ -98,12 +147,29 @@ struct mtk_jpeg_dev {
 	struct v4l2_m2m_dev	*m2m_dev;
 	void			*alloc_ctx;
 	struct video_device	*vdev;
-	void __iomem		*reg_base;
 	struct device		*larb;
-	struct delayed_work job_timeout_work;
 	const struct mtk_jpeg_variant *variant;
+
+	struct clk		*clk_jpeg;
+	struct delayed_work job_timeout_work;
+	struct platform_device *plat_dev;
+	spinlock_t irqlock;	/* spinlock protecting for irq */
+	struct mutex dev_mutex;	/* the mutex protecting for device */
+	void __iomem *reg_base[NUM_MAX_JPEG_HW];
+	int jpegenc_irq;
+	struct mtk_jpeg_dev *hw_dev[NUM_MAX_JPEG_HW];
+	struct device_node *component_node[NUM_MAX_JPEG_HW];
+	int comp_idx;
+	struct mtk_jpegenc_pm pm;
+	struct mtk_jpeg_ctx *curr_ctx;
+	enum mtk_jpeg_hw_state hw_state;
+	struct mtk_jpeg_hw_param hw_param;
+	wait_queue_head_t hw_wq;
+	atomic_t hw_rdy;
 };
 
+extern struct platform_driver mtk_jpegenc_hw_driver;
+
 /**
  * struct mtk_jpeg_fmt - driver's internal color format data
  * @fourcc:	the fourcc code, 0 if not applicable
@@ -149,6 +215,7 @@ struct mtk_jpeg_q_data {
  * @enc_quality:	jpeg encoder quality
  * @restart_interval:	jpeg encoder restart interval
  * @ctrl_hdl:		controls handler
+ * @done_queue_lock:	spinlock protecting for buffer done queue
  */
 struct mtk_jpeg_ctx {
 	struct mtk_jpeg_dev		*jpeg;
@@ -160,6 +227,15 @@ struct mtk_jpeg_ctx {
 	u8 enc_quality;
 	u8 restart_interval;
 	struct v4l2_ctrl_handler ctrl_hdl;
+
+	struct list_head dst_done_queue;
+	spinlock_t done_queue_lock;	/* spinlock protecting done queue */
+	u32 total_frame_num;
+	u32 last_done_frame_num;
+	struct work_struct jpeg_work;
 };
 
+void mtk_jpegenc_timeout_work(struct work_struct *work);
+irqreturn_t mtk_jpegenc_hw_irq_handler(int irq, void *priv);
+
 #endif /* _MTK_JPEG_CORE_H */
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c
index 1cf037b..d44101e 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c
@@ -9,8 +9,20 @@
 #include <linux/kernel.h>
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-contig.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/component.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
 
 #include "mtk_jpeg_enc_hw.h"
+#include "mtk_jpeg_core.h"
+
 
 static const struct mtk_jpeg_enc_qlt mtk_jpeg_enc_quality[] = {
 	{.quality_param = 34, .hardware_value = JPEG_ENC_QUALITY_Q34},
@@ -30,6 +42,99 @@ static const struct mtk_jpeg_enc_qlt mtk_jpeg_enc_quality[] = {
 	{.quality_param = 97, .hardware_value = JPEG_ENC_QUALITY_Q97},
 };
 
+typedef irqreturn_t (*jpegenc_irq_handler)(int irq, void *priv);
+
+static int mtk_jpegenc_hw_bind(struct device *dev,
+			       struct device *master, void *data)
+{
+	struct mtk_jpeg_dev *comp_priv = dev_get_drvdata(dev);
+	struct mtk_jpeg_dev *master_priv = data;
+	int i;
+
+	for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) {
+		if (dev->of_node != master_priv->component_node[i])
+			continue;
+		master_priv->hw_dev[i] = comp_priv;
+		comp_priv->comp_idx = i;
+		master_priv->reg_base[i] = comp_priv->reg_base[MTK_JPEGENC_HW0];
+		break;
+	}
+	if (i == MTK_JPEGENC_HW_MAX) {
+		dev_err(dev, "Failed to get component node\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void mtk_jpegenc_hw_unbind(struct device *dev,
+				  struct device *master, void *data)
+{
+	struct mtk_jpeg_dev *comp_priv = dev_get_drvdata(dev);
+
+	comp_priv->reg_base[MTK_JPEGENC_HW0] = 0;
+}
+
+static const struct component_ops mtk_jpegenc_hw_component_ops = {
+	.bind = mtk_jpegenc_hw_bind,
+	.unbind = mtk_jpegenc_hw_unbind,
+};
+
+int mtk_jpegenc_init_pm(struct mtk_jpeg_dev *mtkdev)
+{
+	struct platform_device *pdev;
+	struct mtk_jpegenc_pm *pm;
+	struct mtk_jpegenc_clk *jpegenc_clk;
+	struct mtk_jpegenc_clk_info *clk_info;
+	int i = 0, ret = 0;
+
+	pdev = mtkdev->plat_dev;
+	pm = &mtkdev->pm;
+	pm->mtkdev = mtkdev;
+
+	jpegenc_clk = &pm->venc_clk;
+	pm->dev = &pdev->dev;
+	jpegenc_clk->clk_num =
+		of_property_count_strings(pdev->dev.of_node, "clock-names");
+	if (jpegenc_clk->clk_num > 0) {
+		jpegenc_clk->clk_info = devm_kcalloc(&pdev->dev,
+						     jpegenc_clk->clk_num,
+						     sizeof(*clk_info),
+						     GFP_KERNEL);
+		if (!jpegenc_clk->clk_info)
+			return -ENOMEM;
+	} else {
+		pr_err("Failed to get jpegenc clock count\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < jpegenc_clk->clk_num; i++) {
+		clk_info = &jpegenc_clk->clk_info[i];
+		ret = of_property_read_string_index(pdev->dev.of_node,
+						    "clock-names", i,
+						    &clk_info->clk_name);
+		if (ret) {
+			pr_err("Failed to get jpegenc clock name id = %d", i);
+			return ret;
+		}
+
+		clk_info->jpegenc_clk = devm_clk_get(&pdev->dev,
+						     clk_info->clk_name);
+		if (IS_ERR(clk_info->jpegenc_clk)) {
+			pr_err("devm_clk_get (%d)%s fail",
+			       i, clk_info->clk_name);
+			return PTR_ERR(clk_info->jpegenc_clk);
+		}
+	}
+
+	pm_runtime_enable(&pdev->dev);
+	return ret;
+}
+
+void mtk_jpegenc_release_pm(struct mtk_jpeg_dev *dev)
+{
+	pm_runtime_disable(dev->pm.dev);
+}
+
 void mtk_jpeg_enc_reset(void __iomem *base)
 {
 	writel(0, base + JPEG_ENC_RSTB);
@@ -152,3 +257,107 @@ void mtk_jpeg_set_enc_params(struct mtk_jpeg_ctx *ctx,  void __iomem *base)
 
 	writel(ctx->restart_interval, base + JPEG_ENC_RST_MCU_NUM);
 }
+
+static int mtk_jpegenc_hw_init_irq(struct mtk_jpeg_dev *dev,
+				   jpegenc_irq_handler irq_handler)
+{
+	struct platform_device *pdev = dev->plat_dev;
+	int ret;
+
+	dev->jpegenc_irq = platform_get_irq(pdev, 0);
+	if (dev->jpegenc_irq < 0) {
+		dev_err(&pdev->dev, "Failed to get irq resource");
+		return dev->jpegenc_irq;
+	}
+
+	ret = devm_request_irq(&pdev->dev, dev->jpegenc_irq,
+			       irq_handler, 0, pdev->name, dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to install dev->jpegenc_irq %d (%d)",
+			dev->jpegenc_irq, ret);
+
+		return -ENOENT;
+	}
+
+	//disable_irq(dev->jpegenc_irq);
+	return 0;
+}
+
+static int mtk_jpegenc_hw_probe(struct platform_device *pdev)
+{
+	struct mtk_jpeg_dev *dev;
+	jpegenc_irq_handler irq_handler;
+	int ret;
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+	dev->plat_dev = pdev;
+	spin_lock_init(&dev->irqlock);
+	mutex_init(&dev->dev_mutex);
+	atomic_set(&dev->hw_rdy, 1U);
+	spin_lock_init(&dev->hw_lock);
+
+	dev->hw_state = MTK_JPEG_HW_IDLE;
+	INIT_DELAYED_WORK(&dev->job_timeout_work, mtk_jpegenc_timeout_work);
+
+	ret = mtk_jpegenc_init_pm(dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to get jpeg enc clock source");
+		return ret;
+	}
+
+	dev->reg_base[MTK_JPEGENC_HW0] =
+		devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR((__force void *)dev->reg_base[MTK_JPEGENC_HW0])) {
+		ret = PTR_ERR((__force void *)dev->reg_base[MTK_JPEGENC_HW0]);
+		goto err;
+	}
+
+	irq_handler = of_device_get_match_data(&pdev->dev);
+	if (!irq_handler) {
+		dev_err(&pdev->dev, "Failed to get match data.\n");
+		goto err;
+	}
+
+	ret = mtk_jpegenc_hw_init_irq(dev, irq_handler);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register JPEGENC irq handler.\n");
+		goto err;
+	}
+
+	platform_set_drvdata(pdev, dev);
+
+	ret = component_add(&pdev->dev, &mtk_jpegenc_hw_component_ops);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to component_add: %d\n", ret);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	mtk_jpegenc_release_pm(dev);
+	return ret;
+}
+
+static const struct of_device_id mtk_jpegenc_hw_ids[] = {
+	{
+		.compatible = "mediatek,mt8195-jpgenc0",
+		.data = mtk_jpegenc_hw_irq_handler,
+	},
+	{	.compatible = "mediatek,mt8195-jpgenc1",
+		.data = mtk_jpegenc_hw_irq_handler,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_jpegenc_hw_ids);
+
+struct platform_driver mtk_jpegenc_hw_driver = {
+	.probe	= mtk_jpegenc_hw_probe,
+	.driver	= {
+		.name	= "mtk-jpegenc-hw",
+		.of_match_table = mtk_jpegenc_hw_ids,
+	},
+};
+
-- 
2.6.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] media: mtk-jpegenc: design SW algorithm for using multi-HW of jpegenc
  2021-06-23  6:05 [PATCH 0/3] Support jpeg encode for MT8195 kyrie.wu
  2021-06-23  6:05 ` [PATCH 1/3] dt-bindings: mtk-jpeg: Add binding for MT8195 JPG kyrie.wu
  2021-06-23  6:05 ` [PATCH 2/3] media: mtk-jpegenc: use component framework to manage jpg HW kyrie.wu
@ 2021-06-23  6:05 ` kyrie.wu
  2 siblings, 0 replies; 10+ messages in thread
From: kyrie.wu @ 2021-06-23  6:05 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Rick Chang,
	Bin Liu, Matthias Brugger, Tzung-Bi Shih
  Cc: Project_Global_Chrome_Upstream_Group, linux-media, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek, Tomasz Figa,
	xia.jiang, maoguang.meng, srv_heupstream, kyrie.wu

the SW algorithm would meet the request of how to use
multi-HW at the same time;
For user process, it only needed to open one device node to use
multi-HW.

Signed-off-by: kyrie.wu <kyrie.wu@mediatek.com>
---
 drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c | 164 +++++++++++++++++++++---
 1 file changed, 147 insertions(+), 17 deletions(-)

diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index c84815a..b8d1303 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -944,38 +944,150 @@ static int mtk_jpeg_set_dec_dst(struct mtk_jpeg_ctx *ctx,
 	return 0;
 }
 
-static void mtk_jpeg_enc_device_run(void *priv)
+static int mtk_jpeg_select_hw(struct mtk_jpeg_ctx *ctx)
 {
-	struct mtk_jpeg_ctx *ctx = priv;
+	int hw_id = -1;
+	int i;
+	unsigned long flags;
+	struct mtk_jpeg_dev *jpeg = ctx->jpeg, *comp_jpeg = NULL;
+
+	spin_lock_irqsave(&jpeg->hw_lock, flags);
+	for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) {
+		comp_jpeg = jpeg->hw_dev[i];
+		if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) {
+			hw_id = i;
+			comp_jpeg->hw_state = MTK_JPEG_HW_BUSY;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&jpeg->hw_lock, flags);
+
+	return hw_id;
+}
+
+static int mtk_jpeg_deselect_hw(struct mtk_jpeg_dev *jpeg, int hw_id)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&jpeg->hw_lock, flags);
+	jpeg->hw_dev[hw_id]->hw_state = MTK_JPEG_HW_IDLE;
+	spin_unlock_irqrestore(&jpeg->hw_lock, flags);
+
+	return 0;
+}
+
+static int mtk_jpeg_set_hw_param(struct mtk_jpeg_ctx *ctx,
+				 int hw_id,
+				 struct vb2_v4l2_buffer *src_buf,
+				 struct vb2_v4l2_buffer *dst_buf)
+{
+	struct mtk_jpeg_dev *jpeg = ctx->jpeg->hw_dev[hw_id];
+
+	jpeg->hw_param.curr_ctx = ctx;
+	jpeg->hw_param.src_buffer = src_buf;
+	jpeg->hw_param.dst_buffer = dst_buf;
+
+	return 0;
+}
+
+static void mtk_jpegenc_worker(struct work_struct *work)
+{
+	struct mtk_jpeg_ctx *ctx = container_of(work, struct mtk_jpeg_ctx,
+		jpeg_work);
 	struct mtk_jpeg_dev *jpeg = ctx->jpeg;
+	struct mtk_jpeg_dev *comp_jpeg[MTK_JPEGENC_HW_MAX];
 	struct vb2_v4l2_buffer *src_buf, *dst_buf;
 	enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
 	unsigned long flags;
-	int ret;
+	struct mtk_jpeg_src_buf *jpeg_src_buf, *jpeg_dst_buf;
+	int ret, i, hw_id = 0;
+	atomic_t *hw_rdy[MTK_JPEGENC_HW_MAX];
+	struct clk *jpegenc_clk;
+
+	for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) {
+		comp_jpeg[i] = jpeg->hw_dev[i];
+		hw_rdy[i] = &comp_jpeg[i]->hw_rdy;
+	}
+
+retry_select:
+	hw_id = mtk_jpeg_select_hw(ctx);
+	if (hw_id < 0) {
+		//wait hw idle
+		ret = wait_event_interruptible(jpeg->hw_wq,
+					       (atomic_read(hw_rdy[0]) ||
+					       atomic_read(hw_rdy[1])) > 0);
+		if (ret != 0) {
+			pr_err("%s : %d, all HW are busy\n",
+			       __func__, __LINE__);
+			v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+			return;
+		}
+		pr_info("%s : %d, NEW HW IDLE, please retry selcet!!!\n",
+			__func__, __LINE__);
+		goto retry_select;
+	}
+	atomic_dec(&comp_jpeg[hw_id]->hw_rdy);
 
 	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+	if (!src_buf) {
+		pr_info("%s : %d, get src_buf fail !!!\n", __func__, __LINE__);
+		goto getbuf_fail;
+	}
+
 	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+	if (!dst_buf) {
+		pr_info("%s : %d, get dst_buf fail !!!\n", __func__, __LINE__);
+		goto getbuf_fail;
+	}
 
-	ret = pm_runtime_get_sync(jpeg->dev);
-	if (ret < 0)
+	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
+	jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf);
+
+	jpeg_src_buf->curr_ctx = ctx;
+	jpeg_src_buf->frame_num = ctx->total_frame_num;
+	jpeg_dst_buf->curr_ctx = ctx;
+	jpeg_dst_buf->frame_num = ctx->total_frame_num;
+	ctx->total_frame_num++;
+
+	v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+	mtk_jpeg_set_hw_param(ctx, hw_id, src_buf, dst_buf);
+
+	ret = pm_runtime_get_sync(comp_jpeg[hw_id]->pm.dev);
+	if (ret < 0) {
+		pr_err("%s : %d, pm_runtime_get_sync fail !!!\n",
+		       __func__, __LINE__);
 		goto enc_end;
+	}
 
-	schedule_delayed_work(&jpeg->job_timeout_work,
-			      msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
+	jpegenc_clk = comp_jpeg[hw_id]->pm.venc_clk.clk_info->jpegenc_clk;
+	ret = clk_prepare_enable(jpegenc_clk);
+	if (ret) {
+		pr_err("%s : %d, jpegenc clk_prepare_enable fail\n",
+		       __func__, __LINE__);
+		goto enc_end;
+	}
 
-	spin_lock_irqsave(&jpeg->hw_lock, flags);
+	schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work,
+			      msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
 
 	/*
 	 * Resetting the hardware every frame is to ensure that all the
 	 * registers are cleared. This is a hardware requirement.
 	 */
-	mtk_jpeg_enc_reset(jpeg->reg_base);
-
-	mtk_jpeg_set_enc_src(ctx, jpeg->reg_base, &src_buf->vb2_buf);
-	mtk_jpeg_set_enc_dst(ctx, jpeg->reg_base, &dst_buf->vb2_buf);
-	mtk_jpeg_set_enc_params(ctx, jpeg->reg_base);
-	mtk_jpeg_enc_start(jpeg->reg_base);
-	spin_unlock_irqrestore(&jpeg->hw_lock, flags);
+	spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags);
+	mtk_jpeg_enc_reset(comp_jpeg[hw_id]->reg_base[0]);
+	mtk_jpeg_set_enc_dst(ctx,
+			     comp_jpeg[hw_id]->reg_base[0],
+			     &dst_buf->vb2_buf);
+	mtk_jpeg_set_enc_src(ctx,
+			     comp_jpeg[hw_id]->reg_base[0],
+			     &src_buf->vb2_buf);
+	mtk_jpeg_set_enc_params(ctx, comp_jpeg[hw_id]->reg_base[0]);
+	mtk_jpeg_enc_start(comp_jpeg[hw_id]->reg_base[0]);
+	v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
+	spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags);
 	return;
 
 enc_end:
@@ -983,9 +1095,20 @@ static void mtk_jpeg_enc_device_run(void *priv)
 	v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 	v4l2_m2m_buf_done(src_buf, buf_state);
 	v4l2_m2m_buf_done(dst_buf, buf_state);
+getbuf_fail:
+	atomic_inc(&comp_jpeg[hw_id]->hw_rdy);
+	mtk_jpeg_deselect_hw(jpeg, hw_id);
 	v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
 }
 
+static void mtk_jpeg_enc_device_run(void *priv)
+{
+	struct mtk_jpeg_ctx *ctx = priv;
+	struct mtk_jpeg_dev *jpeg = ctx->jpeg;
+
+	queue_work(jpeg->workqueue, &ctx->jpeg_work);
+}
+
 static void mtk_jpeg_dec_device_run(void *priv)
 {
 	struct mtk_jpeg_ctx *ctx = priv;
@@ -1002,7 +1125,8 @@ static void mtk_jpeg_dec_device_run(void *priv)
 	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
 
-	if (mtk_jpeg_check_resolution_change(ctx, &jpeg_src_buf->dec_param)) {
+	if (mtk_jpeg_check_resolution_change(ctx,
+					     &jpeg_src_buf->dec_param)) {
 		mtk_jpeg_queue_src_chg_event(ctx);
 		ctx->state = MTK_JPEG_SOURCE_CHANGE;
 		v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
@@ -1017,7 +1141,8 @@ static void mtk_jpeg_dec_device_run(void *priv)
 			      msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
 
 	mtk_jpeg_set_dec_src(ctx, &src_buf->vb2_buf, &bs);
-	if (mtk_jpeg_set_dec_dst(ctx, &jpeg_src_buf->dec_param, &dst_buf->vb2_buf, &fb))
+	if (mtk_jpeg_set_dec_dst(ctx, &jpeg_src_buf->dec_param,
+				 &dst_buf->vb2_buf, &fb))
 		goto dec_end;
 
 	spin_lock_irqsave(&jpeg->hw_lock, flags);
@@ -1248,6 +1373,11 @@ static int mtk_jpeg_open(struct file *file)
 		goto free;
 	}
 
+	if (jpeg->variant->is_encoder) {
+		INIT_WORK(&ctx->jpeg_work, mtk_jpegenc_worker);
+		INIT_LIST_HEAD(&ctx->dst_done_queue);
+	}
+
 	v4l2_fh_init(&ctx->fh, vfd);
 	file->private_data = &ctx->fh;
 	v4l2_fh_add(&ctx->fh);
-- 
2.6.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] dt-bindings: mtk-jpeg: Add binding for MT8195 JPG
  2021-06-23  6:05 ` [PATCH 1/3] dt-bindings: mtk-jpeg: Add binding for MT8195 JPG kyrie.wu
@ 2021-06-25  9:18   ` Tzung-Bi Shih
  2021-06-30  7:55     ` kyrie.wu
  0 siblings, 1 reply; 10+ messages in thread
From: Tzung-Bi Shih @ 2021-06-25  9:18 UTC (permalink / raw)
  To: kyrie.wu
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Rick Chang,
	Bin Liu, Matthias Brugger, Tzung-Bi Shih,
	Project_Global_Chrome_Upstream_Group, linux-media, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek, Tomasz Figa,
	xia.jiang, maoguang.meng, srv_heupstream

On Wed, Jun 23, 2021 at 2:06 PM kyrie.wu <kyrie.wu@mediatek.com> wrote:
>  Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.txt | 3 +++
>  1 file changed, 3 insertions(+)
Note: the patch won't apply after [1].

[1]: https://lore.kernel.org/patchwork/patch/1445298/

>  Required properties:
>  - compatible : "mediatek,mt2701-jpgenc"
> +- compatible : "mediatek,mt8195-jpgenc"
> +- compatible : "mediatek,mt8195-jpgenc0"
> +- compatible : "mediatek,mt8195-jpgenc1"
Why it needs 3 compatible strings?

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] media: mtk-jpegenc: use component framework to manage jpg HW
  2021-06-23  6:05 ` [PATCH 2/3] media: mtk-jpegenc: use component framework to manage jpg HW kyrie.wu
@ 2021-06-25  9:18   ` Tzung-Bi Shih
  2021-06-29  7:33   ` Dafna Hirschfeld
  1 sibling, 0 replies; 10+ messages in thread
From: Tzung-Bi Shih @ 2021-06-25  9:18 UTC (permalink / raw)
  To: kyrie.wu
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Rick Chang,
	Bin Liu, Matthias Brugger, Tzung-Bi Shih,
	Project_Global_Chrome_Upstream_Group, linux-media, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek, Tomasz Figa,
	xia.jiang, maoguang.meng, srv_heupstream

On Wed, Jun 23, 2021 at 2:06 PM kyrie.wu <kyrie.wu@mediatek.com> wrote:
> Mtk jpeg encoder has several hardware, one HW may register a device
> node; use component framework to manage jpg HW device node,
> in this case, one device node could represent all jpg HW.
Can roughly understand.  But could you rephrase your sentences?

>  #include <media/videobuf2-core.h>
>  #include <media/videobuf2-dma-contig.h>
>  #include <soc/mediatek/smi.h>
> +#include <linux/component.h>
Maintain the alphabetical order.

> +void mtk_jpeg_put_buf(struct mtk_jpeg_dev *jpeg)
> +{
> +       struct mtk_jpeg_ctx *ctx = NULL;
> +       struct vb2_v4l2_buffer *dst_buffer = NULL;
> +       struct list_head *temp_entry = NULL;
> +       struct list_head *pos = NULL;
> +       struct mtk_jpeg_src_buf *dst_done_buf = NULL, *tmp_dst_done_buf = NULL;
Remove the initialization if they don't need to.

> +       unsigned long flags;
> +
> +       ctx = jpeg->hw_param.curr_ctx;
> +       if (!ctx) {
> +               pr_err("%s : %d, comp_jpeg ctx fail !!!\n", __func__, __LINE__);
Use dev_err().

> +               return;
> +       }
> +
> +       dst_buffer = jpeg->hw_param.dst_buffer;
> +       if (!dst_buffer) {
> +               pr_err("%s : %d, comp_jpeg dst_buffer fail !!!\n",
> +                      __func__, __LINE__);
Use dev_err().

> +       if (!(irq_status & JPEG_ENC_INT_STATUS_DONE)) {
> +               pr_err("%s : %d, jpeg encode failed\n", __func__, __LINE__);
Use dev_err().

> +void mtk_jpegenc_timeout_work(struct work_struct *work)
> +{
> +       struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev,
> +               job_timeout_work.work);
> +       struct mtk_jpeg_ctx *ctx = NULL;
It doesn't need to initialize.

> +static  const struct of_device_id mtk_jpegenc_drv_ids[] = {
Remove the extra space between "static" and "const".

> +       {
> +               .compatible = "mediatek,mt8195-jpgenc0",
> +               .data = (void *)MTK_JPEGENC_HW0,
> +       },
> +       {
> +               .compatible = "mediatek,mt8195-jpgenc1",
> +               .data = (void *)MTK_JPEGENC_HW1,
> +       },
Using compatible strings to separate them doesn't sound like a scalable method.

>  #include <linux/kernel.h>
>  #include <media/videobuf2-core.h>
>  #include <media/videobuf2-dma-contig.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/component.h>
> +#include <linux/clk.h>
> +#include <linux/pm_runtime.h>
Maintain the alphabetical order.

>  #include "mtk_jpeg_enc_hw.h"
> +#include "mtk_jpeg_core.h"
Maintain the alphabetical order.

> +int mtk_jpegenc_init_pm(struct mtk_jpeg_dev *mtkdev)
> +{
> +       struct platform_device *pdev;
> +       struct mtk_jpegenc_pm *pm;
> +       struct mtk_jpegenc_clk *jpegenc_clk;
> +       struct mtk_jpegenc_clk_info *clk_info;
> +       int i = 0, ret = 0;
They don't need to initialize.

> +       pdev = mtkdev->plat_dev;
> +       pm = &mtkdev->pm;
To be concise, can inline to above when declaring the variables.

> +       jpegenc_clk->clk_num =
> +               of_property_count_strings(pdev->dev.of_node, "clock-names");
> +       if (jpegenc_clk->clk_num > 0) {
> +               jpegenc_clk->clk_info = devm_kcalloc(&pdev->dev,
> +                                                    jpegenc_clk->clk_num,
> +                                                    sizeof(*clk_info),
> +                                                    GFP_KERNEL);
> +               if (!jpegenc_clk->clk_info)
> +                       return -ENOMEM;
> +       } else {
> +               pr_err("Failed to get jpegenc clock count\n");
Use dev_err().
> +               return -EINVAL;
> +       }
Would prefer the block turn to be:

if (... <= 0) {
    ...
    return -EINVAL;
}

... = devm_kcalloc(...);
if (!...)
    return -ENOMEM;

> +       for (i = 0; i < jpegenc_clk->clk_num; i++) {
> +               clk_info = &jpegenc_clk->clk_info[i];
> +               ret = of_property_read_string_index(pdev->dev.of_node,
> +                                                   "clock-names", i,
> +                                                   &clk_info->clk_name);
> +               if (ret) {
> +                       pr_err("Failed to get jpegenc clock name id = %d", i);
Use dev_err().

> +                       return ret;
> +               }
> +
> +               clk_info->jpegenc_clk = devm_clk_get(&pdev->dev,
> +                                                    clk_info->clk_name);
> +               if (IS_ERR(clk_info->jpegenc_clk)) {
> +                       pr_err("devm_clk_get (%d)%s fail",
> +                              i, clk_info->clk_name);
Use dev_err().

> +       pm_runtime_enable(&pdev->dev);
> +       return ret;
return 0;

> +void mtk_jpegenc_release_pm(struct mtk_jpeg_dev *dev)
> +{
> +       pm_runtime_disable(dev->pm.dev);
> +}
Would prefer this function to be more "symmetric" to mtk_jpegenc_init_pm().

For example:

void mtk_jpegenc_release_pm(struct mtk_jpeg_dev *mtkdev)
{
    struct platform_device *pdev = mtkdev->plat_dev;
    pm_runtime_disable(&pdev->dev);
}

That way, it doesn't rely on whether mtkdev->pm is set or not.

> +       ret = devm_request_irq(&pdev->dev, dev->jpegenc_irq,
> +                              irq_handler, 0, pdev->name, dev);
> +       if (ret) {
> +               dev_err(&pdev->dev, "Failed to install dev->jpegenc_irq %d (%d)",
> +                       dev->jpegenc_irq, ret);
> +
> +               return -ENOENT;
How about just returning ret?

> +       }
> +
> +       //disable_irq(dev->jpegenc_irq);
Remove it.

> +       ret = component_add(&pdev->dev, &mtk_jpegenc_hw_component_ops);
> +       if (ret) {
> +               dev_err(&pdev->dev, "Failed to component_add: %d\n", ret);
> +               goto err;
> +       }
How about just returning component_add(...)?

> +err:
> +       mtk_jpegenc_release_pm(dev);
Would expect the platform driver to have a .remove() callback and
invoke the mtk_jpegenc_release_pm() too.

> +static const struct of_device_id mtk_jpegenc_hw_ids[] = {
> +       {
> +               .compatible = "mediatek,mt8195-jpgenc0",
> +               .data = mtk_jpegenc_hw_irq_handler,
> +       },
> +       {       .compatible = "mediatek,mt8195-jpgenc1",
> +               .data = mtk_jpegenc_hw_irq_handler,
> +       },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, mtk_jpegenc_hw_ids);
Had the same concern in dt-bindings patch.  Does it really need
multiple compatible strings to separate?

Also, the block should guard by using CONFIG_OF.

> +struct platform_driver mtk_jpegenc_hw_driver = {
> +       .probe  = mtk_jpegenc_hw_probe,
> +       .driver = {
> +               .name   = "mtk-jpegenc-hw",
> +               .of_match_table = mtk_jpegenc_hw_ids,
Should guard by using of_match_ptr().


Hi, after reading the patch for a while, I realized it is way too big
to me so that I didn't go through too much detail (especially the
component framework part).  Could you further divide the series into
smaller pieces?  For example:
- part i. refactor to make modifying code easier
- part ii. leverage component framework
- part iii. add new code for MT8195
I would expect part i and ii don't change the original behavior.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] media: mtk-jpegenc: use component framework to manage jpg HW
  2021-06-23  6:05 ` [PATCH 2/3] media: mtk-jpegenc: use component framework to manage jpg HW kyrie.wu
  2021-06-25  9:18   ` Tzung-Bi Shih
@ 2021-06-29  7:33   ` Dafna Hirschfeld
  1 sibling, 0 replies; 10+ messages in thread
From: Dafna Hirschfeld @ 2021-06-29  7:33 UTC (permalink / raw)
  To: kyrie.wu, Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Rick Chang, Bin Liu, Matthias Brugger, Tzung-Bi Shih
  Cc: Project_Global_Chrome_Upstream_Group, linux-media, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek, Tomasz Figa,
	xia.jiang, maoguang.meng, srv_heupstream

Hi  kyrie.wu,
It seems that this patch is not rebased on top of media_tree repo. So it will be difficutl to apply.
Also, I sent a bug fix a while ago '[PATCH] media: mtk-jpeg: fix setting plane paylod'
Could you please review it?

Thanks,
Dafna


On 23.06.21 09:05, kyrie.wu wrote:
> Mtk jpeg encoder has several hardware, one HW may register a device
> node; use component framework to manage jpg HW device node,
> in this case, one device node could represent all jpg HW.
> 
> Signed-off-by: kyrie.wu <kyrie.wu@mediatek.com>
> ---
>   drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c   | 467 ++++++++++++++++++----
>   drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h   |  80 +++-
>   drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c | 209 ++++++++++
>   3 files changed, 670 insertions(+), 86 deletions(-)
> 
> diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
> index 88a23bc..c84815a 100644
> --- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
> +++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
> @@ -23,6 +23,7 @@
>   #include <media/videobuf2-core.h>
>   #include <media/videobuf2-dma-contig.h>
>   #include <soc/mediatek/smi.h>
> +#include <linux/component.h>
>   
>   #include "mtk_jpeg_enc_hw.h"
>   #include "mtk_jpeg_dec_hw.h"
> @@ -106,10 +107,45 @@ static struct mtk_jpeg_fmt mtk_jpeg_dec_formats[] = {
>   #define MTK_JPEG_ENC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_enc_formats)
>   #define MTK_JPEG_DEC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_dec_formats)
>   
> +/*
> + * mtk_jpeg_enc_param:  General jpeg encoding parameters
> + * @enc_w:		image width
> + * @enc_h:		image height
> + * @enable_exif:	EXIF enable for jpeg encode mode
> + * @enc_quality:	destination image quality in encode mode
> + * @enc_format:		input image format
> + * @restart_interval:	JPEG restart interval for JPEG encoding
> + * @img_stride:		jpeg encoder image stride
> + * @mem_stride:		jpeg encoder memory stride
> + * @total_encdu:	total 8x8 block number
> + */
> +struct mtk_jpeg_enc_param {
> +	u32 enc_w;
> +	u32 enc_h;
> +	u32 enable_exif;
> +	u32 enc_quality;
> +	u32 enc_format;
> +	u32 restart_interval;
> +	u32 img_stride;
> +	u32 mem_stride;
> +	u32 total_encdu;
> +};
> +
>   struct mtk_jpeg_src_buf {
>   	struct vb2_v4l2_buffer b;
>   	struct list_head list;
> +	u32 frame_num;
> +	u32 bs_size;
> +	int flags;
>   	struct mtk_jpeg_dec_param dec_param;
> +
> +	struct mtk_jpeg_enc_param enc_param;
> +	struct mtk_jpeg_ctx *curr_ctx;
> +};
> +
> +enum {
> +	MTK_JPEG_BUF_FLAGS_INIT	= 0,
> +	MTK_JPEG_BUF_FLAGS_LAST_FRAME = 1,
>   };
>   
>   static int debug;
> @@ -1053,8 +1089,32 @@ static int mtk_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,
>   
>   static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg)
>   {
> -	int ret;
> -
> +	struct mtk_jpeg_dev *comp_dev;
> +	struct mtk_jpegenc_pm *pm;
> +	struct mtk_jpegenc_clk *jpegclk;
> +	struct mtk_jpegenc_clk_info *clk_info;
> +	int ret, i;
> +
> +	if (jpeg->variant->is_encoder) {
> +		for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) {
> +			comp_dev = jpeg->hw_dev[i];
> +			if (!comp_dev) {
> +				pr_err("Failed to get hw dev\n");
> +				return;
> +			}
> +
> +			pm = &comp_dev->pm;
> +			jpegclk = &pm->venc_clk;
> +			clk_info = jpegclk->clk_info;
> +			ret = clk_prepare_enable(clk_info->jpegenc_clk);
> +			if (ret) {
> +				pr_err("jpegenc clk_prepare_enable %d %s fail\n",
> +				       i, jpegclk->clk_info->clk_name);
> +				return;
> +			}
> +		}
> +		return;
> +	}
>   	ret = mtk_smi_larb_get(jpeg->larb);
>   	if (ret)
>   		dev_err(jpeg->dev, "mtk_smi_larb_get larbvdec fail %d\n", ret);
> @@ -1067,59 +1127,30 @@ static void mtk_jpeg_clk_on(struct mtk_jpeg_dev *jpeg)
>   
>   static void mtk_jpeg_clk_off(struct mtk_jpeg_dev *jpeg)
>   {
> +	struct mtk_jpeg_dev *comp_dev;
> +	struct mtk_jpegenc_pm *pm;
> +	struct mtk_jpegenc_clk *jpegclk;
> +	int i;
> +
> +	if (jpeg->variant->is_encoder) {
> +		for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) {
> +			comp_dev = jpeg->hw_dev[i];
> +			if (!comp_dev) {
> +				pr_err("Failed to get hw dev\n");
> +				return;
> +			}
> +
> +			pm = &comp_dev->pm;
> +			jpegclk = &pm->venc_clk;
> +			clk_disable_unprepare(jpegclk->clk_info->jpegenc_clk);
> +		}
> +		return;
> +	}
>   	clk_bulk_disable_unprepare(jpeg->variant->num_clks,
>   				   jpeg->variant->clks);
>   	mtk_smi_larb_put(jpeg->larb);
>   }
>   
> -static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg)
> -{
> -	struct mtk_jpeg_ctx *ctx;
> -	struct vb2_v4l2_buffer *src_buf, *dst_buf;
> -	enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
> -	u32 result_size;
> -
> -	ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
> -	if (!ctx) {
> -		v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n");
> -		return IRQ_HANDLED;
> -	}
> -
> -	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
> -	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
> -
> -	result_size = mtk_jpeg_enc_get_file_size(jpeg->reg_base);
> -	vb2_set_plane_payload(&dst_buf->vb2_buf, 0, result_size);
> -
> -	buf_state = VB2_BUF_STATE_DONE;
> -
> -	v4l2_m2m_buf_done(src_buf, buf_state);
> -	v4l2_m2m_buf_done(dst_buf, buf_state);
> -	v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
> -	pm_runtime_put(ctx->jpeg->dev);
> -	return IRQ_HANDLED;
> -}
> -
> -static irqreturn_t mtk_jpeg_enc_irq(int irq, void *priv)
> -{
> -	struct mtk_jpeg_dev *jpeg = priv;
> -	u32 irq_status;
> -	irqreturn_t ret = IRQ_NONE;
> -
> -	cancel_delayed_work(&jpeg->job_timeout_work);
> -
> -	irq_status = readl(jpeg->reg_base + JPEG_ENC_INT_STS) &
> -		     JPEG_ENC_INT_STATUS_MASK_ALLIRQ;
> -	if (irq_status)
> -		writel(0, jpeg->reg_base + JPEG_ENC_INT_STS);
> -
> -	if (!(irq_status & JPEG_ENC_INT_STATUS_DONE))
> -		return ret;
> -
> -	ret = mtk_jpeg_enc_done(jpeg);
> -	return ret;
> -}
> -
>   static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv)
>   {
>   	struct mtk_jpeg_dev *jpeg = priv;
> @@ -1313,6 +1344,138 @@ static int mtk_jpeg_clk_init(struct mtk_jpeg_dev *jpeg)
>   	return 0;
>   }
>   
> +void mtk_jpeg_put_buf(struct mtk_jpeg_dev *jpeg)
> +{
> +	struct mtk_jpeg_ctx *ctx = NULL;
> +	struct vb2_v4l2_buffer *dst_buffer = NULL;
> +	struct list_head *temp_entry = NULL;
> +	struct list_head *pos = NULL;
> +	struct mtk_jpeg_src_buf *dst_done_buf = NULL, *tmp_dst_done_buf = NULL;
> +	unsigned long flags;
> +
> +	ctx = jpeg->hw_param.curr_ctx;
> +	if (!ctx) {
> +		pr_err("%s : %d, comp_jpeg ctx fail !!!\n", __func__, __LINE__);
> +		return;
> +	}
> +
> +	dst_buffer = jpeg->hw_param.dst_buffer;
> +	if (!dst_buffer) {
> +		pr_err("%s : %d, comp_jpeg dst_buffer fail !!!\n",
> +		       __func__, __LINE__);
> +		return;
> +	}
> +
> +	dst_done_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buffer->vb2_buf);
> +
> +	spin_lock_irqsave(&ctx->done_queue_lock, flags);
> +	list_add_tail(&dst_done_buf->list, &ctx->dst_done_queue);
> +	while (!list_empty(&ctx->dst_done_queue) &&
> +	       (pos != &ctx->dst_done_queue)) {
> +		list_for_each_prev_safe(pos, temp_entry,
> +					(&ctx->dst_done_queue)) {
> +			tmp_dst_done_buf = list_entry(pos,
> +						      struct mtk_jpeg_src_buf,
> +						      list);
> +			if (tmp_dst_done_buf->frame_num ==
> +				ctx->last_done_frame_num) {
> +				list_del(&tmp_dst_done_buf->list);
> +				v4l2_m2m_buf_done(&tmp_dst_done_buf->b,
> +						  VB2_BUF_STATE_DONE);
> +				ctx->last_done_frame_num++;
> +			}
> +		}
> +	}
> +	spin_unlock_irqrestore(&ctx->done_queue_lock, flags);
> +}
> +
> +irqreturn_t mtk_jpegenc_hw_irq_handler(int irq, void *priv)
> +{
> +	struct mtk_jpeg_dev *jpeg = priv;
> +	struct mtk_jpeg_ctx *ctx;
> +	struct mtk_jpeg_dev *master_jpeg;
> +	struct vb2_v4l2_buffer *src_buf, *dst_buf;
> +	struct mtk_jpeg_src_buf *jpeg_dst_buf;
> +
> +	enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
> +	u32 result_size;
> +	u32 irq_status;
> +
> +	cancel_delayed_work(&jpeg->job_timeout_work);
> +
> +	src_buf = jpeg->hw_param.src_buffer;
> +	dst_buf = jpeg->hw_param.dst_buffer;
> +	ctx = jpeg->hw_param.curr_ctx;
> +	master_jpeg = ctx->jpeg;
> +	jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf);
> +	irq_status = readl(jpeg->reg_base[MTK_JPEGENC_HW0] + JPEG_ENC_INT_STS) &
> +		JPEG_ENC_INT_STATUS_MASK_ALLIRQ;
> +	if (irq_status)
> +		writel(0, jpeg->reg_base[MTK_JPEGENC_HW0] + JPEG_ENC_INT_STS);
> +	if (!(irq_status & JPEG_ENC_INT_STATUS_DONE)) {
> +		pr_err("%s : %d, jpeg encode failed\n", __func__, __LINE__);
> +		goto irq_end;
> +	}
> +
> +	result_size = mtk_jpeg_enc_get_file_size(jpeg->reg_base[0]);
> +	vb2_set_plane_payload(&dst_buf->vb2_buf, 0, result_size);
> +
> +	buf_state = VB2_BUF_STATE_DONE;
> +
> +irq_end:
> +	v4l2_m2m_buf_done(src_buf, buf_state);
> +	mtk_jpeg_put_buf(jpeg);
> +	pm_runtime_put(jpeg->pm.dev);
> +	clk_disable_unprepare(jpeg->pm.venc_clk.clk_info->jpegenc_clk);
> +	if (ctx->fh.m2m_ctx &&
> +	    (!list_empty(&ctx->fh.m2m_ctx->out_q_ctx.rdy_queue) ||
> +	    !list_empty(&ctx->fh.m2m_ctx->cap_q_ctx.rdy_queue))) {
> +		queue_work(master_jpeg->workqueue, &ctx->jpeg_work);
> +	}
> +
> +	jpeg->hw_state = MTK_JPEG_HW_IDLE;
> +	wake_up(&master_jpeg->hw_wq);
> +	atomic_inc(&jpeg->hw_rdy);
> +	return IRQ_HANDLED;
> +}
> +
> +void mtk_jpegenc_timeout_work(struct work_struct *work)
> +{
> +	struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev,
> +		job_timeout_work.work);
> +	struct mtk_jpeg_ctx *ctx = NULL;
> +	struct mtk_jpeg_dev *master_jpeg;
> +	struct vb2_v4l2_buffer *src_buf, *dst_buf;
> +	struct mtk_jpeg_src_buf *jpeg_src_buf, *jpeg_dst_buf;
> +	enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
> +
> +	src_buf = jpeg->hw_param.src_buffer;
> +	dst_buf = jpeg->hw_param.dst_buffer;
> +	ctx = jpeg->hw_param.curr_ctx;
> +	if (!ctx) {
> +		v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n");
> +		return;
> +	}
> +
> +	master_jpeg = ctx->jpeg;
> +	if (!master_jpeg) {
> +		v4l2_err(&jpeg->v4l2_dev, "master_jpeg is NULL\n");
> +		return;
> +	}
> +
> +	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
> +	jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf);
> +
> +	mtk_jpeg_enc_reset(jpeg->reg_base[MTK_JPEGENC_HW0]);
> +	pm_runtime_put(jpeg->pm.dev);
> +	clk_disable_unprepare(jpeg->pm.venc_clk.clk_info->jpegenc_clk);
> +	jpeg->hw_state = MTK_JPEG_HW_IDLE;
> +	atomic_inc(&jpeg->hw_rdy);
> +	wake_up(&master_jpeg->hw_wq);
> +	v4l2_m2m_buf_done(src_buf, buf_state);
> +	mtk_jpeg_put_buf(jpeg);
> +}
> +
>   static void mtk_jpeg_job_timeout_work(struct work_struct *work)
>   {
>   	struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev,
> @@ -1338,12 +1501,99 @@ static inline void mtk_jpeg_clk_release(struct mtk_jpeg_dev *jpeg)
>   	put_device(jpeg->larb);
>   }
>   
> +static  const struct of_device_id mtk_jpegenc_drv_ids[] = {
> +	{
> +		.compatible = "mediatek,mt8195-jpgenc0",
> +		.data = (void *)MTK_JPEGENC_HW0,
> +	},
> +	{
> +		.compatible = "mediatek,mt8195-jpgenc1",
> +		.data = (void *)MTK_JPEGENC_HW1,
> +	},
> +	{},
> +};
> +
> +static inline int mtk_vdec_compare_of(struct device *dev, void *data)
> +{
> +	return dev->of_node == data;
> +}
> +
> +static inline void mtk_vdec_release_of(struct device *dev, void *data)
> +{
> +	of_node_put(data);
> +}
> +
> +static inline int mtk_jpegenc_bind(struct device *dev)
> +{
> +	struct mtk_jpeg_dev *data = dev_get_drvdata(dev);
> +
> +	return component_bind_all(dev, data);
> +}
> +
> +static inline void mtk_jpegenc_unbind(struct device *dev)
> +{
> +	struct mtk_jpeg_dev *data = dev_get_drvdata(dev);
> +
> +	component_unbind_all(dev, data);
> +}
> +
> +static const struct component_master_ops mtk_jpegenc_ops = {
> +	.bind = mtk_jpegenc_bind,
> +	.unbind = mtk_jpegenc_unbind,
> +};
> +
> +struct component_match *mtk_jpegenc_match_add(struct mtk_jpeg_dev *jpeg)
> +{
> +	struct device *dev = jpeg->dev;
> +	struct component_match *match = NULL;
> +	int i;
> +	char compatible[128] = {0};
> +
> +	for (i = 0; i < ARRAY_SIZE(mtk_jpegenc_drv_ids); i++) {
> +		struct device_node *comp_node;
> +		enum mtk_jpegenc_hw_id comp_idx;
> +		const struct of_device_id *of_id;
> +
> +		memcpy(compatible, mtk_jpegenc_drv_ids[i].compatible,
> +		       sizeof(mtk_jpegenc_drv_ids[i].compatible));
> +
> +		comp_node = of_find_compatible_node(NULL, NULL,
> +						    compatible);
> +		if (!comp_node)
> +			continue;
> +
> +		if (!of_device_is_available(comp_node)) {
> +			of_node_put(comp_node);
> +			v4l2_err(&jpeg->v4l2_dev, "Fail to get jpeg enc HW node\n");
> +			continue;
> +		}
> +
> +		of_id = of_match_node(mtk_jpegenc_drv_ids, comp_node);
> +		if (!of_id) {
> +			v4l2_err(&jpeg->v4l2_dev, "Failed to get match node\n");
> +			return ERR_PTR(-EINVAL);
> +		}
> +
> +		comp_idx = (enum mtk_jpegenc_hw_id)of_id->data;
> +		v4l2_info(&jpeg->v4l2_dev, "Get component:hw_id(%d),jpeg_dev(0x%p),comp_node(0x%p)\n",
> +			  comp_idx, jpeg, comp_node);
> +
> +		jpeg->component_node[comp_idx] = comp_node;
> +
> +		component_match_add_release(dev, &match, mtk_vdec_release_of,
> +					    mtk_vdec_compare_of, comp_node);
> +	}
> +
> +	return match;
> +}
> +
>   static int mtk_jpeg_probe(struct platform_device *pdev)
>   {
>   	struct mtk_jpeg_dev *jpeg;
>   	struct resource *res;
>   	int jpeg_irq;
>   	int ret;
> +	struct component_match *match;
>   
>   	jpeg = devm_kzalloc(&pdev->dev, sizeof(*jpeg), GFP_KERNEL);
>   	if (!jpeg)
> @@ -1355,31 +1605,47 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
>   	jpeg->variant = of_device_get_match_data(jpeg->dev);
>   	INIT_DELAYED_WORK(&jpeg->job_timeout_work, mtk_jpeg_job_timeout_work);
>   
> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	jpeg->reg_base = devm_ioremap_resource(&pdev->dev, res);
> -	if (IS_ERR(jpeg->reg_base)) {
> -		ret = PTR_ERR(jpeg->reg_base);
> -		return ret;
> -	}
> +	if (!jpeg->variant->is_encoder) {
> +		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +		jpeg->reg_base[MTK_JPEGENC_HW0] =
> +			devm_ioremap_resource(&pdev->dev, res);
> +		if (IS_ERR(jpeg->reg_base[MTK_JPEGENC_HW0])) {
> +			ret = PTR_ERR(jpeg->reg_base[MTK_JPEGENC_HW0]);
> +			return ret;
> +		}
>   
> -	jpeg_irq = platform_get_irq(pdev, 0);
> -	if (jpeg_irq < 0) {
> -		dev_err(&pdev->dev, "Failed to get jpeg_irq %d.\n", jpeg_irq);
> -		return jpeg_irq;
> -	}
> +		jpeg_irq = platform_get_irq(pdev, 0);
> +		if (jpeg_irq < 0) {
> +			dev_err(&pdev->dev, "Failed to get jpeg_irq %d.\n",
> +				jpeg_irq);
> +			return jpeg_irq;
> +		}
>   
> -	ret = devm_request_irq(&pdev->dev, jpeg_irq,
> -			       jpeg->variant->irq_handler, 0, pdev->name, jpeg);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Failed to request jpeg_irq %d (%d)\n",
> -			jpeg_irq, ret);
> -		goto err_req_irq;
> -	}
> +		ret = devm_request_irq(&pdev->dev, jpeg_irq,
> +				       jpeg->variant->irq_handler,
> +				       0, pdev->name, jpeg);
> +		if (ret) {
> +			dev_err(&pdev->dev, "Failed to request jpeg_irq %d (%d)\n",
> +				jpeg_irq, ret);
> +			goto err_req_irq;
> +		}
>   
> -	ret = mtk_jpeg_clk_init(jpeg);
> -	if (ret) {
> -		dev_err(&pdev->dev, "Failed to init clk, err %d\n", ret);
> -		goto err_clk_init;
> +		ret = mtk_jpeg_clk_init(jpeg);
> +		if (ret) {
> +			dev_err(&pdev->dev, "Failed to init clk\n");
> +			goto err_clk_init;
> +		}
> +	} else {
> +		init_waitqueue_head(&jpeg->hw_wq);
> +
> +		jpeg->workqueue = alloc_ordered_workqueue(MTK_JPEG_NAME,
> +							  WQ_MEM_RECLAIM |
> +							  WQ_FREEZABLE);
> +		if (!jpeg->workqueue) {
> +			dev_err(&pdev->dev, "Failed to create jpeg workqueue!\n");
> +			ret = -EINVAL;
> +			goto err_alloc_workqueue;
> +		}
>   	}
>   
>   	ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
> @@ -1390,7 +1656,6 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
>   	}
>   
>   	jpeg->m2m_dev = v4l2_m2m_init(jpeg->variant->m2m_ops);
> -
>   	if (IS_ERR(jpeg->m2m_dev)) {
>   		v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
>   		ret = PTR_ERR(jpeg->m2m_dev);
> @@ -1422,13 +1687,26 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
>   
>   	video_set_drvdata(jpeg->vdev, jpeg);
>   	v4l2_info(&jpeg->v4l2_dev,
> -		  "%s device registered as /dev/video%d (%d,%d)\n",
> -		  jpeg->variant->dev_name, jpeg->vdev->num,
> -		  VIDEO_MAJOR, jpeg->vdev->minor);
> +			  "%s device registered as /dev/video%d (%d,%d)\n",
> +			  jpeg->variant->dev_name, jpeg->vdev->num,
> +			  VIDEO_MAJOR, jpeg->vdev->minor);
>   
>   	platform_set_drvdata(pdev, jpeg);
>   
> -	pm_runtime_enable(&pdev->dev);
> +	if (jpeg->variant->is_encoder) {
> +		match = mtk_jpegenc_match_add(jpeg);
> +		if (IS_ERR_OR_NULL(match))
> +			goto err_vfd_jpeg_register;
> +
> +		video_set_drvdata(jpeg->vdev, jpeg);
> +		platform_set_drvdata(pdev, jpeg);
> +		ret = component_master_add_with_match(&pdev->dev,
> +						      &mtk_jpegenc_ops, match);
> +		if (ret < 0)
> +			goto err_vfd_jpeg_register;
> +	} else {
> +		pm_runtime_enable(&pdev->dev);
> +	}
>   
>   	return 0;
>   
> @@ -1446,6 +1724,8 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
>   
>   err_clk_init:
>   
> +err_alloc_workqueue:
> +
>   err_req_irq:
>   
>   	return ret;
> @@ -1461,6 +1741,8 @@ static int mtk_jpeg_remove(struct platform_device *pdev)
>   	v4l2_m2m_release(jpeg->m2m_dev);
>   	v4l2_device_unregister(&jpeg->v4l2_dev);
>   	mtk_jpeg_clk_release(jpeg);
> +	flush_workqueue(jpeg->workqueue);
> +	destroy_workqueue(jpeg->workqueue);
>   
>   	return 0;
>   }
> @@ -1524,13 +1806,13 @@ static const struct mtk_jpeg_variant mt8173_jpeg_drvdata = {
>   	.cap_q_default_fourcc = V4L2_PIX_FMT_YUV420M,
>   };
>   
> -static const struct mtk_jpeg_variant mtk_jpeg_drvdata = {
> +static const struct mtk_jpeg_variant mtk_jpegenc_drvdata = {
> +	.is_encoder	= true,
>   	.clks = mtk_jpeg_clocks,
>   	.num_clks = ARRAY_SIZE(mtk_jpeg_clocks),
>   	.formats = mtk_jpeg_enc_formats,
>   	.num_formats = MTK_JPEG_ENC_NUM_FORMATS,
>   	.qops = &mtk_jpeg_enc_qops,
> -	.irq_handler = mtk_jpeg_enc_irq,
>   	.hw_reset = mtk_jpeg_enc_reset,
>   	.m2m_ops = &mtk_jpeg_enc_m2m_ops,
>   	.dev_name = "mtk-jpeg-enc",
> @@ -1540,6 +1822,9 @@ static const struct mtk_jpeg_variant mtk_jpeg_drvdata = {
>   };
>   
>   static const struct of_device_id mtk_jpeg_match[] = {
> +	{	.compatible = "mediatek,mt8195-jpgenc",
> +		.data = &mtk_jpegenc_drvdata,
> +	},
>   	{
>   		.compatible = "mediatek,mt8173-jpgdec",
>   		.data = &mt8173_jpeg_drvdata,
> @@ -1548,10 +1833,6 @@ static const struct of_device_id mtk_jpeg_match[] = {
>   		.compatible = "mediatek,mt2701-jpgdec",
>   		.data = &mt8173_jpeg_drvdata,
>   	},
> -	{
> -		.compatible = "mediatek,mtk-jpgenc",
> -		.data = &mtk_jpeg_drvdata,
> -	},
>   	{},
>   };
>   
> @@ -1567,7 +1848,25 @@ static struct platform_driver mtk_jpeg_driver = {
>   	},
>   };
>   
> -module_platform_driver(mtk_jpeg_driver);
> +static struct platform_driver * const mtk_jpeg_source_drivers[] = {
> +	&mtk_jpegenc_hw_driver,
> +	&mtk_jpeg_driver,
> +};
> +
> +static int __init mtk_jpeg_init(void)
> +{
> +	return platform_register_drivers(mtk_jpeg_source_drivers,
> +					 ARRAY_SIZE(mtk_jpeg_source_drivers));
> +}
> +
> +static void __exit mtk_jpeg_exit(void)
> +{
> +	platform_unregister_drivers(mtk_jpeg_source_drivers,
> +				    ARRAY_SIZE(mtk_jpeg_source_drivers));
> +}
> +
> +module_init(mtk_jpeg_init);
> +module_exit(mtk_jpeg_exit);
>   
>   MODULE_DESCRIPTION("MediaTek JPEG codec driver");
>   MODULE_LICENSE("GPL v2");
> diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
> index 595f7f1..d4259f9 100644
> --- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
> +++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
> @@ -60,6 +60,7 @@ enum mtk_jpeg_ctx_state {
>    * @cap_q_default_fourcc:	capture queue default fourcc
>    */
>   struct mtk_jpeg_variant {
> +	bool is_encoder;
>   	struct clk_bulk_data *clks;
>   	int num_clks;
>   	struct mtk_jpeg_fmt *formats;
> @@ -74,6 +75,52 @@ struct mtk_jpeg_variant {
>   	u32 cap_q_default_fourcc;
>   };
>   
> +struct mtk_jpeg_hw_param {
> +	struct vb2_v4l2_buffer *src_buffer;
> +	struct vb2_v4l2_buffer *dst_buffer;
> +	struct mtk_jpeg_ctx *curr_ctx;
> +};
> +
> +enum mtk_jpeg_hw_state {
> +	MTK_JPEG_HW_IDLE = 0,
> +	MTK_JPEG_HW_BUSY = 1,
> +};
> +
> +enum mtk_jpegenc_hw_id {
> +	MTK_JPEGENC_HW0,
> +	MTK_JPEGENC_HW1,
> +	MTK_JPEGENC_HW_MAX,
> +};
> +
> +/** * enum mtk_hw_idx - MTK hw index */
> +enum mtk_jpeghw_idx {
> +	JPEGENC_HW0,
> +	JPEGENC_HW1,
> +	JPEGDEC_HW0,
> +	JPEGDEC_HW1,
> +	JPEGDEC_HW2,
> +	NUM_MAX_JPEG_HW,
> +};
> +
> +/** * struct mtk_jpegenc_clk_info - Structure used to store clock name */
> +struct mtk_jpegenc_clk_info {
> +	const char	*clk_name;
> +	struct clk	*jpegenc_clk;
> +};
> +
> +/* struct mtk_vcodec_clk - Structure used to store vcodec clock information */
> +struct mtk_jpegenc_clk {
> +	struct mtk_jpegenc_clk_info	*clk_info;
> +	int	clk_num;
> +};
> +
> +/** * struct mtk_vcodec_pm - Power management data structure */
> +struct mtk_jpegenc_pm {
> +	struct mtk_jpegenc_clk	venc_clk;
> +	struct device	*dev;
> +	struct mtk_jpeg_dev	*mtkdev;
> +};
> +
>   /**
>    * struct mtk_jpeg_dev - JPEG IP abstraction
>    * @lock:		the mutex protecting this structure
> @@ -88,6 +135,8 @@ struct mtk_jpeg_variant {
>    * @larb:		SMI device
>    * @job_timeout_work:	IRQ timeout structure
>    * @variant:		driver variant to be used
> + * @irqlock:		spinlock protecting for irq
> + * @dev_mutex:		the mutex protecting for device
>    */
>   struct mtk_jpeg_dev {
>   	struct mutex		lock;
> @@ -98,12 +147,29 @@ struct mtk_jpeg_dev {
>   	struct v4l2_m2m_dev	*m2m_dev;
>   	void			*alloc_ctx;
>   	struct video_device	*vdev;
> -	void __iomem		*reg_base;
>   	struct device		*larb;
> -	struct delayed_work job_timeout_work;
>   	const struct mtk_jpeg_variant *variant;
> +
> +	struct clk		*clk_jpeg;
> +	struct delayed_work job_timeout_work;
> +	struct platform_device *plat_dev;
> +	spinlock_t irqlock;	/* spinlock protecting for irq */
> +	struct mutex dev_mutex;	/* the mutex protecting for device */
> +	void __iomem *reg_base[NUM_MAX_JPEG_HW];
> +	int jpegenc_irq;
> +	struct mtk_jpeg_dev *hw_dev[NUM_MAX_JPEG_HW];
> +	struct device_node *component_node[NUM_MAX_JPEG_HW];
> +	int comp_idx;
> +	struct mtk_jpegenc_pm pm;
> +	struct mtk_jpeg_ctx *curr_ctx;
> +	enum mtk_jpeg_hw_state hw_state;
> +	struct mtk_jpeg_hw_param hw_param;
> +	wait_queue_head_t hw_wq;
> +	atomic_t hw_rdy;
>   };
>   
> +extern struct platform_driver mtk_jpegenc_hw_driver;
> +
>   /**
>    * struct mtk_jpeg_fmt - driver's internal color format data
>    * @fourcc:	the fourcc code, 0 if not applicable
> @@ -149,6 +215,7 @@ struct mtk_jpeg_q_data {
>    * @enc_quality:	jpeg encoder quality
>    * @restart_interval:	jpeg encoder restart interval
>    * @ctrl_hdl:		controls handler
> + * @done_queue_lock:	spinlock protecting for buffer done queue
>    */
>   struct mtk_jpeg_ctx {
>   	struct mtk_jpeg_dev		*jpeg;
> @@ -160,6 +227,15 @@ struct mtk_jpeg_ctx {
>   	u8 enc_quality;
>   	u8 restart_interval;
>   	struct v4l2_ctrl_handler ctrl_hdl;
> +
> +	struct list_head dst_done_queue;
> +	spinlock_t done_queue_lock;	/* spinlock protecting done queue */
> +	u32 total_frame_num;
> +	u32 last_done_frame_num;
> +	struct work_struct jpeg_work;
>   };
>   
> +void mtk_jpegenc_timeout_work(struct work_struct *work);
> +irqreturn_t mtk_jpegenc_hw_irq_handler(int irq, void *priv);
> +
>   #endif /* _MTK_JPEG_CORE_H */
> diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c
> index 1cf037b..d44101e 100644
> --- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c
> +++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_enc_hw.c
> @@ -9,8 +9,20 @@
>   #include <linux/kernel.h>
>   #include <media/videobuf2-core.h>
>   #include <media/videobuf2-dma-contig.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/slab.h>
> +#include <linux/component.h>
> +#include <linux/clk.h>
> +#include <linux/pm_runtime.h>
> +
>   
>   #include "mtk_jpeg_enc_hw.h"
> +#include "mtk_jpeg_core.h"
> +
>   
>   static const struct mtk_jpeg_enc_qlt mtk_jpeg_enc_quality[] = {
>   	{.quality_param = 34, .hardware_value = JPEG_ENC_QUALITY_Q34},
> @@ -30,6 +42,99 @@ static const struct mtk_jpeg_enc_qlt mtk_jpeg_enc_quality[] = {
>   	{.quality_param = 97, .hardware_value = JPEG_ENC_QUALITY_Q97},
>   };
>   
> +typedef irqreturn_t (*jpegenc_irq_handler)(int irq, void *priv);
> +
> +static int mtk_jpegenc_hw_bind(struct device *dev,
> +			       struct device *master, void *data)
> +{
> +	struct mtk_jpeg_dev *comp_priv = dev_get_drvdata(dev);
> +	struct mtk_jpeg_dev *master_priv = data;
> +	int i;
> +
> +	for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) {
> +		if (dev->of_node != master_priv->component_node[i])
> +			continue;
> +		master_priv->hw_dev[i] = comp_priv;
> +		comp_priv->comp_idx = i;
> +		master_priv->reg_base[i] = comp_priv->reg_base[MTK_JPEGENC_HW0];
> +		break;
> +	}
> +	if (i == MTK_JPEGENC_HW_MAX) {
> +		dev_err(dev, "Failed to get component node\n");
> +		return -EINVAL;
> +	}
> +	return 0;
> +}
> +
> +static void mtk_jpegenc_hw_unbind(struct device *dev,
> +				  struct device *master, void *data)
> +{
> +	struct mtk_jpeg_dev *comp_priv = dev_get_drvdata(dev);
> +
> +	comp_priv->reg_base[MTK_JPEGENC_HW0] = 0;
> +}
> +
> +static const struct component_ops mtk_jpegenc_hw_component_ops = {
> +	.bind = mtk_jpegenc_hw_bind,
> +	.unbind = mtk_jpegenc_hw_unbind,
> +};
> +
> +int mtk_jpegenc_init_pm(struct mtk_jpeg_dev *mtkdev)
> +{
> +	struct platform_device *pdev;
> +	struct mtk_jpegenc_pm *pm;
> +	struct mtk_jpegenc_clk *jpegenc_clk;
> +	struct mtk_jpegenc_clk_info *clk_info;
> +	int i = 0, ret = 0;
> +
> +	pdev = mtkdev->plat_dev;
> +	pm = &mtkdev->pm;
> +	pm->mtkdev = mtkdev;
> +
> +	jpegenc_clk = &pm->venc_clk;
> +	pm->dev = &pdev->dev;
> +	jpegenc_clk->clk_num =
> +		of_property_count_strings(pdev->dev.of_node, "clock-names");
> +	if (jpegenc_clk->clk_num > 0) {
> +		jpegenc_clk->clk_info = devm_kcalloc(&pdev->dev,
> +						     jpegenc_clk->clk_num,
> +						     sizeof(*clk_info),
> +						     GFP_KERNEL);
> +		if (!jpegenc_clk->clk_info)
> +			return -ENOMEM;
> +	} else {
> +		pr_err("Failed to get jpegenc clock count\n");
> +		return -EINVAL;
> +	}
> +
> +	for (i = 0; i < jpegenc_clk->clk_num; i++) {
> +		clk_info = &jpegenc_clk->clk_info[i];
> +		ret = of_property_read_string_index(pdev->dev.of_node,
> +						    "clock-names", i,
> +						    &clk_info->clk_name);
> +		if (ret) {
> +			pr_err("Failed to get jpegenc clock name id = %d", i);
> +			return ret;
> +		}
> +
> +		clk_info->jpegenc_clk = devm_clk_get(&pdev->dev,
> +						     clk_info->clk_name);
> +		if (IS_ERR(clk_info->jpegenc_clk)) {
> +			pr_err("devm_clk_get (%d)%s fail",
> +			       i, clk_info->clk_name);
> +			return PTR_ERR(clk_info->jpegenc_clk);
> +		}
> +	}
> +
> +	pm_runtime_enable(&pdev->dev);
> +	return ret;
> +}
> +
> +void mtk_jpegenc_release_pm(struct mtk_jpeg_dev *dev)
> +{
> +	pm_runtime_disable(dev->pm.dev);
> +}
> +
>   void mtk_jpeg_enc_reset(void __iomem *base)
>   {
>   	writel(0, base + JPEG_ENC_RSTB);
> @@ -152,3 +257,107 @@ void mtk_jpeg_set_enc_params(struct mtk_jpeg_ctx *ctx,  void __iomem *base)
>   
>   	writel(ctx->restart_interval, base + JPEG_ENC_RST_MCU_NUM);
>   }
> +
> +static int mtk_jpegenc_hw_init_irq(struct mtk_jpeg_dev *dev,
> +				   jpegenc_irq_handler irq_handler)
> +{
> +	struct platform_device *pdev = dev->plat_dev;
> +	int ret;
> +
> +	dev->jpegenc_irq = platform_get_irq(pdev, 0);
> +	if (dev->jpegenc_irq < 0) {
> +		dev_err(&pdev->dev, "Failed to get irq resource");
> +		return dev->jpegenc_irq;
> +	}
> +
> +	ret = devm_request_irq(&pdev->dev, dev->jpegenc_irq,
> +			       irq_handler, 0, pdev->name, dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to install dev->jpegenc_irq %d (%d)",
> +			dev->jpegenc_irq, ret);
> +
> +		return -ENOENT;
> +	}
> +
> +	//disable_irq(dev->jpegenc_irq);
> +	return 0;
> +}
> +
> +static int mtk_jpegenc_hw_probe(struct platform_device *pdev)
> +{
> +	struct mtk_jpeg_dev *dev;
> +	jpegenc_irq_handler irq_handler;
> +	int ret;
> +
> +	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
> +	if (!dev)
> +		return -ENOMEM;
> +	dev->plat_dev = pdev;
> +	spin_lock_init(&dev->irqlock);
> +	mutex_init(&dev->dev_mutex);
> +	atomic_set(&dev->hw_rdy, 1U);
> +	spin_lock_init(&dev->hw_lock);
> +
> +	dev->hw_state = MTK_JPEG_HW_IDLE;
> +	INIT_DELAYED_WORK(&dev->job_timeout_work, mtk_jpegenc_timeout_work);
> +
> +	ret = mtk_jpegenc_init_pm(dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to get jpeg enc clock source");
> +		return ret;
> +	}
> +
> +	dev->reg_base[MTK_JPEGENC_HW0] =
> +		devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR((__force void *)dev->reg_base[MTK_JPEGENC_HW0])) {
> +		ret = PTR_ERR((__force void *)dev->reg_base[MTK_JPEGENC_HW0]);
> +		goto err;
> +	}
> +
> +	irq_handler = of_device_get_match_data(&pdev->dev);
> +	if (!irq_handler) {
> +		dev_err(&pdev->dev, "Failed to get match data.\n");
> +		goto err;
> +	}
> +
> +	ret = mtk_jpegenc_hw_init_irq(dev, irq_handler);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to register JPEGENC irq handler.\n");
> +		goto err;
> +	}
> +
> +	platform_set_drvdata(pdev, dev);
> +
> +	ret = component_add(&pdev->dev, &mtk_jpegenc_hw_component_ops);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to component_add: %d\n", ret);
> +		goto err;
> +	}
> +
> +	return 0;
> +
> +err:
> +	mtk_jpegenc_release_pm(dev);
> +	return ret;
> +}
> +
> +static const struct of_device_id mtk_jpegenc_hw_ids[] = {
> +	{
> +		.compatible = "mediatek,mt8195-jpgenc0",
> +		.data = mtk_jpegenc_hw_irq_handler,
> +	},
> +	{	.compatible = "mediatek,mt8195-jpgenc1",
> +		.data = mtk_jpegenc_hw_irq_handler,
> +	},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, mtk_jpegenc_hw_ids);
> +
> +struct platform_driver mtk_jpegenc_hw_driver = {
> +	.probe	= mtk_jpegenc_hw_probe,
> +	.driver	= {
> +		.name	= "mtk-jpegenc-hw",
> +		.of_match_table = mtk_jpegenc_hw_ids,
> +	},
> +};
> +
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] dt-bindings: mtk-jpeg: Add binding for MT8195 JPG
  2021-06-25  9:18   ` Tzung-Bi Shih
@ 2021-06-30  7:55     ` kyrie.wu
  2021-07-05  8:09       ` Tzung-Bi Shih
  0 siblings, 1 reply; 10+ messages in thread
From: kyrie.wu @ 2021-06-30  7:55 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Rick Chang,
	Bin Liu, Matthias Brugger, Tzung-Bi Shih,
	Project_Global_Chrome_Upstream_Group, linux-media, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek, Tomasz Figa,
	xia.jiang, maoguang.meng, srv_heupstream

Dear Tzung-Bi,

Mt8195 has two hardwares, "mediatek,mt8195-jpgenc0" for hw0 and
"mediatek,mt8195-jpgenc1" for HW1. These two nodes will register
hardware interrupt, initialize clock, power domain, remap register base
addr and other operations. But the device node is not registered.
"mediatek,mt8195-jpgenc" will register the device node to represent jpeg
encode device. Then the component framework is used to manage the above
two hardwares.

Sincerely,
Kyrie

On Fri, 2021-06-25 at 17:18 +0800, Tzung-Bi Shih wrote:
> On Wed, Jun 23, 2021 at 2:06 PM kyrie.wu <kyrie.wu@mediatek.com> wrote:
> >  Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.txt | 3 +++
> >  1 file changed, 3 insertions(+)
> Note: the patch won't apply after [1].
> 
> [1]: https://lore.kernel.org/patchwork/patch/1445298/
> 
> >  Required properties:
> >  - compatible : "mediatek,mt2701-jpgenc"
> > +- compatible : "mediatek,mt8195-jpgenc"
> > +- compatible : "mediatek,mt8195-jpgenc0"
> > +- compatible : "mediatek,mt8195-jpgenc1"
> Why it needs 3 compatible strings?

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] dt-bindings: mtk-jpeg: Add binding for MT8195 JPG
  2021-06-30  7:55     ` kyrie.wu
@ 2021-07-05  8:09       ` Tzung-Bi Shih
  2021-07-05 10:02         ` kyrie.wu
  0 siblings, 1 reply; 10+ messages in thread
From: Tzung-Bi Shih @ 2021-07-05  8:09 UTC (permalink / raw)
  To: kyrie.wu
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Rick Chang,
	Bin Liu, Matthias Brugger, Tzung-Bi Shih,
	Project_Global_Chrome_Upstream_Group, linux-media, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek, Tomasz Figa,
	xia.jiang, maoguang.meng, srv_heupstream

On Wed, Jun 30, 2021 at 3:56 PM kyrie.wu <kyrie.wu@mediatek.com> wrote:
> Mt8195 has two hardwares, "mediatek,mt8195-jpgenc0" for hw0 and
> "mediatek,mt8195-jpgenc1" for HW1. These two nodes will register
> hardware interrupt, initialize clock, power domain, remap register base
> addr and other operations. But the device node is not registered.
> "mediatek,mt8195-jpgenc" will register the device node to represent jpeg
> encode device. Then the component framework is used to manage the above
> two hardwares.
Please don't top-posting.  Inline your replies so that people can
easily follow the discussion.

I still don't quite understand why it needs to introduce 2 compatible
strings.  If hw0 and hw1 are different from interrupts, clocks, power
domain, and etc, couldn't you use the same compatible string (e.g.
"mt8195-jpgenc") and provide them different DT attributes?

> On Fri, 2021-06-25 at 17:18 +0800, Tzung-Bi Shih wrote:
> > On Wed, Jun 23, 2021 at 2:06 PM kyrie.wu <kyrie.wu@mediatek.com> wrote:
> > >  Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.txt | 3 +++
> > >  1 file changed, 3 insertions(+)
> > Note: the patch won't apply after [1].
> >
> > [1]: https://lore.kernel.org/patchwork/patch/1445298/
> >
> > >  Required properties:
> > >  - compatible : "mediatek,mt2701-jpgenc"
> > > +- compatible : "mediatek,mt8195-jpgenc"
> > > +- compatible : "mediatek,mt8195-jpgenc0"
> > > +- compatible : "mediatek,mt8195-jpgenc1"
> > Why it needs 3 compatible strings?

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] dt-bindings: mtk-jpeg: Add binding for MT8195 JPG
  2021-07-05  8:09       ` Tzung-Bi Shih
@ 2021-07-05 10:02         ` kyrie.wu
  0 siblings, 0 replies; 10+ messages in thread
From: kyrie.wu @ 2021-07-05 10:02 UTC (permalink / raw)
  To: Tzung-Bi Shih
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring, Rick Chang,
	Bin Liu, Matthias Brugger, Tzung-Bi Shih,
	Project_Global_Chrome_Upstream_Group, linux-media, devicetree,
	linux-kernel, linux-arm-kernel, linux-mediatek, Tomasz Figa,
	xia.jiang, maoguang.meng, kyrie.wu, srv_heupstream

On Mon, 2021-07-05 at 16:09 +0800, Tzung-Bi Shih wrote:
> On Wed, Jun 30, 2021 at 3:56 PM kyrie.wu <kyrie.wu@mediatek.com> wrote:
> > Mt8195 has two hardwares, "mediatek,mt8195-jpgenc0" for hw0 and
> > "mediatek,mt8195-jpgenc1" for HW1. These two nodes will register
> > hardware interrupt, initialize clock, power domain, remap register base
> > addr and other operations. But the device node is not registered.
> > "mediatek,mt8195-jpgenc" will register the device node to represent jpeg
> > encode device. Then the component framework is used to manage the above
> > two hardwares.
> Please don't top-posting.  Inline your replies so that people can
> easily follow the discussion.
> 
> I still don't quite understand why it needs to introduce 2 compatible
> strings.  If hw0 and hw1 are different from interrupts, clocks, power
> domain, and etc, couldn't you use the same compatible string (e.g.
> "mt8195-jpgenc") and provide them different DT attributes?
Dear Tzung-Bi,

As you replied, I can use the same compatible string (e.g
"mt8195-jpgenc") and provide resources with different DT attributes.
But there are the following problems:
The following description takes the resource of clock as an example:
1. If different DT attributes are used to represent different clock
information,the structure array (e.g.struct clkinfo) can be used in the
driver to save the corresponding information, which will increase the
complexity of the software;
2. When using hw0, you only need to turn on clock0, but not clock1,
which can reduce power consumption. When the driver uses one of the
clocks, it needs to extract each structure from structure array
(e.g.struct clkinfo) and compare the attributes to confirming which one
to use.
The software architecture is as follows:
if (...) {
[...]
} else if (...) {
[...]
} 
......
At present, there are only two HWS, and the software architecture is not
complex. With the increase of the number of hardware, the software
architecture will become more and more complex.
To sum up, using different compatibles to represent different HW
can reduce power consumption, decrease code complexity
and enhance code readability.
> 
> > On Fri, 2021-06-25 at 17:18 +0800, Tzung-Bi Shih wrote:
> > > On Wed, Jun 23, 2021 at 2:06 PM kyrie.wu <kyrie.wu@mediatek.com> wrote:
> > > >  Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.txt | 3 +++
> > > >  1 file changed, 3 insertions(+)
> > > Note: the patch won't apply after [1].
> > >
> > > [1]: https://lore.kernel.org/patchwork/patch/1445298/
> > >
> > > >  Required properties:
> > > >  - compatible : "mediatek,mt2701-jpgenc"
> > > > +- compatible : "mediatek,mt8195-jpgenc"
> > > > +- compatible : "mediatek,mt8195-jpgenc0"
> > > > +- compatible : "mediatek,mt8195-jpgenc1"
> > > Why it needs 3 compatible strings?

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-07-05 10:05 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-23  6:05 [PATCH 0/3] Support jpeg encode for MT8195 kyrie.wu
2021-06-23  6:05 ` [PATCH 1/3] dt-bindings: mtk-jpeg: Add binding for MT8195 JPG kyrie.wu
2021-06-25  9:18   ` Tzung-Bi Shih
2021-06-30  7:55     ` kyrie.wu
2021-07-05  8:09       ` Tzung-Bi Shih
2021-07-05 10:02         ` kyrie.wu
2021-06-23  6:05 ` [PATCH 2/3] media: mtk-jpegenc: use component framework to manage jpg HW kyrie.wu
2021-06-25  9:18   ` Tzung-Bi Shih
2021-06-29  7:33   ` Dafna Hirschfeld
2021-06-23  6:05 ` [PATCH 3/3] media: mtk-jpegenc: design SW algorithm for using multi-HW of jpegenc kyrie.wu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).