18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/* linux/drivers/media/platform/s5p-jpeg/jpeg-hw.h
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (c) 2011 Samsung Electronics Co., Ltd.
58c2ecf20Sopenharmony_ci *		http://www.samsung.com
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/io.h>
118c2ecf20Sopenharmony_ci#include <linux/videodev2.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "jpeg-core.h"
148c2ecf20Sopenharmony_ci#include "jpeg-regs.h"
158c2ecf20Sopenharmony_ci#include "jpeg-hw-s5p.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_civoid s5p_jpeg_reset(void __iomem *regs)
188c2ecf20Sopenharmony_ci{
198c2ecf20Sopenharmony_ci	unsigned long reg;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	writel(1, regs + S5P_JPG_SW_RESET);
228c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPG_SW_RESET);
238c2ecf20Sopenharmony_ci	/* no other way but polling for when JPEG IP becomes operational */
248c2ecf20Sopenharmony_ci	while (reg != 0) {
258c2ecf20Sopenharmony_ci		cpu_relax();
268c2ecf20Sopenharmony_ci		reg = readl(regs + S5P_JPG_SW_RESET);
278c2ecf20Sopenharmony_ci	}
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_civoid s5p_jpeg_poweron(void __iomem *regs)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	writel(S5P_POWER_ON, regs + S5P_JPGCLKCON);
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_civoid s5p_jpeg_input_raw_mode(void __iomem *regs, unsigned long mode)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	unsigned long reg, m;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	m = S5P_MOD_SEL_565;
408c2ecf20Sopenharmony_ci	if (mode == S5P_JPEG_RAW_IN_565)
418c2ecf20Sopenharmony_ci		m = S5P_MOD_SEL_565;
428c2ecf20Sopenharmony_ci	else if (mode == S5P_JPEG_RAW_IN_422)
438c2ecf20Sopenharmony_ci		m = S5P_MOD_SEL_422;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPGCMOD);
468c2ecf20Sopenharmony_ci	reg &= ~S5P_MOD_SEL_MASK;
478c2ecf20Sopenharmony_ci	reg |= m;
488c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPGCMOD);
498c2ecf20Sopenharmony_ci}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_civoid s5p_jpeg_proc_mode(void __iomem *regs, unsigned long mode)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	unsigned long reg, m;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	m = S5P_PROC_MODE_DECOMPR;
568c2ecf20Sopenharmony_ci	if (mode == S5P_JPEG_ENCODE)
578c2ecf20Sopenharmony_ci		m = S5P_PROC_MODE_COMPR;
588c2ecf20Sopenharmony_ci	else
598c2ecf20Sopenharmony_ci		m = S5P_PROC_MODE_DECOMPR;
608c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPGMOD);
618c2ecf20Sopenharmony_ci	reg &= ~S5P_PROC_MODE_MASK;
628c2ecf20Sopenharmony_ci	reg |= m;
638c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPGMOD);
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_civoid s5p_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	unsigned long reg, m;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	if (mode == V4L2_JPEG_CHROMA_SUBSAMPLING_420)
718c2ecf20Sopenharmony_ci		m = S5P_SUBSAMPLING_MODE_420;
728c2ecf20Sopenharmony_ci	else
738c2ecf20Sopenharmony_ci		m = S5P_SUBSAMPLING_MODE_422;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPGMOD);
768c2ecf20Sopenharmony_ci	reg &= ~S5P_SUBSAMPLING_MODE_MASK;
778c2ecf20Sopenharmony_ci	reg |= m;
788c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPGMOD);
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ciunsigned int s5p_jpeg_get_subsampling_mode(void __iomem *regs)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	return readl(regs + S5P_JPGMOD) & S5P_SUBSAMPLING_MODE_MASK;
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_civoid s5p_jpeg_dri(void __iomem *regs, unsigned int dri)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	unsigned long reg;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPGDRI_U);
918c2ecf20Sopenharmony_ci	reg &= ~0xff;
928c2ecf20Sopenharmony_ci	reg |= (dri >> 8) & 0xff;
938c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPGDRI_U);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPGDRI_L);
968c2ecf20Sopenharmony_ci	reg &= ~0xff;
978c2ecf20Sopenharmony_ci	reg |= dri & 0xff;
988c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPGDRI_L);
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_civoid s5p_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	unsigned long reg;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPG_QTBL);
1068c2ecf20Sopenharmony_ci	reg &= ~S5P_QT_NUMt_MASK(t);
1078c2ecf20Sopenharmony_ci	reg |= (n << S5P_QT_NUMt_SHIFT(t)) & S5P_QT_NUMt_MASK(t);
1088c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPG_QTBL);
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_civoid s5p_jpeg_htbl_ac(void __iomem *regs, unsigned int t)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	unsigned long reg;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPG_HTBL);
1168c2ecf20Sopenharmony_ci	reg &= ~S5P_HT_NUMt_AC_MASK(t);
1178c2ecf20Sopenharmony_ci	/* this driver uses table 0 for all color components */
1188c2ecf20Sopenharmony_ci	reg |= (0 << S5P_HT_NUMt_AC_SHIFT(t)) & S5P_HT_NUMt_AC_MASK(t);
1198c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPG_HTBL);
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_civoid s5p_jpeg_htbl_dc(void __iomem *regs, unsigned int t)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	unsigned long reg;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPG_HTBL);
1278c2ecf20Sopenharmony_ci	reg &= ~S5P_HT_NUMt_DC_MASK(t);
1288c2ecf20Sopenharmony_ci	/* this driver uses table 0 for all color components */
1298c2ecf20Sopenharmony_ci	reg |= (0 << S5P_HT_NUMt_DC_SHIFT(t)) & S5P_HT_NUMt_DC_MASK(t);
1308c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPG_HTBL);
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_civoid s5p_jpeg_y(void __iomem *regs, unsigned int y)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	unsigned long reg;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPGY_U);
1388c2ecf20Sopenharmony_ci	reg &= ~0xff;
1398c2ecf20Sopenharmony_ci	reg |= (y >> 8) & 0xff;
1408c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPGY_U);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPGY_L);
1438c2ecf20Sopenharmony_ci	reg &= ~0xff;
1448c2ecf20Sopenharmony_ci	reg |= y & 0xff;
1458c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPGY_L);
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_civoid s5p_jpeg_x(void __iomem *regs, unsigned int x)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	unsigned long reg;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPGX_U);
1538c2ecf20Sopenharmony_ci	reg &= ~0xff;
1548c2ecf20Sopenharmony_ci	reg |= (x >> 8) & 0xff;
1558c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPGX_U);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPGX_L);
1588c2ecf20Sopenharmony_ci	reg &= ~0xff;
1598c2ecf20Sopenharmony_ci	reg |= x & 0xff;
1608c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPGX_L);
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_civoid s5p_jpeg_rst_int_enable(void __iomem *regs, bool enable)
1648c2ecf20Sopenharmony_ci{
1658c2ecf20Sopenharmony_ci	unsigned long reg;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPGINTSE);
1688c2ecf20Sopenharmony_ci	reg &= ~S5P_RSTm_INT_EN_MASK;
1698c2ecf20Sopenharmony_ci	if (enable)
1708c2ecf20Sopenharmony_ci		reg |= S5P_RSTm_INT_EN;
1718c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPGINTSE);
1728c2ecf20Sopenharmony_ci}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_civoid s5p_jpeg_data_num_int_enable(void __iomem *regs, bool enable)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	unsigned long reg;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPGINTSE);
1798c2ecf20Sopenharmony_ci	reg &= ~S5P_DATA_NUM_INT_EN_MASK;
1808c2ecf20Sopenharmony_ci	if (enable)
1818c2ecf20Sopenharmony_ci		reg |= S5P_DATA_NUM_INT_EN;
1828c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPGINTSE);
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_civoid s5p_jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	unsigned long reg;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPGINTSE);
1908c2ecf20Sopenharmony_ci	reg &= ~S5P_FINAL_MCU_NUM_INT_EN_MASK;
1918c2ecf20Sopenharmony_ci	if (enbl)
1928c2ecf20Sopenharmony_ci		reg |= S5P_FINAL_MCU_NUM_INT_EN;
1938c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPGINTSE);
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ciint s5p_jpeg_timer_stat(void __iomem *regs)
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	return (int)((readl(regs + S5P_JPG_TIMER_ST) & S5P_TIMER_INT_STAT_MASK)
1998c2ecf20Sopenharmony_ci		     >> S5P_TIMER_INT_STAT_SHIFT);
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_civoid s5p_jpeg_clear_timer_stat(void __iomem *regs)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	unsigned long reg;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPG_TIMER_SE);
2078c2ecf20Sopenharmony_ci	reg &= ~S5P_TIMER_INT_STAT_MASK;
2088c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPG_TIMER_SE);
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_civoid s5p_jpeg_enc_stream_int(void __iomem *regs, unsigned long size)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	unsigned long reg;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
2168c2ecf20Sopenharmony_ci	reg &= ~S5P_ENC_STREAM_BOUND_MASK;
2178c2ecf20Sopenharmony_ci	reg |= S5P_ENC_STREAM_INT_EN;
2188c2ecf20Sopenharmony_ci	reg |= size & S5P_ENC_STREAM_BOUND_MASK;
2198c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ciint s5p_jpeg_enc_stream_stat(void __iomem *regs)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	return (int)(readl(regs + S5P_JPG_ENC_STREAM_INTST) &
2258c2ecf20Sopenharmony_ci		     S5P_ENC_STREAM_INT_STAT_MASK);
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_civoid s5p_jpeg_clear_enc_stream_stat(void __iomem *regs)
2298c2ecf20Sopenharmony_ci{
2308c2ecf20Sopenharmony_ci	unsigned long reg;
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
2338c2ecf20Sopenharmony_ci	reg &= ~S5P_ENC_STREAM_INT_MASK;
2348c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
2358c2ecf20Sopenharmony_ci}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_civoid s5p_jpeg_outform_raw(void __iomem *regs, unsigned long format)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	unsigned long reg, f;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	f = S5P_DEC_OUT_FORMAT_422;
2428c2ecf20Sopenharmony_ci	if (format == S5P_JPEG_RAW_OUT_422)
2438c2ecf20Sopenharmony_ci		f = S5P_DEC_OUT_FORMAT_422;
2448c2ecf20Sopenharmony_ci	else if (format == S5P_JPEG_RAW_OUT_420)
2458c2ecf20Sopenharmony_ci		f = S5P_DEC_OUT_FORMAT_420;
2468c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPG_OUTFORM);
2478c2ecf20Sopenharmony_ci	reg &= ~S5P_DEC_OUT_FORMAT_MASK;
2488c2ecf20Sopenharmony_ci	reg |= f;
2498c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPG_OUTFORM);
2508c2ecf20Sopenharmony_ci}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_civoid s5p_jpeg_jpgadr(void __iomem *regs, unsigned long addr)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	writel(addr, regs + S5P_JPG_JPGADR);
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_civoid s5p_jpeg_imgadr(void __iomem *regs, unsigned long addr)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	writel(addr, regs + S5P_JPG_IMGADR);
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_civoid s5p_jpeg_coef(void __iomem *regs, unsigned int i,
2638c2ecf20Sopenharmony_ci			     unsigned int j, unsigned int coef)
2648c2ecf20Sopenharmony_ci{
2658c2ecf20Sopenharmony_ci	unsigned long reg;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	reg = readl(regs + S5P_JPG_COEF(i));
2688c2ecf20Sopenharmony_ci	reg &= ~S5P_COEFn_MASK(j);
2698c2ecf20Sopenharmony_ci	reg |= (coef << S5P_COEFn_SHIFT(j)) & S5P_COEFn_MASK(j);
2708c2ecf20Sopenharmony_ci	writel(reg, regs + S5P_JPG_COEF(i));
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_civoid s5p_jpeg_start(void __iomem *regs)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	writel(1, regs + S5P_JSTART);
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ciint s5p_jpeg_result_stat_ok(void __iomem *regs)
2798c2ecf20Sopenharmony_ci{
2808c2ecf20Sopenharmony_ci	return (int)((readl(regs + S5P_JPGINTST) & S5P_RESULT_STAT_MASK)
2818c2ecf20Sopenharmony_ci		     >> S5P_RESULT_STAT_SHIFT);
2828c2ecf20Sopenharmony_ci}
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ciint s5p_jpeg_stream_stat_ok(void __iomem *regs)
2858c2ecf20Sopenharmony_ci{
2868c2ecf20Sopenharmony_ci	return !(int)((readl(regs + S5P_JPGINTST) & S5P_STREAM_STAT_MASK)
2878c2ecf20Sopenharmony_ci		      >> S5P_STREAM_STAT_SHIFT);
2888c2ecf20Sopenharmony_ci}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_civoid s5p_jpeg_clear_int(void __iomem *regs)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	readl(regs + S5P_JPGINTST);
2938c2ecf20Sopenharmony_ci	writel(S5P_INT_RELEASE, regs + S5P_JPGCOM);
2948c2ecf20Sopenharmony_ci	readl(regs + S5P_JPGOPR);
2958c2ecf20Sopenharmony_ci}
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ciunsigned int s5p_jpeg_compressed_size(void __iomem *regs)
2988c2ecf20Sopenharmony_ci{
2998c2ecf20Sopenharmony_ci	unsigned long jpeg_size = 0;
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	jpeg_size |= (readl(regs + S5P_JPGCNT_U) & 0xff) << 16;
3028c2ecf20Sopenharmony_ci	jpeg_size |= (readl(regs + S5P_JPGCNT_M) & 0xff) << 8;
3038c2ecf20Sopenharmony_ci	jpeg_size |= (readl(regs + S5P_JPGCNT_L) & 0xff);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	return (unsigned int)jpeg_size;
3068c2ecf20Sopenharmony_ci}
307