IPUv3 preparations for capture support
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJUD2uxAAoJEFDCiBxwnmDrw8UP/iagFgNbH0z+E5/rkJ3UAuI3 GQGuAiw30QtXg/y9/wSGj8k9p0XqrnKs1XQbEESFMWmfbQdC16JM12Ty/dIbs4K8 qh2kpzqW9VhIrxjjfvx8RoxrBnmFJiCElaGegELzCQ5qG9ue2b8F1bO/NFxEnxsp yRK6mg0Fr77QFpRVfHr+cW82vVHiWP3bJGfu9lAWOQDa6XeZjK++3+aNERcLxbv7 EcD0LLuDMnHMyYxM/HUYt1EhH8C39xvu/kZTSGHcpFiiCGVu6v71C6WcTNmypxeP b/9L8rEDcB0WezQM05nBiVDDtXJCg4GQ9lPcwiY4AmsgajJ3sdC5pzxvuwRZ9qBP yMOIY4wRme3U2giYugSkJ7nyk6/OxMJz8HWqvKy8ttBepZnDinSw3uT2LEO0nga1 USdjWk6+o2fJntQPzpHgE2ZpnHOOZF5MvD+DdAgVcUoVZrT/aRO3TDxBCb3fTalf mkhsjVv9e7rWj4mb9lypLTBDF+yDQLqmV/oe6JumNhfaYmG1PY2SUvGmBbLNlfi1 h+eY1BANW/08s48aruA/pDZ11qTH4uEgShEaR81KmOav3x7qLYuB1r2VLQgAeuPH NVrwTegYHroBqkc30zp6vKkIAERAz0nDub9f5wBGIE/eIrVLkU1qgLk5fORy2RG5 0TrVaWnIclmY3hN/xiDG =qs5t -----END PGP SIGNATURE----- Merge tag 'ipu-3.18' of git://git.pengutronix.de/git/pza/linux into drm-next IPUv3 preparations for capture support * tag 'ipu-3.18' of git://git.pengutronix.de/git/pza/linux: (26 commits) gpu: ipu-v3: Add ipu_dump() gpu: ipu-cpmem: Add ipu_cpmem_dump() gpu: ipu-v3: Add more planar formats support gpu: ipu-cpmem: Add second buffer support to ipu_cpmem_set_image() gpu: ipu-cpmem: Add ipu_cpmem_set_rotation() gpu: ipu-cpmem: Add ipu_cpmem_set_axi_id() gpu: ipu-cpmem: Add ipu_cpmem_set_block_mode() gpu: ipu-v3: Add ipu_idmac_lock_enable() gpu: ipu-v3: Add ipu_idmac_enable_watermark() gpu: ipu-v3: Add ipu_stride_to_bytes() gpu: ipu-v3: Add __ipu_idmac_reset_current_buffer() gpu: ipu-v3: Add ipu_idmac_clear_buffer() gpu: ipu-v3: Add ipu_idmac_buffer_is_ready() gpu: ipu-v3: Move IDMAC channel names to imx-ipu-v3.h gpu: ipu-v3: Add helper function checking if pixfmt is planar gpu: ipu-v3: Add rotation mode conversion utilities gpu: ipu-v3: Add ipu_mbus_code_to_colorspace() gpu: ipu-v3: smfc: Add ipu_smfc_set_watermark() gpu: ipu-v3: smfc: Convert to per-channel gpu: ipu-v3: smfc: Move enable/disable to ipu-smfc.c ...
This commit is contained in:
		
				commit
				
					
						fdcaa1dbb7
					
				
			
		
					 9 changed files with 3082 additions and 682 deletions
				
			
		| 
						 | 
					@ -1,3 +1,4 @@
 | 
				
			||||||
obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
 | 
					obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
imx-ipu-v3-objs := ipu-common.o ipu-dc.o ipu-di.o ipu-dp.o ipu-dmfc.o ipu-smfc.o
 | 
					imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
 | 
				
			||||||
 | 
							ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-smfc.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										764
									
								
								drivers/gpu/ipu-v3/ipu-cpmem.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										764
									
								
								drivers/gpu/ipu-v3/ipu-cpmem.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,764 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 Mentor Graphics Inc.
 | 
				
			||||||
 | 
					 * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The code contained herein is licensed under the GNU General Public
 | 
				
			||||||
 | 
					 * License. You may obtain a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * Version 2 or later at the following locations:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * http://www.opensource.org/licenses/gpl-license.html
 | 
				
			||||||
 | 
					 * http://www.gnu.org/copyleft/gpl.html
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include <linux/types.h>
 | 
				
			||||||
 | 
					#include <linux/bitrev.h>
 | 
				
			||||||
 | 
					#include <linux/io.h>
 | 
				
			||||||
 | 
					#include <drm/drm_fourcc.h>
 | 
				
			||||||
 | 
					#include "ipu-prv.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_cpmem_word {
 | 
				
			||||||
 | 
						u32 data[5];
 | 
				
			||||||
 | 
						u32 res[3];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_ch_param {
 | 
				
			||||||
 | 
						struct ipu_cpmem_word word[2];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_cpmem {
 | 
				
			||||||
 | 
						struct ipu_ch_param __iomem *base;
 | 
				
			||||||
 | 
						u32 module;
 | 
				
			||||||
 | 
						spinlock_t lock;
 | 
				
			||||||
 | 
						int use_count;
 | 
				
			||||||
 | 
						struct ipu_soc *ipu;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IPU_FIELD_UBO		IPU_CPMEM_WORD(0, 46, 22)
 | 
				
			||||||
 | 
					#define IPU_FIELD_VBO		IPU_CPMEM_WORD(0, 68, 22)
 | 
				
			||||||
 | 
					#define IPU_FIELD_IOX		IPU_CPMEM_WORD(0, 90, 4)
 | 
				
			||||||
 | 
					#define IPU_FIELD_RDRW		IPU_CPMEM_WORD(0, 94, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SO		IPU_CPMEM_WORD(0, 113, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SLY		IPU_CPMEM_WORD(1, 102, 14)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SLUV		IPU_CPMEM_WORD(1, 128, 14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IPU_FIELD_XV		IPU_CPMEM_WORD(0, 0, 10)
 | 
				
			||||||
 | 
					#define IPU_FIELD_YV		IPU_CPMEM_WORD(0, 10, 9)
 | 
				
			||||||
 | 
					#define IPU_FIELD_XB		IPU_CPMEM_WORD(0, 19, 13)
 | 
				
			||||||
 | 
					#define IPU_FIELD_YB		IPU_CPMEM_WORD(0, 32, 12)
 | 
				
			||||||
 | 
					#define IPU_FIELD_NSB_B		IPU_CPMEM_WORD(0, 44, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_CF		IPU_CPMEM_WORD(0, 45, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SX		IPU_CPMEM_WORD(0, 46, 12)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SY		IPU_CPMEM_WORD(0, 58, 11)
 | 
				
			||||||
 | 
					#define IPU_FIELD_NS		IPU_CPMEM_WORD(0, 69, 10)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SDX		IPU_CPMEM_WORD(0, 79, 7)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SM		IPU_CPMEM_WORD(0, 86, 10)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SCC		IPU_CPMEM_WORD(0, 96, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SCE		IPU_CPMEM_WORD(0, 97, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SDY		IPU_CPMEM_WORD(0, 98, 7)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SDRX		IPU_CPMEM_WORD(0, 105, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SDRY		IPU_CPMEM_WORD(0, 106, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_BPP		IPU_CPMEM_WORD(0, 107, 3)
 | 
				
			||||||
 | 
					#define IPU_FIELD_DEC_SEL	IPU_CPMEM_WORD(0, 110, 2)
 | 
				
			||||||
 | 
					#define IPU_FIELD_DIM		IPU_CPMEM_WORD(0, 112, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_BNDM		IPU_CPMEM_WORD(0, 114, 3)
 | 
				
			||||||
 | 
					#define IPU_FIELD_BM		IPU_CPMEM_WORD(0, 117, 2)
 | 
				
			||||||
 | 
					#define IPU_FIELD_ROT		IPU_CPMEM_WORD(0, 119, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_ROT_HF_VF	IPU_CPMEM_WORD(0, 119, 3)
 | 
				
			||||||
 | 
					#define IPU_FIELD_HF		IPU_CPMEM_WORD(0, 120, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_VF		IPU_CPMEM_WORD(0, 121, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_THE		IPU_CPMEM_WORD(0, 122, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_CAP		IPU_CPMEM_WORD(0, 123, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_CAE		IPU_CPMEM_WORD(0, 124, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_FW		IPU_CPMEM_WORD(0, 125, 13)
 | 
				
			||||||
 | 
					#define IPU_FIELD_FH		IPU_CPMEM_WORD(0, 138, 12)
 | 
				
			||||||
 | 
					#define IPU_FIELD_EBA0		IPU_CPMEM_WORD(1, 0, 29)
 | 
				
			||||||
 | 
					#define IPU_FIELD_EBA1		IPU_CPMEM_WORD(1, 29, 29)
 | 
				
			||||||
 | 
					#define IPU_FIELD_ILO		IPU_CPMEM_WORD(1, 58, 20)
 | 
				
			||||||
 | 
					#define IPU_FIELD_NPB		IPU_CPMEM_WORD(1, 78, 7)
 | 
				
			||||||
 | 
					#define IPU_FIELD_PFS		IPU_CPMEM_WORD(1, 85, 4)
 | 
				
			||||||
 | 
					#define IPU_FIELD_ALU		IPU_CPMEM_WORD(1, 89, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_ALBM		IPU_CPMEM_WORD(1, 90, 3)
 | 
				
			||||||
 | 
					#define IPU_FIELD_ID		IPU_CPMEM_WORD(1, 93, 2)
 | 
				
			||||||
 | 
					#define IPU_FIELD_TH		IPU_CPMEM_WORD(1, 95, 7)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SL		IPU_CPMEM_WORD(1, 102, 14)
 | 
				
			||||||
 | 
					#define IPU_FIELD_WID0		IPU_CPMEM_WORD(1, 116, 3)
 | 
				
			||||||
 | 
					#define IPU_FIELD_WID1		IPU_CPMEM_WORD(1, 119, 3)
 | 
				
			||||||
 | 
					#define IPU_FIELD_WID2		IPU_CPMEM_WORD(1, 122, 3)
 | 
				
			||||||
 | 
					#define IPU_FIELD_WID3		IPU_CPMEM_WORD(1, 125, 3)
 | 
				
			||||||
 | 
					#define IPU_FIELD_OFS0		IPU_CPMEM_WORD(1, 128, 5)
 | 
				
			||||||
 | 
					#define IPU_FIELD_OFS1		IPU_CPMEM_WORD(1, 133, 5)
 | 
				
			||||||
 | 
					#define IPU_FIELD_OFS2		IPU_CPMEM_WORD(1, 138, 5)
 | 
				
			||||||
 | 
					#define IPU_FIELD_OFS3		IPU_CPMEM_WORD(1, 143, 5)
 | 
				
			||||||
 | 
					#define IPU_FIELD_SXYS		IPU_CPMEM_WORD(1, 148, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_CRE		IPU_CPMEM_WORD(1, 149, 1)
 | 
				
			||||||
 | 
					#define IPU_FIELD_DEC_SEL2	IPU_CPMEM_WORD(1, 150, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct ipu_ch_param __iomem *
 | 
				
			||||||
 | 
					ipu_get_cpmem(struct ipuv3_channel *ch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_cpmem *cpmem = ch->ipu->cpmem_priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cpmem->base + ch->num;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ipu_ch_param_write_field(struct ipuv3_channel *ch, u32 wbs, u32 v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
 | 
				
			||||||
 | 
						u32 bit = (wbs >> 8) % 160;
 | 
				
			||||||
 | 
						u32 size = wbs & 0xff;
 | 
				
			||||||
 | 
						u32 word = (wbs >> 8) / 160;
 | 
				
			||||||
 | 
						u32 i = bit / 32;
 | 
				
			||||||
 | 
						u32 ofs = bit % 32;
 | 
				
			||||||
 | 
						u32 mask = (1 << size) - 1;
 | 
				
			||||||
 | 
						u32 val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pr_debug("%s %d %d %d\n", __func__, word, bit , size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						val = readl(&base->word[word].data[i]);
 | 
				
			||||||
 | 
						val &= ~(mask << ofs);
 | 
				
			||||||
 | 
						val |= v << ofs;
 | 
				
			||||||
 | 
						writel(val, &base->word[word].data[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((bit + size - 1) / 32 > i) {
 | 
				
			||||||
 | 
							val = readl(&base->word[word].data[i + 1]);
 | 
				
			||||||
 | 
							val &= ~(mask >> (ofs ? (32 - ofs) : 0));
 | 
				
			||||||
 | 
							val |= v >> (ofs ? (32 - ofs) : 0);
 | 
				
			||||||
 | 
							writel(val, &base->word[word].data[i + 1]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static u32 ipu_ch_param_read_field(struct ipuv3_channel *ch, u32 wbs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
 | 
				
			||||||
 | 
						u32 bit = (wbs >> 8) % 160;
 | 
				
			||||||
 | 
						u32 size = wbs & 0xff;
 | 
				
			||||||
 | 
						u32 word = (wbs >> 8) / 160;
 | 
				
			||||||
 | 
						u32 i = bit / 32;
 | 
				
			||||||
 | 
						u32 ofs = bit % 32;
 | 
				
			||||||
 | 
						u32 mask = (1 << size) - 1;
 | 
				
			||||||
 | 
						u32 val = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pr_debug("%s %d %d %d\n", __func__, word, bit , size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						val = (readl(&base->word[word].data[i]) >> ofs) & mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((bit + size - 1) / 32 > i) {
 | 
				
			||||||
 | 
							u32 tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							tmp = readl(&base->word[word].data[i + 1]);
 | 
				
			||||||
 | 
							tmp &= mask >> (ofs ? (32 - ofs) : 0);
 | 
				
			||||||
 | 
							val |= tmp << (ofs ? (32 - ofs) : 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * The V4L2 spec defines packed RGB formats in memory byte order, which from
 | 
				
			||||||
 | 
					 * point of view of the IPU corresponds to little-endian words with the first
 | 
				
			||||||
 | 
					 * component in the least significant bits.
 | 
				
			||||||
 | 
					 * The DRM pixel formats and IPU internal representation are ordered the other
 | 
				
			||||||
 | 
					 * way around, with the first named component ordered at the most significant
 | 
				
			||||||
 | 
					 * bits. Further, V4L2 formats are not well defined:
 | 
				
			||||||
 | 
					 *     http://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
 | 
				
			||||||
 | 
					 * We choose the interpretation which matches GStreamer behavior.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (pixelformat) {
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_RGB565:
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Here we choose the 'corrected' interpretation of RGBP, a
 | 
				
			||||||
 | 
							 * little-endian 16-bit word with the red component at the most
 | 
				
			||||||
 | 
							 * significant bits:
 | 
				
			||||||
 | 
							 * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							return DRM_FORMAT_RGB565;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_BGR24:
 | 
				
			||||||
 | 
							/* B G R <=> [24:0] R:G:B */
 | 
				
			||||||
 | 
							return DRM_FORMAT_RGB888;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_RGB24:
 | 
				
			||||||
 | 
							/* R G B <=> [24:0] B:G:R */
 | 
				
			||||||
 | 
							return DRM_FORMAT_BGR888;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_BGR32:
 | 
				
			||||||
 | 
							/* B G R A <=> [32:0] A:B:G:R */
 | 
				
			||||||
 | 
							return DRM_FORMAT_XRGB8888;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_RGB32:
 | 
				
			||||||
 | 
							/* R G B A <=> [32:0] A:B:G:R */
 | 
				
			||||||
 | 
							return DRM_FORMAT_XBGR8888;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_UYVY:
 | 
				
			||||||
 | 
							return DRM_FORMAT_UYVY;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YUYV:
 | 
				
			||||||
 | 
							return DRM_FORMAT_YUYV;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YUV420:
 | 
				
			||||||
 | 
							return DRM_FORMAT_YUV420;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YUV422P:
 | 
				
			||||||
 | 
							return DRM_FORMAT_YUV422;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YVU420:
 | 
				
			||||||
 | 
							return DRM_FORMAT_YVU420;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_NV12:
 | 
				
			||||||
 | 
							return DRM_FORMAT_NV12;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_NV16:
 | 
				
			||||||
 | 
							return DRM_FORMAT_NV16;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EINVAL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_zero(struct ipuv3_channel *ch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
 | 
				
			||||||
 | 
						void __iomem *base = p;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
 | 
				
			||||||
 | 
							writel(0, base + i * sizeof(u32));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_zero);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_FW, xres - 1);
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_FH, yres - 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_stride);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_soc *ipu = ch->ipu;
 | 
				
			||||||
 | 
						u32 val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ipu->ipu_type == IPUV3EX)
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_ID, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(ch->num));
 | 
				
			||||||
 | 
						val |= 1 << (ch->num % 32);
 | 
				
			||||||
 | 
						ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(ch->num));
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (bufnum)
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_EBA1, buf >> 3);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_EBA0, buf >> 3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_ILO, stride / 8);
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_SLY, (stride * 2) - 1);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						id &= 0x3;
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_ID, id);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_burstsize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_BM, 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_block_mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
 | 
				
			||||||
 | 
								    enum ipu_rotate_mode rot)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 temp_rot = bitrev8(rot) >> 5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_ROT_HF_VF, temp_rot);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_rotation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_cpmem_set_format_rgb(struct ipuv3_channel *ch,
 | 
				
			||||||
 | 
								     const struct ipu_rgb *rgb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int bpp = 0, npb = 0, ro, go, bo, to;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
 | 
				
			||||||
 | 
						go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
 | 
				
			||||||
 | 
						bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
 | 
				
			||||||
 | 
						to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_WID0, rgb->red.length - 1);
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_OFS0, ro);
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_WID1, rgb->green.length - 1);
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_OFS1, go);
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_WID2, rgb->blue.length - 1);
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_OFS2, bo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rgb->transp.length) {
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_WID3,
 | 
				
			||||||
 | 
									rgb->transp.length - 1);
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_OFS3, to);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_OFS3,
 | 
				
			||||||
 | 
									rgb->bits_per_pixel);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (rgb->bits_per_pixel) {
 | 
				
			||||||
 | 
						case 32:
 | 
				
			||||||
 | 
							bpp = 0;
 | 
				
			||||||
 | 
							npb = 15;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 24:
 | 
				
			||||||
 | 
							bpp = 1;
 | 
				
			||||||
 | 
							npb = 19;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 16:
 | 
				
			||||||
 | 
							bpp = 3;
 | 
				
			||||||
 | 
							npb = 31;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 8:
 | 
				
			||||||
 | 
							bpp = 5;
 | 
				
			||||||
 | 
							npb = 63;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 7); /* rgb mode */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_cpmem_set_format_passthrough(struct ipuv3_channel *ch, int width)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int bpp = 0, npb = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (width) {
 | 
				
			||||||
 | 
						case 32:
 | 
				
			||||||
 | 
							bpp = 0;
 | 
				
			||||||
 | 
							npb = 15;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 24:
 | 
				
			||||||
 | 
							bpp = 1;
 | 
				
			||||||
 | 
							npb = 19;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 16:
 | 
				
			||||||
 | 
							bpp = 3;
 | 
				
			||||||
 | 
							npb = 31;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 8:
 | 
				
			||||||
 | 
							bpp = 5;
 | 
				
			||||||
 | 
							npb = 63;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
 | 
				
			||||||
 | 
						ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 6); /* raw mode */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (pixel_format) {
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_UYVY:
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);/* pix fmt */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YUYV:
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);/* pix fmt */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
 | 
				
			||||||
 | 
									   u32 pixel_format, int stride,
 | 
				
			||||||
 | 
									   int u_offset, int v_offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (pixel_format) {
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YUV420:
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YUV422P:
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, (stride / 2) - 1);
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YVU420:
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, (stride / 2) - 1);
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_UBO, v_offset / 8);
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_VBO, u_offset / 8);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_NV12:
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_NV16:
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, stride - 1);
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_VBO, u_offset / 8);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch,
 | 
				
			||||||
 | 
								      u32 pixel_format, int stride, int height)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int u_offset, v_offset;
 | 
				
			||||||
 | 
						int uv_stride = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (pixel_format) {
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YUV420:
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YVU420:
 | 
				
			||||||
 | 
							uv_stride = stride / 2;
 | 
				
			||||||
 | 
							u_offset = stride * height;
 | 
				
			||||||
 | 
							v_offset = u_offset + (uv_stride * height / 2);
 | 
				
			||||||
 | 
							ipu_cpmem_set_yuv_planar_full(ch, pixel_format, stride,
 | 
				
			||||||
 | 
										      u_offset, v_offset);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YUV422P:
 | 
				
			||||||
 | 
							uv_stride = stride / 2;
 | 
				
			||||||
 | 
							u_offset = stride * height;
 | 
				
			||||||
 | 
							v_offset = u_offset + (uv_stride * height);
 | 
				
			||||||
 | 
							ipu_cpmem_set_yuv_planar_full(ch, pixel_format, stride,
 | 
				
			||||||
 | 
										      u_offset, v_offset);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_NV12:
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_NV16:
 | 
				
			||||||
 | 
							u_offset = stride * height;
 | 
				
			||||||
 | 
							ipu_cpmem_set_yuv_planar_full(ch, pixel_format, stride,
 | 
				
			||||||
 | 
										      u_offset, 0);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct ipu_rgb def_rgb_32 = {
 | 
				
			||||||
 | 
						.red	= { .offset = 16, .length = 8, },
 | 
				
			||||||
 | 
						.green	= { .offset =  8, .length = 8, },
 | 
				
			||||||
 | 
						.blue	= { .offset =  0, .length = 8, },
 | 
				
			||||||
 | 
						.transp = { .offset = 24, .length = 8, },
 | 
				
			||||||
 | 
						.bits_per_pixel = 32,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct ipu_rgb def_bgr_32 = {
 | 
				
			||||||
 | 
						.red	= { .offset =  0, .length = 8, },
 | 
				
			||||||
 | 
						.green	= { .offset =  8, .length = 8, },
 | 
				
			||||||
 | 
						.blue	= { .offset = 16, .length = 8, },
 | 
				
			||||||
 | 
						.transp = { .offset = 24, .length = 8, },
 | 
				
			||||||
 | 
						.bits_per_pixel = 32,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct ipu_rgb def_rgb_24 = {
 | 
				
			||||||
 | 
						.red	= { .offset = 16, .length = 8, },
 | 
				
			||||||
 | 
						.green	= { .offset =  8, .length = 8, },
 | 
				
			||||||
 | 
						.blue	= { .offset =  0, .length = 8, },
 | 
				
			||||||
 | 
						.transp = { .offset =  0, .length = 0, },
 | 
				
			||||||
 | 
						.bits_per_pixel = 24,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct ipu_rgb def_bgr_24 = {
 | 
				
			||||||
 | 
						.red	= { .offset =  0, .length = 8, },
 | 
				
			||||||
 | 
						.green	= { .offset =  8, .length = 8, },
 | 
				
			||||||
 | 
						.blue	= { .offset = 16, .length = 8, },
 | 
				
			||||||
 | 
						.transp = { .offset =  0, .length = 0, },
 | 
				
			||||||
 | 
						.bits_per_pixel = 24,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct ipu_rgb def_rgb_16 = {
 | 
				
			||||||
 | 
						.red	= { .offset = 11, .length = 5, },
 | 
				
			||||||
 | 
						.green	= { .offset =  5, .length = 6, },
 | 
				
			||||||
 | 
						.blue	= { .offset =  0, .length = 5, },
 | 
				
			||||||
 | 
						.transp = { .offset =  0, .length = 0, },
 | 
				
			||||||
 | 
						.bits_per_pixel = 16,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct ipu_rgb def_bgr_16 = {
 | 
				
			||||||
 | 
						.red	= { .offset =  0, .length = 5, },
 | 
				
			||||||
 | 
						.green	= { .offset =  5, .length = 6, },
 | 
				
			||||||
 | 
						.blue	= { .offset = 11, .length = 5, },
 | 
				
			||||||
 | 
						.transp = { .offset =  0, .length = 0, },
 | 
				
			||||||
 | 
						.bits_per_pixel = 16,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define Y_OFFSET(pix, x, y)	((x) + pix->width * (y))
 | 
				
			||||||
 | 
					#define U_OFFSET(pix, x, y)	((pix->width * pix->height) +		\
 | 
				
			||||||
 | 
									 (pix->width * (y) / 4) + (x) / 2)
 | 
				
			||||||
 | 
					#define V_OFFSET(pix, x, y)	((pix->width * pix->height) +		\
 | 
				
			||||||
 | 
									 (pix->width * pix->height / 4) +	\
 | 
				
			||||||
 | 
									 (pix->width * (y) / 4) + (x) / 2)
 | 
				
			||||||
 | 
					#define U2_OFFSET(pix, x, y)	((pix->width * pix->height) +		\
 | 
				
			||||||
 | 
									 (pix->width * (y) / 2) + (x) / 2)
 | 
				
			||||||
 | 
					#define V2_OFFSET(pix, x, y)	((pix->width * pix->height) +		\
 | 
				
			||||||
 | 
									 (pix->width * pix->height / 2) +	\
 | 
				
			||||||
 | 
									 (pix->width * (y) / 2) + (x) / 2)
 | 
				
			||||||
 | 
					#define UV_OFFSET(pix, x, y)	((pix->width * pix->height) +	\
 | 
				
			||||||
 | 
									 (pix->width * (y) / 2) + (x))
 | 
				
			||||||
 | 
					#define UV2_OFFSET(pix, x, y)	((pix->width * pix->height) +	\
 | 
				
			||||||
 | 
									 (pix->width * y) + (x))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (drm_fourcc) {
 | 
				
			||||||
 | 
						case DRM_FORMAT_YUV420:
 | 
				
			||||||
 | 
						case DRM_FORMAT_YVU420:
 | 
				
			||||||
 | 
							/* pix format */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 2);
 | 
				
			||||||
 | 
							/* burst size */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DRM_FORMAT_YUV422:
 | 
				
			||||||
 | 
						case DRM_FORMAT_YVU422:
 | 
				
			||||||
 | 
							/* pix format */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1);
 | 
				
			||||||
 | 
							/* burst size */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DRM_FORMAT_NV12:
 | 
				
			||||||
 | 
							/* pix format */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
 | 
				
			||||||
 | 
							/* burst size */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DRM_FORMAT_NV16:
 | 
				
			||||||
 | 
							/* pix format */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 3);
 | 
				
			||||||
 | 
							/* burst size */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DRM_FORMAT_UYVY:
 | 
				
			||||||
 | 
							/* bits/pixel */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
 | 
				
			||||||
 | 
							/* pix format */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);
 | 
				
			||||||
 | 
							/* burst size */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DRM_FORMAT_YUYV:
 | 
				
			||||||
 | 
							/* bits/pixel */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
 | 
				
			||||||
 | 
							/* pix format */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);
 | 
				
			||||||
 | 
							/* burst size */
 | 
				
			||||||
 | 
							ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DRM_FORMAT_ABGR8888:
 | 
				
			||||||
 | 
						case DRM_FORMAT_XBGR8888:
 | 
				
			||||||
 | 
							ipu_cpmem_set_format_rgb(ch, &def_bgr_32);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DRM_FORMAT_ARGB8888:
 | 
				
			||||||
 | 
						case DRM_FORMAT_XRGB8888:
 | 
				
			||||||
 | 
							ipu_cpmem_set_format_rgb(ch, &def_rgb_32);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DRM_FORMAT_BGR888:
 | 
				
			||||||
 | 
							ipu_cpmem_set_format_rgb(ch, &def_bgr_24);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DRM_FORMAT_RGB888:
 | 
				
			||||||
 | 
							ipu_cpmem_set_format_rgb(ch, &def_rgb_24);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DRM_FORMAT_RGB565:
 | 
				
			||||||
 | 
							ipu_cpmem_set_format_rgb(ch, &def_rgb_16);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case DRM_FORMAT_BGR565:
 | 
				
			||||||
 | 
							ipu_cpmem_set_format_rgb(ch, &def_bgr_16);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct v4l2_pix_format *pix = &image->pix;
 | 
				
			||||||
 | 
						int offset, u_offset, v_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pr_debug("%s: resolution: %dx%d stride: %d\n",
 | 
				
			||||||
 | 
							 __func__, pix->width, pix->height,
 | 
				
			||||||
 | 
							 pix->bytesperline);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_cpmem_set_resolution(ch, image->rect.width, image->rect.height);
 | 
				
			||||||
 | 
						ipu_cpmem_set_stride(ch, pix->bytesperline);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_cpmem_set_fmt(ch, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (pix->pixelformat) {
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YUV420:
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YVU420:
 | 
				
			||||||
 | 
							offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
 | 
				
			||||||
 | 
							u_offset = U_OFFSET(pix, image->rect.left,
 | 
				
			||||||
 | 
									    image->rect.top) - offset;
 | 
				
			||||||
 | 
							v_offset = V_OFFSET(pix, image->rect.left,
 | 
				
			||||||
 | 
									    image->rect.top) - offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat,
 | 
				
			||||||
 | 
										      pix->bytesperline,
 | 
				
			||||||
 | 
										      u_offset, v_offset);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YUV422P:
 | 
				
			||||||
 | 
							offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
 | 
				
			||||||
 | 
							u_offset = U2_OFFSET(pix, image->rect.left,
 | 
				
			||||||
 | 
									     image->rect.top) - offset;
 | 
				
			||||||
 | 
							v_offset = V2_OFFSET(pix, image->rect.left,
 | 
				
			||||||
 | 
									     image->rect.top) - offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat,
 | 
				
			||||||
 | 
										      pix->bytesperline,
 | 
				
			||||||
 | 
										      u_offset, v_offset);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_NV12:
 | 
				
			||||||
 | 
							offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
 | 
				
			||||||
 | 
							u_offset = UV_OFFSET(pix, image->rect.left,
 | 
				
			||||||
 | 
									     image->rect.top) - offset;
 | 
				
			||||||
 | 
							v_offset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat,
 | 
				
			||||||
 | 
										      pix->bytesperline,
 | 
				
			||||||
 | 
										      u_offset, v_offset);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_NV16:
 | 
				
			||||||
 | 
							offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
 | 
				
			||||||
 | 
							u_offset = UV2_OFFSET(pix, image->rect.left,
 | 
				
			||||||
 | 
									      image->rect.top) - offset;
 | 
				
			||||||
 | 
							v_offset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat,
 | 
				
			||||||
 | 
										      pix->bytesperline,
 | 
				
			||||||
 | 
										      u_offset, v_offset);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_UYVY:
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_YUYV:
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_RGB565:
 | 
				
			||||||
 | 
							offset = image->rect.left * 2 +
 | 
				
			||||||
 | 
								image->rect.top * pix->bytesperline;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_RGB32:
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_BGR32:
 | 
				
			||||||
 | 
							offset = image->rect.left * 4 +
 | 
				
			||||||
 | 
								image->rect.top * pix->bytesperline;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_RGB24:
 | 
				
			||||||
 | 
						case V4L2_PIX_FMT_BGR24:
 | 
				
			||||||
 | 
							offset = image->rect.left * 3 +
 | 
				
			||||||
 | 
								image->rect.top * pix->bytesperline;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset);
 | 
				
			||||||
 | 
						ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_dump(struct ipuv3_channel *ch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
 | 
				
			||||||
 | 
						struct ipu_soc *ipu = ch->ipu;
 | 
				
			||||||
 | 
						int chno = ch->num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", chno,
 | 
				
			||||||
 | 
							readl(&p->word[0].data[0]),
 | 
				
			||||||
 | 
							readl(&p->word[0].data[1]),
 | 
				
			||||||
 | 
							readl(&p->word[0].data[2]),
 | 
				
			||||||
 | 
							readl(&p->word[0].data[3]),
 | 
				
			||||||
 | 
							readl(&p->word[0].data[4]));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", chno,
 | 
				
			||||||
 | 
							readl(&p->word[1].data[0]),
 | 
				
			||||||
 | 
							readl(&p->word[1].data[1]),
 | 
				
			||||||
 | 
							readl(&p->word[1].data[2]),
 | 
				
			||||||
 | 
							readl(&p->word[1].data[3]),
 | 
				
			||||||
 | 
							readl(&p->word[1].data[4]));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "PFS 0x%x, ",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_PFS));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "BPP 0x%x, ",
 | 
				
			||||||
 | 
							ipu_ch_param_read_field(ch, IPU_FIELD_BPP));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "NPB 0x%x\n",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_NPB));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "FW %d, ",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_FW));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "FH %d, ",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_FH));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "EBA0 0x%x\n",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_EBA0) << 3);
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "EBA1 0x%x\n",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_EBA1) << 3);
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "Stride %d\n",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_SL));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "scan_order %d\n",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_SO));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "uv_stride %d\n",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_SLUV));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "u_offset 0x%x\n",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_UBO) << 3);
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "v_offset 0x%x\n",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_VBO) << 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "Width0 %d+1, ",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_WID0));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "Width1 %d+1, ",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_WID1));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "Width2 %d+1, ",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_WID2));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "Width3 %d+1, ",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_WID3));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "Offset0 %d, ",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_OFS0));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "Offset1 %d, ",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_OFS1));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "Offset2 %d, ",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_OFS2));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "Offset3 %d\n",
 | 
				
			||||||
 | 
							 ipu_ch_param_read_field(ch, IPU_FIELD_OFS3));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_cpmem_dump);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_cpmem *cpmem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cpmem = devm_kzalloc(dev, sizeof(*cpmem), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!cpmem)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu->cpmem_priv = cpmem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_init(&cpmem->lock);
 | 
				
			||||||
 | 
						cpmem->base = devm_ioremap(dev, base, SZ_128K);
 | 
				
			||||||
 | 
						if (!cpmem->base)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_dbg(dev, "CPMEM base: 0x%08lx remapped to %p\n",
 | 
				
			||||||
 | 
							base, cpmem->base);
 | 
				
			||||||
 | 
						cpmem->ipu = ipu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_exit(struct ipu_soc *ipu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										741
									
								
								drivers/gpu/ipu-v3/ipu-csi.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										741
									
								
								drivers/gpu/ipu-v3/ipu-csi.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,741 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2012-2014 Mentor Graphics Inc.
 | 
				
			||||||
 | 
					 * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify it
 | 
				
			||||||
 | 
					 * under the terms of the GNU General Public License as published by the
 | 
				
			||||||
 | 
					 * Free Software Foundation; either version 2 of the License, or (at your
 | 
				
			||||||
 | 
					 * option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful, but
 | 
				
			||||||
 | 
					 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 | 
				
			||||||
 | 
					 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 | 
				
			||||||
 | 
					 * for more details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include <linux/export.h>
 | 
				
			||||||
 | 
					#include <linux/module.h>
 | 
				
			||||||
 | 
					#include <linux/types.h>
 | 
				
			||||||
 | 
					#include <linux/errno.h>
 | 
				
			||||||
 | 
					#include <linux/delay.h>
 | 
				
			||||||
 | 
					#include <linux/io.h>
 | 
				
			||||||
 | 
					#include <linux/err.h>
 | 
				
			||||||
 | 
					#include <linux/platform_device.h>
 | 
				
			||||||
 | 
					#include <linux/videodev2.h>
 | 
				
			||||||
 | 
					#include <uapi/linux/v4l2-mediabus.h>
 | 
				
			||||||
 | 
					#include <linux/clk.h>
 | 
				
			||||||
 | 
					#include <linux/clk-provider.h>
 | 
				
			||||||
 | 
					#include <linux/clkdev.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ipu-prv.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_csi {
 | 
				
			||||||
 | 
						void __iomem *base;
 | 
				
			||||||
 | 
						int id;
 | 
				
			||||||
 | 
						u32 module;
 | 
				
			||||||
 | 
						struct clk *clk_ipu;	/* IPU bus clock */
 | 
				
			||||||
 | 
						spinlock_t lock;
 | 
				
			||||||
 | 
						bool inuse;
 | 
				
			||||||
 | 
						struct ipu_soc *ipu;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* CSI Register Offsets */
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF		0x0000
 | 
				
			||||||
 | 
					#define CSI_SENS_FRM_SIZE	0x0004
 | 
				
			||||||
 | 
					#define CSI_ACT_FRM_SIZE	0x0008
 | 
				
			||||||
 | 
					#define CSI_OUT_FRM_CTRL	0x000c
 | 
				
			||||||
 | 
					#define CSI_TST_CTRL		0x0010
 | 
				
			||||||
 | 
					#define CSI_CCIR_CODE_1		0x0014
 | 
				
			||||||
 | 
					#define CSI_CCIR_CODE_2		0x0018
 | 
				
			||||||
 | 
					#define CSI_CCIR_CODE_3		0x001c
 | 
				
			||||||
 | 
					#define CSI_MIPI_DI		0x0020
 | 
				
			||||||
 | 
					#define CSI_SKIP		0x0024
 | 
				
			||||||
 | 
					#define CSI_CPD_CTRL		0x0028
 | 
				
			||||||
 | 
					#define CSI_CPD_RC(n)		(0x002c + ((n)*4))
 | 
				
			||||||
 | 
					#define CSI_CPD_RS(n)		(0x004c + ((n)*4))
 | 
				
			||||||
 | 
					#define CSI_CPD_GRC(n)		(0x005c + ((n)*4))
 | 
				
			||||||
 | 
					#define CSI_CPD_GRS(n)		(0x007c + ((n)*4))
 | 
				
			||||||
 | 
					#define CSI_CPD_GBC(n)		(0x008c + ((n)*4))
 | 
				
			||||||
 | 
					#define CSI_CPD_GBS(n)		(0x00Ac + ((n)*4))
 | 
				
			||||||
 | 
					#define CSI_CPD_BC(n)		(0x00Bc + ((n)*4))
 | 
				
			||||||
 | 
					#define CSI_CPD_BS(n)		(0x00Dc + ((n)*4))
 | 
				
			||||||
 | 
					#define CSI_CPD_OFFSET1		0x00ec
 | 
				
			||||||
 | 
					#define CSI_CPD_OFFSET2		0x00f0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* CSI Register Fields */
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_FMT_SHIFT		8
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_FMT_MASK		0x00000700
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444	0L
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_FMT_YUV422_YUYV	1L
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_FMT_YUV422_UYVY	2L
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_FMT_BAYER		3L
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_FMT_RGB565		4L
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_FMT_RGB555		5L
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_FMT_RGB444		6L
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_FMT_JPEG		7L
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_VSYNC_POL_SHIFT		0
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_HSYNC_POL_SHIFT		1
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_POL_SHIFT		2
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT		3
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_SENS_PRTCL_MASK		0x00000070
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_SENS_PRTCL_SHIFT		4
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_PACK_TIGHT_SHIFT		7
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_WIDTH_SHIFT		11
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_EXT_VSYNC_SHIFT		15
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DIVRATIO_SHIFT		16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DIVRATIO_MASK		0x00ff0000
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_DEST_SHIFT		24
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_DEST_MASK		0x07000000
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_JPEG8_EN_SHIFT		27
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_JPEG_EN_SHIFT		28
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_FORCE_EOF_SHIFT		29
 | 
				
			||||||
 | 
					#define CSI_SENS_CONF_DATA_EN_POL_SHIFT		31
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CSI_DATA_DEST_IC			2
 | 
				
			||||||
 | 
					#define CSI_DATA_DEST_IDMAC			4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CSI_CCIR_ERR_DET_EN			0x01000000
 | 
				
			||||||
 | 
					#define CSI_HORI_DOWNSIZE_EN			0x80000000
 | 
				
			||||||
 | 
					#define CSI_VERT_DOWNSIZE_EN			0x40000000
 | 
				
			||||||
 | 
					#define CSI_TEST_GEN_MODE_EN			0x01000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CSI_HSC_MASK				0x1fff0000
 | 
				
			||||||
 | 
					#define CSI_HSC_SHIFT				16
 | 
				
			||||||
 | 
					#define CSI_VSC_MASK				0x00000fff
 | 
				
			||||||
 | 
					#define CSI_VSC_SHIFT				0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CSI_TEST_GEN_R_MASK			0x000000ff
 | 
				
			||||||
 | 
					#define CSI_TEST_GEN_R_SHIFT			0
 | 
				
			||||||
 | 
					#define CSI_TEST_GEN_G_MASK			0x0000ff00
 | 
				
			||||||
 | 
					#define CSI_TEST_GEN_G_SHIFT			8
 | 
				
			||||||
 | 
					#define CSI_TEST_GEN_B_MASK			0x00ff0000
 | 
				
			||||||
 | 
					#define CSI_TEST_GEN_B_SHIFT			16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CSI_MAX_RATIO_SKIP_SMFC_MASK		0x00000007
 | 
				
			||||||
 | 
					#define CSI_MAX_RATIO_SKIP_SMFC_SHIFT		0
 | 
				
			||||||
 | 
					#define CSI_SKIP_SMFC_MASK			0x000000f8
 | 
				
			||||||
 | 
					#define CSI_SKIP_SMFC_SHIFT			3
 | 
				
			||||||
 | 
					#define CSI_ID_2_SKIP_MASK			0x00000300
 | 
				
			||||||
 | 
					#define CSI_ID_2_SKIP_SHIFT			8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CSI_COLOR_FIRST_ROW_MASK		0x00000002
 | 
				
			||||||
 | 
					#define CSI_COLOR_FIRST_COMP_MASK		0x00000001
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* MIPI CSI-2 data types */
 | 
				
			||||||
 | 
					#define MIPI_DT_YUV420		0x18 /* YYY.../UYVY.... */
 | 
				
			||||||
 | 
					#define MIPI_DT_YUV420_LEGACY	0x1a /* UYY.../VYY...   */
 | 
				
			||||||
 | 
					#define MIPI_DT_YUV422		0x1e /* UYVY...         */
 | 
				
			||||||
 | 
					#define MIPI_DT_RGB444		0x20
 | 
				
			||||||
 | 
					#define MIPI_DT_RGB555		0x21
 | 
				
			||||||
 | 
					#define MIPI_DT_RGB565		0x22
 | 
				
			||||||
 | 
					#define MIPI_DT_RGB666		0x23
 | 
				
			||||||
 | 
					#define MIPI_DT_RGB888		0x24
 | 
				
			||||||
 | 
					#define MIPI_DT_RAW6		0x28
 | 
				
			||||||
 | 
					#define MIPI_DT_RAW7		0x29
 | 
				
			||||||
 | 
					#define MIPI_DT_RAW8		0x2a
 | 
				
			||||||
 | 
					#define MIPI_DT_RAW10		0x2b
 | 
				
			||||||
 | 
					#define MIPI_DT_RAW12		0x2c
 | 
				
			||||||
 | 
					#define MIPI_DT_RAW14		0x2d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Bitfield of CSI bus signal polarities and modes.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct ipu_csi_bus_config {
 | 
				
			||||||
 | 
						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 mipi_dt;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Enumeration of CSI data bus widths.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum ipu_csi_data_width {
 | 
				
			||||||
 | 
						IPU_CSI_DATA_WIDTH_4   = 0,
 | 
				
			||||||
 | 
						IPU_CSI_DATA_WIDTH_8   = 1,
 | 
				
			||||||
 | 
						IPU_CSI_DATA_WIDTH_10  = 3,
 | 
				
			||||||
 | 
						IPU_CSI_DATA_WIDTH_12  = 5,
 | 
				
			||||||
 | 
						IPU_CSI_DATA_WIDTH_16  = 9,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Enumeration of CSI clock modes.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum ipu_csi_clk_mode {
 | 
				
			||||||
 | 
						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,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline u32 ipu_csi_read(struct ipu_csi *csi, unsigned offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return readl(csi->base + offset);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void ipu_csi_write(struct ipu_csi *csi, u32 value,
 | 
				
			||||||
 | 
									 unsigned offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						writel(value, csi->base + offset);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Set mclk division ratio for generating test mode mclk. Only used
 | 
				
			||||||
 | 
					 * for test generator.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk,
 | 
				
			||||||
 | 
										u32 ipu_clk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 temp;
 | 
				
			||||||
 | 
						u32 div_ratio;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						div_ratio = (ipu_clk / pixel_clk) - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (div_ratio > 0xFF || div_ratio < 0) {
 | 
				
			||||||
 | 
							dev_err(csi->ipu->dev,
 | 
				
			||||||
 | 
								"value of pixel_clk extends normal range\n");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						temp = ipu_csi_read(csi, CSI_SENS_CONF);
 | 
				
			||||||
 | 
						temp &= ~CSI_SENS_CONF_DIVRATIO_MASK;
 | 
				
			||||||
 | 
						ipu_csi_write(csi, temp | (div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT),
 | 
				
			||||||
 | 
								  CSI_SENS_CONF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Find the CSI data format and data width for the given V4L2 media
 | 
				
			||||||
 | 
					 * bus pixel format code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (mbus_code) {
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_BGR565_2X8_BE:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_BGR565_2X8_LE:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_RGB565_2X8_BE:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_RGB565_2X8_LE:
 | 
				
			||||||
 | 
							cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
 | 
				
			||||||
 | 
							cfg->mipi_dt = MIPI_DT_RGB565;
 | 
				
			||||||
 | 
							cfg->data_width = IPU_CSI_DATA_WIDTH_8;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE:
 | 
				
			||||||
 | 
							cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB444;
 | 
				
			||||||
 | 
							cfg->mipi_dt = MIPI_DT_RGB444;
 | 
				
			||||||
 | 
							cfg->data_width = IPU_CSI_DATA_WIDTH_8;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
 | 
				
			||||||
 | 
							cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555;
 | 
				
			||||||
 | 
							cfg->mipi_dt = MIPI_DT_RGB555;
 | 
				
			||||||
 | 
							cfg->data_width = IPU_CSI_DATA_WIDTH_8;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_UYVY8_2X8:
 | 
				
			||||||
 | 
							cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
 | 
				
			||||||
 | 
							cfg->mipi_dt = MIPI_DT_YUV422;
 | 
				
			||||||
 | 
							cfg->data_width = IPU_CSI_DATA_WIDTH_8;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_YUYV8_2X8:
 | 
				
			||||||
 | 
							cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
 | 
				
			||||||
 | 
							cfg->mipi_dt = MIPI_DT_YUV422;
 | 
				
			||||||
 | 
							cfg->data_width = IPU_CSI_DATA_WIDTH_8;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_UYVY8_1X16:
 | 
				
			||||||
 | 
							cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
 | 
				
			||||||
 | 
							cfg->mipi_dt = MIPI_DT_YUV422;
 | 
				
			||||||
 | 
							cfg->data_width = IPU_CSI_DATA_WIDTH_16;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_YUYV8_1X16:
 | 
				
			||||||
 | 
							cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
 | 
				
			||||||
 | 
							cfg->mipi_dt = MIPI_DT_YUV422;
 | 
				
			||||||
 | 
							cfg->data_width = IPU_CSI_DATA_WIDTH_16;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SBGGR8_1X8:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SGBRG8_1X8:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SGRBG8_1X8:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SRGGB8_1X8:
 | 
				
			||||||
 | 
							cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
 | 
				
			||||||
 | 
							cfg->mipi_dt = MIPI_DT_RAW8;
 | 
				
			||||||
 | 
							cfg->data_width = IPU_CSI_DATA_WIDTH_8;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE:
 | 
				
			||||||
 | 
							cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
 | 
				
			||||||
 | 
							cfg->mipi_dt = MIPI_DT_RAW10;
 | 
				
			||||||
 | 
							cfg->data_width = IPU_CSI_DATA_WIDTH_8;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SBGGR10_1X10:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SGBRG10_1X10:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SGRBG10_1X10:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SRGGB10_1X10:
 | 
				
			||||||
 | 
							cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
 | 
				
			||||||
 | 
							cfg->mipi_dt = MIPI_DT_RAW10;
 | 
				
			||||||
 | 
							cfg->data_width = IPU_CSI_DATA_WIDTH_10;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SBGGR12_1X12:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SGBRG12_1X12:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SGRBG12_1X12:
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_SRGGB12_1X12:
 | 
				
			||||||
 | 
							cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
 | 
				
			||||||
 | 
							cfg->mipi_dt = MIPI_DT_RAW12;
 | 
				
			||||||
 | 
							cfg->data_width = IPU_CSI_DATA_WIDTH_12;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_FMT_JPEG_1X8:
 | 
				
			||||||
 | 
							/* TODO */
 | 
				
			||||||
 | 
							cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_JPEG;
 | 
				
			||||||
 | 
							cfg->mipi_dt = MIPI_DT_RAW8;
 | 
				
			||||||
 | 
							cfg->data_width = IPU_CSI_DATA_WIDTH_8;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Fill a CSI bus config struct from mbus_config and mbus_framefmt.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
 | 
				
			||||||
 | 
									 struct v4l2_mbus_config *mbus_cfg,
 | 
				
			||||||
 | 
									 struct v4l2_mbus_framefmt *mbus_fmt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						memset(csicfg, 0, sizeof(*csicfg));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mbus_code_to_bus_cfg(csicfg, mbus_fmt->code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (mbus_cfg->type) {
 | 
				
			||||||
 | 
						case V4L2_MBUS_PARALLEL:
 | 
				
			||||||
 | 
							csicfg->ext_vsync = 1;
 | 
				
			||||||
 | 
							csicfg->vsync_pol = (mbus_cfg->flags &
 | 
				
			||||||
 | 
									     V4L2_MBUS_VSYNC_ACTIVE_LOW) ? 1 : 0;
 | 
				
			||||||
 | 
							csicfg->hsync_pol = (mbus_cfg->flags &
 | 
				
			||||||
 | 
									     V4L2_MBUS_HSYNC_ACTIVE_LOW) ? 1 : 0;
 | 
				
			||||||
 | 
							csicfg->pixclk_pol = (mbus_cfg->flags &
 | 
				
			||||||
 | 
									      V4L2_MBUS_PCLK_SAMPLE_FALLING) ? 1 : 0;
 | 
				
			||||||
 | 
							csicfg->clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_BT656:
 | 
				
			||||||
 | 
							csicfg->ext_vsync = 0;
 | 
				
			||||||
 | 
							if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field))
 | 
				
			||||||
 | 
								csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case V4L2_MBUS_CSI2:
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * MIPI CSI-2 requires non gated clock mode, all other
 | 
				
			||||||
 | 
							 * parameters are not applicable for MIPI CSI-2 bus.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							csicfg->clk_mode = IPU_CSI_CLK_MODE_NONGATED_CLK;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							/* will never get here, keep compiler quiet */
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_csi_init_interface(struct ipu_csi *csi,
 | 
				
			||||||
 | 
								   struct v4l2_mbus_config *mbus_cfg,
 | 
				
			||||||
 | 
								   struct v4l2_mbus_framefmt *mbus_fmt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_csi_bus_config cfg;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 data = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fill_csi_bus_cfg(&cfg, mbus_cfg, mbus_fmt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Set the CSI_SENS_CONF register remaining fields */
 | 
				
			||||||
 | 
						data |= cfg.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
 | 
				
			||||||
 | 
							cfg.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT |
 | 
				
			||||||
 | 
							cfg.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
 | 
				
			||||||
 | 
							cfg.vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
 | 
				
			||||||
 | 
							cfg.hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
 | 
				
			||||||
 | 
							cfg.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
 | 
				
			||||||
 | 
							cfg.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
 | 
				
			||||||
 | 
							cfg.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
 | 
				
			||||||
 | 
							cfg.pack_tight << CSI_SENS_CONF_PACK_TIGHT_SHIFT |
 | 
				
			||||||
 | 
							cfg.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
 | 
				
			||||||
 | 
							cfg.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_csi_write(csi, data, CSI_SENS_CONF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Setup sensor frame size */
 | 
				
			||||||
 | 
						ipu_csi_write(csi,
 | 
				
			||||||
 | 
							      (mbus_fmt->width - 1) | ((mbus_fmt->height - 1) << 16),
 | 
				
			||||||
 | 
							      CSI_SENS_FRM_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Set CCIR registers */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (cfg.clk_mode) {
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
 | 
				
			||||||
 | 
							ipu_csi_write(csi, 0x40030, CSI_CCIR_CODE_1);
 | 
				
			||||||
 | 
							ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
 | 
				
			||||||
 | 
							if (mbus_fmt->width == 720 && mbus_fmt->height == 576) {
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * PAL case
 | 
				
			||||||
 | 
								 *
 | 
				
			||||||
 | 
								 * Field0BlankEnd = 0x6, Field0BlankStart = 0x2,
 | 
				
			||||||
 | 
								 * Field0ActiveEnd = 0x4, Field0ActiveStart = 0
 | 
				
			||||||
 | 
								 * Field1BlankEnd = 0x7, Field1BlankStart = 0x3,
 | 
				
			||||||
 | 
								 * Field1ActiveEnd = 0x5, Field1ActiveStart = 0x1
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN,
 | 
				
			||||||
 | 
										  CSI_CCIR_CODE_1);
 | 
				
			||||||
 | 
								ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2);
 | 
				
			||||||
 | 
								ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							} else if (mbus_fmt->width == 720 && mbus_fmt->height == 480) {
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * NTSC case
 | 
				
			||||||
 | 
								 *
 | 
				
			||||||
 | 
								 * Field0BlankEnd = 0x7, Field0BlankStart = 0x3,
 | 
				
			||||||
 | 
								 * Field0ActiveEnd = 0x5, Field0ActiveStart = 0x1
 | 
				
			||||||
 | 
								 * Field1BlankEnd = 0x6, Field1BlankStart = 0x2,
 | 
				
			||||||
 | 
								 * Field1ActiveEnd = 0x4, Field1ActiveStart = 0
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN,
 | 
				
			||||||
 | 
										  CSI_CCIR_CODE_1);
 | 
				
			||||||
 | 
								ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2);
 | 
				
			||||||
 | 
								ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								dev_err(csi->ipu->dev,
 | 
				
			||||||
 | 
									"Unsupported CCIR656 interlaced video mode\n");
 | 
				
			||||||
 | 
								spin_unlock_irqrestore(&csi->lock, flags);
 | 
				
			||||||
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
 | 
				
			||||||
 | 
							ipu_csi_write(csi, 0x40030 | CSI_CCIR_ERR_DET_EN,
 | 
				
			||||||
 | 
									   CSI_CCIR_CODE_1);
 | 
				
			||||||
 | 
							ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_GATED_CLK:
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_NONGATED_CLK:
 | 
				
			||||||
 | 
							ipu_csi_write(csi, 0, CSI_CCIR_CODE_1);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_dbg(csi->ipu->dev, "CSI_SENS_CONF = 0x%08X\n",
 | 
				
			||||||
 | 
							ipu_csi_read(csi, CSI_SENS_CONF));
 | 
				
			||||||
 | 
						dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
 | 
				
			||||||
 | 
							ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_init_interface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ipu_csi_is_interlaced(struct ipu_csi *csi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 sensor_protocol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&csi->lock, flags);
 | 
				
			||||||
 | 
						sensor_protocol =
 | 
				
			||||||
 | 
							(ipu_csi_read(csi, CSI_SENS_CONF) &
 | 
				
			||||||
 | 
							 CSI_SENS_CONF_SENS_PRTCL_MASK) >>
 | 
				
			||||||
 | 
							CSI_SENS_CONF_SENS_PRTCL_SHIFT;
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (sensor_protocol) {
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_GATED_CLK:
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_NONGATED_CLK:
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
 | 
				
			||||||
 | 
						case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							dev_err(csi->ipu->dev,
 | 
				
			||||||
 | 
								"CSI %d sensor protocol unsupported\n", csi->id);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_is_interlaced);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg = ipu_csi_read(csi, CSI_ACT_FRM_SIZE);
 | 
				
			||||||
 | 
						w->width = (reg & 0xFFFF) + 1;
 | 
				
			||||||
 | 
						w->height = (reg >> 16 & 0xFFFF) + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
 | 
				
			||||||
 | 
						w->left = (reg & CSI_HSC_MASK) >> CSI_HSC_SHIFT;
 | 
				
			||||||
 | 
						w->top = (reg & CSI_VSC_MASK) >> CSI_VSC_SHIFT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&csi->lock, flags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_get_window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_csi_write(csi, (w->width - 1) | ((w->height - 1) << 16),
 | 
				
			||||||
 | 
								  CSI_ACT_FRM_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
 | 
				
			||||||
 | 
						reg &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
 | 
				
			||||||
 | 
						reg |= ((w->top << CSI_VSC_SHIFT) | (w->left << CSI_HSC_SHIFT));
 | 
				
			||||||
 | 
						ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&csi->lock, flags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_set_window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
 | 
				
			||||||
 | 
									u32 r_value, u32 g_value, u32 b_value,
 | 
				
			||||||
 | 
									u32 pix_clk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 ipu_clk = clk_get_rate(csi->clk_ipu);
 | 
				
			||||||
 | 
						u32 temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						temp = ipu_csi_read(csi, CSI_TST_CTRL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (active == false) {
 | 
				
			||||||
 | 
							temp &= ~CSI_TEST_GEN_MODE_EN;
 | 
				
			||||||
 | 
							ipu_csi_write(csi, temp, CSI_TST_CTRL);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* Set sensb_mclk div_ratio */
 | 
				
			||||||
 | 
							ipu_csi_set_testgen_mclk(csi, pix_clk, ipu_clk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							temp &= ~(CSI_TEST_GEN_R_MASK | CSI_TEST_GEN_G_MASK |
 | 
				
			||||||
 | 
								  CSI_TEST_GEN_B_MASK);
 | 
				
			||||||
 | 
							temp |= CSI_TEST_GEN_MODE_EN;
 | 
				
			||||||
 | 
							temp |= (r_value << CSI_TEST_GEN_R_SHIFT) |
 | 
				
			||||||
 | 
								(g_value << CSI_TEST_GEN_G_SHIFT) |
 | 
				
			||||||
 | 
								(b_value << CSI_TEST_GEN_B_SHIFT);
 | 
				
			||||||
 | 
							ipu_csi_write(csi, temp, CSI_TST_CTRL);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&csi->lock, flags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_set_test_generator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc,
 | 
				
			||||||
 | 
								      struct v4l2_mbus_framefmt *mbus_fmt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_csi_bus_config cfg;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (vc > 3)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mbus_code_to_bus_cfg(&cfg, mbus_fmt->code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						temp = ipu_csi_read(csi, CSI_MIPI_DI);
 | 
				
			||||||
 | 
						temp &= ~(0xff << (vc * 8));
 | 
				
			||||||
 | 
						temp |= (cfg.mipi_dt << (vc * 8));
 | 
				
			||||||
 | 
						ipu_csi_write(csi, temp, CSI_MIPI_DI);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_set_mipi_datatype);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_csi_set_skip_smfc(struct ipu_csi *csi, u32 skip,
 | 
				
			||||||
 | 
								  u32 max_ratio, u32 id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (max_ratio > 5 || id > 3)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						temp = ipu_csi_read(csi, CSI_SKIP);
 | 
				
			||||||
 | 
						temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
 | 
				
			||||||
 | 
							  CSI_SKIP_SMFC_MASK);
 | 
				
			||||||
 | 
						temp |= (max_ratio << CSI_MAX_RATIO_SKIP_SMFC_SHIFT) |
 | 
				
			||||||
 | 
							(id << CSI_ID_2_SKIP_SHIFT) |
 | 
				
			||||||
 | 
							(skip << CSI_SKIP_SMFC_SHIFT);
 | 
				
			||||||
 | 
						ipu_csi_write(csi, temp, CSI_SKIP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_set_skip_smfc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_csi_set_dest(struct ipu_csi *csi, enum ipu_csi_dest csi_dest)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 csi_sens_conf, dest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (csi_dest == IPU_CSI_DEST_IDMAC)
 | 
				
			||||||
 | 
							dest = CSI_DATA_DEST_IDMAC;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							dest = CSI_DATA_DEST_IC; /* IC or VDIC */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						csi_sens_conf = ipu_csi_read(csi, CSI_SENS_CONF);
 | 
				
			||||||
 | 
						csi_sens_conf &= ~CSI_SENS_CONF_DATA_DEST_MASK;
 | 
				
			||||||
 | 
						csi_sens_conf |= (dest << CSI_SENS_CONF_DATA_DEST_SHIFT);
 | 
				
			||||||
 | 
						ipu_csi_write(csi, csi_sens_conf, CSI_SENS_CONF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_set_dest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_csi_enable(struct ipu_csi *csi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ipu_module_enable(csi->ipu, csi->module);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_enable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_csi_disable(struct ipu_csi *csi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ipu_module_disable(csi->ipu, csi->module);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_disable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_csi *ipu_csi_get(struct ipu_soc *ipu, int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						struct ipu_csi *csi, *ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (id > 1)
 | 
				
			||||||
 | 
							return ERR_PTR(-EINVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						csi = ipu->csi_priv[id];
 | 
				
			||||||
 | 
						ret = csi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&csi->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (csi->inuse) {
 | 
				
			||||||
 | 
							ret = ERR_PTR(-EBUSY);
 | 
				
			||||||
 | 
							goto unlock;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						csi->inuse = true;
 | 
				
			||||||
 | 
					unlock:
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&csi->lock, flags);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_get);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_csi_put(struct ipu_csi *csi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&csi->lock, flags);
 | 
				
			||||||
 | 
						csi->inuse = false;
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&csi->lock, flags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_put);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
 | 
				
			||||||
 | 
							 unsigned long base, u32 module, struct clk *clk_ipu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_csi *csi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (id > 1)
 | 
				
			||||||
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						csi = devm_kzalloc(dev, sizeof(*csi), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!csi)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu->csi_priv[id] = csi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_init(&csi->lock);
 | 
				
			||||||
 | 
						csi->module = module;
 | 
				
			||||||
 | 
						csi->id = id;
 | 
				
			||||||
 | 
						csi->clk_ipu = clk_ipu;
 | 
				
			||||||
 | 
						csi->base = devm_ioremap(dev, base, PAGE_SIZE);
 | 
				
			||||||
 | 
						if (!csi->base)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_dbg(dev, "CSI%d base: 0x%08lx remapped to %p\n",
 | 
				
			||||||
 | 
							id, base, csi->base);
 | 
				
			||||||
 | 
						csi->ipu = ipu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_csi_exit(struct ipu_soc *ipu, int id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_csi_dump(struct ipu_csi *csi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						dev_dbg(csi->ipu->dev, "CSI_SENS_CONF:     %08x\n",
 | 
				
			||||||
 | 
							ipu_csi_read(csi, CSI_SENS_CONF));
 | 
				
			||||||
 | 
						dev_dbg(csi->ipu->dev, "CSI_SENS_FRM_SIZE: %08x\n",
 | 
				
			||||||
 | 
							ipu_csi_read(csi, CSI_SENS_FRM_SIZE));
 | 
				
			||||||
 | 
						dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE:  %08x\n",
 | 
				
			||||||
 | 
							ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
 | 
				
			||||||
 | 
						dev_dbg(csi->ipu->dev, "CSI_OUT_FRM_CTRL:  %08x\n",
 | 
				
			||||||
 | 
							ipu_csi_read(csi, CSI_OUT_FRM_CTRL));
 | 
				
			||||||
 | 
						dev_dbg(csi->ipu->dev, "CSI_TST_CTRL:      %08x\n",
 | 
				
			||||||
 | 
							ipu_csi_read(csi, CSI_TST_CTRL));
 | 
				
			||||||
 | 
						dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_1:   %08x\n",
 | 
				
			||||||
 | 
							ipu_csi_read(csi, CSI_CCIR_CODE_1));
 | 
				
			||||||
 | 
						dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_2:   %08x\n",
 | 
				
			||||||
 | 
							ipu_csi_read(csi, CSI_CCIR_CODE_2));
 | 
				
			||||||
 | 
						dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_3:   %08x\n",
 | 
				
			||||||
 | 
							ipu_csi_read(csi, CSI_CCIR_CODE_3));
 | 
				
			||||||
 | 
						dev_dbg(csi->ipu->dev, "CSI_MIPI_DI:       %08x\n",
 | 
				
			||||||
 | 
							ipu_csi_read(csi, CSI_MIPI_DI));
 | 
				
			||||||
 | 
						dev_dbg(csi->ipu->dev, "CSI_SKIP:          %08x\n",
 | 
				
			||||||
 | 
							ipu_csi_read(csi, CSI_SKIP));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_csi_dump);
 | 
				
			||||||
							
								
								
									
										778
									
								
								drivers/gpu/ipu-v3/ipu-ic.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										778
									
								
								drivers/gpu/ipu-v3/ipu-ic.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,778 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2012-2014 Mentor Graphics Inc.
 | 
				
			||||||
 | 
					 * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The code contained herein is licensed under the GNU General Public
 | 
				
			||||||
 | 
					 * License. You may obtain a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * Version 2 or later at the following locations:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * http://www.opensource.org/licenses/gpl-license.html
 | 
				
			||||||
 | 
					 * http://www.gnu.org/copyleft/gpl.html
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/types.h>
 | 
				
			||||||
 | 
					#include <linux/init.h>
 | 
				
			||||||
 | 
					#include <linux/errno.h>
 | 
				
			||||||
 | 
					#include <linux/spinlock.h>
 | 
				
			||||||
 | 
					#include <linux/bitrev.h>
 | 
				
			||||||
 | 
					#include <linux/io.h>
 | 
				
			||||||
 | 
					#include <linux/err.h>
 | 
				
			||||||
 | 
					#include "ipu-prv.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* IC Register Offsets */
 | 
				
			||||||
 | 
					#define IC_CONF                 0x0000
 | 
				
			||||||
 | 
					#define IC_PRP_ENC_RSC          0x0004
 | 
				
			||||||
 | 
					#define IC_PRP_VF_RSC           0x0008
 | 
				
			||||||
 | 
					#define IC_PP_RSC               0x000C
 | 
				
			||||||
 | 
					#define IC_CMBP_1               0x0010
 | 
				
			||||||
 | 
					#define IC_CMBP_2               0x0014
 | 
				
			||||||
 | 
					#define IC_IDMAC_1              0x0018
 | 
				
			||||||
 | 
					#define IC_IDMAC_2              0x001C
 | 
				
			||||||
 | 
					#define IC_IDMAC_3              0x0020
 | 
				
			||||||
 | 
					#define IC_IDMAC_4              0x0024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* IC Register Fields */
 | 
				
			||||||
 | 
					#define IC_CONF_PRPENC_EN       (1 << 0)
 | 
				
			||||||
 | 
					#define IC_CONF_PRPENC_CSC1     (1 << 1)
 | 
				
			||||||
 | 
					#define IC_CONF_PRPENC_ROT_EN   (1 << 2)
 | 
				
			||||||
 | 
					#define IC_CONF_PRPVF_EN        (1 << 8)
 | 
				
			||||||
 | 
					#define IC_CONF_PRPVF_CSC1      (1 << 9)
 | 
				
			||||||
 | 
					#define IC_CONF_PRPVF_CSC2      (1 << 10)
 | 
				
			||||||
 | 
					#define IC_CONF_PRPVF_CMB       (1 << 11)
 | 
				
			||||||
 | 
					#define IC_CONF_PRPVF_ROT_EN    (1 << 12)
 | 
				
			||||||
 | 
					#define IC_CONF_PP_EN           (1 << 16)
 | 
				
			||||||
 | 
					#define IC_CONF_PP_CSC1         (1 << 17)
 | 
				
			||||||
 | 
					#define IC_CONF_PP_CSC2         (1 << 18)
 | 
				
			||||||
 | 
					#define IC_CONF_PP_CMB          (1 << 19)
 | 
				
			||||||
 | 
					#define IC_CONF_PP_ROT_EN       (1 << 20)
 | 
				
			||||||
 | 
					#define IC_CONF_IC_GLB_LOC_A    (1 << 28)
 | 
				
			||||||
 | 
					#define IC_CONF_KEY_COLOR_EN    (1 << 29)
 | 
				
			||||||
 | 
					#define IC_CONF_RWS_EN          (1 << 30)
 | 
				
			||||||
 | 
					#define IC_CONF_CSI_MEM_WR_EN   (1 << 31)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_CB0_BURST_16         (1 << 0)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_CB1_BURST_16         (1 << 1)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_CB2_BURST_16         (1 << 2)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_CB3_BURST_16         (1 << 3)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_CB4_BURST_16         (1 << 4)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_CB5_BURST_16         (1 << 5)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_CB6_BURST_16         (1 << 6)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_CB7_BURST_16         (1 << 7)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_PRPENC_ROT_MASK      (0x7 << 11)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_PRPENC_ROT_OFFSET    11
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_PRPVF_ROT_MASK       (0x7 << 14)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_PRPVF_ROT_OFFSET     14
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_PP_ROT_MASK          (0x7 << 17)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_PP_ROT_OFFSET        17
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_PP_FLIP_RS           (1 << 22)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_PRPVF_FLIP_RS        (1 << 21)
 | 
				
			||||||
 | 
					#define IC_IDMAC_1_PRPENC_FLIP_RS       (1 << 20)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IC_IDMAC_2_PRPENC_HEIGHT_MASK   (0x3ff << 0)
 | 
				
			||||||
 | 
					#define IC_IDMAC_2_PRPENC_HEIGHT_OFFSET 0
 | 
				
			||||||
 | 
					#define IC_IDMAC_2_PRPVF_HEIGHT_MASK    (0x3ff << 10)
 | 
				
			||||||
 | 
					#define IC_IDMAC_2_PRPVF_HEIGHT_OFFSET  10
 | 
				
			||||||
 | 
					#define IC_IDMAC_2_PP_HEIGHT_MASK       (0x3ff << 20)
 | 
				
			||||||
 | 
					#define IC_IDMAC_2_PP_HEIGHT_OFFSET     20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IC_IDMAC_3_PRPENC_WIDTH_MASK    (0x3ff << 0)
 | 
				
			||||||
 | 
					#define IC_IDMAC_3_PRPENC_WIDTH_OFFSET  0
 | 
				
			||||||
 | 
					#define IC_IDMAC_3_PRPVF_WIDTH_MASK     (0x3ff << 10)
 | 
				
			||||||
 | 
					#define IC_IDMAC_3_PRPVF_WIDTH_OFFSET   10
 | 
				
			||||||
 | 
					#define IC_IDMAC_3_PP_WIDTH_MASK        (0x3ff << 20)
 | 
				
			||||||
 | 
					#define IC_IDMAC_3_PP_WIDTH_OFFSET      20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ic_task_regoffs {
 | 
				
			||||||
 | 
						u32 rsc;
 | 
				
			||||||
 | 
						u32 tpmem_csc[2];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ic_task_bitfields {
 | 
				
			||||||
 | 
						u32 ic_conf_en;
 | 
				
			||||||
 | 
						u32 ic_conf_rot_en;
 | 
				
			||||||
 | 
						u32 ic_conf_cmb_en;
 | 
				
			||||||
 | 
						u32 ic_conf_csc1_en;
 | 
				
			||||||
 | 
						u32 ic_conf_csc2_en;
 | 
				
			||||||
 | 
						u32 ic_cmb_galpha_bit;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct ic_task_regoffs ic_task_reg[IC_NUM_TASKS] = {
 | 
				
			||||||
 | 
						[IC_TASK_ENCODER] = {
 | 
				
			||||||
 | 
							.rsc = IC_PRP_ENC_RSC,
 | 
				
			||||||
 | 
							.tpmem_csc = {0x2008, 0},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[IC_TASK_VIEWFINDER] = {
 | 
				
			||||||
 | 
							.rsc = IC_PRP_VF_RSC,
 | 
				
			||||||
 | 
							.tpmem_csc = {0x4028, 0x4040},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[IC_TASK_POST_PROCESSOR] = {
 | 
				
			||||||
 | 
							.rsc = IC_PP_RSC,
 | 
				
			||||||
 | 
							.tpmem_csc = {0x6060, 0x6078},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct ic_task_bitfields ic_task_bit[IC_NUM_TASKS] = {
 | 
				
			||||||
 | 
						[IC_TASK_ENCODER] = {
 | 
				
			||||||
 | 
							.ic_conf_en = IC_CONF_PRPENC_EN,
 | 
				
			||||||
 | 
							.ic_conf_rot_en = IC_CONF_PRPENC_ROT_EN,
 | 
				
			||||||
 | 
							.ic_conf_cmb_en = 0,    /* NA */
 | 
				
			||||||
 | 
							.ic_conf_csc1_en = IC_CONF_PRPENC_CSC1,
 | 
				
			||||||
 | 
							.ic_conf_csc2_en = 0,   /* NA */
 | 
				
			||||||
 | 
							.ic_cmb_galpha_bit = 0, /* NA */
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[IC_TASK_VIEWFINDER] = {
 | 
				
			||||||
 | 
							.ic_conf_en = IC_CONF_PRPVF_EN,
 | 
				
			||||||
 | 
							.ic_conf_rot_en = IC_CONF_PRPVF_ROT_EN,
 | 
				
			||||||
 | 
							.ic_conf_cmb_en = IC_CONF_PRPVF_CMB,
 | 
				
			||||||
 | 
							.ic_conf_csc1_en = IC_CONF_PRPVF_CSC1,
 | 
				
			||||||
 | 
							.ic_conf_csc2_en = IC_CONF_PRPVF_CSC2,
 | 
				
			||||||
 | 
							.ic_cmb_galpha_bit = 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						[IC_TASK_POST_PROCESSOR] = {
 | 
				
			||||||
 | 
							.ic_conf_en = IC_CONF_PP_EN,
 | 
				
			||||||
 | 
							.ic_conf_rot_en = IC_CONF_PP_ROT_EN,
 | 
				
			||||||
 | 
							.ic_conf_cmb_en = IC_CONF_PP_CMB,
 | 
				
			||||||
 | 
							.ic_conf_csc1_en = IC_CONF_PP_CSC1,
 | 
				
			||||||
 | 
							.ic_conf_csc2_en = IC_CONF_PP_CSC2,
 | 
				
			||||||
 | 
							.ic_cmb_galpha_bit = 8,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_ic_priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_ic {
 | 
				
			||||||
 | 
						enum ipu_ic_task task;
 | 
				
			||||||
 | 
						const struct ic_task_regoffs *reg;
 | 
				
			||||||
 | 
						const struct ic_task_bitfields *bit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum ipu_color_space in_cs, g_in_cs;
 | 
				
			||||||
 | 
						enum ipu_color_space out_cs;
 | 
				
			||||||
 | 
						bool graphics;
 | 
				
			||||||
 | 
						bool rotation;
 | 
				
			||||||
 | 
						bool in_use;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_ic_priv {
 | 
				
			||||||
 | 
						void __iomem *base;
 | 
				
			||||||
 | 
						void __iomem *tpmem_base;
 | 
				
			||||||
 | 
						spinlock_t lock;
 | 
				
			||||||
 | 
						struct ipu_soc *ipu;
 | 
				
			||||||
 | 
						int use_count;
 | 
				
			||||||
 | 
						struct ipu_ic task[IC_NUM_TASKS];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline u32 ipu_ic_read(struct ipu_ic *ic, unsigned offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return readl(ic->priv->base + offset);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void ipu_ic_write(struct ipu_ic *ic, u32 value, unsigned offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						writel(value, ic->priv->base + offset);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ic_csc_params {
 | 
				
			||||||
 | 
						s16 coeff[3][3];	/* signed 9-bit integer coefficients */
 | 
				
			||||||
 | 
						s16 offset[3];		/* signed 11+2-bit fixed point offset */
 | 
				
			||||||
 | 
						u8 scale:2;		/* scale coefficients * 2^(scale-1) */
 | 
				
			||||||
 | 
						bool sat:1;		/* saturate to (16, 235(Y) / 240(U, V)) */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Y = R *  .299 + G *  .587 + B *  .114;
 | 
				
			||||||
 | 
					 * U = R * -.169 + G * -.332 + B *  .500 + 128.;
 | 
				
			||||||
 | 
					 * V = R *  .500 + G * -.419 + B * -.0813 + 128.;
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static const struct ic_csc_params ic_csc_rgb2ycbcr = {
 | 
				
			||||||
 | 
						.coeff = {
 | 
				
			||||||
 | 
							{ 77, 150, 29 },
 | 
				
			||||||
 | 
							{ 469, 427, 128 },
 | 
				
			||||||
 | 
							{ 128, 405, 491 },
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						.offset = { 0, 512, 512 },
 | 
				
			||||||
 | 
						.scale = 1,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* transparent RGB->RGB matrix for graphics combining */
 | 
				
			||||||
 | 
					static const struct ic_csc_params ic_csc_rgb2rgb = {
 | 
				
			||||||
 | 
						.coeff = {
 | 
				
			||||||
 | 
							{ 128, 0, 0 },
 | 
				
			||||||
 | 
							{ 0, 128, 0 },
 | 
				
			||||||
 | 
							{ 0, 0, 128 },
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						.scale = 2,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * R = (1.164 * (Y - 16)) + (1.596 * (Cr - 128));
 | 
				
			||||||
 | 
					 * G = (1.164 * (Y - 16)) - (0.392 * (Cb - 128)) - (0.813 * (Cr - 128));
 | 
				
			||||||
 | 
					 * B = (1.164 * (Y - 16)) + (2.017 * (Cb - 128);
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static const struct ic_csc_params ic_csc_ycbcr2rgb = {
 | 
				
			||||||
 | 
						.coeff = {
 | 
				
			||||||
 | 
							{ 149, 0, 204 },
 | 
				
			||||||
 | 
							{ 149, 462, 408 },
 | 
				
			||||||
 | 
							{ 149, 255, 0 },
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						.offset = { -446, 266, -554 },
 | 
				
			||||||
 | 
						.scale = 2,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int init_csc(struct ipu_ic *ic,
 | 
				
			||||||
 | 
							    enum ipu_color_space inf,
 | 
				
			||||||
 | 
							    enum ipu_color_space outf,
 | 
				
			||||||
 | 
							    int csc_index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv = ic->priv;
 | 
				
			||||||
 | 
						const struct ic_csc_params *params;
 | 
				
			||||||
 | 
						u32 __iomem *base;
 | 
				
			||||||
 | 
						const u16 (*c)[3];
 | 
				
			||||||
 | 
						const u16 *a;
 | 
				
			||||||
 | 
						u32 param;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						base = (u32 __iomem *)
 | 
				
			||||||
 | 
							(priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (inf == IPUV3_COLORSPACE_YUV && outf == IPUV3_COLORSPACE_RGB)
 | 
				
			||||||
 | 
							params = &ic_csc_ycbcr2rgb;
 | 
				
			||||||
 | 
						else if (inf == IPUV3_COLORSPACE_RGB && outf == IPUV3_COLORSPACE_YUV)
 | 
				
			||||||
 | 
							params = &ic_csc_rgb2ycbcr;
 | 
				
			||||||
 | 
						else if (inf == IPUV3_COLORSPACE_RGB && outf == IPUV3_COLORSPACE_RGB)
 | 
				
			||||||
 | 
							params = &ic_csc_rgb2rgb;
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							dev_err(priv->ipu->dev, "Unsupported color space conversion\n");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Cast to unsigned */
 | 
				
			||||||
 | 
						c = (const u16 (*)[3])params->coeff;
 | 
				
			||||||
 | 
						a = (const u16 *)params->offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
 | 
				
			||||||
 | 
							((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
 | 
				
			||||||
 | 
						writel(param, base++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						param = ((a[0] & 0x1fe0) >> 5) | (params->scale << 8) |
 | 
				
			||||||
 | 
							(params->sat << 9);
 | 
				
			||||||
 | 
						writel(param, base++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
 | 
				
			||||||
 | 
							((c[1][0] & 0x1ff) << 9) | (c[2][0] & 0x1ff);
 | 
				
			||||||
 | 
						writel(param, base++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						param = ((a[1] & 0x1fe0) >> 5);
 | 
				
			||||||
 | 
						writel(param, base++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						param = ((a[2] & 0x1f) << 27) | ((c[0][2] & 0x1ff) << 18) |
 | 
				
			||||||
 | 
							((c[1][2] & 0x1ff) << 9) | (c[2][1] & 0x1ff);
 | 
				
			||||||
 | 
						writel(param, base++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						param = ((a[2] & 0x1fe0) >> 5);
 | 
				
			||||||
 | 
						writel(param, base++);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int calc_resize_coeffs(struct ipu_ic *ic,
 | 
				
			||||||
 | 
								      u32 in_size, u32 out_size,
 | 
				
			||||||
 | 
								      u32 *resize_coeff,
 | 
				
			||||||
 | 
								      u32 *downsize_coeff)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv = ic->priv;
 | 
				
			||||||
 | 
						struct ipu_soc *ipu = priv->ipu;
 | 
				
			||||||
 | 
						u32 temp_size, temp_downsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Input size cannot be more than 4096, and output size cannot
 | 
				
			||||||
 | 
						 * be more than 1024
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (in_size > 4096) {
 | 
				
			||||||
 | 
							dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (out_size > 1024) {
 | 
				
			||||||
 | 
							dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Cannot downsize more than 8:1 */
 | 
				
			||||||
 | 
						if ((out_size << 3) < in_size) {
 | 
				
			||||||
 | 
							dev_err(ipu->dev, "Unsupported downsize\n");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Compute downsizing coefficient */
 | 
				
			||||||
 | 
						temp_downsize = 0;
 | 
				
			||||||
 | 
						temp_size = in_size;
 | 
				
			||||||
 | 
						while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
 | 
				
			||||||
 | 
						       (temp_downsize < 2)) {
 | 
				
			||||||
 | 
							temp_size >>= 1;
 | 
				
			||||||
 | 
							temp_downsize++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*downsize_coeff = temp_downsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * compute resizing coefficient using the following equation:
 | 
				
			||||||
 | 
						 * resize_coeff = M * (SI - 1) / (SO - 1)
 | 
				
			||||||
 | 
						 * where M = 2^13, SI = input size, SO = output size
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						*resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
 | 
				
			||||||
 | 
						if (*resize_coeff >= 16384L) {
 | 
				
			||||||
 | 
							dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
 | 
				
			||||||
 | 
							*resize_coeff = 0x3FFF;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_ic_task_enable(struct ipu_ic *ic)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv = ic->priv;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 ic_conf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ic_conf = ipu_ic_read(ic, IC_CONF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ic_conf |= ic->bit->ic_conf_en;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ic->rotation)
 | 
				
			||||||
 | 
							ic_conf |= ic->bit->ic_conf_rot_en;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ic->in_cs != ic->out_cs)
 | 
				
			||||||
 | 
							ic_conf |= ic->bit->ic_conf_csc1_en;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ic->graphics) {
 | 
				
			||||||
 | 
							ic_conf |= ic->bit->ic_conf_cmb_en;
 | 
				
			||||||
 | 
							ic_conf |= ic->bit->ic_conf_csc1_en;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (ic->g_in_cs != ic->out_cs)
 | 
				
			||||||
 | 
								ic_conf |= ic->bit->ic_conf_csc2_en;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_ic_write(ic, ic_conf, IC_CONF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_ic_task_enable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_ic_task_disable(struct ipu_ic *ic)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv = ic->priv;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 ic_conf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ic_conf = ipu_ic_read(ic, IC_CONF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ic_conf &= ~(ic->bit->ic_conf_en |
 | 
				
			||||||
 | 
							     ic->bit->ic_conf_csc1_en |
 | 
				
			||||||
 | 
							     ic->bit->ic_conf_rot_en);
 | 
				
			||||||
 | 
						if (ic->bit->ic_conf_csc2_en)
 | 
				
			||||||
 | 
							ic_conf &= ~ic->bit->ic_conf_csc2_en;
 | 
				
			||||||
 | 
						if (ic->bit->ic_conf_cmb_en)
 | 
				
			||||||
 | 
							ic_conf &= ~ic->bit->ic_conf_cmb_en;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_ic_write(ic, ic_conf, IC_CONF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ic->rotation = ic->graphics = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_ic_task_graphics_init(struct ipu_ic *ic,
 | 
				
			||||||
 | 
								      enum ipu_color_space in_g_cs,
 | 
				
			||||||
 | 
								      bool galpha_en, u32 galpha,
 | 
				
			||||||
 | 
								      bool colorkey_en, u32 colorkey)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv = ic->priv;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 reg, ic_conf;
 | 
				
			||||||
 | 
						int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ic->task == IC_TASK_ENCODER)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ic_conf = ipu_ic_read(ic, IC_CONF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
 | 
				
			||||||
 | 
							/* need transparent CSC1 conversion */
 | 
				
			||||||
 | 
							ret = init_csc(ic, IPUV3_COLORSPACE_RGB,
 | 
				
			||||||
 | 
								       IPUV3_COLORSPACE_RGB, 0);
 | 
				
			||||||
 | 
							if (ret)
 | 
				
			||||||
 | 
								goto unlock;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ic->g_in_cs = in_g_cs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ic->g_in_cs != ic->out_cs) {
 | 
				
			||||||
 | 
							ret = init_csc(ic, ic->g_in_cs, ic->out_cs, 1);
 | 
				
			||||||
 | 
							if (ret)
 | 
				
			||||||
 | 
								goto unlock;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (galpha_en) {
 | 
				
			||||||
 | 
							ic_conf |= IC_CONF_IC_GLB_LOC_A;
 | 
				
			||||||
 | 
							reg = ipu_ic_read(ic, IC_CMBP_1);
 | 
				
			||||||
 | 
							reg &= ~(0xff << ic->bit->ic_cmb_galpha_bit);
 | 
				
			||||||
 | 
							reg |= (galpha << ic->bit->ic_cmb_galpha_bit);
 | 
				
			||||||
 | 
							ipu_ic_write(ic, reg, IC_CMBP_1);
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (colorkey_en) {
 | 
				
			||||||
 | 
							ic_conf |= IC_CONF_KEY_COLOR_EN;
 | 
				
			||||||
 | 
							ipu_ic_write(ic, colorkey, IC_CMBP_2);
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							ic_conf &= ~IC_CONF_KEY_COLOR_EN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_ic_write(ic, ic_conf, IC_CONF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ic->graphics = true;
 | 
				
			||||||
 | 
					unlock:
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_ic_task_init(struct ipu_ic *ic,
 | 
				
			||||||
 | 
							     int in_width, int in_height,
 | 
				
			||||||
 | 
							     int out_width, int out_height,
 | 
				
			||||||
 | 
							     enum ipu_color_space in_cs,
 | 
				
			||||||
 | 
							     enum ipu_color_space out_cs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv = ic->priv;
 | 
				
			||||||
 | 
						u32 reg, downsize_coeff, resize_coeff;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Setup vertical resizing */
 | 
				
			||||||
 | 
						ret = calc_resize_coeffs(ic, in_height, out_height,
 | 
				
			||||||
 | 
									 &resize_coeff, &downsize_coeff);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg = (downsize_coeff << 30) | (resize_coeff << 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Setup horizontal resizing */
 | 
				
			||||||
 | 
						ret = calc_resize_coeffs(ic, in_width, out_width,
 | 
				
			||||||
 | 
									 &resize_coeff, &downsize_coeff);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg |= (downsize_coeff << 14) | resize_coeff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_ic_write(ic, reg, ic->reg->rsc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Setup color space conversion */
 | 
				
			||||||
 | 
						ic->in_cs = in_cs;
 | 
				
			||||||
 | 
						ic->out_cs = out_cs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ic->in_cs != ic->out_cs) {
 | 
				
			||||||
 | 
							ret = init_csc(ic, ic->in_cs, ic->out_cs, 0);
 | 
				
			||||||
 | 
							if (ret)
 | 
				
			||||||
 | 
								goto unlock;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unlock:
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_ic_task_init);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
 | 
				
			||||||
 | 
								  u32 width, u32 height, int burst_size,
 | 
				
			||||||
 | 
								  enum ipu_rotate_mode rot)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv = ic->priv;
 | 
				
			||||||
 | 
						struct ipu_soc *ipu = priv->ipu;
 | 
				
			||||||
 | 
						u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
 | 
				
			||||||
 | 
						u32 temp_rot = bitrev8(rot) >> 5;
 | 
				
			||||||
 | 
						bool need_hor_flip = false;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((burst_size != 8) && (burst_size != 16)) {
 | 
				
			||||||
 | 
							dev_err(ipu->dev, "Illegal burst length for IC\n");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						width--;
 | 
				
			||||||
 | 
						height--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (temp_rot & 0x2)	/* Need horizontal flip */
 | 
				
			||||||
 | 
							need_hor_flip = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ic_idmac_1 = ipu_ic_read(ic, IC_IDMAC_1);
 | 
				
			||||||
 | 
						ic_idmac_2 = ipu_ic_read(ic, IC_IDMAC_2);
 | 
				
			||||||
 | 
						ic_idmac_3 = ipu_ic_read(ic, IC_IDMAC_3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (channel->num) {
 | 
				
			||||||
 | 
						case IPUV3_CHANNEL_IC_PP_MEM:
 | 
				
			||||||
 | 
							if (burst_size == 16)
 | 
				
			||||||
 | 
								ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (need_hor_flip)
 | 
				
			||||||
 | 
								ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
 | 
				
			||||||
 | 
							ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
 | 
				
			||||||
 | 
							ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPUV3_CHANNEL_MEM_IC_PP:
 | 
				
			||||||
 | 
							if (burst_size == 16)
 | 
				
			||||||
 | 
								ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPUV3_CHANNEL_MEM_ROT_PP:
 | 
				
			||||||
 | 
							ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
 | 
				
			||||||
 | 
							ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPUV3_CHANNEL_MEM_IC_PRP_VF:
 | 
				
			||||||
 | 
							if (burst_size == 16)
 | 
				
			||||||
 | 
								ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPUV3_CHANNEL_IC_PRP_ENC_MEM:
 | 
				
			||||||
 | 
							if (burst_size == 16)
 | 
				
			||||||
 | 
								ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (need_hor_flip)
 | 
				
			||||||
 | 
								ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
 | 
				
			||||||
 | 
							ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
 | 
				
			||||||
 | 
							ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPUV3_CHANNEL_MEM_ROT_ENC:
 | 
				
			||||||
 | 
							ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
 | 
				
			||||||
 | 
							ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPUV3_CHANNEL_IC_PRP_VF_MEM:
 | 
				
			||||||
 | 
							if (burst_size == 16)
 | 
				
			||||||
 | 
								ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (need_hor_flip)
 | 
				
			||||||
 | 
								ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
 | 
				
			||||||
 | 
							ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
 | 
				
			||||||
 | 
							ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPUV3_CHANNEL_MEM_ROT_VF:
 | 
				
			||||||
 | 
							ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
 | 
				
			||||||
 | 
							ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:
 | 
				
			||||||
 | 
							if (burst_size == 16)
 | 
				
			||||||
 | 
								ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPUV3_CHANNEL_G_MEM_IC_PP:
 | 
				
			||||||
 | 
							if (burst_size == 16)
 | 
				
			||||||
 | 
								ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case IPUV3_CHANNEL_VDI_MEM_IC_VF:
 | 
				
			||||||
 | 
							if (burst_size == 16)
 | 
				
			||||||
 | 
								ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							goto unlock;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu_ic_write(ic, ic_idmac_1, IC_IDMAC_1);
 | 
				
			||||||
 | 
						ipu_ic_write(ic, ic_idmac_2, IC_IDMAC_2);
 | 
				
			||||||
 | 
						ipu_ic_write(ic, ic_idmac_3, IC_IDMAC_3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rot >= IPU_ROTATE_90_RIGHT)
 | 
				
			||||||
 | 
							ic->rotation = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unlock:
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_ic_enable(struct ipu_ic *ic)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv = ic->priv;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 module = IPU_CONF_IC_EN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ic->rotation)
 | 
				
			||||||
 | 
							module |= IPU_CONF_ROT_EN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!priv->use_count)
 | 
				
			||||||
 | 
							ipu_module_enable(priv->ipu, module);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv->use_count++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_ic_enable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_ic_disable(struct ipu_ic *ic)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv = ic->priv;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 module = IPU_CONF_IC_EN | IPU_CONF_ROT_EN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv->use_count--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!priv->use_count)
 | 
				
			||||||
 | 
							ipu_module_disable(priv->ipu, module);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (priv->use_count < 0)
 | 
				
			||||||
 | 
							priv->use_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_ic_disable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv = ipu->ic_priv;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						struct ipu_ic *ic, *ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (task >= IC_NUM_TASKS)
 | 
				
			||||||
 | 
							return ERR_PTR(-EINVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ic = &priv->task[task];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ic->in_use) {
 | 
				
			||||||
 | 
							ret = ERR_PTR(-EBUSY);
 | 
				
			||||||
 | 
							goto unlock;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ic->in_use = true;
 | 
				
			||||||
 | 
						ret = ic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unlock:
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_ic_get);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_ic_put(struct ipu_ic *ic)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv = ic->priv;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
						ic->in_use = false;
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_ic_put);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
 | 
				
			||||||
 | 
							unsigned long base, unsigned long tpmem_base)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!priv)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ipu->ic_priv = priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_init(&priv->lock);
 | 
				
			||||||
 | 
						priv->base = devm_ioremap(dev, base, PAGE_SIZE);
 | 
				
			||||||
 | 
						if (!priv->base)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						priv->tpmem_base = devm_ioremap(dev, tpmem_base, SZ_64K);
 | 
				
			||||||
 | 
						if (!priv->tpmem_base)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_dbg(dev, "IC base: 0x%08lx remapped to %p\n", base, priv->base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv->ipu = ipu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < IC_NUM_TASKS; i++) {
 | 
				
			||||||
 | 
							priv->task[i].task = i;
 | 
				
			||||||
 | 
							priv->task[i].priv = priv;
 | 
				
			||||||
 | 
							priv->task[i].reg = &ic_task_reg[i];
 | 
				
			||||||
 | 
							priv->task[i].bit = &ic_task_bit[i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_ic_exit(struct ipu_soc *ipu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_ic_dump(struct ipu_ic *ic)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_ic_priv *priv = ic->priv;
 | 
				
			||||||
 | 
						struct ipu_soc *ipu = priv->ipu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "IC_CONF = \t0x%08X\n",
 | 
				
			||||||
 | 
							ipu_ic_read(ic, IC_CONF));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "IC_PRP_ENC_RSC = \t0x%08X\n",
 | 
				
			||||||
 | 
							ipu_ic_read(ic, IC_PRP_ENC_RSC));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "IC_PRP_VF_RSC = \t0x%08X\n",
 | 
				
			||||||
 | 
							ipu_ic_read(ic, IC_PRP_VF_RSC));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "IC_PP_RSC = \t0x%08X\n",
 | 
				
			||||||
 | 
							ipu_ic_read(ic, IC_PP_RSC));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "IC_CMBP_1 = \t0x%08X\n",
 | 
				
			||||||
 | 
							ipu_ic_read(ic, IC_CMBP_1));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "IC_CMBP_2 = \t0x%08X\n",
 | 
				
			||||||
 | 
							ipu_ic_read(ic, IC_CMBP_2));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "IC_IDMAC_1 = \t0x%08X\n",
 | 
				
			||||||
 | 
							ipu_ic_read(ic, IC_IDMAC_1));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "IC_IDMAC_2 = \t0x%08X\n",
 | 
				
			||||||
 | 
							ipu_ic_read(ic, IC_IDMAC_2));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "IC_IDMAC_3 = \t0x%08X\n",
 | 
				
			||||||
 | 
							ipu_ic_read(ic, IC_IDMAC_3));
 | 
				
			||||||
 | 
						dev_dbg(ipu->dev, "IC_IDMAC_4 = \t0x%08X\n",
 | 
				
			||||||
 | 
							ipu_ic_read(ic, IC_IDMAC_4));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_ic_dump);
 | 
				
			||||||
| 
						 | 
					@ -24,23 +24,6 @@ struct ipu_soc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <video/imx-ipu-v3.h>
 | 
					#include <video/imx-ipu-v3.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IPUV3_CHANNEL_CSI0			 0
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_CSI1			 1
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_CSI2			 2
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_CSI3			 3
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_MEM_BG_SYNC		23
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_MEM_FG_SYNC		27
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_MEM_DC_SYNC		28
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_MEM_FG_SYNC_ALPHA		31
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_MEM_DC_ASYNC		41
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_ROT_ENC_MEM		45
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_ROT_VF_MEM		46
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_ROT_PP_MEM		47
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_ROT_ENC_MEM_OUT		48
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_ROT_VF_MEM_OUT		49
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_ROT_PP_MEM_OUT		50
 | 
					 | 
				
			||||||
#define IPUV3_CHANNEL_MEM_BG_SYNC_ALPHA		51
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define IPU_MCU_T_DEFAULT	8
 | 
					#define IPU_MCU_T_DEFAULT	8
 | 
				
			||||||
#define IPU_CM_IDMAC_REG_OFS	0x00008000
 | 
					#define IPU_CM_IDMAC_REG_OFS	0x00008000
 | 
				
			||||||
#define IPU_CM_IC_REG_OFS	0x00020000
 | 
					#define IPU_CM_IC_REG_OFS	0x00020000
 | 
				
			||||||
| 
						 | 
					@ -85,6 +68,7 @@ struct ipu_soc;
 | 
				
			||||||
#define IPU_DISP_TASK_STAT		IPU_CM_REG(0x0254)
 | 
					#define IPU_DISP_TASK_STAT		IPU_CM_REG(0x0254)
 | 
				
			||||||
#define IPU_CHA_BUF0_RDY(ch)		IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
 | 
					#define IPU_CHA_BUF0_RDY(ch)		IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
 | 
				
			||||||
#define IPU_CHA_BUF1_RDY(ch)		IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
 | 
					#define IPU_CHA_BUF1_RDY(ch)		IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
 | 
				
			||||||
 | 
					#define IPU_CHA_BUF2_RDY(ch)		IPU_CM_REG(0x0288 + 4 * ((ch) / 32))
 | 
				
			||||||
#define IPU_ALT_CHA_BUF0_RDY(ch)	IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
 | 
					#define IPU_ALT_CHA_BUF0_RDY(ch)	IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
 | 
				
			||||||
#define IPU_ALT_CHA_BUF1_RDY(ch)	IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
 | 
					#define IPU_ALT_CHA_BUF1_RDY(ch)	IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,9 +132,12 @@ struct ipuv3_channel {
 | 
				
			||||||
	struct ipu_soc *ipu;
 | 
						struct ipu_soc *ipu;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_cpmem;
 | 
				
			||||||
 | 
					struct ipu_csi;
 | 
				
			||||||
struct ipu_dc_priv;
 | 
					struct ipu_dc_priv;
 | 
				
			||||||
struct ipu_dmfc_priv;
 | 
					struct ipu_dmfc_priv;
 | 
				
			||||||
struct ipu_di;
 | 
					struct ipu_di;
 | 
				
			||||||
 | 
					struct ipu_ic_priv;
 | 
				
			||||||
struct ipu_smfc_priv;
 | 
					struct ipu_smfc_priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ipu_devtype;
 | 
					struct ipu_devtype;
 | 
				
			||||||
| 
						 | 
					@ -164,7 +151,6 @@ struct ipu_soc {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void __iomem		*cm_reg;
 | 
						void __iomem		*cm_reg;
 | 
				
			||||||
	void __iomem		*idmac_reg;
 | 
						void __iomem		*idmac_reg;
 | 
				
			||||||
	struct ipu_ch_param __iomem	*cpmem_base;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int			usecount;
 | 
						int			usecount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -176,13 +162,27 @@ struct ipu_soc {
 | 
				
			||||||
	int			irq_err;
 | 
						int			irq_err;
 | 
				
			||||||
	struct irq_domain	*domain;
 | 
						struct irq_domain	*domain;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ipu_cpmem	*cpmem_priv;
 | 
				
			||||||
	struct ipu_dc_priv	*dc_priv;
 | 
						struct ipu_dc_priv	*dc_priv;
 | 
				
			||||||
	struct ipu_dp_priv	*dp_priv;
 | 
						struct ipu_dp_priv	*dp_priv;
 | 
				
			||||||
	struct ipu_dmfc_priv	*dmfc_priv;
 | 
						struct ipu_dmfc_priv	*dmfc_priv;
 | 
				
			||||||
	struct ipu_di		*di_priv[2];
 | 
						struct ipu_di		*di_priv[2];
 | 
				
			||||||
 | 
						struct ipu_csi		*csi_priv[2];
 | 
				
			||||||
 | 
						struct ipu_ic_priv	*ic_priv;
 | 
				
			||||||
	struct ipu_smfc_priv	*smfc_priv;
 | 
						struct ipu_smfc_priv	*smfc_priv;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return readl(ipu->idmac_reg + offset);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
 | 
				
			||||||
 | 
									   unsigned offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						writel(value, ipu->idmac_reg + offset);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ipu_srm_dp_sync_update(struct ipu_soc *ipu);
 | 
					void ipu_srm_dp_sync_update(struct ipu_soc *ipu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
 | 
					int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
 | 
				
			||||||
| 
						 | 
					@ -191,6 +191,14 @@ int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
 | 
				
			||||||
bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
 | 
					bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
 | 
				
			||||||
int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms);
 | 
					int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
 | 
				
			||||||
 | 
							 unsigned long base, u32 module, struct clk *clk_ipu);
 | 
				
			||||||
 | 
					void ipu_csi_exit(struct ipu_soc *ipu, int id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
 | 
				
			||||||
 | 
							unsigned long base, unsigned long tpmem_base);
 | 
				
			||||||
 | 
					void ipu_ic_exit(struct ipu_soc *ipu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
 | 
					int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
 | 
				
			||||||
		unsigned long base, u32 module, struct clk *ipu_clk);
 | 
							unsigned long base, u32 module, struct clk *ipu_clk);
 | 
				
			||||||
void ipu_di_exit(struct ipu_soc *ipu, int id);
 | 
					void ipu_di_exit(struct ipu_soc *ipu, int id);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,9 +21,18 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ipu-prv.h"
 | 
					#include "ipu-prv.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_smfc {
 | 
				
			||||||
 | 
						struct ipu_smfc_priv *priv;
 | 
				
			||||||
 | 
						int chno;
 | 
				
			||||||
 | 
						bool inuse;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ipu_smfc_priv {
 | 
					struct ipu_smfc_priv {
 | 
				
			||||||
	void __iomem *base;
 | 
						void __iomem *base;
 | 
				
			||||||
	spinlock_t lock;
 | 
						spinlock_t lock;
 | 
				
			||||||
 | 
						struct ipu_soc *ipu;
 | 
				
			||||||
 | 
						struct ipu_smfc channel[4];
 | 
				
			||||||
 | 
						int use_count;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*SMFC Registers */
 | 
					/*SMFC Registers */
 | 
				
			||||||
| 
						 | 
					@ -31,63 +40,166 @@ struct ipu_smfc_priv {
 | 
				
			||||||
#define SMFC_WMC	0x0004
 | 
					#define SMFC_WMC	0x0004
 | 
				
			||||||
#define SMFC_BS		0x0008
 | 
					#define SMFC_BS		0x0008
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ipu_smfc_set_burstsize(struct ipu_soc *ipu, int channel, int burstsize)
 | 
					int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ipu_smfc_priv *smfc = ipu->smfc_priv;
 | 
						struct ipu_smfc_priv *priv = smfc->priv;
 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
	u32 val, shift;
 | 
						u32 val, shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&smfc->lock, flags);
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	shift = channel * 4;
 | 
						shift = smfc->chno * 4;
 | 
				
			||||||
	val = readl(smfc->base + SMFC_BS);
 | 
						val = readl(priv->base + SMFC_BS);
 | 
				
			||||||
	val &= ~(0xf << shift);
 | 
						val &= ~(0xf << shift);
 | 
				
			||||||
	val |= burstsize << shift;
 | 
						val |= burstsize << shift;
 | 
				
			||||||
	writel(val, smfc->base + SMFC_BS);
 | 
						writel(val, priv->base + SMFC_BS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_irqrestore(&smfc->lock, flags);
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
 | 
					EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ipu_smfc_map_channel(struct ipu_soc *ipu, int channel, int csi_id, int mipi_id)
 | 
					int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ipu_smfc_priv *smfc = ipu->smfc_priv;
 | 
						struct ipu_smfc_priv *priv = smfc->priv;
 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
	u32 val, shift;
 | 
						u32 val, shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_irqsave(&smfc->lock, flags);
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	shift = channel * 3;
 | 
						shift = smfc->chno * 3;
 | 
				
			||||||
	val = readl(smfc->base + SMFC_MAP);
 | 
						val = readl(priv->base + SMFC_MAP);
 | 
				
			||||||
	val &= ~(0x7 << shift);
 | 
						val &= ~(0x7 << shift);
 | 
				
			||||||
	val |= ((csi_id << 2) | mipi_id) << shift;
 | 
						val |= ((csi_id << 2) | mipi_id) << shift;
 | 
				
			||||||
	writel(val, smfc->base + SMFC_MAP);
 | 
						writel(val, priv->base + SMFC_MAP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_unlock_irqrestore(&smfc->lock, flags);
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
 | 
					EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_smfc_priv *priv = smfc->priv;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
						u32 val, shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
 | 
				
			||||||
 | 
						val = readl(priv->base + SMFC_WMC);
 | 
				
			||||||
 | 
						val &= ~(0x3f << shift);
 | 
				
			||||||
 | 
						val |= ((clr_level << 3) | set_level) << shift;
 | 
				
			||||||
 | 
						writel(val, priv->base + SMFC_WMC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_smfc_enable(struct ipu_smfc *smfc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_smfc_priv *priv = smfc->priv;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!priv->use_count)
 | 
				
			||||||
 | 
							ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv->use_count++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_smfc_enable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ipu_smfc_disable(struct ipu_smfc *smfc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_smfc_priv *priv = smfc->priv;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						priv->use_count--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!priv->use_count)
 | 
				
			||||||
 | 
							ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (priv->use_count < 0)
 | 
				
			||||||
 | 
							priv->use_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_smfc_disable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_smfc_priv *priv = ipu->smfc_priv;
 | 
				
			||||||
 | 
						struct ipu_smfc *smfc, *ret;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (chno >= 4)
 | 
				
			||||||
 | 
							return ERR_PTR(-EINVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						smfc = &priv->channel[chno];
 | 
				
			||||||
 | 
						ret = smfc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (smfc->inuse) {
 | 
				
			||||||
 | 
							ret = ERR_PTR(-EBUSY);
 | 
				
			||||||
 | 
							goto unlock;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						smfc->inuse = true;
 | 
				
			||||||
 | 
					unlock:
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_smfc_get);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_smfc_put(struct ipu_smfc *smfc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ipu_smfc_priv *priv = smfc->priv;
 | 
				
			||||||
 | 
						unsigned long flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock_irqsave(&priv->lock, flags);
 | 
				
			||||||
 | 
						smfc->inuse = false;
 | 
				
			||||||
 | 
						spin_unlock_irqrestore(&priv->lock, flags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(ipu_smfc_put);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
 | 
					int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
 | 
				
			||||||
		  unsigned long base)
 | 
							  unsigned long base)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ipu_smfc_priv *smfc;
 | 
						struct ipu_smfc_priv *priv;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	smfc = devm_kzalloc(dev, sizeof(*smfc), GFP_KERNEL);
 | 
						priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 | 
				
			||||||
	if (!smfc)
 | 
						if (!priv)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ipu->smfc_priv = smfc;
 | 
						ipu->smfc_priv = priv;
 | 
				
			||||||
	spin_lock_init(&smfc->lock);
 | 
						spin_lock_init(&priv->lock);
 | 
				
			||||||
 | 
						priv->ipu = ipu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	smfc->base = devm_ioremap(dev, base, PAGE_SIZE);
 | 
						priv->base = devm_ioremap(dev, base, PAGE_SIZE);
 | 
				
			||||||
	if (!smfc->base)
 | 
						if (!priv->base)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, smfc->base);
 | 
						for (i = 0; i < 4; i++) {
 | 
				
			||||||
 | 
							priv->channel[i].priv = priv;
 | 
				
			||||||
 | 
							priv->channel[i].chno = i;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,6 @@ static inline int calc_bandwidth(int width, int height, unsigned int vref)
 | 
				
			||||||
int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
 | 
					int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
 | 
				
			||||||
		       int x, int y)
 | 
							       int x, int y)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ipu_ch_param __iomem *cpmem;
 | 
					 | 
				
			||||||
	struct drm_gem_cma_object *cma_obj;
 | 
						struct drm_gem_cma_object *cma_obj;
 | 
				
			||||||
	unsigned long eba;
 | 
						unsigned long eba;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,13 +74,12 @@ int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
 | 
				
			||||||
	dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d",
 | 
						dev_dbg(ipu_plane->base.dev->dev, "phys = %pad, x = %d, y = %d",
 | 
				
			||||||
		&cma_obj->paddr, x, y);
 | 
							&cma_obj->paddr, x, y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
 | 
						ipu_cpmem_set_stride(ipu_plane->ipu_ch, fb->pitches[0]);
 | 
				
			||||||
	ipu_cpmem_set_stride(cpmem, fb->pitches[0]);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	eba = cma_obj->paddr + fb->offsets[0] +
 | 
						eba = cma_obj->paddr + fb->offsets[0] +
 | 
				
			||||||
	      fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x;
 | 
						      fb->pitches[0] * y + (fb->bits_per_pixel >> 3) * x;
 | 
				
			||||||
	ipu_cpmem_set_buffer(cpmem, 0, eba);
 | 
						ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
 | 
				
			||||||
	ipu_cpmem_set_buffer(cpmem, 1, eba);
 | 
						ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* cache offsets for subsequent pageflips */
 | 
						/* cache offsets for subsequent pageflips */
 | 
				
			||||||
	ipu_plane->x = x;
 | 
						ipu_plane->x = x;
 | 
				
			||||||
| 
						 | 
					@ -97,7 +95,6 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
 | 
				
			||||||
		       uint32_t src_x, uint32_t src_y,
 | 
							       uint32_t src_x, uint32_t src_y,
 | 
				
			||||||
		       uint32_t src_w, uint32_t src_h)
 | 
							       uint32_t src_w, uint32_t src_h)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ipu_ch_param __iomem *cpmem;
 | 
					 | 
				
			||||||
	struct device *dev = ipu_plane->base.dev->dev;
 | 
						struct device *dev = ipu_plane->base.dev->dev;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -175,10 +172,9 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
 | 
						ipu_cpmem_zero(ipu_plane->ipu_ch);
 | 
				
			||||||
	ipu_ch_param_zero(cpmem);
 | 
						ipu_cpmem_set_resolution(ipu_plane->ipu_ch, src_w, src_h);
 | 
				
			||||||
	ipu_cpmem_set_resolution(cpmem, src_w, src_h);
 | 
						ret = ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->pixel_format);
 | 
				
			||||||
	ret = ipu_cpmem_set_fmt(cpmem, fb->pixel_format);
 | 
					 | 
				
			||||||
	if (ret < 0) {
 | 
						if (ret < 0) {
 | 
				
			||||||
		dev_err(dev, "unsupported pixel format 0x%08x\n",
 | 
							dev_err(dev, "unsupported pixel format 0x%08x\n",
 | 
				
			||||||
			fb->pixel_format);
 | 
								fb->pixel_format);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@
 | 
				
			||||||
#include <linux/videodev2.h>
 | 
					#include <linux/videodev2.h>
 | 
				
			||||||
#include <linux/bitmap.h>
 | 
					#include <linux/bitmap.h>
 | 
				
			||||||
#include <linux/fb.h>
 | 
					#include <linux/fb.h>
 | 
				
			||||||
 | 
					#include <media/v4l2-mediabus.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ipu_soc;
 | 
					struct ipu_soc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,6 +62,29 @@ struct ipu_di_signal_cfg {
 | 
				
			||||||
	u8 vsync_pin;
 | 
						u8 vsync_pin;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Enumeration of CSI destinations
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum ipu_csi_dest {
 | 
				
			||||||
 | 
						IPU_CSI_DEST_IDMAC, /* to memory via SMFC */
 | 
				
			||||||
 | 
						IPU_CSI_DEST_IC,	/* to Image Converter */
 | 
				
			||||||
 | 
						IPU_CSI_DEST_VDIC,  /* to VDIC */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Enumeration of IPU rotation modes
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum ipu_rotate_mode {
 | 
				
			||||||
 | 
						IPU_ROTATE_NONE = 0,
 | 
				
			||||||
 | 
						IPU_ROTATE_VERT_FLIP,
 | 
				
			||||||
 | 
						IPU_ROTATE_HORIZ_FLIP,
 | 
				
			||||||
 | 
						IPU_ROTATE_180,
 | 
				
			||||||
 | 
						IPU_ROTATE_90_RIGHT,
 | 
				
			||||||
 | 
						IPU_ROTATE_90_RIGHT_VFLIP,
 | 
				
			||||||
 | 
						IPU_ROTATE_90_RIGHT_HFLIP,
 | 
				
			||||||
 | 
						IPU_ROTATE_90_LEFT,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum ipu_color_space {
 | 
					enum ipu_color_space {
 | 
				
			||||||
	IPUV3_COLORSPACE_RGB,
 | 
						IPUV3_COLORSPACE_RGB,
 | 
				
			||||||
	IPUV3_COLORSPACE_YUV,
 | 
						IPUV3_COLORSPACE_YUV,
 | 
				
			||||||
| 
						 | 
					@ -76,6 +100,36 @@ enum ipu_channel_irq {
 | 
				
			||||||
	IPU_IRQ_EOS = 192,
 | 
						IPU_IRQ_EOS = 192,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Enumeration of IDMAC channels
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_CSI0			 0
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_CSI1			 1
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_CSI2			 2
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_CSI3			 3
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_VDI_MEM_IC_VF		 5
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_IC_PP			11
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_IC_PRP_VF		12
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_G_MEM_IC_PRP_VF		14
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_G_MEM_IC_PP		15
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_IC_PRP_ENC_MEM		20
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_IC_PRP_VF_MEM		21
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_IC_PP_MEM			22
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_BG_SYNC		23
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_BG_ASYNC		24
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_FG_SYNC		27
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_DC_SYNC		28
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_FG_ASYNC		29
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_FG_SYNC_ALPHA		31
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_DC_ASYNC		41
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_ROT_ENC		45
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_ROT_VF		46
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_ROT_PP		47
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_ROT_ENC_MEM		48
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_ROT_VF_MEM		49
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_ROT_PP_MEM		50
 | 
				
			||||||
 | 
					#define IPUV3_CHANNEL_MEM_BG_SYNC_ALPHA		51
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ipu_map_irq(struct ipu_soc *ipu, int irq);
 | 
					int ipu_map_irq(struct ipu_soc *ipu, int irq);
 | 
				
			||||||
int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
 | 
					int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
 | 
				
			||||||
		enum ipu_channel_irq irq);
 | 
							enum ipu_channel_irq irq);
 | 
				
			||||||
| 
						 | 
					@ -92,6 +146,13 @@ int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
 | 
				
			||||||
#define IPU_IRQ_VSYNC_PRE_0		(448 + 14)
 | 
					#define IPU_IRQ_VSYNC_PRE_0		(448 + 14)
 | 
				
			||||||
#define IPU_IRQ_VSYNC_PRE_1		(448 + 15)
 | 
					#define IPU_IRQ_VSYNC_PRE_1		(448 + 15)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * IPU Common functions
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void ipu_set_csi_src_mux(struct ipu_soc *ipu, int csi_id, bool mipi_csi2);
 | 
				
			||||||
 | 
					void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi);
 | 
				
			||||||
 | 
					void ipu_dump(struct ipu_soc *ipu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * IPU Image DMA Controller (idmac) functions
 | 
					 * IPU Image DMA Controller (idmac) functions
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -100,12 +161,58 @@ void ipu_idmac_put(struct ipuv3_channel *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ipu_idmac_enable_channel(struct ipuv3_channel *channel);
 | 
					int ipu_idmac_enable_channel(struct ipuv3_channel *channel);
 | 
				
			||||||
int ipu_idmac_disable_channel(struct ipuv3_channel *channel);
 | 
					int ipu_idmac_disable_channel(struct ipuv3_channel *channel);
 | 
				
			||||||
 | 
					void ipu_idmac_enable_watermark(struct ipuv3_channel *channel, bool enable);
 | 
				
			||||||
 | 
					int ipu_idmac_lock_enable(struct ipuv3_channel *channel, int num_bursts);
 | 
				
			||||||
int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms);
 | 
					int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
 | 
					void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
 | 
				
			||||||
		bool doublebuffer);
 | 
							bool doublebuffer);
 | 
				
			||||||
int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel);
 | 
					int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel);
 | 
				
			||||||
 | 
					bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num);
 | 
				
			||||||
void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num);
 | 
					void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num);
 | 
				
			||||||
 | 
					void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * IPU Channel Parameter Memory (cpmem) functions
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct ipu_rgb {
 | 
				
			||||||
 | 
						struct fb_bitfield      red;
 | 
				
			||||||
 | 
						struct fb_bitfield      green;
 | 
				
			||||||
 | 
						struct fb_bitfield      blue;
 | 
				
			||||||
 | 
						struct fb_bitfield      transp;
 | 
				
			||||||
 | 
						int                     bits_per_pixel;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_image {
 | 
				
			||||||
 | 
						struct v4l2_pix_format pix;
 | 
				
			||||||
 | 
						struct v4l2_rect rect;
 | 
				
			||||||
 | 
						dma_addr_t phys0;
 | 
				
			||||||
 | 
						dma_addr_t phys1;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ipu_cpmem_zero(struct ipuv3_channel *ch);
 | 
				
			||||||
 | 
					void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres);
 | 
				
			||||||
 | 
					void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride);
 | 
				
			||||||
 | 
					void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch);
 | 
				
			||||||
 | 
					void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf);
 | 
				
			||||||
 | 
					void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride);
 | 
				
			||||||
 | 
					void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id);
 | 
				
			||||||
 | 
					void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize);
 | 
				
			||||||
 | 
					void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch);
 | 
				
			||||||
 | 
					void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
 | 
				
			||||||
 | 
								    enum ipu_rotate_mode rot);
 | 
				
			||||||
 | 
					int ipu_cpmem_set_format_rgb(struct ipuv3_channel *ch,
 | 
				
			||||||
 | 
								     const struct ipu_rgb *rgb);
 | 
				
			||||||
 | 
					int ipu_cpmem_set_format_passthrough(struct ipuv3_channel *ch, int width);
 | 
				
			||||||
 | 
					void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format);
 | 
				
			||||||
 | 
					void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
 | 
				
			||||||
 | 
									   u32 pixel_format, int stride,
 | 
				
			||||||
 | 
									   int u_offset, int v_offset);
 | 
				
			||||||
 | 
					void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch,
 | 
				
			||||||
 | 
								      u32 pixel_format, int stride, int height);
 | 
				
			||||||
 | 
					int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc);
 | 
				
			||||||
 | 
					int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image);
 | 
				
			||||||
 | 
					void ipu_cpmem_dump(struct ipuv3_channel *ch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * IPU Display Controller (dc) functions
 | 
					 * IPU Display Controller (dc) functions
 | 
				
			||||||
| 
						 | 
					@ -169,171 +276,78 @@ int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha,
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * IPU CMOS Sensor Interface (csi) functions
 | 
					 * IPU CMOS Sensor Interface (csi) functions
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int ipu_csi_enable(struct ipu_soc *ipu, int csi);
 | 
					struct ipu_csi;
 | 
				
			||||||
int ipu_csi_disable(struct ipu_soc *ipu, int csi);
 | 
					int ipu_csi_init_interface(struct ipu_csi *csi,
 | 
				
			||||||
 | 
								   struct v4l2_mbus_config *mbus_cfg,
 | 
				
			||||||
 | 
								   struct v4l2_mbus_framefmt *mbus_fmt);
 | 
				
			||||||
 | 
					bool ipu_csi_is_interlaced(struct ipu_csi *csi);
 | 
				
			||||||
 | 
					void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w);
 | 
				
			||||||
 | 
					void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w);
 | 
				
			||||||
 | 
					void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
 | 
				
			||||||
 | 
									u32 r_value, u32 g_value, u32 b_value,
 | 
				
			||||||
 | 
									u32 pix_clk);
 | 
				
			||||||
 | 
					int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc,
 | 
				
			||||||
 | 
								      struct v4l2_mbus_framefmt *mbus_fmt);
 | 
				
			||||||
 | 
					int ipu_csi_set_skip_smfc(struct ipu_csi *csi, u32 skip,
 | 
				
			||||||
 | 
								  u32 max_ratio, u32 id);
 | 
				
			||||||
 | 
					int ipu_csi_set_dest(struct ipu_csi *csi, enum ipu_csi_dest csi_dest);
 | 
				
			||||||
 | 
					int ipu_csi_enable(struct ipu_csi *csi);
 | 
				
			||||||
 | 
					int ipu_csi_disable(struct ipu_csi *csi);
 | 
				
			||||||
 | 
					struct ipu_csi *ipu_csi_get(struct ipu_soc *ipu, int id);
 | 
				
			||||||
 | 
					void ipu_csi_put(struct ipu_csi *csi);
 | 
				
			||||||
 | 
					void ipu_csi_dump(struct ipu_csi *csi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * IPU Image Converter (ic) functions
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum ipu_ic_task {
 | 
				
			||||||
 | 
						IC_TASK_ENCODER,
 | 
				
			||||||
 | 
						IC_TASK_VIEWFINDER,
 | 
				
			||||||
 | 
						IC_TASK_POST_PROCESSOR,
 | 
				
			||||||
 | 
						IC_NUM_TASKS,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ipu_ic;
 | 
				
			||||||
 | 
					int ipu_ic_task_init(struct ipu_ic *ic,
 | 
				
			||||||
 | 
							     int in_width, int in_height,
 | 
				
			||||||
 | 
							     int out_width, int out_height,
 | 
				
			||||||
 | 
							     enum ipu_color_space in_cs,
 | 
				
			||||||
 | 
							     enum ipu_color_space out_cs);
 | 
				
			||||||
 | 
					int ipu_ic_task_graphics_init(struct ipu_ic *ic,
 | 
				
			||||||
 | 
								      enum ipu_color_space in_g_cs,
 | 
				
			||||||
 | 
								      bool galpha_en, u32 galpha,
 | 
				
			||||||
 | 
								      bool colorkey_en, u32 colorkey);
 | 
				
			||||||
 | 
					void ipu_ic_task_enable(struct ipu_ic *ic);
 | 
				
			||||||
 | 
					void ipu_ic_task_disable(struct ipu_ic *ic);
 | 
				
			||||||
 | 
					int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
 | 
				
			||||||
 | 
								  u32 width, u32 height, int burst_size,
 | 
				
			||||||
 | 
								  enum ipu_rotate_mode rot);
 | 
				
			||||||
 | 
					int ipu_ic_enable(struct ipu_ic *ic);
 | 
				
			||||||
 | 
					int ipu_ic_disable(struct ipu_ic *ic);
 | 
				
			||||||
 | 
					struct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task);
 | 
				
			||||||
 | 
					void ipu_ic_put(struct ipu_ic *ic);
 | 
				
			||||||
 | 
					void ipu_ic_dump(struct ipu_ic *ic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * IPU Sensor Multiple FIFO Controller (SMFC) functions
 | 
					 * IPU Sensor Multiple FIFO Controller (SMFC) functions
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int ipu_smfc_enable(struct ipu_soc *ipu);
 | 
					struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno);
 | 
				
			||||||
int ipu_smfc_disable(struct ipu_soc *ipu);
 | 
					void ipu_smfc_put(struct ipu_smfc *smfc);
 | 
				
			||||||
int ipu_smfc_map_channel(struct ipu_soc *ipu, int channel, int csi_id, int mipi_id);
 | 
					int ipu_smfc_enable(struct ipu_smfc *smfc);
 | 
				
			||||||
int ipu_smfc_set_burstsize(struct ipu_soc *ipu, int channel, int burstsize);
 | 
					int ipu_smfc_disable(struct ipu_smfc *smfc);
 | 
				
			||||||
 | 
					int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id);
 | 
				
			||||||
#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
 | 
					int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize);
 | 
				
			||||||
 | 
					int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level);
 | 
				
			||||||
#define IPU_FIELD_UBO		IPU_CPMEM_WORD(0, 46, 22)
 | 
					 | 
				
			||||||
#define IPU_FIELD_VBO		IPU_CPMEM_WORD(0, 68, 22)
 | 
					 | 
				
			||||||
#define IPU_FIELD_IOX		IPU_CPMEM_WORD(0, 90, 4)
 | 
					 | 
				
			||||||
#define IPU_FIELD_RDRW		IPU_CPMEM_WORD(0, 94, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SO		IPU_CPMEM_WORD(0, 113, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SLY		IPU_CPMEM_WORD(1, 102, 14)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SLUV		IPU_CPMEM_WORD(1, 128, 14)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define IPU_FIELD_XV		IPU_CPMEM_WORD(0, 0, 10)
 | 
					 | 
				
			||||||
#define IPU_FIELD_YV		IPU_CPMEM_WORD(0, 10, 9)
 | 
					 | 
				
			||||||
#define IPU_FIELD_XB		IPU_CPMEM_WORD(0, 19, 13)
 | 
					 | 
				
			||||||
#define IPU_FIELD_YB		IPU_CPMEM_WORD(0, 32, 12)
 | 
					 | 
				
			||||||
#define IPU_FIELD_NSB_B		IPU_CPMEM_WORD(0, 44, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_CF		IPU_CPMEM_WORD(0, 45, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SX		IPU_CPMEM_WORD(0, 46, 12)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SY		IPU_CPMEM_WORD(0, 58, 11)
 | 
					 | 
				
			||||||
#define IPU_FIELD_NS		IPU_CPMEM_WORD(0, 69, 10)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SDX		IPU_CPMEM_WORD(0, 79, 7)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SM		IPU_CPMEM_WORD(0, 86, 10)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SCC		IPU_CPMEM_WORD(0, 96, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SCE		IPU_CPMEM_WORD(0, 97, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SDY		IPU_CPMEM_WORD(0, 98, 7)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SDRX		IPU_CPMEM_WORD(0, 105, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SDRY		IPU_CPMEM_WORD(0, 106, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_BPP		IPU_CPMEM_WORD(0, 107, 3)
 | 
					 | 
				
			||||||
#define IPU_FIELD_DEC_SEL	IPU_CPMEM_WORD(0, 110, 2)
 | 
					 | 
				
			||||||
#define IPU_FIELD_DIM		IPU_CPMEM_WORD(0, 112, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_BNDM		IPU_CPMEM_WORD(0, 114, 3)
 | 
					 | 
				
			||||||
#define IPU_FIELD_BM		IPU_CPMEM_WORD(0, 117, 2)
 | 
					 | 
				
			||||||
#define IPU_FIELD_ROT		IPU_CPMEM_WORD(0, 119, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_HF		IPU_CPMEM_WORD(0, 120, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_VF		IPU_CPMEM_WORD(0, 121, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_THE		IPU_CPMEM_WORD(0, 122, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_CAP		IPU_CPMEM_WORD(0, 123, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_CAE		IPU_CPMEM_WORD(0, 124, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_FW		IPU_CPMEM_WORD(0, 125, 13)
 | 
					 | 
				
			||||||
#define IPU_FIELD_FH		IPU_CPMEM_WORD(0, 138, 12)
 | 
					 | 
				
			||||||
#define IPU_FIELD_EBA0		IPU_CPMEM_WORD(1, 0, 29)
 | 
					 | 
				
			||||||
#define IPU_FIELD_EBA1		IPU_CPMEM_WORD(1, 29, 29)
 | 
					 | 
				
			||||||
#define IPU_FIELD_ILO		IPU_CPMEM_WORD(1, 58, 20)
 | 
					 | 
				
			||||||
#define IPU_FIELD_NPB		IPU_CPMEM_WORD(1, 78, 7)
 | 
					 | 
				
			||||||
#define IPU_FIELD_PFS		IPU_CPMEM_WORD(1, 85, 4)
 | 
					 | 
				
			||||||
#define IPU_FIELD_ALU		IPU_CPMEM_WORD(1, 89, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_ALBM		IPU_CPMEM_WORD(1, 90, 3)
 | 
					 | 
				
			||||||
#define IPU_FIELD_ID		IPU_CPMEM_WORD(1, 93, 2)
 | 
					 | 
				
			||||||
#define IPU_FIELD_TH		IPU_CPMEM_WORD(1, 95, 7)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SL		IPU_CPMEM_WORD(1, 102, 14)
 | 
					 | 
				
			||||||
#define IPU_FIELD_WID0		IPU_CPMEM_WORD(1, 116, 3)
 | 
					 | 
				
			||||||
#define IPU_FIELD_WID1		IPU_CPMEM_WORD(1, 119, 3)
 | 
					 | 
				
			||||||
#define IPU_FIELD_WID2		IPU_CPMEM_WORD(1, 122, 3)
 | 
					 | 
				
			||||||
#define IPU_FIELD_WID3		IPU_CPMEM_WORD(1, 125, 3)
 | 
					 | 
				
			||||||
#define IPU_FIELD_OFS0		IPU_CPMEM_WORD(1, 128, 5)
 | 
					 | 
				
			||||||
#define IPU_FIELD_OFS1		IPU_CPMEM_WORD(1, 133, 5)
 | 
					 | 
				
			||||||
#define IPU_FIELD_OFS2		IPU_CPMEM_WORD(1, 138, 5)
 | 
					 | 
				
			||||||
#define IPU_FIELD_OFS3		IPU_CPMEM_WORD(1, 143, 5)
 | 
					 | 
				
			||||||
#define IPU_FIELD_SXYS		IPU_CPMEM_WORD(1, 148, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_CRE		IPU_CPMEM_WORD(1, 149, 1)
 | 
					 | 
				
			||||||
#define IPU_FIELD_DEC_SEL2	IPU_CPMEM_WORD(1, 150, 1)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct ipu_cpmem_word {
 | 
					 | 
				
			||||||
	u32 data[5];
 | 
					 | 
				
			||||||
	u32 res[3];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct ipu_ch_param {
 | 
					 | 
				
			||||||
	struct ipu_cpmem_word word[2];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v);
 | 
					 | 
				
			||||||
u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs);
 | 
					 | 
				
			||||||
struct ipu_ch_param __iomem *ipu_get_cpmem(struct ipuv3_channel *channel);
 | 
					 | 
				
			||||||
void ipu_ch_param_dump(struct ipu_ch_param __iomem *p);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void ipu_ch_param_zero(struct ipu_ch_param __iomem *p)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
	void __iomem *base = p;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
 | 
					 | 
				
			||||||
		writel(0, base + i * sizeof(u32));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void ipu_cpmem_set_buffer(struct ipu_ch_param __iomem *p,
 | 
					 | 
				
			||||||
		int bufnum, dma_addr_t buf)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (bufnum)
 | 
					 | 
				
			||||||
		ipu_ch_param_write_field(p, IPU_FIELD_EBA1, buf >> 3);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		ipu_ch_param_write_field(p, IPU_FIELD_EBA0, buf >> 3);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void ipu_cpmem_set_resolution(struct ipu_ch_param __iomem *p,
 | 
					 | 
				
			||||||
		int xres, int yres)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ipu_ch_param_write_field(p, IPU_FIELD_FW, xres - 1);
 | 
					 | 
				
			||||||
	ipu_ch_param_write_field(p, IPU_FIELD_FH, yres - 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void ipu_cpmem_set_stride(struct ipu_ch_param __iomem *p,
 | 
					 | 
				
			||||||
		int stride)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ipu_ch_param_write_field(p, IPU_FIELD_SLY, stride - 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct ipu_rgb {
 | 
					 | 
				
			||||||
	struct fb_bitfield	red;
 | 
					 | 
				
			||||||
	struct fb_bitfield	green;
 | 
					 | 
				
			||||||
	struct fb_bitfield	blue;
 | 
					 | 
				
			||||||
	struct fb_bitfield	transp;
 | 
					 | 
				
			||||||
	int			bits_per_pixel;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct ipu_image {
 | 
					 | 
				
			||||||
	struct v4l2_pix_format pix;
 | 
					 | 
				
			||||||
	struct v4l2_rect rect;
 | 
					 | 
				
			||||||
	dma_addr_t phys;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p,
 | 
					 | 
				
			||||||
		int width);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *,
 | 
					 | 
				
			||||||
		const struct ipu_rgb *rgb);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void ipu_cpmem_interlaced_scan(struct ipu_ch_param *p,
 | 
					 | 
				
			||||||
		int stride)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ipu_ch_param_write_field(p, IPU_FIELD_SO, 1);
 | 
					 | 
				
			||||||
	ipu_ch_param_write_field(p, IPU_FIELD_ILO, stride / 8);
 | 
					 | 
				
			||||||
	ipu_ch_param_write_field(p, IPU_FIELD_SLY, (stride * 2) - 1);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format,
 | 
					 | 
				
			||||||
			int stride, int height);
 | 
					 | 
				
			||||||
void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param __iomem *p,
 | 
					 | 
				
			||||||
				   u32 pixel_format);
 | 
					 | 
				
			||||||
void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p,
 | 
					 | 
				
			||||||
		u32 pixel_format, int stride, int u_offset, int v_offset);
 | 
					 | 
				
			||||||
int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat);
 | 
					 | 
				
			||||||
int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem,
 | 
					 | 
				
			||||||
		struct ipu_image *image);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc);
 | 
					enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc);
 | 
				
			||||||
enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat);
 | 
					enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat);
 | 
				
			||||||
 | 
					enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code);
 | 
				
			||||||
static inline void ipu_cpmem_set_burstsize(struct ipu_ch_param __iomem *p,
 | 
					int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat);
 | 
				
			||||||
		int burstsize)
 | 
					bool ipu_pixelformat_is_planar(u32 pixelformat);
 | 
				
			||||||
{
 | 
					int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
 | 
				
			||||||
	ipu_ch_param_write_field(p, IPU_FIELD_NPB, burstsize - 1);
 | 
								    bool hflip, bool vflip);
 | 
				
			||||||
};
 | 
					int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
 | 
				
			||||||
 | 
								    bool hflip, bool vflip);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ipu_client_platformdata {
 | 
					struct ipu_client_platformdata {
 | 
				
			||||||
	int csi;
 | 
						int csi;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue