Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / media / platform / exynos-gsc / gsc-regs.c
1 /*
2  * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
3  *              http://www.samsung.com
4  *
5  * Samsung EXYNOS5 SoC series G-Scaler driver
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published
9  * by the Free Software Foundation, either version 2 of the License,
10  * or (at your option) any later version.
11  */
12
13 #include <linux/io.h>
14 #include <linux/delay.h>
15
16 #include "gsc-core.h"
17
18 void gsc_hw_set_sw_reset(struct gsc_dev *dev)
19 {
20         writel(GSC_SW_RESET_SRESET, dev->regs + GSC_SW_RESET);
21 }
22
23 int gsc_wait_reset(struct gsc_dev *dev)
24 {
25         unsigned long end = jiffies + msecs_to_jiffies(50);
26         u32 cfg;
27
28         while (time_before(jiffies, end)) {
29                 cfg = readl(dev->regs + GSC_SW_RESET);
30                 if (!cfg)
31                         return 0;
32                 usleep_range(10, 20);
33         }
34
35         return -EBUSY;
36 }
37
38 void gsc_hw_set_frm_done_irq_mask(struct gsc_dev *dev, bool mask)
39 {
40         u32 cfg;
41
42         cfg = readl(dev->regs + GSC_IRQ);
43         if (mask)
44                 cfg |= GSC_IRQ_FRMDONE_MASK;
45         else
46                 cfg &= ~GSC_IRQ_FRMDONE_MASK;
47         writel(cfg, dev->regs + GSC_IRQ);
48 }
49
50 void gsc_hw_set_gsc_irq_enable(struct gsc_dev *dev, bool mask)
51 {
52         u32 cfg;
53
54         cfg = readl(dev->regs + GSC_IRQ);
55         if (mask)
56                 cfg |= GSC_IRQ_ENABLE;
57         else
58                 cfg &= ~GSC_IRQ_ENABLE;
59         writel(cfg, dev->regs + GSC_IRQ);
60 }
61
62 void gsc_hw_set_input_buf_masking(struct gsc_dev *dev, u32 shift,
63                                 bool enable)
64 {
65         u32 cfg = readl(dev->regs + GSC_IN_BASE_ADDR_Y_MASK);
66         u32 mask = 1 << shift;
67
68         cfg &= ~mask;
69         cfg |= enable << shift;
70
71         writel(cfg, dev->regs + GSC_IN_BASE_ADDR_Y_MASK);
72         writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CB_MASK);
73         writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CR_MASK);
74 }
75
76 void gsc_hw_set_output_buf_masking(struct gsc_dev *dev, u32 shift,
77                                 bool enable)
78 {
79         u32 cfg = readl(dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);
80         u32 mask = 1 << shift;
81
82         cfg &= ~mask;
83         cfg |= enable << shift;
84
85         writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);
86         writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CB_MASK);
87         writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CR_MASK);
88 }
89
90 void gsc_hw_set_input_addr(struct gsc_dev *dev, struct gsc_addr *addr,
91                                 int index)
92 {
93         pr_debug("src_buf[%d]: %pad, cb: %pad, cr: %pad", index,
94                         &addr->y, &addr->cb, &addr->cr);
95         writel(addr->y, dev->regs + GSC_IN_BASE_ADDR_Y(index));
96         writel(addr->cb, dev->regs + GSC_IN_BASE_ADDR_CB(index));
97         writel(addr->cr, dev->regs + GSC_IN_BASE_ADDR_CR(index));
98
99 }
100
101 void gsc_hw_set_output_addr(struct gsc_dev *dev,
102                              struct gsc_addr *addr, int index)
103 {
104         pr_debug("dst_buf[%d]: %pad, cb: %pad, cr: %pad",
105                         index, &addr->y, &addr->cb, &addr->cr);
106         writel(addr->y, dev->regs + GSC_OUT_BASE_ADDR_Y(index));
107         writel(addr->cb, dev->regs + GSC_OUT_BASE_ADDR_CB(index));
108         writel(addr->cr, dev->regs + GSC_OUT_BASE_ADDR_CR(index));
109 }
110
111 void gsc_hw_set_input_path(struct gsc_ctx *ctx)
112 {
113         struct gsc_dev *dev = ctx->gsc_dev;
114
115         u32 cfg = readl(dev->regs + GSC_IN_CON);
116         cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK);
117
118         if (ctx->in_path == GSC_DMA)
119                 cfg |= GSC_IN_PATH_MEMORY;
120
121         writel(cfg, dev->regs + GSC_IN_CON);
122 }
123
124 void gsc_hw_set_in_size(struct gsc_ctx *ctx)
125 {
126         struct gsc_dev *dev = ctx->gsc_dev;
127         struct gsc_frame *frame = &ctx->s_frame;
128         u32 cfg;
129
130         /* Set input pixel offset */
131         cfg = GSC_SRCIMG_OFFSET_X(frame->crop.left);
132         cfg |= GSC_SRCIMG_OFFSET_Y(frame->crop.top);
133         writel(cfg, dev->regs + GSC_SRCIMG_OFFSET);
134
135         /* Set input original size */
136         cfg = GSC_SRCIMG_WIDTH(frame->f_width);
137         cfg |= GSC_SRCIMG_HEIGHT(frame->f_height);
138         writel(cfg, dev->regs + GSC_SRCIMG_SIZE);
139
140         /* Set input cropped size */
141         cfg = GSC_CROPPED_WIDTH(frame->crop.width);
142         cfg |= GSC_CROPPED_HEIGHT(frame->crop.height);
143         writel(cfg, dev->regs + GSC_CROPPED_SIZE);
144 }
145
146 void gsc_hw_set_in_image_rgb(struct gsc_ctx *ctx)
147 {
148         struct gsc_dev *dev = ctx->gsc_dev;
149         struct gsc_frame *frame = &ctx->s_frame;
150         u32 cfg;
151
152         cfg = readl(dev->regs + GSC_IN_CON);
153         if (frame->colorspace == V4L2_COLORSPACE_REC709)
154                 cfg |= GSC_IN_RGB_HD_WIDE;
155         else
156                 cfg |= GSC_IN_RGB_SD_WIDE;
157
158         if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)
159                 cfg |= GSC_IN_RGB565;
160         else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)
161                 cfg |= GSC_IN_XRGB8888;
162
163         writel(cfg, dev->regs + GSC_IN_CON);
164 }
165
166 void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
167 {
168         struct gsc_dev *dev = ctx->gsc_dev;
169         struct gsc_frame *frame = &ctx->s_frame;
170         u32 i, depth = 0;
171         u32 cfg;
172
173         cfg = readl(dev->regs + GSC_IN_CON);
174         cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK |
175                  GSC_IN_CHROMA_ORDER_MASK | GSC_IN_FORMAT_MASK |
176                  GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);
177         writel(cfg, dev->regs + GSC_IN_CON);
178
179         if (is_rgb(frame->fmt->color)) {
180                 gsc_hw_set_in_image_rgb(ctx);
181                 return;
182         }
183         for (i = 0; i < frame->fmt->num_planes; i++)
184                 depth += frame->fmt->depth[i];
185
186         switch (frame->fmt->num_comp) {
187         case 1:
188                 cfg |= GSC_IN_YUV422_1P;
189                 if (frame->fmt->yorder == GSC_LSB_Y)
190                         cfg |= GSC_IN_YUV422_1P_ORDER_LSB_Y;
191                 else
192                         cfg |= GSC_IN_YUV422_1P_OEDER_LSB_C;
193                 if (frame->fmt->corder == GSC_CBCR)
194                         cfg |= GSC_IN_CHROMA_ORDER_CBCR;
195                 else
196                         cfg |= GSC_IN_CHROMA_ORDER_CRCB;
197                 break;
198         case 2:
199                 if (depth == 12)
200                         cfg |= GSC_IN_YUV420_2P;
201                 else
202                         cfg |= GSC_IN_YUV422_2P;
203                 if (frame->fmt->corder == GSC_CBCR)
204                         cfg |= GSC_IN_CHROMA_ORDER_CBCR;
205                 else
206                         cfg |= GSC_IN_CHROMA_ORDER_CRCB;
207                 break;
208         case 3:
209                 if (depth == 12)
210                         cfg |= GSC_IN_YUV420_3P;
211                 else
212                         cfg |= GSC_IN_YUV422_3P;
213                 break;
214         }
215
216         if (is_tiled(frame->fmt))
217                 cfg |= GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE;
218
219         writel(cfg, dev->regs + GSC_IN_CON);
220 }
221
222 void gsc_hw_set_output_path(struct gsc_ctx *ctx)
223 {
224         struct gsc_dev *dev = ctx->gsc_dev;
225
226         u32 cfg = readl(dev->regs + GSC_OUT_CON);
227         cfg &= ~GSC_OUT_PATH_MASK;
228
229         if (ctx->out_path == GSC_DMA)
230                 cfg |= GSC_OUT_PATH_MEMORY;
231         else
232                 cfg |= GSC_OUT_PATH_LOCAL;
233
234         writel(cfg, dev->regs + GSC_OUT_CON);
235 }
236
237 void gsc_hw_set_out_size(struct gsc_ctx *ctx)
238 {
239         struct gsc_dev *dev = ctx->gsc_dev;
240         struct gsc_frame *frame = &ctx->d_frame;
241         u32 cfg;
242
243         /* Set output original size */
244         if (ctx->out_path == GSC_DMA) {
245                 cfg = GSC_DSTIMG_OFFSET_X(frame->crop.left);
246                 cfg |= GSC_DSTIMG_OFFSET_Y(frame->crop.top);
247                 writel(cfg, dev->regs + GSC_DSTIMG_OFFSET);
248
249                 cfg = GSC_DSTIMG_WIDTH(frame->f_width);
250                 cfg |= GSC_DSTIMG_HEIGHT(frame->f_height);
251                 writel(cfg, dev->regs + GSC_DSTIMG_SIZE);
252         }
253
254         /* Set output scaled size */
255         if (ctx->gsc_ctrls.rotate->val == 90 ||
256             ctx->gsc_ctrls.rotate->val == 270) {
257                 cfg = GSC_SCALED_WIDTH(frame->crop.height);
258                 cfg |= GSC_SCALED_HEIGHT(frame->crop.width);
259         } else {
260                 cfg = GSC_SCALED_WIDTH(frame->crop.width);
261                 cfg |= GSC_SCALED_HEIGHT(frame->crop.height);
262         }
263         writel(cfg, dev->regs + GSC_SCALED_SIZE);
264 }
265
266 void gsc_hw_set_out_image_rgb(struct gsc_ctx *ctx)
267 {
268         struct gsc_dev *dev = ctx->gsc_dev;
269         struct gsc_frame *frame = &ctx->d_frame;
270         u32 cfg;
271
272         cfg = readl(dev->regs + GSC_OUT_CON);
273         if (frame->colorspace == V4L2_COLORSPACE_REC709)
274                 cfg |= GSC_OUT_RGB_HD_WIDE;
275         else
276                 cfg |= GSC_OUT_RGB_SD_WIDE;
277
278         if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)
279                 cfg |= GSC_OUT_RGB565;
280         else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)
281                 cfg |= GSC_OUT_XRGB8888;
282
283         writel(cfg, dev->regs + GSC_OUT_CON);
284 }
285
286 void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
287 {
288         struct gsc_dev *dev = ctx->gsc_dev;
289         struct gsc_frame *frame = &ctx->d_frame;
290         u32 i, depth = 0;
291         u32 cfg;
292
293         cfg = readl(dev->regs + GSC_OUT_CON);
294         cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK |
295                  GSC_OUT_CHROMA_ORDER_MASK | GSC_OUT_FORMAT_MASK |
296                  GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);
297         writel(cfg, dev->regs + GSC_OUT_CON);
298
299         if (is_rgb(frame->fmt->color)) {
300                 gsc_hw_set_out_image_rgb(ctx);
301                 return;
302         }
303
304         if (ctx->out_path != GSC_DMA) {
305                 cfg |= GSC_OUT_YUV444;
306                 goto end_set;
307         }
308
309         for (i = 0; i < frame->fmt->num_planes; i++)
310                 depth += frame->fmt->depth[i];
311
312         switch (frame->fmt->num_comp) {
313         case 1:
314                 cfg |= GSC_OUT_YUV422_1P;
315                 if (frame->fmt->yorder == GSC_LSB_Y)
316                         cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_Y;
317                 else
318                         cfg |= GSC_OUT_YUV422_1P_OEDER_LSB_C;
319                 if (frame->fmt->corder == GSC_CBCR)
320                         cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
321                 else
322                         cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
323                 break;
324         case 2:
325                 if (depth == 12)
326                         cfg |= GSC_OUT_YUV420_2P;
327                 else
328                         cfg |= GSC_OUT_YUV422_2P;
329                 if (frame->fmt->corder == GSC_CBCR)
330                         cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
331                 else
332                         cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
333                 break;
334         case 3:
335                 cfg |= GSC_OUT_YUV420_3P;
336                 break;
337         }
338
339         if (is_tiled(frame->fmt))
340                 cfg |= GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE;
341
342 end_set:
343         writel(cfg, dev->regs + GSC_OUT_CON);
344 }
345
346 void gsc_hw_set_prescaler(struct gsc_ctx *ctx)
347 {
348         struct gsc_dev *dev = ctx->gsc_dev;
349         struct gsc_scaler *sc = &ctx->scaler;
350         u32 cfg;
351
352         cfg = GSC_PRESC_SHFACTOR(sc->pre_shfactor);
353         cfg |= GSC_PRESC_H_RATIO(sc->pre_hratio);
354         cfg |= GSC_PRESC_V_RATIO(sc->pre_vratio);
355         writel(cfg, dev->regs + GSC_PRE_SCALE_RATIO);
356 }
357
358 void gsc_hw_set_mainscaler(struct gsc_ctx *ctx)
359 {
360         struct gsc_dev *dev = ctx->gsc_dev;
361         struct gsc_scaler *sc = &ctx->scaler;
362         u32 cfg;
363
364         cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio);
365         writel(cfg, dev->regs + GSC_MAIN_H_RATIO);
366
367         cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio);
368         writel(cfg, dev->regs + GSC_MAIN_V_RATIO);
369 }
370
371 void gsc_hw_set_rotation(struct gsc_ctx *ctx)
372 {
373         struct gsc_dev *dev = ctx->gsc_dev;
374         u32 cfg;
375
376         cfg = readl(dev->regs + GSC_IN_CON);
377         cfg &= ~GSC_IN_ROT_MASK;
378
379         switch (ctx->gsc_ctrls.rotate->val) {
380         case 270:
381                 cfg |= GSC_IN_ROT_270;
382                 break;
383         case 180:
384                 cfg |= GSC_IN_ROT_180;
385                 break;
386         case 90:
387                 if (ctx->gsc_ctrls.hflip->val)
388                         cfg |= GSC_IN_ROT_90_XFLIP;
389                 else if (ctx->gsc_ctrls.vflip->val)
390                         cfg |= GSC_IN_ROT_90_YFLIP;
391                 else
392                         cfg |= GSC_IN_ROT_90;
393                 break;
394         case 0:
395                 if (ctx->gsc_ctrls.hflip->val)
396                         cfg |= GSC_IN_ROT_XFLIP;
397                 else if (ctx->gsc_ctrls.vflip->val)
398                         cfg |= GSC_IN_ROT_YFLIP;
399         }
400
401         writel(cfg, dev->regs + GSC_IN_CON);
402 }
403
404 void gsc_hw_set_global_alpha(struct gsc_ctx *ctx)
405 {
406         struct gsc_dev *dev = ctx->gsc_dev;
407         struct gsc_frame *frame = &ctx->d_frame;
408         u32 cfg;
409
410         if (!is_rgb(frame->fmt->color)) {
411                 pr_debug("Not a RGB format");
412                 return;
413         }
414
415         cfg = readl(dev->regs + GSC_OUT_CON);
416         cfg &= ~GSC_OUT_GLOBAL_ALPHA_MASK;
417
418         cfg |= GSC_OUT_GLOBAL_ALPHA(ctx->gsc_ctrls.global_alpha->val);
419         writel(cfg, dev->regs + GSC_OUT_CON);
420 }
421
422 void gsc_hw_set_sfr_update(struct gsc_ctx *ctx)
423 {
424         struct gsc_dev *dev = ctx->gsc_dev;
425         u32 cfg;
426
427         cfg = readl(dev->regs + GSC_ENABLE);
428         cfg |= GSC_ENABLE_SFR_UPDATE;
429         writel(cfg, dev->regs + GSC_ENABLE);
430 }