summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Weber <rjohnweber@gmail.com>2013-07-01 14:15:27 -0500
committerJohn Weber <rjohnweber@gmail.com>2013-07-17 14:22:37 -0500
commit5d5f87827ec0ef89f65d7831529d4ce8ceba1c59 (patch)
tree99a1ba46d30fdf9285585720f3d89670d0bdc726
parentf548d605a23d56eeadb4ce085121d6323e76074c (diff)
downloadlinux-5d5f87827ec0ef89f65d7831529d4ce8ceba1c59.tar.gz
wandboard: add mipi csi support
Adds MIPI-CSI support for Wandboard Upstream-Status: Inappropriate
-rw-r--r--arch/arm/configs/wandboard_defconfig10
-rw-r--r--arch/arm/mach-mx6/Kconfig1
-rw-r--r--arch/arm/mach-mx6/board-wand.c153
-rw-r--r--drivers/media/video/mxc/capture/sensor_clock.c8
4 files changed, 164 insertions, 8 deletions
diff --git a/arch/arm/configs/wandboard_defconfig b/arch/arm/configs/wandboard_defconfig
index ecdd4a3a4f1e..717ff7374419 100644
--- a/arch/arm/configs/wandboard_defconfig
+++ b/arch/arm/configs/wandboard_defconfig
@@ -32,7 +32,6 @@ CONFIG_ARM_THUMBEE=y
# CONFIG_SWP_EMULATE is not set
CONFIG_ARM_ERRATA_743622=y
CONFIG_ARM_ERRATA_753970=y
-CONFIG_PCIEPORTBUS=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
@@ -88,7 +87,6 @@ CONFIG_DEVTMPFS_MOUNT=y
CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_ATA=y
-CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
# CONFIG_ATA_SFF is not set
CONFIG_NETDEVICES=y
@@ -127,8 +125,11 @@ CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
# CONFIG_RC_CORE is not set
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-# CONFIG_VIDEO_MXC_CAMERA is not set
-CONFIG_USB_VIDEO_CLASS=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_MXC_CAMERA=m
+CONFIG_MXC_CAMERA_OV5640_MIPI=m
+CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m
+CONFIG_USB_VIDEO_CLASS=m
# CONFIG_USB_GSPCA is not set
# CONFIG_RADIO_ADAPTERS is not set
CONFIG_DRM=y
@@ -193,6 +194,7 @@ CONFIG_MXC_SSI=y
# CONFIG_MXC_HWEVENT is not set
CONFIG_MXC_ASRC=y
CONFIG_MXC_GPU_VIV=y
+CONFIG_MXC_MIPI_CSI2=y
CONFIG_EXT4_FS=y
# CONFIG_DNOTIFY is not set
CONFIG_VFAT_FS=y
diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig
index cf783cfec072..c8e81449f25b 100644
--- a/arch/arm/mach-mx6/Kconfig
+++ b/arch/arm/mach-mx6/Kconfig
@@ -303,6 +303,7 @@ config MACH_WANDBOARD
select IMX_HAVE_PLATFORM_VIV_GPU if MXC_GPU_VIV
select IMX_HAVE_PLATFORM_IMX_VPU if MXC_VPU
select IMX_HAVE_PLATFORM_IMX_MIPI_DSI if VIDEO_MXC_IPU_OUTPUT
+ select IMX_HAVE_PLATFORM_IMX_MIPI_CSI2 if MXC_MIPI_CSI2
select IMX_HAVE_PLATFORM_IMX_PCIE if IMX_PCIE
select ZONE_DMA if ION=n
select IMX_HAVE_PLATFORM_AHCI if SATA_AHCI_PLATFORM
diff --git a/arch/arm/mach-mx6/board-wand.c b/arch/arm/mach-mx6/board-wand.c
index e7ce54cf1128..2fa4f21fac25 100644
--- a/arch/arm/mach-mx6/board-wand.c
+++ b/arch/arm/mach-mx6/board-wand.c
@@ -31,7 +31,6 @@
#include <mach/ahci_sata.h>
#include <mach/common.h>
-//#include <mach/devices-common.h>
#include <mach/gpio.h>
#include <mach/iomux-mx6dl.h>
#include <mach/iomux-mx6q.h>
@@ -65,6 +64,10 @@
#define WAND_WL_HOST_WAKE IMX_GPIO_NR(1, 29)
#define WAND_WL_WAKE IMX_GPIO_NR(1, 30)
+#define WAND_MIPICSI_PWN IMX_GPIO_NR(1, 6)
+#define WAND_MIPICSI_RESET IMX_GPIO_NR(4, 14)
+
+
/* Syntactic sugar for pad configuration */
#define IMX6_SETUP_PAD(p) \
if (cpu_is_mx6q()) \
@@ -438,10 +441,10 @@ static __init void wand_init_usb(void) {
static struct imx_ipuv3_platform_data wand_ipu_data[] = {
{
.rev = 4,
- .csi_clk[0] = "ccm_clk0",
+ .csi_clk[0] = "clko2_clk",
}, {
.rev = 4,
- .csi_clk[0] = "ccm_clk0",
+ .csi_clk[0] = "clko2_clk",
},
};
@@ -510,6 +513,132 @@ static void wand_init_hdmi(void) {
mxc_iomux_set_gpr_register(0, 0, 1, 1);
}
+/****************************************************************************
+ *
+ * MIPI CSI
+ *
+ ****************************************************************************/
+static void wand_mipi_sensor_io_init(void) {
+
+ struct clk *mipi_csi_mclk;
+
+ IMX6_SETUP_PAD( GPIO_3__CCM_CLKO2 ); /* Camera clock */
+ IMX6_SETUP_PAD( KEY_COL4__GPIO_4_14 ); /* Camera reset */
+ IMX6_SETUP_PAD( GPIO_6__GPIO_1_6 ); /* Camera power down */
+
+ pr_debug("%s\n", __func__);
+
+ gpio_request(WAND_MIPICSI_RESET, "cam-reset");
+ gpio_direction_output(WAND_MIPICSI_RESET, 1);
+
+ gpio_request(WAND_MIPICSI_PWN, "cam-pwdn");
+ gpio_direction_output(WAND_MIPICSI_PWN, 1);
+
+ int rate;
+
+ /* Master clock for the sensor */
+ mipi_csi_mclk = clk_get(NULL, "clko2_clk");
+ if (IS_ERR(mipi_csi_mclk)) {
+ pr_err("can't get CLKO2 clock.\n");
+ return PTR_ERR(mipi_csi_mclk);
+ }
+
+ rate = clk_round_rate(mipi_csi_mclk, 24000000);
+ clk_set_rate(mipi_csi_mclk, rate);
+ clk_enable(mipi_csi_mclk);
+
+ msleep(5);
+ /* Power up */
+ gpio_set_value(WAND_MIPICSI_PWN, 0);
+ msleep(5);
+ /* Reset on */
+ gpio_set_value(WAND_MIPICSI_RESET, 0);
+ msleep(1);
+ /* Reset off */
+ gpio_set_value(WAND_MIPICSI_RESET, 1);
+ msleep(5);
+ /* power down */
+ gpio_set_value(WAND_MIPICSI_PWN, 1);
+
+ /* For MX6Q:
+ * GPR1 bit19 and bit20 meaning:
+ * Bit19: 0 - Enable mipi to IPU1 CSI0
+ * virtual channel is fixed to 0
+ * 1 - Enable parallel interface to IPU1 CSI0
+ * Bit20: 0 - Enable mipi to IPU2 CSI1
+ * virtual channel is fixed to 3
+ * 1 - Enable parallel interface to IPU2 CSI1
+ * IPU1 CSI1 directly connect to mipi csi2,
+ * virtual channel is fixed to 1
+ * IPU2 CSI0 directly connect to mipi csi2,
+ * virtual channel is fixed to 2
+ *
+ * For MX6DL:
+ * GPR13 bit 0-2 IPU_CSI0_MUX
+ * 000 MIPI_CSI0
+ * 100 IPU CSI0
+ */
+
+ if (cpu_is_mx6q())
+ mxc_iomux_set_gpr_register(1, 19, 1, 1);
+ else if (cpu_is_mx6dl())
+ mxc_iomux_set_gpr_register(13, 0, 3, 0);
+}
+
+static void wand_mipi_powerdown(int powerdown)
+{
+ pr_debug("%s: powerdown=%d\n", __func__,powerdown);
+
+ if (powerdown)
+ gpio_set_value(WAND_MIPICSI_PWN, 1); /* Power off */
+ else
+ gpio_set_value(WAND_MIPICSI_PWN, 0); /* Power on */
+
+ msleep(2);
+}
+
+/* Platform data for CSI sensor driver, passed to driver
+ through i2c platform data */
+static struct fsl_mxc_camera_platform_data wand_mipi_csi2_data = {
+ .mclk = 24000000,
+ .mclk_source = 0,
+ .csi = 0,
+ .io_init = wand_mipi_sensor_io_init,
+ .pwdn = wand_mipi_powerdown,
+};
+
+/* TODO - reorg code so that adding i2c board info is done all in one
+ step at init. This makes adding I2C devices easier */
+static struct i2c_board_info wand_mipi_csi_i2c_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("ov5640_mipi", 0x3C),
+ .platform_data = (void*)&wand_mipi_csi2_data,
+ },
+};
+
+/* Platform data for MIPI CSI init */
+static struct mipi_csi2_platform_data wand_mipi_csi2_platform_data = {
+ .ipu_id = 0,
+ .csi_id = 0,
+ .v_channel = 0,
+ .lanes = 2,
+ .dphy_clk = "mipi_pllref_clk",
+ .pixel_clk = "emi_clk",
+};
+
+/* Wandboard MIPI CSI init function */
+static void __init wand_init_mipi_csi(void){
+
+ pr_debug("%s\n", __func__);
+
+ /* Add CSI2 */
+ imx6q_add_mipi_csi2(&wand_mipi_csi2_platform_data);
+
+ /* Register MIPI CSI I2C board info. This sits on I2C2, which
+ is i2c device index 1 */
+ i2c_register_board_info(1, wand_mipi_csi_i2c_board_info,
+ ARRAY_SIZE(wand_mipi_csi_i2c_board_info));
+}
/****************************************************************************
*
@@ -1024,7 +1153,19 @@ static void __init wand_reserve(void) {
*
*****************************************************************************/
+static struct fsl_mxc_capture_platform_data capture_data[] = {
+#if defined(CONFIG_MXC_CAMERA_OV5640_MIPI) || defined(CONFIG_MXC_CAMERA_OV5640_MIPI_MODULE)
+ {
+ .ipu = 0,
+ .csi = 0,
+ .mclk_source = 0,
+ .is_mipi = 1,
+ },
+#endif
+};
+
static void __init wand_board_init(void) {
+ int i;
wand_init_dma();
wand_init_uart();
wand_init_sd();
@@ -1034,6 +1175,12 @@ static void __init wand_board_init(void) {
wand_init_usb();
wand_init_ipu();
wand_init_hdmi();
+ for (i = 0; i < ARRAY_SIZE(capture_data); i++) {
+ if (!cpu_is_mx6q())
+ capture_data[i].ipu = 0;
+ imx6q_add_v4l2_capture(i, &capture_data[i]);
+ }
+ wand_init_mipi_csi();
wand_init_lcd();
wand_init_wifi();
wand_init_bluetooth();
diff --git a/drivers/media/video/mxc/capture/sensor_clock.c b/drivers/media/video/mxc/capture/sensor_clock.c
index 150659fa5dc0..ddf2a563abb7 100644
--- a/drivers/media/video/mxc/capture/sensor_clock.c
+++ b/drivers/media/video/mxc/capture/sensor_clock.c
@@ -39,6 +39,9 @@ void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi)
uint32_t freq = 0;
char *mclk;
+ /*FIXME remove this comment in production */
+ pr_debug("%s: entered\n",__func__);
+
if (cpu_is_mx53()) {
if (csi == 0)
mclk = "ssi_ext1_clk";
@@ -48,8 +51,11 @@ void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi)
}
} else if (cpu_is_mx6q() || cpu_is_mx6dl()) {
if (csi == 0) {
- if (machine_is_mx6q_sabrelite())
+ if (machine_is_mx6q_sabrelite() ||
+ machine_is_wandboard()) {
+ pr_debug("%s: Clock is clko2_clk\n",__func__);
mclk = "clko2_clk";
+ }
else
mclk = "clko_clk";
} else {