mtk_jpeg_dec_hw.c (11545B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2016 MediaTek Inc. 4 * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com> 5 * Rick Chang <rick.chang@mediatek.com> 6 */ 7 8#include <linux/io.h> 9#include <linux/kernel.h> 10#include <media/videobuf2-core.h> 11 12#include "mtk_jpeg_dec_hw.h" 13 14#define MTK_JPEG_DUNUM_MASK(val) (((val) - 1) & 0x3) 15 16enum mtk_jpeg_color { 17 MTK_JPEG_COLOR_420 = 0x00221111, 18 MTK_JPEG_COLOR_422 = 0x00211111, 19 MTK_JPEG_COLOR_444 = 0x00111111, 20 MTK_JPEG_COLOR_422V = 0x00121111, 21 MTK_JPEG_COLOR_422X2 = 0x00412121, 22 MTK_JPEG_COLOR_422VX2 = 0x00222121, 23 MTK_JPEG_COLOR_400 = 0x00110000 24}; 25 26static inline int mtk_jpeg_verify_align(u32 val, int align, u32 reg) 27{ 28 if (val & (align - 1)) { 29 pr_err("mtk-jpeg: write reg %x without %d align\n", reg, align); 30 return -1; 31 } 32 33 return 0; 34} 35 36static int mtk_jpeg_decide_format(struct mtk_jpeg_dec_param *param) 37{ 38 param->src_color = (param->sampling_w[0] << 20) | 39 (param->sampling_h[0] << 16) | 40 (param->sampling_w[1] << 12) | 41 (param->sampling_h[1] << 8) | 42 (param->sampling_w[2] << 4) | 43 (param->sampling_h[2]); 44 45 param->uv_brz_w = 0; 46 switch (param->src_color) { 47 case MTK_JPEG_COLOR_444: 48 param->uv_brz_w = 1; 49 param->dst_fourcc = V4L2_PIX_FMT_YUV422M; 50 break; 51 case MTK_JPEG_COLOR_422X2: 52 case MTK_JPEG_COLOR_422: 53 param->dst_fourcc = V4L2_PIX_FMT_YUV422M; 54 break; 55 case MTK_JPEG_COLOR_422V: 56 case MTK_JPEG_COLOR_422VX2: 57 param->uv_brz_w = 1; 58 param->dst_fourcc = V4L2_PIX_FMT_YUV420M; 59 break; 60 case MTK_JPEG_COLOR_420: 61 param->dst_fourcc = V4L2_PIX_FMT_YUV420M; 62 break; 63 case MTK_JPEG_COLOR_400: 64 param->dst_fourcc = V4L2_PIX_FMT_GREY; 65 break; 66 default: 67 param->dst_fourcc = 0; 68 return -1; 69 } 70 71 return 0; 72} 73 74static void mtk_jpeg_calc_mcu(struct mtk_jpeg_dec_param *param) 75{ 76 u32 factor_w, factor_h; 77 u32 i, comp, blk; 78 79 factor_w = 2 + param->sampling_w[0]; 80 factor_h = 2 + param->sampling_h[0]; 81 param->mcu_w = (param->pic_w + (1 << factor_w) - 1) >> factor_w; 82 param->mcu_h = (param->pic_h + (1 << factor_h) - 1) >> factor_h; 83 param->total_mcu = param->mcu_w * param->mcu_h; 84 param->unit_num = ((param->pic_w + 7) >> 3) * ((param->pic_h + 7) >> 3); 85 param->blk_num = 0; 86 for (i = 0; i < MTK_JPEG_COMP_MAX; i++) { 87 param->blk_comp[i] = 0; 88 if (i >= param->comp_num) 89 continue; 90 param->blk_comp[i] = param->sampling_w[i] * 91 param->sampling_h[i]; 92 param->blk_num += param->blk_comp[i]; 93 } 94 95 param->membership = 0; 96 for (i = 0, blk = 0, comp = 0; i < MTK_JPEG_BLOCK_MAX; i++) { 97 if (i < param->blk_num && comp < param->comp_num) { 98 u32 tmp; 99 100 tmp = (0x04 + (comp & 0x3)); 101 param->membership |= tmp << (i * 3); 102 if (++blk == param->blk_comp[comp]) { 103 comp++; 104 blk = 0; 105 } 106 } else { 107 param->membership |= 7 << (i * 3); 108 } 109 } 110} 111 112static void mtk_jpeg_calc_dma_group(struct mtk_jpeg_dec_param *param) 113{ 114 u32 factor_mcu = 3; 115 116 if (param->src_color == MTK_JPEG_COLOR_444 && 117 param->dst_fourcc == V4L2_PIX_FMT_YUV422M) 118 factor_mcu = 4; 119 else if (param->src_color == MTK_JPEG_COLOR_422V && 120 param->dst_fourcc == V4L2_PIX_FMT_YUV420M) 121 factor_mcu = 4; 122 else if (param->src_color == MTK_JPEG_COLOR_422X2 && 123 param->dst_fourcc == V4L2_PIX_FMT_YUV422M) 124 factor_mcu = 2; 125 else if (param->src_color == MTK_JPEG_COLOR_400 || 126 (param->src_color & 0x0FFFF) == 0) 127 factor_mcu = 4; 128 129 param->dma_mcu = 1 << factor_mcu; 130 param->dma_group = param->mcu_w / param->dma_mcu; 131 param->dma_last_mcu = param->mcu_w % param->dma_mcu; 132 if (param->dma_last_mcu) 133 param->dma_group++; 134 else 135 param->dma_last_mcu = param->dma_mcu; 136} 137 138static int mtk_jpeg_calc_dst_size(struct mtk_jpeg_dec_param *param) 139{ 140 u32 i, padding_w; 141 u32 ds_row_h[3]; 142 u32 brz_w[3]; 143 144 brz_w[0] = 0; 145 brz_w[1] = param->uv_brz_w; 146 brz_w[2] = brz_w[1]; 147 148 for (i = 0; i < param->comp_num; i++) { 149 if (brz_w[i] > 3) 150 return -1; 151 152 padding_w = param->mcu_w * MTK_JPEG_DCTSIZE * 153 param->sampling_w[i]; 154 /* output format is 420/422 */ 155 param->comp_w[i] = padding_w >> brz_w[i]; 156 param->comp_w[i] = round_up(param->comp_w[i], 157 MTK_JPEG_DCTSIZE); 158 param->img_stride[i] = i ? round_up(param->comp_w[i], 16) 159 : round_up(param->comp_w[i], 32); 160 ds_row_h[i] = (MTK_JPEG_DCTSIZE * param->sampling_h[i]); 161 } 162 param->dec_w = param->img_stride[0]; 163 param->dec_h = ds_row_h[0] * param->mcu_h; 164 165 for (i = 0; i < MTK_JPEG_COMP_MAX; i++) { 166 /* They must be equal in frame mode. */ 167 param->mem_stride[i] = param->img_stride[i]; 168 param->comp_size[i] = param->mem_stride[i] * ds_row_h[i] * 169 param->mcu_h; 170 } 171 172 param->y_size = param->comp_size[0]; 173 param->uv_size = param->comp_size[1]; 174 param->dec_size = param->y_size + (param->uv_size << 1); 175 176 return 0; 177} 178 179int mtk_jpeg_dec_fill_param(struct mtk_jpeg_dec_param *param) 180{ 181 if (mtk_jpeg_decide_format(param)) 182 return -1; 183 184 mtk_jpeg_calc_mcu(param); 185 mtk_jpeg_calc_dma_group(param); 186 if (mtk_jpeg_calc_dst_size(param)) 187 return -2; 188 189 return 0; 190} 191 192u32 mtk_jpeg_dec_get_int_status(void __iomem *base) 193{ 194 u32 ret; 195 196 ret = readl(base + JPGDEC_REG_INTERRUPT_STATUS) & BIT_INQST_MASK_ALLIRQ; 197 if (ret) 198 writel(ret, base + JPGDEC_REG_INTERRUPT_STATUS); 199 200 return ret; 201} 202 203u32 mtk_jpeg_dec_enum_result(u32 irq_result) 204{ 205 if (irq_result & BIT_INQST_MASK_EOF) 206 return MTK_JPEG_DEC_RESULT_EOF_DONE; 207 if (irq_result & BIT_INQST_MASK_PAUSE) 208 return MTK_JPEG_DEC_RESULT_PAUSE; 209 if (irq_result & BIT_INQST_MASK_UNDERFLOW) 210 return MTK_JPEG_DEC_RESULT_UNDERFLOW; 211 if (irq_result & BIT_INQST_MASK_OVERFLOW) 212 return MTK_JPEG_DEC_RESULT_OVERFLOW; 213 if (irq_result & BIT_INQST_MASK_ERROR_BS) 214 return MTK_JPEG_DEC_RESULT_ERROR_BS; 215 216 return MTK_JPEG_DEC_RESULT_ERROR_UNKNOWN; 217} 218 219void mtk_jpeg_dec_start(void __iomem *base) 220{ 221 writel(0, base + JPGDEC_REG_TRIG); 222} 223 224static void mtk_jpeg_dec_soft_reset(void __iomem *base) 225{ 226 writel(0x0000FFFF, base + JPGDEC_REG_INTERRUPT_STATUS); 227 writel(0x00, base + JPGDEC_REG_RESET); 228 writel(0x01, base + JPGDEC_REG_RESET); 229} 230 231static void mtk_jpeg_dec_hard_reset(void __iomem *base) 232{ 233 writel(0x00, base + JPGDEC_REG_RESET); 234 writel(0x10, base + JPGDEC_REG_RESET); 235} 236 237void mtk_jpeg_dec_reset(void __iomem *base) 238{ 239 mtk_jpeg_dec_soft_reset(base); 240 mtk_jpeg_dec_hard_reset(base); 241} 242 243static void mtk_jpeg_dec_set_brz_factor(void __iomem *base, u8 yscale_w, 244 u8 yscale_h, u8 uvscale_w, u8 uvscale_h) 245{ 246 u32 val; 247 248 val = (uvscale_h << 12) | (uvscale_w << 8) | 249 (yscale_h << 4) | yscale_w; 250 writel(val, base + JPGDEC_REG_BRZ_FACTOR); 251} 252 253static void mtk_jpeg_dec_set_dst_bank0(void __iomem *base, u32 addr_y, 254 u32 addr_u, u32 addr_v) 255{ 256 mtk_jpeg_verify_align(addr_y, 16, JPGDEC_REG_DEST_ADDR0_Y); 257 writel(addr_y, base + JPGDEC_REG_DEST_ADDR0_Y); 258 mtk_jpeg_verify_align(addr_u, 16, JPGDEC_REG_DEST_ADDR0_U); 259 writel(addr_u, base + JPGDEC_REG_DEST_ADDR0_U); 260 mtk_jpeg_verify_align(addr_v, 16, JPGDEC_REG_DEST_ADDR0_V); 261 writel(addr_v, base + JPGDEC_REG_DEST_ADDR0_V); 262} 263 264static void mtk_jpeg_dec_set_dst_bank1(void __iomem *base, u32 addr_y, 265 u32 addr_u, u32 addr_v) 266{ 267 writel(addr_y, base + JPGDEC_REG_DEST_ADDR1_Y); 268 writel(addr_u, base + JPGDEC_REG_DEST_ADDR1_U); 269 writel(addr_v, base + JPGDEC_REG_DEST_ADDR1_V); 270} 271 272static void mtk_jpeg_dec_set_mem_stride(void __iomem *base, u32 stride_y, 273 u32 stride_uv) 274{ 275 writel((stride_y & 0xFFFF), base + JPGDEC_REG_STRIDE_Y); 276 writel((stride_uv & 0xFFFF), base + JPGDEC_REG_STRIDE_UV); 277} 278 279static void mtk_jpeg_dec_set_img_stride(void __iomem *base, u32 stride_y, 280 u32 stride_uv) 281{ 282 writel((stride_y & 0xFFFF), base + JPGDEC_REG_IMG_STRIDE_Y); 283 writel((stride_uv & 0xFFFF), base + JPGDEC_REG_IMG_STRIDE_UV); 284} 285 286static void mtk_jpeg_dec_set_pause_mcu_idx(void __iomem *base, u32 idx) 287{ 288 writel(idx & 0x0003FFFFFF, base + JPGDEC_REG_PAUSE_MCU_NUM); 289} 290 291static void mtk_jpeg_dec_set_dec_mode(void __iomem *base, u32 mode) 292{ 293 writel(mode & 0x03, base + JPGDEC_REG_OPERATION_MODE); 294} 295 296static void mtk_jpeg_dec_set_bs_write_ptr(void __iomem *base, u32 ptr) 297{ 298 mtk_jpeg_verify_align(ptr, 16, JPGDEC_REG_FILE_BRP); 299 writel(ptr, base + JPGDEC_REG_FILE_BRP); 300} 301 302static void mtk_jpeg_dec_set_bs_info(void __iomem *base, u32 addr, u32 size) 303{ 304 mtk_jpeg_verify_align(addr, 16, JPGDEC_REG_FILE_ADDR); 305 mtk_jpeg_verify_align(size, 128, JPGDEC_REG_FILE_TOTAL_SIZE); 306 writel(addr, base + JPGDEC_REG_FILE_ADDR); 307 writel(size, base + JPGDEC_REG_FILE_TOTAL_SIZE); 308} 309 310static void mtk_jpeg_dec_set_comp_id(void __iomem *base, u32 id_y, u32 id_u, 311 u32 id_v) 312{ 313 u32 val; 314 315 val = ((id_y & 0x00FF) << 24) | ((id_u & 0x00FF) << 16) | 316 ((id_v & 0x00FF) << 8); 317 writel(val, base + JPGDEC_REG_COMP_ID); 318} 319 320static void mtk_jpeg_dec_set_total_mcu(void __iomem *base, u32 num) 321{ 322 writel(num - 1, base + JPGDEC_REG_TOTAL_MCU_NUM); 323} 324 325static void mtk_jpeg_dec_set_comp0_du(void __iomem *base, u32 num) 326{ 327 writel(num - 1, base + JPGDEC_REG_COMP0_DATA_UNIT_NUM); 328} 329 330static void mtk_jpeg_dec_set_du_membership(void __iomem *base, u32 member, 331 u32 gmc, u32 isgray) 332{ 333 if (isgray) 334 member = 0x3FFFFFFC; 335 member |= (isgray << 31) | (gmc << 30); 336 writel(member, base + JPGDEC_REG_DU_CTRL); 337} 338 339static void mtk_jpeg_dec_set_q_table(void __iomem *base, u32 id0, u32 id1, 340 u32 id2) 341{ 342 u32 val; 343 344 val = ((id0 & 0x0f) << 8) | ((id1 & 0x0f) << 4) | ((id2 & 0x0f) << 0); 345 writel(val, base + JPGDEC_REG_QT_ID); 346} 347 348static void mtk_jpeg_dec_set_dma_group(void __iomem *base, u32 mcu_group, 349 u32 group_num, u32 last_mcu) 350{ 351 u32 val; 352 353 val = (((mcu_group - 1) & 0x00FF) << 16) | 354 (((group_num - 1) & 0x007F) << 8) | 355 ((last_mcu - 1) & 0x00FF); 356 writel(val, base + JPGDEC_REG_WDMA_CTRL); 357} 358 359static void mtk_jpeg_dec_set_sampling_factor(void __iomem *base, u32 comp_num, 360 u32 y_w, u32 y_h, u32 u_w, 361 u32 u_h, u32 v_w, u32 v_h) 362{ 363 u32 val; 364 u32 y_wh = (MTK_JPEG_DUNUM_MASK(y_w) << 2) | MTK_JPEG_DUNUM_MASK(y_h); 365 u32 u_wh = (MTK_JPEG_DUNUM_MASK(u_w) << 2) | MTK_JPEG_DUNUM_MASK(u_h); 366 u32 v_wh = (MTK_JPEG_DUNUM_MASK(v_w) << 2) | MTK_JPEG_DUNUM_MASK(v_h); 367 368 if (comp_num == 1) 369 val = 0; 370 else 371 val = (y_wh << 8) | (u_wh << 4) | v_wh; 372 writel(val, base + JPGDEC_REG_DU_NUM); 373} 374 375void mtk_jpeg_dec_set_config(void __iomem *base, 376 struct mtk_jpeg_dec_param *config, 377 struct mtk_jpeg_bs *bs, 378 struct mtk_jpeg_fb *fb) 379{ 380 mtk_jpeg_dec_set_brz_factor(base, 0, 0, config->uv_brz_w, 0); 381 mtk_jpeg_dec_set_dec_mode(base, 0); 382 mtk_jpeg_dec_set_comp0_du(base, config->unit_num); 383 mtk_jpeg_dec_set_total_mcu(base, config->total_mcu); 384 mtk_jpeg_dec_set_bs_info(base, bs->str_addr, bs->size); 385 mtk_jpeg_dec_set_bs_write_ptr(base, bs->end_addr); 386 mtk_jpeg_dec_set_du_membership(base, config->membership, 1, 387 (config->comp_num == 1) ? 1 : 0); 388 mtk_jpeg_dec_set_comp_id(base, config->comp_id[0], config->comp_id[1], 389 config->comp_id[2]); 390 mtk_jpeg_dec_set_q_table(base, config->qtbl_num[0], 391 config->qtbl_num[1], config->qtbl_num[2]); 392 mtk_jpeg_dec_set_sampling_factor(base, config->comp_num, 393 config->sampling_w[0], 394 config->sampling_h[0], 395 config->sampling_w[1], 396 config->sampling_h[1], 397 config->sampling_w[2], 398 config->sampling_h[2]); 399 mtk_jpeg_dec_set_mem_stride(base, config->mem_stride[0], 400 config->mem_stride[1]); 401 mtk_jpeg_dec_set_img_stride(base, config->img_stride[0], 402 config->img_stride[1]); 403 mtk_jpeg_dec_set_dst_bank0(base, fb->plane_addr[0], 404 fb->plane_addr[1], fb->plane_addr[2]); 405 mtk_jpeg_dec_set_dst_bank1(base, 0, 0, 0); 406 mtk_jpeg_dec_set_dma_group(base, config->dma_mcu, config->dma_group, 407 config->dma_last_mcu); 408 mtk_jpeg_dec_set_pause_mcu_idx(base, config->total_mcu); 409}