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