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