root/drivers/media/platform/exynos4-is/fimc-lite-reg.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. flite_hw_reset
  2. flite_hw_clear_pending_irq
  3. flite_hw_get_interrupt_source
  4. flite_hw_clear_last_capture_end
  5. flite_hw_set_interrupt_mask
  6. flite_hw_capture_start
  7. flite_hw_capture_stop
  8. flite_hw_set_test_pattern
  9. flite_hw_set_source_format
  10. flite_hw_set_window_offset
  11. flite_hw_set_camera_port
  12. flite_hw_set_camera_bus
  13. flite_hw_set_pack12
  14. flite_hw_set_out_order
  15. flite_hw_set_dma_window
  16. flite_hw_set_dma_buffer
  17. flite_hw_mask_dma_buffer
  18. flite_hw_set_output_dma
  19. flite_hw_dump_regs

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Register interface file for EXYNOS FIMC-LITE (camera interface) driver
   4  *
   5  * Copyright (C) 2012 Samsung Electronics Co., Ltd.
   6  * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
   7 */
   8 
   9 #include <linux/bitops.h>
  10 #include <linux/delay.h>
  11 #include <linux/io.h>
  12 #include <media/drv-intf/exynos-fimc.h>
  13 
  14 #include "fimc-lite-reg.h"
  15 #include "fimc-lite.h"
  16 #include "fimc-core.h"
  17 
  18 #define FLITE_RESET_TIMEOUT 50 /* in ms */
  19 
  20 void flite_hw_reset(struct fimc_lite *dev)
  21 {
  22         unsigned long end = jiffies + msecs_to_jiffies(FLITE_RESET_TIMEOUT);
  23         u32 cfg;
  24 
  25         cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
  26         cfg |= FLITE_REG_CIGCTRL_SWRST_REQ;
  27         writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
  28 
  29         while (time_is_after_jiffies(end)) {
  30                 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
  31                 if (cfg & FLITE_REG_CIGCTRL_SWRST_RDY)
  32                         break;
  33                 usleep_range(1000, 5000);
  34         }
  35 
  36         cfg |= FLITE_REG_CIGCTRL_SWRST;
  37         writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
  38 }
  39 
  40 void flite_hw_clear_pending_irq(struct fimc_lite *dev)
  41 {
  42         u32 cfg = readl(dev->regs + FLITE_REG_CISTATUS);
  43         cfg &= ~FLITE_REG_CISTATUS_IRQ_CAM;
  44         writel(cfg, dev->regs + FLITE_REG_CISTATUS);
  45 }
  46 
  47 u32 flite_hw_get_interrupt_source(struct fimc_lite *dev)
  48 {
  49         u32 intsrc = readl(dev->regs + FLITE_REG_CISTATUS);
  50         return intsrc & FLITE_REG_CISTATUS_IRQ_MASK;
  51 }
  52 
  53 void flite_hw_clear_last_capture_end(struct fimc_lite *dev)
  54 {
  55 
  56         u32 cfg = readl(dev->regs + FLITE_REG_CISTATUS2);
  57         cfg &= ~FLITE_REG_CISTATUS2_LASTCAPEND;
  58         writel(cfg, dev->regs + FLITE_REG_CISTATUS2);
  59 }
  60 
  61 void flite_hw_set_interrupt_mask(struct fimc_lite *dev)
  62 {
  63         u32 cfg, intsrc;
  64 
  65         /* Select interrupts to be enabled for each output mode */
  66         if (atomic_read(&dev->out_path) == FIMC_IO_DMA) {
  67                 intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN |
  68                          FLITE_REG_CIGCTRL_IRQ_LASTEN |
  69                          FLITE_REG_CIGCTRL_IRQ_STARTEN |
  70                          FLITE_REG_CIGCTRL_IRQ_ENDEN;
  71         } else {
  72                 /* An output to the FIMC-IS */
  73                 intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN |
  74                          FLITE_REG_CIGCTRL_IRQ_LASTEN;
  75         }
  76 
  77         cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
  78         cfg |= FLITE_REG_CIGCTRL_IRQ_DISABLE_MASK;
  79         cfg &= ~intsrc;
  80         writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
  81 }
  82 
  83 void flite_hw_capture_start(struct fimc_lite *dev)
  84 {
  85         u32 cfg = readl(dev->regs + FLITE_REG_CIIMGCPT);
  86         cfg |= FLITE_REG_CIIMGCPT_IMGCPTEN;
  87         writel(cfg, dev->regs + FLITE_REG_CIIMGCPT);
  88 }
  89 
  90 void flite_hw_capture_stop(struct fimc_lite *dev)
  91 {
  92         u32 cfg = readl(dev->regs + FLITE_REG_CIIMGCPT);
  93         cfg &= ~FLITE_REG_CIIMGCPT_IMGCPTEN;
  94         writel(cfg, dev->regs + FLITE_REG_CIIMGCPT);
  95 }
  96 
  97 /*
  98  * Test pattern (color bars) enable/disable. External sensor
  99  * pixel clock must be active for the test pattern to work.
 100  */
 101 void flite_hw_set_test_pattern(struct fimc_lite *dev, bool on)
 102 {
 103         u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
 104         if (on)
 105                 cfg |= FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR;
 106         else
 107                 cfg &= ~FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR;
 108         writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
 109 }
 110 
 111 static const u32 src_pixfmt_map[8][3] = {
 112         { MEDIA_BUS_FMT_YUYV8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCBYCR,
 113           FLITE_REG_CIGCTRL_YUV422_1P },
 114         { MEDIA_BUS_FMT_YVYU8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCRYCB,
 115           FLITE_REG_CIGCTRL_YUV422_1P },
 116         { MEDIA_BUS_FMT_UYVY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CBYCRY,
 117           FLITE_REG_CIGCTRL_YUV422_1P },
 118         { MEDIA_BUS_FMT_VYUY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY,
 119           FLITE_REG_CIGCTRL_YUV422_1P },
 120         { MEDIA_BUS_FMT_SGRBG8_1X8, 0, FLITE_REG_CIGCTRL_RAW8 },
 121         { MEDIA_BUS_FMT_SGRBG10_1X10, 0, FLITE_REG_CIGCTRL_RAW10 },
 122         { MEDIA_BUS_FMT_SGRBG12_1X12, 0, FLITE_REG_CIGCTRL_RAW12 },
 123         { MEDIA_BUS_FMT_JPEG_1X8, 0, FLITE_REG_CIGCTRL_USER(1) },
 124 };
 125 
 126 /* Set camera input pixel format and resolution */
 127 void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f)
 128 {
 129         u32 pixelcode = f->fmt->mbus_code;
 130         int i = ARRAY_SIZE(src_pixfmt_map);
 131         u32 cfg;
 132 
 133         while (--i) {
 134                 if (src_pixfmt_map[i][0] == pixelcode)
 135                         break;
 136         }
 137 
 138         if (i == 0 && src_pixfmt_map[i][0] != pixelcode) {
 139                 v4l2_err(&dev->ve.vdev,
 140                          "Unsupported pixel code, falling back to %#08x\n",
 141                          src_pixfmt_map[i][0]);
 142         }
 143 
 144         cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
 145         cfg &= ~FLITE_REG_CIGCTRL_FMT_MASK;
 146         cfg |= src_pixfmt_map[i][2];
 147         writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
 148 
 149         cfg = readl(dev->regs + FLITE_REG_CISRCSIZE);
 150         cfg &= ~(FLITE_REG_CISRCSIZE_ORDER422_MASK |
 151                  FLITE_REG_CISRCSIZE_SIZE_CAM_MASK);
 152         cfg |= (f->f_width << 16) | f->f_height;
 153         cfg |= src_pixfmt_map[i][1];
 154         writel(cfg, dev->regs + FLITE_REG_CISRCSIZE);
 155 }
 156 
 157 /* Set the camera host input window offsets (cropping) */
 158 void flite_hw_set_window_offset(struct fimc_lite *dev, struct flite_frame *f)
 159 {
 160         u32 hoff2, voff2;
 161         u32 cfg;
 162 
 163         cfg = readl(dev->regs + FLITE_REG_CIWDOFST);
 164         cfg &= ~FLITE_REG_CIWDOFST_OFST_MASK;
 165         cfg |= (f->rect.left << 16) | f->rect.top;
 166         cfg |= FLITE_REG_CIWDOFST_WINOFSEN;
 167         writel(cfg, dev->regs + FLITE_REG_CIWDOFST);
 168 
 169         hoff2 = f->f_width - f->rect.width - f->rect.left;
 170         voff2 = f->f_height - f->rect.height - f->rect.top;
 171 
 172         cfg = (hoff2 << 16) | voff2;
 173         writel(cfg, dev->regs + FLITE_REG_CIWDOFST2);
 174 }
 175 
 176 /* Select camera port (A, B) */
 177 static void flite_hw_set_camera_port(struct fimc_lite *dev, int id)
 178 {
 179         u32 cfg = readl(dev->regs + FLITE_REG_CIGENERAL);
 180         if (id == 0)
 181                 cfg &= ~FLITE_REG_CIGENERAL_CAM_B;
 182         else
 183                 cfg |= FLITE_REG_CIGENERAL_CAM_B;
 184         writel(cfg, dev->regs + FLITE_REG_CIGENERAL);
 185 }
 186 
 187 /* Select serial or parallel bus, camera port (A,B) and set signals polarity */
 188 void flite_hw_set_camera_bus(struct fimc_lite *dev,
 189                              struct fimc_source_info *si)
 190 {
 191         u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
 192         unsigned int flags = si->flags;
 193 
 194         if (si->sensor_bus_type != FIMC_BUS_TYPE_MIPI_CSI2) {
 195                 cfg &= ~(FLITE_REG_CIGCTRL_SELCAM_MIPI |
 196                          FLITE_REG_CIGCTRL_INVPOLPCLK |
 197                          FLITE_REG_CIGCTRL_INVPOLVSYNC |
 198                          FLITE_REG_CIGCTRL_INVPOLHREF);
 199 
 200                 if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
 201                         cfg |= FLITE_REG_CIGCTRL_INVPOLPCLK;
 202 
 203                 if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
 204                         cfg |= FLITE_REG_CIGCTRL_INVPOLVSYNC;
 205 
 206                 if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
 207                         cfg |= FLITE_REG_CIGCTRL_INVPOLHREF;
 208         } else {
 209                 cfg |= FLITE_REG_CIGCTRL_SELCAM_MIPI;
 210         }
 211 
 212         writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
 213 
 214         flite_hw_set_camera_port(dev, si->mux_id);
 215 }
 216 
 217 static void flite_hw_set_pack12(struct fimc_lite *dev, int on)
 218 {
 219         u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT);
 220 
 221         cfg &= ~FLITE_REG_CIODMAFMT_PACK12;
 222 
 223         if (on)
 224                 cfg |= FLITE_REG_CIODMAFMT_PACK12;
 225 
 226         writel(cfg, dev->regs + FLITE_REG_CIODMAFMT);
 227 }
 228 
 229 static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f)
 230 {
 231         static const u32 pixcode[4][2] = {
 232                 { MEDIA_BUS_FMT_YUYV8_2X8, FLITE_REG_CIODMAFMT_YCBYCR },
 233                 { MEDIA_BUS_FMT_YVYU8_2X8, FLITE_REG_CIODMAFMT_YCRYCB },
 234                 { MEDIA_BUS_FMT_UYVY8_2X8, FLITE_REG_CIODMAFMT_CBYCRY },
 235                 { MEDIA_BUS_FMT_VYUY8_2X8, FLITE_REG_CIODMAFMT_CRYCBY },
 236         };
 237         u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT);
 238         int i = ARRAY_SIZE(pixcode);
 239 
 240         while (--i)
 241                 if (pixcode[i][0] == f->fmt->mbus_code)
 242                         break;
 243         cfg &= ~FLITE_REG_CIODMAFMT_YCBCR_ORDER_MASK;
 244         writel(cfg | pixcode[i][1], dev->regs + FLITE_REG_CIODMAFMT);
 245 }
 246 
 247 void flite_hw_set_dma_window(struct fimc_lite *dev, struct flite_frame *f)
 248 {
 249         u32 cfg;
 250 
 251         /* Maximum output pixel size */
 252         cfg = readl(dev->regs + FLITE_REG_CIOCAN);
 253         cfg &= ~FLITE_REG_CIOCAN_MASK;
 254         cfg |= (f->f_height << 16) | f->f_width;
 255         writel(cfg, dev->regs + FLITE_REG_CIOCAN);
 256 
 257         /* DMA offsets */
 258         cfg = readl(dev->regs + FLITE_REG_CIOOFF);
 259         cfg &= ~FLITE_REG_CIOOFF_MASK;
 260         cfg |= (f->rect.top << 16) | f->rect.left;
 261         writel(cfg, dev->regs + FLITE_REG_CIOOFF);
 262 }
 263 
 264 void flite_hw_set_dma_buffer(struct fimc_lite *dev, struct flite_buffer *buf)
 265 {
 266         unsigned int index;
 267         u32 cfg;
 268 
 269         if (dev->dd->max_dma_bufs == 1)
 270                 index = 0;
 271         else
 272                 index = buf->index;
 273 
 274         if (index == 0)
 275                 writel(buf->paddr, dev->regs + FLITE_REG_CIOSA);
 276         else
 277                 writel(buf->paddr, dev->regs + FLITE_REG_CIOSAN(index - 1));
 278 
 279         cfg = readl(dev->regs + FLITE_REG_CIFCNTSEQ);
 280         cfg |= BIT(index);
 281         writel(cfg, dev->regs + FLITE_REG_CIFCNTSEQ);
 282 }
 283 
 284 void flite_hw_mask_dma_buffer(struct fimc_lite *dev, u32 index)
 285 {
 286         u32 cfg;
 287 
 288         if (dev->dd->max_dma_bufs == 1)
 289                 index = 0;
 290 
 291         cfg = readl(dev->regs + FLITE_REG_CIFCNTSEQ);
 292         cfg &= ~BIT(index);
 293         writel(cfg, dev->regs + FLITE_REG_CIFCNTSEQ);
 294 }
 295 
 296 /* Enable/disable output DMA, set output pixel size and offsets (composition) */
 297 void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f,
 298                              bool enable)
 299 {
 300         u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
 301 
 302         if (!enable) {
 303                 cfg |= FLITE_REG_CIGCTRL_ODMA_DISABLE;
 304                 writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
 305                 return;
 306         }
 307 
 308         cfg &= ~FLITE_REG_CIGCTRL_ODMA_DISABLE;
 309         writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
 310 
 311         flite_hw_set_out_order(dev, f);
 312         flite_hw_set_dma_window(dev, f);
 313         flite_hw_set_pack12(dev, 0);
 314 }
 315 
 316 void flite_hw_dump_regs(struct fimc_lite *dev, const char *label)
 317 {
 318         struct {
 319                 u32 offset;
 320                 const char * const name;
 321         } registers[] = {
 322                 { 0x00, "CISRCSIZE" },
 323                 { 0x04, "CIGCTRL" },
 324                 { 0x08, "CIIMGCPT" },
 325                 { 0x0c, "CICPTSEQ" },
 326                 { 0x10, "CIWDOFST" },
 327                 { 0x14, "CIWDOFST2" },
 328                 { 0x18, "CIODMAFMT" },
 329                 { 0x20, "CIOCAN" },
 330                 { 0x24, "CIOOFF" },
 331                 { 0x30, "CIOSA" },
 332                 { 0x40, "CISTATUS" },
 333                 { 0x44, "CISTATUS2" },
 334                 { 0xf0, "CITHOLD" },
 335                 { 0xfc, "CIGENERAL" },
 336         };
 337         u32 i;
 338 
 339         v4l2_info(&dev->subdev, "--- %s ---\n", label);
 340 
 341         for (i = 0; i < ARRAY_SIZE(registers); i++) {
 342                 u32 cfg = readl(dev->regs + registers[i].offset);
 343                 v4l2_info(&dev->subdev, "%9s: 0x%08x\n",
 344                           registers[i].name, cfg);
 345         }
 346 }

/* [<][>][^][v][top][bottom][index][help] */