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_proc_mode(void __iomem *regs, unsigned long mode)
55{
56	unsigned long reg, m;
57
58	m = S5P_PROC_MODE_DECOMPR;
59	if (mode == S5P_JPEG_ENCODE)
60		m = S5P_PROC_MODE_COMPR;
61	else
62		m = S5P_PROC_MODE_DECOMPR;
63	reg = readl(regs + S5P_JPGMOD);
64	reg &= ~S5P_PROC_MODE_MASK;
65	reg |= m;
66	writel(reg, regs + S5P_JPGMOD);
67}
68
69void s5p_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode)
70{
71	unsigned long reg, m;
72
73	if (mode == V4L2_JPEG_CHROMA_SUBSAMPLING_420)
74		m = S5P_SUBSAMPLING_MODE_420;
75	else
76		m = S5P_SUBSAMPLING_MODE_422;
77
78	reg = readl(regs + S5P_JPGMOD);
79	reg &= ~S5P_SUBSAMPLING_MODE_MASK;
80	reg |= m;
81	writel(reg, regs + S5P_JPGMOD);
82}
83
84unsigned int s5p_jpeg_get_subsampling_mode(void __iomem *regs)
85{
86	return readl(regs + S5P_JPGMOD) & S5P_SUBSAMPLING_MODE_MASK;
87}
88
89void s5p_jpeg_dri(void __iomem *regs, unsigned int dri)
90{
91	unsigned long reg;
92
93	reg = readl(regs + S5P_JPGDRI_U);
94	reg &= ~0xff;
95	reg |= (dri >> 8) & 0xff;
96	writel(reg, regs + S5P_JPGDRI_U);
97
98	reg = readl(regs + S5P_JPGDRI_L);
99	reg &= ~0xff;
100	reg |= dri & 0xff;
101	writel(reg, regs + S5P_JPGDRI_L);
102}
103
104void s5p_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
105{
106	unsigned long reg;
107
108	reg = readl(regs + S5P_JPG_QTBL);
109	reg &= ~S5P_QT_NUMt_MASK(t);
110	reg |= (n << S5P_QT_NUMt_SHIFT(t)) & S5P_QT_NUMt_MASK(t);
111	writel(reg, regs + S5P_JPG_QTBL);
112}
113
114void s5p_jpeg_htbl_ac(void __iomem *regs, unsigned int t)
115{
116	unsigned long reg;
117
118	reg = readl(regs + S5P_JPG_HTBL);
119	reg &= ~S5P_HT_NUMt_AC_MASK(t);
120	/* this driver uses table 0 for all color components */
121	reg |= (0 << S5P_HT_NUMt_AC_SHIFT(t)) & S5P_HT_NUMt_AC_MASK(t);
122	writel(reg, regs + S5P_JPG_HTBL);
123}
124
125void s5p_jpeg_htbl_dc(void __iomem *regs, unsigned int t)
126{
127	unsigned long reg;
128
129	reg = readl(regs + S5P_JPG_HTBL);
130	reg &= ~S5P_HT_NUMt_DC_MASK(t);
131	/* this driver uses table 0 for all color components */
132	reg |= (0 << S5P_HT_NUMt_DC_SHIFT(t)) & S5P_HT_NUMt_DC_MASK(t);
133	writel(reg, regs + S5P_JPG_HTBL);
134}
135
136void s5p_jpeg_y(void __iomem *regs, unsigned int y)
137{
138	unsigned long reg;
139
140	reg = readl(regs + S5P_JPGY_U);
141	reg &= ~0xff;
142	reg |= (y >> 8) & 0xff;
143	writel(reg, regs + S5P_JPGY_U);
144
145	reg = readl(regs + S5P_JPGY_L);
146	reg &= ~0xff;
147	reg |= y & 0xff;
148	writel(reg, regs + S5P_JPGY_L);
149}
150
151void s5p_jpeg_x(void __iomem *regs, unsigned int x)
152{
153	unsigned long reg;
154
155	reg = readl(regs + S5P_JPGX_U);
156	reg &= ~0xff;
157	reg |= (x >> 8) & 0xff;
158	writel(reg, regs + S5P_JPGX_U);
159
160	reg = readl(regs + S5P_JPGX_L);
161	reg &= ~0xff;
162	reg |= x & 0xff;
163	writel(reg, regs + S5P_JPGX_L);
164}
165
166void s5p_jpeg_rst_int_enable(void __iomem *regs, bool enable)
167{
168	unsigned long reg;
169
170	reg = readl(regs + S5P_JPGINTSE);
171	reg &= ~S5P_RSTm_INT_EN_MASK;
172	if (enable)
173		reg |= S5P_RSTm_INT_EN;
174	writel(reg, regs + S5P_JPGINTSE);
175}
176
177void s5p_jpeg_data_num_int_enable(void __iomem *regs, bool enable)
178{
179	unsigned long reg;
180
181	reg = readl(regs + S5P_JPGINTSE);
182	reg &= ~S5P_DATA_NUM_INT_EN_MASK;
183	if (enable)
184		reg |= S5P_DATA_NUM_INT_EN;
185	writel(reg, regs + S5P_JPGINTSE);
186}
187
188void s5p_jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl)
189{
190	unsigned long reg;
191
192	reg = readl(regs + S5P_JPGINTSE);
193	reg &= ~S5P_FINAL_MCU_NUM_INT_EN_MASK;
194	if (enbl)
195		reg |= S5P_FINAL_MCU_NUM_INT_EN;
196	writel(reg, regs + S5P_JPGINTSE);
197}
198
199int s5p_jpeg_timer_stat(void __iomem *regs)
200{
201	return (int)((readl(regs + S5P_JPG_TIMER_ST) & S5P_TIMER_INT_STAT_MASK)
202		     >> S5P_TIMER_INT_STAT_SHIFT);
203}
204
205void s5p_jpeg_clear_timer_stat(void __iomem *regs)
206{
207	unsigned long reg;
208
209	reg = readl(regs + S5P_JPG_TIMER_SE);
210	reg &= ~S5P_TIMER_INT_STAT_MASK;
211	writel(reg, regs + S5P_JPG_TIMER_SE);
212}
213
214void s5p_jpeg_enc_stream_int(void __iomem *regs, unsigned long size)
215{
216	unsigned long reg;
217
218	reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
219	reg &= ~S5P_ENC_STREAM_BOUND_MASK;
220	reg |= S5P_ENC_STREAM_INT_EN;
221	reg |= size & S5P_ENC_STREAM_BOUND_MASK;
222	writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
223}
224
225int s5p_jpeg_enc_stream_stat(void __iomem *regs)
226{
227	return (int)(readl(regs + S5P_JPG_ENC_STREAM_INTST) &
228		     S5P_ENC_STREAM_INT_STAT_MASK);
229}
230
231void s5p_jpeg_clear_enc_stream_stat(void __iomem *regs)
232{
233	unsigned long reg;
234
235	reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
236	reg &= ~S5P_ENC_STREAM_INT_MASK;
237	writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
238}
239
240void s5p_jpeg_outform_raw(void __iomem *regs, unsigned long format)
241{
242	unsigned long reg, f;
243
244	f = S5P_DEC_OUT_FORMAT_422;
245	if (format == S5P_JPEG_RAW_OUT_422)
246		f = S5P_DEC_OUT_FORMAT_422;
247	else if (format == S5P_JPEG_RAW_OUT_420)
248		f = S5P_DEC_OUT_FORMAT_420;
249	reg = readl(regs + S5P_JPG_OUTFORM);
250	reg &= ~S5P_DEC_OUT_FORMAT_MASK;
251	reg |= f;
252	writel(reg, regs + S5P_JPG_OUTFORM);
253}
254
255void s5p_jpeg_jpgadr(void __iomem *regs, unsigned long addr)
256{
257	writel(addr, regs + S5P_JPG_JPGADR);
258}
259
260void s5p_jpeg_imgadr(void __iomem *regs, unsigned long addr)
261{
262	writel(addr, regs + S5P_JPG_IMGADR);
263}
264
265void s5p_jpeg_coef(void __iomem *regs, unsigned int i,
266			     unsigned int j, unsigned int coef)
267{
268	unsigned long reg;
269
270	reg = readl(regs + S5P_JPG_COEF(i));
271	reg &= ~S5P_COEFn_MASK(j);
272	reg |= (coef << S5P_COEFn_SHIFT(j)) & S5P_COEFn_MASK(j);
273	writel(reg, regs + S5P_JPG_COEF(i));
274}
275
276void s5p_jpeg_start(void __iomem *regs)
277{
278	writel(1, regs + S5P_JSTART);
279}
280
281int s5p_jpeg_result_stat_ok(void __iomem *regs)
282{
283	return (int)((readl(regs + S5P_JPGINTST) & S5P_RESULT_STAT_MASK)
284		     >> S5P_RESULT_STAT_SHIFT);
285}
286
287int s5p_jpeg_stream_stat_ok(void __iomem *regs)
288{
289	return !(int)((readl(regs + S5P_JPGINTST) & S5P_STREAM_STAT_MASK)
290		      >> S5P_STREAM_STAT_SHIFT);
291}
292
293void s5p_jpeg_clear_int(void __iomem *regs)
294{
295	readl(regs + S5P_JPGINTST);
296	writel(S5P_INT_RELEASE, regs + S5P_JPGCOM);
297	readl(regs + S5P_JPGOPR);
298}
299
300unsigned int s5p_jpeg_compressed_size(void __iomem *regs)
301{
302	unsigned long jpeg_size = 0;
303
304	jpeg_size |= (readl(regs + S5P_JPGCNT_U) & 0xff) << 16;
305	jpeg_size |= (readl(regs + S5P_JPGCNT_M) & 0xff) << 8;
306	jpeg_size |= (readl(regs + S5P_JPGCNT_L) & 0xff);
307
308	return (unsigned int)jpeg_size;
309}
310