All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Add camera support for i.MX27 Baseboards
@ 2010-08-03  9:20 Michael Grzeschik
  2010-08-03  9:20 ` [PATCH 1/2] ARM: i.MX27 pcm970: Add camera support Michael Grzeschik
  2010-08-03  9:20 ` [PATCH 2/2] ARM: i.MX27 pca100: " Michael Grzeschik
  0 siblings, 2 replies; 13+ messages in thread
From: Michael Grzeschik @ 2010-08-03  9:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hey everyone,

this baseboard code adds support for the cameras mt9m001,
mt9v022 and mt9m131/mt9m111.

Thanks,
Michael

Michael Grzeschik (2):
  ARM: i.MX27 pcm970: Add camera support
  ARM: i.MX27 pca100: Add camera support

 arch/arm/mach-imx/mach-pca100.c      |  135 +++++++++++++++++++++++++++-
 arch/arm/mach-imx/pcm970-baseboard.c |  165 ++++++++++++++++++++++++++++++++++
 2 files changed, 298 insertions(+), 2 deletions(-)

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/2] ARM: i.MX27 pcm970: Add camera support
  2010-08-03  9:20 [PATCH 0/2] Add camera support for i.MX27 Baseboards Michael Grzeschik
@ 2010-08-03  9:20 ` Michael Grzeschik
  2010-08-11  7:38   ` [PATCH v2] " Michael Grzeschik
  2010-08-03  9:20 ` [PATCH 2/2] ARM: i.MX27 pca100: " Michael Grzeschik
  1 sibling, 1 reply; 13+ messages in thread
From: Michael Grzeschik @ 2010-08-03  9:20 UTC (permalink / raw)
  To: linux-arm-kernel

Adds the glue code for the pcm970 baseboard. It has a power regulator
which is registered first and instrumented in an late_initcall to turn
on the power for the camera device.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 arch/arm/mach-imx/pcm970-baseboard.c |  165 ++++++++++++++++++++++++++++++++++
 1 files changed, 165 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-imx/pcm970-baseboard.c b/arch/arm/mach-imx/pcm970-baseboard.c
index f490a40..1931e5d 100644
--- a/arch/arm/mach-imx/pcm970-baseboard.c
+++ b/arch/arm/mach-imx/pcm970-baseboard.c
@@ -20,15 +20,23 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/can/platform/sja1000.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <media/soc_camera.h>
 
 #include <mach/common.h>
 #include <mach/iomux-mx27.h>
 #include <mach/imxfb.h>
 #include <mach/hardware.h>
 #include <mach/mmc.h>
+#include <mach/mx2_cam.h>
+#include <mach/i2c.h>
 
+#include "devices-imx27.h"
 #include "devices.h"
 
 static int pcm970_pins[] = {
@@ -215,6 +223,104 @@ static struct platform_device pcm970_sja1000 = {
 	.num_resources = ARRAY_SIZE(pcm970_sja1000_resources),
 };
 
+/* count of GPIOs that are occupied by the CPU itself */
+#define MAX_INTERNAL_GPIO 192
+
+static unsigned long pcm970_camera_query_bus_param(struct soc_camera_link *icl)
+{
+	return SOCAM_DATAWIDTH_8;
+}
+
+static int pcm970_camera_set_bus_param(struct soc_camera_link *icl,
+		unsigned long flags)
+{
+	return 0;
+}
+
+static struct pca953x_platform_data pca9536_data = {
+	.gpio_base      = MAX_INTERNAL_GPIO,
+};
+
+/* Board I2C devices. */
+static struct i2c_board_info __initdata pcm970_i2c_devices[] = {
+	{
+		/* Must initialize before the camera(s) */
+		I2C_BOARD_INFO("pca953x", 0x41),
+		.type = "pca9536",
+		.platform_data = &pca9536_data,
+	},
+};
+
+static struct i2c_board_info __initdata pcm970_camera_mt9m001 = {
+		I2C_BOARD_INFO("mt9m001", 0x5d),
+		.type = "mt9m001",
+};
+
+static struct i2c_board_info __initdata pcm970_camera_mt9v022 = {
+		I2C_BOARD_INFO("mt9v022", 0x48),
+		.type = "mt9v022",
+};
+
+static struct i2c_board_info __initdata pcm970_camera_mt9m131 = {
+		I2C_BOARD_INFO("mt9m111", 0x48),
+		.type = "mt9m111",
+};
+
+static struct soc_camera_link iclink_mt9m001 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pcm970_camera_mt9m001,
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9m001",
+	.query_bus_param = pcm970_camera_query_bus_param,
+	.set_bus_param	= pcm970_camera_set_bus_param,
+};
+
+static struct soc_camera_link iclink_mt9v022 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pcm970_camera_mt9v022,
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9v022",
+	.query_bus_param = pcm970_camera_query_bus_param,
+	.set_bus_param	= pcm970_camera_set_bus_param,
+};
+
+static struct soc_camera_link iclink_mt9m131 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pcm970_camera_mt9m131,
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9m111",
+	.query_bus_param = pcm970_camera_query_bus_param,
+	.set_bus_param	= pcm970_camera_set_bus_param,
+};
+
+static struct imxi2c_platform_data pcm038_i2c_0_data = {
+	.bitrate = 10000,
+};
+
+static struct platform_device pcm970_mt9m001 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &iclink_mt9m001,
+	},
+};
+
+static struct platform_device pcm970_mt9v022 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &iclink_mt9v022,
+	},
+};
+
+static struct platform_device pcm970_mt9m131 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 2,
+	.dev	= {
+		.platform_data = &iclink_mt9m131,
+	},
+};
+
 /*
  * system init for baseboard usage. Will be called by pcm038 init.
  *
@@ -230,4 +336,63 @@ void __init pcm970_baseboard_init(void)
 	mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN);
 	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
 	platform_device_register(&pcm970_sja1000);
+
+	i2c_register_board_info(0, pcm970_i2c_devices,
+		ARRAY_SIZE(pcm970_i2c_devices));
+
+	platform_device_register(&pcm970_mt9m001);
+	platform_device_register(&pcm970_mt9v022);
+	platform_device_register(&pcm970_mt9m131);
+
+	/* the first i2c master is used for devices on the baseboard */
+	imx27_add_i2c_imx0(&pcm038_i2c_0_data);
+}
+
+/*
+ * Ok, we have to deal with several situations here. We connect
+ * 10bit image sensors to a 8bit interface and we must make sure
+ * that the upper 8bit from the sensor are connected to the image
+ * interface. Some sensors have a i2c GPIO expander which controls
+ * a bus switch to fixup the routing. Mapper boards >= 1285.2 do
+ * the fixup without the need of a gpio switch.
+ * Set this parameter to '1' to use a camera with gpio switch on a
+ * newer mapper board to prevent the fixup being done twice.
+ */
+static int use_camera_gpio;
+core_param(use_camera_gpio, use_camera_gpio, int, 0444);
+
+struct mx2_camera_platform_data pcm970_camera = {
+	.clk  = 26600000,
+	.flags = MX2_CAMERA_HSYNC_HIGH | MX2_CAMERA_GATED_CLOCK |
+		MX2_CAMERA_PACK_DIR_MSB,
+};
+
+static int __init pcm970_baseboard_init_late(void)
+{
+	int ret;
+	struct regulator *regulator;
+
+	if (!machine_is_pcm038())
+		return 0;
+
+	regulator = regulator_get(NULL, "imx_cam_vcc");
+	if (IS_ERR(regulator))
+		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
+	else
+		regulator_enable(regulator);
+
+	/* Be sure this registers after the regulators */
+	mxc_register_device(&mx27_camera_device, &pcm970_camera);
+
+	ret = gpio_request(MAX_INTERNAL_GPIO, "camera");
+	if (!ret) {
+		printk(KERN_INFO "pcm970 camera: Found GPIO expander on camera, %susing it\n",
+				use_camera_gpio ? "" : "not ");
+		gpio_direction_output(MAX_INTERNAL_GPIO, !!use_camera_gpio);
+	} else
+		printk(KERN_INFO "pcm970 camera: No GPIO expander on camera found\n");
+
+	return 0;
 }
+late_initcall(pcm970_baseboard_init_late);
+
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/2] ARM: i.MX27 pca100: Add camera support
  2010-08-03  9:20 [PATCH 0/2] Add camera support for i.MX27 Baseboards Michael Grzeschik
  2010-08-03  9:20 ` [PATCH 1/2] ARM: i.MX27 pcm970: Add camera support Michael Grzeschik
@ 2010-08-03  9:20 ` Michael Grzeschik
  1 sibling, 0 replies; 13+ messages in thread
From: Michael Grzeschik @ 2010-08-03  9:20 UTC (permalink / raw)
  To: linux-arm-kernel

The glue code for the pca100 to implement the serial LVDS camera. Based
on the camera glue code for pcm970.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 arch/arm/mach-imx/mach-pca100.c |  135 ++++++++++++++++++++++++++++++++++++++-
 1 files changed, 133 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index a389d11..30a4c02 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -31,6 +31,10 @@
 #include <linux/usb/ulpi.h>
 #include <linux/fsl_devices.h>
 
+#include <media/soc_camera.h>
+
+#include <mach/mx2_cam.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/common.h>
@@ -160,6 +164,19 @@ static int pca100_pins[] = {
 	GPIO_PORTC | 31 | GPIO_GPIO | GPIO_IN, /* GPIO0_IRQ */
 	GPIO_PORTC | 25 | GPIO_GPIO | GPIO_IN, /* GPIO1_IRQ */
 	GPIO_PORTE | 5 | GPIO_GPIO | GPIO_IN, /* GPIO2_IRQ */
+	/* Camera */
+	PB10_PF_CSI_D0,
+	PB11_PF_CSI_D1,
+	PB12_PF_CSI_D2,
+	PB13_PF_CSI_D3,
+	PB14_PF_CSI_D4,
+	PB15_PF_CSI_MCLK,
+	PB16_PF_CSI_PIXCLK,
+	PB17_PF_CSI_D5,
+	PB18_PF_CSI_D6,
+	PB19_PF_CSI_D7,
+	PB20_PF_CSI_VSYNC,
+	PB21_PF_CSI_HSYNC,
 };
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
@@ -188,6 +205,20 @@ static struct at24_platform_data board_eeprom = {
 	.flags = AT24_FLAG_ADDR16,
 };
 
+/* count of GPIOs that are occupied by the CPU itself */
+#define MAX_INTERNAL_GPIO 192
+
+static unsigned long pbaa01_camera_query_bus_param(struct soc_camera_link *icl)
+{
+	return SOCAM_DATAWIDTH_8;
+}
+
+static int pbaa01_camera_set_bus_param(struct soc_camera_link *icl,
+		unsigned long flags)
+{
+	return 0;
+}
+
 static struct i2c_board_info pca100_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
@@ -316,6 +347,91 @@ static struct fsl_usb2_platform_data otg_device_pdata = {
 
 static int otg_mode_host;
 
+static struct i2c_board_info __initdata pbaa01_camera_mt9m001 = {
+		I2C_BOARD_INFO("mt9m001", 0x5d),
+		.type = "mt9m001",
+};
+
+static struct i2c_board_info __initdata pbaa01_camera_mt9v022 = {
+		I2C_BOARD_INFO("mt9v022", 0x48),
+		.type = "mt9v022",
+};
+
+static struct i2c_board_info __initdata pbaa01_camera_mt9m131 = {
+		I2C_BOARD_INFO("mt9m111", 0x48),
+		.type = "mt9m111",
+};
+
+static struct soc_camera_link iclink_mt9m001 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pbaa01_camera_mt9m001,
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9m001",
+	.query_bus_param = pbaa01_camera_query_bus_param,
+	.set_bus_param	= pbaa01_camera_set_bus_param,
+};
+
+static struct soc_camera_link iclink_mt9v022 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pbaa01_camera_mt9v022,
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9v022",
+	.query_bus_param = pbaa01_camera_query_bus_param,
+	.set_bus_param	= pbaa01_camera_set_bus_param,
+};
+
+static struct soc_camera_link iclink_mt9m131 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pbaa01_camera_mt9m131,
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9m111",
+	.query_bus_param = pbaa01_camera_query_bus_param,
+	.set_bus_param	= pbaa01_camera_set_bus_param,
+};
+
+static struct platform_device pca100_mt9m001 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &iclink_mt9m001,
+	},
+};
+
+static struct platform_device pca100_mt9v022 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &iclink_mt9v022,
+	},
+};
+
+static struct platform_device pca100_mt9m131 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 2,
+	.dev	= {
+		.platform_data = &iclink_mt9m131,
+	},
+};
+
+/*
+ * Ok, we have to deal with several situations here. We connect
+ * 10bit image sensors to a 8bit interface and we must make sure
+ * that the upper 8bit from the sensor are connected to the image
+ * interface. Some sensors have a i2c GPIO expander which controls
+ * a bus switch to fixup the routing. Mapper boards >= 1285.2 do
+ * the fixup without the need of a gpio switch.
+ * Set this parameter to '1' to use a camera with gpio switch on a
+ * newer mapper board to prevent the fixup being done twice.
+ */
+static int use_camera_gpio;
+/* core_param(use_camera_gpio, use_camera_gpio, int, 0444); */
+
+struct mx2_camera_platform_data pca100_camera = {
+	.clk  = 26600000,
+	.flags = MX2_CAMERA_HSYNC_HIGH | MX2_CAMERA_GATED_CLOCK |
+		MX2_CAMERA_PACK_DIR_MSB,
+};
+
 static int __init pca100_otg_mode(char *options)
 {
 	if (!strcmp(options, "host"))
@@ -398,10 +514,14 @@ static void __init pca100_init(void)
 	imx27_add_mxc_nand(&pca100_nand_board_info);
 
 	/* only the i2c master 1 is used on this CPU card */
-	i2c_register_board_info(1, pca100_i2c_devices,
+	i2c_register_board_info(0, pca100_i2c_devices,
 				ARRAY_SIZE(pca100_i2c_devices));
 
-	imx27_add_i2c_imx1(&pca100_i2c1_data);
+	platform_device_register(&pca100_mt9m001);
+	platform_device_register(&pca100_mt9v022);
+	platform_device_register(&pca100_mt9m131);
+
+	imx27_add_i2c_imx0(&pca100_i2c1_data);
 
 #if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
 	mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_IN);
@@ -436,6 +556,17 @@ static void __init pca100_init(void)
 
 	mxc_register_device(&mxc_fb_device, &pca100_fb_data);
 
+	mxc_register_device(&mx27_camera_device, &pca100_camera);
+
+	ret = gpio_request(MAX_INTERNAL_GPIO, "camera");
+	if (!ret) {
+		printk(KERN_INFO "pca100 camera: Found GPIO expander on camera, %susing it\n",
+				use_camera_gpio ? "" : "not ");
+		gpio_direction_output(MAX_INTERNAL_GPIO, !!use_camera_gpio);
+	} else
+		printk(KERN_INFO "pca100 camera: No GPIO expander on camera found\n");
+
+
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
 }
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2] ARM: i.MX27 pcm970: Add camera support
  2010-08-03  9:20 ` [PATCH 1/2] ARM: i.MX27 pcm970: Add camera support Michael Grzeschik
@ 2010-08-11  7:38   ` Michael Grzeschik
  2010-08-11 20:10     ` Guennadi Liakhovetski
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Grzeschik @ 2010-08-11  7:38 UTC (permalink / raw)
  To: linux-arm-kernel

Adds the glue code for the pcm970 baseboard. It has a power regulator
which is registered first and instrumented in the power hook of
soc_camera_link to turn on the power for the camera device.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 arch/arm/mach-imx/pcm970-baseboard.c |  184 ++++++++++++++++++++++++++++++++++
 1 files changed, 184 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-imx/pcm970-baseboard.c b/arch/arm/mach-imx/pcm970-baseboard.c
index f490a40..1034c92 100644
--- a/arch/arm/mach-imx/pcm970-baseboard.c
+++ b/arch/arm/mach-imx/pcm970-baseboard.c
@@ -20,15 +20,23 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/can/platform/sja1000.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <media/soc_camera.h>
 
 #include <mach/common.h>
 #include <mach/iomux-mx27.h>
 #include <mach/imxfb.h>
 #include <mach/hardware.h>
 #include <mach/mmc.h>
+#include <mach/mx2_cam.h>
+#include <mach/i2c.h>
 
+#include "devices-imx27.h"
 #include "devices.h"
 
 static int pcm970_pins[] = {
@@ -215,6 +223,130 @@ static struct platform_device pcm970_sja1000 = {
 	.num_resources = ARRAY_SIZE(pcm970_sja1000_resources),
 };
 
+/* count of GPIOs that are occupied by the CPU itself */
+#define MAX_INTERNAL_GPIO 192
+
+static unsigned long pcm970_camera_query_bus_param(struct soc_camera_link *icl)
+{
+	return SOCAM_DATAWIDTH_8;
+}
+
+static int pcm970_camera_set_bus_param(struct soc_camera_link *icl,
+		unsigned long flags)
+{
+	return 0;
+}
+
+static int pcm970_camera_power_bus(struct device *dev, int toggle)
+{
+	struct regulator *regulator;
+
+	regulator = regulator_get(NULL, "imx_cam_vcc");
+	if (IS_ERR(regulator)) {
+		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
+		return -ENODEV;
+	} else {
+		if (toggle)
+			regulator_enable(regulator);
+		else
+			regulator_disable(regulator);
+	}
+	return 0;
+}
+
+static struct pca953x_platform_data pca9536_data = {
+	.gpio_base      = MAX_INTERNAL_GPIO,
+};
+
+/* Board I2C devices. */
+static struct i2c_board_info __initdata pcm970_i2c_devices[] = {
+	{
+		/* Must initialize before the camera(s) */
+		I2C_BOARD_INFO("pca953x", 0x41),
+		.type = "pca9536",
+		.platform_data = &pca9536_data,
+	},
+};
+
+static struct i2c_board_info __initdata pcm970_camera_mt9m001 = {
+		I2C_BOARD_INFO("mt9m001", 0x5d),
+		.type = "mt9m001",
+};
+
+static struct i2c_board_info __initdata pcm970_camera_mt9v022 = {
+		I2C_BOARD_INFO("mt9v022", 0x48),
+		.type = "mt9v022",
+};
+
+static struct i2c_board_info __initdata pcm970_camera_mt9m131 = {
+		I2C_BOARD_INFO("mt9m111", 0x48),
+		.type = "mt9m111",
+};
+
+static struct soc_camera_link iclink_mt9m001 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pcm970_camera_mt9m001,
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9m001",
+	.power		= pcm970_camera_power_bus,
+	.query_bus_param = pcm970_camera_query_bus_param,
+	.set_bus_param	= pcm970_camera_set_bus_param,
+};
+
+static struct soc_camera_link iclink_mt9v022 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pcm970_camera_mt9v022,
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9v022",
+	.power		= pcm970_camera_power_bus,
+	.query_bus_param = pcm970_camera_query_bus_param,
+	.set_bus_param	= pcm970_camera_set_bus_param,
+};
+
+static struct soc_camera_link iclink_mt9m131 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pcm970_camera_mt9m131,
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9m111",
+	.power		= pcm970_camera_power_bus,
+	.query_bus_param = pcm970_camera_query_bus_param,
+	.set_bus_param	= pcm970_camera_set_bus_param,
+};
+
+static struct imxi2c_platform_data pcm038_i2c_0_data = {
+	.bitrate = 10000,
+};
+
+static struct platform_device pcm970_mt9m001 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &iclink_mt9m001,
+	},
+};
+
+static struct platform_device pcm970_mt9v022 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &iclink_mt9v022,
+	},
+};
+
+static struct platform_device pcm970_mt9m131 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 2,
+	.dev	= {
+		.platform_data = &iclink_mt9m131,
+	},
+};
+
+struct mx2_camera_platform_data pcm970_camera = {
+	.clk  = 26600000,
+	.flags = MX2_CAMERA_HSYNC_HIGH | MX2_CAMERA_GATED_CLOCK |
+		MX2_CAMERA_PACK_DIR_MSB,
+};
+
 /*
  * system init for baseboard usage. Will be called by pcm038 init.
  *
@@ -230,4 +362,56 @@ void __init pcm970_baseboard_init(void)
 	mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN);
 	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
 	platform_device_register(&pcm970_sja1000);
+
+	i2c_register_board_info(0, pcm970_i2c_devices,
+		ARRAY_SIZE(pcm970_i2c_devices));
+
+	platform_device_register(&pcm970_mt9m001);
+	platform_device_register(&pcm970_mt9v022);
+	platform_device_register(&pcm970_mt9m131);
+
+	/* the first i2c master is used for devices on the baseboard */
+	imx27_add_i2c_imx0(&pcm038_i2c_0_data);
+
+	mxc_register_device(&mx27_camera_device, &pcm970_camera);
 }
+
+/*
+ * Ok, we have to deal with several situations here. We connect
+ * 10bit image sensors to a 8bit interface and we must make sure
+ * that the upper 8bit from the sensor are connected to the image
+ * interface. Some sensors have a i2c GPIO expander which controls
+ * a bus switch to fixup the routing. Mapper boards >= 1285.2 do
+ * the fixup without the need of a gpio switch.
+ * Set this parameter to '1' to use a camera with gpio switch on a
+ * newer mapper board to prevent the fixup being done twice.
+ */
+static int use_camera_gpio;
+core_param(use_camera_gpio, use_camera_gpio, int, 0444);
+
+static int __init pcm970_baseboard_init_late(void)
+{
+	int ret;
+	struct regulator *regulator;
+
+	if (!machine_is_pcm038())
+		return 0;
+
+	regulator = regulator_get(NULL, "imx_cam_vcc");
+	if (IS_ERR(regulator))
+		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
+	else
+		regulator_enable(regulator);
+
+	ret = gpio_request(MAX_INTERNAL_GPIO, "camera");
+	if (!ret) {
+		printk(KERN_INFO "pcm970 camera: Found GPIO expander on camera, %susing it\n",
+				use_camera_gpio ? "" : "not ");
+		gpio_direction_output(MAX_INTERNAL_GPIO, !!use_camera_gpio);
+	} else
+		printk(KERN_INFO "pcm970 camera: No GPIO expander on camera found\n");
+
+	return 0;
+}
+late_initcall(pcm970_baseboard_init_late);
+
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2] ARM: i.MX27 pcm970: Add camera support
  2010-08-11  7:38   ` [PATCH v2] " Michael Grzeschik
@ 2010-08-11 20:10     ` Guennadi Liakhovetski
  2010-08-11 21:07       ` Michael Grzeschik
  0 siblings, 1 reply; 13+ messages in thread
From: Guennadi Liakhovetski @ 2010-08-11 20:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 11 Aug 2010, Michael Grzeschik wrote:

> Adds the glue code for the pcm970 baseboard. It has a power regulator
> which is registered first and instrumented in the power hook of
> soc_camera_link to turn on the power for the camera device.

Ok, this looks better now, with this you don't have to patch the driver 
any more. But - are you sure you really need both - the power callback and 
the lateinitcall doing the same - requesting the regulator and enabling 
it. I think, just the power callback should suffice.

Thanks
Guennadi

> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> ---
>  arch/arm/mach-imx/pcm970-baseboard.c |  184 ++++++++++++++++++++++++++++++++++
>  1 files changed, 184 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/pcm970-baseboard.c b/arch/arm/mach-imx/pcm970-baseboard.c
> index f490a40..1034c92 100644
> --- a/arch/arm/mach-imx/pcm970-baseboard.c
> +++ b/arch/arm/mach-imx/pcm970-baseboard.c
> @@ -20,15 +20,23 @@
>  #include <linux/irq.h>
>  #include <linux/platform_device.h>
>  #include <linux/can/platform/sja1000.h>
> +#include <linux/i2c/pca953x.h>
> +#include <linux/regulator/consumer.h>
>  
>  #include <asm/mach/arch.h>
> +#include <asm/mach-types.h>
> +
> +#include <media/soc_camera.h>
>  
>  #include <mach/common.h>
>  #include <mach/iomux-mx27.h>
>  #include <mach/imxfb.h>
>  #include <mach/hardware.h>
>  #include <mach/mmc.h>
> +#include <mach/mx2_cam.h>
> +#include <mach/i2c.h>
>  
> +#include "devices-imx27.h"
>  #include "devices.h"
>  
>  static int pcm970_pins[] = {
> @@ -215,6 +223,130 @@ static struct platform_device pcm970_sja1000 = {
>  	.num_resources = ARRAY_SIZE(pcm970_sja1000_resources),
>  };
>  
> +/* count of GPIOs that are occupied by the CPU itself */
> +#define MAX_INTERNAL_GPIO 192
> +
> +static unsigned long pcm970_camera_query_bus_param(struct soc_camera_link *icl)
> +{
> +	return SOCAM_DATAWIDTH_8;
> +}
> +
> +static int pcm970_camera_set_bus_param(struct soc_camera_link *icl,
> +		unsigned long flags)
> +{
> +	return 0;
> +}
> +
> +static int pcm970_camera_power_bus(struct device *dev, int toggle)
> +{
> +	struct regulator *regulator;
> +
> +	regulator = regulator_get(NULL, "imx_cam_vcc");
> +	if (IS_ERR(regulator)) {
> +		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
> +		return -ENODEV;
> +	} else {
> +		if (toggle)
> +			regulator_enable(regulator);
> +		else
> +			regulator_disable(regulator);
> +	}
> +	return 0;
> +}
> +
> +static struct pca953x_platform_data pca9536_data = {
> +	.gpio_base      = MAX_INTERNAL_GPIO,
> +};
> +
> +/* Board I2C devices. */
> +static struct i2c_board_info __initdata pcm970_i2c_devices[] = {
> +	{
> +		/* Must initialize before the camera(s) */
> +		I2C_BOARD_INFO("pca953x", 0x41),
> +		.type = "pca9536",
> +		.platform_data = &pca9536_data,
> +	},
> +};
> +
> +static struct i2c_board_info __initdata pcm970_camera_mt9m001 = {
> +		I2C_BOARD_INFO("mt9m001", 0x5d),
> +		.type = "mt9m001",
> +};
> +
> +static struct i2c_board_info __initdata pcm970_camera_mt9v022 = {
> +		I2C_BOARD_INFO("mt9v022", 0x48),
> +		.type = "mt9v022",
> +};
> +
> +static struct i2c_board_info __initdata pcm970_camera_mt9m131 = {
> +		I2C_BOARD_INFO("mt9m111", 0x48),
> +		.type = "mt9m111",
> +};
> +
> +static struct soc_camera_link iclink_mt9m001 = {
> +	.bus_id		= 0,		/* Must match with the camera ID */
> +	.board_info	= &pcm970_camera_mt9m001,
> +	.i2c_adapter_id	= 0,
> +	.module_name	= "mt9m001",
> +	.power		= pcm970_camera_power_bus,
> +	.query_bus_param = pcm970_camera_query_bus_param,
> +	.set_bus_param	= pcm970_camera_set_bus_param,
> +};
> +
> +static struct soc_camera_link iclink_mt9v022 = {
> +	.bus_id		= 0,		/* Must match with the camera ID */
> +	.board_info	= &pcm970_camera_mt9v022,
> +	.i2c_adapter_id	= 0,
> +	.module_name	= "mt9v022",
> +	.power		= pcm970_camera_power_bus,
> +	.query_bus_param = pcm970_camera_query_bus_param,
> +	.set_bus_param	= pcm970_camera_set_bus_param,
> +};
> +
> +static struct soc_camera_link iclink_mt9m131 = {
> +	.bus_id		= 0,		/* Must match with the camera ID */
> +	.board_info	= &pcm970_camera_mt9m131,
> +	.i2c_adapter_id	= 0,
> +	.module_name	= "mt9m111",
> +	.power		= pcm970_camera_power_bus,
> +	.query_bus_param = pcm970_camera_query_bus_param,
> +	.set_bus_param	= pcm970_camera_set_bus_param,
> +};
> +
> +static struct imxi2c_platform_data pcm038_i2c_0_data = {
> +	.bitrate = 10000,
> +};
> +
> +static struct platform_device pcm970_mt9m001 = {
> +	.name	= "soc-camera-pdrv",
> +	.id	= 0,
> +	.dev	= {
> +		.platform_data = &iclink_mt9m001,
> +	},
> +};
> +
> +static struct platform_device pcm970_mt9v022 = {
> +	.name	= "soc-camera-pdrv",
> +	.id	= 1,
> +	.dev	= {
> +		.platform_data = &iclink_mt9v022,
> +	},
> +};
> +
> +static struct platform_device pcm970_mt9m131 = {
> +	.name	= "soc-camera-pdrv",
> +	.id	= 2,
> +	.dev	= {
> +		.platform_data = &iclink_mt9m131,
> +	},
> +};
> +
> +struct mx2_camera_platform_data pcm970_camera = {
> +	.clk  = 26600000,
> +	.flags = MX2_CAMERA_HSYNC_HIGH | MX2_CAMERA_GATED_CLOCK |
> +		MX2_CAMERA_PACK_DIR_MSB,
> +};
> +
>  /*
>   * system init for baseboard usage. Will be called by pcm038 init.
>   *
> @@ -230,4 +362,56 @@ void __init pcm970_baseboard_init(void)
>  	mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN);
>  	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
>  	platform_device_register(&pcm970_sja1000);
> +
> +	i2c_register_board_info(0, pcm970_i2c_devices,
> +		ARRAY_SIZE(pcm970_i2c_devices));
> +
> +	platform_device_register(&pcm970_mt9m001);
> +	platform_device_register(&pcm970_mt9v022);
> +	platform_device_register(&pcm970_mt9m131);
> +
> +	/* the first i2c master is used for devices on the baseboard */
> +	imx27_add_i2c_imx0(&pcm038_i2c_0_data);
> +
> +	mxc_register_device(&mx27_camera_device, &pcm970_camera);
>  }
> +
> +/*
> + * Ok, we have to deal with several situations here. We connect
> + * 10bit image sensors to a 8bit interface and we must make sure
> + * that the upper 8bit from the sensor are connected to the image
> + * interface. Some sensors have a i2c GPIO expander which controls
> + * a bus switch to fixup the routing. Mapper boards >= 1285.2 do
> + * the fixup without the need of a gpio switch.
> + * Set this parameter to '1' to use a camera with gpio switch on a
> + * newer mapper board to prevent the fixup being done twice.
> + */
> +static int use_camera_gpio;
> +core_param(use_camera_gpio, use_camera_gpio, int, 0444);
> +
> +static int __init pcm970_baseboard_init_late(void)
> +{
> +	int ret;
> +	struct regulator *regulator;
> +
> +	if (!machine_is_pcm038())
> +		return 0;
> +
> +	regulator = regulator_get(NULL, "imx_cam_vcc");
> +	if (IS_ERR(regulator))
> +		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
> +	else
> +		regulator_enable(regulator);
> +
> +	ret = gpio_request(MAX_INTERNAL_GPIO, "camera");
> +	if (!ret) {
> +		printk(KERN_INFO "pcm970 camera: Found GPIO expander on camera, %susing it\n",
> +				use_camera_gpio ? "" : "not ");
> +		gpio_direction_output(MAX_INTERNAL_GPIO, !!use_camera_gpio);
> +	} else
> +		printk(KERN_INFO "pcm970 camera: No GPIO expander on camera found\n");
> +
> +	return 0;
> +}
> +late_initcall(pcm970_baseboard_init_late);
> +
> -- 
> 1.7.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2] ARM: i.MX27 pcm970: Add camera support
  2010-08-11 20:10     ` Guennadi Liakhovetski
@ 2010-08-11 21:07       ` Michael Grzeschik
  2010-08-12 20:27         ` Guennadi Liakhovetski
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Grzeschik @ 2010-08-11 21:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 11, 2010 at 10:10:38PM +0200, Guennadi Liakhovetski wrote:
> On Wed, 11 Aug 2010, Michael Grzeschik wrote:
> 
> > Adds the glue code for the pcm970 baseboard. It has a power regulator
> > which is registered first and instrumented in the power hook of
> > soc_camera_link to turn on the power for the camera device.
> 
> Ok, this looks better now, with this you don't have to patch the driver 
> any more. But - are you sure you really need both - the power callback and 
> the lateinitcall doing the same - requesting the regulator and enabling 
> it. I think, just the power callback should suffice.

Yes, i left it this way because we just need to look for the gpio
expander only once. Since the power callback will be called everytime we
try to handle a camera, this part of code don't has to be there. With
the late_initcall we can leave the power-on-off behaviour of the
callback functions simple and as intended. After we initialized all the
i2c cameras, we do the final check for the gpio in the late_initcall.
For this we again, have to switch power on, look for the expander and
power off again, independent of which cameras has been found.

Michael

> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> > ---
> >  arch/arm/mach-imx/pcm970-baseboard.c |  184 ++++++++++++++++++++++++++++++++++
> >  1 files changed, 184 insertions(+), 0 deletions(-)
> > 
> > diff --git a/arch/arm/mach-imx/pcm970-baseboard.c b/arch/arm/mach-imx/pcm970-baseboard.c
> > index f490a40..1034c92 100644
> > --- a/arch/arm/mach-imx/pcm970-baseboard.c
> > +++ b/arch/arm/mach-imx/pcm970-baseboard.c
> > @@ -20,15 +20,23 @@
> >  #include <linux/irq.h>
> >  #include <linux/platform_device.h>
> >  #include <linux/can/platform/sja1000.h>
> > +#include <linux/i2c/pca953x.h>
> > +#include <linux/regulator/consumer.h>
> >  
> >  #include <asm/mach/arch.h>
> > +#include <asm/mach-types.h>
> > +
> > +#include <media/soc_camera.h>
> >  
> >  #include <mach/common.h>
> >  #include <mach/iomux-mx27.h>
> >  #include <mach/imxfb.h>
> >  #include <mach/hardware.h>
> >  #include <mach/mmc.h>
> > +#include <mach/mx2_cam.h>
> > +#include <mach/i2c.h>
> >  
> > +#include "devices-imx27.h"
> >  #include "devices.h"
> >  
> >  static int pcm970_pins[] = {
> > @@ -215,6 +223,130 @@ static struct platform_device pcm970_sja1000 = {
> >  	.num_resources = ARRAY_SIZE(pcm970_sja1000_resources),
> >  };
> >  
> > +/* count of GPIOs that are occupied by the CPU itself */
> > +#define MAX_INTERNAL_GPIO 192
> > +
> > +static unsigned long pcm970_camera_query_bus_param(struct soc_camera_link *icl)
> > +{
> > +	return SOCAM_DATAWIDTH_8;
> > +}
> > +
> > +static int pcm970_camera_set_bus_param(struct soc_camera_link *icl,
> > +		unsigned long flags)
> > +{
> > +	return 0;
> > +}
> > +
> > +static int pcm970_camera_power_bus(struct device *dev, int toggle)
> > +{
> > +	struct regulator *regulator;
> > +
> > +	regulator = regulator_get(NULL, "imx_cam_vcc");
> > +	if (IS_ERR(regulator)) {
> > +		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
> > +		return -ENODEV;
> > +	} else {
> > +		if (toggle)
> > +			regulator_enable(regulator);
> > +		else
> > +			regulator_disable(regulator);
> > +	}
> > +	return 0;
> > +}
> > +
> > +static struct pca953x_platform_data pca9536_data = {
> > +	.gpio_base      = MAX_INTERNAL_GPIO,
> > +};
> > +
> > +/* Board I2C devices. */
> > +static struct i2c_board_info __initdata pcm970_i2c_devices[] = {
> > +	{
> > +		/* Must initialize before the camera(s) */
> > +		I2C_BOARD_INFO("pca953x", 0x41),
> > +		.type = "pca9536",
> > +		.platform_data = &pca9536_data,
> > +	},
> > +};
> > +
> > +static struct i2c_board_info __initdata pcm970_camera_mt9m001 = {
> > +		I2C_BOARD_INFO("mt9m001", 0x5d),
> > +		.type = "mt9m001",
> > +};
> > +
> > +static struct i2c_board_info __initdata pcm970_camera_mt9v022 = {
> > +		I2C_BOARD_INFO("mt9v022", 0x48),
> > +		.type = "mt9v022",
> > +};
> > +
> > +static struct i2c_board_info __initdata pcm970_camera_mt9m131 = {
> > +		I2C_BOARD_INFO("mt9m111", 0x48),
> > +		.type = "mt9m111",
> > +};
> > +
> > +static struct soc_camera_link iclink_mt9m001 = {
> > +	.bus_id		= 0,		/* Must match with the camera ID */
> > +	.board_info	= &pcm970_camera_mt9m001,
> > +	.i2c_adapter_id	= 0,
> > +	.module_name	= "mt9m001",
> > +	.power		= pcm970_camera_power_bus,
> > +	.query_bus_param = pcm970_camera_query_bus_param,
> > +	.set_bus_param	= pcm970_camera_set_bus_param,
> > +};
> > +
> > +static struct soc_camera_link iclink_mt9v022 = {
> > +	.bus_id		= 0,		/* Must match with the camera ID */
> > +	.board_info	= &pcm970_camera_mt9v022,
> > +	.i2c_adapter_id	= 0,
> > +	.module_name	= "mt9v022",
> > +	.power		= pcm970_camera_power_bus,
> > +	.query_bus_param = pcm970_camera_query_bus_param,
> > +	.set_bus_param	= pcm970_camera_set_bus_param,
> > +};
> > +
> > +static struct soc_camera_link iclink_mt9m131 = {
> > +	.bus_id		= 0,		/* Must match with the camera ID */
> > +	.board_info	= &pcm970_camera_mt9m131,
> > +	.i2c_adapter_id	= 0,
> > +	.module_name	= "mt9m111",
> > +	.power		= pcm970_camera_power_bus,
> > +	.query_bus_param = pcm970_camera_query_bus_param,
> > +	.set_bus_param	= pcm970_camera_set_bus_param,
> > +};
> > +
> > +static struct imxi2c_platform_data pcm038_i2c_0_data = {
> > +	.bitrate = 10000,
> > +};
> > +
> > +static struct platform_device pcm970_mt9m001 = {
> > +	.name	= "soc-camera-pdrv",
> > +	.id	= 0,
> > +	.dev	= {
> > +		.platform_data = &iclink_mt9m001,
> > +	},
> > +};
> > +
> > +static struct platform_device pcm970_mt9v022 = {
> > +	.name	= "soc-camera-pdrv",
> > +	.id	= 1,
> > +	.dev	= {
> > +		.platform_data = &iclink_mt9v022,
> > +	},
> > +};
> > +
> > +static struct platform_device pcm970_mt9m131 = {
> > +	.name	= "soc-camera-pdrv",
> > +	.id	= 2,
> > +	.dev	= {
> > +		.platform_data = &iclink_mt9m131,
> > +	},
> > +};
> > +
> > +struct mx2_camera_platform_data pcm970_camera = {
> > +	.clk  = 26600000,
> > +	.flags = MX2_CAMERA_HSYNC_HIGH | MX2_CAMERA_GATED_CLOCK |
> > +		MX2_CAMERA_PACK_DIR_MSB,
> > +};
> > +
> >  /*
> >   * system init for baseboard usage. Will be called by pcm038 init.
> >   *
> > @@ -230,4 +362,56 @@ void __init pcm970_baseboard_init(void)
> >  	mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN);
> >  	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
> >  	platform_device_register(&pcm970_sja1000);
> > +
> > +	i2c_register_board_info(0, pcm970_i2c_devices,
> > +		ARRAY_SIZE(pcm970_i2c_devices));
> > +
> > +	platform_device_register(&pcm970_mt9m001);
> > +	platform_device_register(&pcm970_mt9v022);
> > +	platform_device_register(&pcm970_mt9m131);
> > +
> > +	/* the first i2c master is used for devices on the baseboard */
> > +	imx27_add_i2c_imx0(&pcm038_i2c_0_data);
> > +
> > +	mxc_register_device(&mx27_camera_device, &pcm970_camera);
> >  }
> > +
> > +/*
> > + * Ok, we have to deal with several situations here. We connect
> > + * 10bit image sensors to a 8bit interface and we must make sure
> > + * that the upper 8bit from the sensor are connected to the image
> > + * interface. Some sensors have a i2c GPIO expander which controls
> > + * a bus switch to fixup the routing. Mapper boards >= 1285.2 do
> > + * the fixup without the need of a gpio switch.
> > + * Set this parameter to '1' to use a camera with gpio switch on a
> > + * newer mapper board to prevent the fixup being done twice.
> > + */
> > +static int use_camera_gpio;
> > +core_param(use_camera_gpio, use_camera_gpio, int, 0444);
> > +
> > +static int __init pcm970_baseboard_init_late(void)
> > +{
> > +	int ret;
> > +	struct regulator *regulator;
> > +
> > +	if (!machine_is_pcm038())
> > +		return 0;
> > +
> > +	regulator = regulator_get(NULL, "imx_cam_vcc");
> > +	if (IS_ERR(regulator))
> > +		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
> > +	else
> > +		regulator_enable(regulator);
> > +
> > +	ret = gpio_request(MAX_INTERNAL_GPIO, "camera");
> > +	if (!ret) {
> > +		printk(KERN_INFO "pcm970 camera: Found GPIO expander on camera, %susing it\n",
> > +				use_camera_gpio ? "" : "not ");
> > +		gpio_direction_output(MAX_INTERNAL_GPIO, !!use_camera_gpio);
> > +	} else
> > +		printk(KERN_INFO "pcm970 camera: No GPIO expander on camera found\n");
> > +
> > +	return 0;
> > +}
> > +late_initcall(pcm970_baseboard_init_late);
> > +
> > -- 
> > 1.7.1
> > 
> > 
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> > 
> > 
> 
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
> http://www.open-technology.de/
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2] ARM: i.MX27 pcm970: Add camera support
  2010-08-11 21:07       ` Michael Grzeschik
@ 2010-08-12 20:27         ` Guennadi Liakhovetski
  2010-08-15  8:55           ` Michael Grzeschik
  2010-08-15  9:08           ` [PATCH v3] " Michael Grzeschik
  0 siblings, 2 replies; 13+ messages in thread
From: Guennadi Liakhovetski @ 2010-08-12 20:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 11 Aug 2010, Michael Grzeschik wrote:

> On Wed, Aug 11, 2010 at 10:10:38PM +0200, Guennadi Liakhovetski wrote:
> > On Wed, 11 Aug 2010, Michael Grzeschik wrote:
> > 
> > > Adds the glue code for the pcm970 baseboard. It has a power regulator
> > > which is registered first and instrumented in the power hook of
> > > soc_camera_link to turn on the power for the camera device.
> > 
> > Ok, this looks better now, with this you don't have to patch the driver 
> > any more. But - are you sure you really need both - the power callback and 
> > the lateinitcall doing the same - requesting the regulator and enabling 
> > it. I think, just the power callback should suffice.
> 
> Yes, i left it this way because we just need to look for the gpio
> expander only once. Since the power callback will be called everytime we
> try to handle a camera, this part of code don't has to be there. With
> the late_initcall we can leave the power-on-off behaviour of the
> callback functions simple and as intended. After we initialized all the
> i2c cameras, we do the final check for the gpio in the late_initcall.
> For this we again, have to switch power on, look for the expander and
> power off again, independent of which cameras has been found.

Do you mean, that your GPIO expander is also powered from the same 
regulator, as the camera sensor? But you request and enable the regulator 
in pcm970_baseboard_init_late() and do not disable it there again. Is this 
required for your expander to preserve the state? I am not familiar with 
the regulator API - does it count enables and disables? In which case, 
with the below patch it would stay on permanently?

Thanks
Guennadi

> 
> Michael
> 
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> > > ---
> > >  arch/arm/mach-imx/pcm970-baseboard.c |  184 ++++++++++++++++++++++++++++++++++
> > >  1 files changed, 184 insertions(+), 0 deletions(-)
> > > 
> > > diff --git a/arch/arm/mach-imx/pcm970-baseboard.c b/arch/arm/mach-imx/pcm970-baseboard.c
> > > index f490a40..1034c92 100644
> > > --- a/arch/arm/mach-imx/pcm970-baseboard.c
> > > +++ b/arch/arm/mach-imx/pcm970-baseboard.c
> > > @@ -20,15 +20,23 @@
> > >  #include <linux/irq.h>
> > >  #include <linux/platform_device.h>
> > >  #include <linux/can/platform/sja1000.h>
> > > +#include <linux/i2c/pca953x.h>
> > > +#include <linux/regulator/consumer.h>
> > >  
> > >  #include <asm/mach/arch.h>
> > > +#include <asm/mach-types.h>
> > > +
> > > +#include <media/soc_camera.h>
> > >  
> > >  #include <mach/common.h>
> > >  #include <mach/iomux-mx27.h>
> > >  #include <mach/imxfb.h>
> > >  #include <mach/hardware.h>
> > >  #include <mach/mmc.h>
> > > +#include <mach/mx2_cam.h>
> > > +#include <mach/i2c.h>
> > >  
> > > +#include "devices-imx27.h"
> > >  #include "devices.h"
> > >  
> > >  static int pcm970_pins[] = {
> > > @@ -215,6 +223,130 @@ static struct platform_device pcm970_sja1000 = {
> > >  	.num_resources = ARRAY_SIZE(pcm970_sja1000_resources),
> > >  };
> > >  
> > > +/* count of GPIOs that are occupied by the CPU itself */
> > > +#define MAX_INTERNAL_GPIO 192
> > > +
> > > +static unsigned long pcm970_camera_query_bus_param(struct soc_camera_link *icl)
> > > +{
> > > +	return SOCAM_DATAWIDTH_8;
> > > +}
> > > +
> > > +static int pcm970_camera_set_bus_param(struct soc_camera_link *icl,
> > > +		unsigned long flags)
> > > +{
> > > +	return 0;
> > > +}
> > > +
> > > +static int pcm970_camera_power_bus(struct device *dev, int toggle)
> > > +{
> > > +	struct regulator *regulator;
> > > +
> > > +	regulator = regulator_get(NULL, "imx_cam_vcc");
> > > +	if (IS_ERR(regulator)) {
> > > +		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
> > > +		return -ENODEV;
> > > +	} else {
> > > +		if (toggle)
> > > +			regulator_enable(regulator);
> > > +		else
> > > +			regulator_disable(regulator);
> > > +	}
> > > +	return 0;
> > > +}
> > > +
> > > +static struct pca953x_platform_data pca9536_data = {
> > > +	.gpio_base      = MAX_INTERNAL_GPIO,
> > > +};
> > > +
> > > +/* Board I2C devices. */
> > > +static struct i2c_board_info __initdata pcm970_i2c_devices[] = {
> > > +	{
> > > +		/* Must initialize before the camera(s) */
> > > +		I2C_BOARD_INFO("pca953x", 0x41),
> > > +		.type = "pca9536",
> > > +		.platform_data = &pca9536_data,
> > > +	},
> > > +};
> > > +
> > > +static struct i2c_board_info __initdata pcm970_camera_mt9m001 = {
> > > +		I2C_BOARD_INFO("mt9m001", 0x5d),
> > > +		.type = "mt9m001",
> > > +};
> > > +
> > > +static struct i2c_board_info __initdata pcm970_camera_mt9v022 = {
> > > +		I2C_BOARD_INFO("mt9v022", 0x48),
> > > +		.type = "mt9v022",
> > > +};
> > > +
> > > +static struct i2c_board_info __initdata pcm970_camera_mt9m131 = {
> > > +		I2C_BOARD_INFO("mt9m111", 0x48),
> > > +		.type = "mt9m111",
> > > +};
> > > +
> > > +static struct soc_camera_link iclink_mt9m001 = {
> > > +	.bus_id		= 0,		/* Must match with the camera ID */
> > > +	.board_info	= &pcm970_camera_mt9m001,
> > > +	.i2c_adapter_id	= 0,
> > > +	.module_name	= "mt9m001",
> > > +	.power		= pcm970_camera_power_bus,
> > > +	.query_bus_param = pcm970_camera_query_bus_param,
> > > +	.set_bus_param	= pcm970_camera_set_bus_param,
> > > +};
> > > +
> > > +static struct soc_camera_link iclink_mt9v022 = {
> > > +	.bus_id		= 0,		/* Must match with the camera ID */
> > > +	.board_info	= &pcm970_camera_mt9v022,
> > > +	.i2c_adapter_id	= 0,
> > > +	.module_name	= "mt9v022",
> > > +	.power		= pcm970_camera_power_bus,
> > > +	.query_bus_param = pcm970_camera_query_bus_param,
> > > +	.set_bus_param	= pcm970_camera_set_bus_param,
> > > +};
> > > +
> > > +static struct soc_camera_link iclink_mt9m131 = {
> > > +	.bus_id		= 0,		/* Must match with the camera ID */
> > > +	.board_info	= &pcm970_camera_mt9m131,
> > > +	.i2c_adapter_id	= 0,
> > > +	.module_name	= "mt9m111",
> > > +	.power		= pcm970_camera_power_bus,
> > > +	.query_bus_param = pcm970_camera_query_bus_param,
> > > +	.set_bus_param	= pcm970_camera_set_bus_param,
> > > +};
> > > +
> > > +static struct imxi2c_platform_data pcm038_i2c_0_data = {
> > > +	.bitrate = 10000,
> > > +};
> > > +
> > > +static struct platform_device pcm970_mt9m001 = {
> > > +	.name	= "soc-camera-pdrv",
> > > +	.id	= 0,
> > > +	.dev	= {
> > > +		.platform_data = &iclink_mt9m001,
> > > +	},
> > > +};
> > > +
> > > +static struct platform_device pcm970_mt9v022 = {
> > > +	.name	= "soc-camera-pdrv",
> > > +	.id	= 1,
> > > +	.dev	= {
> > > +		.platform_data = &iclink_mt9v022,
> > > +	},
> > > +};
> > > +
> > > +static struct platform_device pcm970_mt9m131 = {
> > > +	.name	= "soc-camera-pdrv",
> > > +	.id	= 2,
> > > +	.dev	= {
> > > +		.platform_data = &iclink_mt9m131,
> > > +	},
> > > +};
> > > +
> > > +struct mx2_camera_platform_data pcm970_camera = {
> > > +	.clk  = 26600000,
> > > +	.flags = MX2_CAMERA_HSYNC_HIGH | MX2_CAMERA_GATED_CLOCK |
> > > +		MX2_CAMERA_PACK_DIR_MSB,
> > > +};
> > > +
> > >  /*
> > >   * system init for baseboard usage. Will be called by pcm038 init.
> > >   *
> > > @@ -230,4 +362,56 @@ void __init pcm970_baseboard_init(void)
> > >  	mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN);
> > >  	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
> > >  	platform_device_register(&pcm970_sja1000);
> > > +
> > > +	i2c_register_board_info(0, pcm970_i2c_devices,
> > > +		ARRAY_SIZE(pcm970_i2c_devices));
> > > +
> > > +	platform_device_register(&pcm970_mt9m001);
> > > +	platform_device_register(&pcm970_mt9v022);
> > > +	platform_device_register(&pcm970_mt9m131);
> > > +
> > > +	/* the first i2c master is used for devices on the baseboard */
> > > +	imx27_add_i2c_imx0(&pcm038_i2c_0_data);
> > > +
> > > +	mxc_register_device(&mx27_camera_device, &pcm970_camera);
> > >  }
> > > +
> > > +/*
> > > + * Ok, we have to deal with several situations here. We connect
> > > + * 10bit image sensors to a 8bit interface and we must make sure
> > > + * that the upper 8bit from the sensor are connected to the image
> > > + * interface. Some sensors have a i2c GPIO expander which controls
> > > + * a bus switch to fixup the routing. Mapper boards >= 1285.2 do
> > > + * the fixup without the need of a gpio switch.
> > > + * Set this parameter to '1' to use a camera with gpio switch on a
> > > + * newer mapper board to prevent the fixup being done twice.
> > > + */
> > > +static int use_camera_gpio;
> > > +core_param(use_camera_gpio, use_camera_gpio, int, 0444);
> > > +
> > > +static int __init pcm970_baseboard_init_late(void)
> > > +{
> > > +	int ret;
> > > +	struct regulator *regulator;
> > > +
> > > +	if (!machine_is_pcm038())
> > > +		return 0;
> > > +
> > > +	regulator = regulator_get(NULL, "imx_cam_vcc");
> > > +	if (IS_ERR(regulator))
> > > +		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
> > > +	else
> > > +		regulator_enable(regulator);
> > > +
> > > +	ret = gpio_request(MAX_INTERNAL_GPIO, "camera");
> > > +	if (!ret) {
> > > +		printk(KERN_INFO "pcm970 camera: Found GPIO expander on camera, %susing it\n",
> > > +				use_camera_gpio ? "" : "not ");
> > > +		gpio_direction_output(MAX_INTERNAL_GPIO, !!use_camera_gpio);
> > > +	} else
> > > +		printk(KERN_INFO "pcm970 camera: No GPIO expander on camera found\n");
> > > +
> > > +	return 0;
> > > +}
> > > +late_initcall(pcm970_baseboard_init_late);
> > > +
> > > -- 
> > > 1.7.1
> > > 
> > > 
> > > _______________________________________________
> > > linux-arm-kernel mailing list
> > > linux-arm-kernel at lists.infradead.org
> > > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> > > 
> > > 
> > 
> > ---
> > Guennadi Liakhovetski, Ph.D.
> > Freelance Open-Source Software Developer
> > http://www.open-technology.de/
> > 
> 
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2] ARM: i.MX27 pcm970: Add camera support
  2010-08-12 20:27         ` Guennadi Liakhovetski
@ 2010-08-15  8:55           ` Michael Grzeschik
  2010-08-15  9:08           ` [PATCH v3] " Michael Grzeschik
  1 sibling, 0 replies; 13+ messages in thread
From: Michael Grzeschik @ 2010-08-15  8:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 12, 2010 at 10:27:57PM +0200, Guennadi Liakhovetski wrote:
> On Wed, 11 Aug 2010, Michael Grzeschik wrote:
> 
> > On Wed, Aug 11, 2010 at 10:10:38PM +0200, Guennadi Liakhovetski wrote:
> > > On Wed, 11 Aug 2010, Michael Grzeschik wrote:
> > > 
> > > > Adds the glue code for the pcm970 baseboard. It has a power regulator
> > > > which is registered first and instrumented in the power hook of
> > > > soc_camera_link to turn on the power for the camera device.
> > > 
> > > Ok, this looks better now, with this you don't have to patch the driver 
> > > any more. But - are you sure you really need both - the power callback and 
> > > the lateinitcall doing the same - requesting the regulator and enabling 
> > > it. I think, just the power callback should suffice.
> > 
> > Yes, i left it this way because we just need to look for the gpio
> > expander only once. Since the power callback will be called everytime we
> > try to handle a camera, this part of code don't has to be there. With
> > the late_initcall we can leave the power-on-off behaviour of the
> > callback functions simple and as intended. After we initialized all the
> > i2c cameras, we do the final check for the gpio in the late_initcall.
> > For this we again, have to switch power on, look for the expander and
> > power off again, independent of which cameras has been found.
> 
> Do you mean, that your GPIO expander is also powered from the same 
> regulator, as the camera sensor? But you request and enable the regulator 
> in pcm970_baseboard_init_late() and do not disable it there again. Is this 
> required for your expander to preserve the state? I am not familiar with 
> the regulator API - does it count enables and disables? In which case, 
> with the below patch it would stay on permanently?

There is no case for this version of patch in which the power regulator
will stay turned on. Since we trigger the gpio on the expander,
the camera module with the expander on board has to stay turned on.
Otherwise our gpio setting will be lost. I send v3 now. In this version
the regulator will not be turned off again.

Thanks for helping on this,
Michael

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3] ARM: i.MX27 pcm970: Add camera support
  2010-08-12 20:27         ` Guennadi Liakhovetski
  2010-08-15  8:55           ` Michael Grzeschik
@ 2010-08-15  9:08           ` Michael Grzeschik
  2010-08-18 20:05             ` Guennadi Liakhovetski
  1 sibling, 1 reply; 13+ messages in thread
From: Michael Grzeschik @ 2010-08-15  9:08 UTC (permalink / raw)
  To: linux-arm-kernel

Adds the glue code for the pcm970 baseboard. It has a power regulator
which is registered first and instrumented in the power hook of
soc_camera_link to turn on the power for the camera device.

Additionaly there are some cameras with an gpio expander, also powered
by the regulator. The search for this expander is taking place in the
late_initcall to be sure to have the power already already turned on
and have searched for all registered cameras.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
v2 - v3:
	* removed off function from soc_camera_link power hook
v1 - v2:
	* moved camera register_device to baseboard_init
	* changed to soc_camera_link power hook with on-off function

 arch/arm/mach-imx/pcm970-baseboard.c |  183 ++++++++++++++++++++++++++++++++++
 1 files changed, 183 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-imx/pcm970-baseboard.c b/arch/arm/mach-imx/pcm970-baseboard.c
index f490a40..1ca126a 100644
--- a/arch/arm/mach-imx/pcm970-baseboard.c
+++ b/arch/arm/mach-imx/pcm970-baseboard.c
@@ -20,15 +20,23 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/can/platform/sja1000.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <media/soc_camera.h>
 
 #include <mach/common.h>
 #include <mach/iomux-mx27.h>
 #include <mach/imxfb.h>
 #include <mach/hardware.h>
 #include <mach/mmc.h>
+#include <mach/mx2_cam.h>
+#include <mach/i2c.h>
 
+#include "devices-imx27.h"
 #include "devices.h"
 
 static int pcm970_pins[] = {
@@ -215,6 +223,128 @@ static struct platform_device pcm970_sja1000 = {
 	.num_resources = ARRAY_SIZE(pcm970_sja1000_resources),
 };
 
+/* count of GPIOs that are occupied by the CPU itself */
+#define MAX_INTERNAL_GPIO 192
+
+static unsigned long pcm970_camera_query_bus_param(struct soc_camera_link *icl)
+{
+	return SOCAM_DATAWIDTH_8;
+}
+
+static int pcm970_camera_set_bus_param(struct soc_camera_link *icl,
+		unsigned long flags)
+{
+	return 0;
+}
+
+static int pcm970_camera_power_bus(struct device *dev, int toggle)
+{
+	struct regulator *regulator;
+
+	regulator = regulator_get(NULL, "imx_cam_vcc");
+	if (IS_ERR(regulator)) {
+		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
+		return -ENODEV;
+	} else {
+		if (!regulator_is_enabled(regulator) && toggle)
+			regulator_enable(regulator);
+	}
+	return 0;
+}
+
+static struct pca953x_platform_data pca9536_data = {
+	.gpio_base      = MAX_INTERNAL_GPIO,
+};
+
+/* Board I2C devices. */
+static struct i2c_board_info __initdata pcm970_i2c_devices[] = {
+	{
+		/* Must initialize before the camera(s) */
+		I2C_BOARD_INFO("pca953x", 0x41),
+		.type = "pca9536",
+		.platform_data = &pca9536_data,
+	},
+};
+
+static struct i2c_board_info __initdata pcm970_camera_mt9m001 = {
+		I2C_BOARD_INFO("mt9m001", 0x5d),
+		.type = "mt9m001",
+};
+
+static struct i2c_board_info __initdata pcm970_camera_mt9v022 = {
+		I2C_BOARD_INFO("mt9v022", 0x48),
+		.type = "mt9v022",
+};
+
+static struct i2c_board_info __initdata pcm970_camera_mt9m131 = {
+		I2C_BOARD_INFO("mt9m111", 0x48),
+		.type = "mt9m111",
+};
+
+static struct soc_camera_link iclink_mt9m001 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pcm970_camera_mt9m001,
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9m001",
+	.power		= pcm970_camera_power_bus,
+	.query_bus_param = pcm970_camera_query_bus_param,
+	.set_bus_param	= pcm970_camera_set_bus_param,
+};
+
+static struct soc_camera_link iclink_mt9v022 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pcm970_camera_mt9v022,
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9v022",
+	.power		= pcm970_camera_power_bus,
+	.query_bus_param = pcm970_camera_query_bus_param,
+	.set_bus_param	= pcm970_camera_set_bus_param,
+};
+
+static struct soc_camera_link iclink_mt9m131 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pcm970_camera_mt9m131,
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9m111",
+	.power		= pcm970_camera_power_bus,
+	.query_bus_param = pcm970_camera_query_bus_param,
+	.set_bus_param	= pcm970_camera_set_bus_param,
+};
+
+static struct imxi2c_platform_data pcm038_i2c_0_data = {
+	.bitrate = 10000,
+};
+
+static struct platform_device pcm970_mt9m001 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &iclink_mt9m001,
+	},
+};
+
+static struct platform_device pcm970_mt9v022 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &iclink_mt9v022,
+	},
+};
+
+static struct platform_device pcm970_mt9m131 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 2,
+	.dev	= {
+		.platform_data = &iclink_mt9m131,
+	},
+};
+
+struct mx2_camera_platform_data pcm970_camera = {
+	.clk  = 26600000,
+	.flags = MX2_CAMERA_HSYNC_HIGH | MX2_CAMERA_GATED_CLOCK |
+		MX2_CAMERA_PACK_DIR_MSB,
+};
+
 /*
  * system init for baseboard usage. Will be called by pcm038 init.
  *
@@ -230,4 +360,57 @@ void __init pcm970_baseboard_init(void)
 	mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN);
 	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
 	platform_device_register(&pcm970_sja1000);
+
+	i2c_register_board_info(0, pcm970_i2c_devices,
+		ARRAY_SIZE(pcm970_i2c_devices));
+
+	platform_device_register(&pcm970_mt9m001);
+	platform_device_register(&pcm970_mt9v022);
+	platform_device_register(&pcm970_mt9m131);
+
+	/* the first i2c master is used for devices on the baseboard */
+	imx27_add_i2c_imx0(&pcm038_i2c_0_data);
+
+	mxc_register_device(&mx27_camera_device, &pcm970_camera);
+}
+
+/*
+ * Ok, we have to deal with several situations here. We connect
+ * 10bit image sensors to a 8bit interface and we must make sure
+ * that the upper 8bit from the sensor are connected to the image
+ * interface. Some sensors have a i2c GPIO expander which controls
+ * a bus switch to fixup the routing. Mapper boards >= 1285.2 do
+ * the fixup without the need of a gpio switch.
+ * Set this parameter to '1' to use a camera with gpio switch on a
+ * newer mapper board to prevent the fixup being done twice.
+ */
+static int use_camera_gpio;
+core_param(use_camera_gpio, use_camera_gpio, int, 0444);
+
+static int __init pcm970_baseboard_init_late(void)
+{
+	int ret;
+	struct regulator *regulator;
+
+	if (!machine_is_pcm038())
+		return 0;
+
+	regulator = regulator_get(NULL, "imx_cam_vcc");
+	if (IS_ERR(regulator)) {
+		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
+		return -ENODEV;
+	} else if (!regulator_is_enabled(regulator)) {
+		regulator_enable(regulator);
+	}
+
+	ret = gpio_request(MAX_INTERNAL_GPIO, "camera");
+	if (!ret) {
+		printk(KERN_INFO "pcm970 camera: Found GPIO expander on camera, %susing it\n",
+				use_camera_gpio ? "" : "not ");
+		gpio_direction_output(MAX_INTERNAL_GPIO, !!use_camera_gpio);
+	} else
+		printk(KERN_INFO "pcm970 camera: No GPIO expander on camera found\n");
+
+	return 0;
 }
+late_initcall(pcm970_baseboard_init_late);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3] ARM: i.MX27 pcm970: Add camera support
  2010-08-15  9:08           ` [PATCH v3] " Michael Grzeschik
@ 2010-08-18 20:05             ` Guennadi Liakhovetski
  2010-08-18 20:33               ` Mark Brown
  0 siblings, 1 reply; 13+ messages in thread
From: Guennadi Liakhovetski @ 2010-08-18 20:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, 15 Aug 2010, Michael Grzeschik wrote:

> Adds the glue code for the pcm970 baseboard. It has a power regulator
> which is registered first and instrumented in the power hook of
> soc_camera_link to turn on the power for the camera device.
> 
> Additionaly there are some cameras with an gpio expander, also powered
> by the regulator. The search for this expander is taking place in the
> late_initcall to be sure to have the power already already turned on
> and have searched for all registered cameras.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> ---
> v2 - v3:
> 	* removed off function from soc_camera_link power hook

No, sorry, I don't like it again.

1. unbalanced regulator enable. IMHO, this is no exception to the general 
enable / disable, alloc / free, lock / unlock etc. call balancing rule. If 
your regulator has to stay enabled for the whole system run-time, you 
don't have to (even try to) enable it multiple times. Please, either make 
enabling / disabling symmetric, or leave only one enable in the 
initialisation call.

2. Have you tested this with the camera drivers linked into the kernel - 
not as modules? I suspect, this won't work, because in this case camera 
probe will be called before your late initcall. I'd (again) suggest to use 
bus notification either on spi_bus_type to wait for the driver to be 
attached to your pmic, or on soc_camera_bus_type to wait until your camera 
device gets added (_not_ driver attached - a different notification event) 
to the soc-camera bus.

Thanks
Guennadi

> v1 - v2:
> 	* moved camera register_device to baseboard_init
> 	* changed to soc_camera_link power hook with on-off function
> 
>  arch/arm/mach-imx/pcm970-baseboard.c |  183 ++++++++++++++++++++++++++++++++++
>  1 files changed, 183 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/pcm970-baseboard.c b/arch/arm/mach-imx/pcm970-baseboard.c
> index f490a40..1ca126a 100644
> --- a/arch/arm/mach-imx/pcm970-baseboard.c
> +++ b/arch/arm/mach-imx/pcm970-baseboard.c
> @@ -20,15 +20,23 @@
>  #include <linux/irq.h>
>  #include <linux/platform_device.h>
>  #include <linux/can/platform/sja1000.h>
> +#include <linux/i2c/pca953x.h>
> +#include <linux/regulator/consumer.h>
>  
>  #include <asm/mach/arch.h>
> +#include <asm/mach-types.h>
> +
> +#include <media/soc_camera.h>
>  
>  #include <mach/common.h>
>  #include <mach/iomux-mx27.h>
>  #include <mach/imxfb.h>
>  #include <mach/hardware.h>
>  #include <mach/mmc.h>
> +#include <mach/mx2_cam.h>
> +#include <mach/i2c.h>
>  
> +#include "devices-imx27.h"
>  #include "devices.h"
>  
>  static int pcm970_pins[] = {
> @@ -215,6 +223,128 @@ static struct platform_device pcm970_sja1000 = {
>  	.num_resources = ARRAY_SIZE(pcm970_sja1000_resources),
>  };
>  
> +/* count of GPIOs that are occupied by the CPU itself */
> +#define MAX_INTERNAL_GPIO 192
> +
> +static unsigned long pcm970_camera_query_bus_param(struct soc_camera_link *icl)
> +{
> +	return SOCAM_DATAWIDTH_8;
> +}
> +
> +static int pcm970_camera_set_bus_param(struct soc_camera_link *icl,
> +		unsigned long flags)
> +{
> +	return 0;
> +}
> +
> +static int pcm970_camera_power_bus(struct device *dev, int toggle)
> +{
> +	struct regulator *regulator;
> +
> +	regulator = regulator_get(NULL, "imx_cam_vcc");
> +	if (IS_ERR(regulator)) {
> +		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
> +		return -ENODEV;
> +	} else {
> +		if (!regulator_is_enabled(regulator) && toggle)
> +			regulator_enable(regulator);
> +	}
> +	return 0;
> +}
> +
> +static struct pca953x_platform_data pca9536_data = {
> +	.gpio_base      = MAX_INTERNAL_GPIO,
> +};
> +
> +/* Board I2C devices. */
> +static struct i2c_board_info __initdata pcm970_i2c_devices[] = {
> +	{
> +		/* Must initialize before the camera(s) */
> +		I2C_BOARD_INFO("pca953x", 0x41),
> +		.type = "pca9536",
> +		.platform_data = &pca9536_data,
> +	},
> +};
> +
> +static struct i2c_board_info __initdata pcm970_camera_mt9m001 = {
> +		I2C_BOARD_INFO("mt9m001", 0x5d),
> +		.type = "mt9m001",
> +};
> +
> +static struct i2c_board_info __initdata pcm970_camera_mt9v022 = {
> +		I2C_BOARD_INFO("mt9v022", 0x48),
> +		.type = "mt9v022",
> +};
> +
> +static struct i2c_board_info __initdata pcm970_camera_mt9m131 = {
> +		I2C_BOARD_INFO("mt9m111", 0x48),
> +		.type = "mt9m111",
> +};
> +
> +static struct soc_camera_link iclink_mt9m001 = {
> +	.bus_id		= 0,		/* Must match with the camera ID */
> +	.board_info	= &pcm970_camera_mt9m001,
> +	.i2c_adapter_id	= 0,
> +	.module_name	= "mt9m001",
> +	.power		= pcm970_camera_power_bus,
> +	.query_bus_param = pcm970_camera_query_bus_param,
> +	.set_bus_param	= pcm970_camera_set_bus_param,
> +};
> +
> +static struct soc_camera_link iclink_mt9v022 = {
> +	.bus_id		= 0,		/* Must match with the camera ID */
> +	.board_info	= &pcm970_camera_mt9v022,
> +	.i2c_adapter_id	= 0,
> +	.module_name	= "mt9v022",
> +	.power		= pcm970_camera_power_bus,
> +	.query_bus_param = pcm970_camera_query_bus_param,
> +	.set_bus_param	= pcm970_camera_set_bus_param,
> +};
> +
> +static struct soc_camera_link iclink_mt9m131 = {
> +	.bus_id		= 0,		/* Must match with the camera ID */
> +	.board_info	= &pcm970_camera_mt9m131,
> +	.i2c_adapter_id	= 0,
> +	.module_name	= "mt9m111",
> +	.power		= pcm970_camera_power_bus,
> +	.query_bus_param = pcm970_camera_query_bus_param,
> +	.set_bus_param	= pcm970_camera_set_bus_param,
> +};
> +
> +static struct imxi2c_platform_data pcm038_i2c_0_data = {
> +	.bitrate = 10000,
> +};
> +
> +static struct platform_device pcm970_mt9m001 = {
> +	.name	= "soc-camera-pdrv",
> +	.id	= 0,
> +	.dev	= {
> +		.platform_data = &iclink_mt9m001,
> +	},
> +};
> +
> +static struct platform_device pcm970_mt9v022 = {
> +	.name	= "soc-camera-pdrv",
> +	.id	= 1,
> +	.dev	= {
> +		.platform_data = &iclink_mt9v022,
> +	},
> +};
> +
> +static struct platform_device pcm970_mt9m131 = {
> +	.name	= "soc-camera-pdrv",
> +	.id	= 2,
> +	.dev	= {
> +		.platform_data = &iclink_mt9m131,
> +	},
> +};
> +
> +struct mx2_camera_platform_data pcm970_camera = {
> +	.clk  = 26600000,
> +	.flags = MX2_CAMERA_HSYNC_HIGH | MX2_CAMERA_GATED_CLOCK |
> +		MX2_CAMERA_PACK_DIR_MSB,
> +};
> +
>  /*
>   * system init for baseboard usage. Will be called by pcm038 init.
>   *
> @@ -230,4 +360,57 @@ void __init pcm970_baseboard_init(void)
>  	mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN);
>  	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
>  	platform_device_register(&pcm970_sja1000);
> +
> +	i2c_register_board_info(0, pcm970_i2c_devices,
> +		ARRAY_SIZE(pcm970_i2c_devices));
> +
> +	platform_device_register(&pcm970_mt9m001);
> +	platform_device_register(&pcm970_mt9v022);
> +	platform_device_register(&pcm970_mt9m131);
> +
> +	/* the first i2c master is used for devices on the baseboard */
> +	imx27_add_i2c_imx0(&pcm038_i2c_0_data);
> +
> +	mxc_register_device(&mx27_camera_device, &pcm970_camera);
> +}
> +
> +/*
> + * Ok, we have to deal with several situations here. We connect
> + * 10bit image sensors to a 8bit interface and we must make sure
> + * that the upper 8bit from the sensor are connected to the image
> + * interface. Some sensors have a i2c GPIO expander which controls
> + * a bus switch to fixup the routing. Mapper boards >= 1285.2 do
> + * the fixup without the need of a gpio switch.
> + * Set this parameter to '1' to use a camera with gpio switch on a
> + * newer mapper board to prevent the fixup being done twice.
> + */
> +static int use_camera_gpio;
> +core_param(use_camera_gpio, use_camera_gpio, int, 0444);
> +
> +static int __init pcm970_baseboard_init_late(void)
> +{
> +	int ret;
> +	struct regulator *regulator;
> +
> +	if (!machine_is_pcm038())
> +		return 0;
> +
> +	regulator = regulator_get(NULL, "imx_cam_vcc");
> +	if (IS_ERR(regulator)) {
> +		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
> +		return -ENODEV;
> +	} else if (!regulator_is_enabled(regulator)) {
> +		regulator_enable(regulator);
> +	}
> +
> +	ret = gpio_request(MAX_INTERNAL_GPIO, "camera");
> +	if (!ret) {
> +		printk(KERN_INFO "pcm970 camera: Found GPIO expander on camera, %susing it\n",
> +				use_camera_gpio ? "" : "not ");
> +		gpio_direction_output(MAX_INTERNAL_GPIO, !!use_camera_gpio);
> +	} else
> +		printk(KERN_INFO "pcm970 camera: No GPIO expander on camera found\n");
> +
> +	return 0;
>  }
> +late_initcall(pcm970_baseboard_init_late);
> -- 
> 1.7.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3] ARM: i.MX27 pcm970: Add camera support
  2010-08-18 20:05             ` Guennadi Liakhovetski
@ 2010-08-18 20:33               ` Mark Brown
  2010-08-18 21:13                 ` Guennadi Liakhovetski
  0 siblings, 1 reply; 13+ messages in thread
From: Mark Brown @ 2010-08-18 20:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 18, 2010 at 10:05:25PM +0200, Guennadi Liakhovetski wrote:

> 1. unbalanced regulator enable. IMHO, this is no exception to the general 
> enable / disable, alloc / free, lock / unlock etc. call balancing rule. If 
> your regulator has to stay enabled for the whole system run-time, you 
> don't have to (even try to) enable it multiple times. Please, either make 
> enabling / disabling symmetric, or leave only one enable in the 
> initialisation call.

If the regulator needs to be on all the time on a given board then
forcing this with always_on in the constraints is much more idiomatic
and straightforward.

> > +static int pcm970_camera_power_bus(struct device *dev, int toggle)
> > +{
> > +	struct regulator *regulator;
> > +
> > +	regulator = regulator_get(NULL, "imx_cam_vcc");
> > +	if (IS_ERR(regulator)) {
> > +		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
> > +		return -ENODEV;
> > +	} else {
> > +		if (!regulator_is_enabled(regulator) && toggle)
> > +			regulator_enable(regulator);
> > +	}
> > +	return 0;
> > +}

This is all very suspicious - your regulator_get() should be using the
struct device it was passed to look up the regulator by supply name
(probably "cam_vcc").  The regulator_is_enabled() call is going to break
if the supply is shared, too.

It all looks like something that I'd expect the camera driver to be
taking care of for itself, there's nothing board specific in here.

> > +	regulator = regulator_get(NULL, "imx_cam_vcc");
> > +	if (IS_ERR(regulator)) {
> > +		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
> > +		return -ENODEV;
> > +	} else if (!regulator_is_enabled(regulator)) {
> > +		regulator_enable(regulator);
> > +	}

Again, this looks like you need to add regulator support to the camera
driver.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3] ARM: i.MX27 pcm970: Add camera support
  2010-08-18 20:33               ` Mark Brown
@ 2010-08-18 21:13                 ` Guennadi Liakhovetski
  2010-08-18 21:46                   ` Mark Brown
  0 siblings, 1 reply; 13+ messages in thread
From: Guennadi Liakhovetski @ 2010-08-18 21:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 18 Aug 2010, Mark Brown wrote:

> On Wed, Aug 18, 2010 at 10:05:25PM +0200, Guennadi Liakhovetski wrote:
> 
> > 1. unbalanced regulator enable. IMHO, this is no exception to the general 
> > enable / disable, alloc / free, lock / unlock etc. call balancing rule. If 
> > your regulator has to stay enabled for the whole system run-time, you 
> > don't have to (even try to) enable it multiple times. Please, either make 
> > enabling / disabling symmetric, or leave only one enable in the 
> > initialisation call.
> 
> If the regulator needs to be on all the time on a given board then
> forcing this with always_on in the constraints is much more idiomatic
> and straightforward.
> 
> > > +static int pcm970_camera_power_bus(struct device *dev, int toggle)
> > > +{
> > > +	struct regulator *regulator;
> > > +
> > > +	regulator = regulator_get(NULL, "imx_cam_vcc");
> > > +	if (IS_ERR(regulator)) {
> > > +		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
> > > +		return -ENODEV;
> > > +	} else {
> > > +		if (!regulator_is_enabled(regulator) && toggle)
> > > +			regulator_enable(regulator);
> > > +	}
> > > +	return 0;
> > > +}
> 
> This is all very suspicious - your regulator_get() should be using the
> struct device it was passed to look up the regulator by supply name
> (probably "cam_vcc").  The regulator_is_enabled() call is going to break
> if the supply is shared, too.
> 
> It all looks like something that I'd expect the camera driver to be
> taking care of for itself, there's nothing board specific in here.
> 
> > > +	regulator = regulator_get(NULL, "imx_cam_vcc");
> > > +	if (IS_ERR(regulator)) {
> > > +		pr_err("unable to get regulator: %ld\n", PTR_ERR(regulator));
> > > +		return -ENODEV;
> > > +	} else if (!regulator_is_enabled(regulator)) {
> > > +		regulator_enable(regulator);
> > > +	}
> 
> Again, this looks like you need to add regulator support to the camera
> driver.

No, don't think so. This is a generic camera sensor, that can be attached 
to any video-capable SoC or built into a USB webcam. It knows nothing 
about where it's getting its power from.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3] ARM: i.MX27 pcm970: Add camera support
  2010-08-18 21:13                 ` Guennadi Liakhovetski
@ 2010-08-18 21:46                   ` Mark Brown
  0 siblings, 0 replies; 13+ messages in thread
From: Mark Brown @ 2010-08-18 21:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 18 Aug 2010, at 22:13, Guennadi Liakhovetski <g.liakhovetski@gmx.de> wrote:

> On Wed, 18 Aug 2010, Mark Brown wrote:
> 
>> Again, this looks like you need to add regulator support to the camera
>> driver.
> 
> No, don't think so. This is a generic camera sensor, that can be attached 
> to any video-capable SoC or built into a USB webcam. It knows nothing 
> about where it's getting its power from.

With the regulator API it doesn't need to - that's all done externally by the machine layer. At the very least the regulator stuff should be going somewhere in the core driver where a machine only needs an assignment statement to use it since the code is going to be identical for all machines with regulators supplying the camera.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2010-08-18 21:46 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-03  9:20 [PATCH 0/2] Add camera support for i.MX27 Baseboards Michael Grzeschik
2010-08-03  9:20 ` [PATCH 1/2] ARM: i.MX27 pcm970: Add camera support Michael Grzeschik
2010-08-11  7:38   ` [PATCH v2] " Michael Grzeschik
2010-08-11 20:10     ` Guennadi Liakhovetski
2010-08-11 21:07       ` Michael Grzeschik
2010-08-12 20:27         ` Guennadi Liakhovetski
2010-08-15  8:55           ` Michael Grzeschik
2010-08-15  9:08           ` [PATCH v3] " Michael Grzeschik
2010-08-18 20:05             ` Guennadi Liakhovetski
2010-08-18 20:33               ` Mark Brown
2010-08-18 21:13                 ` Guennadi Liakhovetski
2010-08-18 21:46                   ` Mark Brown
2010-08-03  9:20 ` [PATCH 2/2] ARM: i.MX27 pca100: " Michael Grzeschik

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.