1 // SPDX-License-Identifier: GPL-2.0-only
2 /* linux/drivers/media/platform/s5p-jpeg/jpeg-hw.h
3  *
4  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
5  *		http://www.samsung.com
6  *
7  * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
8  */
9 
10 #include <linux/io.h>
11 #include <linux/videodev2.h>
12 
13 #include "jpeg-core.h"
14 #include "jpeg-regs.h"
15 #include "jpeg-hw-s5p.h"
16 
s5p_jpeg_reset(void __iomem * regs)17 void s5p_jpeg_reset(void __iomem *regs)
18 {
19 	unsigned long reg;
20 
21 	writel(1, regs + S5P_JPG_SW_RESET);
22 	reg = readl(regs + S5P_JPG_SW_RESET);
23 	/* no other way but polling for when JPEG IP becomes operational */
24 	while (reg != 0) {
25 		cpu_relax();
26 		reg = readl(regs + S5P_JPG_SW_RESET);
27 	}
28 }
29 
s5p_jpeg_poweron(void __iomem * regs)30 void s5p_jpeg_poweron(void __iomem *regs)
31 {
32 	writel(S5P_POWER_ON, regs + S5P_JPGCLKCON);
33 }
34 
s5p_jpeg_input_raw_mode(void __iomem * regs,unsigned long mode)35 void s5p_jpeg_input_raw_mode(void __iomem *regs, unsigned long mode)
36 {
37 	unsigned long reg, m;
38 
39 	m = S5P_MOD_SEL_565;
40 	if (mode == S5P_JPEG_RAW_IN_565)
41 		m = S5P_MOD_SEL_565;
42 	else if (mode == S5P_JPEG_RAW_IN_422)
43 		m = S5P_MOD_SEL_422;
44 
45 	reg = readl(regs + S5P_JPGCMOD);
46 	reg &= ~S5P_MOD_SEL_MASK;
47 	reg |= m;
48 	writel(reg, regs + S5P_JPGCMOD);
49 }
50 
s5p_jpeg_proc_mode(void __iomem * regs,unsigned long mode)51 void s5p_jpeg_proc_mode(void __iomem *regs, unsigned long mode)
52 {
53 	unsigned long reg, m;
54 
55 	m = S5P_PROC_MODE_DECOMPR;
56 	if (mode == S5P_JPEG_ENCODE)
57 		m = S5P_PROC_MODE_COMPR;
58 	else
59 		m = S5P_PROC_MODE_DECOMPR;
60 	reg = readl(regs + S5P_JPGMOD);
61 	reg &= ~S5P_PROC_MODE_MASK;
62 	reg |= m;
63 	writel(reg, regs + S5P_JPGMOD);
64 }
65 
s5p_jpeg_subsampling_mode(void __iomem * regs,unsigned int mode)66 void s5p_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode)
67 {
68 	unsigned long reg, m;
69 
70 	if (mode == V4L2_JPEG_CHROMA_SUBSAMPLING_420)
71 		m = S5P_SUBSAMPLING_MODE_420;
72 	else
73 		m = S5P_SUBSAMPLING_MODE_422;
74 
75 	reg = readl(regs + S5P_JPGMOD);
76 	reg &= ~S5P_SUBSAMPLING_MODE_MASK;
77 	reg |= m;
78 	writel(reg, regs + S5P_JPGMOD);
79 }
80 
s5p_jpeg_get_subsampling_mode(void __iomem * regs)81 unsigned int s5p_jpeg_get_subsampling_mode(void __iomem *regs)
82 {
83 	return readl(regs + S5P_JPGMOD) & S5P_SUBSAMPLING_MODE_MASK;
84 }
85 
s5p_jpeg_dri(void __iomem * regs,unsigned int dri)86 void s5p_jpeg_dri(void __iomem *regs, unsigned int dri)
87 {
88 	unsigned long reg;
89 
90 	reg = readl(regs + S5P_JPGDRI_U);
91 	reg &= ~0xff;
92 	reg |= (dri >> 8) & 0xff;
93 	writel(reg, regs + S5P_JPGDRI_U);
94 
95 	reg = readl(regs + S5P_JPGDRI_L);
96 	reg &= ~0xff;
97 	reg |= dri & 0xff;
98 	writel(reg, regs + S5P_JPGDRI_L);
99 }
100 
s5p_jpeg_qtbl(void __iomem * regs,unsigned int t,unsigned int n)101 void s5p_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
102 {
103 	unsigned long reg;
104 
105 	reg = readl(regs + S5P_JPG_QTBL);
106 	reg &= ~S5P_QT_NUMt_MASK(t);
107 	reg |= (n << S5P_QT_NUMt_SHIFT(t)) & S5P_QT_NUMt_MASK(t);
108 	writel(reg, regs + S5P_JPG_QTBL);
109 }
110 
s5p_jpeg_htbl_ac(void __iomem * regs,unsigned int t)111 void s5p_jpeg_htbl_ac(void __iomem *regs, unsigned int t)
112 {
113 	unsigned long reg;
114 
115 	reg = readl(regs + S5P_JPG_HTBL);
116 	reg &= ~S5P_HT_NUMt_AC_MASK(t);
117 	/* this driver uses table 0 for all color components */
118 	reg |= (0 << S5P_HT_NUMt_AC_SHIFT(t)) & S5P_HT_NUMt_AC_MASK(t);
119 	writel(reg, regs + S5P_JPG_HTBL);
120 }
121 
s5p_jpeg_htbl_dc(void __iomem * regs,unsigned int t)122 void s5p_jpeg_htbl_dc(void __iomem *regs, unsigned int t)
123 {
124 	unsigned long reg;
125 
126 	reg = readl(regs + S5P_JPG_HTBL);
127 	reg &= ~S5P_HT_NUMt_DC_MASK(t);
128 	/* this driver uses table 0 for all color components */
129 	reg |= (0 << S5P_HT_NUMt_DC_SHIFT(t)) & S5P_HT_NUMt_DC_MASK(t);
130 	writel(reg, regs + S5P_JPG_HTBL);
131 }
132 
s5p_jpeg_y(void __iomem * regs,unsigned int y)133 void s5p_jpeg_y(void __iomem *regs, unsigned int y)
134 {
135 	unsigned long reg;
136 
137 	reg = readl(regs + S5P_JPGY_U);
138 	reg &= ~0xff;
139 	reg |= (y >> 8) & 0xff;
140 	writel(reg, regs + S5P_JPGY_U);
141 
142 	reg = readl(regs + S5P_JPGY_L);
143 	reg &= ~0xff;
144 	reg |= y & 0xff;
145 	writel(reg, regs + S5P_JPGY_L);
146 }
147 
s5p_jpeg_x(void __iomem * regs,unsigned int x)148 void s5p_jpeg_x(void __iomem *regs, unsigned int x)
149 {
150 	unsigned long reg;
151 
152 	reg = readl(regs + S5P_JPGX_U);
153 	reg &= ~0xff;
154 	reg |= (x >> 8) & 0xff;
155 	writel(reg, regs + S5P_JPGX_U);
156 
157 	reg = readl(regs + S5P_JPGX_L);
158 	reg &= ~0xff;
159 	reg |= x & 0xff;
160 	writel(reg, regs + S5P_JPGX_L);
161 }
162 
s5p_jpeg_rst_int_enable(void __iomem * regs,bool enable)163 void s5p_jpeg_rst_int_enable(void __iomem *regs, bool enable)
164 {
165 	unsigned long reg;
166 
167 	reg = readl(regs + S5P_JPGINTSE);
168 	reg &= ~S5P_RSTm_INT_EN_MASK;
169 	if (enable)
170 		reg |= S5P_RSTm_INT_EN;
171 	writel(reg, regs + S5P_JPGINTSE);
172 }
173 
s5p_jpeg_data_num_int_enable(void __iomem * regs,bool enable)174 void s5p_jpeg_data_num_int_enable(void __iomem *regs, bool enable)
175 {
176 	unsigned long reg;
177 
178 	reg = readl(regs + S5P_JPGINTSE);
179 	reg &= ~S5P_DATA_NUM_INT_EN_MASK;
180 	if (enable)
181 		reg |= S5P_DATA_NUM_INT_EN;
182 	writel(reg, regs + S5P_JPGINTSE);
183 }
184 
s5p_jpeg_final_mcu_num_int_enable(void __iomem * regs,bool enbl)185 void s5p_jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl)
186 {
187 	unsigned long reg;
188 
189 	reg = readl(regs + S5P_JPGINTSE);
190 	reg &= ~S5P_FINAL_MCU_NUM_INT_EN_MASK;
191 	if (enbl)
192 		reg |= S5P_FINAL_MCU_NUM_INT_EN;
193 	writel(reg, regs + S5P_JPGINTSE);
194 }
195 
s5p_jpeg_timer_stat(void __iomem * regs)196 int s5p_jpeg_timer_stat(void __iomem *regs)
197 {
198 	return (int)((readl(regs + S5P_JPG_TIMER_ST) & S5P_TIMER_INT_STAT_MASK)
199 		     >> S5P_TIMER_INT_STAT_SHIFT);
200 }
201 
s5p_jpeg_clear_timer_stat(void __iomem * regs)202 void s5p_jpeg_clear_timer_stat(void __iomem *regs)
203 {
204 	unsigned long reg;
205 
206 	reg = readl(regs + S5P_JPG_TIMER_SE);
207 	reg &= ~S5P_TIMER_INT_STAT_MASK;
208 	writel(reg, regs + S5P_JPG_TIMER_SE);
209 }
210 
s5p_jpeg_enc_stream_int(void __iomem * regs,unsigned long size)211 void s5p_jpeg_enc_stream_int(void __iomem *regs, unsigned long size)
212 {
213 	unsigned long reg;
214 
215 	reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
216 	reg &= ~S5P_ENC_STREAM_BOUND_MASK;
217 	reg |= S5P_ENC_STREAM_INT_EN;
218 	reg |= size & S5P_ENC_STREAM_BOUND_MASK;
219 	writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
220 }
221 
s5p_jpeg_enc_stream_stat(void __iomem * regs)222 int s5p_jpeg_enc_stream_stat(void __iomem *regs)
223 {
224 	return (int)(readl(regs + S5P_JPG_ENC_STREAM_INTST) &
225 		     S5P_ENC_STREAM_INT_STAT_MASK);
226 }
227 
s5p_jpeg_clear_enc_stream_stat(void __iomem * regs)228 void s5p_jpeg_clear_enc_stream_stat(void __iomem *regs)
229 {
230 	unsigned long reg;
231 
232 	reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
233 	reg &= ~S5P_ENC_STREAM_INT_MASK;
234 	writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
235 }
236 
s5p_jpeg_outform_raw(void __iomem * regs,unsigned long format)237 void s5p_jpeg_outform_raw(void __iomem *regs, unsigned long format)
238 {
239 	unsigned long reg, f;
240 
241 	f = S5P_DEC_OUT_FORMAT_422;
242 	if (format == S5P_JPEG_RAW_OUT_422)
243 		f = S5P_DEC_OUT_FORMAT_422;
244 	else if (format == S5P_JPEG_RAW_OUT_420)
245 		f = S5P_DEC_OUT_FORMAT_420;
246 	reg = readl(regs + S5P_JPG_OUTFORM);
247 	reg &= ~S5P_DEC_OUT_FORMAT_MASK;
248 	reg |= f;
249 	writel(reg, regs + S5P_JPG_OUTFORM);
250 }
251 
s5p_jpeg_jpgadr(void __iomem * regs,unsigned long addr)252 void s5p_jpeg_jpgadr(void __iomem *regs, unsigned long addr)
253 {
254 	writel(addr, regs + S5P_JPG_JPGADR);
255 }
256 
s5p_jpeg_imgadr(void __iomem * regs,unsigned long addr)257 void s5p_jpeg_imgadr(void __iomem *regs, unsigned long addr)
258 {
259 	writel(addr, regs + S5P_JPG_IMGADR);
260 }
261 
s5p_jpeg_coef(void __iomem * regs,unsigned int i,unsigned int j,unsigned int coef)262 void s5p_jpeg_coef(void __iomem *regs, unsigned int i,
263 			     unsigned int j, unsigned int coef)
264 {
265 	unsigned long reg;
266 
267 	reg = readl(regs + S5P_JPG_COEF(i));
268 	reg &= ~S5P_COEFn_MASK(j);
269 	reg |= (coef << S5P_COEFn_SHIFT(j)) & S5P_COEFn_MASK(j);
270 	writel(reg, regs + S5P_JPG_COEF(i));
271 }
272 
s5p_jpeg_start(void __iomem * regs)273 void s5p_jpeg_start(void __iomem *regs)
274 {
275 	writel(1, regs + S5P_JSTART);
276 }
277 
s5p_jpeg_result_stat_ok(void __iomem * regs)278 int s5p_jpeg_result_stat_ok(void __iomem *regs)
279 {
280 	return (int)((readl(regs + S5P_JPGINTST) & S5P_RESULT_STAT_MASK)
281 		     >> S5P_RESULT_STAT_SHIFT);
282 }
283 
s5p_jpeg_stream_stat_ok(void __iomem * regs)284 int s5p_jpeg_stream_stat_ok(void __iomem *regs)
285 {
286 	return !(int)((readl(regs + S5P_JPGINTST) & S5P_STREAM_STAT_MASK)
287 		      >> S5P_STREAM_STAT_SHIFT);
288 }
289 
s5p_jpeg_clear_int(void __iomem * regs)290 void s5p_jpeg_clear_int(void __iomem *regs)
291 {
292 	readl(regs + S5P_JPGINTST);
293 	writel(S5P_INT_RELEASE, regs + S5P_JPGCOM);
294 	readl(regs + S5P_JPGOPR);
295 }
296 
s5p_jpeg_compressed_size(void __iomem * regs)297 unsigned int s5p_jpeg_compressed_size(void __iomem *regs)
298 {
299 	unsigned long jpeg_size = 0;
300 
301 	jpeg_size |= (readl(regs + S5P_JPGCNT_U) & 0xff) << 16;
302 	jpeg_size |= (readl(regs + S5P_JPGCNT_M) & 0xff) << 8;
303 	jpeg_size |= (readl(regs + S5P_JPGCNT_L) & 0xff);
304 
305 	return (unsigned int)jpeg_size;
306 }
307