[PATCH/RFT 0/3] ARM: davinci: da850-evm: camera capture

STALE3400d

4 messages, 1 author, 2017-06-02 · open the first message on its own page

[PATCH/RFT 0/3] ARM: davinci: da850-evm: camera capture

From: khilman@baylibre.com (Kevin Hilman)
Date: 2017-06-02 23:43:58

This series is the final step to demonstrate VPIF capture via an
external camera sensor.  It is only FYI and for testing/validation
purposes, and not intended for upstream merge.

Tested on a da850-evm with UI board.

With only the first patch (GPIO hogs) patch applied, VPIF capture
works for composite input, but still relies on pdata-quirks for the
tvp514x input/output routing.

With the rest of the series applied, it works for camera input with
VPIF in DT mode (no more pdata-quirks needed.)  

Tested with da850-evm + UI board + On-Semi camera board using
aptina,mt9v032 sensor:
  http://www.mouser.com/search/ProductDetail.aspx?R=0virtualkey0virtualkeyMT9V032C12STCH-GEVB

Dependencies:
- VPIF driver changes
  https://marc.info/?l=linux-arm-kernel&m=149643932427173
- davinci platform updates
  https://marc.info/?l=linux-arm-kernel&m=149644517728393

Kevin Hilman (3):
  ARM: dts: da850-evm: VPIF input selction via GPIO hogs
  ARM: dts: da850-evm.dts: add mt9v032 camera sensor
  HACK: ARM: davinci: add cdce913 clock controller

 arch/arm/boot/dts/da850-evm.dts      |  76 ++++++++++++++++
 arch/arm/mach-davinci/Makefile       |   2 +-
 arch/arm/mach-davinci/cdce913.c      | 164 +++++++++++++++++++++++++++++++++++
 arch/arm/mach-davinci/pdata-quirks.c |   8 +-
 4 files changed, 247 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-davinci/cdce913.c

-- 
2.9.3

[PATCH/RFT 1/3] ARM: dts: da850-evm: VPIF input selction via GPIO hogs

From: khilman@baylibre.com (Kevin Hilman)
Date: 2017-06-02 23:43:59

Force VPIF input selection to use composite video input.
---
 arch/arm/boot/dts/da850-evm.dts | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
index 67e72bc72e80..cbbf2c0d0269 100644
--- a/arch/arm/boot/dts/da850-evm.dts
+++ b/arch/arm/boot/dts/da850-evm.dts
@@ -302,3 +302,27 @@
 	pinctrl-0 = <&vpif_capture_pins>, <&vpif_display_pins>;
 	status = "okay";
 };
+
+/* UI board: VPIF input selection */
+&tca6416 {
+	 status = "okay";
+
+	 sel_a {
+		gpio-hog;
+		gpios = <7 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "ADC_ENn";
+	 };
+	 sel_b {
+		gpio-hog;
+		gpios = <6 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "CAMERA_ENn";
+	 };
+	 sel_c {
+		gpio-hog;
+		gpios = <5 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "VIDEO_IN_ENn";
+	 };
+};
-- 
2.9.3

[PATCH/RFT 2/3] ARM: dts: da850-evm.dts: add mt9v032 camera sensor

From: khilman@baylibre.com (Kevin Hilman)
Date: 2017-06-02 23:44:00

Add nodes to support camera input via UI board connector. Includes;

- i2c-mux used to connect VPIF input peripherals

- camera-sensor on the On-Semi camera board[1], which provides
  and aptina,mt9v032 sensor.  Note that this board provides
  a way to change the i2c addr via a switch, and this series
  assumes 0x4c

- clock-controler for the master clock provided to camera.  Note that
  this node is FYI only.  The upstream driver for ti,cdce913 requires
  CCF, which davinci does not support, so a subsequent patch/hack
  will create a basic clock driver so the camera driver can work

- VPIF endpoint nodes to connect VPIF input and camera sensor

- GPIO hog changes to switch VPIF input from composite to camera

[1] http://www.mouser.com/search/ProductDetail.aspx?R=0virtualkey0virtualkeyMT9V032C12STCH-GEVB
---
 arch/arm/boot/dts/da850-evm.dts | 56 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 54 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
index cbbf2c0d0269..c428d1d99ef6 100644
--- a/arch/arm/boot/dts/da850-evm.dts
+++ b/arch/arm/boot/dts/da850-evm.dts
@@ -297,10 +297,62 @@
 	};
 };
 
+/*
+ * Extentions provided on UI board
+ */
+&i2c0 {
+	/* clock generator used for camera input */
+	cdce913: clock-controller at 65 {
+		compatible = "ti,cdce913";
+		reg = <0x65>;
+		#clock-cells = <1>;
+	};
+
+	pca9543: i2c-mux at 73 {
+		compatible = "nxp,pca9543";
+		reg = <0x73>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pca9543_i2c1: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+	};
+};
+
+&pca9543_i2c1 {
+	mt9v032: camera at 4c {
+		compatible = "aptina,mt9v032";
+		reg = <0x4c>;
+		port {
+		     mt9v032_out: endpoint {
+			 remote-endpoint = <&vpif_input_ch0>;
+		     };	
+		};
+	};
+};
+
 &vpif {
 	pinctrl-names = "default";
 	pinctrl-0 = <&vpif_capture_pins>, <&vpif_display_pins>;
 	status = "okay";
+
+	/* VPIF capture port */
+	port at 0 {
+		vpif_input_ch0: endpoint at 0 {
+			reg = <0>;
+			bus-width = <8>;
+			remote-endpoint = <&mt9v032_out>;
+		};
+
+		vpif_input_ch1: endpoint at 1 {
+			reg = <1>;
+			bus-width = <8>;
+			data-shift = <8>;
+		};
+	};
 };
 
 /* UI board: VPIF input selection */
@@ -316,13 +368,13 @@
 	 sel_b {
 		gpio-hog;
 		gpios = <6 GPIO_ACTIVE_HIGH>;
-		output-high;
+		output-low;
 		line-name = "CAMERA_ENn";
 	 };
 	 sel_c {
 		gpio-hog;
 		gpios = <5 GPIO_ACTIVE_HIGH>;
-		output-low;
+		output-high;
 		line-name = "VIDEO_IN_ENn";
 	 };
 };
-- 
2.9.3

[PATCH/RFT 3/3] HACK: ARM: davinci: add cdce913 clock controller

From: khilman@baylibre.com (Kevin Hilman)
Date: 2017-06-02 23:44:01

The da850-evm UI board has a ti,cdce913 clock controller with a 27MHz
crystal to provide the master clock to the camera connector.

While there is an upstream driver for the ti,cdce913, it is CCF only,
and since davinci does not currently support CCF, an alternate driver is
needed to make camera sensors that depend on the clock API to work
correctly.

Note that the current driver is very dumb and doesn't even implement
.set_rate, because the default, power-on defaults are sufficient to
provide the 27 MHz clock expected by the aptina,mt9v032 which was used
for testing.
---
 arch/arm/mach-davinci/Makefile       |   2 +-
 arch/arm/mach-davinci/cdce913.c      | 164 +++++++++++++++++++++++++++++++++++
 arch/arm/mach-davinci/pdata-quirks.c |   8 +-
 3 files changed, 171 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-davinci/cdce913.c
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index df96ca9eab6d..c91e3a323488 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_AINTC)			+= irq.o
 obj-$(CONFIG_CP_INTC)			+= cp_intc.o
 
 # Board specific
-obj-$(CONFIG_MACH_DA8XX_DT)		+= da8xx-dt.o pdata-quirks.o
+obj-$(CONFIG_MACH_DA8XX_DT)		+= da8xx-dt.o pdata-quirks.o cdce913.o
 obj-$(CONFIG_MACH_DAVINCI_EVM)  	+= board-dm644x-evm.o
 obj-$(CONFIG_MACH_SFFSDR)		+= board-sffsdr.o
 obj-$(CONFIG_MACH_NEUROS_OSD2)		+= board-neuros-osd2.o
diff --git a/arch/arm/mach-davinci/cdce913.c b/arch/arm/mach-davinci/cdce913.c
new file mode 100644
index 000000000000..ef306707f283
--- /dev/null
+++ b/arch/arm/mach-davinci/cdce913.c
@@ -0,0 +1,164 @@
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
+
+#include <mach/common.h>
+#include <mach/da8xx.h>
+#include "clock.h"
+
+static struct i2c_client *cdce913;
+
+static void cdce_enable(struct clk *clk)
+{
+	pr_debug("%s: %s\n", __func__, clk->name);
+	return;
+}
+
+static void cdce_disable(struct clk *clk)
+{
+	pr_debug("%s: %s\n", __func__, clk->name);
+	return;
+}
+
+int cdce_set_rate(struct clk *clk, unsigned long rate)
+{
+	WARN_ON(!cdce913);
+	pr_warn("%s: %s: rate = %lu; WARNING  not implemented\n",
+		__func__, clk->name, rate);
+	return 0;
+}
+
+#define CAMERA_XTAL_FREQ	27000000
+
+static struct clk cdce913_clk = {
+	.name		= "cdce913",
+	.clk_enable	= cdce_enable,
+	.clk_disable	= cdce_disable,
+	.rate		= CAMERA_XTAL_FREQ,
+	.set_rate	= cdce_set_rate,
+};
+		
+static struct clk_lookup cdce913_clks[] = {
+        /* HACK: needs i2c address as dev name for proper lookup */
+	CLK("1-004c",		NULL,		&cdce913_clk), 
+};
+
+#define CDCE925_I2C_COMMAND_BLOCK_TRANSFER      0x00
+#define CDCE925_I2C_COMMAND_BYTE_TRANSFER       0x80
+
+static int cdce925_i2c_write(const void *data, size_t count)
+{
+	struct i2c_client *i2c = cdce913;
+	int ret;
+	u8 reg_data[2];
+
+	if (count != 2)
+		return -ENOTSUPP;
+
+	/* First byte is command code */
+	reg_data[0] = CDCE925_I2C_COMMAND_BYTE_TRANSFER | ((u8 *)data)[0];
+	reg_data[1] = ((u8 *)data)[1];
+
+	ret = i2c_master_send(i2c, reg_data, count);
+	if (likely(ret == count))
+		return 0;
+	else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+/*
+ * NOTE: i2c read/write functions lifted directly from CCF driver:
+ *       drivers/clk/clk-cdce925.c
+ */
+
+static int cdce925_i2c_read(
+	const void *reg, size_t reg_size, void *val, size_t val_size)
+{
+	struct i2c_client *i2c = cdce913;
+	struct i2c_msg xfer[2];
+	int ret;
+	u8 reg_data[2];
+
+	if (reg_size != 1)
+		return -ENOTSUPP;
+
+	xfer[0].addr = i2c->addr;
+	xfer[0].flags = 0;
+	xfer[0].buf = reg_data;
+	if (val_size == 1) {
+		reg_data[0] =
+			CDCE925_I2C_COMMAND_BYTE_TRANSFER | ((u8 *)reg)[0];
+		xfer[0].len = 1;
+	} else {
+		reg_data[0] =
+			CDCE925_I2C_COMMAND_BLOCK_TRANSFER | ((u8 *)reg)[0];
+		reg_data[1] = val_size;
+		xfer[0].len = 2;
+	}
+
+	xfer[1].addr = i2c->addr;
+	xfer[1].flags = I2C_M_RD;
+	xfer[1].len = val_size;
+	xfer[1].buf = val;
+
+	ret = i2c_transfer(i2c->adapter, xfer, 2);
+	if (likely(ret == 2)) {
+		return 0;
+	} else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static int cdce913_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+        u8 data[16], reg;
+
+	if (cdce913) {
+		dev_warn(&client->dev, "already probed !!\n");
+		return 0;
+	}
+	cdce913 = client;
+	davinci_clk_init(cdce913_clks);
+
+	for (reg = 0; reg < 4; reg++) {
+		cdce925_i2c_read(&reg, 1, &data, 1);
+		dev_dbg(&client->dev, "reg 0x%02x: val=0x%02x\n", reg, data[0]);
+	}
+
+	return 0;
+}
+
+static int cdce913_remove(struct i2c_client *client)
+{
+	cdce913 = NULL;
+	return 0;
+}
+
+static const struct i2c_device_id cdce913_ids[] = {
+	{ "cdce913", 0, },
+	{ /* end of list */ },
+};
+
+static const struct of_device_id cdce913_of_match[] = {
+	{ .compatible = "ti,cdce913", },
+	{ },
+};
+
+static struct i2c_driver cdce913_driver = {
+	.driver = {
+		.name    = "cdce913",
+		.of_match_table = of_match_ptr(cdce913_of_match),
+	},
+	.id_table       = cdce913_ids,
+	.probe          = cdce913_probe,
+	.remove         = cdce913_remove,
+};
+
+void __init da850_evm_camera_capture_init(void)
+{
+	i2c_add_driver(&cdce913_driver);
+}
diff --git a/arch/arm/mach-davinci/pdata-quirks.c b/arch/arm/mach-davinci/pdata-quirks.c
index 4858b1cdf31b..2d0c8586f6f0 100644
--- a/arch/arm/mach-davinci/pdata-quirks.c
+++ b/arch/arm/mach-davinci/pdata-quirks.c
@@ -191,6 +191,9 @@ static void __init da850_vpif_display_legacy_init_evm(void)
 			__func__, ret);
 }
 
+	
+extern void __init da850_evm_camera_capture_init(void);
+
 static void pdata_quirks_check(struct pdata_init *quirks)
 {
 	while (quirks->compatible) {
@@ -204,8 +207,9 @@ static void pdata_quirks_check(struct pdata_init *quirks)
 
 static struct pdata_init pdata_quirks[] __initdata = {
 	{ "ti,da850-lcdk", da850_vpif_capture_legacy_init_lcdk, },
-	{ "ti,da850-evm", da850_vpif_display_legacy_init_evm, },
-	{ "ti,da850-evm", da850_vpif_capture_legacy_init_evm, },
+	{ "ti,da850-evm", da850_evm_camera_capture_init, },
+	/* { "ti,da850-evm", da850_vpif_display_legacy_init_evm, }, */
+	/* { "ti,da850-evm", da850_vpif_capture_legacy_init_evm, }, */
 	{ /* sentinel */ },
 };
 
-- 
2.9.3
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help