1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2019 MediaTek Inc.
4 * Author: Xia Jiang <xia.jiang@mediatek.com>
9 #include <linux/kernel.h>
10 #include <media/videobuf2-core.h>
11 #include <media/videobuf2-dma-contig.h>
13 #include "mtk_jpeg_enc_hw.h"
15 static const struct mtk_jpeg_enc_qlt mtk_jpeg_enc_quality
[] = {
16 {.quality_param
= 34, .hardware_value
= JPEG_ENC_QUALITY_Q34
},
17 {.quality_param
= 39, .hardware_value
= JPEG_ENC_QUALITY_Q39
},
18 {.quality_param
= 48, .hardware_value
= JPEG_ENC_QUALITY_Q48
},
19 {.quality_param
= 60, .hardware_value
= JPEG_ENC_QUALITY_Q60
},
20 {.quality_param
= 64, .hardware_value
= JPEG_ENC_QUALITY_Q64
},
21 {.quality_param
= 68, .hardware_value
= JPEG_ENC_QUALITY_Q68
},
22 {.quality_param
= 74, .hardware_value
= JPEG_ENC_QUALITY_Q74
},
23 {.quality_param
= 80, .hardware_value
= JPEG_ENC_QUALITY_Q80
},
24 {.quality_param
= 82, .hardware_value
= JPEG_ENC_QUALITY_Q82
},
25 {.quality_param
= 84, .hardware_value
= JPEG_ENC_QUALITY_Q84
},
26 {.quality_param
= 87, .hardware_value
= JPEG_ENC_QUALITY_Q87
},
27 {.quality_param
= 90, .hardware_value
= JPEG_ENC_QUALITY_Q90
},
28 {.quality_param
= 92, .hardware_value
= JPEG_ENC_QUALITY_Q92
},
29 {.quality_param
= 95, .hardware_value
= JPEG_ENC_QUALITY_Q95
},
30 {.quality_param
= 97, .hardware_value
= JPEG_ENC_QUALITY_Q97
},
33 void mtk_jpeg_enc_reset(void __iomem
*base
)
35 writel(0, base
+ JPEG_ENC_RSTB
);
36 writel(JPEG_ENC_RESET_BIT
, base
+ JPEG_ENC_RSTB
);
37 writel(0, base
+ JPEG_ENC_CODEC_SEL
);
40 u32
mtk_jpeg_enc_get_file_size(void __iomem
*base
)
42 return readl(base
+ JPEG_ENC_DMA_ADDR0
) -
43 readl(base
+ JPEG_ENC_DST_ADDR0
);
46 void mtk_jpeg_enc_start(void __iomem
*base
)
50 value
= readl(base
+ JPEG_ENC_CTRL
);
51 value
|= JPEG_ENC_CTRL_INT_EN_BIT
| JPEG_ENC_CTRL_ENABLE_BIT
;
52 writel(value
, base
+ JPEG_ENC_CTRL
);
55 void mtk_jpeg_set_enc_src(struct mtk_jpeg_ctx
*ctx
, void __iomem
*base
,
56 struct vb2_buffer
*src_buf
)
61 for (i
= 0; i
< src_buf
->num_planes
; i
++) {
62 dma_addr
= vb2_dma_contig_plane_dma_addr(src_buf
, i
) +
63 src_buf
->planes
[i
].data_offset
;
65 writel(dma_addr
, base
+ JPEG_ENC_SRC_LUMA_ADDR
);
67 writel(dma_addr
, base
+ JPEG_ENC_SRC_CHROMA_ADDR
);
71 void mtk_jpeg_set_enc_dst(struct mtk_jpeg_ctx
*ctx
, void __iomem
*base
,
72 struct vb2_buffer
*dst_buf
)
77 u32 dma_addr_offsetmask
;
79 dma_addr
= vb2_dma_contig_plane_dma_addr(dst_buf
, 0);
80 dma_addr_offset
= ctx
->enable_exif
? MTK_JPEG_MAX_EXIF_SIZE
: 0;
81 dma_addr_offsetmask
= dma_addr
& JPEG_ENC_DST_ADDR_OFFSET_MASK
;
82 size
= vb2_plane_size(dst_buf
, 0);
84 writel(dma_addr_offset
& ~0xf, base
+ JPEG_ENC_OFFSET_ADDR
);
85 writel(dma_addr_offsetmask
& 0xf, base
+ JPEG_ENC_BYTE_OFFSET_MASK
);
86 writel(dma_addr
& ~0xf, base
+ JPEG_ENC_DST_ADDR0
);
87 writel((dma_addr
+ size
) & ~0xf, base
+ JPEG_ENC_STALL_ADDR0
);
90 void mtk_jpeg_set_enc_params(struct mtk_jpeg_ctx
*ctx
, void __iomem
*base
)
93 u32 width
= ctx
->out_q
.enc_crop_rect
.width
;
94 u32 height
= ctx
->out_q
.enc_crop_rect
.height
;
95 u32 enc_format
= ctx
->out_q
.fmt
->fourcc
;
96 u32 bytesperline
= ctx
->out_q
.pix_mp
.plane_fmt
[0].bytesperline
;
102 value
= width
<< 16 | height
;
103 writel(value
, base
+ JPEG_ENC_IMG_SIZE
);
105 if (enc_format
== V4L2_PIX_FMT_NV12M
||
106 enc_format
== V4L2_PIX_FMT_NV21M
)
108 * Total 8 x 8 block number of luma and chroma.
109 * The number of blocks is counted from 0.
111 blk_num
= DIV_ROUND_UP(width
, 16) *
112 DIV_ROUND_UP(height
, 16) * 6 - 1;
114 blk_num
= DIV_ROUND_UP(width
, 16) *
115 DIV_ROUND_UP(height
, 8) * 4 - 1;
116 writel(blk_num
, base
+ JPEG_ENC_BLK_NUM
);
118 if (enc_format
== V4L2_PIX_FMT_NV12M
||
119 enc_format
== V4L2_PIX_FMT_NV21M
) {
121 img_stride
= round_up(width
, 16);
122 mem_stride
= bytesperline
;
125 img_stride
= round_up(width
* 2, 32);
126 mem_stride
= img_stride
;
128 writel(img_stride
, base
+ JPEG_ENC_IMG_STRIDE
);
129 writel(mem_stride
, base
+ JPEG_ENC_STRIDE
);
131 enc_quality
= mtk_jpeg_enc_quality
[0].hardware_value
;
132 for (i
= 0; i
< ARRAY_SIZE(mtk_jpeg_enc_quality
); i
++) {
133 if (ctx
->enc_quality
<= mtk_jpeg_enc_quality
[i
].quality_param
) {
134 enc_quality
= mtk_jpeg_enc_quality
[i
].hardware_value
;
138 writel(enc_quality
, base
+ JPEG_ENC_QUALITY
);
140 value
= readl(base
+ JPEG_ENC_CTRL
);
141 value
&= ~JPEG_ENC_CTRL_YUV_FORMAT_MASK
;
142 value
|= (ctx
->out_q
.fmt
->hw_format
& 3) << 3;
143 if (ctx
->enable_exif
)
144 value
|= JPEG_ENC_CTRL_FILE_FORMAT_BIT
;
146 value
&= ~JPEG_ENC_CTRL_FILE_FORMAT_BIT
;
147 if (ctx
->restart_interval
)
148 value
|= JPEG_ENC_CTRL_RESTART_EN_BIT
;
150 value
&= ~JPEG_ENC_CTRL_RESTART_EN_BIT
;
151 writel(value
, base
+ JPEG_ENC_CTRL
);
153 writel(ctx
->restart_interval
, base
+ JPEG_ENC_RST_MCU_NUM
);