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
18void 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
44void exynos3250_jpeg_poweron(void __iomem *regs)
45{
46	writel(EXYNOS3250_POWER_ON, regs + EXYNOS3250_JPGCLKCON);
47}
48
49void 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
60void 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
69void 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
120void 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
132void 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
146void 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
168unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs)
169{
170	return readl(regs + EXYNOS3250_JPGMOD) &
171				EXYNOS3250_SUBSAMPLING_MODE_MASK;
172}
173
174void 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
182void 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
193void 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
205void 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
217void 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
225void 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 */
234unsigned int exynos3250_jpeg_get_y(void __iomem *regs)
235{
236	return readl(regs + EXYNOS3250_JPGY);
237}
238
239unsigned int exynos3250_jpeg_get_x(void __iomem *regs)
240{
241	return readl(regs + EXYNOS3250_JPGX);
242}
243#endif
244
245void 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
260void 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
268void 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
316void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr)
317{
318	writel(addr, regs + EXYNOS3250_JPG_JPGADR);
319}
320
321void 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
328void 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
363void 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
390void 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
409void exynos3250_jpeg_start(void __iomem *regs)
410{
411	writel(1, regs + EXYNOS3250_JSTART);
412}
413
414void exynos3250_jpeg_rstart(void __iomem *regs)
415{
416	writel(1, regs + EXYNOS3250_JRSTART);
417}
418
419unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs)
420{
421	return readl(regs + EXYNOS3250_JPGINTST);
422}
423
424void exynos3250_jpeg_clear_int_status(void __iomem *regs,
425				      unsigned int value)
426{
427	writel(value, regs + EXYNOS3250_JPGINTST);
428}
429
430unsigned int exynos3250_jpeg_operating(void __iomem *regs)
431{
432	return readl(regs + S5P_JPGOPR) & EXYNOS3250_JPGOPR_MASK;
433}
434
435unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs)
436{
437	return readl(regs + EXYNOS3250_JPGCNT) & EXYNOS3250_JPGCNT_MASK;
438}
439
440void 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
447void 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
470void 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
478unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs)
479{
480	return readl(regs + EXYNOS3250_TIMER_ST);
481}
482
483void exynos3250_jpeg_clear_timer_status(void __iomem *regs)
484{
485	writel(EXYNOS3250_TIMER_INT_STAT, regs + EXYNOS3250_TIMER_ST);
486}
487