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