From 2884c12eb455a87e1c66f12be67595ecfbb734d0 Mon Sep 17 00:00:00 2001 From: Jason Chen Date: Wed, 14 Sep 2011 14:41:27 +0800 Subject: 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 --- arch/arm/plat-mxc/include/mach/ipu-v3.h | 731 ----------------------- drivers/mxc/ipu3/ipu_calc_stripes_sizes.c | 1 - drivers/mxc/ipu3/ipu_capture.c | 158 ++++- drivers/mxc/ipu3/ipu_common.c | 641 +++++++++++++------- drivers/mxc/ipu3/ipu_disp.c | 256 ++------ drivers/mxc/ipu3/ipu_param_mem.h | 154 ++--- drivers/mxc/ipu3/ipu_prv.h | 21 +- include/linux/ipu.h | 948 +++++++++++++++++++++++++++++- 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 - -/* 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 #include -#include #include #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 #include #include +#include #include #include +#include #include -#include -#include #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 #include #include -#include #include #include #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 #include -#include +#include #include #include -#include -#include #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 @@ -58,6 +58,25 @@ typedef enum { IPU_ROTATE_90_LEFT = 7, } 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 */ @@ -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; -- cgit v1.2.3