mtk_jpeg_enc_hw.c (4852B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2019 MediaTek Inc. 4 * Author: Xia Jiang <xia.jiang@mediatek.com> 5 * 6 */ 7 8#include <linux/io.h> 9#include <linux/kernel.h> 10#include <media/videobuf2-core.h> 11#include <media/videobuf2-dma-contig.h> 12 13#include "mtk_jpeg_enc_hw.h" 14 15static 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}, 31}; 32 33void mtk_jpeg_enc_reset(void __iomem *base) 34{ 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); 38} 39 40u32 mtk_jpeg_enc_get_file_size(void __iomem *base) 41{ 42 return readl(base + JPEG_ENC_DMA_ADDR0) - 43 readl(base + JPEG_ENC_DST_ADDR0); 44} 45 46void mtk_jpeg_enc_start(void __iomem *base) 47{ 48 u32 value; 49 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); 53} 54 55void mtk_jpeg_set_enc_src(struct mtk_jpeg_ctx *ctx, void __iomem *base, 56 struct vb2_buffer *src_buf) 57{ 58 int i; 59 dma_addr_t dma_addr; 60 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; 64 if (!i) 65 writel(dma_addr, base + JPEG_ENC_SRC_LUMA_ADDR); 66 else 67 writel(dma_addr, base + JPEG_ENC_SRC_CHROMA_ADDR); 68 } 69} 70 71void mtk_jpeg_set_enc_dst(struct mtk_jpeg_ctx *ctx, void __iomem *base, 72 struct vb2_buffer *dst_buf) 73{ 74 dma_addr_t dma_addr; 75 size_t size; 76 u32 dma_addr_offset; 77 u32 dma_addr_offsetmask; 78 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); 83 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); 88} 89 90void mtk_jpeg_set_enc_params(struct mtk_jpeg_ctx *ctx, void __iomem *base) 91{ 92 u32 value; 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; 97 u32 blk_num; 98 u32 img_stride; 99 u32 mem_stride; 100 u32 i, enc_quality; 101 102 value = width << 16 | height; 103 writel(value, base + JPEG_ENC_IMG_SIZE); 104 105 if (enc_format == V4L2_PIX_FMT_NV12M || 106 enc_format == V4L2_PIX_FMT_NV21M) 107 /* 108 * Total 8 x 8 block number of luma and chroma. 109 * The number of blocks is counted from 0. 110 */ 111 blk_num = DIV_ROUND_UP(width, 16) * 112 DIV_ROUND_UP(height, 16) * 6 - 1; 113 else 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); 117 118 if (enc_format == V4L2_PIX_FMT_NV12M || 119 enc_format == V4L2_PIX_FMT_NV21M) { 120 /* 4:2:0 */ 121 img_stride = round_up(width, 16); 122 mem_stride = bytesperline; 123 } else { 124 /* 4:2:2 */ 125 img_stride = round_up(width * 2, 32); 126 mem_stride = img_stride; 127 } 128 writel(img_stride, base + JPEG_ENC_IMG_STRIDE); 129 writel(mem_stride, base + JPEG_ENC_STRIDE); 130 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; 135 break; 136 } 137 } 138 writel(enc_quality, base + JPEG_ENC_QUALITY); 139 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; 145 else 146 value &= ~JPEG_ENC_CTRL_FILE_FORMAT_BIT; 147 if (ctx->restart_interval) 148 value |= JPEG_ENC_CTRL_RESTART_EN_BIT; 149 else 150 value &= ~JPEG_ENC_CTRL_RESTART_EN_BIT; 151 writel(value, base + JPEG_ENC_CTRL); 152 153 writel(ctx->restart_interval, base + JPEG_ENC_RST_MCU_NUM); 154}