mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-09-23 15:15:32 +00:00
Add CCIR interlaced mode for TV decoder. And add pwdn callback function in mxc_camera_platform_data. Signed-off-by: Sammy He <r62914@freescale.com>
226 lines
5.9 KiB
C
226 lines
5.9 KiB
C
/*
|
|
* Copyright 2005-2010 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
|
|
*/
|
|
|
|
/*!
|
|
* @file ipu_csi.c
|
|
*
|
|
* @brief IPU CMOS Sensor interface functions
|
|
*
|
|
* @ingroup IPU
|
|
*/
|
|
#include <linux/types.h>
|
|
#include <linux/init.h>
|
|
#include <linux/io.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/ipu.h>
|
|
|
|
#include "ipu_prv.h"
|
|
#include "ipu_regs.h"
|
|
|
|
static bool gipu_csi_get_mclk_flag = false;
|
|
static int csi_mclk_flag = 0;
|
|
|
|
extern void gpio_sensor_suspend(bool flag);
|
|
|
|
/*!
|
|
* ipu_csi_init_interface
|
|
* Sets initial values for the CSI registers.
|
|
* The width and height of the sensor and the actual frame size will be
|
|
* set to the same values.
|
|
* @param width Sensor width
|
|
* @param height Sensor height
|
|
* @param pixel_fmt pixel format
|
|
* @param sig ipu_csi_signal_cfg_t structure
|
|
*
|
|
* @return 0 for success, -EINVAL for error
|
|
*/
|
|
int32_t
|
|
ipu_csi_init_interface(uint16_t width, uint16_t height, uint32_t pixel_fmt,
|
|
ipu_csi_signal_cfg_t sig)
|
|
{
|
|
uint32_t data = 0;
|
|
|
|
/* Set SENS_DATA_FORMAT bits (8 and 9)
|
|
RGB or YUV444 is 0 which is current value in data so not set explicitly
|
|
This is also the default value if attempts are made to set it to
|
|
something invalid. */
|
|
switch (pixel_fmt) {
|
|
case IPU_PIX_FMT_UYVY:
|
|
data = CSI_SENS_CONF_DATA_FMT_YUV422;
|
|
break;
|
|
case IPU_PIX_FMT_RGB24:
|
|
case IPU_PIX_FMT_BGR24:
|
|
data = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
|
|
break;
|
|
case IPU_PIX_FMT_GENERIC:
|
|
data = CSI_SENS_CONF_DATA_FMT_BAYER;
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* Set the CSI_SENS_CONF register remaining fields */
|
|
data |= sig.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
|
|
sig.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
|
|
sig.Vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
|
|
sig.Hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
|
|
sig.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
|
|
sig.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
|
|
sig.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
|
|
sig.sens_clksrc << CSI_SENS_CONF_SENS_CLKSRC_SHIFT;
|
|
|
|
__raw_writel(data, CSI_SENS_CONF);
|
|
|
|
/* Setup frame size */
|
|
__raw_writel(width | height << 16, CSI_SENS_FRM_SIZE);
|
|
|
|
__raw_writel(width << 16, CSI_FLASH_STROBE_1);
|
|
__raw_writel(height << 16 | 0x22, CSI_FLASH_STROBE_2);
|
|
|
|
/* Set CCIR registers */
|
|
if (sig.clk_mode == IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE) {
|
|
__raw_writel(0x40030, CSI_CCIR_CODE_1);
|
|
__raw_writel(0xFF0000, CSI_CCIR_CODE_3);
|
|
} else if (sig.clk_mode == IPU_CSI_CLK_MODE_CCIR656_INTERLACED) {
|
|
__raw_writel(0xD07DF, CSI_CCIR_CODE_1);
|
|
__raw_writel(0x40596, CSI_CCIR_CODE_2);
|
|
__raw_writel(0xFF0000, CSI_CCIR_CODE_3);
|
|
}
|
|
|
|
dev_dbg(g_ipu_dev, "CSI_SENS_CONF = 0x%08X\n",
|
|
__raw_readl(CSI_SENS_CONF));
|
|
dev_dbg(g_ipu_dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
|
|
__raw_readl(CSI_ACT_FRM_SIZE));
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* ipu_csi_flash_strobe
|
|
*
|
|
* @param flag true to turn on flash strobe
|
|
*
|
|
* @return 0 for success
|
|
*/
|
|
void ipu_csi_flash_strobe(bool flag)
|
|
{
|
|
if (flag == true) {
|
|
__raw_writel(__raw_readl(CSI_FLASH_STROBE_2) | 0x1,
|
|
CSI_FLASH_STROBE_2);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* ipu_csi_enable_mclk
|
|
*
|
|
* @param src enum define which source to control the clk
|
|
* CSI_MCLK_VF CSI_MCLK_ENC CSI_MCLK_RAW CSI_MCLK_I2C
|
|
* @param flag true to enable mclk, false to disable mclk
|
|
* @param wait true to wait 100ms make clock stable, false not wait
|
|
*
|
|
* @return 0 for success
|
|
*/
|
|
int32_t ipu_csi_enable_mclk(int src, bool flag, bool wait)
|
|
{
|
|
if (flag == true) {
|
|
csi_mclk_flag |= src;
|
|
} else {
|
|
csi_mclk_flag &= ~src;
|
|
}
|
|
|
|
if (gipu_csi_get_mclk_flag == flag)
|
|
return 0;
|
|
|
|
if (flag == true) {
|
|
clk_enable(g_ipu_csi_clk);
|
|
if (wait == true)
|
|
msleep(10);
|
|
/*printk("enable csi clock from source %d\n", src); */
|
|
gipu_csi_get_mclk_flag = true;
|
|
} else if (csi_mclk_flag == 0) {
|
|
clk_disable(g_ipu_csi_clk);
|
|
/*printk("disable csi clock from source %d\n", src); */
|
|
gipu_csi_get_mclk_flag = flag;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* ipu_csi_read_mclk_flag
|
|
*
|
|
* @return csi_mclk_flag
|
|
*/
|
|
int ipu_csi_read_mclk_flag(void)
|
|
{
|
|
return csi_mclk_flag;
|
|
}
|
|
|
|
/*!
|
|
* ipu_csi_get_window_size
|
|
*
|
|
* @param width pointer to window width
|
|
* @param height pointer to window height
|
|
* @param dummy dummy for IPUv1 to keep the same interface with IPUv3
|
|
*
|
|
*/
|
|
void ipu_csi_get_window_size(uint32_t *width, uint32_t *height,
|
|
uint32_t dummy)
|
|
{
|
|
uint32_t reg;
|
|
|
|
reg = __raw_readl(CSI_ACT_FRM_SIZE);
|
|
*width = (reg & 0xFFFF) + 1;
|
|
*height = (reg >> 16 & 0xFFFF) + 1;
|
|
}
|
|
|
|
/*!
|
|
* ipu_csi_set_window_size
|
|
*
|
|
* @param width window width
|
|
* @param height window height
|
|
* @param dummy dummy for IPUv1 to keep the same interface with IPUv3
|
|
*
|
|
*/
|
|
void ipu_csi_set_window_size(uint32_t width, uint32_t height, uint32_t dummy)
|
|
{
|
|
__raw_writel((width - 1) | (height - 1) << 16, CSI_ACT_FRM_SIZE);
|
|
}
|
|
|
|
/*!
|
|
* ipu_csi_set_window_pos
|
|
*
|
|
* @param left uint32 window x start
|
|
* @param top uint32 window y start
|
|
* @param dummy dummy for IPUv1 to keep the same interface with IPUv3
|
|
*
|
|
*/
|
|
void ipu_csi_set_window_pos(uint32_t left, uint32_t top, uint32_t dummy)
|
|
{
|
|
uint32_t temp = __raw_readl(CSI_OUT_FRM_CTRL);
|
|
temp &= 0xffff0000;
|
|
temp = top | (left << 8) | temp;
|
|
__raw_writel(temp, CSI_OUT_FRM_CTRL);
|
|
}
|
|
|
|
/* Exported symbols for modules. */
|
|
EXPORT_SYMBOL(ipu_csi_set_window_pos);
|
|
EXPORT_SYMBOL(ipu_csi_set_window_size);
|
|
EXPORT_SYMBOL(ipu_csi_get_window_size);
|
|
EXPORT_SYMBOL(ipu_csi_read_mclk_flag);
|
|
EXPORT_SYMBOL(ipu_csi_enable_mclk);
|
|
EXPORT_SYMBOL(ipu_csi_flash_strobe);
|
|
EXPORT_SYMBOL(ipu_csi_init_interface);
|