Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gsc-regs.c
Go to the documentation of this file.
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 
20 {
22 }
23 
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 
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 
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 
64  bool enable)
65 {
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);
75 }
76 
78  bool enable)
79 {
81  u32 mask = 1 << shift;
82 
83  cfg &= ~mask;
84  cfg |= enable << shift;
85 
89 }
90 
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 
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 
113 {
114  struct gsc_dev *dev = ctx->gsc_dev;
115 
116  u32 cfg = readl(dev->regs + GSC_IN_CON);
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 
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 
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 
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);
178  writel(cfg, dev->regs + GSC_IN_CON);
179 
180  if (is_rgb(frame->fmt->color)) {
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)
192  else
194  if (frame->fmt->corder == GSC_CBCR)
196  else
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)
206  else
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 
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 
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 
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 
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);
295  writel(cfg, dev->regs + GSC_OUT_CON);
296 
297  if (is_rgb(frame->fmt->color)) {
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)
315  else
317  if (frame->fmt->corder == GSC_CBCR)
319  else
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)
329  else
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 
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 
354 {
355  struct gsc_dev *dev = ctx->gsc_dev;
356  struct gsc_scaler *sc = &ctx->scaler;
357  u32 cfg;
358 
360  writel(cfg, dev->regs + GSC_MAIN_H_RATIO);
361 
363  writel(cfg, dev->regs + GSC_MAIN_V_RATIO);
364 }
365 
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 
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);
412 
413  cfg |= GSC_OUT_GLOBAL_ALPHA(ctx->gsc_ctrls.global_alpha->val);
414  writel(cfg, dev->regs + GSC_OUT_CON);
415 }
416 
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 }