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