• Home
  • Raw
  • Download

Lines Matching +full:csi +full:- +full:2

2  * Copyright (C) 2012-2014 Mentor Graphics Inc.
3 * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
7 * Free Software Foundation; either version 2 of the License, or (at your
24 #include <uapi/linux/v4l2-mediabus.h>
26 #include <linux/clk-provider.h>
29 #include "ipu-prv.h"
41 /* CSI Register Offsets */
64 /* CSI Register Fields */
69 #define CSI_SENS_CONF_DATA_FMT_YUV422_UYVY 2L
78 #define CSI_SENS_CONF_DATA_POL_SHIFT 2
95 #define CSI_DATA_DEST_IC 2
125 /* MIPI CSI-2 data types */
142 * Bitfield of CSI bus signal polarities and modes.
162 * Enumeration of CSI data bus widths.
173 * Enumeration of CSI clock modes.
186 static inline u32 ipu_csi_read(struct ipu_csi *csi, unsigned offset) in ipu_csi_read() argument
188 return readl(csi->base + offset); in ipu_csi_read()
191 static inline void ipu_csi_write(struct ipu_csi *csi, u32 value, in ipu_csi_write() argument
194 writel(value, csi->base + offset); in ipu_csi_write()
201 static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk, in ipu_csi_set_testgen_mclk() argument
207 div_ratio = (ipu_clk / pixel_clk) - 1; in ipu_csi_set_testgen_mclk()
210 dev_err(csi->ipu->dev, in ipu_csi_set_testgen_mclk()
212 return -EINVAL; in ipu_csi_set_testgen_mclk()
215 temp = ipu_csi_read(csi, CSI_SENS_CONF); in ipu_csi_set_testgen_mclk()
217 ipu_csi_write(csi, temp | (div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT), in ipu_csi_set_testgen_mclk()
224 * Find the CSI data format and data width for the given V4L2 media
236 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565; in mbus_code_to_bus_cfg()
238 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; in mbus_code_to_bus_cfg()
239 cfg->mipi_dt = MIPI_DT_RGB565; in mbus_code_to_bus_cfg()
240 cfg->data_width = IPU_CSI_DATA_WIDTH_8; in mbus_code_to_bus_cfg()
244 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB444; in mbus_code_to_bus_cfg()
245 cfg->mipi_dt = MIPI_DT_RGB444; in mbus_code_to_bus_cfg()
246 cfg->data_width = IPU_CSI_DATA_WIDTH_8; in mbus_code_to_bus_cfg()
250 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555; in mbus_code_to_bus_cfg()
251 cfg->mipi_dt = MIPI_DT_RGB555; in mbus_code_to_bus_cfg()
252 cfg->data_width = IPU_CSI_DATA_WIDTH_8; in mbus_code_to_bus_cfg()
256 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444; in mbus_code_to_bus_cfg()
257 cfg->mipi_dt = MIPI_DT_RGB888; in mbus_code_to_bus_cfg()
258 cfg->data_width = IPU_CSI_DATA_WIDTH_8; in mbus_code_to_bus_cfg()
261 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY; in mbus_code_to_bus_cfg()
262 cfg->mipi_dt = MIPI_DT_YUV422; in mbus_code_to_bus_cfg()
263 cfg->data_width = IPU_CSI_DATA_WIDTH_8; in mbus_code_to_bus_cfg()
266 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV; in mbus_code_to_bus_cfg()
267 cfg->mipi_dt = MIPI_DT_YUV422; in mbus_code_to_bus_cfg()
268 cfg->data_width = IPU_CSI_DATA_WIDTH_8; in mbus_code_to_bus_cfg()
272 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; in mbus_code_to_bus_cfg()
273 cfg->mipi_dt = MIPI_DT_YUV422; in mbus_code_to_bus_cfg()
274 cfg->data_width = IPU_CSI_DATA_WIDTH_16; in mbus_code_to_bus_cfg()
281 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; in mbus_code_to_bus_cfg()
282 cfg->mipi_dt = MIPI_DT_RAW8; in mbus_code_to_bus_cfg()
283 cfg->data_width = IPU_CSI_DATA_WIDTH_8; in mbus_code_to_bus_cfg()
293 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; in mbus_code_to_bus_cfg()
294 cfg->mipi_dt = MIPI_DT_RAW10; in mbus_code_to_bus_cfg()
295 cfg->data_width = IPU_CSI_DATA_WIDTH_8; in mbus_code_to_bus_cfg()
302 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; in mbus_code_to_bus_cfg()
303 cfg->mipi_dt = MIPI_DT_RAW10; in mbus_code_to_bus_cfg()
304 cfg->data_width = IPU_CSI_DATA_WIDTH_10; in mbus_code_to_bus_cfg()
311 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; in mbus_code_to_bus_cfg()
312 cfg->mipi_dt = MIPI_DT_RAW12; in mbus_code_to_bus_cfg()
313 cfg->data_width = IPU_CSI_DATA_WIDTH_12; in mbus_code_to_bus_cfg()
317 cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_JPEG; in mbus_code_to_bus_cfg()
318 cfg->mipi_dt = MIPI_DT_RAW8; in mbus_code_to_bus_cfg()
319 cfg->data_width = IPU_CSI_DATA_WIDTH_8; in mbus_code_to_bus_cfg()
322 return -EINVAL; in mbus_code_to_bus_cfg()
329 * Fill a CSI bus config struct from mbus_config and mbus_framefmt.
339 ret = mbus_code_to_bus_cfg(csicfg, mbus_fmt->code, mbus_cfg->type); in fill_csi_bus_cfg()
343 switch (mbus_cfg->type) { in fill_csi_bus_cfg()
345 csicfg->ext_vsync = 1; in fill_csi_bus_cfg()
346 csicfg->vsync_pol = (mbus_cfg->flags & in fill_csi_bus_cfg()
348 csicfg->hsync_pol = (mbus_cfg->flags & in fill_csi_bus_cfg()
350 csicfg->pixclk_pol = (mbus_cfg->flags & in fill_csi_bus_cfg()
352 csicfg->clk_mode = IPU_CSI_CLK_MODE_GATED_CLK; in fill_csi_bus_cfg()
355 csicfg->ext_vsync = 0; in fill_csi_bus_cfg()
356 if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field) || in fill_csi_bus_cfg()
357 mbus_fmt->field == V4L2_FIELD_ALTERNATE) in fill_csi_bus_cfg()
358 csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED; in fill_csi_bus_cfg()
360 csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE; in fill_csi_bus_cfg()
364 * MIPI CSI-2 requires non gated clock mode, all other in fill_csi_bus_cfg()
365 * parameters are not applicable for MIPI CSI-2 bus. in fill_csi_bus_cfg()
367 csicfg->clk_mode = IPU_CSI_CLK_MODE_NONGATED_CLK; in fill_csi_bus_cfg()
377 int ipu_csi_init_interface(struct ipu_csi *csi, in ipu_csi_init_interface() argument
391 width = mbus_fmt->width; in ipu_csi_init_interface()
392 height = mbus_fmt->height; in ipu_csi_init_interface()
407 spin_lock_irqsave(&csi->lock, flags); in ipu_csi_init_interface()
409 ipu_csi_write(csi, data, CSI_SENS_CONF); in ipu_csi_init_interface()
415 ipu_csi_write(csi, 0x40030, CSI_CCIR_CODE_1); in ipu_csi_init_interface()
416 ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3); in ipu_csi_init_interface()
419 if (mbus_fmt->width == 720 && mbus_fmt->height == 576) { in ipu_csi_init_interface()
430 ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN, in ipu_csi_init_interface()
432 ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2); in ipu_csi_init_interface()
433 ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3); in ipu_csi_init_interface()
434 } else if (mbus_fmt->width == 720 && mbus_fmt->height == 480) { in ipu_csi_init_interface()
445 ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN, in ipu_csi_init_interface()
447 ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2); in ipu_csi_init_interface()
448 ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3); in ipu_csi_init_interface()
450 dev_err(csi->ipu->dev, in ipu_csi_init_interface()
452 spin_unlock_irqrestore(&csi->lock, flags); in ipu_csi_init_interface()
453 return -EINVAL; in ipu_csi_init_interface()
460 ipu_csi_write(csi, 0x40030 | CSI_CCIR_ERR_DET_EN, in ipu_csi_init_interface()
462 ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3); in ipu_csi_init_interface()
466 ipu_csi_write(csi, 0, CSI_CCIR_CODE_1); in ipu_csi_init_interface()
471 ipu_csi_write(csi, (width - 1) | ((height - 1) << 16), in ipu_csi_init_interface()
474 dev_dbg(csi->ipu->dev, "CSI_SENS_CONF = 0x%08X\n", in ipu_csi_init_interface()
475 ipu_csi_read(csi, CSI_SENS_CONF)); in ipu_csi_init_interface()
476 dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n", in ipu_csi_init_interface()
477 ipu_csi_read(csi, CSI_ACT_FRM_SIZE)); in ipu_csi_init_interface()
479 spin_unlock_irqrestore(&csi->lock, flags); in ipu_csi_init_interface()
485 bool ipu_csi_is_interlaced(struct ipu_csi *csi) in ipu_csi_is_interlaced() argument
490 spin_lock_irqsave(&csi->lock, flags); in ipu_csi_is_interlaced()
492 (ipu_csi_read(csi, CSI_SENS_CONF) & in ipu_csi_is_interlaced()
495 spin_unlock_irqrestore(&csi->lock, flags); in ipu_csi_is_interlaced()
509 dev_err(csi->ipu->dev, in ipu_csi_is_interlaced()
510 "CSI %d sensor protocol unsupported\n", csi->id); in ipu_csi_is_interlaced()
516 void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w) in ipu_csi_get_window() argument
521 spin_lock_irqsave(&csi->lock, flags); in ipu_csi_get_window()
523 reg = ipu_csi_read(csi, CSI_ACT_FRM_SIZE); in ipu_csi_get_window()
524 w->width = (reg & 0xFFFF) + 1; in ipu_csi_get_window()
525 w->height = (reg >> 16 & 0xFFFF) + 1; in ipu_csi_get_window()
527 reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL); in ipu_csi_get_window()
528 w->left = (reg & CSI_HSC_MASK) >> CSI_HSC_SHIFT; in ipu_csi_get_window()
529 w->top = (reg & CSI_VSC_MASK) >> CSI_VSC_SHIFT; in ipu_csi_get_window()
531 spin_unlock_irqrestore(&csi->lock, flags); in ipu_csi_get_window()
535 void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w) in ipu_csi_set_window() argument
540 spin_lock_irqsave(&csi->lock, flags); in ipu_csi_set_window()
542 ipu_csi_write(csi, (w->width - 1) | ((w->height - 1) << 16), in ipu_csi_set_window()
545 reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL); in ipu_csi_set_window()
547 reg |= ((w->top << CSI_VSC_SHIFT) | (w->left << CSI_HSC_SHIFT)); in ipu_csi_set_window()
548 ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL); in ipu_csi_set_window()
550 spin_unlock_irqrestore(&csi->lock, flags); in ipu_csi_set_window()
554 void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert) in ipu_csi_set_downsize() argument
559 spin_lock_irqsave(&csi->lock, flags); in ipu_csi_set_downsize()
561 reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL); in ipu_csi_set_downsize()
565 ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL); in ipu_csi_set_downsize()
567 spin_unlock_irqrestore(&csi->lock, flags); in ipu_csi_set_downsize()
571 void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active, in ipu_csi_set_test_generator() argument
576 u32 ipu_clk = clk_get_rate(csi->clk_ipu); in ipu_csi_set_test_generator()
579 spin_lock_irqsave(&csi->lock, flags); in ipu_csi_set_test_generator()
581 temp = ipu_csi_read(csi, CSI_TST_CTRL); in ipu_csi_set_test_generator()
585 ipu_csi_write(csi, temp, CSI_TST_CTRL); in ipu_csi_set_test_generator()
588 ipu_csi_set_testgen_mclk(csi, pix_clk, ipu_clk); in ipu_csi_set_test_generator()
596 ipu_csi_write(csi, temp, CSI_TST_CTRL); in ipu_csi_set_test_generator()
599 spin_unlock_irqrestore(&csi->lock, flags); in ipu_csi_set_test_generator()
603 int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc, in ipu_csi_set_mipi_datatype() argument
612 return -EINVAL; in ipu_csi_set_mipi_datatype()
614 ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2); in ipu_csi_set_mipi_datatype()
618 spin_lock_irqsave(&csi->lock, flags); in ipu_csi_set_mipi_datatype()
620 temp = ipu_csi_read(csi, CSI_MIPI_DI); in ipu_csi_set_mipi_datatype()
623 ipu_csi_write(csi, temp, CSI_MIPI_DI); in ipu_csi_set_mipi_datatype()
625 spin_unlock_irqrestore(&csi->lock, flags); in ipu_csi_set_mipi_datatype()
631 int ipu_csi_set_skip_smfc(struct ipu_csi *csi, u32 skip, in ipu_csi_set_skip_smfc() argument
638 return -EINVAL; in ipu_csi_set_skip_smfc()
640 spin_lock_irqsave(&csi->lock, flags); in ipu_csi_set_skip_smfc()
642 temp = ipu_csi_read(csi, CSI_SKIP); in ipu_csi_set_skip_smfc()
648 ipu_csi_write(csi, temp, CSI_SKIP); in ipu_csi_set_skip_smfc()
650 spin_unlock_irqrestore(&csi->lock, flags); in ipu_csi_set_skip_smfc()
656 int ipu_csi_set_dest(struct ipu_csi *csi, enum ipu_csi_dest csi_dest) in ipu_csi_set_dest() argument
666 spin_lock_irqsave(&csi->lock, flags); in ipu_csi_set_dest()
668 csi_sens_conf = ipu_csi_read(csi, CSI_SENS_CONF); in ipu_csi_set_dest()
671 ipu_csi_write(csi, csi_sens_conf, CSI_SENS_CONF); in ipu_csi_set_dest()
673 spin_unlock_irqrestore(&csi->lock, flags); in ipu_csi_set_dest()
679 int ipu_csi_enable(struct ipu_csi *csi) in ipu_csi_enable() argument
681 ipu_module_enable(csi->ipu, csi->module); in ipu_csi_enable()
687 int ipu_csi_disable(struct ipu_csi *csi) in ipu_csi_disable() argument
689 ipu_module_disable(csi->ipu, csi->module); in ipu_csi_disable()
698 struct ipu_csi *csi, *ret; in ipu_csi_get() local
701 return ERR_PTR(-EINVAL); in ipu_csi_get()
703 csi = ipu->csi_priv[id]; in ipu_csi_get()
704 ret = csi; in ipu_csi_get()
706 spin_lock_irqsave(&csi->lock, flags); in ipu_csi_get()
708 if (csi->inuse) { in ipu_csi_get()
709 ret = ERR_PTR(-EBUSY); in ipu_csi_get()
713 csi->inuse = true; in ipu_csi_get()
715 spin_unlock_irqrestore(&csi->lock, flags); in ipu_csi_get()
720 void ipu_csi_put(struct ipu_csi *csi) in ipu_csi_put() argument
724 spin_lock_irqsave(&csi->lock, flags); in ipu_csi_put()
725 csi->inuse = false; in ipu_csi_put()
726 spin_unlock_irqrestore(&csi->lock, flags); in ipu_csi_put()
733 struct ipu_csi *csi; in ipu_csi_init() local
736 return -ENODEV; in ipu_csi_init()
738 csi = devm_kzalloc(dev, sizeof(*csi), GFP_KERNEL); in ipu_csi_init()
739 if (!csi) in ipu_csi_init()
740 return -ENOMEM; in ipu_csi_init()
742 ipu->csi_priv[id] = csi; in ipu_csi_init()
744 spin_lock_init(&csi->lock); in ipu_csi_init()
745 csi->module = module; in ipu_csi_init()
746 csi->id = id; in ipu_csi_init()
747 csi->clk_ipu = clk_ipu; in ipu_csi_init()
748 csi->base = devm_ioremap(dev, base, PAGE_SIZE); in ipu_csi_init()
749 if (!csi->base) in ipu_csi_init()
750 return -ENOMEM; in ipu_csi_init()
752 dev_dbg(dev, "CSI%d base: 0x%08lx remapped to %p\n", in ipu_csi_init()
753 id, base, csi->base); in ipu_csi_init()
754 csi->ipu = ipu; in ipu_csi_init()
763 void ipu_csi_dump(struct ipu_csi *csi) in ipu_csi_dump() argument
765 dev_dbg(csi->ipu->dev, "CSI_SENS_CONF: %08x\n", in ipu_csi_dump()
766 ipu_csi_read(csi, CSI_SENS_CONF)); in ipu_csi_dump()
767 dev_dbg(csi->ipu->dev, "CSI_SENS_FRM_SIZE: %08x\n", in ipu_csi_dump()
768 ipu_csi_read(csi, CSI_SENS_FRM_SIZE)); in ipu_csi_dump()
769 dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE: %08x\n", in ipu_csi_dump()
770 ipu_csi_read(csi, CSI_ACT_FRM_SIZE)); in ipu_csi_dump()
771 dev_dbg(csi->ipu->dev, "CSI_OUT_FRM_CTRL: %08x\n", in ipu_csi_dump()
772 ipu_csi_read(csi, CSI_OUT_FRM_CTRL)); in ipu_csi_dump()
773 dev_dbg(csi->ipu->dev, "CSI_TST_CTRL: %08x\n", in ipu_csi_dump()
774 ipu_csi_read(csi, CSI_TST_CTRL)); in ipu_csi_dump()
775 dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_1: %08x\n", in ipu_csi_dump()
776 ipu_csi_read(csi, CSI_CCIR_CODE_1)); in ipu_csi_dump()
777 dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_2: %08x\n", in ipu_csi_dump()
778 ipu_csi_read(csi, CSI_CCIR_CODE_2)); in ipu_csi_dump()
779 dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_3: %08x\n", in ipu_csi_dump()
780 ipu_csi_read(csi, CSI_CCIR_CODE_3)); in ipu_csi_dump()
781 dev_dbg(csi->ipu->dev, "CSI_MIPI_DI: %08x\n", in ipu_csi_dump()
782 ipu_csi_read(csi, CSI_MIPI_DI)); in ipu_csi_dump()
783 dev_dbg(csi->ipu->dev, "CSI_SKIP: %08x\n", in ipu_csi_dump()
784 ipu_csi_read(csi, CSI_SKIP)); in ipu_csi_dump()