1/* linux/drivers/media/platform/s5p-jpeg/jpeg-hw.h
2 *
3 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4 *		http://www.samsung.com
5 *
6 * Author: Andrzej Pietrasiewicz <andrzej.p@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
16#include "jpeg-core.h"
17#include "jpeg-regs.h"
18#include "jpeg-hw-s5p.h"
19
20void s5p_jpeg_reset(void __iomem *regs)
21{
22	unsigned long reg;
23
24	writel(1, regs + S5P_JPG_SW_RESET);
25	reg = readl(regs + S5P_JPG_SW_RESET);
26	/* no other way but polling for when JPEG IP becomes operational */
27	while (reg != 0) {
28		cpu_relax();
29		reg = readl(regs + S5P_JPG_SW_RESET);
30	}
31}
32
33void s5p_jpeg_poweron(void __iomem *regs)
34{
35	writel(S5P_POWER_ON, regs + S5P_JPGCLKCON);
36}
37
38void s5p_jpeg_input_raw_mode(void __iomem *regs, unsigned long mode)
39{
40	unsigned long reg, m;
41
42	m = S5P_MOD_SEL_565;
43	if (mode == S5P_JPEG_RAW_IN_565)
44		m = S5P_MOD_SEL_565;
45	else if (mode == S5P_JPEG_RAW_IN_422)
46		m = S5P_MOD_SEL_422;
47
48	reg = readl(regs + S5P_JPGCMOD);
49	reg &= ~S5P_MOD_SEL_MASK;
50	reg |= m;
51	writel(reg, regs + S5P_JPGCMOD);
52}
53
54void s5p_jpeg_input_raw_y16(void __iomem *regs, bool y16)
55{
56	unsigned long reg;
57
58	reg = readl(regs + S5P_JPGCMOD);
59	if (y16)
60		reg |= S5P_MODE_Y16;
61	else
62		reg &= ~S5P_MODE_Y16_MASK;
63	writel(reg, regs + S5P_JPGCMOD);
64}
65
66void s5p_jpeg_proc_mode(void __iomem *regs, unsigned long mode)
67{
68	unsigned long reg, m;
69
70	m = S5P_PROC_MODE_DECOMPR;
71	if (mode == S5P_JPEG_ENCODE)
72		m = S5P_PROC_MODE_COMPR;
73	else
74		m = S5P_PROC_MODE_DECOMPR;
75	reg = readl(regs + S5P_JPGMOD);
76	reg &= ~S5P_PROC_MODE_MASK;
77	reg |= m;
78	writel(reg, regs + S5P_JPGMOD);
79}
80
81void s5p_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode)
82{
83	unsigned long reg, m;
84
85	if (mode == V4L2_JPEG_CHROMA_SUBSAMPLING_420)
86		m = S5P_SUBSAMPLING_MODE_420;
87	else
88		m = S5P_SUBSAMPLING_MODE_422;
89
90	reg = readl(regs + S5P_JPGMOD);
91	reg &= ~S5P_SUBSAMPLING_MODE_MASK;
92	reg |= m;
93	writel(reg, regs + S5P_JPGMOD);
94}
95
96unsigned int s5p_jpeg_get_subsampling_mode(void __iomem *regs)
97{
98	return readl(regs + S5P_JPGMOD) & S5P_SUBSAMPLING_MODE_MASK;
99}
100
101void s5p_jpeg_dri(void __iomem *regs, unsigned int dri)
102{
103	unsigned long reg;
104
105	reg = readl(regs + S5P_JPGDRI_U);
106	reg &= ~0xff;
107	reg |= (dri >> 8) & 0xff;
108	writel(reg, regs + S5P_JPGDRI_U);
109
110	reg = readl(regs + S5P_JPGDRI_L);
111	reg &= ~0xff;
112	reg |= dri & 0xff;
113	writel(reg, regs + S5P_JPGDRI_L);
114}
115
116void s5p_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
117{
118	unsigned long reg;
119
120	reg = readl(regs + S5P_JPG_QTBL);
121	reg &= ~S5P_QT_NUMt_MASK(t);
122	reg |= (n << S5P_QT_NUMt_SHIFT(t)) & S5P_QT_NUMt_MASK(t);
123	writel(reg, regs + S5P_JPG_QTBL);
124}
125
126void s5p_jpeg_htbl_ac(void __iomem *regs, unsigned int t)
127{
128	unsigned long reg;
129
130	reg = readl(regs + S5P_JPG_HTBL);
131	reg &= ~S5P_HT_NUMt_AC_MASK(t);
132	/* this driver uses table 0 for all color components */
133	reg |= (0 << S5P_HT_NUMt_AC_SHIFT(t)) & S5P_HT_NUMt_AC_MASK(t);
134	writel(reg, regs + S5P_JPG_HTBL);
135}
136
137void s5p_jpeg_htbl_dc(void __iomem *regs, unsigned int t)
138{
139	unsigned long reg;
140
141	reg = readl(regs + S5P_JPG_HTBL);
142	reg &= ~S5P_HT_NUMt_DC_MASK(t);
143	/* this driver uses table 0 for all color components */
144	reg |= (0 << S5P_HT_NUMt_DC_SHIFT(t)) & S5P_HT_NUMt_DC_MASK(t);
145	writel(reg, regs + S5P_JPG_HTBL);
146}
147
148void s5p_jpeg_y(void __iomem *regs, unsigned int y)
149{
150	unsigned long reg;
151
152	reg = readl(regs + S5P_JPGY_U);
153	reg &= ~0xff;
154	reg |= (y >> 8) & 0xff;
155	writel(reg, regs + S5P_JPGY_U);
156
157	reg = readl(regs + S5P_JPGY_L);
158	reg &= ~0xff;
159	reg |= y & 0xff;
160	writel(reg, regs + S5P_JPGY_L);
161}
162
163void s5p_jpeg_x(void __iomem *regs, unsigned int x)
164{
165	unsigned long reg;
166
167	reg = readl(regs + S5P_JPGX_U);
168	reg &= ~0xff;
169	reg |= (x >> 8) & 0xff;
170	writel(reg, regs + S5P_JPGX_U);
171
172	reg = readl(regs + S5P_JPGX_L);
173	reg &= ~0xff;
174	reg |= x & 0xff;
175	writel(reg, regs + S5P_JPGX_L);
176}
177
178void s5p_jpeg_rst_int_enable(void __iomem *regs, bool enable)
179{
180	unsigned long reg;
181
182	reg = readl(regs + S5P_JPGINTSE);
183	reg &= ~S5P_RSTm_INT_EN_MASK;
184	if (enable)
185		reg |= S5P_RSTm_INT_EN;
186	writel(reg, regs + S5P_JPGINTSE);
187}
188
189void s5p_jpeg_data_num_int_enable(void __iomem *regs, bool enable)
190{
191	unsigned long reg;
192
193	reg = readl(regs + S5P_JPGINTSE);
194	reg &= ~S5P_DATA_NUM_INT_EN_MASK;
195	if (enable)
196		reg |= S5P_DATA_NUM_INT_EN;
197	writel(reg, regs + S5P_JPGINTSE);
198}
199
200void s5p_jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl)
201{
202	unsigned long reg;
203
204	reg = readl(regs + S5P_JPGINTSE);
205	reg &= ~S5P_FINAL_MCU_NUM_INT_EN_MASK;
206	if (enbl)
207		reg |= S5P_FINAL_MCU_NUM_INT_EN;
208	writel(reg, regs + S5P_JPGINTSE);
209}
210
211void s5p_jpeg_timer_enable(void __iomem *regs, unsigned long val)
212{
213	unsigned long reg;
214
215	reg = readl(regs + S5P_JPG_TIMER_SE);
216	reg |= S5P_TIMER_INT_EN;
217	reg &= ~S5P_TIMER_INIT_MASK;
218	reg |= val & S5P_TIMER_INIT_MASK;
219	writel(reg, regs + S5P_JPG_TIMER_SE);
220}
221
222void s5p_jpeg_timer_disable(void __iomem *regs)
223{
224	unsigned long reg;
225
226	reg = readl(regs + S5P_JPG_TIMER_SE);
227	reg &= ~S5P_TIMER_INT_EN_MASK;
228	writel(reg, regs + S5P_JPG_TIMER_SE);
229}
230
231int s5p_jpeg_timer_stat(void __iomem *regs)
232{
233	return (int)((readl(regs + S5P_JPG_TIMER_ST) & S5P_TIMER_INT_STAT_MASK)
234		     >> S5P_TIMER_INT_STAT_SHIFT);
235}
236
237void s5p_jpeg_clear_timer_stat(void __iomem *regs)
238{
239	unsigned long reg;
240
241	reg = readl(regs + S5P_JPG_TIMER_SE);
242	reg &= ~S5P_TIMER_INT_STAT_MASK;
243	writel(reg, regs + S5P_JPG_TIMER_SE);
244}
245
246void s5p_jpeg_enc_stream_int(void __iomem *regs, unsigned long size)
247{
248	unsigned long reg;
249
250	reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
251	reg &= ~S5P_ENC_STREAM_BOUND_MASK;
252	reg |= S5P_ENC_STREAM_INT_EN;
253	reg |= size & S5P_ENC_STREAM_BOUND_MASK;
254	writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
255}
256
257int s5p_jpeg_enc_stream_stat(void __iomem *regs)
258{
259	return (int)(readl(regs + S5P_JPG_ENC_STREAM_INTST) &
260		     S5P_ENC_STREAM_INT_STAT_MASK);
261}
262
263void s5p_jpeg_clear_enc_stream_stat(void __iomem *regs)
264{
265	unsigned long reg;
266
267	reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
268	reg &= ~S5P_ENC_STREAM_INT_MASK;
269	writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
270}
271
272void s5p_jpeg_outform_raw(void __iomem *regs, unsigned long format)
273{
274	unsigned long reg, f;
275
276	f = S5P_DEC_OUT_FORMAT_422;
277	if (format == S5P_JPEG_RAW_OUT_422)
278		f = S5P_DEC_OUT_FORMAT_422;
279	else if (format == S5P_JPEG_RAW_OUT_420)
280		f = S5P_DEC_OUT_FORMAT_420;
281	reg = readl(regs + S5P_JPG_OUTFORM);
282	reg &= ~S5P_DEC_OUT_FORMAT_MASK;
283	reg |= f;
284	writel(reg, regs + S5P_JPG_OUTFORM);
285}
286
287void s5p_jpeg_jpgadr(void __iomem *regs, unsigned long addr)
288{
289	writel(addr, regs + S5P_JPG_JPGADR);
290}
291
292void s5p_jpeg_imgadr(void __iomem *regs, unsigned long addr)
293{
294	writel(addr, regs + S5P_JPG_IMGADR);
295}
296
297void s5p_jpeg_coef(void __iomem *regs, unsigned int i,
298			     unsigned int j, unsigned int coef)
299{
300	unsigned long reg;
301
302	reg = readl(regs + S5P_JPG_COEF(i));
303	reg &= ~S5P_COEFn_MASK(j);
304	reg |= (coef << S5P_COEFn_SHIFT(j)) & S5P_COEFn_MASK(j);
305	writel(reg, regs + S5P_JPG_COEF(i));
306}
307
308void s5p_jpeg_start(void __iomem *regs)
309{
310	writel(1, regs + S5P_JSTART);
311}
312
313int s5p_jpeg_result_stat_ok(void __iomem *regs)
314{
315	return (int)((readl(regs + S5P_JPGINTST) & S5P_RESULT_STAT_MASK)
316		     >> S5P_RESULT_STAT_SHIFT);
317}
318
319int s5p_jpeg_stream_stat_ok(void __iomem *regs)
320{
321	return !(int)((readl(regs + S5P_JPGINTST) & S5P_STREAM_STAT_MASK)
322		      >> S5P_STREAM_STAT_SHIFT);
323}
324
325void s5p_jpeg_clear_int(void __iomem *regs)
326{
327	readl(regs + S5P_JPGINTST);
328	writel(S5P_INT_RELEASE, regs + S5P_JPGCOM);
329	readl(regs + S5P_JPGOPR);
330}
331
332unsigned int s5p_jpeg_compressed_size(void __iomem *regs)
333{
334	unsigned long jpeg_size = 0;
335
336	jpeg_size |= (readl(regs + S5P_JPGCNT_U) & 0xff) << 16;
337	jpeg_size |= (readl(regs + S5P_JPGCNT_M) & 0xff) << 8;
338	jpeg_size |= (readl(regs + S5P_JPGCNT_L) & 0xff);
339
340	return (unsigned int)jpeg_size;
341}
342