aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Chen <b02280@freescale.com>2011-09-14 14:41:27 +0800
committerEric Miao <eric.miao@linaro.org>2011-10-21 11:10:22 +0800
commit2884c12eb455a87e1c66f12be67595ecfbb734d0 (patch)
tree9337254db61899b109ae784f1a655fec19a4fe43
parent248bbb9079d7526648049c6c4a336eee395e96a2 (diff)
downloadlinux-linaro-2884c12eb455a87e1c66f12be67595ecfbb734d0.tar.gz
ipu3: Backport to freescale commit
commit ad19aef4a80094221b1b826185aea924627e8642 ENGR00155140 ipuv3: add support of power suspend/resume add support of power suspend/resume. because IPU has issue of restore current buffer register, this code only work for single buffer mode. Signed-off-by: Jason Chen <b02280@freescale.com>
-rw-r--r--arch/arm/plat-mxc/include/mach/ipu-v3.h731
-rw-r--r--drivers/mxc/ipu3/ipu_calc_stripes_sizes.c1
-rw-r--r--drivers/mxc/ipu3/ipu_capture.c158
-rw-r--r--drivers/mxc/ipu3/ipu_common.c641
-rw-r--r--drivers/mxc/ipu3/ipu_disp.c256
-rw-r--r--drivers/mxc/ipu3/ipu_param_mem.h154
-rw-r--r--drivers/mxc/ipu3/ipu_prv.h21
-rw-r--r--include/linux/ipu.h948
8 files changed, 1625 insertions, 1285 deletions
diff --git a/arch/arm/plat-mxc/include/mach/ipu-v3.h b/arch/arm/plat-mxc/include/mach/ipu-v3.h
index 713ee9f62d5..8ef0dd32068 100644
--- a/arch/arm/plat-mxc/include/mach/ipu-v3.h
+++ b/arch/arm/plat-mxc/include/mach/ipu-v3.h
@@ -16,737 +16,6 @@
#ifndef __MACH_IPU_V3_H_
#define __MACH_IPU_V3_H_
-#include <linux/ipu.h>
-
-/* IPU Pixel format definitions */
-/* Four-character-code (FOURCC) */
-#define fourcc(a, b, c, d)\
- (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
-
-/*!
- * @name IPU Pixel Formats
- *
- * Pixel formats are defined with ASCII FOURCC code. The pixel format codes are
- * the same used by V4L2 API.
- */
-
-/*! @{ */
-/*! @name Generic or Raw Data Formats */
-/*! @{ */
-#define IPU_PIX_FMT_GENERIC fourcc('I', 'P', 'U', '0') /*!< IPU Generic Data */
-#define IPU_PIX_FMT_GENERIC_32 fourcc('I', 'P', 'U', '1') /*!< IPU Generic Data */
-#define IPU_PIX_FMT_LVDS666 fourcc('L', 'V', 'D', '6') /*!< IPU Generic Data */
-#define IPU_PIX_FMT_LVDS888 fourcc('L', 'V', 'D', '8') /*!< IPU Generic Data */
-/*! @} */
-/*! @name RGB Formats */
-/*! @{ */
-#define IPU_PIX_FMT_RGB332 fourcc('R', 'G', 'B', '1') /*!< 8 RGB-3-3-2 */
-#define IPU_PIX_FMT_RGB555 fourcc('R', 'G', 'B', 'O') /*!< 16 RGB-5-5-5 */
-#define IPU_PIX_FMT_RGB565 fourcc('R', 'G', 'B', 'P') /*!< 1 6 RGB-5-6-5 */
-#define IPU_PIX_FMT_RGB666 fourcc('R', 'G', 'B', '6') /*!< 18 RGB-6-6-6 */
-#define IPU_PIX_FMT_BGR666 fourcc('B', 'G', 'R', '6') /*!< 18 BGR-6-6-6 */
-#define IPU_PIX_FMT_BGR24 fourcc('B', 'G', 'R', '3') /*!< 24 BGR-8-8-8 */
-#define IPU_PIX_FMT_RGB24 fourcc('R', 'G', 'B', '3') /*!< 24 RGB-8-8-8 */
-#define IPU_PIX_FMT_GBR24 fourcc('G', 'B', 'R', '3') /*!< 24 GBR-8-8-8 */
-#define IPU_PIX_FMT_BGR32 fourcc('B', 'G', 'R', '4') /*!< 32 BGR-8-8-8-8 */
-#define IPU_PIX_FMT_BGRA32 fourcc('B', 'G', 'R', 'A') /*!< 32 BGR-8-8-8-8 */
-#define IPU_PIX_FMT_RGB32 fourcc('R', 'G', 'B', '4') /*!< 32 RGB-8-8-8-8 */
-#define IPU_PIX_FMT_RGBA32 fourcc('R', 'G', 'B', 'A') /*!< 32 RGB-8-8-8-8 */
-#define IPU_PIX_FMT_ABGR32 fourcc('A', 'B', 'G', 'R') /*!< 32 ABGR-8-8-8-8 */
-/*! @} */
-/*! @name YUV Interleaved Formats */
-/*! @{ */
-#define IPU_PIX_FMT_YUYV fourcc('Y', 'U', 'Y', 'V') /*!< 16 YUV 4:2:2 */
-#define IPU_PIX_FMT_UYVY fourcc('U', 'Y', 'V', 'Y') /*!< 16 YUV 4:2:2 */
-#define IPU_PIX_FMT_YVYU fourcc('Y', 'V', 'Y', 'U') /*!< 16 YVYU 4:2:2 */
-#define IPU_PIX_FMT_VYUY fourcc('V', 'Y', 'U', 'Y') /*!< 16 VYYU 4:2:2 */
-#define IPU_PIX_FMT_Y41P fourcc('Y', '4', '1', 'P') /*!< 12 YUV 4:1:1 */
-#define IPU_PIX_FMT_YUV444 fourcc('Y', '4', '4', '4') /*!< 24 YUV 4:4:4 */
-#define IPU_PIX_FMT_VYU444 fourcc('V', '4', '4', '4') /*!< 24 VYU 4:4:4 */
-/* two planes -- one Y, one Cb + Cr interleaved */
-#define IPU_PIX_FMT_NV12 fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */
-/*! @} */
-/*! @name YUV Planar Formats */
-/*! @{ */
-#define IPU_PIX_FMT_GREY fourcc('G', 'R', 'E', 'Y') /*!< 8 Greyscale */
-#define IPU_PIX_FMT_YVU410P fourcc('Y', 'V', 'U', '9') /*!< 9 YVU 4:1:0 */
-#define IPU_PIX_FMT_YUV410P fourcc('Y', 'U', 'V', '9') /*!< 9 YUV 4:1:0 */
-#define IPU_PIX_FMT_YVU420P fourcc('Y', 'V', '1', '2') /*!< 12 YVU 4:2:0 */
-#define IPU_PIX_FMT_YUV420P fourcc('I', '4', '2', '0') /*!< 12 YUV 4:2:0 */
-#define IPU_PIX_FMT_YUV420P2 fourcc('Y', 'U', '1', '2') /*!< 12 YUV 4:2:0 */
-#define IPU_PIX_FMT_YVU422P fourcc('Y', 'V', '1', '6') /*!< 16 YVU 4:2:2 */
-#define IPU_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P') /*!< 16 YUV 4:2:2 */
-/*! @} */
-
-/* IPU Driver channels definitions. */
-/* Note these are different from IDMA channels */
-#define IPU_MAX_CH 32
-#define _MAKE_CHAN(num, v_in, g_in, a_in, out) \
- ((num << 24) | (v_in << 18) | (g_in << 12) | (a_in << 6) | out)
-#define _MAKE_ALT_CHAN(ch) (ch | (IPU_MAX_CH << 24))
-#define IPU_CHAN_ID(ch) (ch >> 24)
-#define IPU_CHAN_ALT(ch) (ch & 0x02000000)
-#define IPU_CHAN_ALPHA_IN_DMA(ch) ((uint32_t) (ch >> 6) & 0x3F)
-#define IPU_CHAN_GRAPH_IN_DMA(ch) ((uint32_t) (ch >> 12) & 0x3F)
-#define IPU_CHAN_VIDEO_IN_DMA(ch) ((uint32_t) (ch >> 18) & 0x3F)
-#define IPU_CHAN_OUT_DMA(ch) ((uint32_t) (ch & 0x3F))
-#define NO_DMA 0x3F
-#define ALT 1
-/*!
- * Enumeration of IPU logical channels. An IPU logical channel is defined as a
- * combination of an input (memory to IPU), output (IPU to memory), and/or
- * secondary input IDMA channels and in some cases an Image Converter task.
- * Some channels consist of only an input or output.
- */
-typedef enum {
- CHAN_NONE = -1,
- MEM_ROT_ENC_MEM = _MAKE_CHAN(1, 45, NO_DMA, NO_DMA, 48),
- MEM_ROT_VF_MEM = _MAKE_CHAN(2, 46, NO_DMA, NO_DMA, 49),
- MEM_ROT_PP_MEM = _MAKE_CHAN(3, 47, NO_DMA, NO_DMA, 50),
-
- MEM_PRP_ENC_MEM = _MAKE_CHAN(4, 12, 14, 17, 20),
- MEM_PRP_VF_MEM = _MAKE_CHAN(5, 12, 14, 17, 21),
- MEM_PP_MEM = _MAKE_CHAN(6, 11, 15, 18, 22),
-
- MEM_DC_SYNC = _MAKE_CHAN(7, 28, NO_DMA, NO_DMA, NO_DMA),
- MEM_DC_ASYNC = _MAKE_CHAN(8, 41, NO_DMA, NO_DMA, NO_DMA),
- MEM_BG_SYNC = _MAKE_CHAN(9, 23, NO_DMA, 51, NO_DMA),
- MEM_FG_SYNC = _MAKE_CHAN(10, 27, NO_DMA, 31, NO_DMA),
-
- MEM_BG_ASYNC0 = _MAKE_CHAN(11, 24, NO_DMA, 52, NO_DMA),
- MEM_FG_ASYNC0 = _MAKE_CHAN(12, 29, NO_DMA, 33, NO_DMA),
- MEM_BG_ASYNC1 = _MAKE_ALT_CHAN(MEM_BG_ASYNC0),
- MEM_FG_ASYNC1 = _MAKE_ALT_CHAN(MEM_FG_ASYNC0),
-
- DIRECT_ASYNC0 = _MAKE_CHAN(13, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
- DIRECT_ASYNC1 = _MAKE_CHAN(14, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
-
- CSI_MEM0 = _MAKE_CHAN(15, NO_DMA, NO_DMA, NO_DMA, 0),
- CSI_MEM1 = _MAKE_CHAN(16, NO_DMA, NO_DMA, NO_DMA, 1),
- CSI_MEM2 = _MAKE_CHAN(17, NO_DMA, NO_DMA, NO_DMA, 2),
- CSI_MEM3 = _MAKE_CHAN(18, NO_DMA, NO_DMA, NO_DMA, 3),
-
- CSI_MEM = CSI_MEM0,
-
- CSI_PRP_ENC_MEM = _MAKE_CHAN(19, NO_DMA, NO_DMA, NO_DMA, 20),
- CSI_PRP_VF_MEM = _MAKE_CHAN(20, NO_DMA, NO_DMA, NO_DMA, 21),
-
- MEM_VDI_PRP_VF_MEM_P = _MAKE_CHAN(21, 8, 14, 17, 21),
- MEM_VDI_PRP_VF_MEM = _MAKE_CHAN(22, 9, 14, 17, 21),
- MEM_VDI_PRP_VF_MEM_N = _MAKE_CHAN(23, 10, 14, 17, 21),
-
- MEM_PP_ADC = CHAN_NONE,
- ADC_SYS2 = CHAN_NONE,
-
-} ipu_channel_t;
-
-/*!
- * Enumeration of types of buffers for a logical channel.
- */
-typedef enum {
- IPU_OUTPUT_BUFFER = 0, /*!< Buffer for output from IPU */
- IPU_ALPHA_IN_BUFFER = 1, /*!< Buffer for input to IPU */
- IPU_GRAPH_IN_BUFFER = 2, /*!< Buffer for input to IPU */
- IPU_VIDEO_IN_BUFFER = 3, /*!< Buffer for input to IPU */
- IPU_INPUT_BUFFER = IPU_VIDEO_IN_BUFFER,
- IPU_SEC_INPUT_BUFFER = IPU_GRAPH_IN_BUFFER,
-} ipu_buffer_t;
-
-#define IPU_PANEL_SERIAL 1
-#define IPU_PANEL_PARALLEL 2
-
-/*!
- * Enumeration of ADC channel operation mode.
- */
-typedef enum {
- Disable,
- WriteTemplateNonSeq,
- ReadTemplateNonSeq,
- WriteTemplateUnCon,
- ReadTemplateUnCon,
- WriteDataWithRS,
- WriteDataWoRS,
- WriteCmd
-} mcu_mode_t;
-
-/*!
- * Enumeration of ADC channel addressing mode.
- */
-typedef enum {
- FullWoBE,
- FullWithBE,
- XY
-} display_addressing_t;
-
-/*!
- * Union of initialization parameters for a logical channel.
- */
-typedef union {
- struct {
- uint32_t csi;
- uint32_t mipi_id;
- bool mipi_en;
- bool interlaced;
- } csi_mem;
- struct {
- uint32_t in_width;
- uint32_t in_height;
- uint32_t in_pixel_fmt;
- uint32_t out_width;
- uint32_t out_height;
- uint32_t out_pixel_fmt;
- uint32_t csi;
- } csi_prp_enc_mem;
- struct {
- uint32_t in_width;
- uint32_t in_height;
- uint32_t in_pixel_fmt;
- uint32_t out_width;
- uint32_t out_height;
- uint32_t out_pixel_fmt;
- uint32_t outh_resize_ratio;
- uint32_t outv_resize_ratio;
- } mem_prp_enc_mem;
- struct {
- uint32_t in_width;
- uint32_t in_height;
- uint32_t in_pixel_fmt;
- uint32_t out_width;
- uint32_t out_height;
- uint32_t out_pixel_fmt;
- } mem_rot_enc_mem;
- struct {
- uint32_t in_width;
- uint32_t in_height;
- uint32_t in_pixel_fmt;
- uint32_t out_width;
- uint32_t out_height;
- uint32_t out_pixel_fmt;
- bool graphics_combine_en;
- bool global_alpha_en;
- bool key_color_en;
- uint32_t csi;
- } csi_prp_vf_mem;
- struct {
- uint32_t in_width;
- uint32_t in_height;
- uint32_t in_pixel_fmt;
- uint32_t out_width;
- uint32_t out_height;
- uint32_t out_pixel_fmt;
- bool graphics_combine_en;
- bool global_alpha_en;
- bool key_color_en;
- display_port_t disp;
- uint32_t out_left;
- uint32_t out_top;
- } csi_prp_vf_adc;
- struct {
- uint32_t in_width;
- uint32_t in_height;
- uint32_t in_pixel_fmt;
- uint32_t out_width;
- uint32_t out_height;
- uint32_t out_pixel_fmt;
- uint32_t outh_resize_ratio;
- uint32_t outv_resize_ratio;
- bool graphics_combine_en;
- bool global_alpha_en;
- bool key_color_en;
- uint32_t in_g_pixel_fmt;
- uint8_t alpha;
- uint32_t key_color;
- bool alpha_chan_en;
- ipu_motion_sel motion_sel;
- enum v4l2_field field_fmt;
- } mem_prp_vf_mem;
- struct {
- uint32_t temp;
- } mem_prp_vf_adc;
- struct {
- uint32_t temp;
- } mem_rot_vf_mem;
- struct {
- uint32_t in_width;
- uint32_t in_height;
- uint32_t in_pixel_fmt;
- uint32_t out_width;
- uint32_t out_height;
- uint32_t out_pixel_fmt;
- uint32_t outh_resize_ratio;
- uint32_t outv_resize_ratio;
- bool graphics_combine_en;
- bool global_alpha_en;
- bool key_color_en;
- uint32_t in_g_pixel_fmt;
- uint8_t alpha;
- uint32_t key_color;
- bool alpha_chan_en;
- } mem_pp_mem;
- struct {
- uint32_t temp;
- } mem_rot_mem;
- struct {
- uint32_t in_width;
- uint32_t in_height;
- uint32_t in_pixel_fmt;
- uint32_t out_width;
- uint32_t out_height;
- uint32_t out_pixel_fmt;
- bool graphics_combine_en;
- bool global_alpha_en;
- bool key_color_en;
- display_port_t disp;
- uint32_t out_left;
- uint32_t out_top;
- } mem_pp_adc;
- struct {
- uint32_t di;
- bool interlaced;
- uint32_t in_pixel_fmt;
- uint32_t out_pixel_fmt;
- } mem_dc_sync;
- struct {
- uint32_t temp;
- } mem_sdc_fg;
- struct {
- uint32_t di;
- bool interlaced;
- uint32_t in_pixel_fmt;
- uint32_t out_pixel_fmt;
- bool alpha_chan_en;
- } mem_dp_bg_sync;
- struct {
- uint32_t temp;
- } mem_sdc_bg;
- struct {
- uint32_t di;
- bool interlaced;
- uint32_t in_pixel_fmt;
- uint32_t out_pixel_fmt;
- bool alpha_chan_en;
- } mem_dp_fg_sync;
- struct {
- uint32_t di;
- } direct_async;
- struct {
- display_port_t disp;
- mcu_mode_t ch_mode;
- uint32_t out_left;
- uint32_t out_top;
- } adc_sys1;
- struct {
- display_port_t disp;
- mcu_mode_t ch_mode;
- uint32_t out_left;
- uint32_t out_top;
- } adc_sys2;
-} ipu_channel_params_t;
-
-/*!
- * Enumeration of IPU interrupt sources.
- */
-enum ipu_irq_line {
- IPU_IRQ_CSI0_OUT_EOF = 0,
- IPU_IRQ_CSI1_OUT_EOF = 1,
- IPU_IRQ_CSI2_OUT_EOF = 2,
- IPU_IRQ_CSI3_OUT_EOF = 3,
- IPU_IRQ_VDI_P_IN_EOF = 8,
- IPU_IRQ_VDI_C_IN_EOF = 9,
- IPU_IRQ_VDI_N_IN_EOF = 10,
- IPU_IRQ_PP_IN_EOF = 11,
- IPU_IRQ_PRP_IN_EOF = 12,
- IPU_IRQ_PRP_GRAPH_IN_EOF = 14,
- IPU_IRQ_PP_GRAPH_IN_EOF = 15,
- IPU_IRQ_PRP_ALPHA_IN_EOF = 17,
- IPU_IRQ_PP_ALPHA_IN_EOF = 18,
- IPU_IRQ_PRP_ENC_OUT_EOF = 20,
- IPU_IRQ_PRP_VF_OUT_EOF = 21,
- IPU_IRQ_PP_OUT_EOF = 22,
- IPU_IRQ_BG_SYNC_EOF = 23,
- IPU_IRQ_BG_ASYNC_EOF = 24,
- IPU_IRQ_FG_SYNC_EOF = 27,
- IPU_IRQ_DC_SYNC_EOF = 28,
- IPU_IRQ_FG_ASYNC_EOF = 29,
- IPU_IRQ_FG_ALPHA_SYNC_EOF = 31,
-
- IPU_IRQ_FG_ALPHA_ASYNC_EOF = 33,
- IPU_IRQ_DC_READ_EOF = 40,
- IPU_IRQ_DC_ASYNC_EOF = 41,
- IPU_IRQ_DC_CMD1_EOF = 42,
- IPU_IRQ_DC_CMD2_EOF = 43,
- IPU_IRQ_DC_MASK_EOF = 44,
- IPU_IRQ_PRP_ENC_ROT_IN_EOF = 45,
- IPU_IRQ_PRP_VF_ROT_IN_EOF = 46,
- IPU_IRQ_PP_ROT_IN_EOF = 47,
- IPU_IRQ_PRP_ENC_ROT_OUT_EOF = 48,
- IPU_IRQ_PRP_VF_ROT_OUT_EOF = 49,
- IPU_IRQ_PP_ROT_OUT_EOF = 50,
- IPU_IRQ_BG_ALPHA_SYNC_EOF = 51,
- IPU_IRQ_BG_ALPHA_ASYNC_EOF = 52,
-
- IPU_IRQ_DP_SF_START = 448 + 2,
- IPU_IRQ_DP_SF_END = 448 + 3,
- IPU_IRQ_BG_SF_END = IPU_IRQ_DP_SF_END,
- IPU_IRQ_DC_FC_0 = 448 + 8,
- IPU_IRQ_DC_FC_1 = 448 + 9,
- IPU_IRQ_DC_FC_2 = 448 + 10,
- IPU_IRQ_DC_FC_3 = 448 + 11,
- IPU_IRQ_DC_FC_4 = 448 + 12,
- IPU_IRQ_DC_FC_6 = 448 + 13,
- IPU_IRQ_VSYNC_PRE_0 = 448 + 14,
- IPU_IRQ_VSYNC_PRE_1 = 448 + 15,
-
- IPU_IRQ_COUNT
-};
-
-/*!
- * Bitfield of Display Interface signal polarities.
- */
-typedef struct {
- unsigned datamask_en:1;
- unsigned int_clk:1;
- unsigned interlaced:1;
- unsigned odd_field_first:1;
- unsigned clksel_en:1;
- unsigned clkidle_en:1;
- unsigned data_pol:1; /* true = inverted */
- unsigned clk_pol:1; /* true = rising edge */
- unsigned enable_pol:1;
- unsigned Hsync_pol:1; /* true = active high */
- unsigned Vsync_pol:1;
-} ipu_di_signal_cfg_t;
-
-/*!
- * Bitfield of CSI signal polarities and modes.
- */
-
-typedef struct {
- unsigned data_width:4;
- unsigned clk_mode:3;
- unsigned ext_vsync:1;
- unsigned Vsync_pol:1;
- unsigned Hsync_pol:1;
- unsigned pixclk_pol:1;
- unsigned data_pol:1;
- unsigned sens_clksrc:1;
- unsigned pack_tight:1;
- unsigned force_eof:1;
- unsigned data_en_pol:1;
- unsigned data_fmt;
- unsigned csi;
- unsigned mclk;
-} ipu_csi_signal_cfg_t;
-
-/*!
- * Enumeration of CSI data bus widths.
- */
-enum {
- IPU_CSI_DATA_WIDTH_4,
- IPU_CSI_DATA_WIDTH_8,
- IPU_CSI_DATA_WIDTH_10,
- IPU_CSI_DATA_WIDTH_16,
-};
-
-/*!
- * Enumeration of CSI clock modes.
- */
-enum {
- IPU_CSI_CLK_MODE_GATED_CLK,
- IPU_CSI_CLK_MODE_NONGATED_CLK,
- IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
- IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
- IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
- IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
- IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
- IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
-};
-
-enum {
- IPU_CSI_MIPI_DI0,
- IPU_CSI_MIPI_DI1,
- IPU_CSI_MIPI_DI2,
- IPU_CSI_MIPI_DI3,
-};
-
-typedef enum {
- RGB,
- YCbCr,
- YUV
-} ipu_color_space_t;
-
-/*!
- * Enumeration of ADC vertical sync mode.
- */
-typedef enum {
- VsyncNone,
- VsyncInternal,
- VsyncCSI,
- VsyncExternal
-} vsync_t;
-
-typedef enum {
- DAT,
- CMD
-} cmddata_t;
-
-/*!
- * Enumeration of ADC display update mode.
- */
-typedef enum {
- IPU_ADC_REFRESH_NONE,
- IPU_ADC_AUTO_REFRESH,
- IPU_ADC_AUTO_REFRESH_SNOOP,
- IPU_ADC_SNOOPING,
-} ipu_adc_update_mode_t;
-
-/*!
- * Enumeration of ADC display interface types (serial or parallel).
- */
-enum {
- IPU_ADC_IFC_MODE_SYS80_TYPE1,
- IPU_ADC_IFC_MODE_SYS80_TYPE2,
- IPU_ADC_IFC_MODE_SYS68K_TYPE1,
- IPU_ADC_IFC_MODE_SYS68K_TYPE2,
- IPU_ADC_IFC_MODE_3WIRE_SERIAL,
- IPU_ADC_IFC_MODE_4WIRE_SERIAL,
- IPU_ADC_IFC_MODE_5WIRE_SERIAL_CLK,
- IPU_ADC_IFC_MODE_5WIRE_SERIAL_CS,
-};
-
-enum {
- IPU_ADC_IFC_WIDTH_8,
- IPU_ADC_IFC_WIDTH_16,
-};
-
-/*!
- * Enumeration of ADC display interface burst mode.
- */
-enum {
- IPU_ADC_BURST_WCS,
- IPU_ADC_BURST_WBLCK,
- IPU_ADC_BURST_NONE,
- IPU_ADC_BURST_SERIAL,
-};
-
-/*!
- * Enumeration of ADC display interface RW signal timing modes.
- */
-enum {
- IPU_ADC_SER_NO_RW,
- IPU_ADC_SER_RW_BEFORE_RS,
- IPU_ADC_SER_RW_AFTER_RS,
-};
-
-/*!
- * Bitfield of ADC signal polarities and modes.
- */
-typedef struct {
- unsigned data_pol:1;
- unsigned clk_pol:1;
- unsigned cs_pol:1;
- unsigned rs_pol:1;
- unsigned addr_pol:1;
- unsigned read_pol:1;
- unsigned write_pol:1;
- unsigned Vsync_pol:1;
- unsigned burst_pol:1;
- unsigned burst_mode:2;
- unsigned ifc_mode:3;
- unsigned ifc_width:5;
- unsigned ser_preamble_len:4;
- unsigned ser_preamble:8;
- unsigned ser_rw_mode:2;
-} ipu_adc_sig_cfg_t;
-
-/*!
- * Enumeration of ADC template commands.
- */
-enum {
- RD_DATA,
- RD_ACK,
- RD_WAIT,
- WR_XADDR,
- WR_YADDR,
- WR_ADDR,
- WR_CMND,
- WR_DATA,
-};
-
-/*!
- * Enumeration of ADC template command flow control.
- */
-enum {
- SINGLE_STEP,
- PAUSE,
- STOP,
-};
-
-
-/*Define template constants*/
-#define ATM_ADDR_RANGE 0x20 /*offset address of DISP */
-#define TEMPLATE_BUF_SIZE 0x20 /*size of template */
-
-/*!
- * Define to create ADC template command entry.
- */
-#define ipu_adc_template_gen(oc, rs, fc, dat) (((rs) << 29) | ((fc) << 27) | \
- ((oc) << 24) | (dat))
-
-typedef struct {
- u32 reg;
- u32 value;
-} ipu_lpmc_reg_t;
-
-#define IPU_LPMC_REG_READ 0x80000000L
-
-#define CSI_MCLK_VF 1
-#define CSI_MCLK_ENC 2
-#define CSI_MCLK_RAW 4
-#define CSI_MCLK_I2C 8
-
-struct ipu_soc;
-/* Common IPU API */
-struct ipu_soc *ipu_get_soc(int id);
-int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params);
-void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel);
-
-static inline bool ipu_can_rotate_in_place(ipu_rotate_mode_t rot)
-{
-#ifdef CONFIG_MXC_IPU_V3D
- return (rot < IPU_ROTATE_HORIZ_FLIP);
-#else
- return (rot < IPU_ROTATE_90_RIGHT);
-#endif
-}
-
-int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- uint32_t pixel_fmt,
- uint16_t width, uint16_t height,
- uint32_t stride,
- ipu_rotate_mode_t rot_mode,
- dma_addr_t phyaddr_0, dma_addr_t phyaddr_1,
- dma_addr_t phyaddr_2,
- uint32_t u_offset, uint32_t v_offset);
-
-int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- uint32_t bufNum, dma_addr_t phyaddr);
-
-int32_t ipu_update_channel_offset(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- uint32_t pixel_fmt,
- uint16_t width, uint16_t height,
- uint32_t stride,
- uint32_t u, uint32_t v,
- uint32_t vertical_offset, uint32_t horizontal_offset);
-
-int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
- ipu_buffer_t type, uint32_t bufNum);
-int32_t ipu_select_multi_vdi_buffer(struct ipu_soc *ipu, uint32_t bufNum);
-
-int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch);
-int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch);
-
-int32_t ipu_is_channel_busy(struct ipu_soc *ipu, ipu_channel_t channel);
-int32_t ipu_check_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- uint32_t bufNum);
-void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- uint32_t bufNum);
-uint32_t ipu_get_cur_buffer_idx(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type);
-int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel);
-int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wait_for_stop);
-int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel_t to_ch);
-
-int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi);
-int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi);
-
-int ipu_lowpwr_display_enable(void);
-int ipu_lowpwr_display_disable(void);
-
-void ipu_enable_irq(struct ipu_soc *ipu, uint32_t irq);
-void ipu_disable_irq(struct ipu_soc *ipu, uint32_t irq);
-void ipu_clear_irq(struct ipu_soc *ipu, uint32_t irq);
-int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
- irqreturn_t(*handler) (int, void *),
- uint32_t irq_flags, const char *devname, void *dev_id);
-void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id);
-bool ipu_get_irq_status(struct ipu_soc *ipu, uint32_t irq);
-void ipu_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3]);
-
-/* two stripe calculations */
-struct stripe_param{
- unsigned int input_width; /* width of the input stripe */
- unsigned int output_width; /* width of the output stripe */
- unsigned int input_column; /* the first column on the input stripe */
- unsigned int output_column; /* the first column on the output stripe */
- unsigned int idr;
- /* inverse downisizing ratio parameter; expressed as a power of 2 */
- unsigned int irr;
- /* inverse resizing ratio parameter; expressed as a multiple of 2^-13 */
-};
-int ipu_calc_stripes_sizes(const unsigned int input_frame_width,
- unsigned int output_frame_width,
- const unsigned int maximal_stripe_width,
- const unsigned long long cirr,
- const unsigned int equal_stripes,
- u32 input_pixelformat,
- u32 output_pixelformat,
- struct stripe_param *left,
- struct stripe_param *right);
-
-/* SDC API */
-int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp,
- uint32_t pixel_clk,
- uint16_t width, uint16_t height,
- uint32_t pixel_fmt,
- uint16_t h_start_width, uint16_t h_sync_width,
- uint16_t h_end_width, uint16_t v_start_width,
- uint16_t v_sync_width, uint16_t v_end_width,
- uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig);
-
-void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp);
-
-int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel, int16_t x_pos,
- int16_t y_pos);
-int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel, int16_t *x_pos,
- int16_t *y_pos);
-int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
- uint8_t alpha);
-int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
- uint32_t colorKey);
-int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
- int constk[], int slopek[]);
-
-int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle_time,
- uint32_t pixel_fmt, ipu_adc_sig_cfg_t sig);
-void ipu_disp_direct_write(struct ipu_soc *ipu, ipu_channel_t channel, u32 value, u32 offset);
-void ipu_reset_disp_panel(struct ipu_soc *ipu);
-
-/* CMOS Sensor Interface API */
-int32_t ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
- uint32_t pixel_fmt, ipu_csi_signal_cfg_t sig);
-
-int32_t ipu_csi_get_sensor_protocol(struct ipu_soc *ipu, uint32_t csi);
-
-int32_t ipu_csi_enable_mclk(struct ipu_soc *ipu, int src, bool flag, bool wait);
-
-static inline int32_t ipu_csi_enable_mclk_if(struct ipu_soc *ipu, int src, uint32_t csi,
- bool flag, bool wait)
-{
- return ipu_csi_enable_mclk(ipu, csi, flag, wait);
-}
-
-int ipu_csi_read_mclk_flag(void);
-
-void ipu_csi_flash_strobe(bool flag);
-
-void ipu_csi_get_window_size(struct ipu_soc *ipu, uint32_t *width, uint32_t *height, uint32_t csi);
-
-void ipu_csi_set_window_size(struct ipu_soc *ipu, uint32_t width, uint32_t height, uint32_t csi);
-
-void ipu_csi_set_window_pos(struct ipu_soc *ipu, uint32_t left, uint32_t top, uint32_t csi);
-
-uint32_t bytes_per_pixel(uint32_t fmt);
-
struct ipuv3_fb_platform_data {
char disp_dev[32];
u32 interface_pix_fmt;
diff --git a/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c b/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c
index c4e5b4012c5..8c13a36312b 100644
--- a/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c
+++ b/drivers/mxc/ipu3/ipu_calc_stripes_sizes.c
@@ -21,7 +21,6 @@
#include <linux/module.h>
#include <linux/ipu.h>
-#include <mach/ipu-v3.h>
#include <asm/div64.h>
#define BPP_32 0
diff --git a/drivers/mxc/ipu3/ipu_capture.c b/drivers/mxc/ipu3/ipu_capture.c
index 26b8b1573ca..88b1a3954ae 100644
--- a/drivers/mxc/ipu3/ipu_capture.c
+++ b/drivers/mxc/ipu3/ipu_capture.c
@@ -94,9 +94,10 @@ ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
cfg_param.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
cfg_param.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
- _ipu_get(ipu);
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
ipu_csi_write(ipu, csi, data, CSI_SENS_CONF);
@@ -135,10 +136,11 @@ ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
ipu_csi_write(ipu, csi, 0x40596, CSI_CCIR_CODE_2);
ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
} else {
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
dev_err(ipu->dev, "Unsupported CCIR656 interlaced "
"video mode\n");
- _ipu_unlock(ipu, &lock_flags);
- _ipu_put(ipu);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
return -EINVAL;
}
_ipu_csi_ccir_err_detection_enable(ipu, csi);
@@ -163,9 +165,10 @@ ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
dev_dbg(ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
ipu_csi_read(ipu, csi, CSI_ACT_FRM_SIZE));
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
- _ipu_put(ipu);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
return 0;
}
@@ -253,17 +256,19 @@ void ipu_csi_get_window_size(struct ipu_soc *ipu, uint32_t *width, uint32_t *hei
uint32_t reg;
unsigned long lock_flags;
- _ipu_get(ipu);
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
reg = ipu_csi_read(ipu, csi, CSI_ACT_FRM_SIZE);
*width = (reg & 0xFFFF) + 1;
*height = (reg >> 16 & 0xFFFF) + 1;
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
- _ipu_put(ipu);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
EXPORT_SYMBOL(ipu_csi_get_window_size);
@@ -279,15 +284,17 @@ void ipu_csi_set_window_size(struct ipu_soc *ipu, uint32_t width, uint32_t heigh
{
unsigned long lock_flags;
- _ipu_get(ipu);
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
ipu_csi_write(ipu, csi, (width - 1) | (height - 1) << 16, CSI_ACT_FRM_SIZE);
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
- _ipu_put(ipu);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
EXPORT_SYMBOL(ipu_csi_set_window_size);
@@ -304,18 +311,20 @@ void ipu_csi_set_window_pos(struct ipu_soc *ipu, uint32_t left, uint32_t top, ui
uint32_t temp;
unsigned long lock_flags;
- _ipu_get(ipu);
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
temp &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
temp |= ((top << CSI_VSC_SHIFT) | (left << CSI_HSC_SHIFT));
ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
- _ipu_put(ipu);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
EXPORT_SYMBOL(ipu_csi_set_window_pos);
@@ -329,10 +338,21 @@ EXPORT_SYMBOL(ipu_csi_set_window_pos);
void _ipu_csi_horizontal_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
{
uint32_t temp;
+ unsigned long lock_flags;
+
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
temp |= CSI_HORI_DOWNSIZE_EN;
ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
+
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
/*!
@@ -345,10 +365,21 @@ void _ipu_csi_horizontal_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
void _ipu_csi_horizontal_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
{
uint32_t temp;
+ unsigned long lock_flags;
+
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
temp &= ~CSI_HORI_DOWNSIZE_EN;
ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
+
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
/*!
@@ -361,10 +392,21 @@ void _ipu_csi_horizontal_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
void _ipu_csi_vertical_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
{
uint32_t temp;
+ unsigned long lock_flags;
+
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
temp |= CSI_VERT_DOWNSIZE_EN;
ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
+
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
/*!
@@ -377,14 +419,25 @@ void _ipu_csi_vertical_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
void _ipu_csi_vertical_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
{
uint32_t temp;
+ unsigned long lock_flags;
+
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
temp &= ~CSI_VERT_DOWNSIZE_EN;
ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
+
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
/*!
- * _ipu_csi_set_test_generator
+ * ipu_csi_set_test_generator
*
* @param ipu ipu handler
* @param active 1 for active and 0 for inactive
@@ -395,10 +448,16 @@ void _ipu_csi_vertical_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
* @param pixel_clk desired pixel clock frequency in Hz
* @param csi csi 0 or csi 1
*/
-void _ipu_csi_set_test_generator(struct ipu_soc *ipu, bool active, uint32_t r_value,
+void ipu_csi_set_test_generator(struct ipu_soc *ipu, bool active, uint32_t r_value,
uint32_t g_value, uint32_t b_value, uint32_t pix_clk, uint32_t csi)
{
uint32_t temp;
+ unsigned long lock_flags;
+
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
temp = ipu_csi_read(ipu, csi, CSI_TST_CTRL);
@@ -417,7 +476,13 @@ void _ipu_csi_set_test_generator(struct ipu_soc *ipu, bool active, uint32_t r_va
(b_value << CSI_TEST_GEN_B_SHIFT);
ipu_csi_write(ipu, csi, temp, CSI_TST_CTRL);
}
+
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
+EXPORT_SYMBOL(ipu_csi_set_test_generator);
/*!
* _ipu_csi_ccir_err_detection_en
@@ -431,10 +496,15 @@ void _ipu_csi_ccir_err_detection_enable(struct ipu_soc *ipu, uint32_t csi)
{
uint32_t temp;
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+
temp = ipu_csi_read(ipu, csi, CSI_CCIR_CODE_1);
temp |= CSI_CCIR_ERR_DET_EN;
ipu_csi_write(ipu, csi, temp, CSI_CCIR_CODE_1);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
/*!
@@ -449,10 +519,15 @@ void _ipu_csi_ccir_err_detection_disable(struct ipu_soc *ipu, uint32_t csi)
{
uint32_t temp;
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+
temp = ipu_csi_read(ipu, csi, CSI_CCIR_CODE_1);
temp &= ~CSI_CCIR_ERR_DET_EN;
ipu_csi_write(ipu, csi, temp, CSI_CCIR_CODE_1);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
/*!
@@ -469,12 +544,18 @@ int _ipu_csi_set_mipi_di(struct ipu_soc *ipu, uint32_t num, uint32_t di_val, uin
{
uint32_t temp;
int retval = 0;
+ unsigned long lock_flags;
if (di_val > 0xFFL) {
retval = -EINVAL;
goto err;
}
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+
temp = ipu_csi_read(ipu, csi, CSI_MIPI_DI);
switch (num) {
@@ -502,6 +583,9 @@ int _ipu_csi_set_mipi_di(struct ipu_soc *ipu, uint32_t num, uint32_t di_val, uin
retval = -EINVAL;
}
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
err:
return retval;
}
@@ -522,18 +606,27 @@ int _ipu_csi_set_skip_isp(struct ipu_soc *ipu, uint32_t skip, uint32_t max_ratio
{
uint32_t temp;
int retval = 0;
+ unsigned long lock_flags;
if (max_ratio > 5) {
retval = -EINVAL;
goto err;
}
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+
temp = ipu_csi_read(ipu, csi, CSI_SKIP);
temp &= ~(CSI_MAX_RATIO_SKIP_ISP_MASK | CSI_SKIP_ISP_MASK);
temp |= (max_ratio << CSI_MAX_RATIO_SKIP_ISP_SHIFT) |
(skip << CSI_SKIP_ISP_SHIFT);
ipu_csi_write(ipu, csi, temp, CSI_SKIP);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
err:
return retval;
}
@@ -556,12 +649,18 @@ int _ipu_csi_set_skip_smfc(struct ipu_soc *ipu, uint32_t skip,
{
uint32_t temp;
int retval = 0;
+ unsigned long lock_flags;
if (max_ratio > 5 || id > 3) {
retval = -EINVAL;
goto err;
}
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+
temp = ipu_csi_read(ipu, csi, CSI_SKIP);
temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
CSI_SKIP_SMFC_MASK);
@@ -570,6 +669,10 @@ int _ipu_csi_set_skip_smfc(struct ipu_soc *ipu, uint32_t skip,
(skip << CSI_SKIP_SMFC_SHIFT);
ipu_csi_write(ipu, csi, temp, CSI_SKIP);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
err:
return retval;
}
@@ -627,6 +730,12 @@ void _ipu_smfc_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t mipi_id
void _ipu_smfc_set_wmc(struct ipu_soc *ipu, ipu_channel_t channel, bool set, uint32_t level)
{
uint32_t temp;
+ unsigned long lock_flags;
+
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
temp = ipu_smfc_read(ipu, SMFC_WMC);
@@ -672,6 +781,10 @@ void _ipu_smfc_set_wmc(struct ipu_soc *ipu, ipu_channel_t channel, bool set, uin
}
ipu_smfc_write(ipu, temp, SMFC_WMC);
+
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
/*!
@@ -685,6 +798,9 @@ void _ipu_smfc_set_wmc(struct ipu_soc *ipu, ipu_channel_t channel, bool set, uin
void _ipu_smfc_set_burst_size(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t bs)
{
uint32_t temp;
+ unsigned long lock_flags;
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
temp = ipu_smfc_read(ipu, SMFC_BS);
@@ -710,6 +826,8 @@ void _ipu_smfc_set_burst_size(struct ipu_soc *ipu, ipu_channel_t channel, uint32
}
ipu_smfc_write(ipu, temp, SMFC_BS);
+
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
}
/*!
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c
index fb06f56b1a9..3e099d9e0f1 100644
--- a/drivers/mxc/ipu3/ipu_common.c
+++ b/drivers/mxc/ipu3/ipu_common.c
@@ -30,11 +30,11 @@
#include <linux/irqdesc.h>
#include <linux/ipu.h>
#include <linux/clk.h>
+#include <linux/clkdev.h>
#include <mach/clock.h>
#include <mach/hardware.h>
+#include <mach/ipu-v3.h>
#include <mach/devices-common.h>
-#include <asm/cacheflush.h>
-#include <linux/delay.h>
#include "ipu_prv.h"
#include "ipu_regs.h"
@@ -112,10 +112,156 @@ static int ipu_reset(struct ipu_soc *ipu)
return 0;
}
+static inline struct ipu_soc *pixelclk2ipu(struct clk *clk)
+{
+ struct ipu_soc *ipu;
+ struct clk *base = clk - clk->id;
+
+ ipu = container_of(base, struct ipu_soc, pixel_clk[0]);
+
+ return ipu;
+}
+
+static unsigned long _ipu_pixel_clk_get_rate(struct clk *clk)
+{
+ struct ipu_soc *ipu = pixelclk2ipu(clk);
+ u32 div = ipu_di_read(ipu, clk->id, DI_BS_CLKGEN0);
+ if (div == 0)
+ return 0;
+ return (clk_get_rate(clk->parent) * 16) / div;
+}
+
+static unsigned long _ipu_pixel_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent) * 16;
+ /*
+ * Calculate divider
+ * Fractional part is 4 bits,
+ * so simply multiply by 2^4 to get fractional part.
+ */
+ div = parent_rate / rate;
+
+ if (div < 0x10) /* Min DI disp clock divider is 1 */
+ div = 0x10;
+ if (div & ~0xFEF)
+ div &= 0xFF8;
+ else {
+ /* Round up divider if it gets us closer to desired pix clk */
+ if ((div & 0xC) == 0xC) {
+ div += 0x10;
+ div &= ~0xF;
+ }
+ }
+ return parent_rate / div;
+}
+
+static int _ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct ipu_soc *ipu = pixelclk2ipu(clk);
+ u32 div = (clk_get_rate(clk->parent) * 16) / rate;
+ unsigned long lock_flags;
+
+ /* Round up divider if it gets us closer to desired pix clk */
+ if ((div & 0xC) == 0xC) {
+ div += 0x10;
+ div &= ~0xF;
+ }
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+ ipu_di_write(ipu, clk->id, div, DI_BS_CLKGEN0);
+
+ /* Setup pixel clock timing */
+ /* FIXME: needs to be more flexible */
+ /* Down time is half of period */
+ ipu_di_write(ipu, clk->id, (div / 16) << 16, DI_BS_CLKGEN1);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+
+ return 0;
+}
+
+static int _ipu_pixel_clk_enable(struct clk *clk)
+{
+ struct ipu_soc *ipu = pixelclk2ipu(clk);
+ u32 disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
+ disp_gen |= clk->id ? DI1_COUNTER_RELEASE : DI0_COUNTER_RELEASE;
+ ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
+
+ return 0;
+}
+
+static void _ipu_pixel_clk_disable(struct clk *clk)
+{
+ struct ipu_soc *ipu = pixelclk2ipu(clk);
+
+ u32 disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
+ disp_gen &= clk->id ? ~DI1_COUNTER_RELEASE : ~DI0_COUNTER_RELEASE;
+ ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
+}
+
+static int _ipu_pixel_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct ipu_soc *ipu = pixelclk2ipu(clk);
+ unsigned long lock_flags;
+ u32 di_gen;
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+ di_gen = ipu_di_read(ipu, clk->id, DI_GENERAL);
+ if (parent == ipu->ipu_clk)
+ di_gen &= ~DI_GEN_DI_CLK_EXT;
+ else if (!IS_ERR(ipu->di_clk[clk->id]) && parent == ipu->di_clk[clk->id])
+ di_gen |= DI_GEN_DI_CLK_EXT;
+ else {
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+ return -EINVAL;
+ }
+
+ ipu_di_write(ipu, clk->id, di_gen, DI_GENERAL);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+ return 0;
+}
+
+#ifdef CONFIG_CLK_DEBUG
+#define __INIT_CLK_DEBUG(n) .name = #n,
+#else
+#define __INIT_CLK_DEBUG(n)
+#endif
static int __devinit ipu_clk_setup_enable(struct ipu_soc *ipu,
struct platform_device *pdev)
{
struct imx_ipuv3_platform_data *plat_data = pdev->dev.platform_data;
+ static struct clk ipu_pixel_clk[] = {
+ {
+ __INIT_CLK_DEBUG(pixel_clk_0)
+ .id = 0,
+ .get_rate = _ipu_pixel_clk_get_rate,
+ .set_rate = _ipu_pixel_clk_set_rate,
+ .round_rate = _ipu_pixel_clk_round_rate,
+ .set_parent = _ipu_pixel_clk_set_parent,
+ .enable = _ipu_pixel_clk_enable,
+ .disable = _ipu_pixel_clk_disable,
+ },
+ {
+ __INIT_CLK_DEBUG(pixel_clk_1)
+ .id = 1,
+ .get_rate = _ipu_pixel_clk_get_rate,
+ .set_rate = _ipu_pixel_clk_set_rate,
+ .round_rate = _ipu_pixel_clk_round_rate,
+ .set_parent = _ipu_pixel_clk_set_parent,
+ .enable = _ipu_pixel_clk_enable,
+ .disable = _ipu_pixel_clk_disable,
+ },
+ };
+ static struct clk_lookup ipu_lookups[] = {
+ {
+ .dev_id = NULL,
+ .con_id = "pixel_clk_0",
+ },
+ {
+ .dev_id = NULL,
+ .con_id = "pixel_clk_1",
+ },
+ };
char ipu_clk[] = "ipu1_clk";
char di0_clk[] = "ipu1_di0_clk";
char di1_clk[] = "ipu1_di1_clk";
@@ -156,35 +302,180 @@ static int __devinit ipu_clk_setup_enable(struct ipu_soc *ipu,
return 0;
}
-struct ipu_soc *ipu_get_soc(int id)
+#if 0
+static void ipu_irq_handler(unsigned int irq, struct irq_desc *desc)
{
- if (id >= MXC_IPU_MAX_NUM)
- return ERR_PTR(-ENODEV);
- else
- return &(ipu_array[id]);
+ struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
+ const int int_reg[] = { 1, 2, 3, 4, 11, 12, 13, 14, 15, 0 };
+ u32 status;
+ int i, line;
+
+ for (i = 0;; i++) {
+ if (int_reg[i] == 0)
+ break;
+
+ status = ipu_cm_read(ipu, IPU_INT_STAT(int_reg[i]));
+ status &= ipu_cm_read(ipu, IPU_INT_CTRL(int_reg[i]));
+
+ while ((line = ffs(status))) {
+ line--;
+ status &= ~(1UL << line);
+ line += ipu->irq_start + (int_reg[i] - 1) * 32;
+ generic_handle_irq(line);
+ }
+
+ }
}
-EXPORT_SYMBOL_GPL(ipu_get_soc);
-void _ipu_lock(struct ipu_soc *ipu, unsigned long *flags)
+static void ipu_err_irq_handler(unsigned int irq, struct irq_desc *desc)
{
- spin_lock_irqsave(&ipu->spin_lock, *flags);
+ struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
+ const int int_reg[] = { 5, 6, 9, 10, 0 };
+ u32 status;
+ int i, line;
+
+ for (i = 0;; i++) {
+ if (int_reg[i] == 0)
+ break;
+
+ status = ipu_cm_read(ipu, IPU_INT_STAT(int_reg[i]));
+ status &= ipu_cm_read(ipu, IPU_INT_CTRL(int_reg[i]));
+
+ while ((line = ffs(status))) {
+ line--;
+ status &= ~(1UL << line);
+ line += ipu->irq_start + (int_reg[i] - 1) * 32;
+ generic_handle_irq(line);
+ }
+
+ }
}
-void _ipu_unlock(struct ipu_soc *ipu, unsigned long *flags)
+static void ipu_ack_irq(struct irq_data *d)
{
- spin_unlock_irqrestore(&ipu->spin_lock, *flags);
+ struct ipu_soc *ipu = irq_data_get_irq_chip_data(d);
+ unsigned int irq = d->irq - ipu->irq_start;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ipu->ipu_lock, flags);
+ ipu_cm_write(ipu, 1 << (irq % 32), IPU_INT_STAT(irq / 32 + 1));
+ spin_unlock_irqrestore(&ipu->ipu_lock, flags);
}
-void _ipu_get(struct ipu_soc *ipu)
+static void ipu_unmask_irq(struct irq_data *d)
{
- if (ipu->ipu_use_count++ == 0)
- clk_enable(ipu->ipu_clk);
+ struct ipu_soc *ipu = irq_data_get_irq_chip_data(d);
+ unsigned int irq = d->irq - ipu->irq_start;
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&ipu->ipu_lock, flags);
+ reg = ipu_cm_read(ipu, IPU_INT_CTRL(irq / 32 + 1));
+ reg |= 1 << (irq % 32);
+ ipu_cm_write(ipu, reg, IPU_INT_CTRL(irq / 32 + 1));
+ spin_unlock_irqrestore(&ipu->ipu_lock, flags);
}
-void _ipu_put(struct ipu_soc *ipu)
+static void ipu_mask_irq(struct irq_data *d)
{
- if (--ipu->ipu_use_count == 0)
- clk_disable(ipu->ipu_clk);
+ struct ipu_soc *ipu = irq_data_get_irq_chip_data(d);
+ unsigned int irq = d->irq - ipu->irq_start;
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&ipu->ipu_lock, flags);
+ reg = ipu_cm_read(ipu, IPU_INT_CTRL(irq / 32 + 1));
+ reg &= ~(1 << (irq % 32));
+ ipu_cm_write(ipu, reg, IPU_INT_CTRL(irq / 32 + 1));
+ spin_unlock_irqrestore(&ipu->ipu_lock, flags);
+}
+
+static struct irq_chip ipu_irq_chip = {
+ .name = "IPU",
+ .irq_ack = ipu_ack_irq,
+ .irq_mask = ipu_mask_irq,
+ .irq_unmask = ipu_unmask_irq,
+};
+
+static void __devinit ipu_irq_setup(struct ipu_soc *ipu)
+{
+ int i;
+
+ for (i = ipu->irq_start; i < ipu->irq_start + MX5_IPU_IRQS; i++) {
+ irq_set_chip_and_handler(i, &ipu_irq_chip, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID);
+ irq_set_chip_data(i, ipu);
+ }
+
+ irq_set_chained_handler(ipu->irq_sync, ipu_irq_handler);
+ irq_set_handler_data(ipu->irq_sync, ipu);
+ irq_set_chained_handler(ipu->irq_err, ipu_err_irq_handler);
+ irq_set_handler_data(ipu->irq_err, ipu);
+}
+
+int ipu_request_irq(struct ipu_soc *ipu, unsigned int irq,
+ irq_handler_t handler, unsigned long flags,
+ const char *name, void *dev)
+{
+ return request_irq(ipu->irq_start + irq, handler, flags, name, dev);
+}
+EXPORT_SYMBOL_GPL(ipu_request_irq);
+
+void ipu_enable_irq(struct ipu_soc *ipu, unsigned int irq)
+{
+ return enable_irq(ipu->irq_start + irq);
+}
+EXPORT_SYMBOL_GPL(ipu_disable_irq);
+
+void ipu_disable_irq(struct ipu_soc *ipu, unsigned int irq)
+{
+ return disable_irq(ipu->irq_start + irq);
+}
+EXPORT_SYMBOL_GPL(ipu_disable_irq);
+
+void ipu_free_irq(struct ipu_soc *ipu, unsigned int irq, void *dev_id)
+{
+ free_irq(ipu->irq_start + irq, dev_id);
+}
+EXPORT_SYMBOL_GPL(ipu_free_irq);
+
+static irqreturn_t ipu_completion_handler(int irq, void *dev)
+{
+ struct completion *completion = dev;
+
+ complete(completion);
+ return IRQ_HANDLED;
+}
+
+int ipu_wait_for_interrupt(struct ipu_soc *ipu, int interrupt, int timeout_ms)
+{
+ DECLARE_COMPLETION_ONSTACK(completion);
+ int ret;
+
+ ret = ipu_request_irq(ipu, interrupt, ipu_completion_handler,
+ 0, NULL, &completion);
+ if (ret) {
+ dev_err(ipu->dev,
+ "ipu request irq %d fail\n", interrupt);
+ return ret;
+ }
+
+ ret = wait_for_completion_timeout(&completion,
+ msecs_to_jiffies(timeout_ms));
+
+ ipu_free_irq(ipu, interrupt, &completion);
+
+ return ret > 0 ? 0 : -ETIMEDOUT;
+}
+EXPORT_SYMBOL_GPL(ipu_wait_for_interrupt);
+#endif
+
+struct ipu_soc *ipu_get_soc(int id)
+{
+ if (id >= MXC_IPU_MAX_NUM)
+ return ERR_PTR(-ENODEV);
+ else
+ return &(ipu_array[id]);
}
/*!
@@ -210,8 +501,7 @@ static int __devinit ipu_probe(struct platform_device *pdev)
ipu = &ipu_array[pdev->id];
memset(ipu, 0, sizeof(struct ipu_soc));
- spin_lock_init(&ipu->spin_lock);
- mutex_init(&ipu->mutex_lock);
+ spin_lock_init(&ipu->ipu_lock);
g_ipu_hw_rev = plat_data->rev;
@@ -448,12 +738,15 @@ int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel
dev_dbg(ipu->dev, "init channel = %d\n", IPU_CHAN_ID(channel));
- _ipu_get(ipu);
+ if (ipu->clk_enabled == false) {
+ ipu->clk_enabled = true;
+ clk_enable(ipu->ipu_clk);
+ }
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if (ipu->channel_init_mask & (1L << IPU_CHAN_ID(channel))) {
- dev_warn(ipu->dev, "Warning: channel already initialized %d\n",
+ dev_err(ipu->dev, "Warning: channel already initialized %d\n",
IPU_CHAN_ID(channel));
}
@@ -703,7 +996,7 @@ int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel
ipu_cm_write(ipu, ipu_conf, IPU_CONF);
err:
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return ret;
}
EXPORT_SYMBOL(ipu_init_channel);
@@ -716,17 +1009,17 @@ EXPORT_SYMBOL(ipu_init_channel);
*/
void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
{
+ unsigned long lock_flags;
uint32_t reg;
uint32_t in_dma, out_dma = 0;
uint32_t ipu_conf;
- unsigned long lock_flags;
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if ((ipu->channel_init_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
dev_err(ipu->dev, "Channel already uninitialized %d\n",
IPU_CHAN_ID(channel));
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return;
}
@@ -740,7 +1033,7 @@ void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
dev_err(ipu->dev,
"Channel %d is not disabled, disable first\n",
IPU_CHAN_ID(channel));
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return;
}
@@ -875,6 +1168,8 @@ void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
break;
}
+ ipu->channel_init_mask &= ~(1L << IPU_CHAN_ID(channel));
+
if (ipu->ic_use_count == 0)
ipu_conf &= ~IPU_CONF_IC_EN;
if (ipu->vdi_use_count == 0) {
@@ -901,11 +1196,12 @@ void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
ipu_cm_write(ipu, ipu_conf, IPU_CONF);
- ipu->channel_init_mask &= ~(1L << IPU_CHAN_ID(channel));
-
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
- _ipu_put(ipu);
+ if (ipu_conf == 0) {
+ clk_disable(ipu->ipu_clk);
+ ipu->clk_enabled = false;
+ }
WARN_ON(ipu->ic_use_count < 0);
WARN_ON(ipu->vdi_use_count < 0);
@@ -971,10 +1267,10 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
dma_addr_t phyaddr_2,
uint32_t u, uint32_t v)
{
+ unsigned long lock_flags;
uint32_t reg;
uint32_t dma_chan;
uint32_t burst_size;
- unsigned long lock_flags;
dma_chan = channel_2_dma(channel, type);
if (!idma_is_valid(dma_chan))
@@ -1007,8 +1303,6 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
return -EINVAL;
}
- _ipu_lock(ipu, &lock_flags);
-
/* Build parameter memory data for DMA channel */
_ipu_ch_param_init(ipu, dma_chan, pixel_fmt, width, height, stride, u, v, 0,
phyaddr_0, phyaddr_1, phyaddr_2);
@@ -1041,8 +1335,10 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
_ipu_ch_param_set_block_mode(ipu, dma_chan);
} else if (_ipu_is_dmfc_chan(dma_chan)) {
burst_size = _ipu_ch_param_get_burst_size(ipu, dma_chan);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
_ipu_dmfc_set_wait4eot(ipu, dma_chan, width);
_ipu_dmfc_set_burst_size(ipu, dma_chan, burst_size);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
}
if (_ipu_disp_chan_is_interlaced(ipu, channel) ||
@@ -1064,81 +1360,13 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
_ipu_smfc_set_burst_size(ipu, channel, burst_size-1);
}
- /* AXI-id */
- if (idma_is_set(ipu, IDMAC_CHA_PRI, dma_chan)) {
- unsigned reg = IDMAC_CH_LOCK_EN_1;
- uint32_t value = 0;
- if (cpu_is_mx53()) {
- _ipu_ch_param_set_axi_id(ipu, dma_chan, 0);
- switch (dma_chan) {
- case 5:
- value = 0x3;
- break;
- case 11:
- value = 0x3 << 2;
- break;
- case 12:
- value = 0x3 << 4;
- break;
- case 14:
- value = 0x3 << 6;
- break;
- case 15:
- value = 0x3 << 8;
- break;
- case 20:
- value = 0x3 << 10;
- break;
- case 21:
- value = 0x3 << 12;
- break;
- case 22:
- value = 0x3 << 14;
- break;
- case 23:
- value = 0x3 << 16;
- break;
- case 27:
- value = 0x3 << 18;
- break;
- case 28:
- value = 0x3 << 20;
- break;
- case 45:
- reg = IDMAC_CH_LOCK_EN_2;
- value = 0x3 << 0;
- break;
- case 46:
- reg = IDMAC_CH_LOCK_EN_2;
- value = 0x3 << 2;
- break;
- case 47:
- reg = IDMAC_CH_LOCK_EN_2;
- value = 0x3 << 4;
- break;
- case 48:
- reg = IDMAC_CH_LOCK_EN_2;
- value = 0x3 << 6;
- break;
- case 49:
- reg = IDMAC_CH_LOCK_EN_2;
- value = 0x3 << 8;
- break;
- case 50:
- reg = IDMAC_CH_LOCK_EN_2;
- value = 0x3 << 10;
- break;
- default:
- break;
- }
- value |= ipu_idmac_read(ipu, reg);
- ipu_idmac_write(ipu, value, reg);
- } else
- _ipu_ch_param_set_axi_id(ipu, dma_chan, 1);
- }
+ if (idma_is_set(ipu, IDMAC_CHA_PRI, dma_chan) && !cpu_is_mx53()
+ && !cpu_is_mx6q())
+ _ipu_ch_param_set_high_priority(ipu, dma_chan);
_ipu_ch_param_dump(ipu, dma_chan);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if (phyaddr_2 && g_ipu_hw_rev >= 2) {
reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(dma_chan));
reg &= ~idma_mask(dma_chan);
@@ -1174,8 +1402,7 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
IPU_CHA_CUR_BUF(dma_chan));
}
-
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return 0;
}
@@ -1203,13 +1430,12 @@ int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
{
uint32_t reg;
int ret = 0;
- uint32_t dma_chan = channel_2_dma(channel, type);
unsigned long lock_flags;
-
+ uint32_t dma_chan = channel_2_dma(channel, type);
if (dma_chan == IDMA_CHAN_INVALID)
return -EINVAL;
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if (bufNum == 0)
reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(dma_chan));
@@ -1223,8 +1449,7 @@ int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
else
ret = -EACCES;
- _ipu_unlock(ipu, &lock_flags);
-
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return ret;
}
EXPORT_SYMBOL(ipu_update_channel_buffer);
@@ -1275,13 +1500,13 @@ int32_t ipu_update_channel_offset(struct ipu_soc *ipu,
uint32_t vertical_offset, uint32_t horizontal_offset)
{
int ret = 0;
- uint32_t dma_chan = channel_2_dma(channel, type);
unsigned long lock_flags;
+ uint32_t dma_chan = channel_2_dma(channel, type);
if (dma_chan == IDMA_CHAN_INVALID)
return -EINVAL;
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if ((ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(dma_chan)) & idma_mask(dma_chan)) ||
(ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(dma_chan)) & idma_mask(dma_chan)) ||
@@ -1293,7 +1518,7 @@ int32_t ipu_update_channel_offset(struct ipu_soc *ipu,
_ipu_ch_offset_update(ipu, dma_chan, pixel_fmt, width, height, stride,
u, v, 0, vertical_offset, horizontal_offset);
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return ret;
}
EXPORT_SYMBOL(ipu_update_channel_offset);
@@ -1322,7 +1547,7 @@ int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
return -EINVAL;
/* Mark buffer to be ready. */
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if (bufNum == 0)
ipu_cm_write(ipu, idma_mask(dma_chan),
IPU_CHA_BUF0_RDY(dma_chan));
@@ -1332,7 +1557,7 @@ int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
else
ipu_cm_write(ipu, idma_mask(dma_chan),
IPU_CHA_BUF2_RDY(dma_chan));
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return 0;
}
EXPORT_SYMBOL(ipu_select_buffer);
@@ -1357,12 +1582,12 @@ int32_t ipu_select_multi_vdi_buffer(struct ipu_soc *ipu, uint32_t bufNum)
unsigned long lock_flags;
/* Mark buffers to be ready. */
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if (bufNum == 0)
ipu_cm_write(ipu, mask_bit, IPU_CHA_BUF0_RDY(dma_chan));
else
ipu_cm_write(ipu, mask_bit, IPU_CHA_BUF1_RDY(dma_chan));
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return 0;
}
EXPORT_SYMBOL(ipu_select_multi_vdi_buffer);
@@ -1395,13 +1620,13 @@ static int disp_src_sel[] = { 0, 6, 7, 8, 3, 4, 5, NA, NA, NA,
int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch)
{
int retval = 0;
+ unsigned long lock_flags;
uint32_t fs_proc_flow1;
uint32_t fs_proc_flow2;
uint32_t fs_proc_flow3;
uint32_t fs_disp_flow1;
- unsigned long lock_flags;
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
fs_proc_flow1 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
fs_proc_flow2 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW2);
@@ -1576,7 +1801,7 @@ int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel
ipu_cm_write(ipu, fs_disp_flow1, IPU_FS_DISP_FLOW1);
err:
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return retval;
}
EXPORT_SYMBOL(ipu_link_channels);
@@ -1598,13 +1823,13 @@ EXPORT_SYMBOL(ipu_link_channels);
int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch)
{
int retval = 0;
+ unsigned long lock_flags;
uint32_t fs_proc_flow1;
uint32_t fs_proc_flow2;
uint32_t fs_proc_flow3;
uint32_t fs_disp_flow1;
- unsigned long lock_flags;
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
fs_proc_flow1 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
fs_proc_flow2 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW2);
@@ -1707,7 +1932,7 @@ int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_chann
ipu_cm_write(ipu, fs_disp_flow1, IPU_FS_DISP_FLOW1);
err:
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return retval;
}
EXPORT_SYMBOL(ipu_unlink_channels);
@@ -1752,19 +1977,19 @@ EXPORT_SYMBOL(ipu_is_channel_busy);
int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel)
{
uint32_t reg;
+ unsigned long lock_flags;
uint32_t ipu_conf;
uint32_t in_dma;
uint32_t out_dma;
uint32_t sec_dma;
uint32_t thrd_dma;
- unsigned long lock_flags;
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if (ipu->channel_enable_mask & (1L << IPU_CHAN_ID(channel))) {
dev_err(ipu->dev, "Warning: channel already enabled %d\n",
IPU_CHAN_ID(channel));
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return -EACCES;
}
@@ -1846,7 +2071,7 @@ int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel)
ipu->channel_enable_mask |= 1L << IPU_CHAN_ID(channel);
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return 0;
}
@@ -1899,14 +2124,16 @@ EXPORT_SYMBOL(ipu_check_buffer_ready);
* ready state.
*
*/
-void _ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
uint32_t bufNum)
{
+ unsigned long lock_flags;
uint32_t dma_ch = channel_2_dma(channel, type);
if (!idma_is_valid(dma_ch))
return;
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
if (bufNum == 0)
ipu_cm_write(ipu, idma_mask(dma_ch),
@@ -1918,17 +2145,17 @@ void _ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buf
ipu_cm_write(ipu, idma_mask(dma_ch),
IPU_CHA_BUF2_RDY(dma_ch));
ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
}
+EXPORT_SYMBOL(ipu_clear_buffer_ready);
-void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
- uint32_t bufNum)
+static irqreturn_t disable_chan_irq_handler(int irq, void *dev_id)
{
- unsigned long lock_flags;
- _ipu_lock(ipu, &lock_flags);
- _ipu_clear_buffer_ready(ipu, channel, type, bufNum);
- _ipu_unlock(ipu, &lock_flags);
+ struct completion *comp = dev_id;
+
+ complete(comp);
+ return IRQ_HANDLED;
}
-EXPORT_SYMBOL(ipu_clear_buffer_ready);
/*!
* This function disables a logical channel.
@@ -1945,22 +2172,24 @@ EXPORT_SYMBOL(ipu_clear_buffer_ready);
int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wait_for_stop)
{
uint32_t reg;
+ unsigned long lock_flags;
uint32_t in_dma;
uint32_t out_dma;
uint32_t sec_dma = NO_DMA;
uint32_t thrd_dma = NO_DMA;
uint16_t fg_pos_x, fg_pos_y;
- unsigned long lock_flags;
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if ((ipu->channel_enable_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
dev_err(ipu->dev, "Channel already disabled %d\n",
IPU_CHAN_ID(channel));
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return -EACCES;
}
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+
/* Get input and output dma channels */
out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
@@ -1968,10 +2197,8 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
if ((idma_is_valid(in_dma) &&
!idma_is_set(ipu, IDMAC_CHA_EN, in_dma))
&& (idma_is_valid(out_dma) &&
- !idma_is_set(ipu, IDMAC_CHA_EN, out_dma))) {
- _ipu_unlock(ipu, &lock_flags);
+ !idma_is_set(ipu, IDMAC_CHA_EN, out_dma)))
return -EINVAL;
- }
if (ipu->sec_chan_en[IPU_CHAN_ID(channel)])
sec_dma = channel_2_dma(channel, IPU_GRAPH_IN_BUFFER);
@@ -1980,12 +2207,11 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
thrd_dma = channel_2_dma(channel, IPU_ALPHA_IN_BUFFER);
}
- _ipu_unlock(ipu, &lock_flags);
if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) ||
(channel == MEM_DC_SYNC)) {
if (channel == MEM_FG_SYNC) {
- _ipu_disp_get_window_pos(ipu, channel, &fg_pos_x, &fg_pos_y);
- _ipu_disp_set_window_pos(ipu, channel, 0, 0);
+ ipu_disp_get_window_pos(ipu, channel, &fg_pos_x, &fg_pos_y);
+ ipu_disp_set_window_pos(ipu, channel, 0, 0);
}
_ipu_dp_dc_disable(ipu, channel, false);
@@ -2016,9 +2242,8 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
idma_is_set(ipu, IDMAC_CHA_BUSY, sec_dma)) ||
(ipu->thrd_chan_en[IPU_CHAN_ID(channel)] &&
idma_is_set(ipu, IDMAC_CHA_BUSY, thrd_dma))) {
- uint32_t irq = 0xffffffff;
+ uint32_t ret, irq = 0xffffffff;
DECLARE_COMPLETION_ONSTACK(disable_comp);
- int timeout = 50;
if (idma_is_set(ipu, IDMAC_CHA_BUSY, out_dma))
irq = out_dma;
@@ -2038,22 +2263,23 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
dev_err(ipu->dev, "warning: channel %d busy, need wait\n", irq);
- ipu_cm_write(ipu, IPUIRQ_2_MASK(irq),
- IPUIRQ_2_STATREG(irq));
- while ((ipu_cm_read(ipu, IPUIRQ_2_STATREG(irq)) &
- IPUIRQ_2_MASK(irq)) == 0) {
- msleep(10);
- timeout -= 10;
- if (timeout <= 0) {
+ ret = ipu_request_irq(ipu, irq, disable_chan_irq_handler, 0, NULL, &disable_comp);
+ if (ret < 0) {
+ dev_err(ipu->dev, "irq %d in use\n", irq);
+ break;
+ } else {
+ ret = wait_for_completion_timeout(&disable_comp, msecs_to_jiffies(200));
+ ipu_free_irq(ipu, irq, &disable_comp);
+ if (ret == 0) {
ipu_dump_registers(ipu);
dev_err(ipu->dev, "warning: disable ipu dma channel %d during its busy state\n", irq);
break;
}
}
-
}
}
- _ipu_lock(ipu, &lock_flags);
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) ||
(channel == MEM_DC_SYNC)) {
@@ -2101,29 +2327,29 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
ipu->channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel));
- if (channel == MEM_FG_SYNC)
- _ipu_disp_set_window_pos(ipu, channel, fg_pos_x, fg_pos_y);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
/* Set channel buffers NOT to be ready */
if (idma_is_valid(in_dma)) {
- _ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 0);
- _ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 1);
- _ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 2);
+ ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 0);
+ ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 1);
+ ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 2);
}
if (idma_is_valid(out_dma)) {
- _ipu_clear_buffer_ready(ipu, channel, IPU_OUTPUT_BUFFER, 0);
- _ipu_clear_buffer_ready(ipu, channel, IPU_OUTPUT_BUFFER, 1);
+ ipu_clear_buffer_ready(ipu, channel, IPU_OUTPUT_BUFFER, 0);
+ ipu_clear_buffer_ready(ipu, channel, IPU_OUTPUT_BUFFER, 1);
}
if (ipu->sec_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(sec_dma)) {
- _ipu_clear_buffer_ready(ipu, channel, IPU_GRAPH_IN_BUFFER, 0);
- _ipu_clear_buffer_ready(ipu, channel, IPU_GRAPH_IN_BUFFER, 1);
+ ipu_clear_buffer_ready(ipu, channel, IPU_GRAPH_IN_BUFFER, 0);
+ ipu_clear_buffer_ready(ipu, channel, IPU_GRAPH_IN_BUFFER, 1);
}
if (ipu->thrd_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(thrd_dma)) {
- _ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 0);
- _ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 1);
+ ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 0);
+ ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 1);
}
- _ipu_unlock(ipu, &lock_flags);
+ if (channel == MEM_FG_SYNC)
+ ipu_disp_set_window_pos(ipu, channel, fg_pos_x, fg_pos_y);
return 0;
}
@@ -2148,7 +2374,7 @@ int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi)
return -EINVAL;
}
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
ipu->csi_use_count[csi]++;
if (ipu->csi_use_count[csi] == 1) {
@@ -2158,7 +2384,7 @@ int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi)
else
ipu_cm_write(ipu, reg | IPU_CONF_CSI1_EN, IPU_CONF);
}
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return 0;
}
EXPORT_SYMBOL(ipu_enable_csi);
@@ -2182,8 +2408,9 @@ int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi)
return -EINVAL;
}
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
ipu->csi_use_count[csi]--;
+
if (ipu->csi_use_count[csi] == 0) {
reg = ipu_cm_read(ipu, IPU_CONF);
if (csi == 0)
@@ -2191,7 +2418,7 @@ int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi)
else
ipu_cm_write(ipu, reg & ~IPU_CONF_CSI1_EN, IPU_CONF);
}
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return 0;
}
EXPORT_SYMBOL(ipu_disable_csi);
@@ -2256,17 +2483,18 @@ void ipu_enable_irq(struct ipu_soc *ipu, uint32_t irq)
uint32_t reg;
unsigned long lock_flags;
- _ipu_get(ipu);
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
- spin_lock_irqsave(&ipu->spin_lock, lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
reg |= IPUIRQ_2_MASK(irq);
ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
- spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
-
- _ipu_put(ipu);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
EXPORT_SYMBOL(ipu_enable_irq);
@@ -2283,17 +2511,18 @@ void ipu_disable_irq(struct ipu_soc *ipu, uint32_t irq)
uint32_t reg;
unsigned long lock_flags;
- _ipu_get(ipu);
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
- spin_lock_irqsave(&ipu->spin_lock, lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
reg &= ~IPUIRQ_2_MASK(irq);
ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
- spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
-
- _ipu_put(ipu);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
EXPORT_SYMBOL(ipu_disable_irq);
@@ -2307,11 +2536,13 @@ EXPORT_SYMBOL(ipu_disable_irq);
*/
void ipu_clear_irq(struct ipu_soc *ipu, uint32_t irq)
{
- _ipu_get(ipu);
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
ipu_cm_write(ipu, IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq));
- _ipu_put(ipu);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
}
EXPORT_SYMBOL(ipu_clear_irq);
@@ -2329,11 +2560,13 @@ bool ipu_get_irq_status(struct ipu_soc *ipu, uint32_t irq)
{
uint32_t reg;
- _ipu_get(ipu);
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
reg = ipu_cm_read(ipu, IPUIRQ_2_STATREG(irq));
- _ipu_put(ipu);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
if (reg & IPUIRQ_2_MASK(irq))
return true;
@@ -2371,12 +2604,12 @@ int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
BUG_ON(irq >= IPU_IRQ_COUNT);
- spin_lock_irqsave(&ipu->spin_lock, lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if (ipu->irq_list[irq].handler != NULL) {
dev_err(ipu->dev,
"handler already installed on irq %d\n", irq);
- spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return -EINVAL;
}
@@ -2385,7 +2618,7 @@ int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
ipu->irq_list[irq].dev_id = dev_id;
ipu->irq_list[irq].name = devname;
- spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
ipu_enable_irq(ipu, irq); /* enable the interrupt */
@@ -2484,20 +2717,22 @@ int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel
int from_dma = channel_2_dma(from_ch, IPU_INPUT_BUFFER);
int to_dma = channel_2_dma(to_ch, IPU_INPUT_BUFFER);
- _ipu_lock(ipu, &lock_flags);
-
/* enable target channel */
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+
reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(to_dma));
ipu_idmac_write(ipu, reg | idma_mask(to_dma), IDMAC_CHA_EN(to_dma));
ipu->channel_enable_mask |= 1L << IPU_CHAN_ID(to_ch);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+
/* switch dp dc */
- _ipu_unlock(ipu, &lock_flags);
_ipu_dp_dc_disable(ipu, from_ch, true);
- _ipu_lock(ipu, &lock_flags);
/* disable source channel */
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+
reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(from_dma));
ipu_idmac_write(ipu, reg & ~idma_mask(from_dma), IDMAC_CHA_EN(from_dma));
ipu_cm_write(ipu, idma_mask(from_dma), IPU_CHA_CUR_BUF(from_dma));
@@ -2506,11 +2741,11 @@ int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel
ipu->channel_enable_mask &= ~(1L << IPU_CHAN_ID(from_ch));
- _ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 0);
- _ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 1);
- _ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 2);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
- _ipu_unlock(ipu, &lock_flags);
+ ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 0);
+ ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 1);
+ ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 2);
return 0;
}
@@ -2591,6 +2826,12 @@ bool ipu_pixel_format_has_alpha(uint32_t fmt)
return false;
}
+void ipu_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3])
+{
+ _ipu_dp_set_csc_coefficients(ipu, channel, param);
+}
+EXPORT_SYMBOL(ipu_set_csc_coefficients);
+
static int ipu_suspend(struct platform_device *pdev, pm_message_t state)
{
struct imx_ipuv3_platform_data *plat_data = pdev->dev.platform_data;
diff --git a/drivers/mxc/ipu3/ipu_disp.c b/drivers/mxc/ipu3/ipu_disp.c
index 9867d5717df..12e36e28c2d 100644
--- a/drivers/mxc/ipu3/ipu_disp.c
+++ b/drivers/mxc/ipu3/ipu_disp.c
@@ -26,7 +26,6 @@
#include <linux/io.h>
#include <linux/ipu.h>
#include <linux/clk.h>
-#include <linux/err.h>
#include <asm/atomic.h>
#include <mach/clock.h>
#include "ipu_prv.h"
@@ -46,141 +45,6 @@ struct dp_csc_param_t {
#define DC_DISP_ID_SERIAL 2
#define DC_DISP_ID_ASYNC 3
-static inline struct ipu_soc *pixelclk2ipu(struct clk *clk)
-{
- struct ipu_soc *ipu;
- struct clk *base = clk - clk->id;
-
- ipu = container_of(base, struct ipu_soc, pixel_clk[0]);
-
- return ipu;
-}
-
-static unsigned long _ipu_pixel_clk_get_rate(struct clk *clk)
-{
- struct ipu_soc *ipu = pixelclk2ipu(clk);
- u32 div = ipu_di_read(ipu, clk->id, DI_BS_CLKGEN0);
- if (div == 0)
- return 0;
- return (clk_get_rate(clk->parent) * 16) / div;
-}
-
-static unsigned long _ipu_pixel_clk_round_rate(struct clk *clk, unsigned long rate)
-{
- u32 div, div1;
- u32 parent_rate = clk_get_rate(clk->parent) * 16;
- /*
- * Calculate divider
- * Fractional part is 4 bits,
- * so simply multiply by 2^4 to get fractional part.
- */
- div = parent_rate / rate;
-
- if (div < 0x10) /* Min DI disp clock divider is 1 */
- div = 0x10;
- if (div & ~0xFEF)
- div &= 0xFF8;
- else {
- div1 = div & 0xFE0;
- if ((parent_rate / div1 - parent_rate / div) < rate / 4)
- div = div1;
- else
- div &= 0xFF8;
- }
- return parent_rate / div;
-}
-
-static int _ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate)
-{
- struct ipu_soc *ipu = pixelclk2ipu(clk);
- u32 div = (clk_get_rate(clk->parent) * 16) / rate;
-
- ipu_di_write(ipu, clk->id, div, DI_BS_CLKGEN0);
-
- /* Setup pixel clock timing */
- /* FIXME: needs to be more flexible */
- /* Down time is half of period */
- ipu_di_write(ipu, clk->id, (div / 16) << 16, DI_BS_CLKGEN1);
-
- return 0;
-}
-
-static int _ipu_pixel_clk_enable(struct clk *clk)
-{
- struct ipu_soc *ipu = pixelclk2ipu(clk);
- u32 disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
- disp_gen |= clk->id ? DI1_COUNTER_RELEASE : DI0_COUNTER_RELEASE;
- ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
-
- return 0;
-}
-
-static void _ipu_pixel_clk_disable(struct clk *clk)
-{
- struct ipu_soc *ipu = pixelclk2ipu(clk);
-
- u32 disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
- disp_gen &= clk->id ? ~DI1_COUNTER_RELEASE : ~DI0_COUNTER_RELEASE;
- ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
-}
-
-static int _ipu_pixel_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- struct ipu_soc *ipu = pixelclk2ipu(clk);
- u32 di_gen;
-
- di_gen = ipu_di_read(ipu, clk->id, DI_GENERAL);
- if (parent == ipu->ipu_clk)
- di_gen &= ~DI_GEN_DI_CLK_EXT;
- else if (!IS_ERR(ipu->di_clk[clk->id]) && parent == ipu->di_clk[clk->id])
- di_gen |= DI_GEN_DI_CLK_EXT;
- else {
- return -EINVAL;
- }
-
- ipu_di_write(ipu, clk->id, di_gen, DI_GENERAL);
- return 0;
-}
-
-#ifdef CONFIG_CLK_DEBUG
-#define __INIT_CLK_DEBUG(n) .name = #n,
-#else
-#define __INIT_CLK_DEBUG(n)
-#endif
-struct clk ipu_pixel_clk[] = {
- {
- __INIT_CLK_DEBUG(pixel_clk_0)
- .id = 0,
- .get_rate = _ipu_pixel_clk_get_rate,
- .set_rate = _ipu_pixel_clk_set_rate,
- .round_rate = _ipu_pixel_clk_round_rate,
- .set_parent = _ipu_pixel_clk_set_parent,
- .enable = _ipu_pixel_clk_enable,
- .disable = _ipu_pixel_clk_disable,
- },
- {
- __INIT_CLK_DEBUG(pixel_clk_1)
- .id = 1,
- .get_rate = _ipu_pixel_clk_get_rate,
- .set_rate = _ipu_pixel_clk_set_rate,
- .round_rate = _ipu_pixel_clk_round_rate,
- .set_parent = _ipu_pixel_clk_set_parent,
- .enable = _ipu_pixel_clk_enable,
- .disable = _ipu_pixel_clk_disable,
- },
-};
-
-struct clk_lookup ipu_lookups[] = {
- {
- .dev_id = NULL,
- .con_id = "pixel_clk_0",
- },
- {
- .dev_id = NULL,
- .con_id = "pixel_clk_1",
- },
-};
-
int dmfc_type_setup;
void _ipu_dmfc_init(struct ipu_soc *ipu, int dmfc_type, int first)
@@ -900,6 +764,7 @@ static irqreturn_t dc_irq_handler(int irq, void *dev_id)
void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap)
{
int ret;
+ unsigned long lock_flags;
uint32_t reg;
uint32_t csc;
uint32_t dc_chan;
@@ -918,6 +783,8 @@ void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap)
/* Disable FG channel */
dc_chan = 5;
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+
reg = ipu_dp_read(ipu, DP_COM_CONF(DP_SYNC));
csc = reg & DP_COM_CONF_CSC_DEF_MASK;
if (csc == DP_COM_CONF_CSC_DEF_FG)
@@ -929,6 +796,8 @@ void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap)
reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+
ipu_cm_write(ipu, IPUIRQ_2_MASK(IPU_IRQ_DP_SF_END),
IPUIRQ_2_STATREG(IPU_IRQ_DP_SF_END));
while ((ipu_cm_read(ipu, IPUIRQ_2_STATREG(IPU_IRQ_DP_SF_END)) &
@@ -955,12 +824,14 @@ void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap)
dev_dbg(ipu->dev, "DC stop timeout - %d * 10ms\n", 5 - ret);
if (ipu->dc_swap) {
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
/* Swap DC channel 1 and 5 settings, and disable old dc chan */
reg = ipu_dc_read(ipu, DC_WR_CH_CONF(dc_chan));
ipu_dc_write(ipu, reg, DC_WR_CH_CONF(6 - dc_chan));
reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
reg ^= DC_WR_CH_CONF_PROG_DI_ID;
ipu_dc_write(ipu, reg, DC_WR_CH_CONF(dc_chan));
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
} else
/* Clock is already off because it must be done quickly, but
we need to fix the ref count */
@@ -1100,12 +971,6 @@ void _ipu_dp_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, in
__ipu_dp_csc_setup(ipu, dp, dp_csc_param, true);
}
-void ipu_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3])
-{
- _ipu_dp_set_csc_coefficients(ipu, channel, param);
-}
-EXPORT_SYMBOL(ipu_set_csc_coefficients);
-
/*!
* This function is called to adapt synchronous LCD panel to IPU restriction.
*
@@ -1173,6 +1038,7 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
uint16_t v_sync_width, uint16_t v_end_width,
uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig)
{
+ unsigned long lock_flags;
uint32_t field0_offset = 0;
uint32_t field1_offset;
uint32_t reg;
@@ -1181,7 +1047,6 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
uint32_t h_total, v_total;
int map;
struct clk *di_parent;
- unsigned long lock_flags;
dev_dbg(ipu->dev, "panel size = %d x %d\n", width, height);
@@ -1243,7 +1108,7 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
/* Get integer portion of divider */
div = clk_get_rate(clk_get_parent(&ipu->pixel_clk[disp])) / rounded_pixel_clk;
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
_ipu_di_data_wave_config(ipu, disp, SYNC_WAVE, div - 1, div - 1);
_ipu_di_data_pin_config(ipu, disp, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
@@ -1251,7 +1116,7 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
map = _ipu_pixfmt_to_map(pixel_fmt);
if (map < 0) {
dev_dbg(ipu->dev, "IPU_DISP: No MAP\n");
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return -EINVAL;
}
@@ -1638,7 +1503,7 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
ipu_dc_write(ipu, width, DC_DISP_CONF2(DC_DISP_ID_SYNC(disp)));
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return 0;
}
@@ -1646,14 +1511,14 @@ EXPORT_SYMBOL(ipu_init_sync_panel);
void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp)
{
+ unsigned long lock_flags;
uint32_t reg;
uint32_t di_gen;
- unsigned long lock_flags;
if ((disp != 0) || (disp != 1))
return;
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
di_gen = ipu_di_read(ipu, disp, DI_GENERAL);
di_gen |= 0x3ff | DI_GEN_POLARITY_DISP_CLK;
@@ -1663,18 +1528,18 @@ void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp)
reg |= 0x3ffffff;
ipu_di_write(ipu, disp, reg, DI_POL);
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
}
EXPORT_SYMBOL(ipu_uninit_sync_panel);
int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle_time,
uint32_t pixel_fmt, ipu_adc_sig_cfg_t sig)
{
+ unsigned long lock_flags;
int map;
u32 ser_conf = 0;
u32 div;
u32 di_clk = clk_get_rate(ipu->ipu_clk);
- unsigned long lock_flags;
/* round up cycle_time, then calcalate the divider using scaled math */
cycle_time += (1000000000UL / di_clk) - 1;
@@ -1684,7 +1549,7 @@ int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle
if (map < 0)
return -EINVAL;
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if (type == IPU_PANEL_SERIAL) {
ipu_di_write(ipu, disp, (div << 24) | ((sig.ifc_width - 1) << 4),
@@ -1713,7 +1578,7 @@ int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle
ipu_di_write(ipu, disp, ser_conf, DI_SER_CONF);
}
- _ipu_unlock(ipu, &lock_flags);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
return 0;
}
EXPORT_SYMBOL(ipu_init_async_panel);
@@ -1738,8 +1603,8 @@ int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel,
{
uint32_t reg;
uint32_t flow;
- bool bg_chan;
unsigned long lock_flags;
+ bool bg_chan;
if (channel == MEM_BG_SYNC || channel == MEM_FG_SYNC)
flow = DP_SYNC;
@@ -1756,9 +1621,9 @@ int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel,
else
bg_chan = false;
- _ipu_get(ipu);
-
- _ipu_lock(ipu, &lock_flags);
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
if (bg_chan) {
reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
@@ -1783,9 +1648,9 @@ int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel,
reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- _ipu_unlock(ipu, &lock_flags);
-
- _ipu_put(ipu);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
return 0;
}
@@ -1820,9 +1685,10 @@ int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel,
else
return -EINVAL;
- _ipu_get(ipu);
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
- _ipu_lock(ipu, &lock_flags);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
ipu->color_key_4rgb = true;
/* Transform color key from rgb to yuv if CSC is enabled */
@@ -1861,9 +1727,9 @@ int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel,
reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- _ipu_unlock(ipu, &lock_flags);
-
- _ipu_put(ipu);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
return 0;
}
@@ -1897,9 +1763,9 @@ int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel
else
return -EINVAL;
- _ipu_get(ipu);
-
- _ipu_lock(ipu, &lock_flags);
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
for (i = 0; i < 8; i++)
ipu_dp_write(ipu, (constk[2*i] & 0x1ff) | ((constk[2*i+1] & 0x1ff) << 16), DP_GAMMA_C(flow, i));
@@ -1920,9 +1786,9 @@ int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel
reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- _ipu_unlock(ipu, &lock_flags);
-
- _ipu_put(ipu);
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
return 0;
}
@@ -1943,10 +1809,11 @@ EXPORT_SYMBOL(ipu_disp_set_gamma_correction);
*
* @return Returns 0 on success or negative error code on fail
*/
-int32_t _ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
int16_t x_pos, int16_t y_pos)
{
u32 reg;
+ unsigned long lock_flags;
uint32_t flow = 0;
uint32_t dp_srm_shift;
@@ -1962,6 +1829,11 @@ int32_t _ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
} else
return -EINVAL;
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+
ipu_dp_write(ipu, (x_pos << 16) | y_pos, DP_FG_POS(flow));
if (ipu_is_channel_busy(ipu, channel)) {
@@ -1975,28 +1847,19 @@ int32_t _ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
}
- return 0;
-}
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
-int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
- int16_t x_pos, int16_t y_pos)
-{
- int ret;
- unsigned long lock_flags;
-
- _ipu_get(ipu);
- _ipu_lock(ipu, &lock_flags);
- ret = _ipu_disp_set_window_pos(ipu, channel, x_pos, y_pos);
- _ipu_unlock(ipu, &lock_flags);
- _ipu_put(ipu);
- return ret;
+ return 0;
}
EXPORT_SYMBOL(ipu_disp_set_window_pos);
-int32_t _ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
+int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
int16_t *x_pos, int16_t *y_pos)
{
u32 reg;
+ unsigned long lock_flags;
uint32_t flow = 0;
if (channel == MEM_FG_SYNC)
@@ -2008,25 +1871,20 @@ int32_t _ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
else
return -EINVAL;
+ if (!ipu->clk_enabled)
+ clk_enable(ipu->ipu_clk);
+ spin_lock_irqsave(&ipu->ipu_lock, lock_flags);
+
reg = ipu_dp_read(ipu, DP_FG_POS(flow));
*x_pos = (reg >> 16) & 0x7FF;
*y_pos = reg & 0x7FF;
- return 0;
-}
-int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
- int16_t *x_pos, int16_t *y_pos)
-{
- int ret;
- unsigned long lock_flags;
+ spin_unlock_irqrestore(&ipu->ipu_lock, lock_flags);
+ if (!ipu->clk_enabled)
+ clk_disable(ipu->ipu_clk);
- _ipu_get(ipu);
- _ipu_lock(ipu, &lock_flags);
- ret = _ipu_disp_get_window_pos(ipu, channel, x_pos, y_pos);
- _ipu_unlock(ipu, &lock_flags);
- _ipu_put(ipu);
- return ret;
+ return 0;
}
EXPORT_SYMBOL(ipu_disp_get_window_pos);
diff --git a/drivers/mxc/ipu3/ipu_param_mem.h b/drivers/mxc/ipu3/ipu_param_mem.h
index d2ad2695b68..d7167f7831e 100644
--- a/drivers/mxc/ipu3/ipu_param_mem.h
+++ b/drivers/mxc/ipu3/ipu_param_mem.h
@@ -41,24 +41,6 @@ struct ipu_ch_param {
} \
}
-#define ipu_ch_param_set_field_io(base, w, bit, size, v) { \
- int i = (bit) / 32; \
- int off = (bit) % 32; \
- unsigned reg_offset; \
- u32 temp; \
- reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
- reg_offset += i; \
- temp = readl((u32 *)base + reg_offset); \
- temp |= (v) << off; \
- writel(temp, (u32 *)base + reg_offset); \
- if (((bit)+(size)-1)/32 > i) { \
- reg_offset++; \
- temp = readl((u32 *)base + reg_offset); \
- temp |= (v) >> (off ? (32 - off) : 0); \
- writel(temp, (u32 *)base + reg_offset); \
- } \
-}
-
#define ipu_ch_param_mod_field(base, w, bit, size, v) { \
int i = (bit) / 32; \
int off = (bit) % 32; \
@@ -74,27 +56,6 @@ struct ipu_ch_param {
} \
}
-#define ipu_ch_param_mod_field_io(base, w, bit, size, v) { \
- int i = (bit) / 32; \
- int off = (bit) % 32; \
- u32 mask = (1UL << size) - 1; \
- unsigned reg_offset; \
- u32 temp; \
- reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
- reg_offset += i; \
- temp = readl((u32 *)base + reg_offset); \
- temp &= ~(mask << off); \
- temp |= (v) << off; \
- writel(temp, (u32 *)base + reg_offset); \
- if (((bit)+(size)-1)/32 > i) { \
- reg_offset++; \
- temp = readl((u32 *)base + reg_offset); \
- temp &= ~(mask >> (32 - off)); \
- temp |= ((v) >> (off ? (32 - off) : 0)); \
- writel(temp, (u32 *)base + reg_offset); \
- } \
-}
-
#define ipu_ch_param_read_field(base, w, bit, size) ({ \
u32 temp2; \
int i = (bit) / 32; \
@@ -110,25 +71,6 @@ struct ipu_ch_param {
temp1; \
})
-#define ipu_ch_param_read_field_io(base, w, bit, size) ({ \
- u32 temp1, temp2; \
- int i = (bit) / 32; \
- int off = (bit) % 32; \
- u32 mask = (1UL << size) - 1; \
- unsigned reg_offset; \
- reg_offset = sizeof(struct ipu_ch_param_word) * w / 4; \
- reg_offset += i; \
- temp1 = readl((u32 *)base + reg_offset); \
- temp1 = mask & (temp1 >> off); \
- if (((bit)+(size)-1)/32 > i) { \
- reg_offset++; \
- temp2 = readl((u32 *)base + reg_offset); \
- temp2 &= mask >> (off ? (32 - off) : 0); \
- temp1 |= temp2 << (off ? (32 - off) : 0); \
- } \
- temp1; \
-})
-
static inline int __ipu_ch_get_third_buf_cpmem_num(int ch)
{
switch (ch) {
@@ -184,35 +126,35 @@ static inline void _ipu_ch_param_dump(struct ipu_soc *ipu, int ch)
p->word[1].data[0], p->word[1].data[1], p->word[1].data[2],
p->word[1].data[3], p->word[1].data[4]);
dev_dbg(ipu->dev, "PFS 0x%x, ",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 85, 4));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 85, 4));
dev_dbg(ipu->dev, "BPP 0x%x, ",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 0, 107, 3));
dev_dbg(ipu->dev, "NPB 0x%x\n",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 78, 7));
dev_dbg(ipu->dev, "FW %d, ",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 125, 13));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 0, 125, 13));
dev_dbg(ipu->dev, "FH %d, ",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 138, 12));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 0, 138, 12));
dev_dbg(ipu->dev, "Stride %d\n",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 102, 14));
dev_dbg(ipu->dev, "Width0 %d+1, ",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 116, 3));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 116, 3));
dev_dbg(ipu->dev, "Width1 %d+1, ",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 119, 3));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 119, 3));
dev_dbg(ipu->dev, "Width2 %d+1, ",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 122, 3));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 122, 3));
dev_dbg(ipu->dev, "Width3 %d+1, ",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 125, 3));
dev_dbg(ipu->dev, "Offset0 %d, ",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 128, 5));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 128, 5));
dev_dbg(ipu->dev, "Offset1 %d, ",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 133, 5));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 133, 5));
dev_dbg(ipu->dev, "Offset2 %d, ",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 138, 5));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 138, 5));
dev_dbg(ipu->dev, "Offset3 %d\n",
- ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 143, 5));
+ ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 143, 5));
}
static inline void _ipu_ch_param_init(struct ipu_soc *ipu, int ch,
@@ -450,24 +392,24 @@ static inline void _ipu_ch_param_set_burst_size(struct ipu_soc *ipu,
{
int32_t sub_ch = 0;
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7,
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 78, 7,
burst_pixels - 1);
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
if (sub_ch <= 0)
return;
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 78, 7,
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 78, 7,
burst_pixels - 1);
};
static inline int _ipu_ch_param_get_burst_size(struct ipu_soc *ipu, uint32_t ch)
{
- return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7) + 1;
+ return ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 78, 7) + 1;
};
static inline int _ipu_ch_param_get_bpp(struct ipu_soc *ipu, uint32_t ch)
{
- return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3);
+ return ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 0, 107, 3);
};
static inline void _ipu_ch_param_set_buffer(struct ipu_soc *ipu, uint32_t ch,
@@ -480,7 +422,7 @@ static inline void _ipu_ch_param_set_buffer(struct ipu_soc *ipu, uint32_t ch,
bufNum = 0;
}
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 29 * bufNum, 29,
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 29 * bufNum, 29,
phyaddr / 8);
};
@@ -490,24 +432,24 @@ static inline void _ipu_ch_param_set_rotation(struct ipu_soc *ipu, uint32_t ch,
u32 temp_rot = bitrev8(rot) >> 5;
int32_t sub_ch = 0;
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 119, 3, temp_rot);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 0, 119, 3, temp_rot);
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
if (sub_ch <= 0)
return;
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 119, 3, temp_rot);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 0, 119, 3, temp_rot);
};
static inline void _ipu_ch_param_set_block_mode(struct ipu_soc *ipu, uint32_t ch)
{
int32_t sub_ch = 0;
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 117, 2, 1);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 0, 117, 2, 1);
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
if (sub_ch <= 0)
return;
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 117, 2, 1);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 0, 117, 2, 1);
};
static inline void _ipu_ch_param_set_alpha_use_separate_channel(struct ipu_soc *ipu,
@@ -517,9 +459,9 @@ static inline void _ipu_ch_param_set_alpha_use_separate_channel(struct ipu_soc *
int32_t sub_ch = 0;
if (option) {
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 1);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 1);
} else {
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 0);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 0);
}
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
@@ -527,9 +469,9 @@ static inline void _ipu_ch_param_set_alpha_use_separate_channel(struct ipu_soc *
return;
if (option) {
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 1);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 1);
} else {
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 0);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 0);
}
};
@@ -537,12 +479,12 @@ static inline void _ipu_ch_param_set_alpha_condition_read(struct ipu_soc *ipu, u
{
int32_t sub_ch = 0;
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 149, 1, 1);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 149, 1, 1);
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
if (sub_ch <= 0)
return;
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 149, 1, 1);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 149, 1, 1);
};
static inline void _ipu_ch_param_set_alpha_buffer_memory(struct ipu_soc *ipu, uint32_t ch)
@@ -569,12 +511,12 @@ static inline void _ipu_ch_param_set_alpha_buffer_memory(struct ipu_soc *ipu, ui
return;
}
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 90, 3, alp_mem_idx);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 90, 3, alp_mem_idx);
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
if (sub_ch <= 0)
return;
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 90, 3, alp_mem_idx);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 90, 3, alp_mem_idx);
};
static inline void _ipu_ch_param_set_interlaced_scan(struct ipu_soc *ipu, uint32_t ch)
@@ -584,10 +526,10 @@ static inline void _ipu_ch_param_set_interlaced_scan(struct ipu_soc *ipu, uint32
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
- ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 0, 113, 1, 1);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ipu, ch), 0, 113, 1, 1);
if (sub_ch > 0)
- ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 113, 1, 1);
- stride = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14) + 1;
+ ipu_ch_param_set_field(ipu_ch_param_addr(ipu, sub_ch), 0, 113, 1, 1);
+ stride = ipu_ch_param_read_field(ipu_ch_param_addr(ipu, ch), 1, 102, 14) + 1;
/* ILO is 20-bit and 8-byte aligned */
if (stride/8 > 0xfffff)
dev_warn(ipu->dev,
@@ -595,29 +537,27 @@ static inline void _ipu_ch_param_set_interlaced_scan(struct ipu_soc *ipu, uint32
if (stride%8)
dev_warn(ipu->dev,
"IDMAC%d's ILO is not 8-byte aligned\n", ch);
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 58, 20, stride / 8);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 58, 20, stride / 8);
if (sub_ch > 0)
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 58, 20,
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 58, 20,
stride / 8);
stride *= 2;
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14, stride - 1);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 102, 14, stride - 1);
if (sub_ch > 0)
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 102, 14,
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 102, 14,
stride - 1);
};
-static inline void _ipu_ch_param_set_axi_id(struct ipu_soc *ipu, uint32_t ch, uint32_t id)
+static inline void _ipu_ch_param_set_high_priority(struct ipu_soc *ipu, uint32_t ch)
{
int32_t sub_ch = 0;
- id %= 4;
-
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 93, 2, id);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 1, 93, 2, 1);
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
if (sub_ch <= 0)
return;
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 93, 2, id);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 1, 93, 2, 1);
};
/* IDMAC U/V offset changing support */
@@ -773,26 +713,26 @@ static inline void _ipu_ch_offset_update(struct ipu_soc *ipu,
dev_warn(ipu->dev,
"IDMAC%d's V offset is not 8-byte aligned\n", ch);
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22, u_offset / 8);
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22, v_offset / 8);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 0, 46, 22, u_offset / 8);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, ch), 0, 68, 22, v_offset / 8);
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
if (sub_ch <= 0)
return;
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 46, 22, u_offset / 8);
- ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 68, 22, v_offset / 8);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 0, 46, 22, u_offset / 8);
+ ipu_ch_param_mod_field(ipu_ch_param_addr(ipu, sub_ch), 0, 68, 22, v_offset / 8);
};
static inline void _ipu_ch_params_set_alpha_width(struct ipu_soc *ipu, uint32_t ch, int alpha_width)
{
int32_t sub_ch = 0;
- ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3, alpha_width - 1);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ipu, ch), 1, 125, 3, alpha_width - 1);
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
if (sub_ch <= 0)
return;
- ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 125, 3, alpha_width - 1);
+ ipu_ch_param_set_field(ipu_ch_param_addr(ipu, sub_ch), 1, 125, 3, alpha_width - 1);
};
#endif
diff --git a/drivers/mxc/ipu3/ipu_prv.h b/drivers/mxc/ipu3/ipu_prv.h
index 0114cc167ee..dfb7b38bc44 100644
--- a/drivers/mxc/ipu3/ipu_prv.h
+++ b/drivers/mxc/ipu3/ipu_prv.h
@@ -15,11 +15,9 @@
#include <linux/types.h>
#include <linux/device.h>
-#include <linux/clkdev.h>
+#include <mach/clock.h>
#include <linux/interrupt.h>
#include <linux/fsl_devices.h>
-#include <mach/clock.h>
-#include <mach/ipu-v3.h>
#ifdef CONFIG_MXC_IPU_V3H
#define MXC_IPU_MAX_NUM 2
@@ -29,8 +27,6 @@
/* Globals */
extern int dmfc_type_setup;
-extern struct clk ipu_pixel_clk[];
-extern struct clk_lookup ipu_lookups[];
#define IDMA_CHAN_INVALID 0xFF
#define HIGH_RESOLUTION_WIDTH 1024
@@ -54,6 +50,7 @@ enum csc_type_t {
struct ipu_soc {
/*clk*/
struct clk *ipu_clk;
+ bool clk_enabled;
struct clk *di_clk[2];
struct clk *csi_clk[2];
struct clk pixel_clk[2];
@@ -79,6 +76,7 @@ struct ipu_soc {
u32 *disp_base[2];
u32 *vdi_reg;
+ spinlock_t ipu_lock;
struct device *dev;
ipu_channel_t csi_channel[2];
@@ -91,7 +89,6 @@ struct ipu_soc {
uint32_t channel_enable_mask;
/*use count*/
- int ipu_use_count;
int dc_use_count;
int dp_use_count;
int dmfc_use_count;
@@ -102,9 +99,6 @@ struct ipu_soc {
int di_use_count[2];
int csi_use_count[2];
- struct mutex mutex_lock;
- spinlock_t spin_lock;
-
int dmfc_size_28;
int dmfc_size_29;
int dmfc_size_24;
@@ -321,12 +315,5 @@ void _ipu_csi_ccir_err_detection_disable(struct ipu_soc *ipu, uint32_t csi);
void _ipu_smfc_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t mipi_id, uint32_t csi);
void _ipu_smfc_set_burst_size(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t bs);
void _ipu_dp_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3]);
-int32_t _ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
- int16_t x_pos, int16_t y_pos);
-int32_t _ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
- int16_t *x_pos, int16_t *y_pos);
-void _ipu_get(struct ipu_soc *ipu);
-void _ipu_put(struct ipu_soc *ipu);
-void _ipu_lock(struct ipu_soc *ipu, unsigned long *flags);
-void _ipu_unlock(struct ipu_soc *ipu, unsigned long *flags);
+
#endif /* __INCLUDE_IPU_PRV_H__ */
diff --git a/include/linux/ipu.h b/include/linux/ipu.h
index d6c1588b82c..06d8c64a6d6 100644
--- a/include/linux/ipu.h
+++ b/include/linux/ipu.h
@@ -59,6 +59,25 @@ typedef enum {
} ipu_rotate_mode_t;
/*!
+ * Enumeration of Post Filter modes
+ */
+typedef enum {
+ PF_DISABLE_ALL = 0,
+ PF_MPEG4_DEBLOCK = 1,
+ PF_MPEG4_DERING = 2,
+ PF_MPEG4_DEBLOCK_DERING = 3,
+ PF_H264_DEBLOCK = 4,
+} pf_operation_t;
+
+/*!
+ * Enumeration of Synchronous (Memory-less) panel types
+ */
+typedef enum {
+ IPU_PANEL_SHARP_TFT,
+ IPU_PANEL_TFT,
+} ipu_panel_t;
+
+/*!
* Enumeration of VDI MOTION select
*/
typedef enum {
@@ -67,16 +86,6 @@ typedef enum {
HIGH_MOTION = 2,
} ipu_motion_sel;
-/*!
- * Enumeration of DI ports for ADC.
- */
-typedef enum {
- DISP0,
- DISP1,
- DISP2,
- DISP3
-} display_port_t;
-
/* IPU Pixel format definitions */
/* Four-character-code (FOURCC) */
#define fourcc(a, b, c, d)\
@@ -137,6 +146,925 @@ typedef enum {
#define IPU_PIX_FMT_YUV422P fourcc('4', '2', '2', 'P') /*!< 16 YUV 4:2:2 */
/*! @} */
+/* IPU Driver channels definitions. */
+/* Note these are different from IDMA channels */
+#ifdef CONFIG_MXC_IPU_V1
+#define _MAKE_CHAN(num, in, out, sec) ((num << 24) | (sec << 16) | (out << 8) | in)
+#define IPU_CHAN_ID(ch) (ch >> 24)
+#define IPU_CHAN_SEC_DMA(ch) ((uint32_t) (ch >> 16) & 0xFF)
+#define IPU_CHAN_OUT_DMA(ch) ((uint32_t) (ch >> 8) & 0xFF)
+#define IPU_CHAN_IN_DMA(ch) ((uint32_t) (ch & 0xFF))
+
+#else
+#define IPU_MAX_CH 32
+#define _MAKE_CHAN(num, v_in, g_in, a_in, out) \
+ ((num << 24) | (v_in << 18) | (g_in << 12) | (a_in << 6) | out)
+#define _MAKE_ALT_CHAN(ch) (ch | (IPU_MAX_CH << 24))
+#define IPU_CHAN_ID(ch) (ch >> 24)
+#define IPU_CHAN_ALT(ch) (ch & 0x02000000)
+#define IPU_CHAN_ALPHA_IN_DMA(ch) ((uint32_t) (ch >> 6) & 0x3F)
+#define IPU_CHAN_GRAPH_IN_DMA(ch) ((uint32_t) (ch >> 12) & 0x3F)
+#define IPU_CHAN_VIDEO_IN_DMA(ch) ((uint32_t) (ch >> 18) & 0x3F)
+#define IPU_CHAN_OUT_DMA(ch) ((uint32_t) (ch & 0x3F))
+#define NO_DMA 0x3F
+#define ALT 1
+#endif
+/*!
+ * Enumeration of IPU logical channels. An IPU logical channel is defined as a
+ * combination of an input (memory to IPU), output (IPU to memory), and/or
+ * secondary input IDMA channels and in some cases an Image Converter task.
+ * Some channels consist of only an input or output.
+ */
+typedef enum {
+ CHAN_NONE = -1,
+#ifdef CONFIG_MXC_IPU_V1
+ CSI_MEM = _MAKE_CHAN(1, 0xFF, 7, 0xFF), /*!< CSI raw sensor data to memory */
+
+ CSI_PRP_ENC_MEM = _MAKE_CHAN(2, 0xFF, 0, 0xFF), /*!< CSI to IC Encoder PreProcessing to Memory */
+ MEM_PRP_ENC_MEM = _MAKE_CHAN(3, 6, 0, 0xFF), /*!< Memory to IC Encoder PreProcessing to Memory */
+ MEM_ROT_ENC_MEM = _MAKE_CHAN(4, 10, 8, 0xFF), /*!< Memory to IC Encoder Rotation to Memory */
+
+ CSI_PRP_VF_MEM = _MAKE_CHAN(5, 0xFF, 1, 0xFF), /*!< CSI to IC Viewfinder PreProcessing to Memory */
+ CSI_PRP_VF_ADC = _MAKE_CHAN(6, 0xFF, 1, 0xFF), /*!< CSI to IC Viewfinder PreProcessing to ADC */
+ MEM_PRP_VF_MEM = _MAKE_CHAN(7, 6, 1, 3), /*!< Memory to IC Viewfinder PreProcessing to Memory */
+ MEM_PRP_VF_ADC = _MAKE_CHAN(8, 6, 1, 3), /*!< Memory to IC Viewfinder PreProcessing to ADC */
+ MEM_ROT_VF_MEM = _MAKE_CHAN(9, 11, 9, 0xFF), /*!< Memory to IC Viewfinder Rotation to Memory */
+
+ MEM_PP_MEM = _MAKE_CHAN(10, 5, 2, 4), /*!< Memory to IC PostProcessing to Memory */
+ MEM_ROT_PP_MEM = _MAKE_CHAN(11, 13, 12, 0xFF), /*!< Memory to IC PostProcessing Rotation to Memory */
+ MEM_PP_ADC = _MAKE_CHAN(12, 5, 2, 4), /*!< Memory to IC PostProcessing to ADC */
+
+ MEM_SDC_BG = _MAKE_CHAN(14, 14, 0xFF, 0xFF), /*!< Memory to SDC Background plane */
+ MEM_SDC_FG = _MAKE_CHAN(15, 15, 0xFF, 0xFF), /*!< Memory to SDC Foreground plane */
+ MEM_SDC_MASK = _MAKE_CHAN(16, 16, 0xFF, 0xFF), /*!< Memory to SDC Mask */
+
+ MEM_BG_SYNC = MEM_SDC_BG,
+ MEM_FG_SYNC = MEM_SDC_FG,
+
+ ADC_SYS1 = _MAKE_CHAN(17, 18, 22, 20), /*!< Memory to ADC System Channel 1 */
+ ADC_SYS2 = _MAKE_CHAN(18, 19, 23, 21), /*!< Memory to ADC System Channel 2 */
+
+ MEM_PF_Y_MEM = _MAKE_CHAN(19, 26, 29, 24), /*!< Y and PF Memory to Post-filter to Y Memory */
+ MEM_PF_U_MEM = _MAKE_CHAN(20, 27, 30, 25), /*!< U and PF Memory to Post-filter to U Memory */
+ MEM_PF_V_MEM = _MAKE_CHAN(21, 28, 31, 0xFF), /*!< V Memory to Post-filter to V Memory */
+
+ MEM_DC_SYNC = CHAN_NONE,
+ DIRECT_ASYNC0 = CHAN_NONE,
+ DIRECT_ASYNC1 = CHAN_NONE,
+ MEM_VDI_PRP_VF_MEM_P = CHAN_NONE,
+ MEM_VDI_PRP_VF_MEM = CHAN_NONE,
+ MEM_VDI_PRP_VF_MEM_N = CHAN_NONE,
+#else
+ MEM_ROT_ENC_MEM = _MAKE_CHAN(1, 45, NO_DMA, NO_DMA, 48),
+ MEM_ROT_VF_MEM = _MAKE_CHAN(2, 46, NO_DMA, NO_DMA, 49),
+ MEM_ROT_PP_MEM = _MAKE_CHAN(3, 47, NO_DMA, NO_DMA, 50),
+
+ MEM_PRP_ENC_MEM = _MAKE_CHAN(4, 12, 14, 17, 20),
+ MEM_PRP_VF_MEM = _MAKE_CHAN(5, 12, 14, 17, 21),
+ MEM_PP_MEM = _MAKE_CHAN(6, 11, 15, 18, 22),
+
+ MEM_DC_SYNC = _MAKE_CHAN(7, 28, NO_DMA, NO_DMA, NO_DMA),
+ MEM_DC_ASYNC = _MAKE_CHAN(8, 41, NO_DMA, NO_DMA, NO_DMA),
+ MEM_BG_SYNC = _MAKE_CHAN(9, 23, NO_DMA, 51, NO_DMA),
+ MEM_FG_SYNC = _MAKE_CHAN(10, 27, NO_DMA, 31, NO_DMA),
+
+ MEM_BG_ASYNC0 = _MAKE_CHAN(11, 24, NO_DMA, 52, NO_DMA),
+ MEM_FG_ASYNC0 = _MAKE_CHAN(12, 29, NO_DMA, 33, NO_DMA),
+ MEM_BG_ASYNC1 = _MAKE_ALT_CHAN(MEM_BG_ASYNC0),
+ MEM_FG_ASYNC1 = _MAKE_ALT_CHAN(MEM_FG_ASYNC0),
+
+ DIRECT_ASYNC0 = _MAKE_CHAN(13, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
+ DIRECT_ASYNC1 = _MAKE_CHAN(14, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
+
+ CSI_MEM0 = _MAKE_CHAN(15, NO_DMA, NO_DMA, NO_DMA, 0),
+ CSI_MEM1 = _MAKE_CHAN(16, NO_DMA, NO_DMA, NO_DMA, 1),
+ CSI_MEM2 = _MAKE_CHAN(17, NO_DMA, NO_DMA, NO_DMA, 2),
+ CSI_MEM3 = _MAKE_CHAN(18, NO_DMA, NO_DMA, NO_DMA, 3),
+
+ CSI_MEM = CSI_MEM0,
+
+ CSI_PRP_ENC_MEM = _MAKE_CHAN(19, NO_DMA, NO_DMA, NO_DMA, 20),
+ CSI_PRP_VF_MEM = _MAKE_CHAN(20, NO_DMA, NO_DMA, NO_DMA, 21),
+
+ MEM_VDI_PRP_VF_MEM_P = _MAKE_CHAN(21, 8, 14, 17, 21),
+ MEM_VDI_PRP_VF_MEM = _MAKE_CHAN(22, 9, 14, 17, 21),
+ MEM_VDI_PRP_VF_MEM_N = _MAKE_CHAN(23, 10, 14, 17, 21),
+
+ MEM_PP_ADC = CHAN_NONE,
+ ADC_SYS2 = CHAN_NONE,
+#endif
+
+} ipu_channel_t;
+
+/*!
+ * Enumeration of types of buffers for a logical channel.
+ */
+typedef enum {
+ IPU_OUTPUT_BUFFER = 0, /*!< Buffer for output from IPU */
+ IPU_ALPHA_IN_BUFFER = 1, /*!< Buffer for input to IPU */
+ IPU_GRAPH_IN_BUFFER = 2, /*!< Buffer for input to IPU */
+ IPU_VIDEO_IN_BUFFER = 3, /*!< Buffer for input to IPU */
+ IPU_INPUT_BUFFER = IPU_VIDEO_IN_BUFFER,
+ IPU_SEC_INPUT_BUFFER = IPU_GRAPH_IN_BUFFER,
+} ipu_buffer_t;
+
+#define IPU_PANEL_SERIAL 1
+#define IPU_PANEL_PARALLEL 2
+
+/*!
+ * Enumeration of DI ports for ADC.
+ */
+typedef enum {
+ DISP0,
+ DISP1,
+ DISP2,
+ DISP3
+} display_port_t;
+
+/*!
+ * Enumeration of ADC channel operation mode.
+ */
+typedef enum {
+ Disable,
+ WriteTemplateNonSeq,
+ ReadTemplateNonSeq,
+ WriteTemplateUnCon,
+ ReadTemplateUnCon,
+ WriteDataWithRS,
+ WriteDataWoRS,
+ WriteCmd
+} mcu_mode_t;
+
+/*!
+ * Enumeration of ADC channel addressing mode.
+ */
+typedef enum {
+ FullWoBE,
+ FullWithBE,
+ XY
+} display_addressing_t;
+
+/*!
+ * Union of initialization parameters for a logical channel.
+ */
+typedef union {
+ struct {
+ uint32_t csi;
+ uint32_t mipi_id;
+ bool mipi_en;
+ bool interlaced;
+ } csi_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ uint32_t csi;
+ } csi_prp_enc_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ uint32_t outh_resize_ratio;
+ uint32_t outv_resize_ratio;
+ } mem_prp_enc_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ } mem_rot_enc_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ bool graphics_combine_en;
+ bool global_alpha_en;
+ bool key_color_en;
+ uint32_t csi;
+ } csi_prp_vf_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ bool graphics_combine_en;
+ bool global_alpha_en;
+ bool key_color_en;
+ display_port_t disp;
+ uint32_t out_left;
+ uint32_t out_top;
+ } csi_prp_vf_adc;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ uint32_t outh_resize_ratio;
+ uint32_t outv_resize_ratio;
+ bool graphics_combine_en;
+ bool global_alpha_en;
+ bool key_color_en;
+ uint32_t in_g_pixel_fmt;
+ uint8_t alpha;
+ uint32_t key_color;
+ bool alpha_chan_en;
+ ipu_motion_sel motion_sel;
+ enum v4l2_field field_fmt;
+ } mem_prp_vf_mem;
+ struct {
+ uint32_t temp;
+ } mem_prp_vf_adc;
+ struct {
+ uint32_t temp;
+ } mem_rot_vf_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ uint32_t outh_resize_ratio;
+ uint32_t outv_resize_ratio;
+ bool graphics_combine_en;
+ bool global_alpha_en;
+ bool key_color_en;
+ uint32_t in_g_pixel_fmt;
+ uint8_t alpha;
+ uint32_t key_color;
+ bool alpha_chan_en;
+ } mem_pp_mem;
+ struct {
+ uint32_t temp;
+ } mem_rot_mem;
+ struct {
+ uint32_t in_width;
+ uint32_t in_height;
+ uint32_t in_pixel_fmt;
+ uint32_t out_width;
+ uint32_t out_height;
+ uint32_t out_pixel_fmt;
+ bool graphics_combine_en;
+ bool global_alpha_en;
+ bool key_color_en;
+ display_port_t disp;
+ uint32_t out_left;
+ uint32_t out_top;
+ } mem_pp_adc;
+ struct {
+ pf_operation_t operation;
+ } mem_pf_mem;
+ struct {
+ uint32_t di;
+ bool interlaced;
+ uint32_t in_pixel_fmt;
+ uint32_t out_pixel_fmt;
+ } mem_dc_sync;
+ struct {
+ uint32_t temp;
+ } mem_sdc_fg;
+ struct {
+ uint32_t di;
+ bool interlaced;
+ uint32_t in_pixel_fmt;
+ uint32_t out_pixel_fmt;
+ bool alpha_chan_en;
+ } mem_dp_bg_sync;
+ struct {
+ uint32_t temp;
+ } mem_sdc_bg;
+ struct {
+ uint32_t di;
+ bool interlaced;
+ uint32_t in_pixel_fmt;
+ uint32_t out_pixel_fmt;
+ bool alpha_chan_en;
+ } mem_dp_fg_sync;
+ struct {
+ uint32_t di;
+ } direct_async;
+ struct {
+ display_port_t disp;
+ mcu_mode_t ch_mode;
+ uint32_t out_left;
+ uint32_t out_top;
+ } adc_sys1;
+ struct {
+ display_port_t disp;
+ mcu_mode_t ch_mode;
+ uint32_t out_left;
+ uint32_t out_top;
+ } adc_sys2;
+} ipu_channel_params_t;
+
+/*!
+ * Enumeration of IPU interrupt sources.
+ */
+enum ipu_irq_line {
+#ifdef CONFIG_MXC_IPU_V1
+ IPU_IRQ_DC_FC_1 = -1,
+
+ IPU_IRQ_PRP_ENC_OUT_EOF = 0,
+ IPU_IRQ_PRP_VF_OUT_EOF = 1,
+ IPU_IRQ_PP_OUT_EOF = 2,
+ IPU_IRQ_PRP_GRAPH_IN_EOF = 3,
+ IPU_IRQ_PP_GRAPH_IN_EOF = 4,
+ IPU_IRQ_PP_IN_EOF = 5,
+ IPU_IRQ_PRP_IN_EOF = 6,
+ IPU_IRQ_SENSOR_OUT_EOF = 7,
+ IPU_IRQ_CSI0_OUT_EOF = IPU_IRQ_SENSOR_OUT_EOF,
+ IPU_IRQ_PRP_ENC_ROT_OUT_EOF = 8,
+ IPU_IRQ_PRP_VF_ROT_OUT_EOF = 9,
+ IPU_IRQ_PRP_ENC_ROT_IN_EOF = 10,
+ IPU_IRQ_PRP_VF_ROT_IN_EOF = 11,
+ IPU_IRQ_PP_ROT_OUT_EOF = 12,
+ IPU_IRQ_PP_ROT_IN_EOF = 13,
+ IPU_IRQ_BG_SYNC_EOF = 14,
+ IPU_IRQ_SDC_BG_EOF = IPU_IRQ_BG_SYNC_EOF,
+ IPU_IRQ_FG_SYNC_EOF = 15,
+ IPU_IRQ_SDC_FG_EOF = IPU_IRQ_FG_SYNC_EOF,
+ IPU_IRQ_SDC_MASK_EOF = 16,
+ IPU_IRQ_SDC_BG_PART_EOF = 17,
+ IPU_IRQ_ADC_SYS1_WR_EOF = 18,
+ IPU_IRQ_ADC_SYS2_WR_EOF = 19,
+ IPU_IRQ_ADC_SYS1_CMD_EOF = 20,
+ IPU_IRQ_ADC_SYS2_CMD_EOF = 21,
+ IPU_IRQ_ADC_SYS1_RD_EOF = 22,
+ IPU_IRQ_ADC_SYS2_RD_EOF = 23,
+ IPU_IRQ_PF_QP_IN_EOF = 24,
+ IPU_IRQ_PF_BSP_IN_EOF = 25,
+ IPU_IRQ_PF_Y_IN_EOF = 26,
+ IPU_IRQ_PF_U_IN_EOF = 27,
+ IPU_IRQ_PF_V_IN_EOF = 28,
+ IPU_IRQ_PF_Y_OUT_EOF = 29,
+ IPU_IRQ_PF_U_OUT_EOF = 30,
+ IPU_IRQ_PF_V_OUT_EOF = 31,
+
+ IPU_IRQ_PRP_ENC_OUT_NF = 32,
+ IPU_IRQ_PRP_VF_OUT_NF = 33,
+ IPU_IRQ_PP_OUT_NF = 34,
+ IPU_IRQ_PRP_GRAPH_IN_NF = 35,
+ IPU_IRQ_PP_GRAPH_IN_NF = 36,
+ IPU_IRQ_PP_IN_NF = 37,
+ IPU_IRQ_PRP_IN_NF = 38,
+ IPU_IRQ_SENSOR_OUT_NF = 39,
+ IPU_IRQ_PRP_ENC_ROT_OUT_NF = 40,
+ IPU_IRQ_PRP_VF_ROT_OUT_NF = 41,
+ IPU_IRQ_PRP_ENC_ROT_IN_NF = 42,
+ IPU_IRQ_PRP_VF_ROT_IN_NF = 43,
+ IPU_IRQ_PP_ROT_OUT_NF = 44,
+ IPU_IRQ_PP_ROT_IN_NF = 45,
+ IPU_IRQ_SDC_FG_NF = 46,
+ IPU_IRQ_SDC_BG_NF = 47,
+ IPU_IRQ_SDC_MASK_NF = 48,
+ IPU_IRQ_SDC_BG_PART_NF = 49,
+ IPU_IRQ_ADC_SYS1_WR_NF = 50,
+ IPU_IRQ_ADC_SYS2_WR_NF = 51,
+ IPU_IRQ_ADC_SYS1_CMD_NF = 52,
+ IPU_IRQ_ADC_SYS2_CMD_NF = 53,
+ IPU_IRQ_ADC_SYS1_RD_NF = 54,
+ IPU_IRQ_ADC_SYS2_RD_NF = 55,
+ IPU_IRQ_PF_QP_IN_NF = 56,
+ IPU_IRQ_PF_BSP_IN_NF = 57,
+ IPU_IRQ_PF_Y_IN_NF = 58,
+ IPU_IRQ_PF_U_IN_NF = 59,
+ IPU_IRQ_PF_V_IN_NF = 60,
+ IPU_IRQ_PF_Y_OUT_NF = 61,
+ IPU_IRQ_PF_U_OUT_NF = 62,
+ IPU_IRQ_PF_V_OUT_NF = 63,
+
+ IPU_IRQ_BREAKRQ = 64,
+ IPU_IRQ_SDC_BG_OUT_EOF = 65,
+ IPU_IRQ_BG_SF_END = IPU_IRQ_SDC_BG_OUT_EOF,
+ IPU_IRQ_SDC_FG_OUT_EOF = 66,
+ IPU_IRQ_SDC_MASK_OUT_EOF = 67,
+ IPU_IRQ_ADC_SERIAL_DATA_OUT = 68,
+ IPU_IRQ_SENSOR_NF = 69,
+ IPU_IRQ_SENSOR_EOF = 70,
+ IPU_IRQ_SDC_DISP3_VSYNC = 80,
+ IPU_IRQ_ADC_DISP0_VSYNC = 81,
+ IPU_IRQ_ADC_DISP12_VSYNC = 82,
+ IPU_IRQ_ADC_PRP_EOF = 83,
+ IPU_IRQ_ADC_PP_EOF = 84,
+ IPU_IRQ_ADC_SYS1_EOF = 85,
+ IPU_IRQ_ADC_SYS2_EOF = 86,
+
+ IPU_IRQ_PRP_ENC_OUT_NFB4EOF_ERR = 96,
+ IPU_IRQ_PRP_VF_OUT_NFB4EOF_ERR = 97,
+ IPU_IRQ_PP_OUT_NFB4EOF_ERR = 98,
+ IPU_IRQ_PRP_GRAPH_IN_NFB4EOF_ERR = 99,
+ IPU_IRQ_PP_GRAPH_IN_NFB4EOF_ERR = 100,
+ IPU_IRQ_PP_IN_NFB4EOF_ERR = 101,
+ IPU_IRQ_PRP_IN_NFB4EOF_ERR = 102,
+ IPU_IRQ_SENSOR_OUT_NFB4EOF_ERR = 103,
+ IPU_IRQ_PRP_ENC_ROT_OUT_NFB4EOF_ERR = 104,
+ IPU_IRQ_PRP_VF_ROT_OUT_NFB4EOF_ERR = 105,
+ IPU_IRQ_PRP_ENC_ROT_IN_NFB4EOF_ERR = 106,
+ IPU_IRQ_PRP_VF_ROT_IN_NFB4EOF_ERR = 107,
+ IPU_IRQ_PP_ROT_OUT_NFB4EOF_ERR = 108,
+ IPU_IRQ_PP_ROT_IN_NFB4EOF_ERR = 109,
+ IPU_IRQ_SDC_FG_NFB4EOF_ERR = 110,
+ IPU_IRQ_SDC_BG_NFB4EOF_ERR = 111,
+ IPU_IRQ_SDC_MASK_NFB4EOF_ERR = 112,
+ IPU_IRQ_SDC_BG_PART_NFB4EOF_ERR = 113,
+ IPU_IRQ_ADC_SYS1_WR_NFB4EOF_ERR = 114,
+ IPU_IRQ_ADC_SYS2_WR_NFB4EOF_ERR = 115,
+ IPU_IRQ_ADC_SYS1_CMD_NFB4EOF_ERR = 116,
+ IPU_IRQ_ADC_SYS2_CMD_NFB4EOF_ERR = 117,
+ IPU_IRQ_ADC_SYS1_RD_NFB4EOF_ERR = 118,
+ IPU_IRQ_ADC_SYS2_RD_NFB4EOF_ERR = 119,
+ IPU_IRQ_PF_QP_IN_NFB4EOF_ERR = 120,
+ IPU_IRQ_PF_BSP_IN_NFB4EOF_ERR = 121,
+ IPU_IRQ_PF_Y_IN_NFB4EOF_ERR = 122,
+ IPU_IRQ_PF_U_IN_NFB4EOF_ERR = 123,
+ IPU_IRQ_PF_V_IN_NFB4EOF_ERR = 124,
+ IPU_IRQ_PF_Y_OUT_NFB4EOF_ERR = 125,
+ IPU_IRQ_PF_U_OUT_NFB4EOF_ERR = 126,
+ IPU_IRQ_PF_V_OUT_NFB4EOF_ERR = 127,
+
+ IPU_IRQ_BAYER_BUFOVF_ERR = 128,
+ IPU_IRQ_ENC_BUFOVF_ERR = 129,
+ IPU_IRQ_VF_BUFOVF_ERR = 130,
+ IPU_IRQ_ADC_PP_TEAR_ERR = 131,
+ IPU_IRQ_ADC_SYS1_TEAR_ERR = 132,
+ IPU_IRQ_ADC_SYS2_TEAR_ERR = 133,
+ IPU_IRQ_SDC_BGD_ERR = 134,
+ IPU_IRQ_SDC_FGD_ERR = 135,
+ IPU_IRQ_SDC_MASKD_ERR = 136,
+ IPU_IRQ_BAYER_FRM_LOST_ERR = 137,
+ IPU_IRQ_ENC_FRM_LOST_ERR = 138,
+ IPU_IRQ_VF_FRM_LOST_ERR = 139,
+ IPU_IRQ_ADC_LOCK_ERR = 140,
+ IPU_IRQ_DI_LLA_LOCK_ERR = 141,
+ IPU_IRQ_AHB_M1_ERR = 142,
+ IPU_IRQ_AHB_M12_ERR = 143,
+#else
+ IPU_IRQ_CSI0_OUT_EOF = 0,
+ IPU_IRQ_CSI1_OUT_EOF = 1,
+ IPU_IRQ_CSI2_OUT_EOF = 2,
+ IPU_IRQ_CSI3_OUT_EOF = 3,
+ IPU_IRQ_VDI_P_IN_EOF = 8,
+ IPU_IRQ_VDI_C_IN_EOF = 9,
+ IPU_IRQ_VDI_N_IN_EOF = 10,
+ IPU_IRQ_PP_IN_EOF = 11,
+ IPU_IRQ_PRP_IN_EOF = 12,
+ IPU_IRQ_PRP_GRAPH_IN_EOF = 14,
+ IPU_IRQ_PP_GRAPH_IN_EOF = 15,
+ IPU_IRQ_PRP_ALPHA_IN_EOF = 17,
+ IPU_IRQ_PP_ALPHA_IN_EOF = 18,
+ IPU_IRQ_PRP_ENC_OUT_EOF = 20,
+ IPU_IRQ_PRP_VF_OUT_EOF = 21,
+ IPU_IRQ_PP_OUT_EOF = 22,
+ IPU_IRQ_BG_SYNC_EOF = 23,
+ IPU_IRQ_BG_ASYNC_EOF = 24,
+ IPU_IRQ_FG_SYNC_EOF = 27,
+ IPU_IRQ_DC_SYNC_EOF = 28,
+ IPU_IRQ_FG_ASYNC_EOF = 29,
+ IPU_IRQ_FG_ALPHA_SYNC_EOF = 31,
+
+ IPU_IRQ_FG_ALPHA_ASYNC_EOF = 33,
+ IPU_IRQ_DC_READ_EOF = 40,
+ IPU_IRQ_DC_ASYNC_EOF = 41,
+ IPU_IRQ_DC_CMD1_EOF = 42,
+ IPU_IRQ_DC_CMD2_EOF = 43,
+ IPU_IRQ_DC_MASK_EOF = 44,
+ IPU_IRQ_PRP_ENC_ROT_IN_EOF = 45,
+ IPU_IRQ_PRP_VF_ROT_IN_EOF = 46,
+ IPU_IRQ_PP_ROT_IN_EOF = 47,
+ IPU_IRQ_PRP_ENC_ROT_OUT_EOF = 48,
+ IPU_IRQ_PRP_VF_ROT_OUT_EOF = 49,
+ IPU_IRQ_PP_ROT_OUT_EOF = 50,
+ IPU_IRQ_BG_ALPHA_SYNC_EOF = 51,
+ IPU_IRQ_BG_ALPHA_ASYNC_EOF = 52,
+
+ IPU_IRQ_DP_SF_START = 448 + 2,
+ IPU_IRQ_DP_SF_END = 448 + 3,
+ IPU_IRQ_BG_SF_END = IPU_IRQ_DP_SF_END,
+ IPU_IRQ_DC_FC_0 = 448 + 8,
+ IPU_IRQ_DC_FC_1 = 448 + 9,
+ IPU_IRQ_DC_FC_2 = 448 + 10,
+ IPU_IRQ_DC_FC_3 = 448 + 11,
+ IPU_IRQ_DC_FC_4 = 448 + 12,
+ IPU_IRQ_DC_FC_6 = 448 + 13,
+ IPU_IRQ_VSYNC_PRE_0 = 448 + 14,
+ IPU_IRQ_VSYNC_PRE_1 = 448 + 15,
+#endif
+
+ IPU_IRQ_COUNT
+};
+
+/*!
+ * Bitfield of Display Interface signal polarities.
+ */
+typedef struct {
+ unsigned datamask_en:1;
+ unsigned int_clk:1;
+ unsigned interlaced:1;
+ unsigned odd_field_first:1;
+ unsigned clksel_en:1;
+ unsigned clkidle_en:1;
+ unsigned data_pol:1; /* true = inverted */
+ unsigned clk_pol:1; /* true = rising edge */
+ unsigned enable_pol:1;
+ unsigned Hsync_pol:1; /* true = active high */
+ unsigned Vsync_pol:1;
+} ipu_di_signal_cfg_t;
+
+/*!
+ * Bitfield of CSI signal polarities and modes.
+ */
+
+typedef struct {
+ unsigned data_width:4;
+ unsigned clk_mode:3;
+ unsigned ext_vsync:1;
+ unsigned Vsync_pol:1;
+ unsigned Hsync_pol:1;
+ unsigned pixclk_pol:1;
+ unsigned data_pol:1;
+ unsigned sens_clksrc:1;
+ unsigned pack_tight:1;
+ unsigned force_eof:1;
+ unsigned data_en_pol:1;
+ unsigned data_fmt;
+ unsigned csi;
+ unsigned mclk;
+} ipu_csi_signal_cfg_t;
+
+/*!
+ * Enumeration of CSI data bus widths.
+ */
+enum {
+ IPU_CSI_DATA_WIDTH_4,
+ IPU_CSI_DATA_WIDTH_8,
+ IPU_CSI_DATA_WIDTH_10,
+ IPU_CSI_DATA_WIDTH_16,
+};
+
+/*!
+ * Enumeration of CSI clock modes.
+ */
+enum {
+ IPU_CSI_CLK_MODE_GATED_CLK,
+ IPU_CSI_CLK_MODE_NONGATED_CLK,
+ IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
+ IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
+ IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
+ IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
+ IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
+ IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
+};
+
+enum {
+ IPU_CSI_MIPI_DI0,
+ IPU_CSI_MIPI_DI1,
+ IPU_CSI_MIPI_DI2,
+ IPU_CSI_MIPI_DI3,
+};
+
+typedef enum {
+ RGB,
+ YCbCr,
+ YUV
+} ipu_color_space_t;
+
+/*!
+ * Enumeration of ADC vertical sync mode.
+ */
+typedef enum {
+ VsyncNone,
+ VsyncInternal,
+ VsyncCSI,
+ VsyncExternal
+} vsync_t;
+
+typedef enum {
+ DAT,
+ CMD
+} cmddata_t;
+
+/*!
+ * Enumeration of ADC display update mode.
+ */
+typedef enum {
+ IPU_ADC_REFRESH_NONE,
+ IPU_ADC_AUTO_REFRESH,
+ IPU_ADC_AUTO_REFRESH_SNOOP,
+ IPU_ADC_SNOOPING,
+} ipu_adc_update_mode_t;
+
+/*!
+ * Enumeration of ADC display interface types (serial or parallel).
+ */
+enum {
+ IPU_ADC_IFC_MODE_SYS80_TYPE1,
+ IPU_ADC_IFC_MODE_SYS80_TYPE2,
+ IPU_ADC_IFC_MODE_SYS68K_TYPE1,
+ IPU_ADC_IFC_MODE_SYS68K_TYPE2,
+ IPU_ADC_IFC_MODE_3WIRE_SERIAL,
+ IPU_ADC_IFC_MODE_4WIRE_SERIAL,
+ IPU_ADC_IFC_MODE_5WIRE_SERIAL_CLK,
+ IPU_ADC_IFC_MODE_5WIRE_SERIAL_CS,
+};
+
+enum {
+ IPU_ADC_IFC_WIDTH_8,
+ IPU_ADC_IFC_WIDTH_16,
+};
+
+/*!
+ * Enumeration of ADC display interface burst mode.
+ */
+enum {
+ IPU_ADC_BURST_WCS,
+ IPU_ADC_BURST_WBLCK,
+ IPU_ADC_BURST_NONE,
+ IPU_ADC_BURST_SERIAL,
+};
+
+/*!
+ * Enumeration of ADC display interface RW signal timing modes.
+ */
+enum {
+ IPU_ADC_SER_NO_RW,
+ IPU_ADC_SER_RW_BEFORE_RS,
+ IPU_ADC_SER_RW_AFTER_RS,
+};
+
+/*!
+ * Bitfield of ADC signal polarities and modes.
+ */
+typedef struct {
+ unsigned data_pol:1;
+ unsigned clk_pol:1;
+ unsigned cs_pol:1;
+ unsigned rs_pol:1;
+ unsigned addr_pol:1;
+ unsigned read_pol:1;
+ unsigned write_pol:1;
+ unsigned Vsync_pol:1;
+ unsigned burst_pol:1;
+ unsigned burst_mode:2;
+ unsigned ifc_mode:3;
+ unsigned ifc_width:5;
+ unsigned ser_preamble_len:4;
+ unsigned ser_preamble:8;
+ unsigned ser_rw_mode:2;
+} ipu_adc_sig_cfg_t;
+
+/*!
+ * Enumeration of ADC template commands.
+ */
+enum {
+ RD_DATA,
+ RD_ACK,
+ RD_WAIT,
+ WR_XADDR,
+ WR_YADDR,
+ WR_ADDR,
+ WR_CMND,
+ WR_DATA,
+};
+
+/*!
+ * Enumeration of ADC template command flow control.
+ */
+enum {
+ SINGLE_STEP,
+ PAUSE,
+ STOP,
+};
+
+
+/*Define template constants*/
+#define ATM_ADDR_RANGE 0x20 /*offset address of DISP */
+#define TEMPLATE_BUF_SIZE 0x20 /*size of template */
+
+/*!
+ * Define to create ADC template command entry.
+ */
+#define ipu_adc_template_gen(oc, rs, fc, dat) (((rs) << 29) | ((fc) << 27) | \
+ ((oc) << 24) | (dat))
+
+typedef struct {
+ u32 reg;
+ u32 value;
+} ipu_lpmc_reg_t;
+
+#define IPU_LPMC_REG_READ 0x80000000L
+
+#define CSI_MCLK_VF 1
+#define CSI_MCLK_ENC 2
+#define CSI_MCLK_RAW 4
+#define CSI_MCLK_I2C 8
+
+struct ipu_soc;
+/* Common IPU API */
+struct ipu_soc *ipu_get_soc(int id);
+int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params);
+void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel);
+
+static inline bool ipu_can_rotate_in_place(ipu_rotate_mode_t rot)
+{
+#ifdef CONFIG_MXC_IPU_V3D
+ return (rot < IPU_ROTATE_HORIZ_FLIP);
+#else
+ return (rot < IPU_ROTATE_90_RIGHT);
+#endif
+}
+
+int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t pixel_fmt,
+ uint16_t width, uint16_t height,
+ uint32_t stride,
+ ipu_rotate_mode_t rot_mode,
+ dma_addr_t phyaddr_0, dma_addr_t phyaddr_1,
+ dma_addr_t phyaddr_2,
+ uint32_t u_offset, uint32_t v_offset);
+
+int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t bufNum, dma_addr_t phyaddr);
+
+int32_t ipu_update_channel_offset(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t pixel_fmt,
+ uint16_t width, uint16_t height,
+ uint32_t stride,
+ uint32_t u, uint32_t v,
+ uint32_t vertical_offset, uint32_t horizontal_offset);
+
+int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
+ ipu_buffer_t type, uint32_t bufNum);
+int32_t ipu_select_multi_vdi_buffer(struct ipu_soc *ipu, uint32_t bufNum);
+
+int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch);
+int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch);
+
+int32_t ipu_is_channel_busy(struct ipu_soc *ipu, ipu_channel_t channel);
+int32_t ipu_check_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t bufNum);
+void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
+ uint32_t bufNum);
+uint32_t ipu_get_cur_buffer_idx(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type);
+int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel);
+int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wait_for_stop);
+int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel_t to_ch);
+
+int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi);
+int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi);
+
+int ipu_lowpwr_display_enable(void);
+int ipu_lowpwr_display_disable(void);
+
+void ipu_enable_irq(struct ipu_soc *ipu, uint32_t irq);
+void ipu_disable_irq(struct ipu_soc *ipu, uint32_t irq);
+void ipu_clear_irq(struct ipu_soc *ipu, uint32_t irq);
+int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
+ irqreturn_t(*handler) (int, void *),
+ uint32_t irq_flags, const char *devname, void *dev_id);
+void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id);
+bool ipu_get_irq_status(struct ipu_soc *ipu, uint32_t irq);
+void ipu_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3]);
+
+/* two stripe calculations */
+struct stripe_param{
+ unsigned int input_width; /* width of the input stripe */
+ unsigned int output_width; /* width of the output stripe */
+ unsigned int input_column; /* the first column on the input stripe */
+ unsigned int output_column; /* the first column on the output stripe */
+ unsigned int idr;
+ /* inverse downisizing ratio parameter; expressed as a power of 2 */
+ unsigned int irr;
+ /* inverse resizing ratio parameter; expressed as a multiple of 2^-13 */
+};
+int ipu_calc_stripes_sizes(const unsigned int input_frame_width,
+ unsigned int output_frame_width,
+ const unsigned int maximal_stripe_width,
+ const unsigned long long cirr,
+ const unsigned int equal_stripes,
+ u32 input_pixelformat,
+ u32 output_pixelformat,
+ struct stripe_param *left,
+ struct stripe_param *right);
+
+/* SDC API */
+int32_t ipu_sdc_init_panel(ipu_panel_t panel,
+ uint32_t pixel_clk,
+ uint16_t width, uint16_t height,
+ uint32_t pixel_fmt,
+ uint16_t hStartWidth, uint16_t hSyncWidth,
+ uint16_t hEndWidth, uint16_t vStartWidth,
+ uint16_t vSyncWidth, uint16_t vEndWidth,
+ ipu_di_signal_cfg_t sig);
+
+int32_t ipu_sdc_set_global_alpha(bool enable, uint8_t alpha);
+int32_t ipu_sdc_set_color_key(ipu_channel_t channel, bool enable,
+ uint32_t colorKey);
+int32_t ipu_sdc_set_brightness(uint8_t value);
+
+int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp,
+ uint32_t pixel_clk,
+ uint16_t width, uint16_t height,
+ uint32_t pixel_fmt,
+ uint16_t h_start_width, uint16_t h_sync_width,
+ uint16_t h_end_width, uint16_t v_start_width,
+ uint16_t v_sync_width, uint16_t v_end_width,
+ uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig);
+
+void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp);
+
+int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel, int16_t x_pos,
+ int16_t y_pos);
+int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel, int16_t *x_pos,
+ int16_t *y_pos);
+int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
+ uint8_t alpha);
+int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
+ uint32_t colorKey);
+int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
+ int constk[], int slopek[]);
+
+int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle_time,
+ uint32_t pixel_fmt, ipu_adc_sig_cfg_t sig);
+void ipu_disp_direct_write(struct ipu_soc *ipu, ipu_channel_t channel, u32 value, u32 offset);
+void ipu_reset_disp_panel(struct ipu_soc *ipu);
+
+/* ADC API */
+int32_t ipu_adc_write_template(display_port_t disp, uint32_t *pCmd,
+ bool write);
+
+int32_t ipu_adc_set_update_mode(ipu_channel_t channel,
+ ipu_adc_update_mode_t mode,
+ uint32_t refresh_rate, unsigned long addr,
+ uint32_t *size);
+
+int32_t ipu_adc_get_snooping_status(uint32_t *statl, uint32_t *stath);
+
+int32_t ipu_adc_write_cmd(display_port_t disp, cmddata_t type,
+ uint32_t cmd, const uint32_t *params,
+ uint16_t numParams);
+
+int32_t ipu_adc_init_panel(display_port_t disp,
+ uint16_t width, uint16_t height,
+ uint32_t pixel_fmt,
+ uint32_t stride,
+ ipu_adc_sig_cfg_t sig,
+ display_addressing_t addr,
+ uint32_t vsync_width, vsync_t mode);
+
+int32_t ipu_adc_init_ifc_timing(display_port_t disp, bool read,
+ uint32_t cycle_time,
+ uint32_t up_time,
+ uint32_t down_time,
+ uint32_t read_latch_time, uint32_t pixel_clk);
+
+/* CMOS Sensor Interface API */
+int32_t ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
+ uint32_t pixel_fmt, ipu_csi_signal_cfg_t sig);
+
+int32_t ipu_csi_get_sensor_protocol(struct ipu_soc *ipu, uint32_t csi);
+
+int32_t ipu_csi_enable_mclk(struct ipu_soc *ipu, int src, bool flag, bool wait);
+
+static inline int32_t ipu_csi_enable_mclk_if(struct ipu_soc *ipu, int src, uint32_t csi,
+ bool flag, bool wait)
+{
+#ifdef CONFIG_MXC_IPU_V1
+ return ipu_csi_enable_mclk(ipu, src, flag, wait);
+#else
+ return ipu_csi_enable_mclk(ipu, csi, flag, wait);
+#endif
+}
+
+int ipu_csi_read_mclk_flag(void);
+
+void ipu_csi_flash_strobe(bool flag);
+
+void ipu_csi_get_window_size(struct ipu_soc *ipu, uint32_t *width, uint32_t *height, uint32_t csi);
+
+void ipu_csi_set_window_size(struct ipu_soc *ipu, uint32_t width, uint32_t height, uint32_t csi);
+
+void ipu_csi_set_window_pos(struct ipu_soc *ipu, uint32_t left, uint32_t top, uint32_t csi);
+
+/* Post Filter functions */
+int32_t ipu_pf_set_pause_row(uint32_t pause_row);
+
+uint32_t bytes_per_pixel(uint32_t fmt);
+
/* IPU device */
struct ipu_pos {
u32 x;