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
17void 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
30void s5p_jpeg_poweron(void __iomem *regs)
31{
32	writel(S5P_POWER_ON, regs + S5P_JPGCLKCON);
33}
34
35void 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
51void 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
66void 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
81unsigned int s5p_jpeg_get_subsampling_mode(void __iomem *regs)
82{
83	return readl(regs + S5P_JPGMOD) & S5P_SUBSAMPLING_MODE_MASK;
84}
85
86void 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
101void 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
111void 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
122void 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
133void 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
148void 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
163void 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
174void 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
185void 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
196int 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
202void 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
211void 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
222int 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
228void 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
237void 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
252void s5p_jpeg_jpgadr(void __iomem *regs, unsigned long addr)
253{
254	writel(addr, regs + S5P_JPG_JPGADR);
255}
256
257void s5p_jpeg_imgadr(void __iomem *regs, unsigned long addr)
258{
259	writel(addr, regs + S5P_JPG_IMGADR);
260}
261
262void 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
273void s5p_jpeg_start(void __iomem *regs)
274{
275	writel(1, regs + S5P_JSTART);
276}
277
278int 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
284int 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
290void 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
297unsigned 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