1 // SPDX-License-Identifier: GPL-2.0-only
2 /* linux/drivers/media/platform/exynos3250-jpeg/jpeg-hw.h
3  *
4  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
5  *		http://www.samsung.com
6  *
7  * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
8  */
9 
10 #include <linux/io.h>
11 #include <linux/videodev2.h>
12 #include <linux/delay.h>
13 
14 #include "jpeg-core.h"
15 #include "jpeg-regs.h"
16 #include "jpeg-hw-exynos3250.h"
17 
18 void exynos3250_jpeg_reset(void __iomem *regs)
19 {
20 	u32 reg = 1;
21 	int count = 1000;
22 
23 	writel(1, regs + EXYNOS3250_SW_RESET);
24 	/* no other way but polling for when JPEG IP becomes operational */
25 	while (reg != 0 && --count > 0) {
26 		udelay(1);
27 		cpu_relax();
28 		reg = readl(regs + EXYNOS3250_SW_RESET);
29 	}
30 
31 	reg = 0;
32 	count = 1000;
33 
34 	while (reg != 1 && --count > 0) {
35 		writel(1, regs + EXYNOS3250_JPGDRI);
36 		udelay(1);
37 		cpu_relax();
38 		reg = readl(regs + EXYNOS3250_JPGDRI);
39 	}
40 
41 	writel(0, regs + EXYNOS3250_JPGDRI);
42 }
43 
44 void exynos3250_jpeg_poweron(void __iomem *regs)
45 {
46 	writel(EXYNOS3250_POWER_ON, regs + EXYNOS3250_JPGCLKCON);
47 }
48 
49 void exynos3250_jpeg_set_dma_num(void __iomem *regs)
50 {
51 	writel(((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_WDMA_ISSUE_NUM_SHIFT) &
52 			EXYNOS3250_WDMA_ISSUE_NUM_MASK) |
53 	       ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_RDMA_ISSUE_NUM_SHIFT) &
54 			EXYNOS3250_RDMA_ISSUE_NUM_MASK) |
55 	       ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_ISSUE_GATHER_NUM_SHIFT) &
56 			EXYNOS3250_ISSUE_GATHER_NUM_MASK),
57 		regs + EXYNOS3250_DMA_ISSUE_NUM);
58 }
59 
60 void exynos3250_jpeg_clk_set(void __iomem *base)
61 {
62 	u32 reg;
63 
64 	reg = readl(base + EXYNOS3250_JPGCMOD) & ~EXYNOS3250_HALF_EN_MASK;
65 
66 	writel(reg | EXYNOS3250_HALF_EN, base + EXYNOS3250_JPGCMOD);
67 }
68 
69 void exynos3250_jpeg_input_raw_fmt(void __iomem *regs, unsigned int fmt)
70 {
71 	u32 reg;
72 
73 	reg = readl(regs + EXYNOS3250_JPGCMOD) &
74 			EXYNOS3250_MODE_Y16_MASK;
75 
76 	switch (fmt) {
77 	case V4L2_PIX_FMT_RGB32:
78 		reg |= EXYNOS3250_MODE_SEL_ARGB8888;
79 		break;
80 	case V4L2_PIX_FMT_BGR32:
81 		reg |= EXYNOS3250_MODE_SEL_ARGB8888 | EXYNOS3250_SRC_SWAP_RGB;
82 		break;
83 	case V4L2_PIX_FMT_RGB565:
84 		reg |= EXYNOS3250_MODE_SEL_RGB565;
85 		break;
86 	case V4L2_PIX_FMT_RGB565X:
87 		reg |= EXYNOS3250_MODE_SEL_RGB565 | EXYNOS3250_SRC_SWAP_RGB;
88 		break;
89 	case V4L2_PIX_FMT_YUYV:
90 		reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR;
91 		break;
92 	case V4L2_PIX_FMT_YVYU:
93 		reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR |
94 			EXYNOS3250_SRC_SWAP_UV;
95 		break;
96 	case V4L2_PIX_FMT_UYVY:
97 		reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM;
98 		break;
99 	case V4L2_PIX_FMT_VYUY:
100 		reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM |
101 			EXYNOS3250_SRC_SWAP_UV;
102 		break;
103 	case V4L2_PIX_FMT_NV12:
104 		reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV12;
105 		break;
106 	case V4L2_PIX_FMT_NV21:
107 		reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV21;
108 		break;
109 	case V4L2_PIX_FMT_YUV420:
110 		reg |= EXYNOS3250_MODE_SEL_420_3P;
111 		break;
112 	default:
113 		break;
114 
115 	}
116 
117 	writel(reg, regs + EXYNOS3250_JPGCMOD);
118 }
119 
120 void exynos3250_jpeg_set_y16(void __iomem *regs, bool y16)
121 {
122 	u32 reg;
123 
124 	reg = readl(regs + EXYNOS3250_JPGCMOD);
125 	if (y16)
126 		reg |= EXYNOS3250_MODE_Y16;
127 	else
128 		reg &= ~EXYNOS3250_MODE_Y16_MASK;
129 	writel(reg, regs + EXYNOS3250_JPGCMOD);
130 }
131 
132 void exynos3250_jpeg_proc_mode(void __iomem *regs, unsigned int mode)
133 {
134 	u32 reg, m;
135 
136 	if (mode == S5P_JPEG_ENCODE)
137 		m = EXYNOS3250_PROC_MODE_COMPR;
138 	else
139 		m = EXYNOS3250_PROC_MODE_DECOMPR;
140 	reg = readl(regs + EXYNOS3250_JPGMOD);
141 	reg &= ~EXYNOS3250_PROC_MODE_MASK;
142 	reg |= m;
143 	writel(reg, regs + EXYNOS3250_JPGMOD);
144 }
145 
146 void exynos3250_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode)
147 {
148 	u32 reg, m = 0;
149 
150 	switch (mode) {
151 	case V4L2_JPEG_CHROMA_SUBSAMPLING_444:
152 		m = EXYNOS3250_SUBSAMPLING_MODE_444;
153 		break;
154 	case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
155 		m = EXYNOS3250_SUBSAMPLING_MODE_422;
156 		break;
157 	case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
158 		m = EXYNOS3250_SUBSAMPLING_MODE_420;
159 		break;
160 	}
161 
162 	reg = readl(regs + EXYNOS3250_JPGMOD);
163 	reg &= ~EXYNOS3250_SUBSAMPLING_MODE_MASK;
164 	reg |= m;
165 	writel(reg, regs + EXYNOS3250_JPGMOD);
166 }
167 
168 unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs)
169 {
170 	return readl(regs + EXYNOS3250_JPGMOD) &
171 				EXYNOS3250_SUBSAMPLING_MODE_MASK;
172 }
173 
174 void exynos3250_jpeg_dri(void __iomem *regs, unsigned int dri)
175 {
176 	u32 reg;
177 
178 	reg = dri & EXYNOS3250_JPGDRI_MASK;
179 	writel(reg, regs + EXYNOS3250_JPGDRI);
180 }
181 
182 void exynos3250_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
183 {
184 	unsigned long reg;
185 
186 	reg = readl(regs + EXYNOS3250_QHTBL);
187 	reg &= ~EXYNOS3250_QT_NUM_MASK(t);
188 	reg |= (n << EXYNOS3250_QT_NUM_SHIFT(t)) &
189 					EXYNOS3250_QT_NUM_MASK(t);
190 	writel(reg, regs + EXYNOS3250_QHTBL);
191 }
192 
193 void exynos3250_jpeg_htbl_ac(void __iomem *regs, unsigned int t)
194 {
195 	unsigned long reg;
196 
197 	reg = readl(regs + EXYNOS3250_QHTBL);
198 	reg &= ~EXYNOS3250_HT_NUM_AC_MASK(t);
199 	/* this driver uses table 0 for all color components */
200 	reg |= (0 << EXYNOS3250_HT_NUM_AC_SHIFT(t)) &
201 					EXYNOS3250_HT_NUM_AC_MASK(t);
202 	writel(reg, regs + EXYNOS3250_QHTBL);
203 }
204 
205 void exynos3250_jpeg_htbl_dc(void __iomem *regs, unsigned int t)
206 {
207 	unsigned long reg;
208 
209 	reg = readl(regs + EXYNOS3250_QHTBL);
210 	reg &= ~EXYNOS3250_HT_NUM_DC_MASK(t);
211 	/* this driver uses table 0 for all color components */
212 	reg |= (0 << EXYNOS3250_HT_NUM_DC_SHIFT(t)) &
213 					EXYNOS3250_HT_NUM_DC_MASK(t);
214 	writel(reg, regs + EXYNOS3250_QHTBL);
215 }
216 
217 void exynos3250_jpeg_set_y(void __iomem *regs, unsigned int y)
218 {
219 	u32 reg;
220 
221 	reg = y & EXYNOS3250_JPGY_MASK;
222 	writel(reg, regs + EXYNOS3250_JPGY);
223 }
224 
225 void exynos3250_jpeg_set_x(void __iomem *regs, unsigned int x)
226 {
227 	u32 reg;
228 
229 	reg = x & EXYNOS3250_JPGX_MASK;
230 	writel(reg, regs + EXYNOS3250_JPGX);
231 }
232 
233 #if 0	/* Currently unused */
234 unsigned int exynos3250_jpeg_get_y(void __iomem *regs)
235 {
236 	return readl(regs + EXYNOS3250_JPGY);
237 }
238 
239 unsigned int exynos3250_jpeg_get_x(void __iomem *regs)
240 {
241 	return readl(regs + EXYNOS3250_JPGX);
242 }
243 #endif
244 
245 void exynos3250_jpeg_interrupts_enable(void __iomem *regs)
246 {
247 	u32 reg;
248 
249 	reg = readl(regs + EXYNOS3250_JPGINTSE);
250 	reg |= (EXYNOS3250_JPEG_DONE_EN |
251 		EXYNOS3250_WDMA_DONE_EN |
252 		EXYNOS3250_RDMA_DONE_EN |
253 		EXYNOS3250_ENC_STREAM_INT_EN |
254 		EXYNOS3250_CORE_DONE_EN |
255 		EXYNOS3250_ERR_INT_EN |
256 		EXYNOS3250_HEAD_INT_EN);
257 	writel(reg, regs + EXYNOS3250_JPGINTSE);
258 }
259 
260 void exynos3250_jpeg_enc_stream_bound(void __iomem *regs, unsigned int size)
261 {
262 	u32 reg;
263 
264 	reg = size & EXYNOS3250_ENC_STREAM_BOUND_MASK;
265 	writel(reg, regs + EXYNOS3250_ENC_STREAM_BOUND);
266 }
267 
268 void exynos3250_jpeg_output_raw_fmt(void __iomem *regs, unsigned int fmt)
269 {
270 	u32 reg;
271 
272 	switch (fmt) {
273 	case V4L2_PIX_FMT_RGB32:
274 		reg = EXYNOS3250_OUT_FMT_ARGB8888;
275 		break;
276 	case V4L2_PIX_FMT_BGR32:
277 		reg = EXYNOS3250_OUT_FMT_ARGB8888 | EXYNOS3250_OUT_SWAP_RGB;
278 		break;
279 	case V4L2_PIX_FMT_RGB565:
280 		reg = EXYNOS3250_OUT_FMT_RGB565;
281 		break;
282 	case V4L2_PIX_FMT_RGB565X:
283 		reg = EXYNOS3250_OUT_FMT_RGB565 | EXYNOS3250_OUT_SWAP_RGB;
284 		break;
285 	case V4L2_PIX_FMT_YUYV:
286 		reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR;
287 		break;
288 	case V4L2_PIX_FMT_YVYU:
289 		reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR |
290 			EXYNOS3250_OUT_SWAP_UV;
291 		break;
292 	case V4L2_PIX_FMT_UYVY:
293 		reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM;
294 		break;
295 	case V4L2_PIX_FMT_VYUY:
296 		reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM |
297 			EXYNOS3250_OUT_SWAP_UV;
298 		break;
299 	case V4L2_PIX_FMT_NV12:
300 		reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV12;
301 		break;
302 	case V4L2_PIX_FMT_NV21:
303 		reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV21;
304 		break;
305 	case V4L2_PIX_FMT_YUV420:
306 		reg = EXYNOS3250_OUT_FMT_420_3P;
307 		break;
308 	default:
309 		reg = 0;
310 		break;
311 	}
312 
313 	writel(reg, regs + EXYNOS3250_OUTFORM);
314 }
315 
316 void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr)
317 {
318 	writel(addr, regs + EXYNOS3250_JPG_JPGADR);
319 }
320 
321 void exynos3250_jpeg_imgadr(void __iomem *regs, struct s5p_jpeg_addr *img_addr)
322 {
323 	writel(img_addr->y, regs + EXYNOS3250_LUMA_BASE);
324 	writel(img_addr->cb, regs + EXYNOS3250_CHROMA_BASE);
325 	writel(img_addr->cr, regs + EXYNOS3250_CHROMA_CR_BASE);
326 }
327 
328 void exynos3250_jpeg_stride(void __iomem *regs, unsigned int img_fmt,
329 			    unsigned int width)
330 {
331 	u32 reg_luma = 0, reg_cr = 0, reg_cb = 0;
332 
333 	switch (img_fmt) {
334 	case V4L2_PIX_FMT_RGB32:
335 		reg_luma = 4 * width;
336 		break;
337 	case V4L2_PIX_FMT_RGB565:
338 	case V4L2_PIX_FMT_RGB565X:
339 	case V4L2_PIX_FMT_YUYV:
340 	case V4L2_PIX_FMT_YVYU:
341 	case V4L2_PIX_FMT_UYVY:
342 	case V4L2_PIX_FMT_VYUY:
343 		reg_luma = 2 * width;
344 		break;
345 	case V4L2_PIX_FMT_NV12:
346 	case V4L2_PIX_FMT_NV21:
347 		reg_luma = width;
348 		reg_cb = reg_luma;
349 		break;
350 	case V4L2_PIX_FMT_YUV420:
351 		reg_luma = width;
352 		reg_cb = reg_cr = reg_luma / 2;
353 		break;
354 	default:
355 		break;
356 	}
357 
358 	writel(reg_luma, regs + EXYNOS3250_LUMA_STRIDE);
359 	writel(reg_cb, regs + EXYNOS3250_CHROMA_STRIDE);
360 	writel(reg_cr, regs + EXYNOS3250_CHROMA_CR_STRIDE);
361 }
362 
363 void exynos3250_jpeg_offset(void __iomem *regs, unsigned int x_offset,
364 				unsigned int y_offset)
365 {
366 	u32 reg;
367 
368 	reg = (y_offset << EXYNOS3250_LUMA_YY_OFFSET_SHIFT) &
369 			EXYNOS3250_LUMA_YY_OFFSET_MASK;
370 	reg |= (x_offset << EXYNOS3250_LUMA_YX_OFFSET_SHIFT) &
371 			EXYNOS3250_LUMA_YX_OFFSET_MASK;
372 
373 	writel(reg, regs + EXYNOS3250_LUMA_XY_OFFSET);
374 
375 	reg = (y_offset << EXYNOS3250_CHROMA_YY_OFFSET_SHIFT) &
376 			EXYNOS3250_CHROMA_YY_OFFSET_MASK;
377 	reg |= (x_offset << EXYNOS3250_CHROMA_YX_OFFSET_SHIFT) &
378 			EXYNOS3250_CHROMA_YX_OFFSET_MASK;
379 
380 	writel(reg, regs + EXYNOS3250_CHROMA_XY_OFFSET);
381 
382 	reg = (y_offset << EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT) &
383 			EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK;
384 	reg |= (x_offset << EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT) &
385 			EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK;
386 
387 	writel(reg, regs + EXYNOS3250_CHROMA_CR_XY_OFFSET);
388 }
389 
390 void exynos3250_jpeg_coef(void __iomem *base, unsigned int mode)
391 {
392 	if (mode == S5P_JPEG_ENCODE) {
393 		writel(EXYNOS3250_JPEG_ENC_COEF1,
394 					base + EXYNOS3250_JPG_COEF(1));
395 		writel(EXYNOS3250_JPEG_ENC_COEF2,
396 					base + EXYNOS3250_JPG_COEF(2));
397 		writel(EXYNOS3250_JPEG_ENC_COEF3,
398 					base + EXYNOS3250_JPG_COEF(3));
399 	} else {
400 		writel(EXYNOS3250_JPEG_DEC_COEF1,
401 					base + EXYNOS3250_JPG_COEF(1));
402 		writel(EXYNOS3250_JPEG_DEC_COEF2,
403 					base + EXYNOS3250_JPG_COEF(2));
404 		writel(EXYNOS3250_JPEG_DEC_COEF3,
405 					base + EXYNOS3250_JPG_COEF(3));
406 	}
407 }
408 
409 void exynos3250_jpeg_start(void __iomem *regs)
410 {
411 	writel(1, regs + EXYNOS3250_JSTART);
412 }
413 
414 void exynos3250_jpeg_rstart(void __iomem *regs)
415 {
416 	writel(1, regs + EXYNOS3250_JRSTART);
417 }
418 
419 unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs)
420 {
421 	return readl(regs + EXYNOS3250_JPGINTST);
422 }
423 
424 void exynos3250_jpeg_clear_int_status(void __iomem *regs,
425 				      unsigned int value)
426 {
427 	writel(value, regs + EXYNOS3250_JPGINTST);
428 }
429 
430 unsigned int exynos3250_jpeg_operating(void __iomem *regs)
431 {
432 	return readl(regs + S5P_JPGOPR) & EXYNOS3250_JPGOPR_MASK;
433 }
434 
435 unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs)
436 {
437 	return readl(regs + EXYNOS3250_JPGCNT) & EXYNOS3250_JPGCNT_MASK;
438 }
439 
440 void exynos3250_jpeg_dec_stream_size(void __iomem *regs,
441 						unsigned int size)
442 {
443 	writel(size & EXYNOS3250_DEC_STREAM_MASK,
444 				regs + EXYNOS3250_DEC_STREAM_SIZE);
445 }
446 
447 void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs,
448 						unsigned int sratio)
449 {
450 	switch (sratio) {
451 	case 1:
452 	default:
453 		sratio = EXYNOS3250_DEC_SCALE_FACTOR_8_8;
454 		break;
455 	case 2:
456 		sratio = EXYNOS3250_DEC_SCALE_FACTOR_4_8;
457 		break;
458 	case 4:
459 		sratio = EXYNOS3250_DEC_SCALE_FACTOR_2_8;
460 		break;
461 	case 8:
462 		sratio = EXYNOS3250_DEC_SCALE_FACTOR_1_8;
463 		break;
464 	}
465 
466 	writel(sratio & EXYNOS3250_DEC_SCALE_FACTOR_MASK,
467 				regs + EXYNOS3250_DEC_SCALING_RATIO);
468 }
469 
470 void exynos3250_jpeg_set_timer(void __iomem *regs, unsigned int time_value)
471 {
472 	time_value &= EXYNOS3250_TIMER_INIT_MASK;
473 
474 	writel(EXYNOS3250_TIMER_INT_STAT | time_value,
475 					regs + EXYNOS3250_TIMER_SE);
476 }
477 
478 unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs)
479 {
480 	return readl(regs + EXYNOS3250_TIMER_ST);
481 }
482 
483 void exynos3250_jpeg_clear_timer_status(void __iomem *regs)
484 {
485 	writel(EXYNOS3250_TIMER_INT_STAT, regs + EXYNOS3250_TIMER_ST);
486 }
487