Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fimc-lite-reg.c
Go to the documentation of this file.
1 /*
2  * Register interface file for EXYNOS FIMC-LITE (camera interface) driver
3  *
4  * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5  * Sylwester Nawrocki <[email protected]>
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 version 2 as
9  * published by the Free Software Foundation.
10 */
11 
12 #include <linux/io.h>
13 #include <linux/delay.h>
14 #include <media/s5p_fimc.h>
15 
16 #include "fimc-lite-reg.h"
17 #include "fimc-lite.h"
18 #include "fimc-core.h"
19 
20 #define FLITE_RESET_TIMEOUT 50 /* in ms */
21 
23 {
25  u32 cfg;
26 
27  cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
29  writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
30 
31  while (time_is_after_jiffies(end)) {
32  cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
34  break;
35  usleep_range(1000, 5000);
36  }
37 
39  writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
40 }
41 
43 {
46  writel(cfg, dev->regs + FLITE_REG_CISTATUS);
47 }
48 
50 {
51  u32 intsrc = readl(dev->regs + FLITE_REG_CISTATUS);
52  return intsrc & FLITE_REG_CISTATUS_IRQ_MASK;
53 }
54 
56 {
57 
60  writel(cfg, dev->regs + FLITE_REG_CISTATUS2);
61 }
62 
64 {
65  u32 cfg, intsrc;
66 
67  /* Select interrupts to be enabled for each output mode */
68  if (dev->out_path == FIMC_IO_DMA) {
72  } else {
73  /* An output to the FIMC-IS */
76  }
77 
78  cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
80  cfg &= ~intsrc;
81  writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
82 }
83 
85 {
88  writel(cfg, dev->regs + FLITE_REG_CIIMGCPT);
89 }
90 
92 {
95  writel(cfg, dev->regs + FLITE_REG_CIIMGCPT);
96 }
97 
98 /*
99  * Test pattern (color bars) enable/disable. External sensor
100  * pixel clock must be active for the test pattern to work.
101  */
103 {
104  u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
105  if (on)
107  else
109  writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
110 }
111 
112 static const u32 src_pixfmt_map[8][3] = {
125 };
126 
127 /* Set camera input pixel format and resolution */
129 {
130  enum v4l2_mbus_pixelcode pixelcode = dev->fmt->mbus_code;
131  unsigned int i = ARRAY_SIZE(src_pixfmt_map);
132  u32 cfg;
133 
134  while (i-- >= 0) {
135  if (src_pixfmt_map[i][0] == pixelcode)
136  break;
137  }
138 
139  if (i == 0 && src_pixfmt_map[i][0] != pixelcode) {
140  v4l2_err(&dev->vfd,
141  "Unsupported pixel code, falling back to %#08x\n",
142  src_pixfmt_map[i][0]);
143  }
144 
145  cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
147  cfg |= src_pixfmt_map[i][2];
148  writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
149 
150  cfg = readl(dev->regs + FLITE_REG_CISRCSIZE);
153  cfg |= (f->f_width << 16) | f->f_height;
154  cfg |= src_pixfmt_map[i][1];
155  writel(cfg, dev->regs + FLITE_REG_CISRCSIZE);
156 }
157 
158 /* Set the camera host input window offsets (cropping) */
160 {
161  u32 hoff2, voff2;
162  u32 cfg;
163 
164  cfg = readl(dev->regs + FLITE_REG_CIWDOFST);
166  cfg |= (f->rect.left << 16) | f->rect.top;
168  writel(cfg, dev->regs + FLITE_REG_CIWDOFST);
169 
170  hoff2 = f->f_width - f->rect.width - f->rect.left;
171  voff2 = f->f_height - f->rect.height - f->rect.top;
172 
173  cfg = (hoff2 << 16) | voff2;
174  writel(cfg, dev->regs + FLITE_REG_CIWDOFST2);
175 }
176 
177 /* Select camera port (A, B) */
178 static void flite_hw_set_camera_port(struct fimc_lite *dev, int id)
179 {
181  if (id == 0)
183  else
185  writel(cfg, dev->regs + FLITE_REG_CIGENERAL);
186 }
187 
188 /* Select serial or parallel bus, camera port (A,B) and set signals polarity */
190  struct s5p_fimc_isp_info *s_info)
191 {
192  u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
193  unsigned int flags = s_info->flags;
194 
195  if (s_info->bus_type != FIMC_MIPI_CSI2) {
200 
201  if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
203 
204  if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
206 
207  if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
209  } else {
211  }
212 
213  writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
214 
215  flite_hw_set_camera_port(dev, s_info->mux_id);
216 }
217 
218 static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f)
219 {
220  static const u32 pixcode[4][2] = {
225  };
226  u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT);
227  unsigned int i = ARRAY_SIZE(pixcode);
228 
229  while (i-- >= 0)
230  if (pixcode[i][0] == dev->fmt->mbus_code)
231  break;
233  writel(cfg | pixcode[i][1], dev->regs + FLITE_REG_CIODMAFMT);
234 }
235 
236 void flite_hw_set_dma_window(struct fimc_lite *dev, struct flite_frame *f)
237 {
238  u32 cfg;
239 
240  /* Maximum output pixel size */
241  cfg = readl(dev->regs + FLITE_REG_CIOCAN);
242  cfg &= ~FLITE_REG_CIOCAN_MASK;
243  cfg = (f->f_height << 16) | f->f_width;
244  writel(cfg, dev->regs + FLITE_REG_CIOCAN);
245 
246  /* DMA offsets */
247  cfg = readl(dev->regs + FLITE_REG_CIOOFF);
248  cfg &= ~FLITE_REG_CIOOFF_MASK;
249  cfg |= (f->rect.top << 16) | f->rect.left;
250  writel(cfg, dev->regs + FLITE_REG_CIOOFF);
251 }
252 
253 /* Enable/disable output DMA, set output pixel size and offsets (composition) */
254 void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f,
255  bool enable)
256 {
257  u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
258 
259  if (!enable) {
261  writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
262  return;
263  }
264 
266  writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
267 
268  flite_hw_set_out_order(dev, f);
269  flite_hw_set_dma_window(dev, f);
270 }
271 
272 void flite_hw_dump_regs(struct fimc_lite *dev, const char *label)
273 {
274  struct {
275  u32 offset;
276  const char * const name;
277  } registers[] = {
278  { 0x00, "CISRCSIZE" },
279  { 0x04, "CIGCTRL" },
280  { 0x08, "CIIMGCPT" },
281  { 0x0c, "CICPTSEQ" },
282  { 0x10, "CIWDOFST" },
283  { 0x14, "CIWDOFST2" },
284  { 0x18, "CIODMAFMT" },
285  { 0x20, "CIOCAN" },
286  { 0x24, "CIOOFF" },
287  { 0x30, "CIOSA" },
288  { 0x40, "CISTATUS" },
289  { 0x44, "CISTATUS2" },
290  { 0xf0, "CITHOLD" },
291  { 0xfc, "CIGENERAL" },
292  };
293  u32 i;
294 
295  pr_info("--- %s ---\n", label);
296  for (i = 0; i < ARRAY_SIZE(registers); i++) {
297  u32 cfg = readl(dev->regs + registers[i].offset);
298  pr_info("%s: %s:\t0x%08x\n", __func__, registers[i].name, cfg);
299  }
300 }